Beispiel #1
0
def g_forloop_iter(n): 
    # 0: identifier; 1: list; 2: suite
    det_type(n[1], file_name)
    iterable = n[1].type

    # Determine the type of the iterative variable based on the container 
    # it's iterating over
    if basetype(iterable) in (builtins["StringType"], builtins["FileType"]):
        id_type = builtins["string"]

    elif basetype(iterable) in containertypes:
          id_type = iterable.elem_type[0]
  
    else:
         # recovering from a type error
         # a type error will be thrown during type checking
         id_type = iterable


    # Add the iterative variable to the loop's environment 
    if (n[2].label == "SUITE_BLOCK"):
         # 0: docstring; 1: block
         n[2][1].initiate_var(n[0], id_type)
 
    if (n[2].label == "SUITE_INLINE"):
         # 0: simple statement
         n[2].initiate_var(n[0], id_type)
Beispiel #2
0
def g_declaration(n):
    # 0: identifier; 1: type
    det_type(n[1], file_name)
    try:
        n.initiate_var(n[0], n[1].type)
    except DeclarationException:
        type_error("The variable '" + n[0] +"' has already been defined in " +
                   "the current scope.\nOnly functions and procedures can " +
                   "have multiple definitions.", file_name, n)
Beispiel #3
0
def g_argumentlist(n):
    # 0: identifier; 1: type
    det_type(n[1], file_name)
    identifier = n[0]
    t = n[1].type

    # Locate the function or procedure node
    while (n.label != "FUNCTION_DEFINITION" and \
               n.label != "PROCEDURE_DEFINITION" and \
               n.label != "LITERAL_FUNCTION" and \
               n.label != "LITERAL_PROCEDURE"):
        n = n.parent

    # Function or procedure literal - lambda expression
    if n.label == "LITERAL_FUNCTION" or n.label == "LITERAL_PROCEDURE":
        try:
            n.initiate_var(identifier, t)
        except DeclarationException:
            type_error(
                "'" + n[0] + "' has already been declared in the " +
                "current scope, and is not a function or procedure.\n" +
                "Only function and procedure definitions are allowed to " +
                " have more than one value.", file_name, n)

    else:
        # Function or procedure defintion
        # Child node with an environment = n[3] if function, n[2] if procedure
        n = n[3] if (len(n.children) == 4) else n[2]
        if (n.label == "SUITE_BLOCK"):
            try:
                n[1].initiate_var(identifier, t)
            except DeclarationException:
                type_error(
                    "'" + n[0] + "' has already been declared in the "
                    " current scope, and is not a function or " +
                    "procedure.\nOnly function and procedure " +
                    " definitions are allowed to have more than one " +
                    "value.", file_name, n)
        if (n.label == "SUITE_INLINE"):
            try:
                n.initiate_var(identifier, t)
            except DeclarationException:
                type_error(
                    "'" + n[0] + "' has already been declared in the "
                    " current scope, and is not a function or " +
                    "procedure.\nOnly function and procedure " +
                    " definitions are allowed to have more than one " +
                    "value.", file_name, n)
Beispiel #4
0
def g_procedure_definition(n):
    # 0: identifier; 1: argument list; 2: suite
    det_type(n[1], file_name)
    sig = n[1].type

    try:
        n.parent.initiate_var(n[0],type_obj("proc",builtins["proc"], sig = sig))

    except SignatureException:
        # Function overloading - duplicate signature
        type_error("The procedure '" + n[0] + "' with the signature '" +
                   repr(sig) + "' has already been defined.", file_name, n[1])

    except DeclarationException:
        type_error("'" + n[0] + "' has already been declared in the current" + 
                   "scope, and is not a function or procedure.\n" +
                   "Only function and procedure definitions are allowed to " + 
                   " have more than one value.", file_name, n)
Beispiel #5
0
def importgenerate(cspyfile, _imports=[]):

    _imports.append(cspyfile)

    # LEX AND PARSE THE FILE
    filename = cspyfile
    if not os.path.isfile(filename):
        print >> sys.stderr, cspyfile + " could not be found. Did you mean" +\
            " to use pyimport instead of import?"
        exit(1)

    cspy_file_match = re.match(r"(?P<path>.*)/[^/]+\.cspy", filename)
    if cspy_file_match:
        # path found - not being run in current directory
        cspy_file_path = cspy_file_match.group("path")
    else:
        cspy_file_path = ""

    cspyfile = open(cspyfile, 'rU').read() + "\n"
    
    lexer = lex.lex()
    lexer.indentwith = None
    lexer.indentedline = None
    lexer.indentstack = [0]    
    lexer.input(cspyfile)

    parser = yacc.yacc()
    lexer.parser = parser
    parsetree = parser.parse(tracking = True) 
    if parsetree:
        parsetree.set_column_num(cspyfile)
    else:
        print >> sys.stderr, 'Should something have been printed? cspy_master.py'
        remove_files()
        exit(1)


    # GET IMPORTED FILES
    imports = parsetree.flatten("IMPORTBLOCK_SINGLE")

    name = filename[:len(filename) - 5]

    tmp_path = "/tmp/" + getpass.getuser()

    try:
        os.stat(tmp_path)
    except:
        os.mkdir(tmp_path)

    # NO FILES IMPORTED
    if not imports:

        # SAVE FILE NAME
        F = open(tmp_path + "/__import_names.txt", "a")         # see documentation
        F.write(name + "\n")
        F.close()
        
        # PROCESS SELF
        generate_environments(parsetree, filename)            # add environments
        det_type(parsetree, file_name=filename)                # type check
        overloads = translate(parsetree, filename, cspy_file_path) # translate to Python

        return parsetree, _imports, overloads

    # FILES IMPORTED
    else:
        for statement in imports:
            
            # SAVE FILE NAME
            F = open(tmp_path + "/__import_names.txt", "a")     # see documentation
            F.write(name + "\n")
            F.close()

            # PROCESS IMPORTS
            statement = statement[0]
            importtype = statement.label

            # ADD IMPORTED CODE TO PARSE TREE

            # import simple : import module
            if importtype == "IMPORT_SIMPLE":
                importfile = statement[0] + ".cspy"
                importtree, _imports, import_overloads \
                    = importgenerate(path + importfile,
                                     _imports)
                importmodule = type_obj("import module",
                                        builtins["ImportModule"], 
                                    methods = importtree.env)
                import_overloads = {'global' : {},
                                    statement[0] : import_overloads}
                parsetree.initiate_var(statement[0], importmodule)

            # import alias : import module as id
            elif importtype == "IMPORT_ALIAS":
                importfile = statement[0] + ".cspy"
                importtree, _imports, import_overloads \
                    = importgenerate(path + importfile,
                                     _imports)
                alias =  statement[1]
                importmodule = type_obj("import module",
                                        builtins["ImportModule"], 
                                        methods = importtree.env)
                import_overloads = {'global' : {},
                                    alias : import_overloads}
                parsetree.initiate_var(alias, importmodule)

            # import bulk : from module import * 
            elif importtype == "IMPORT_BULK":
                importfile = statement[0] + ".cspy"
                importtree, _imports, import_overloads \
                    = importgenerate(path + importfile,
                                     _imports)
                for variable in importtree.env:
                    parsetree.initiate_var(variable, importtree.env[variable])

            # import discrete : from module import id1, id2, ...
            elif importtype == "IMPORT_DISCRETE":
                importfile = statement[0] + ".cspy"
                importtree, _imports, import_overloads \
                    = importgenerate(path + importfile,
                                     _imports)
                importids = statement.flatten("IMPORTLIST_SIMPLE")
                for identifier in importids:
                    name = identifier[0]
                    value = importtree.lookup_var(name)
                    parsetree.initiate_var(name, value)

                # copy over overloaded names from imports
                tmp = {'global' : {}}

                for name in import_overloads['global']:
                    # copy over the global functions and procedures
                    if import_overloads['global'][name] in importids:
                        tmp['global'][name] = import_overloads['global'][name]
                
                # copy over the imported classes
                for class_name in import_overloads:
                    if class_name in importids:
                        tmp[class_name] = import_overloads[class_name]
                        
                import_overloads = tmp

            #--------------------------------#
            # PYIMPORT - imports from python #
            #--------------------------------#

            # pyimport simple : pyimport module
            elif importtype == "PYIMPORT_SIMPLE":
                importfile = statement[0] + ".cspyh"
                importtree = pyimportgenerate(importfile,
                                              path)
                importmodule = type_obj("import module", 
                                        builtins["ImportModule"],
                                        methods = importtree.env)
                parsetree.initiate_py_var(statement[0], importmodule)
                import_overloads = {'global' : {}}

            # pyimport alias : pyimport module as id
            elif importtype == "PYIMPORT_ALIAS":
                importfile = statement[0] + ".cspyh"
                importtree = pyimportgenerate(importfile, 
                                              path)
                alias = statement[1]
                importmodule = type_obj("import module",
                                        builtins["ImportModule"],
                                        methods = importtree.env)
                parsetree.initiate_py_var(alias, importmodule)
                import_overloads = {'global' : {}}

            # pyimport bulk : from module pyimport *
            elif importtype == "PYIMPORT_BULK":
                importfile = statement[0] + ".cspyh"
                importtree = pyimportgenerate(importfile,
                                                         path)
                for variable in importtree.env:
                    parsetree.initiate_py_var(variable, importtree.env[variable])
                import_overloads = {'global' : {}}
            
            # pyimport discrete : from module pyimport id1, id2, ...
            elif importtype == "PYIMPORT_DISCRETE":
                importfile = statement[0] + ".cspyh"
                importtree = pyimportgenerate(importfile,
                                              path)
                importids = statement.flatten("IMPORTLIST_SIMPLE")
                for identifier in importids:
                    name = identifier[0]
                    value = importtree.lookup_var(name)
                    parsetree.initiate_py_var(name, value)

                import_overloads = {'global' : {}}

            else:
                # Should never reach this point
                print >> sys.stderr, "\nCompiler error with imports in " + \
                    "cspy_master.py.\n" + \
                    "No import type matched"
                sys.exit(1)
            
        # PROCESS SELF
        generate_environments(parsetree, filename)        # add environments
        det_type(parsetree, file_name=filename)                     # type check
        overloads = translate(parsetree, 
                              filename,
                              cspy_file_path,
                              import_overloads)          # translate to Python
        
        return parsetree, _imports, overloads
Beispiel #6
0
def g_class_definition(n):
    # 0: identifier; 1: super class; 2: suite

    # Class extension
    if (n[1].label == "EMPTY"):
        sup = builtins["object"]
        n[1].label = "TYPE"
        n[1].children.append("object")
    else:
        det_type(n[1], file_name)
        sup = n[1].type

    # Temporarily initialize the class in the global environment
    # without any methods.  This allows methods in the class to 
    # have local variables whose type is the class
    try:
        n.parent.initiate_var(n[0], type_obj(n[0], builtins["type"], sup = sup))

    except DeclarationException:
        type_error("'" + n[0] + "' has already been declared in the current" + 
                   "scope, and is not a function or procedure.\n" +
                   "Only function and procedure definitions are allowed to " + 
                   " have more than one value.", file_name, n)


    # Get the class attributes  
    det_type(n[2][1][0], file_name)
    attributes = n[2][1][0] 
    if (attributes.label == "EMPTY"): 
        # Empty variable declaration block - no class attributes
        attribute_nodes = []

    else:
        # Nonempty variable declartion block - has class attributes
        attribute_nodes = attributes.flatten("DECLARATION_SIMPLE") + \
                          attributes.flatten("DECLARATION_INITIALIZE") 


    # Add the attributes to the method dictionary
    methods = {}
    for a in attribute_nodes:
        methods[a[0]] = a[1].type 


    # Get the class methods
    method_nodes = n[2].flatten("PROCEDURE_DEFINITION") + \
                   n[2].flatten("FUNCTION_DEFINITION")

    # Add each method to the method dictionary
    for m in method_nodes:
        name = m[0]
        det_type(m[1], file_name)
        sig = m[1].type
        if m.label == "PROCEDURE_DEFINITION":
            # procedure overloading
            if name in methods.keys():
                if (isinstance(methods[name], list)):
                    # Add the new procedure signature to the class
                    methods[name].append(type_obj("proc", builtins["proc"], sig = sig))

                # First overload
                else:
                    methods[name] = [methods[name], type_obj("proc", builtins["proc"], sig = sig)]
            # Undeclared variable - add it to the class
            else:
                methods[name] = type_obj("proc", builtins["proc"], sig = sig)
        else:
            det_type(m[2], file_name)
            sig.return_type = m[2].type
            # function overloading
            if name in methods.keys():
                if (isinstance(methods[name], list)):
                    # Add the new function signature to the class
                    methods[name].append(type_obj("fn", builtins["fn"], sig = sig))

                # First overload
                else:
                    methods[name] = [methods[name], type_obj("fn", builtins["fn"], sig = sig)]
            # Undeclared variable - add it to the class
            else:
                methods[name] = type_obj("fn", builtins["fn"], sig = sig)

    # Locate the global environment and update the class method dictionary
    current = n
    while current.parent:
        current = current.parent

    current.env[n[0]].methods = methods