예제 #1
0
파일: joosc.py 프로젝트: holdenli/CS-444
def joosc(targets, options):
    
    # SETUP
    ########

    global stdlib_asts

    # Build a list of targets to compile.
    target_files = []
    for target in targets:
        if os.path.isfile(target) and target.endswith('.java'):
            target_files.append(target)
        elif os.path.isdir(target) and options.directory_crawl == True:
            target_files.extend(opts.directory_crawl(target))
        else:
            logging.error("Invalid target %s, exiting..." % target)

    if options.include_stdlib == True and stdlib_asts == None:
        target_files.extend(opts.stdlib_files)

    # BUILD AST
    ############

    # Build token list for each file.
    token_lists = []
    for target_file in target_files:
        token_lists.append(get_tokens(target_file, options))
    if options.stage == 'scanner':
        sys.exit(0)

    # Build parse trees for each file.
    parse_trees = []
    for i, tokens in enumerate(token_lists):
        parse_trees.append(get_parse_tree(tokens, target_files[i], options))
    if options.stage == 'parser':
        sys.exit(0)

    # Weed each parse tree.
    for i, parse_tree in enumerate(parse_trees):
        weed_parse_tree(parse_tree, target_files[i], options)
    if options.stage == 'weeder':
        sys.exit(0)

    ast_list = []
    from utils.node import find_nodes, Node
    for i, parse_tree in enumerate(parse_trees):

        for o, n in enumerate(find_nodes(parse_tree, [Node('FieldDeclaration'),
                Node('ConstructorDeclaration'), Node('MethodDeclaration')])):
            n.decl_order = o

        ast_list.append(get_ast(parse_tree, target_files[i], options))
    if options.stage == 'ast':
        sys.exit(0)

    # stdlib optimization
    if options.include_stdlib == True:
        if stdlib_asts != None:
            ast_list.extend(stdlib_asts)
        else:
            stdlib_asts = []
            for i, ast in enumerate(ast_list):
                if target_files[i] in opts.stdlib_files:
                    stdlib_asts.append(ast)

    # TYPE RESOLUTION
    ##################

    pkg_index = build_environments(ast_list)
    
    type_index = typelink.typelink(ast_list, pkg_index)

    class_index = class_hierarchy.class_hierarchy(ast_list, pkg_index, type_index)
    if options.stage == 'hierarchy':
        sys.exit(0)

    name_resolve.name_link(pkg_index, type_index, class_index)
    if options.stage == 'name':
        for i, _ in enumerate(ast_list): 
            if options.include_stdlib == False or target_files[i] not in opts.stdlib_files or \
                    options.print_stdlib == True:
                ast_list[i].pprint()
        sys.exit(0)

    typecheck.typecheck(type_index, class_index)
    if options.stage == 'typecheck':
        for i, _ in enumerate(ast_list): 
            if options.include_stdlib == False or target_files[i] not in opts.stdlib_files or \
                    options.print_stdlib == True:
                ast_list[i].pprint()
        sys.exit(0)

    name_resolve.check_method_forwardreference(pkg_index, type_index,
        class_index)

    for i in ast_list:
        reachability.reachability(i)
    if options.stage == 'reachability':
        for i, _ in enumerate(ast_list): 
            if options.include_stdlib == False or target_files[i] not in opts.stdlib_files or \
                    options.print_stdlib == True:
                ast_list[i].pprint()
        sys.exit(0)

    codegen.gen(options, ast_list, class_index, type_index)
예제 #2
0
def build_block_env(tree, carry, new_block=True):
    """
        returns a list of environments
        sub-environments are recursively generated
    """
    envs = []

    for block in find_nodes(tree, [Node('Block'), Node('ForStatement')]):
        # get all the variables in this environment
        env = Environment(name='Block')
        env.node = block
        block.env = env # the block should point back to the env
        
        new_carry = set(carry)

        if block.name == 'ForStatement':
            if new_block:
                env.children.extend(build_block_env(ASTNode(children=[block]),
                    new_carry, new_block=False))
            else:
                # block[0] is ForInit
                # block[0][0] is LocalVariableDeclaration
                # block[0][0][1] is Identifier for LocalVariableDecl
                # block[3] is ForBody
                for_vars = list(block.select(['ForStatement', 'ForInit',
                    'LocalVariableDeclaration']))

                if len(for_vars) != 0 and block[0][0] == Node('LocalVariableDeclaration'):
                    name = for_vars[0][1].value.value
                    if name in new_carry:
                        logging.error("No two local variables=%s with overlapping scope have the same name"
                            % name)
                        sys.exit(42)

                    env.names[name] = for_vars[0]
                    new_carry.add(name)

                env.children.extend(build_block_env(block[3], new_carry))
        else:

            for stmt in find_nodes(block, [Node('Block'),
                Node('ForStatement'),
                Node('LocalVariableDeclaration')]):

                # are we making a new block?
                if stmt == Node('Block') or stmt == Node('ForStatement'):
                    env.children.extend(
                        build_block_env(Node(children=[stmt]), new_carry))

                # are we declaring a variable?
                elif stmt == Node('LocalVariableDeclaration'):
                    name = list(stmt.select(['LocalVariableDeclaration', 'Identifier']))
                    name = name[0].value.value
                    if name in new_carry:
                        logging.error("No two local variables=%s with overlapping scope have the same name"
                            % name)
                        sys.exit(42)

                    env.names[name] = stmt
                    new_carry.add(name)
                       
        envs.append(env)

    return envs
예제 #3
0
def find_and_resolve_names(type_index, cu_env, pkg_name, stmt, local_vars,
        disallowed_simple_names=None):

    for node in find_nodes(stmt, [Node('Name'), Node('MethodInvocation'),
            Node('FieldAccess'),
            Node('ArrayAccess'),
            Node('Assignment')]):

        if node == Node('MethodInvocation'):
            # node.children = ['MethodName', 'MethodReceiver', 'Arguments']

            # resolve the receiver as much as possible
            meth_recv = node[1]
            if len(meth_recv.children) > 0:
                if meth_recv[0] == Node('Name'):
                    meth_recv_name = '.'.join(meth_recv.leaf_values())
                    name_node = meth_recv[0]
                    resolved_node = name_link_name(type_index, cu_env,
                        pkg_name, local_vars,
                        meth_recv_name.split('.'),
                        disallowed_simple_names)

                    canon_type = resolve_type_by_name(type_index,
                        cu_env,
                        pkg_name,
                        meth_recv_name)
                    
                    # it could an ambig name
                    if resolved_node != None:
                        name_node.decl = resolved_node
                        name_node.typ = resolved_node.find_child('Type').canon
                        name_node.canon = node.typ

                    # it could be a static type
                    elif canon_type != None:
                        name_node.canon = canon_type
                    else:
                        logging.error('method receiver %s could not be resolved!' %
                            (meth_recv_name))
                        sys.exit(42)

                    # iteratively resolve the method receiver's identifier --
                    # used during codegen
                    iteratively_name_link_nodes(type_index, cu_env, pkg_name,
                        local_vars, meth_recv.leafs(), disallowed_simple_names)

                else:
                    # resolve some more!
                    find_and_resolve_names(type_index, cu_env, pkg_name,
                        meth_recv,
                        local_vars,
                        disallowed_simple_names)
                
            # if it has arguments, name resolve those
            if len(node.children) == 3:
                find_and_resolve_names(type_index, cu_env, pkg_name, node[2],
                    local_vars,
                    disallowed_simple_names)
            continue

        elif node == Node('ArrayAccess'):
            # node.children = ['ArrayReceiver', 'Primary']
            find_and_resolve_names(type_index, cu_env, pkg_name, node[0],
                local_vars,
                {})

            find_and_resolve_names(type_index, cu_env, pkg_name, node[1],
                local_vars,
                disallowed_simple_names)

            continue

        elif node == Node('FieldAccess'):
            # this?
            # node.children = ['FieldName', 'FieldReceiver']
            if node[1][0] == Node('This'):
                name = ['this'] + node[0].leaf_values()
                name_nodes = [node[1][0]] + node[0].leafs()
            else:
                find_and_resolve_names(type_index, cu_env, pkg_name,
                    node[1],
                    local_vars,
                    disallowed_simple_names)

                continue

        elif node == Node('Assignment'):

            find_and_resolve_names(type_index, cu_env, pkg_name,
                ASTNode(children=[node[0]]),
                local_vars)

            find_and_resolve_names(type_index, cu_env, pkg_name,
                ASTNode(children=[node[1]]),
                local_vars,
                disallowed_simple_names)

            continue

        elif node == Node('Name'):
            name = node.leaf_values()
            name_nodes = node.leafs()
       
        resolved_node = name_link_name(type_index, cu_env, pkg_name,
            local_vars,
            name,
            disallowed_simple_names)

        if resolved_node == None:
            logging.error('Could not resolve name %s in %s.%s with %s' % (name, pkg_name,
                cu_env['ClassDeclaration'], local_vars))
            sys.exit(42)

        # now lets label each part of this ambiguous name
        iteratively_name_link_nodes(type_index, cu_env, pkg_name, local_vars,
            name_nodes, disallowed_simple_names)

        node.decl = resolved_node
        node.typ = resolved_node.find_child('Type').canon