def run(args): if args.input_file: with open(args.input_file, "r") as input_file: source = input_file.read() else: import sys source = sys.stdin.read() if args.assemble: with open(args.output, "w") as binout: write_binary(parse_instructions(source), binout) else: tree = parse(preprocess(source)) if args.print_ast: print_tree(tree) if not tree: return instructions = link(*translate(tree)) if args.print_assembly: print_instructions(instructions) with open(args.output, "w") as binout: write_binary(instructions, binout)
def run(args): if args.input_file: with open(args.input_file, 'r') as input_file: source = input_file.read() else: import sys source = sys.stdin.read() if args.assemble: with open(args.output, 'w') as binout: write_binary(parse_instructions(source), binout) else: tree = parse(preprocess(source)) if args.print_ast: print_tree(tree) if not tree: return instructions = link(*translate(tree)) if args.print_assembly: print_instructions(instructions) with open(args.output, 'w') as binout: write_binary(instructions, binout)
def translate_statement(ftree, glob, funcs): ''' TODO: BREAK GOTO ''' # Assignment if ftree[0] == '=': rhs = translate_statement(ftree[2], glob, funcs) return rhs + [('store', ftree[1])] # Variable access if ftree[1] == 'var': return [('load', ftree)] # Call stack-related if ftree[0] == 'call': # Calls to asm() skip translation and go straight to instruction parser. if ftree[1][0] == 'asm': return parse_instructions(ftree[2][0][0]) func = funcs[ftree[1][0]] if len(func.args) != len(ftree[2]): raise Exception('Not enough arguments to function "%s"' % ftree[1][0]) arg_evals = [] for arg in ftree[2]: arg_evals.extend(translate_statement(arg, glob, funcs)) funcpair = (ftree[1][0], 'func') return arg_evals + [('ldconst', funcpair), ('call', funcpair)] if ftree[0] == 'return': if ftree[1]: return translate_statement(ftree[1], glob, funcs) + [('return',)] else: return [('return',)] # Unary operators if ftree[0] == '++': return translate_unop_expression('incr', ftree, glob, funcs) if ftree[0] == '--': return translate_unop_expression('decr', ftree, glob, funcs) if ftree[0] == '~': return translate_unop_expression('not', ftree, glob, funcs) if ftree[0] == '!': return translate_unop_expression('bnot', ftree, glob, funcs) # Binary operators if ftree[0] == '*' and len(ftree) == 3: return translate_binop_expression('mul', ftree, glob, funcs) if ftree[0] == '+': return translate_binop_expression('add', ftree, glob, funcs) if ftree[0] == '-': return translate_binop_expression('sub', ftree, glob, funcs) if ftree[0] == '/': return translate_binop_expression('div', ftree, glob, funcs) if ftree[0] == '%': return translate_binop_expression('mod', ftree, glob, funcs) if ftree[0] == '&' and len(ftree[0]) == 3: return translate_binop_expression('and', ftree, glob, funcs) if ftree[0] == '|': return translate_binop_expression('or', ftree, glob, funcs) if ftree[0] == '^': return translate_binop_expression('xor', ftree, glob, funcs) if ftree[0] == '<<': return translate_binop_expression('lsh', ftree, glob, funcs) if ftree[0] == '>>': return translate_binop_expression('rsh', ftree, glob, funcs) if ftree[0] == '&&': return translate_binop_expression('band', ftree, glob, funcs) if ftree[0] == '||': return translate_binop_expression('bor', ftree, glob, funcs) # Comparison operators if ftree[0] == '==': return translate_binop_expression('eq', ftree, glob, funcs) if ftree[0] == '>=': return translate_binop_expression('geq', ftree, glob, funcs) if ftree[0] == '<=': return translate_binop_expression('leq', ftree, glob, funcs) if ftree[0] == '>': return translate_binop_expression('gt', ftree, glob, funcs) if ftree[0] == '<': return translate_binop_expression('lt', ftree, glob, funcs) if ftree[0] == '!=': return translate_binop_expression('neq', ftree, glob, funcs) # Assignment operators if ftree[0] == '+=': return translate_assign_expression('add', ftree, glob, funcs) if ftree[0] == '-=': return translate_assign_expression('sub', ftree, glob, funcs) if ftree[0] == '*=': return translate_assign_expression('mul', ftree, glob, funcs) if ftree[0] == '/=': return translate_assign_expression('div', ftree, glob, funcs) if ftree[0] == '%=': return translate_assign_expression('mod', ftree, glob, funcs) if ftree[0] == '&=': return translate_assign_expression('and', ftree, glob, funcs) if ftree[0] == '|=': return translate_assign_expression('or', ftree, glob, funcs) if ftree[0] == '^=': return translate_assign_expression('xor', ftree, glob, funcs) if ftree[0] == '>>=': return translate_assign_expression('rsh', ftree, glob, funcs) if ftree[0] == '<<=': return translate_assign_expression('lsh', ftree, glob, funcs) # Dereferencing if ftree[0] == '->': pass if ftree[0] == '.': pass if ftree[0] == '&': return [('addr', ftree[1])] if ftree[0] == '*': return ( translate_statement(ftree[1], glob, funcs) + [('load', ('result', 'reg'))]) # Conditionals if ftree[0] == 'if': code_true, ignore = translate_compound(ftree[2], glob, funcs) code_false, ignore = translate_compound(ftree[3], glob, funcs) return ( translate_statement(ftree[1], glob, funcs) + # Conditional Offset Zero JuMP -- # relative jump if result register == 0 [('ozjmp', len(code_true) + 2)] + code_true + [('ojmp', len(code_false))] + code_false) if ftree[0] == '?': code_true = translate_statement(ftree[2], glob, funcs) code_false = translate_statement(ftree[3], glob, funcs) return ( translate_statement(ftree[1], glob, funcs) + # Conditional Offset Zero JuMP -- # relative jump if result register == 0 [('ozjmp', len(code_true) + 2)] + code_true + [('ojmp', len(code_false))] + code_false + [('nop',)]) if ftree[0] == 'while': condition = translate_statement(ftree[1], glob, funcs) code_true, ignore = translate_compound(ftree[2], glob, funcs) return ( condition + [('ozjmp', len(code_true) + 2)] + code_true + [('ojmp', -len(code_true) - len(condition) - 1), ('nop',)]) if ftree[0] == 'do': condition = translate_statement(ftree[1], glob, funcs) code_true, ignore = translate_compound(ftree[2], glob, funcs) return ( code_true + condition + [('ozjmp', 2), ('ojmp', -len(code_true) - len(condition) - 1), ('nop',)]) if ftree[0] == 'for': body, ignore = translate_compound(ftree[4], glob, funcs) condition = translate_statement(ftree[2], glob, funcs) update = [] if ftree[3]: update = translate_statement(ftree[3], glob, funcs) return ( translate_statement(ftree[1], glob, funcs) + condition + [('ozjmp', len(body) + len(update) + 2)] + body + update + [('ojmp', -len(body) - len(update) - len(condition) - 1), ('nop',)]) # Numeric constant if ('i' in ftree[1] or 'l' in ftree[1] or 'f' in ftree[1] or 'd' in ftree[1] or 'c' in ftree[1]): return [('ldconst', ftree[0])] print('Warning: statement tree %s could not be translated.' % (ftree,)) return []