示例#1
0
    def call(self, obj, args):
        arrayType = type(None)
        isArgArray = _isType(args, RocketArray)
        nin_lexeme = obj.KSL[1][_TokenType.NIN.value]

        if isArgArray:
            arrayType = args.arrayType

        else:
            arrayType = type(args[0])

        # if a single arg is given we assume it to be the size of the Array
        if len(args) == 1 and not (isArgArray):
            if _isType(args[0], _number.RocketInt):
                arrayType = type(None)

                return RocketArray([None for i in range(args[0].value)],
                                   arrayType, nin_lexeme)

            else:
                raise _RuntimeError("Array', 'Array size must be Int.")

        if len(args) > 1 and not (isArgArray):
            # Check that all elms are of the same type
            if not _isAllSameType(args, arrayType):
                raise _RuntimeError('Array',
                                    "Array elements must be adjacent types.")

        return RocketArray(args, arrayType,
                           nin_lexeme) if not isArgArray else args
示例#2
0
 def call(interpreter, args):
     if self.notEmpty():
         if args[0].value in self.value:
             return String().call(self, [self.value.index(args[0].value)])
             
         else:
             raise _RuntimeError('String', "IndexError: Item not in string")
     else:
         raise _RuntimeError('String', "IndexError: cannot index from an empty string")
示例#3
0
            def call(interpreter, args):
                if self.notEmpty():
                    for i in range(len(self.elements)):
                        if args[0].value == self.elements[i].value:
                            return _number.Int().call(self, [i])

                    raise _RuntimeError('List', "IndexError: Item not in list")

                else:
                    raise _RuntimeError('List', "IndexError: cannot index from an empty list")
示例#4
0
    def visitImportStmt(self, stmt: _Import):
        import_lexeme = self.KSL[1][_TokenType.IMPORT.value]

        # TODO: add more native modules
        native_modules = [
            'math'  # Note: even this module isn't done
        ]

        if len(stmt.modules) == 0:
            raise _RuntimeError(
                import_lexeme,
                f"{import_lexeme} statement requires atleast one module name.",
                False)

        for module in stmt.modules:
            if (module.type == _TokenType.IDENTIFIER) and (module.lexeme
                                                           in native_modules):
                # read and execute sorce file
                contents = ''

                # Get exec base home
                basehome = _os.path.dirname(
                    _os.path.dirname(_os.path.realpath(__file__)))

                # Assemble native module path
                filename = _os.path.join(
                    basehome, "native/modules/" + module.lexeme + '.rckt')

                stmts = _importCodeStmts(filename, self.KSL)

                self.interpret(stmts)

            else:
                try:
                    # read and execute sorce file
                    contents = ''

                    # This way the user can specify both './path/to/module.rckt' and './path/to/module' are valid
                    filename = (
                        module.lexeme + '.rckt') if module.lexeme.split(
                            _os.path.extsep)[-1] != 'rckt' else module.lexeme

                    stmts = _importCodeStmts(filename, self.KSL)

                    self.interpret(stmts)

                except FileNotFoundError:
                    raise _RuntimeError(
                        import_lexeme,
                        f"No native or local module named '{module.lexeme}'.",
                        False)

        return None
示例#5
0
    def visitGetExpr(self, expr: _Get):
        object = self.evaluate(expr.object)

        if isinstance(object, _RocketInstance):
            return object.get(expr.name)

        # Another special check for datatypes
        if hasattr(object, 'nature'):
            try:
                return object.get(expr.name)
            except Exception as err:
                raise _RuntimeError(err.token, err.msg)

        else:
            raise _RuntimeError(expr.name, "Only instances have properties.",
                                False)
示例#6
0
    def visitClassStmt(self, stmt: _Class):
        super_lexeme = self.KSL[1][_TokenType.SUPER.value]
        this_lexeme = self.KSL[1][_TokenType.THIS.value]

        superclass = None
        if (stmt.superclass != None):
            superclass = self.evaluate(stmt.superclass)
            if not isinstance(superclass, _RocketClass):
                raise _RuntimeError(stmt.superclass.name,
                                    "Superclass must be a class.", False)

        self.environment.define(stmt.name.lexeme, None)

        if stmt.superclass != None:
            self.environment = _Environment(self.environment)
            self.environment.define(super_lexeme, superclass)

        methods = {}

        for method in stmt.methods:
            function = _RocketFunction(method, self.environment,
                                       method.name.lexeme.__eq__("init"),
                                       this_lexeme)
            methods[method.name.lexeme] = function

        class_ = _RocketClass(stmt.name.lexeme, superclass, methods)

        if (superclass != None):
            self.environment = self.environment.enclosing

        self.environment.assign(stmt.name, class_)

        return None
示例#7
0
            def call(interpreter, args):
                index = args[0].value

                if index >= len(self.elements):
                    raise _RuntimeError('List', "IndexError: list index out of range")

                return self.elements[index]
示例#8
0
            def call(interpreter, args):
                if (self.arrayType != _number.RocketInt) and (
                        self.arrayType != _number.RocketFloat):
                    raise _RuntimeError(
                        self, "Can only perform operation on number Arrays.")

                if len(self.elements) == 0:
                    return _RuntimeError(self,
                                         "Can't get mean of empty an Array.")

                sum = 0

                for i in range(0, len(self.elements)):
                    sum += self.elements[i].value

                return _number.Float().call(self, [sum / len(self.elements)])
示例#9
0
            def call(interpreter, args):
                if isinstance(args[0], RocketList):
                    # we return the mutation
                    return List().call(self, self.elements + args[0].elements)

                else:
                    raise _RuntimeError('List', "IndexError: can only concatenate 'List' native type with another 'List'.")
示例#10
0
            def call(interpreter, args):
                index = args[0].value

                if index >= len(self.value):
                    raise _RuntimeError('String', "IndexError: string index out of range")

                return String().call(self, [self.value[index]])
示例#11
0
 def call(interpreter, args):
     if self.notEmpty():
         last = self.elements[-1]
         self.elements.remove(last)
         return last
     else:
         raise _RuntimeError('List', "IndexError: cannot pop empty list")
示例#12
0
 def call(interpreter, args):
     if self.notEmpty():
         if args[0].value in self.value:
             return _boolean.Bool().call(self, [True])
         else:
             return _boolean.Bool().call(self, [False])
     else:
         raise _RuntimeError('String', "IndexError: cannot index from an empty string")
示例#13
0
 def call(interpreter, args):
     if self.notEmpty():
         for item in self.elements:
             args[0].call(interpreter, [item])
     else:
         raise _RuntimeError(
             'Array',
             "IndexError: cannot run function on an empty list")
示例#14
0
            def call(interpreter, args):
                if (self.arrayType != _number.RocketInt) and (
                        self.arrayType != _number.RocketFloat):
                    raise _RuntimeError(
                        self, "Can only perform operation on number Arrays.")

                if len(self.elements) == 0:
                    return _RuntimeError(self,
                                         "Can't get max of empty an Array.")

                max = self.elements[0].value

                for i in range(1, len(self.elements)):
                    if max < self.elements[i].value:
                        max = self.elements[i].value

                return _number.Int().call(self, [max])
示例#15
0
            def call(interpreter, args):
                if self.notEmpty():
                    removed_index = -1

                    for i in range(len(self.elements) - 1):
                        if args[0].value == self.elements[i].value:
                            self.elements.remove(self.elements[i])
                            removed_index = i

                    if removed_index == -1:
                        raise _RuntimeError('List', "IndexError: Item not in list")
                
                    else:
                        return _number.Int().call(self, [removed_index])

                else:
                    raise _RuntimeError('List', "IndexError: cannot remove items from an empty list")
示例#16
0
    def visitSetExpr(self, expr: _Set):
        obj = self.evaluate(expr.object)

        if hasattr(obj, 'kind'):
            if ('List' in obj.kind):
                raise _RuntimeError(
                    'List',
                    f"Cannot assign external attribute to native datatype 'List'",
                    False)

        if not isinstance(obj, _RocketInstance):
            raise _RuntimeError(expr.name, "Only instances have fields.",
                                False)

        value = self.evaluate(expr.value)
        obj.set(expr.name, value)

        return value
示例#17
0
            def call(interpreter, args):
                if _isType(args[0], _number.RocketInt):
                    for i in range(len(self.elements)):
                        self.elements[i] = args[0]

                    return self

                else:
                    raise _RuntimeError(self, "Expected an Int.")
示例#18
0
            def call(interpreter, args):
                if self.notEmpty():
                    if len(self.value) >= 2:
                        return String().call(self, [self.value[0].upper() + self.value[1:]])

                    else:
                        return String().call(self, [self.value])
                else:
                    raise _RuntimeError('String', "IndexError: cannot index from an empty string")
示例#19
0
 def call(interpreter, args):
     if self.notEmpty():
         endlen = len(args[0].value)
         index = -(endlen)
         if args[0] == self.value[index:]:
             return _boolean.Bool().call(self, [True])
         else:
             return _boolean.Bool().call(self, [False])
     else:
         raise _RuntimeError('String', "IndexError: cannot index from an empty string")
示例#20
0
            def call(interpreter, args):
                if self.notEmpty():
                    for i in range(len(self.elements)):
                        if args[0].value == self.elements[i].value:
                            return _boolean.Bool().call(self, [True])
                    
                    return _boolean.Bool().call(self, [False])

                else:
                    raise _RuntimeError('List', "IndexError: cannot index from an empty list")
示例#21
0
    def call(self, obj, args):
        if isNumber(args[0]):
            value = args[0]

            if (hasattr(args[0], 'value')):
                value = args[0].value

            return RocketInt(int(float(value)) if _isType(args[0], _string.RocketString) else int(value))

        raise _RuntimeError(obj, f"Type Mismatch: Cannot convert {args[0].kind} to Int.")
示例#22
0
            def call(interpreter, args):
                if isinstance(args[0], RocketString):
                    # We do not internally edit it, instead its returned
                    # self.value = self.value + new_list.elements
                    text = args[0].value

                    return String().call(self, [self.value + text])

                else:
                    raise _RuntimeError('String', "IndexError: can only concatenate 'String' native type with another 'String'.")
示例#23
0
    def call(self, obj, args):
        if isNumber(args[0]):
            value = args[0]

            if hasattr(args[0], 'value'):
                value = args[0].value

            return RocketFloat(float(value))

        else:
            raise _RuntimeError(obj, f"'Float' accepts either Int or Float as an argument.")
示例#24
0
    def visitConstStmt(self, stmt: _Const):
        value = self.evaluate(stmt.initializer)

        # check for variable before definition to avoid passing in 'const' redefinitions
        if self.environment.constExists(stmt.name):
            raise _RuntimeError(stmt.name.lexeme,
                                "Name already used as const.", False)

        if self.environment.varExists(stmt.name):
            raise _RuntimeError(stmt.name.lexeme,
                                "Name already used as variable.", False)

        # stop 'const' re-decl for 'classes' 'functions'
        elif self.globals.isTaken(stmt.name):
            raise _RuntimeError(
                stmt.name.lexeme,
                "Name already used as 'class' or 'function' name.", False)

        # Use different decleration function for consts
        self.environment.decl(stmt.name.lexeme, value)
示例#25
0
            def call(interpreter, args, inc=False):
                if inc:
                    if args[0].value >= len(self.elements) or args[1].value >= len(self.elements):
                        raise _RuntimeError('List', "IndexError: list index out of range")

                    # Special case
                    if (args[0].value >= args[1].value):
                        return List().call(self, [])

                    else:
                        return List().call(self, self.elements[args[0].value:args[1].value])

                return List().call(self, self.elements[args[0].value:])
示例#26
0
            def call(interpreter, args, inc=False):
                if inc:
                    if (args[0].value >= len(self.value)) or (args[1].value >= len(self.value)):
                        raise _RuntimeError('String', "IndexError: string index out of range")

                    # Special case
                    if (args[0].value >= args[1].value):
                        String().call(self, [''])

                    else:
                        return String().call(self, [self.value[args[0].value:args[1].value]])

                return self.value[args[0].value:]
示例#27
0
            def call(interpreter, args):
                if (self.arrayType != _number.RocketInt) and (
                        self.arrayType != _number.RocketFloat):
                    raise _RuntimeError(
                        self, "Can only perform operation on number Arrays.")

                prod = 1

                for i in range(len(self.elements)):
                    prod *= self.elements[i].value
                    self.elements[i].value = prod

                return self
示例#28
0
    def checkValidOperands(self, operator: _Token, left: object,
                           right: object):
        if ((isinstance(left, str)) and (isinstance(right, str))): return

        if self.is_number(left) and self.is_number(right): return

        else:
            # Is comparing strings and numbers really important?
            # Maybe if you are trying to see if a number id transformed to an 'str'.
            # But wouldn't you just check the type with 'Type' native func?!
            raise _RuntimeError(
                operator.lexeme,
                "operands must both be either 'strings' or 'numbers'.", False)
示例#29
0
    def visitVariableExpr(self, expr: _Variable):
        # NOTE: 'const' variables get retrieved from this call also
        try:
            return self.globals.get(expr.name)

        except:
            # We try to see if its in either 'envs'
            # if not we raise the exception for our interpreter to catch
            try:
                return self.environment.get(expr.name)

            except _RuntimeError as err:
                print(err, file=_sys.stderr)
                raise _RuntimeError(err.token, err.msg)
示例#30
0
    def visitVarStmt(self, stmt: _Var):
        if (stmt.initializer is not None):
            value = self.evaluate(stmt.initializer)

        else:
            value = None

        # To avoid redifining vars with the same name as consts, functions, or classes
        if not (self.globals.isTaken(stmt.name)):
            self.environment.define(stmt.name.lexeme, value)

        else:
            raise _RuntimeError(
                stmt.name.lexeme,
                "Name already defined as 'class' or 'function'", False)