コード例 #1
0
 def generate_generic_code(self, ast: SPLFile, env: Env):
     Logger.info(
         '-------------------------------------------------------------')
     Logger.info(
         '----------------- Starting code generation ------------------')
     Logger.info(
         '-------------------------------------------------------------')
     Logger.info('* Starting generation of intermediate code')
     generic_functions_code = GenericGenerator(ast, env,
                                               self.builtins).generate()
     Logger.info('- Generation of intermediate code DONE')
     return generic_functions_code
コード例 #2
0
 def generate_x64_code(self, generic_functions_code: List, out_path: str):
     Logger.info('* Starting generation of x86_64 code')
     gen = X64Generator(generic_functions_code)
     gen.generate_x64_instructions()
     Logger.info('- Generation of x86_64 code DONE')
     Logger.info(f'* Writing x86_64 code to file {out_path}.asm')
     gen.write_to_file(out_path + '.asm')
     Logger.info('* Assembling and linking x86_64 code')
     gen.assemble_and_link(out_path + '.asm', out_path)
コード例 #3
0
 def generate_ssm_code(self, generic_functions_code: List, out_path: str):
     Logger.info('* Starting generation of SSM code')
     ssm_generator = SSMGenerator(generic_functions_code)
     ssm_generator.generate()
     Logger.info('- Generation of SSM code DONE')
     Logger.info(f'* Writing SSM code to file: {out_path}.ssm')
     ssm_generator.to_file(out_path + '.ssm')
コード例 #4
0
 def assemble_and_link(self, file_path: str, out_path: str):
     object_path = out_path + '.o'
     cp = subprocess.run([
         'nasm',
         '-g',  # Include debug info
         '-f macho64',  # Macho-O file format
         '-o',
         object_path,
         file_path,
     ])
     if cp.returncode == 0:
         cp = subprocess.run([
             'ld',
             '/usr/lib/libSystem.dylib',  # Include C library
             object_path,  # object file
             '-o',
             out_path
         ])
         if cp.returncode == 0:
             Logger.info(f'Input file {file_path} assembled and linked to {out_path}')
         else:
             Logger.error('Error: linker returned non-zero status code')
     else:
         Logger.error('Error: assembler returned non-zero status code')
コード例 #5
0
    def analysis(self, ast: SPLFile):
        Logger.info(
            '-------------------------------------------------------------')
        Logger.info(
            '------------------ Starting analysis phase ------------------')
        Logger.info(
            '-------------------------------------------------------------')

        Logger.info('* Starting return value checking')
        rvc = ReturnValueChecker()
        return_warnings, return_errors = rvc.check_spl_file(ast)
        Logger.info('- Return value checking DONE')
        if len(return_warnings) > 0:
            for w in return_warnings:
                Logger.warning(w)
        if len(return_errors) > 0:
            for e in return_errors:
                Logger.error(e)
            sys.exit(1)
        context = Context()
        for b in self.builtins:
            b.add_to_context(context)
        Logger.info(
            f'- Added {len(self.builtins)} builtin functions to binding context: {self.get_builtin_str()}'
        )

        binding_feedback = {'errors': [], 'warnings': []}
        Logger.info('* Starting binding analysis')
        ast.binding_analysis(context, binding_feedback)
        Logger.info('- Binding analysis DONE')

        Logger.info(
            '*** Pretty printing AST with identifier IDs after binding analysis: ***'
        )
        Logger.info('\n' + ast.indented_print())

        if len(binding_feedback['warnings']) > 0:
            for w in binding_feedback['warnings']:
                Logger.warning(w)
        if len(binding_feedback['errors']) > 0:
            for e in binding_feedback['errors']:
                Logger.error(e)
            sys.exit(1)

        env = Env()
        for b in self.builtins:
            b.add_to_env(env)
        Logger.info(
            f'- Added {len(self.builtins)} builtin functions to type environment: {self.get_builtin_str()}'
        )
        subst = Subst.empty()
        Logger.info('* Starting type inference')
        try:
            subst = ast.infer_type(env, InferenceVoid())
        except Exception as e:
            Logger.error(str(e))
            # raise e
            sys.exit(1)
        env.substitute(subst)

        Logger.debug('* Inferred function types after inference:')
        for name, f in env.functions.items():
            Logger.debug(
                f'- {name} :: args: [{", ".join(str(a) for a in f.usage.arg_types)}], ret: {str(f.usage.return_type)}'
            )
        Logger.debug('* Inferred variable types after inference:')
        for num, v in env.variables.items():
            Logger.debug(f'- {num} :: {str(v)}')

        Logger.info('- Typing DONE')
        return env
コード例 #6
0
    def parse_input(self, path: str):
        f = open(path, 'r')
        InputHandler.set_input_text(f.read())
        Logger.info(
            '-------------------------------------------------------------')
        Logger.info(
            '------------------- Starting parsing phase ------------------')
        Logger.info(
            '-------------------------------------------------------------')
        lexer = Lexer()
        Logger.info('* Starting lexing')
        tokens = lexer.lex_input()
        Logger.info('- Lexing DONE')

        Logger.debug('*** Printing lexed tokens: ***')
        for i, t in enumerate(tokens):
            Logger.debug('{token_type}::{value}'.format(
                token_type=t.token_type, value=t.value))
        if len(lexer.lex_errors) > 0:
            for e in lexer.lex_errors:
                Logger.error(e)
            sys.exit(1)

        tr = TokenReader(tokens)
        parser = Parser(tr)
        Logger.info('* Starting parsing')
        ast = parser.parse_spl()
        Logger.info('- Parsing DONE')
        Logger.info('*** Pretty printing AST: ***')
        Logger.info('\n' + ast.indented_print())

        if len(parser.errors) > 0:
            for e in parser.errors:
                Logger.error(e)
            sys.exit(1)
        return ast