예제 #1
0
파일: ast.py 프로젝트: dorris19/soda
 def compile(self, compiler):
     function = SodaFunction(name=self.name,
                             arity=len(self.params),
                             compiler=self.compiler,
                             package=self.package,
                             line=self.line,
                             col=self.col)
     compiler.register_function(function)
     for constant in compiler.constants:
         if isinstance(constant, SodaFunction):
             self.compiler.register_function(constant)
     sd = SodaDummy()
     for i in range(0, function.arity):
         self.compiler.emit(bytecode.LOAD_CONST,
                            self.compiler.register_constant(sd),
                            self.package, self.line, self.col)
     for param in self.params:
         assert isinstance(param, RegisterVariable)
         if param.value == unicode("vargs"):
             if self.params.index(param) != len(self.params) - 1:
                 sodaError(
                     self.package, self.line, self.col,
                     "vargs must be final parameter in "
                     "function declaration")
             function.isvariadic = True
         param.compile(self.compiler)
     for statement in self.body:
         statement.compile(self.compiler)
     self.returnstatement.compile(self.compiler)
예제 #2
0
파일: parser.py 프로젝트: dorris19/soda
def error_handler(token):
    package = fetcher.packages[token.getsourcepos().idx]
    line = str(token.getsourcepos().lineno)
    col = str(token.getsourcepos().colno)
    if token.name == "ERROR":
        sodaError(package, line, col, token.value)
    else:
        msg = "unexpected \"%s\"" % token.value
        sodaError(package, line, col, msg)
예제 #3
0
파일: parser.py 프로젝트: dorris19/soda
def statement_assignment(s):
    sourcepos = s[1].getsourcepos()
    package = fetcher.packages[sourcepos.idx]
    line = str(sourcepos.lineno)
    col = str(sourcepos.colno)
    if not len(s[0].get()) == len(s[2].get()):
        sodaError(
            package, line, col, "assignment operator requires number "
            "of variables to match number of expressions")
    return ast.Assignment(s[0], s[2], package, line, col)
예제 #4
0
 def register_function(self, function):
     package = unicode(function.package)
     try:
         self.functions[function.name + package]
         sodaError(
             function.package, function.line, function.col,
             "redeclaration of function \"%s\"" %
             function.name.encode("utf-8"))
     except KeyError:
         self.functions[function.name +
                        package] = self.register_constant(function)
예제 #5
0
파일: parser.py 프로젝트: dorris19/soda
def number_number(s):
    sourcepos = s[0].getsourcepos()
    package = fetcher.packages[sourcepos.idx]
    line = str(sourcepos.lineno)
    col = str(sourcepos.colno)
    try:
        a = rbigint()
        return ast.Integer(a.fromstr(s[0].getstr()), package, line, col)
    except Exception:
        package = fetcher.packages[s[0].getsourcepos().idx]
        line = str(s[0].getsourcepos().lineno)
        col = str(s[0].getsourcepos().colno)
        msg = "error in number %s" % s[0].getstr()
        sodaError(package, line, col, msg)
예제 #6
0
파일: fetcher.py 프로젝트: dorris19/soda
 def fetch(self):
     data = ""
     for package in self.packages:
         fetchfound = False
         packagefound = False
         filepath = self.pathtopackage[package] + package + ".na"
         try:
             sourcefile = open_file_as_stream(filepath)
             data = sourcefile.readall()
             sourcefile.close()
         except OSError:
             errtok = self.tokentopackage.get(package, None)
             errfile = self.packages[errtok.getsourcepos().idx]
             sodaError(errfile, str(errtok.getsourcepos().lineno),
                       str(errtok.getsourcepos().colno),
                       "package \"%s\" not found" % package)
         i = 0
         tokenlist = []
         if not data == "":
             for token in lexer.lex(data, self.idx):
                 if not fetchfound:
                     if token.name == "FETCH":
                         if not i == 0:
                             sodaError(
                                 package, str(token.getsourcepos().lineno),
                                 str(token.getsourcepos().colno),
                                 "fetch statement must precede main program"
                             )
                         else:
                             i += 1
                             fetchfound = True
                     else:
                         i += 1
                         tokenlist.append(token)
                 else:
                     if token.name == "STRING":
                         self.tokentopackage[token.value] = token
                         if not packagefound:
                             fullpath = self.pathtopackage[self.packages[
                                 self.idx]] + token.value
                             self.addpackage(fullpath)
                             packagefound = True
                             continue
                         else:
                             sodaError(
                                 package, str(token.getsourcepos().lineno),
                                 str(token.getsourcepos().colno),
                                 "package names must be "
                                 "separated by newlines")
                     elif token.name == "END":
                         packagefound = False
                         continue
                     else:
                         tokenlist.append(token)
                         fetchfound = False
         data = ""
         self.idx += 1
         self.tokgeneratorlist.append(tokenlist)
예제 #7
0
def run(frame, bc):
    code = bc.code
    positions = bc.positions
    pc = 0
    iteridx = 0
    while pc < len(bc.code):
        driver.jit_merge_point(pc=pc,
                               iteridx=iteridx,
                               code=code,
                               positions=positions,
                               bc=bc,
                               frame=frame)
        c = code[pc]
        arg = code[pc + 1]
        package, line, col = positions[pc]
        pc += 2
        if c == bytecode.DROP_CONST:
            frame.pop()
        elif c == bytecode.LOAD_CONST:
            const = bc.constants[arg]
            frame.push(const)
        elif c == bytecode.LOAD_VAR:
            if arg == -1:
                sodaError(package, line, col,
                          "cannot evaluate undeclared variable")
            var = frame.variables[arg]
            frame.push(var)
        elif c == bytecode.STORE_VAR:
            package = package
            line = line
            col = col
            value = frame.pop()
            frame.variables[arg] = value
        elif c == bytecode.STOR_ARRAY:
            package = package
            line = line
            col = col
            items = []
            for i in range(0, arg):
                items.append(frame.pop())
            sa = SodaArray(items)
            frame.push(sa)
        elif c == bytecode.NEG:
            operand = frame.pop()
            if not operand.isint():
                try:
                    operand = operand.toint()
                except Exception:
                    sodaError(package, line, col,
                              "cannot negate non-integer type")
            result = operand.neg()
            frame.push(result)
        elif c == bytecode.ADD:
            right = frame.pop()
            left = frame.pop()
            if not right.isint():
                try:
                    right = right.toint()
                except Exception:
                    sodaError(package, line, col,
                              "cannot add non-integer types")
            if not left.isint():
                try:
                    left = left.toint()
                except Exception:
                    sodaError(package, line, col,
                              "cannot add non-integer types")
            result = right.add(left)
            frame.push(result)
        elif c == bytecode.CONCAT:
            right = frame.pop()
            left = frame.pop()
            if not left.isstr():
                try:
                    left = left.tostr()
                except Exception:
                    sodaError(package, line, col,
                              "cannot concatenate non-string types")
            if not right.isstr():
                try:
                    right = right.tostr()
                except Exception:
                    sodaError(package, line, col,
                              "cannot concatenate non-string types")
            result = right.concat(left)
            frame.push(result)
        elif c == bytecode.DIFF:
            right = frame.pop()
            left = frame.pop()
            if not left.isstr():
                try:
                    left = left.tostr()
                except Exception:
                    sodaError(
                        package, line, col,
                        "cannot find string difference of non-string"
                        " types")
            if not right.isstr():
                try:
                    right = right.tostr()
                except Exception:
                    sodaError(
                        package, line, col,
                        "cannot find string difference of non-string"
                        " types")
            result = right.diff(left)
            frame.push(result)
        elif c == bytecode.SUB:
            right = frame.pop()
            left = frame.pop()
            if not right.isint():
                try:
                    right = right.toint()
                except Exception:
                    sodaError(package, line, col,
                              "cannot subtract non-integer types")
            if not left.isint():
                try:
                    left = left.toint()
                except Exception:
                    sodaError(package, line, col,
                              "cannot subtract non-integer types")
            result = right.sub(left)
            frame.push(result)
        elif c == bytecode.MUL:
            right = frame.pop()
            left = frame.pop()
            if not right.isint():
                try:
                    right = right.toint()
                except Exception:
                    sodaError(package, line, col,
                              "cannot multiply non-integer types")
            if not left.isint():
                try:
                    left = left.toint()
                except Exception:
                    sodaError(package, line, col,
                              "cannot multiply non-integer types")
            result = right.mul(left)
            frame.push(result)
        elif c == bytecode.DIV:
            right = frame.pop()
            left = frame.pop()
            if not right.isint():
                try:
                    right = right.toint()
                except Exception:
                    sodaError(package, line, col,
                              "cannot divide non-integer types")
            if not left.isint():
                try:
                    left = left.toint()
                except Exception:
                    sodaError(package, line, col,
                              "cannot divide non-integer types")
            try:
                result = right.div(left)
            except ZeroDivisionError:
                sodaError(package, line, col, "cannot divide by zero")
                break
            frame.push(result)
        elif c == bytecode.MOD:
            right = frame.pop()
            left = frame.pop()
            if not right.isint():
                try:
                    right = right.toint()
                except Exception:
                    sodaError(package, line, col,
                              "cannot modulo non-integer types")
            if not left.isint():
                try:
                    left = left.toint()
                except Exception:
                    sodaError(package, line, col,
                              "cannot modulo non-integer types")
            try:
                result = right.mod(left)
            except ZeroDivisionError:
                sodaError(package, line, col, "cannot modulo by zero")
                break
            frame.push(result)
        elif c == bytecode.POW:
            right = frame.pop()
            left = frame.pop()
            if not right.isint():
                try:
                    right = right.toint()
                except Exception:
                    sodaError(package, line, col,
                              "cannot exponentiate non-integer types")
            if not left.isint():
                try:
                    left = left.toint()
                except Exception:
                    sodaError(package, line, col,
                              "cannot exponentiate non-integer types")
            try:
                result = right.pow(left)
            except ValueError:
                sodaError(package, line, col,
                          "cannot exponentiate by a negative integer")
                break
            frame.push(result)
        elif c == bytecode.EQ:
            right = frame.pop()
            left = frame.pop()
            if left.isstr() and right.isstr() or left.isint()\
               and right.isint():
                result = right.eq(left)
                frame.push(result)
                continue
            try:
                right = right.toint()
                left = left.toint()
                result = right.eq(left)
                frame.push(result)
                continue
            except Exception:
                try:
                    right = right.tostr()
                    left = left.tostr()
                    result = right.eq(left)
                    frame.push(result)
                    continue
                except Exception:
                    sodaError(package, line, col, "cannot compare arrays")
        elif c == bytecode.NE:
            right = frame.pop()
            left = frame.pop()
            if left.isstr() and right.isstr() or left.isint()\
               and right.isint():
                result = right.ne(left)
                frame.push(result)
                continue
            try:
                right = right.toint()
                left = left.toint()
                result = right.ne(left)
                frame.push(result)
                continue
            except Exception:
                try:
                    right = right.tostr()
                    left = left.tostr()
                    result = right.ne(left)
                    frame.push(result)
                    continue
                except Exception:
                    sodaError(package, line, col, "cannot compare arrays")
        elif c == bytecode.GT:
            right = frame.pop()
            left = frame.pop()
            if left.isstr() and right.isstr() or left.isint()\
               and right.isint():
                result = right.gt(left)
                frame.push(result)
                continue
            try:
                right = right.toint()
                left = left.toint()
                result = right.gt(left)
                frame.push(result)
                continue
            except Exception:
                try:
                    right = right.tostr()
                    left = left.tostr()
                    result = right.gt(left)
                    frame.push(result)
                    continue
                except Exception:
                    sodaError(package, line, col, "cannot compare arrays")
        elif c == bytecode.LT:
            right = frame.pop()
            left = frame.pop()
            if left.isstr() and right.isstr() or left.isint()\
               and right.isint():
                result = right.lt(left)
                frame.push(result)
                continue
            try:
                right = right.toint()
                left = left.toint()
                result = right.lt(left)
                frame.push(result)
                continue
            except Exception:
                try:
                    right = right.tostr()
                    left = left.tostr()
                    result = right.lt(left)
                    frame.push(result)
                    continue
                except Exception:
                    sodaError(package, line, col, "cannot compare arrays")
        elif c == bytecode.GE:
            right = frame.pop()
            left = frame.pop()
            if left.isstr() and right.isstr() or left.isint()\
               and right.isint():
                result = right.ge(left)
                frame.push(result)
                continue
            try:
                right = right.toint()
                left = left.toint()
                result = right.ge(left)
                frame.push(result)
                continue
            except Exception:
                try:
                    right = right.tostr()
                    left = left.tostr()
                    result = right.ge(left)
                    frame.push(result)
                    continue
                except Exception:
                    sodaError(package, line, col, "cannot compare arrays")
        elif c == bytecode.LE:
            right = frame.pop()
            left = frame.pop()
            if left.isstr() and right.isstr() or left.isint()\
               and right.isint():
                result = right.le(left)
                frame.push(result)
                continue
            try:
                right = right.toint()
                left = left.toint()
                result = right.le(left)
                frame.push(result)
                continue
            except Exception:
                try:
                    right = right.tostr()
                    left = left.tostr()
                    result = right.le(left)
                    frame.push(result)
                    continue
                except Exception:
                    sodaError(package, line, col, "cannot compare arrays")
        elif c == bytecode.AND:
            right = frame.pop()
            left = frame.pop()
            if not left.isstr():
                try:
                    left = left.tostr()
                except Exception:
                    sodaError(package, line, col, "cannot compare arrays")
            if not right.isstr():
                try:
                    right = right.tostr()
                except Exception:
                    sodaError(package, line, col, "cannot compare arrays")
            result = right.land(left)
            frame.push(result)
        elif c == bytecode.OR:
            right = frame.pop()
            left = frame.pop()
            if not left.isstr():
                try:
                    left = left.tostr()
                except Exception:
                    sodaError(package, line, col, "cannot compare arrays")
            if not right.isstr():
                try:
                    right = right.tostr()
                except Exception:
                    sodaError(package, line, col, "cannot compare arrays")
            result = right.lor(left)
            frame.push(result)
        elif c == bytecode.NOT:
            operand = frame.pop()
            if not operand.isstr():
                try:
                    operand = operand.tostr()
                except Exception:
                    sodaError(package, line, col, "cannot compare arrays")
            result = operand.lnot()
            frame.push(result)
        elif c == bytecode.RETURN:
            result = frame.pop()
            return result
        elif c == bytecode.CALL:
            if arg == -1:
                sodaError(package, line, col,
                          "cannot evaluate undeclared function")
            elif arg == -2:
                sodaError(
                    package, line, col,
                    "number of arguments passed to function "
                    "must match number of expected parameters")
            function = bc.constants[arg]
            if unicode(function.name) == u"Print" and unicode(
                    function.package) == u"io":
                output = frame.pop().str()
                os.write(1, output)
                fbc = function.compiler.create_bytecode()
                frame.push(interpret(fbc))
            if unicode(function.name) == u"Error" and unicode(
                    function.package) == u"io":
                output = frame.pop().str()
                os.write(2, output)
                fbc = function.compiler.create_bytecode()
                frame.push(interpret(fbc))
            else:
                arglist = []
                if function.isvariadic:
                    function.numargs = len(frame.valuestack)
                for i in range(0, function.numargs):
                    value = frame.pop()
                    arglist.append(value)
                function.evaluate_args(arglist)
                fbc = function.compiler.create_bytecode()
                fbc.textarrays = bc.textarrays
                try:
                    function.revert_state()
                    result = interpret(fbc)
                    frame.push(result)
                except RuntimeError:
                    sodaError(package, line, col,
                              "maximum recursion depth exceeded")
        elif c == bytecode.J_IF_TRUE:
            if not frame.pop().str() == "false":
                pc = arg
        elif c == bytecode.J_IF_FALSE:
            if frame.pop().str() == "false":
                pc = arg
        elif c == bytecode.ITERATE:
            array = frame.pop()
            try:
                keyval = array.getkey(iteridx)
                if keyval is None:
                    pc = arg
                    iteridx = 0
                else:
                    frame.push(keyval)
                    iteridx += 1
            except Exception:
                sodaError(package, line, col, "cannot iterate non-array types")
        elif c == bytecode.SET_INDEX:
            expr = frame.pop()
            var = frame.pop()
            newval = frame.pop()
            try:
                var.setval(expr, newval)
            except Exception:
                sodaError(package, line, col, "cannot mutate non-array types")
        elif c == bytecode.GET_INDEX:
            expr = frame.pop()
            var = frame.pop()
            try:
                result = var.getval(expr)
                frame.push(result)
            except IndexError:
                sodaError(package, line, col, "string index out of range")
            except Exception:
                sodaError(package, line, col, "cannot index integers")
        elif c == bytecode.JUMP:
            if arg == -3:
                sodaError(package, line, col, "break statement outside loop")
            oldpc = pc
            pc = arg
            if pc < oldpc:
                driver.can_enter_jit(pc=pc,
                                     iteridx=iteridx,
                                     code=code,
                                     positions=positions,
                                     bc=bc,
                                     frame=frame)
        elif c == bytecode.LEN:
            length = frame.pop().length
            if length is not None:
                frame.push(length)
            else:
                sodaError(package, line, col, "cannot find length of integer")
        elif c == bytecode.CHARS:
            frame.push(bc.textarrays[0])
        elif c == bytecode.WORDS:
            frame.push(bc.textarrays[1])
        elif c == bytecode.LINES:
            frame.push(bc.textarrays[2])
        else:
            sodaError("test", "-1", "-1", "unrecognized bytecode %s" % c)