示例#1
0
文件: weeder.py 项目: rpeng/cs444
 def VisitCastExpression(self, node):
     if not (isinstance(node.cast_type, PrimitiveType) or
             isinstance(node.cast_type, ClassOrInterfaceType) or
             isinstance(node.cast_type, NameExpression) or
             node.is_array):
         err(node[0].token,
             "A cast must be of primitive or reference types")
示例#2
0
文件: resolver.py 项目: rpeng/cs444
 def Resolve(self, name):
     canon = name.AsString()
     resolved = self._ResolveCanon(canon, name)
     if resolved:
         name.linked_type = resolved
     else:
         err(name.tokens[0], "Resolver: Type does not exist: " + canon)
示例#3
0
def VerifyReplaceDecl(old_decl, new_decl, abstract=False):
    old_header = old_decl.header
    new_header = new_decl.header

    old_modifiers = [x.lexeme for x in old_header.modifiers]
    new_modifiers = [x.lexeme for x in new_header.modifiers]

    m_name = new_header.m_id.lexeme

    # Check return types match
    if MakeTypeSig(old_header.m_type) != MakeTypeSig(new_header.m_type):
        err(new_header.m_id, "Return type mismatch in: " + m_name)

    # Check static -> non_static
    if 'static' in old_modifiers and 'static' not in new_modifiers:
        err(new_header.m_id, "Static replaced with non-static in: " + m_name)

    # Check nonstatic -> static
    if 'static' not in old_modifiers and 'static' in new_modifiers:
        err(new_header.m_id, "Non-static replaced with static in: " + m_name)

    # Check public -> protected
    if 'public' in old_modifiers and 'protected' in new_modifiers:
        err(new_header.m_id, "Public replaced with protected in: " + m_name)

    # Check override final
    if 'final' in old_modifiers:
        err(new_header.m_id, "Attempt to override final method: " + m_name)
示例#4
0
def CheckInterfaceSimple(node):
    if node.extends_interface:
        CheckDuplicateInterfaces(node.name, node.extends_interface)
        for interface in node.extends_interface:
            if not isinstance(interface.linked_type, InterfaceDecl):
                err(node.name, "An interface must not extend a class: " +
                    interface.AsString())
示例#5
0
文件: analyzer.py 项目: rpeng/cs444
 def VisitBlock(self, node):
     self.saw_return = False
     if node.stmts:
         for stmt in node.stmts:
             if self.saw_return or self.infinite_loop:
                 err(node[0].token, "Unreachable statement.")
             self.Visit(stmt)
示例#6
0
 def VisitName(self, node):
     if not node.linked_type:
         if self.decl is not None:
             index = node.env.FieldIndex(node.Split()[0])
             if index is not None and index >= self.decl:
                 err(node.tokens[0], "Invalid forward reference: " + node.AsString())
         self.linker.DisambiguateAndLink(node)
示例#7
0
def ResolveLinkClassMethods(node):
    # Returns decls: set(MethodDecls)
    decl_map = collections.OrderedDict()
    class_modifiers = [x.lexeme for x in node.modifiers]
    is_abstract = 'abstract' in class_modifiers

    if node.interfaces:
        for interface in node.interfaces:
            decls = ResolveLinkInterfaceDecls(interface.linked_type)
            AddDecls(decls, decl_map)

    if node.extends:
        decls = ResolveLinkClassMethods(node.extends.linked_type)
        AddDecls(decls, decl_map, is_abstract)
    elif GetObject():
        AddDecls(GetObject().method_decls, decl_map, is_abstract)

    if node is not GetObject():
        AddDecls(node.method_decls, decl_map, is_abstract)

    if not is_abstract:
        for decl in decl_map.values():
            if decl.IsAbstract():
                err(
                    node.name,
                    "Non abstract class must implement all methods: " +
                    decl.header.m_id.lexeme)

    node.method_map = decl_map
    return set(decl_map.values())
示例#8
0
文件: weeder.py 项目: rpeng/cs444
    def VisitConstructorDecl(self, node):
        self._CheckModifiersCommon(node.name, node.modifiers)

        if node.name.lexeme != self.filename:
            err(node.name, "Constructor must have same name as base class")

        if node.body:
            node.body.visit(self)
示例#9
0
文件: analyzer.py 项目: rpeng/cs444
 def VisitWhileStatement(self, node):
     result = self.evaluator.Visit(node.test_expr)
     if result is False:
         err(node[0].token, "Unreachable statement in while loop.")
     if result is True:
         self.infinite_loop = True
     self.Visit(node.body)
     self.saw_return = False
示例#10
0
文件: resolver.py 项目: rpeng/cs444
 def _ResolvePackageImports(self, canon, name):
     # Look in package imports
     results = name.env.LookupNameInPackages(canon)
     if results:
         if len(results) > 1:
             err(name.tokens[0], "Ambiguous usage of: " + canon)
         else:
             return results[0]
示例#11
0
文件: resolver.py 项目: rpeng/cs444
    def _CheckPrefix(self, canon, name):
        split = canon.split('.')

        for i in range(1, len(split)):
            prefix = '.'.join(split[:i])
            if self._ResolveCanon(prefix, name):
                err(
                    name.tokens[0], "Prefix of qualified type should "
                    "not resolve to a type: " + canon + ' prefix: ' + prefix)
示例#12
0
 def CheckConstructor(self, node):
     if node.linked_type.IsProtected():
         own_pkg = node.env.LookupPackage()
         other_pkg = node.linked_type.env.LookupPackage()
         if own_pkg is None or other_pkg is None:
             if own_pkg != other_pkg:
                 err(node[0].token, "Access of protected constructor")
         elif own_pkg[1] != other_pkg[1]:
             err(node[0].token, "Access of protected constructor")
示例#13
0
 def VisitMethodInvocation(self, node):
     if node.name:
         if self.decl is not None:
             index = node.env.FieldIndex(node.name.Split()[0])
             if index is not None and index >= self.decl:
                 err(node.name.tokens[0],
                     "Invalid forward reference: " + node.name.AsString())
         self.linker.DisambiguateAndLinkMethod(node)
     self.Visit(node.primary)
     self.Visit(node.args)
示例#14
0
文件: analyzer.py 项目: rpeng/cs444
    def VisitMethodDecl(self, node):
        should_ret = not isinstance(node.header.m_type, VoidType)
        self.infinite_loop = False
        self.saw_return = False

        if node.body_block:
            self.Visit(node.body_block)
            if not self.infinite_loop:
                if should_ret and not self.saw_return:
                    err(node.header.m_id, "Expected return statement.")
示例#15
0
文件: weeder.py 项目: rpeng/cs444
    def VisitFieldDecl(self, node):
        self._CheckModifiersCommon(node.var_decl.var_id, node.modifiers)

        modifiers = [x.lexeme for x in node.modifiers]
        if 'final' in modifiers and node.var_decl.exp is None:
            err(node.modifiers[0], "A final field must be initialized")
        if 'public' not in modifiers and 'protected' not in modifiers:
            err(node.f_type, "Package cannot have private field")
        if node.var_decl:
            node.var_decl.visit(self)
示例#16
0
def CheckDuplicateMethods(method_decls):
    if method_decls is None:
        return

    sigs = set()
    for decl in method_decls:
        sig = tuple(MakeMethodSig(decl.header))
        if sig in sigs:
            err(decl.header.m_id,
                "Duplicate method definition: " + decl.header.m_id.lexeme)
        sigs.add(sig)
示例#17
0
文件: weeder.py 项目: rpeng/cs444
    def VisitMethodDecl(self, node):
        node.header.visit(self)

        modifiers = [x.lexeme for x in node.header.modifiers]
        if (('abstract' in modifiers or 'native' in modifiers) and
                node.body_block is not None):
            err(node.header.modifiers[0],
                "A method has a body if and"
                "only if it is neither abstract nor native")
        if node.body_block is not None and node.body_block.stmts is not None:
            for stmt in node.body_block.stmts:
                stmt.visit(self)
示例#18
0
文件: weeder.py 项目: rpeng/cs444
 def VisitInterfaceDecl(self, node):
     if node.name.lexeme != self.filename:
         err(node.name, "The interface name must match the filename "
             + self.filename)
     if node.method_decls:
         for decl in node.method_decls:
             modifiers = [x.lexeme for x in decl.header.modifiers]
             if ('static' in modifiers or 'final' in modifiers
                     or 'native' in modifiers):
                 err(decl.header.modifiers[0],
                     ('An interface method cannot be '
                      'static, final, or native'))
             decl.header.visit(self)
示例#19
0
文件: weeder.py 项目: rpeng/cs444
 def _CheckModifiersCommon(self, name, modifiers):
     # Check duplicate
     hashed = set()
     for modifier in modifiers:
         if modifier.lexeme in hashed:
             err(modifier, "Duplicate modifier: " + modifier.lexeme)
         hashed.add(modifier.lexeme)
     modifiers = [x.lexeme for x in modifiers]
     # Check no package private
     if ('public' not in modifiers
             and 'protected' not in modifiers
             and 'private' not in modifiers):
         err(name, "Cannot have package private modifiers")
示例#20
0
def CheckLinkConstructors(node):
    if node.constructor_decls is None:
        return

    cons_map = {}
    for decl in node.constructor_decls:
        sig = tuple(MakeMethodSig(decl))
        if sig in cons_map:
            err(decl.name,
                "Duplicate constructor definition: " + decl.name.lexeme)
        cons_map[sig] = decl

    node.cons_map = cons_map
示例#21
0
    def CheckAccess(self, debug_token, names, context):
        if not names:
            return context

        for current in names:
            try:
                if context.type == AccessContext.PKG:
                    (type, decl, linked) = self.CheckInPackage(current, context)
                else:
                    b = self.CheckAll(current, context)
                    (type, decl, linked) = self.CheckAll(current, context)
                context = AccessContext(type, decl, context.parent_type, linked)
            except AccessError, e:
                err(debug_token, e.message)
示例#22
0
def CheckClassNoCycles(node):
    if node in acyclic_class_nodes:
        return

    visited_set = set(node)
    while True:
        extends = node.extends
        if extends:
            node = extends.linked_type
            if node in visited_set:
                err(node.name, "Cyclic inheritance of: " + extends.AsString())
            visited_set.add(node)
        else:
            break

    acyclic_class_nodes.add(node)
示例#23
0
def CheckInterfaceNoCycles(node, path=None):
    if node in acyclic_interface_nodes:
        return

    if path is None:
        path = set()

    if node.extends_interface:
        path.add(node)
        for name in node.extends_interface:
            if name.linked_type in path:
                err(node.name,
                    "Cyclic interface extends: " + name.AsString())
            CheckInterfaceNoCycles(name.linked_type, path)
        path.remove(node)
    acyclic_interface_nodes.add(node)
示例#24
0
文件: env.py 项目: rpeng/cs444
 def AddClassImport(self, node, decl):
     # node : Name
     name = node.Last()
     type = self.LookupClassOrInterface()
     if type is not None and name == type[0]:
         pkg = self.LookupPackage()
         decl = self.LookupClassOrInterface()
         if pkg and decl:
             pkg = pkg[0]
             decl = decl[0]
         # You are allowed to import yourself
         if not (node.Prefix() == pkg and node.Last() == decl):
             err(node.tokens[0], "Import clashes with class decl: " + name)
     class_import = self.LookupClassImport(name)
     if class_import is not None:
         class_name = class_import[0]
         # You can include the same thing twice
         if node.AsString() != class_name.AsString():
             err(node.tokens[0], "Import clashes with another: " + name)
     self.class_imports[name] = (node, decl)
示例#25
0
文件: weeder.py 项目: rpeng/cs444
    def VisitMethodHeader(self, node):
        self._CheckModifiersCommon(node.m_id, node.modifiers)

        modifiers = [x.lexeme for x in node.modifiers]
        if 'abstract' in modifiers and ('static' in modifiers
                                        or 'final' in modifiers):
            err(node.modifiers[0],
                'An abstract method cannot be static or final')
        if 'static' in modifiers and 'final' in modifiers:
            err(node.modifiers[0], 'A static method cannot be final')
        if 'native' in modifiers and 'static' not in modifiers:
            err(node.modifiers[0], 'A native method must be static')
        if 'public' not in modifiers and 'protected' not in modifiers:
            err("Package cannot have private field")
示例#26
0
    def CheckMethodName(self, node, is_static):
        tokens = node.name.Split()
        parent = node.env.LookupClassOrInterface()[1]

        if is_static:
            context = AccessContext(AccessContext.CLASS, node, parent)
        else:
            context = AccessContext(AccessContext.EXPR, node, parent)
        context = self.CheckAccess(node[1].token, tokens[:-1], context)

        if (context.type == AccessContext.CLASS and not node.linked_method.IsStatic()):
            err(node[1].token, "Access of non-static method in static context")
        if (context.type == AccessContext.EXPR and node.linked_method.IsStatic()):
            err(node[1].token, "Access of static method in non-static context")

        if node.linked_method.IsStatic():
            context.decl = node.linked_method.env.LookupClassOrInterface()[1]

        if node.linked_method.IsProtected():
            if not self.CanAccessProtected(
                    context,
                    node.linked_method,
                    static=node.linked_method.IsStatic()):
                err(node[1].token, "Access of protected method")

        node.context = context
示例#27
0
    def DisambiguateAndLink(self, node, name_tokens=None):
        tokens = name_tokens
        if not name_tokens:
            tokens = node.Split()
        first = tokens[0]
        env = node.env
        result = self.CheckNameAndEnv(first, env)

        if result:
            name_type, decl_or_pkg = result
            for name in tokens[1:]:
                if decl_or_pkg is None:
                    err(node.tokens[0],
                        "Name " + node.AsString() + " not found.")
                if name_type == NameType.PACKAGE:
                    next = (self.CheckTypeInPackage(name, decl_or_pkg)
                            or self.CheckPackageInPackage(name, decl_or_pkg))
                elif name_type == NameType.TYPE or name_type == NameType.EXPR:
                    if isinstance(decl_or_pkg, ArrayType):
                        if name == 'length':
                            next = (NameType.TYPE, ArrayType.LengthDecl)
                    elif isinstance(decl_or_pkg, PrimitiveType):
                        err(node.tokens[0],
                            "Cannot dereference primitive type")
                    else:
                        next = (self.CheckFields(name, decl_or_pkg.env))
                if not next:
                    err(node.tokens[0],
                        "Name " + node.AsString() + " not found.")
                name_type, decl_or_pkg = next
            if name_type == NameType.PACKAGE:
                err(node.tokens[0], "Unexpected package")
            node.name_type = name_type
            node.linked_type = decl_or_pkg
        else:
            err(node.tokens[0], "Name " + node.AsString() + " not found.")
示例#28
0
 def RecursiveAddNode(self, pkg_list, decl_tuple):
     (name, decl) = decl_tuple
     if pkg_list:
         first, last = pkg_list[0], pkg_list[1:]
         if first not in self.packages:
             if first in self.decls and self.packages:
                 err(decl.name,
                     'Attempted to redefine type with package: ' + name)
             self.packages[first] = TypeMap()
         self.packages[first].RecursiveAddNode(last, decl_tuple)
     else:
         if name in self.decls:
             err(decl.name, "Duplicate definition of " + name)
         if name in self.packages and not self.default:
             err(decl.name,
                 "Attempted to redefine package with type: " + name)
         self.decls[name] = decl
示例#29
0
def CheckClassSimple(node):
    class_modifiers = [x.lexeme for x in node.modifiers]
    is_abstract = 'abstract' in class_modifiers

    if node.extends is not None:
        if not isinstance(node.extends.linked_type, ClassDecl):
            err(node.name, "A class must extend a class")
        else:
            modifiers = [x.lexeme for x in node.extends.linked_type.modifiers]
            if 'final' in modifiers:
                err(node.name, "A class must not extend a final class")

    if node.interfaces is not None:
        CheckDuplicateInterfaces(node.name, node.interfaces)
        for interface in node.interfaces:
            if not isinstance(interface.linked_type, InterfaceDecl):
                err(node.name, "A class must implement an interface.")
示例#30
0
def CheckDuplicateInterfaces(name, nodes):
    decls = set()
    for interface in nodes:
        if interface.linked_type in decls:
            err(name, "Duplicate interface impl: " + interface.AsString())
        decls.add(interface.linked_type)