Beispiel #1
0
 def check_params(self, function):
     if len(function.params) != len(self.calling_params):
         Exit(Error.SyntaxError, "Wrong number of parameters")
     for calling_param, declared_param in zip(self.calling_params,
                                              function.params.values()):
         if calling_param.type != declared_param.type:
             Exit(Error.TypesIncompatibility, "Parameters types mismatch")
Beispiel #2
0
    def get_instructions(self, parent):
        self.parent = parent
        function = self.find_function()
        if function.type == VYPaVoid():
            if self.expression is not None:
                Exit(Error.SyntaxError, "Void can not have return value")
        else:
            self.instruction_tape.merge(self.expression.get_instructions(self))
            self.type = self.expression.type
            if self.type != function.type:
                Exit(Error.SemanticError,
                     "Different return type and function type")

        variables_defined_in_function_count = len(function.variables)
        scope = self
        while scope != function:
            variables_defined_in_function_count += len(scope.variables)
            scope = scope.parent

        dealloc_count = variables_defined_in_function_count + len(
            function.params)

        if function.type != VYPaVoid():
            self.instruction_tape.add(COMMENT(f"Set return value"))
            self.stack.set(self.expression, -dealloc_count - 1)

        self.instruction_tape.add(
            COMMENT(
                f"Deallocate {dealloc_count} scope variables and paramters"))
        self.stack.deallocate(dealloc_count)

        self.stack.deallocate(1)
        self.instruction_tape.add(RETURN(self.stack.get(1)))
        return self.instruction_tape
Beispiel #3
0
 def get_variable(self, name):
     if self.variables.get(name, None) is not None:
         return self.variables[name]
     elif self.params.get(name, None) is not None:
         return self.params[name]
     else:
         Exit(Error.SemanticError, f"Variable {name} was not defined")
Beispiel #4
0
 def add_param(self, param):
     param.set_parent(self)
     if self.params.get(param.name, None) is not None:
         Exit(Error.SemanticError,
              f"Param with name {param.name} already exists")
     else:
         self.params[param.name] = param
Beispiel #5
0
 def add_variable(self, variable):
     if self.variables.get(variable.name, None) is None:
         variable.set_parent(self)
         self.variables[variable.name] = variable
         return variable
     else:
         Exit(Error.SyntaxError, f"Variable {variable.name} already exists")
Beispiel #6
0
 def add_class(self, classs):
     if not self.classes.get(classs.name, None) is not None:
         classs.set_parent(self)
         self.classes[classs.name] = classs
         return classs
     else:
         Exit(Error.SyntaxError, f"Class {classs.name} already exists")
Beispiel #7
0
 def add_function(self, function):
     if not self.functions.get(function.name, None) is not None:
         function.set_parent(self)
         self.functions[function.name] = function
         return function
     else:
         Exit(Error.SyntaxError, f"Function {function.name} already exists")
Beispiel #8
0
def p_program(t):
    '''program : init program_body'''
    main = AST.get_root().get_function("main")
    if not (main and main.type == VYPaVoid()):
        Exit(Error.SemanticError, "wrong type or not defined Main function")

    MAIN_INSTRUCTION_TAPE.add_constant_section()
    MAIN_INSTRUCTION_TAPE.merge(AST.get_root().get_instructions(None))
    MAIN_INSTRUCTION_TAPE.add(LABEL("END"))
Beispiel #9
0
 def get_variable(self, name):
     if name == "super":
         return self.predecessor.get_variable("this")
     if self.variables.get(name, None) is not None:
         return self.variables[name]
     else:
         if self.name != "Object":
             return self.predecessor.get_variable(name)
         else:
             Exit(Error.SyntaxError, f"Variable {name} was not defined")
Beispiel #10
0
 def get_variable_offset(self, name):
     if name == "super":
         return len(
             self.variables) + self.predecessor.get_variable_offset("this")
     if self.variables.get(name, None) is not None:
         return list(self.variables)[::-1].index(name)
     else:
         if self.name != "Object":
             return len(self.variables
                        ) + self.predecessor.get_variable_offset(name)
         else:
             Exit(Error.SyntaxError, f"Variable {name} was not defined")
Beispiel #11
0
    def get_instructions(self, parent):
        self.parent = parent
        self.stack_offset += parent.stack_offset

        # print is a special function which can be called with multiple parameters
        # so internally we call PrintInt or PrintString for each parameter...
        if self.name == "print":
            self.type = VYPaVoid()
            if len(self.calling_params) == 0:
                Exit(Error.SemanticError, "Print called with zero params")

            for idx, param in enumerate(self.calling_params, 1):
                self.instruction_tape.merge(param.get_instructions(self))
                if param.type == VYPaInt():
                    function = AST.root.get_function("printInt")

                elif param.type == VYPaString():
                    function = AST.root.get_function("printString")
                else:
                    Exit(Error.SemanticError,
                         "argument of print can be only int or str")

                self.stack.set(param, 3)
                self.add_instruction(CALL(self.stack.get(2), function))
                if idx != len(self.calling_params):
                    self.stack.pop()

        else:
            function = AST.root.get_function(self.name)
            self.type = function.type

            for offset, param in enumerate(self.calling_params, 3):
                if self.name != "stringConcat":  # string concat has already merged instructions
                    self.instruction_tape.merge(param.get_instructions(self))
                self.stack.set(param, offset)

            self.check_params(function)
            self.add_instruction(CALL(self.stack.get(2), function))
        self.add_expression_stack_offset()
        return self.instruction_tape
Beispiel #12
0
    def get_variable_offset(self, name):
        if self.params.get(name, None) is not None:
            return len(self.variables) + list(self.params)[::-1].index(name)
        elif self.variables.get(name, None) is not None:
            offset = 0
            for variable in list(self.variables.values())[::-1]:
                if variable.name == name:
                    return offset
                else:
                    offset += variable.get_size()

        else:
            Exit(Error.SemanticError,
                 f"Variable {name} not found in function scope")
Beispiel #13
0
    def get_instructions(self, parent):
        self.parent = parent
        self.instruction_tape.clear()
        for name in self.variable_names:
            if self.type == VYPaInt():
                parent.add_variable(self.declare_integer(name))
            elif self.type == VYPaString():
                parent.add_variable(self.declare_string(name))
            elif self.type == VYPaVoid():
                Exit(Error.SemanticError, "Can not create void variable")
            else:
                parent.add_variable(self.declare_class_instance(name))

        return self.instruction_tape
Beispiel #14
0
def t_WORD(t):
    r'\"([^\\\"]|\\.)*\"'  # should be all printable characters

    hexChars = [x for x in re.findall(r'\\x[A-Fa-f0-9]{6}', t.value)]

    for hexChar in hexChars:
        try:
            unicode_char = chr(int(hexChar[2:], 16))
        except ValueError:
            Exit(Error.LexicalError,
                 "unicode character not in range of unicode characters")
        t.value = t.value.replace(hexChar, unicode_char)

    return t
Beispiel #15
0
    def get_instructions(self, parent):
        self.parent = parent
        self.stack_offset += parent.stack_offset
        self.instruction_tape.merge(self.left.get_instructions(self))
        self.instruction_tape.merge(self.right.get_instructions(self))

        if self.left.type == VYPaInt() and self.right.type == VYPaInt():
            self.instruction = EQI
            self.type = VYPaInt()
            self.add_instruction(self.instruction(self.left, self.right))
        elif self.left.type == VYPaString() and self.right.type == VYPaString(
        ):
            self.instruction = EQS
            self.type = VYPaInt()
            self.add_instruction(self.instruction(self.left, self.right))
        elif isinstance(self.left.type, VYPaClass) and isinstance(
                self.right.type, VYPaClass):
            self.instruction = EQI
            self.type = VYPaInt()

            left_class = AST_expression(
                AST_class_variable_call(self.left.name, "**runtime_name**"))
            self.merge_instructions(left_class.get_instructions(self))
            self.add_instruction(SET("$6", VYPaRegister.Accumulator))

            right_class = AST_expression(
                AST_class_variable_call(self.right.name, "**runtime_name**"))
            self.merge_instructions(right_class.get_instructions(self))
            self.add_instruction(SET("$7", VYPaRegister.Accumulator))
            self.add_instruction(DUMPREGS())
            self.add_instruction(DUMPSTACK())
            self.add_instruction(DUMPHEAP())

            self.add_instruction(
                self.instruction(AST_value(VYPaInt(), "$6"),
                                 AST_value(VYPaInt(), "$7")))
        else:
            Exit(Error.SemanticError, "Types mismatch")
            pass
        self.stack.push(AST_value(self.type, str(VYPaRegister.Accumulator)))
        self.add_expression_stack_offset()
        return self.instruction_tape
Beispiel #16
0
    def get_instructions(self, parent):
        self.parent = parent
        global CLASS_INSTANCE_COUNTS
        self.instruction_tape.merge(self.expression.get_instructions(self))
        self.variables["_"] = AST_variable(VYPaInt(), "_")
        self.stack.push(
            AST_value(self.expression.type, VYPaRegister.Accumulator))
        self.instruction_tape.merge(self.variable.get_instructions(self))

        from src.VYPcode.AST.blocks.class_instance import AST_class_instance
        if hasattr(self.expression, "expression_root") and isinstance(
                self.expression.expression_root, AST_class_instance):
            class_instance_variable = AST_variable(
                VYPaClass(self.expression.type.name),
                f"instance of {self.expression.type.name} {CLASS_INSTANCE_COUNTS}"
            )
            class_instance_variable.set_size(
                AST.root.get_class(self.expression.type.name).get_size())
            self.variable.variable.parent.add_variable(class_instance_variable)
            CLASS_INSTANCE_COUNTS += 1

        if self.variable.type != self.expression.type:
            if self.variable.name != "this":
                Exit(Error.TypesIncompatibility, "Type check error!")

        if isinstance(self.variable.type,
                      VYPaClass) and self.variable.name != "this":
            this_offset = 0
            class_name = self.expression.type.name
            self.add_instruction(
                SET(VYPaRegister.ClassCallReg, self.stack.top()))
            while self.variable.type.name != class_name:
                this_offset -= len(AST.root.get_class(class_name).variables)
                class_name = AST.root.get_class(class_name).predecessor_name

            self.instruction_tape.add(
                SET(self.variable,
                    self.stack.get(this_offset, VYPaRegister.ClassCallReg)))
        else:
            self.instruction_tape.add(SET(self.variable, self.stack.top()))
        self.stack.pop()
        return self.instruction_tape
Beispiel #17
0
    def get_instructions(self, parent):
        self.parent = parent
        self.stack_offset += parent.stack_offset
        self.instruction_tape.merge(self.left.get_instructions(self))
        self.instruction_tape.merge(self.right.get_instructions(self))

        if self.left.type == VYPaInt() and self.right.type == VYPaInt():
            self.instruction = GTI
            self.type = VYPaInt()
            self.add_instruction(self.instruction(self.left, self.right))
        elif self.left.type == VYPaString() and self.right.type == VYPaString(
        ):
            self.instruction = GTS
            self.type = VYPaString()
            self.add_instruction(self.instruction(self.left, self.right))
        else:
            Exit(Error.SemanticError, "Types mismatch")
            pass
        self.stack.push(AST_value(self.type, str(VYPaRegister.Accumulator)))
        self.add_expression_stack_offset()
        return self.instruction_tape
Beispiel #18
0
    def get_instructions(self, parent):
        self.parent = parent
        self.stack_offset += parent.stack_offset
        self.instruction_tape.merge(self.left.get_instructions(self))
        self.instruction_tape.merge(self.right.get_instructions(self))

        if self.left.type == VYPaInt() and self.right.type == VYPaInt():
            self.instruction = ADDI
            self.check_types()
            self.type = VYPaInt()
            self.add_instruction(self.instruction(self.left, self.right))
            self.stack.push(AST_value(self.type, str(VYPaRegister.Accumulator)))
            self.add_expression_stack_offset()
        elif self.left.type == VYPaString() and self.right.type == VYPaString():
            self.check_types()
            self.type = VYPaString()
            self.instruction_tape.merge(
                AST_function_call("stringConcat", [self.left, self.right]).get_instructions(self)
            )
        else:
            Exit(Error.TypesIncompatibility, "Can not add other types as primitives")

        return self.instruction_tape
Beispiel #19
0
 def check_types(self):
     if not ((self.expression.type == VYPaInt()
              and self.casting_type == VYPaString()) or
             (isinstance(self.expression.type, VYPaClass)
              and AST.root.classes.get(self.casting_type.name, False))):
         Exit(Error.TypesIncompatibility, "Type check error!")
Beispiel #20
0
def t_error(t):
    Exit(Error.LexicalError,
         f"Illegal character '{t.value[0]}' on line {t.lexer.lineno}")
Beispiel #21
0
 def check_types(self):
     if self.left.type != VYPaInt() or self.right.type != VYPaInt():
         Exit(Error.TypesIncompatibility, "Type check error!")
Beispiel #22
0
def p_error(t):
    Exit(Error.SyntaxError, "Syntax error. Can not parse")
Beispiel #23
0
 def get_class(self, class_name):
     try:
         return self.classes[class_name]
     except KeyError:
         Exit(Error.SyntaxError, f"Class {class_name} was not defined")
Beispiel #24
0
 def get_function(self, function_name):
     try:
         return self.functions[function_name]
     except KeyError:
         Exit(Error.SyntaxError,
              f"Function {function_name} was not defined")
Beispiel #25
0
 def get_variable(self, name):
     Exit(Error.SyntaxError, f"Variable {name} was not defined")
Beispiel #26
0
 def check_types(self):
     if self.expression.type != VYPaInt():
         Exit(Error.TypesIncompatibility, "Type check error!")
Beispiel #27
0
 def get_variable_offset(self, name):
     if self.variables.get(name, None) is not None:
         return list(self.variables)[::-1].index(name)
     else:
         Exit(Error.SyntaxError,
              f"Variable {name} not found in function scope")