Beispiel #1
0
 def visit(self, node: ast.StaticDispatch, scope: Scope):
     instance_type = self.visit(node.instance, scope)
     class_type = scope.getType(node.dispatch_type)
     if instance_type.name == 'SELF_TYPE':
         instance_type = scope.getType(scope.classname)
     if not instance_type < class_type:
         raise CheckSemanticError(
             f'type {str(instance_type)} is not a {str(class_type)}')
     if not class_type.is_method(node.method):
         raise CheckSemanticError(f'method {node.method} not defined')
     args_type = class_type.get_method_args(node.method)
     if len(args_type) != len(node.arguments):
         raise CheckSemanticError(
             f'{node.method} require {len(args_type)} arguments')
     for i in range(len(args_type)):
         t = self.visit(node.arguments[i], scope)
         if not t < args_type[i]:
             raise CheckSemanticError(
                 f'{str(t)} doesn\'t conform {str(args_type[i])}')
     method = class_type.get_method(node.method)
     r_type = method[node.method]['return_type']
     if r_type.name == 'SELF_TYPE':
         node.static_type = class_type
         return class_type
     node.static_type = r_type
     return r_type
Beispiel #2
0
    def visit(self, node: ast.Case, scope: Scope):
        t = list(scope.get_types().keys())
        t.reverse()

        def get_by_(tp, l: ast.Action):
            for i in l:
                if tp == i.action_type:
                    return i

        k = []
        for i in t:
            n = get_by_(i, node.actions)
            if n:
                k.append(n)

        node.actions = k
        self.visit(node.expr, scope)
        list_type = []
        for item in node.actions:
            list_type.append(self.visit(item, scope))
        return_type = list_type[0]
        for item in list_type[1:]:
            if return_type.name == 'SELF_TYPE' and item.name == 'SELF_TYPE':
                continue
            elif return_type.name == 'SELF_TYPE':
                return_type = scope.join(scope.getType(scope.classname), item)
            elif item.name == 'SELF_TYPE':
                return_type = scope.join(scope.getType(scope.classname),
                                         return_type)
            else:
                return_type = scope.join(return_type, item)
        node.static_type = return_type
        return return_type
Beispiel #3
0
 def visit(self, node: ast.Action, scope: Scope):
     scope.getType(node.action_type)
     new_scope = Scope(scope.classname, scope)
     new_scope.defineSymbol(node.name, scope.getType(node.action_type))
     return_type = self.visit(node.body, new_scope)
     node.static_type = return_type
     return return_type
Beispiel #4
0
 def visit(self, node:ast.ClassMethod, scope:Scope, errors):
     for i in node.formal_params:
         try:
             scope.defineSymbol(i.name, scope.getType(i.param_type))
         except Exception as e:
             print(e)
     tb = self.visit(node.body, scope, error)
     if not tb < scope.getType(node.return_type):
         raise CheckSemanticError(f'{tb} doesn\'t conform {node.return_type}')
     return scope.getType(node.return_type)
Beispiel #5
0
 def visit(self, node:ast.Case, scope:Scope, errors):
     self.visit(node.expr, scope, errors)
     listType = []
     for item in node.actions:
         try:
             scope.getType(item.action_type)
         except Exception as e:
             print(e)
         listType.append(self.visit(item, scope, errors))
     returnType = listType[0]
     for item in listType[1:]:
         returnType = scope.join(returnType, item)
     return returnType
Beispiel #6
0
 def visit(self, node: ast.Equal, scope: Scope):
     left_type = self.visit(node.first, scope)
     right_type = self.visit(node.second, scope)
     if left_type.name == 'SELF_TYPE':
         left_type = scope.getType(scope.classname)
     if right_type.name == 'SELF_TYPE':
         right_type = scope.getType(scope.classname)
     if not left_type.name == right_type.name:
         raise CheckSemanticError(
             f'In equal expressions type must be the same type')
     bool_type = scope.getType('Bool')
     node.static_type = bool_type
     return bool_type
Beispiel #7
0
 def visit(self, node: ast.LessThan, scope: Scope):
     left_type = self.visit(node.first, scope)
     right_type = self.visit(node.second, scope)
     if not left_type.name == 'Int' or not right_type.name == 'Int':
         raise CheckSemanticError(f'expressions type must be Int')
     bool_type = scope.getType('Bool')
     return bool_type
Beispiel #8
0
 def visit(self, node: ast.IntegerComplement, scope: Scope):
     exp_type = self.visit(node.integer_expr, scope)
     if not exp_type.name == "Int":
         raise CheckSemanticError(f'{exp_type.name} doest\' match with Int')
     int_type = scope.getType('Int')
     node.static_type = int_type
     return int_type
Beispiel #9
0
 def visit(self, node: ast.BooleanComplement, scope: Scope):
     exp_type = self.visit(node.boolean_expr, scope)
     if not exp_type.name == 'Bool':
         raise CheckSemanticError(f'{exp_type.name} doest\' match wiht Int')
     bool_type = scope.getType('Bool')
     node.static_type = bool_type
     return bool_type
Beispiel #10
0
 def visit(self, node: ast.Division, scope: Scope):
     left_type = self.visit(node.first, scope)
     right_type = self.visit(node.second, scope)
     if not left_type.name == 'Int' or not right_type.name == 'Int':
         raise CheckSemanticError(f'expressions type must be Int')
     int_type = scope.getType('Int')
     node.static_type = int_type
     return int_type
Beispiel #11
0
 def visit(self, node: ast.ClassAttribute, scope: Scope):
     node.static_type = scope.getType(node.attr_type)
     if node.init_expr:
         t_exp = self.visit(node.init_expr, scope)
         if node.attr_type != 'SELF_TYPE':
             if t_exp.name == 'SELF_TYPE':
                 raise CheckSemanticError(
                     f'You can\'t not assign a SELF_TYPE expression in a non SELF_TYPE'
                     f'attribute')
             if not t_exp < scope.getType(node.attr_type):
                 raise CheckSemanticError(
                     f'{str(t_exp)} doesn\'t conform {str(scope.getType(node.attr_type))}'
                 )
         else:
             if t_exp.name == 'SELF_TYPE':
                 raise CheckSemanticError(
                     f'Attribute {node.name} of type {node.attr_type} must to be instanced'
                     f' by a SELF_type expression.')
Beispiel #12
0
 def visit(self, node: ast.WhileLoop, scope: Scope):
     pred_type = self.visit(node.predicate, scope)
     if not pred_type.name == "Bool":
         raise CheckSemanticError(
             f'you can\'t match {pred_type.name} with Bool')
     self.visit(node.body, scope)
     object_type = scope.getType('Object')
     node.static_type = object_type
     return object_type
Beispiel #13
0
 def visit(self, node: ast.ClassMethod, scope: Scope):
     node.static_type = scope.getType(node.return_type)
     for i in node.formal_params:
         scope.defineSymbol(i.name, scope.getType(i.param_type))
     tb = self.visit(node.body, scope)
     if tb.name == 'SELF_TYPE' and node.return_type == 'SELF_TYPE':
         return scope.classname
     elif tb.name == 'SELF_TYPE':
         if scope.getType(scope.classname) < node.static_type:
             return node.static_type
         else:
             raise CheckSemanticError(
                 f'{scope.getType(scope.classname)} doesn\'t conform {node.static_type}'
             )
     elif node.return_type == 'SELF_TYPE':
         raise CheckSemanticError(
             f'Method {node.name} returns SELF_TYPE and body doesn\'t')
     if not tb < scope.getType(node.return_type):
         raise CheckSemanticError(
             f'{tb} doesn\'t conform {node.return_type}')
     return scope.getType(node.return_type)
Beispiel #14
0
 def visit(self, node: ast.If, scope: Scope):
     pred_type = self.visit(node.predicate, scope)
     if not pred_type.name == "Bool":
         raise CheckSemanticError(
             f'you can\'t match {pred_type.name} with Bool')
     if_type = self.visit(node.then_body, scope)
     else_type = self.visit(node.else_body, scope)
     if if_type.name == 'SELF_TYPE' and if_type.name == 'SELF_TYPE':
         node.static_type = if_type
         return if_type
     elif if_type.name == 'SELF_TYPE':
         return_type = scope.join(else_type, scope.getType(scope.classname))
         node.static_type = return_type
         return return_type
     elif else_type.name == 'SELF_TYPE':
         return_type = scope.join(if_type, scope.getType(scope.classname))
         node.static_type = return_type
         return return_type
     else:
         return_type = scope.join(if_type, else_type)
         node.static_type = return_type
         return return_type
Beispiel #15
0
 def visit(self, node: ast.Formal, scope: Scope):
     scope.defineSymbol(node.name, scope.getType(node.param_type), True)
     t = self.visit(node.init_expr, scope)
     if not t:
         node.static_type = scope.getType(
             node.param_type
         ) if node.param_type != 'SELF_TYPE' else scope.getType(
             scope.classname)
         return
     if node.param_type == 'SELF_TYPE' and t.name == 'SELF_TYPE':
         return
     elif t.name == 'SELF_TYPE':
         if t < scope.getType(scope.classname):
             return
         else:
             raise CheckSemanticError(
                 f'{node.name} doesn\'t conform {scope.classname}')
     elif node.param_type == 'SELF_TYPE':
         raise CheckSemanticError(
             f'Only can assign SELF_TYPE in a SELF_TYPE variable.')
     if not t < scope.getType(node.param_type):
         raise CheckSemanticError(
             f'{str(t)} doesn\'t conform {str(node.param_type)}')
Beispiel #16
0
 def visit(self, node: ast.Assignment, scope: Scope):
     instance_type = scope.getTypeFor(node.instance.name)
     expr_type = self.visit(node.expr, scope)
     if expr_type.name == 'SELF_TYPE':
         r_type = scope.getType(scope.classname)
         if r_type < instance_type:
             return r_type
         raise CheckSemanticError(
             f'{r_type} doesn\'t conform {instance_type}')
     if not expr_type < instance_type:
         raise CheckSemanticError(
             f'{expr_type} doesn\'t conform {instance_type}')
     node.static_type = expr_type
     return expr_type
Beispiel #17
0
 def visit(self, node:ast.StaticDispatch, scope:Scope, errors):
     instanceType = scope.getTypeFor(node.instance)
     classType = scope.getType(node.dispatch_type)
     if not instanceType < :
         raise CheckSemanticError(f'type {instanceType} is not a {node.dispatch_type}')
     if not classType.is_method(node.method):
        raise CheckSemanticError(f'method {node.method} not defined')
     argsType = classType.get_method_args(node.method)
     if len(argsType) != len(node.arguments):
         raise CheckSemanticError(f'{node.method} require {len(argsType)} arguments')
     for x, y in argsType, node.arguments:
         t = self.visit(y, scope, errors)
         if not t < x:
             raise CheckSemanticError(f'{str(t)} doesn\'t conform {str(x)}')
     method = classType.get_method(node.method)
     return  method.return_type
Beispiel #18
0
 def visit(self, node:ast.Class, scope:Scope, errors):
     methods = filter(lambda x: type(x) is ast.ClassMethod, classDef)
     methods = list(methods)
     attribs = filter(lambda x: type(x) is ast.ClassAttribute, classDef)
     attribs = list(attribs)
     for i in attribs:
         ta = self.visit(i, scope, errors)
         try:
             scope.getType(node.name).add_attrib({i.name: scope.getType(i.attr_type)})
         except Exception as e:
             print(e)
     for i in methods:
         try:
             scope.getType(node.name).add_method({i.name:{
                 'formal_params':{
                     t.name: scope.getType(t.param_type) for j in i.formal_params
                 },
                 'return_type': scope.getType(i.return_type),
                 'body': i.body
             }})
         exec Exception as e:
             print(e)
Beispiel #19
0
 def visit(self, node: ast.Self, scope: Scope):
     node.static_type = scope.getType(scope.classname)
     return scope.getType('SELF_TYPE')
Beispiel #20
0
 def visit(self, node:ast.Equal, scope:Scope, errors):
     leftType = self.visit(node.first, scope, errors)
     rigthType = self.visit(node.second, scope, errors)
     if not leftType.name == rigth.name:
         raise CheckSemanticError(f'expressions type must be the same type')
     return scope.getType('Bool')
Beispiel #21
0
 def visit(self, node:ast.LessThanOrEqual, scope:Scope, errors):
     leftType = self.visit(node.first, scope, errors)
     rigthType = self.visit(node.second, scope, errors)
     if not leftType.name == 'Int' or not rigth.name == 'Int':
         raise CheckSemanticError(f'expressions type must be Int')
     return scope.getType('Int')
Beispiel #22
0
 def visit(self, node:ast.Integer, scope:Scope, errors):
     return scope.getType("Int")
Beispiel #23
0
    def visit(self, node: ast.ClassAttribute, scope: Scope, errors):
    try:
        scope.defineAttrib(node.name, scope.getType(node.attr_type))
    except Exception as e:
        print(e)

    @visitor.when(ast.ClassMethod)
    def visit(self, node:ast.ClassMethod, scope:Scope, errors):
        for i in node.formal_params:
            try:
                scope.defineSymbol(i.name, scope.getType(i.param_type))
            except Exception as e:
                print(e)
        tb = self.visit(node.body, scope, error)
        if not tb < scope.getType(node.return_type):
            raise CheckSemanticError(f'{tb} doesn\'t conform {node.return_type}')
        return scope.getType(node.return_type)

    @visitor.when(ast.Integer)
    def visit(self, node:ast.Integer, scope:Scope, errors):
        return scope.getType("Int")

    @visitor.when(ast.String)
    def visit(self, node:ast.String, scope:Scope, errors):
        return scope.getType("String")

    @visitor.when(ast.Boolean)
    def visit(self, node:ast.Boolean, scope:Scope, errors):
        return scope.getType("Bool")

    @visitor.when(ast.Object)
    def visit(self, node:ast.Object, scope:Scope, errors):
        return scope.getTypeFor(node.name)

    @visitor.when(ast.Self)
    def visit(self, node:ast.Self, scope:Scope, errors):
        return scope.getType(scope.classname)

    @visitor.when(ast.NewObject)
    def visit(self, node:ast.NewObject, scope:Scope, errors):
        return scope.getType(node.type)

    @visitor.when(ast.IsVoid)
    def visit(self, node:ast.IsVoid, scope:Scope, errors):
        self.visit(node.expr)
        return scope.getType("Bool")

    @visitor.when(ast.Assignment)
    def visit(self, node:ast.Assignment, scope:Scope, errors):
        try:
            instanceType = scope.getTypeFor(node.instance.name)
            exprType = self.visit(node.expr, scope, errors)
            if not instanceType < exprType :
                raise CheckSemanticError(f'{tb} doesn\'t conform {node.return_type}')
            return exprType
        except:
            raise CheckSemanticError(f'Symbol {node.instance.name} not defined in the Scope.')

    @visitor.when(ast.Block)
    def visit(self, node:ast.Block, scope:Scope, errors):
        for item in node.expr_list:
            self.visit(item, scope, errors)
        return self.visit(node.expr_list[-1], scope, errors)

    @visitor.when(ast.DynamicDispatch)
    def visit(self, node:ast.DynamicDispatch, scope:Scope, errors):
        instanceType = scope.getTypeFor(node.instance)
        if not instanceType.is_method(node.method):
           raise CheckSemanticError(f'method {node.method} not defined')
        argsType = instanceType.get_method_args(node.method)
        if len(argsType) != len(node.arguments):
            raise CheckSemanticError(f'{node.method} require {len(argsType)} arguments')
        for x, y in argsType, node.arguments:
            t = self.visit(y, scope, errors)
            if not t < x:
                raise CheckSemanticError(f'{str(t)} doesn\'t conform {str(x)}')
        method = instanceType.get_method(node.method)
        return  method.return_type

    @visitor.when(ast.StaticDispatch)
    def visit(self, node:ast.StaticDispatch, scope:Scope, errors):
        instanceType = scope.getTypeFor(node.instance)
        classType = scope.getType(node.dispatch_type)
        if not instanceType < :
            raise CheckSemanticError(f'type {instanceType} is not a {node.dispatch_type}')
        if not classType.is_method(node.method):
           raise CheckSemanticError(f'method {node.method} not defined')
        argsType = classType.get_method_args(node.method)
        if len(argsType) != len(node.arguments):
            raise CheckSemanticError(f'{node.method} require {len(argsType)} arguments')
        for x, y in argsType, node.arguments:
            t = self.visit(y, scope, errors)
            if not t < x:
                raise CheckSemanticError(f'{str(t)} doesn\'t conform {str(x)}')
        method = classType.get_method(node.method)
        return  method.return_type

    @visitor.when(ast.Let)
    def visit(self, node:ast.Let, scope:Scope, errors):
        newScope = Scope(scope.classname, scope)
        for decl in node.init_expr :
            try:
                self.visit(decl, newScope, errors)
            except Exception as e:
                print(e)
        return self.visit(node.body, newScope, errors)

    @visitor.when(ast.Formal)
    def visit(self, node:ast.Formal, scope:Scope, errors):
        scope.defineSymbol(node.name, scope.getType(node.param_type), True)
        t = self.visit(node.init_expr, scope)
    	if not t < node.param_type:
            raise CheckSemanticError(f'{str(t)} doesn\'t conform {str(node.param_type)}')

    @visitor.when(ast.If)
    def visit(self, node:ast.If, scope:Scope, errors):
        predType = self.visit(node.predicate, scope, errors)
        if not predType.name == "Bool":
            raise CheckSemanticError(f'you can\'t match {predType.name} with Bool')
        ifType = self.visit(node.then_body, scope, errors)
        elseType = self.visit(node.else_body, scope, errors)
        return scope.join(ifType, elseType)

    @visitor.when(ast.WhileLoop)
    def visit(self, node:ast.WhileLoop, scope:Scope, errors):
        predType = self.visit(node.predicate, scope, errors)
        if not predType.name == "Bool":
            raise CheckSemanticError(f'you can\'t match {predType.name} with Bool')
        self.visit(node.body, scope, errors)
        return scope.getType('Object')

    @visitor.when(ast.Case)
    def visit(self, node:ast.Case, scope:Scope, errors):
        self.visit(node.expr, scope, errors)
        listType = []
        for item in node.actions:
            try:
                scope.getType(item.action_type)
            except Exception as e:
                print(e)
            listType.append(self.visit(item, scope, errors))
        returnType = listType[0]
        for item in listType[1:]:
            returnType = scope.join(returnType, item)
        return returnType

    @visitor.when(ast.Action)
    def visit(self, node:ast.Action, scope:Scope, errors):
        newScope = Scope(scope.classname, scope)
        newScope.defineSymbol(node.name, scope.getType(node.action_type))
        return self.visit(node.body, newScope, errors)

    @visitor.when(ast.IntegerComplement)
    def visit(self, node:ast.IntegerComplement, scope:Scope, errors):
        exprType = self.visit(node.integer_expr, scope, errors)
        if not exprType.name == "Int":
            raise CheckSemanticError(f'{exprType.name} doest\' match wiht Int')
        return scope.getType('Int')

    @visitor.when(ast.BooleanComplement)
    def visit(self, node:ast.BooleanComplement, scope:Scope, errors):
        exprType = self.visit(node.integer_expr, scope, errors)
        if not exprType.name == 'Bool':
            raise CheckSemanticError(f'{exprType.name} doest\' match wiht Int')
        return scope.getType('Bool')

    @visitor.when(ast.Addition)
    def visit(self, node:ast.Addition, scope:Scope, errors):
        leftType = self.visit(node.first, scope, errors)
        rigthType = self.visit(node.second, scope, errors)
        if not leftType.name == 'Int' or not rigth.name == 'Int':
            raise CheckSemanticError(f'expressions type must to be Int')
        return scope.getType('Int')

    @visitor.when(ast.Subtraction)
    def visit(self, node:ast.Subtraction, scope:Scope, errors):
        leftType = self.visit(node.first, scope, errors)
        rigthType = self.visit(node.second, scope, errors)
        if not leftType.name == 'Int' or not rigth.name == 'Int':
            raise CheckSemanticError(f'expressions type must to be Int')
        return scope.getType('Int')

    @visitor.when(ast.Multiplication)
    def visit(self, node:ast.Multiplication, scope:Scope, errors):
        leftType = self.visit(node.first, scope, errors)
        rigthType = self.visit(node.second, scope, errors)
        if not leftType.name == 'Int' or not rigth.name == 'Int':
            raise CheckSemanticError(f'expressions type must to be Int')
        return scope.getType('Int')

    @visitor.when(ast.Division)
    def visit(self, node:ast.Division, scope:Scope, errors):
        leftType = self.visit(node.first, scope, errors)
        rigthType = self.visit(node.second, scope, errors)
        if not leftType.name == 'Int' or not rigth.name == 'Int':
            raise CheckSemanticError(f'expressions type must be Int')
        return scope.getType('Int')
    
    @visitor.when(ast.Equal)
    def visit(self, node:ast.Equal, scope:Scope, errors):
        leftType = self.visit(node.first, scope, errors)
        rigthType = self.visit(node.second, scope, errors)
        if not leftType.name == rigth.name:
            raise CheckSemanticError(f'expressions type must be the same type')
        return scope.getType('Bool')

    @visitor.when(ast.LessThan)
    def visit(self, node:ast.LessThan, scope:Scope, errors):
        leftType = self.visit(node.first, scope, errors)
        rigthType = self.visit(node.second, scope, errors)
        if not leftType.name == 'Int' or not rigth.name == 'Int':
            raise CheckSemanticError(f'expressions type must be Int')
        return scope.getType('Int')

     @visitor.when(ast.LessThanOrEqual)
    def visit(self, node:ast.LessThanOrEqual, scope:Scope, errors):
        leftType = self.visit(node.first, scope, errors)
        rigthType = self.visit(node.second, scope, errors)
        if not leftType.name == 'Int' or not rigth.name == 'Int':
            raise CheckSemanticError(f'expressions type must be Int')
        return scope.getType('Int')
Beispiel #24
0
 def visit(self, node:ast.String, scope:Scope, errors):
     return scope.getType("String")
Beispiel #25
0
 def visit(self, node: ast.Integer, scope: Scope):
     node.static_type = scope.getType('Int')
     return scope.getType("Int")
Beispiel #26
0
 def visit(self, node: ast.String, scope: Scope):
     node.static_type = scope.getType('String')
     return scope.getType("String")
Beispiel #27
0
 def visit(self, node: ast.Boolean, scope: Scope):
     node.static_type = scope.getType('Bool')
     return scope.getType("Bool")
Beispiel #28
0
 def visit(self, node: ast.IsVoid, scope: Scope):
     node.static_type = scope.getType('Bool')
     self.visit(node.expr, scope)
     return scope.getType("Bool")
Beispiel #29
0
    def visit(self, node: ast.Program, _):
        scope_root = Scope(None, None)
        for classDef in node.classes:
            new_type = ctype(classDef.name)
            scope_root.createType(new_type)
        for classDef in node.classes:
            a = scope_root.getType(classDef.name)
            a.parent = scope_root.getType(classDef.parent)
        new_types = self.sort_type(scope_root.get_types())
        node.classes = list(
            map(lambda x: self.get_node_by_type(x, node.classes),
                list(new_types.keys())[6:]))
        scope_root.set_types(new_types)
        self.check_ciclic_inheritance(scope_root.get_types())
        scopes = []
        for j in node.classes:
            scope = Scope(j.name, scope_root)
            methods = filter(lambda x: type(x) is ast.ClassMethod, j.features)
            methods = list(methods)
            attribs = filter(lambda x: type(x) is ast.ClassAttribute,
                             j.features)
            attribs = list(attribs)
            p_type = scope.getType(j.parent)
            if p_type.name in ['Int', 'Bool', 'String']:
                raise CheckSemanticError(
                    f'Any type can\'t inheriths from {p_type}')
            for i in p_type.attributes:
                try:
                    scope.getType(j.name).add_attrib(i)
                except Exception as e:
                    raise e
                try:
                    scope.defineAttrib(list(i.keys())[0], list(i.values())[0])
                except Exception as e:
                    raise e

            for i in attribs:
                try:
                    scope.getType(j.name).add_attrib(
                        {i.name: scope.getType(i.attr_type)})
                except Exception as e:
                    raise e
                try:
                    scope.defineAttrib(i.name, scope.getType(i.attr_type))
                except Exception as e:
                    raise e
            for i in methods:
                try:
                    scope.getType(j.name).add_method({
                        i.name: {
                            'formal_params': {
                                t.name: scope.getType(t.param_type)
                                for t in i.formal_params
                            },
                            'return_type': scope.getType(i.return_type),
                            'body': i.body
                        }
                    })
                except Exception as e:
                    raise e
            scopes.append(scope)
        for i in range(len(node.classes)):
            self.visit(node.classes[i], scopes[i])
        return scope_root
Beispiel #30
0
 def visit(self, node: ast.NewObject, scope: Scope):
     node.static_type = scope.getType(node.type)
     return scope.getType(node.type)