def create_write(mod,ln=False): """ Creates a stub of println """ if ln: fname = "writeln" else: fname = "write" printf = mod.get_function_named("printf") string_pointer = Type.pointer(types.int8, 0) f = mod.add_function( types.function(types.void, (string_pointer,) ) , fname) bb = f.append_basic_block("entry") builder = Builder.new(bb) builder.call(printf, ( f.args[0], )) if ln: builder.call(printf, ( pointer(builder, c_string(mod,"\n")), )) builder.ret_void() return f
def add_stdio(mod): """ Adds stdio functions to a module """ return { "printf": mod.add_function(types.function(types.void, (Type.pointer(types.int8, 0),), 1), "printf"), "writeln": create_write(mod,ln=True), "write": create_write(mod), "writeint": create_write_alt('integer', mod) }
def add_stdio(mod): """ Adds stdio functions to a module """ return { "printf": mod.add_function(types.function(types.void, (Type.pointer(types.int8, 0),), 1), "printf"), "writeln": create_write(mod,ln=True), "write": create_write(mod), "writeint": create_write_alt('integer',mod), "writereal": create_write_alt('real',mod), "writelnint": create_write_alt('integer',mod,ln=True), "writelnreal": create_write_alt('real',mod,ln=True) }
def add_stdio(mod): """ Adds stdio functions to a module """ return { "printf": mod.add_function(types.function(types.void, (Type.pointer(types.int8, 0),), 1), "printf"), "println": create_print(mod,ln=True), "print": create_print(mod), "printint": create_print_alt('int',mod), "printreal": create_print_alt('real',mod), "printchar": create_print_alt('char',mod), "printbool": create_print_alt('bool',mod), "printlnint": create_print_alt('int',mod,ln=True), "printlnreal": create_print_alt('real',mod,ln=True), "printlnchar": create_print_alt('char',mod,ln=True), "printlnbool": create_print_alt('bool',mod,ln=True) }
def __call__(self,ast): if ast.__class__ != Node: return ast if ast.type == "program": mod_name = self.descend(ast.args[0]) if not mod_name: mod_name = "pascal_program" self.module = Module.new(mod_name) stdio = add_stdio(self.module) for f in stdio: self.functions[f] = stdio[f] main = create_main(self.module) block = Builder.new(main.append_basic_block("entry")) self.contexts.append(Context(main,block)) self.descend(ast.args[1]) self.get_builder().ret(c_int(0)) return self.module elif ast.type == "block": self.descend(ast.args[0]) # Var self.descend(ast.args[1]) # Function def self.descend(ast.args[2]) # Statement elif ast.type in ["var_list","statement_list","function_list"]: for son in ast.args: self.descend(son) elif ast.type == "var": var_name = self.descend(ast.args[0]) var_type_name = self.descend(ast.args[1]) builder = self.get_builder() v = var_init(builder, var_name, var_type_name) self.set_var(var_name,v) elif ast.type == "type": return str(ast.args[0]).upper() elif ast.type == "identifier": return str(ast.args[0]).lower() elif ast.type in ["function_call","function_call_inline"]: builder = self.get_builder() function_name = self.descend(ast.args[0]) arguments = [] if len(ast.args) > 1: if ast.args[1]: arguments = self.descend(ast.args[1]) if function_name in ['write','writeln']: if str(arguments[0].type) == 'double': function_name += "real" elif str(arguments[0].type) == 'i32': function_name += "int" function = self.module.get_function_named(function_name) return builder.call(function,arguments) elif ast.type == "parameter_list": l = [] l.extend(self.descend(ast.args[0])) l.extend(self.descend(ast.args[1])) return l elif ast.type == "parameter": c = ast.args[0] if c.type == "identifier": label = self.descend(ast.args[0]) c = self.get_var(label) else: c = self.descend(ast.args[0]) return [c] elif ast.type == "assign": builder = self.get_builder() varName = self.descend(ast.args[0]) value = self.descend(ast.args[1]) ref = self.get_var(varName) builder.store(value, ref) return varName elif ast.type in ['procedure','function']: def get_params(node): """ Return a list of tuples of params """ if node.type == 'parameter': return [(self.descend(node.args[0]), types.translation[self.descend(node.args[1])])] else: l = [] for p in node.args: l.extend(get_params(p)) return l head = ast.args[0] if head.type == 'procedure_head': return_type = types.void else: return_type = types.translation[self.descend(head.args[-1])] name = self.descend(head.args[0]) if len(head.args) > 1: params = get_params(head.args[1]) else: params = [] code = ast.args[1] ftype = types.function(return_type,[ i[1] for i in params ]) f = Function.new(self.module, ftype, name) fb = Builder.new(f.append_basic_block("entry")) self.contexts.append(Context( f,fb )) b = self.get_builder() for i,p in enumerate(params): x = f.args[i]; x.name = p[0] self.set_param(p[0],x) if ast.type == 'function': type_name = types.reverse_translation[return_type] v = var_init(b, name, type_name) self.set_var(name,v) self.descend(code) b = self.get_builder() if ast.type == 'procedure': b.ret_void() else: b.ret(b.load(self.get_var(name))) self.contexts.pop() elif ast.type == "while": self.counter += 1 now = self.get_function() builder = self.get_builder() loop = now.append_basic_block("loop_%d" % self.counter) body = now.append_basic_block("body_%d" % self.counter) tail = now.append_basic_block("tail_%d" % self.counter) # do while code self.contexts.append(Context(loop)) b = self.get_builder() cond = self.descend(ast.args[0]) b.cbranch(cond,body,tail) self.contexts.pop() self.contexts.append(Context(body)) b = self.get_builder() self.descend(ast.args[1]) # repeat b.branch(loop) self.contexts.pop() # start loop builder.branch(loop) self.contexts[-1].builder = Builder.new(tail) elif ast.type == "repeat": cond = Node('not',ast.args[1]) body = ast.args[0] while_b = Node('while',cond,body) final = Node('statement_list',body,while_b) return self.descend(final) elif ast.type == "for": direction = self.descend(ast.args[1]) limit = ast.args[2] builder = self.get_builder() # var declaration varname = self.descend(ast.args[0].args[0]) vartype = "INTEGER" v = var_init(builder, varname, vartype) self.set_var(varname,v) # var init variable = self.descend(ast.args[0]) # cond var1 = Node('element',Node('identifier',varname)) var1_name = Node('identifier',varname) sign = Node('sign',(direction == "to") and '<=' or '>=') comp = Node('op',sign,var1,limit) # body op = Node('sign',(direction == "to") and '+' or '-') varvalue = Node('op',op,var1,Node('element',Node('integer',1))) increment = Node('assign',var1_name,varvalue) body = Node('statement_list',ast.args[3],increment) # do while while_block = Node('while',comp,body) self.descend(while_block) elif ast.type == "if": now = self.get_function() builder = self.get_builder() #if cond = self.descend(ast.args[0]) # the rest self.counter += 1 tail = now.append_basic_block("tail_%d" % self.counter) # then then_block = now.append_basic_block("if_%d" % self.counter) self.contexts.append( Context(then_block) ) self.descend(ast.args[1]) b = self.get_builder() b.branch(tail) b.position_at_end(tail) self.contexts.pop() # else else_block = now.append_basic_block("else_%d" % self.counter) self.contexts.append( Context(else_block) ) if len(ast.args) > 2: self.descend(ast.args[2]) b = self.get_builder() b.branch(tail) b.position_at_end(tail) self.contexts.pop() builder.cbranch(cond,then_block,else_block) self.contexts[-1].builder = Builder.new(tail) elif ast.type in ["sign","and_or"]: return ast.args[0] elif ast.type == 'not': v = self.descend(ast.args[0]) builder = self.get_builder() return builder.not_(v) elif ast.type == "op": sign = self.descend(ast.args[0]) v1 = self.descend(ast.args[1]) v2 = self.descend(ast.args[2]) builder = self.get_builder() if sign == "+": return builder.add(v1, v2) elif sign == "-": return builder.sub(v1, v2) elif sign == "*": return builder.mul(v1, v2) elif sign == "/": return builder.fdiv(v1, v2) elif sign == "div": return builder.sdiv(v1, v2) elif sign == "mod": return builder.urem(v1, v2) elif sign in [">",">=","=","<=","<","<>"]: return compare(sign,v1,v2,builder) elif sign == "and": return builder.and_(v1,v2) elif sign == "or": return builder.or_(v1,v2) else: print sign elif ast.type == "element": builder = self.get_builder() e = ast.args[0] if e.type == "identifier": ref = self.get_var(self.descend(e)) if ref.__class__ == Argument: return ref return builder.load(ref) else: return self.descend(ast.args[0]) elif ast.type == "string": b = self.get_builder() s = c_string(self.module,ast.args[0]) return pointer(b,s) elif ast.type == "integer": return c_int(int(ast.args[0])) elif ast.type == "real": return c_real(float(ast.args[0])) else: print "unknown:", ast.type sys.exit()
def __call__(self, ast): if ast.__class__ != Node: return ast if ast.type == "program": mod_name = self.descend(ast.args[0]) if not mod_name: mod_name = "pascal_program" self.module = Module.new(mod_name) stdio = add_stdio(self.module) for f in stdio: self.functions[f] = stdio[f] main = create_main(self.module) block = Builder.new(main.append_basic_block("entry")) self.contexts.append(Context(main, block)) self.descend(ast.args[1]) self.get_builder().ret(c_int(0)) return self.module elif ast.type == "block": self.descend(ast.args[0]) # Var self.descend(ast.args[1]) # Function def self.descend(ast.args[2]) # Statement elif ast.type in ["var_list", "statement_list", "function_list"]: for son in ast.args: self.descend(son) elif ast.type == "var": var_name = self.descend(ast.args[0]) var_type_name = self.descend(ast.args[1]) builder = self.get_builder() v = var_init(builder, var_name, var_type_name) self.set_var(var_name, v) elif ast.type == "type": return str(ast.args[0]).upper() elif ast.type == "identifier": return str(ast.args[0]).lower() elif ast.type in ["function_call", "function_call_inline"]: builder = self.get_builder() function_name = self.descend(ast.args[0]) arguments = [] if len(ast.args) > 1: if ast.args[1]: arguments = self.descend(ast.args[1]) if function_name in ['write', 'writeln']: if str(arguments[0].type) == 'double': function_name += "real" elif str(arguments[0].type) == 'i32': function_name += "int" function = self.module.get_function_named(function_name) return builder.call(function, arguments) elif ast.type == "parameter_list": l = [] l.extend(self.descend(ast.args[0])) l.extend(self.descend(ast.args[1])) return l elif ast.type == "parameter": c = ast.args[0] if c.type == "identifier": label = self.descend(ast.args[0]) c = self.get_var(label) else: c = self.descend(ast.args[0]) return [c] elif ast.type == "assign": builder = self.get_builder() varName = self.descend(ast.args[0]) value = self.descend(ast.args[1]) ref = self.get_var(varName) builder.store(value, ref) return varName elif ast.type in ['procedure', 'function']: def get_params(node): """ Return a list of tuples of params """ if node.type == 'parameter': return [(self.descend(node.args[0]), types.translation[self.descend(node.args[1])])] else: l = [] for p in node.args: l.extend(get_params(p)) return l head = ast.args[0] if head.type == 'procedure_head': return_type = types.void else: return_type = types.translation[self.descend(head.args[-1])] name = self.descend(head.args[0]) if len(head.args) > 1: params = get_params(head.args[1]) else: params = [] code = ast.args[1] ftype = types.function(return_type, [i[1] for i in params]) f = Function.new(self.module, ftype, name) fb = Builder.new(f.append_basic_block("entry")) self.contexts.append(Context(f, fb)) b = self.get_builder() for i, p in enumerate(params): x = f.args[i] x.name = p[0] self.set_param(p[0], x) if ast.type == 'function': type_name = types.reverse_translation[return_type] v = var_init(b, name, type_name) self.set_var(name, v) self.descend(code) b = self.get_builder() if ast.type == 'procedure': b.ret_void() else: b.ret(b.load(self.get_var(name))) self.contexts.pop() elif ast.type == "while": self.counter += 1 now = self.get_function() builder = self.get_builder() loop = now.append_basic_block("loop_%d" % self.counter) body = now.append_basic_block("body_%d" % self.counter) tail = now.append_basic_block("tail_%d" % self.counter) # do while code self.contexts.append(Context(loop)) b = self.get_builder() cond = self.descend(ast.args[0]) b.cbranch(cond, body, tail) self.contexts.pop() self.contexts.append(Context(body)) b = self.get_builder() self.descend(ast.args[1]) # repeat b.branch(loop) self.contexts.pop() # start loop builder.branch(loop) self.contexts[-1].builder = Builder.new(tail) elif ast.type == "repeat": cond = Node('not', ast.args[1]) body = ast.args[0] while_b = Node('while', cond, body) final = Node('statement_list', body, while_b) return self.descend(final) elif ast.type == "for": direction = self.descend(ast.args[1]) limit = ast.args[2] builder = self.get_builder() # var declaration varname = self.descend(ast.args[0].args[0]) vartype = "INTEGER" v = var_init(builder, varname, vartype) self.set_var(varname, v) # var init variable = self.descend(ast.args[0]) # cond var1 = Node('element', Node('identifier', varname)) var1_name = Node('identifier', varname) sign = Node('sign', (direction == "to") and '<=' or '>=') comp = Node('op', sign, var1, limit) # body op = Node('sign', (direction == "to") and '+' or '-') varvalue = Node('op', op, var1, Node('element', Node('integer', 1))) increment = Node('assign', var1_name, varvalue) body = Node('statement_list', ast.args[3], increment) # do while while_block = Node('while', comp, body) self.descend(while_block) elif ast.type == "if": now = self.get_function() builder = self.get_builder() #if cond = self.descend(ast.args[0]) # the rest self.counter += 1 tail = now.append_basic_block("tail_%d" % self.counter) # then then_block = now.append_basic_block("if_%d" % self.counter) self.contexts.append(Context(then_block)) self.descend(ast.args[1]) b = self.get_builder() b.branch(tail) b.position_at_end(tail) self.contexts.pop() # else else_block = now.append_basic_block("else_%d" % self.counter) self.contexts.append(Context(else_block)) if len(ast.args) > 2: self.descend(ast.args[2]) b = self.get_builder() b.branch(tail) b.position_at_end(tail) self.contexts.pop() builder.cbranch(cond, then_block, else_block) self.contexts[-1].builder = Builder.new(tail) elif ast.type in ["sign", "and_or"]: return ast.args[0] elif ast.type == 'not': v = self.descend(ast.args[0]) builder = self.get_builder() return builder.not_(v) elif ast.type == "op": sign = self.descend(ast.args[0]) v1 = self.descend(ast.args[1]) v2 = self.descend(ast.args[2]) builder = self.get_builder() if sign == "+": return builder.add(v1, v2) elif sign == "-": return builder.sub(v1, v2) elif sign == "*": return builder.mul(v1, v2) elif sign == "/": return builder.fdiv(v1, v2) elif sign == "div": return builder.sdiv(v1, v2) elif sign == "mod": return builder.urem(v1, v2) elif sign in [">", ">=", "=", "<=", "<", "<>"]: return compare(sign, v1, v2, builder) elif sign == "and": return builder.and_(v1, v2) elif sign == "or": return builder.or_(v1, v2) else: print sign elif ast.type == "element": builder = self.get_builder() e = ast.args[0] if e.type == "identifier": ref = self.get_var(self.descend(e)) if ref.__class__ == Argument: return ref return builder.load(ref) else: return self.descend(ast.args[0]) elif ast.type == "string": b = self.get_builder() s = c_string(self.module, ast.args[0]) return pointer(b, s) elif ast.type == "integer": return c_int(int(ast.args[0])) elif ast.type == "real": return c_real(float(ast.args[0])) else: print "unknown:", ast.type sys.exit()
def __call__(self,ast): if ast.__class__ != Node: return ast if ast.type == "program": mod_name = "algol_program" self.module = Module.new(mod_name) stdio = add_stdio(self.module) for f in stdio: self.functions[f] = stdio[f] main = create_main(self.module) block = Builder.new(main.append_basic_block("entry")) self.contexts.append(Context(main,block)) self.descend(ast.args[0]) self.get_builder().ret(c_int(0)) return self.module elif ast.type in ["block", "statement", "array_list", "bound_pair_list", "switch_list", "formal_parameter_list", "for_list", "for_list_element", "subscript_list", "type_list","unlabeled_block","block_head", "compound_statement", "compound_tail", "declaration", "formal_parameter_part", "unconditional_statement", "basic_statement", "unlabelled_basic_statement", "boolean_expression"]: for son in ast.args: self.descend(son) elif ast.type in ["expression", "label"]: return self.descend( ast.args[0]) elif ast.type == "designational_expression": if len(ast.args) == 1: return self.descend( ast.args[0]) elif ast.type == "simple_designational_expression": return self.descend( ast.args[0]) elif ast.type == "actual_parameter_part": return self.descend(ast.args[0]) elif ast.type == "actual_parameter_list": builder = self.get_builder() if len(ast.args) == 1: var = self.descend(ast.args[0]) if isinstance(var, str): return [builder.load(self.get_var(var))] return [var] else: ls = list() ls.extend(self.descend(ast.args[0])) var = self.get_var( self.descend(ast.args[2]) ) ls.append(var) return ls elif ast.type == "actual_parameter": return self.descend(ast.args[0]) elif ast.type in ["function_designator", "procedure_statement"]: builder = self.get_builder() function_name = self.descend(ast.args[0]) arguments = list() if ast.args[1]: arguments = self.descend(ast.args[1]) function = self.module.get_function_named(function_name) return builder.call(function, arguments) elif ast.type == "boolean_expression": pass elif ast.type == "if_statement": return self.descend(ast.args[0].args[0]), self.descend(ast.args[1]) elif ast.type == "conditional_statement": #if if ast.args[0].type == 'if_clause': now = self.get_function() builder = self.get_builder() cond, statement = self.descend(ast.args[0]) self.counter += 1 tail = now.append_basic_block("tail_%d" % self.counter) # then then_block = now.append_basic_block("if_%d" % self.counter) self.contexts.append( Context(then_block) ) b = self.get_builder() b.branch(tail) b.position_at_end(tail) self.contexts.pop() #else else_block = None if len(ast.args) == 2 and ast.args[1].type == "statement": else_block = now.append_basic_block("else_%d" % self.counter) self.contexts.append( Context(else_block) ) self.descend(ast.args[1]) b = self.get_builder() b.branch(tail) b.position_at_end(tail) self.contexts.pop() builder.cbranch(cond,then_block,else_block) self.contexts[-1].builder = Builder.new(tail) elif ast.type == "left_part_list": if len(ast.args) == 1: return [self.descend( ast.args[0] )] else: ls = list() ls.extend( self.descend(ast.args[0]) ) ls.append( self.descend(ast.args[1]) ) elif ast.type == "left_part": return self.descend(ast.args[0]) elif ast.type == "variable": return self.get_var( self.descend(ast.args[0]) ) elif ast.type == "simple_variable": return self.descend(ast.args[0]) elif ast.type == "arithmetic_expression": if len(ast.args) == 1: return self.descend(ast.args[0]) elif ast.type == "simple_arithmetic_expression": if len(ast.args) == 1: return self.term(ast.args[0]) elif len(ast.args) == 2: builder = self.get_builder() if ast.args[0].args[0] == "+": return builder.add(c_int(0), self.term(ast.args[1])) else: return builder.sub(c_int(0), self.term(ast.args[1])) else: builder = self.get_builder() if ast.args[1].args[0] == "+": return builder.add(self.descend(ast.args[0]), self.term(ast.args[2])) else: return builder.sub(self.descend(ast.args[0]), self.term(ast.args[2])) #добавляем название переменных и их типы из type_declaration elif ast.type == "type_declaration": local_or_own_type = ast.args[0] if len(local_or_own_type.args) == 1: var_type = local_or_own_type.args[0].args[0] else: var_type = local_or_own_type.args[0].args[0] + local_or_own_type.args[0].args[1] builder = self.get_builder() type_list = self.flatten(ast.args[1]) for var_name in type_list: v = var_init(builder, var_name.args[0], var_type) self.set_var(var_name.args[0], v) elif ast.type in ["array_identifier", "variable_identifier", "procedure_identifier", "identifier"]: return str(ast.args[0]).lower() #присваивание elif ast.type == "assignment_statement": builder = self.get_builder() varName = self.descend(ast.args[0]) value = self.descend(ast.args[1]) for v in varName: ref = self.get_var(v) builder.store(value, ref) return varName[0] elif ast.type == "identifier_list": if len(ast.args) == 1: return [ast.args[0]] else: ls = list() ls.extend( self.descend(ast.args[0]) ) ls.append( ast.args[2] ) elif ast.type == "type": return types.translation[ast.args[0]] elif ast.type == "specifier": if len(ast.args) == 1: return self.descend(ast.args[0]) elif ast.type == "specification_part": if len(ast.args) == 2: specifier = self.descend(ast.args[0]) identifiers = self.descend(ast.args[1]) return [(specifier, identifiers)] else: ls = list() ls.extend( self.descend(ast.args[0]) ) ls.append( (self.descend(ast.args[1]), self.descend(ast.args[2]) ) ) return ls #объявление процедур. Храним название процедур(перегрузку запрещаем) elif ast.type == "procedure_declaration": type = None if len(ast.args) > 2: type = ast.args[0].args[0] heading = ast.args[1] body = ast.args[2] else: heading = ast.args[0] body = ast.args[1] if not type: return_type = types.void else: return_type = types.translation[type] proc_name = heading.args[0].args[0].lower() args = list() value_part = list() specification_part = list() if len(heading.args) > 1: i = 1 while i < len(heading.args): if heading.args[i] is not None: if heading.args[i].type == "formal_parameter_part": if len(heading.args[i].args) > 0: formal_parameter = heading.args[i].args[0] if len(formal_parameter.args) > 0: args = self.flatten(formal_parameter.args[0]) elif heading.args[i].type == "value_part": value_part = heading.args[i] if len(value_part.args) > 0: value_part = self.flatten(value_part.args[0]) elif heading.args[i].type == "specification_part": specification_part = self.descend(heading.args[i]) i += 1 code = body param_types = list() for arg in args: for type, var_names in specification_part: if arg in var_names: param_types.append(type) break ftype = types.function(return_type,param_types) #типы заранее мы не знаем f = Function.new(self.module, ftype, proc_name) fb = Builder.new(f.append_basic_block("entry")) self.contexts.append(Context( f,fb )) b = self.get_builder() for i, p in enumerate(args): x = f.args[i] x.name = p self.set_param(p, x) type_name = types.reverse_translation[return_type] v = var_init(b, proc_name, type_name) self.set_var(proc_name,v) self.descend(code) b = self.get_builder() b.ret(b.load(self.get_var(proc_name))) self.contexts.pop() elif ast.type == "while": self.counter += 1 now = self.get_function() builder = self.get_builder() loop = now.append_basic_block("loop_%d" % self.counter) body = now.append_basic_block("body_%d" % self.counter) tail = now.append_basic_block("tail_%d" % self.counter) # do while code self.contexts.append(Context(loop)) b = self.get_builder() cond = self.descend(ast.args[0]) b.cbranch(cond,body,tail) self.contexts.pop() self.contexts.append(Context(body)) b = self.get_builder() self.descend(ast.args[1]) # repeat b.branch(loop) self.contexts.pop() # start loop builder.branch(loop) self.contexts[-1].builder = Builder.new(tail) elif ast.type == "repeat": cond = Node('not',ast.args[1]) body = ast.args[0] while_b = Node('while',cond,body) final = Node('statement_list',body,while_b) return self.descend(final) elif ast.type == "for": direction = self.descend(ast.args[1]) limit = ast.args[2] builder = self.get_builder() # var declaration varname = self.descend(ast.args[0].args[0]) vartype = "INTEGER" v = var_init(builder, varname, vartype) self.set_var(varname,v) # var init variable = self.descend(ast.args[0]) # cond var1 = Node('element',Node('identifier',varname)) var1_name = Node('identifier',varname) sign = Node('sign',(direction == "to") and '<=' or '>=') comp = Node('op',sign,var1,limit) # body op = Node('sign',(direction == "to") and '+' or '-') varvalue = Node('op',op,var1,Node('element',Node('integer',1))) increment = Node('assign',var1_name,varvalue) body = Node('statement_list',ast.args[3],increment) # do while while_block = Node('while',comp,body) self.descend(while_block) elif ast.type in ["sign","and_or"]: return ast.args[0] elif ast.type == 'not': v = self.descend(ast.args[0]) builder = self.get_builder() return builder.not_(v) elif ast.type == "element": builder = self.get_builder() e = ast.args[0] if e.type == "identifier": ref = self.get_var(self.descend(e)) if ref.__class__ == Argument: return ref return builder.load(ref) else: return self.descend(ast.args[0]) elif ast.type == "string": b = self.get_builder() s = c_string(self.module,ast.args[0]) return pointer(b,s) elif ast.type == "unsigned_number": if len(ast.args) == 1: return self.descend(ast.args[0]) else: exp = self.descend(ast.args[1]) return self.descend(ast.args[0]) * pow(x=10, y=exp) elif ast.type == "decimal_number": if len(ast.args) == 1: return self.descend(ast.args[0]) else: return self.descend(ast.args[0]) + self.descend(ast.args[1]) elif ast.type == "unsigned_integer": if len(ast.args) == 1: return c_int(int(ast.args[0])) else: value = self.descend(ast.args[0]) * 10 + ast.args[1] return c_int(int(ast.args[0])) elif ast.type == "real": return c_real(float(ast.args[0])) else: print "unknown:", ast.type sys.exit()
def __call__(self, ast): if ast.__class__ != Node: return ast # PROGRAM if ast.type == "program": # Ínicio do programa self.module = Module.new("scurry") # Criar o módulo (string é um ID) # Os módulos LLVM são contentores. É preciso criá-lo antes de se poderem # adicionar variáveis globais, funções, etc. # Ver: http://mdevan.nfshost.com/llvm-py/userguide.html stdio = add_stdio(self.module) for f in stdio: self.functions[f] = stdio[f] main = create_main(self.module) block = Builder.new(main.append_basic_block("entry")) self.context_stack.push(Context(main,block)) self.descend(ast.args[0]) # Variáveis globais, funções e procedimentos self.descend(ast.args[1]) # Main self.get_builder().ret(c_int(0)) return self.module # PROC-FUNC-AND-VAR-LIST, STATEMENT-LIST elif ast.type in ["proc_func_and_var_list","statement_list"]: for son in ast.args: self.descend(son) # VAR elif ast.type == "var": # Declaração de variáveis var_type_name = self.descend(ast.args[0]) var_name = self.descend(ast.args[1]) builder = self.get_builder() v = var_init(self.module, builder, var_name, var_type_name) self.set_var(var_name,v) # GLOBAL-VAR elif ast.type == "global_var": # Declaração de variáveis globais var_type_name = self.descend(ast.args[0]) var_name = self.descend(ast.args[1]) builder = self.get_builder() v = global_var_init(self.module, var_type_name, var_name) # TYPE elif ast.type == "type": return str(ast.args[0]) # IDENTIFIER elif ast.type == "identifier": return str(ast.args[0]) # FUNCTION-CALL, FUNCTION-CALL-INLINE elif ast.type in ["function_call","function_call_inline"]: builder = self.get_builder() function_name = self.descend(ast.args[0]) arguments = [] if len(ast.args) > 1: if ast.args[1]: arguments = self.descend(ast.args[1]) if function_name in ['print','println']: if str(arguments[0].type) == 'double': function_name += "real" elif str(arguments[0].type) == 'i32': function_name += "int" elif str(arguments[0].type) == 'i8': function_name += "char" elif str(arguments[0].type) == 'i1': function_name += "bool" function = self.module.get_function_named(function_name) return builder.call(function,arguments) # PARAMETER-LIST elif ast.type == "parameter_list": l = [] l.extend(self.descend(ast.args[0])) l.extend(self.descend(ast.args[1])) return l # PARAMETER elif ast.type == "parameter": c = ast.args[0] if c.type == "identifier": label = self.descend(ast.args[0]) c = self.get_var(label) else: c = self.descend(ast.args[0]) return [c] # ASSIGN elif ast.type == "assign": builder = self.get_builder() varName = self.descend(ast.args[0]) value = self.descend(ast.args[1]) (ref, isGlobal) = self.get_var(varName) if not isGlobal: # Variáveis locais # self.set_var(value, ref) builder.store(value, ref) else: # Variáveis globais ref.initializer = value return varName # VAR-ASSIGN elif ast.type == "var_assign": var_type_name = self.descend(ast.args[0]) var_name = self.descend(ast.args[1]) value = self.descend(ast.args[2]) builder = self.get_builder() v = var_init(self.module, builder, var_name, var_type_name) self.set_var(var_name,v) if var_type_name != 'string': builder.store(value, v) # PROCEDURE, FUNCTION elif ast.type in ['procedure','function']: def get_params(node): """ Return a list of tuples of params """ if node.type == 'parameter': return [(self.descend(node.args[0]), types.translation[self.descend(node.args[1])])] else: l = [] for p in node.args: l.extend(get_params(p)) return l head = ast.args[0] if head.type == 'procedure_head': return_type = types.void else: return_type = types.translation[self.descend(head.args[-1])] name = self.descend(head.args[0]) if ast.type == 'procedure' and len(head.args) == 1: # Apenas o nome params = [] # Nos procedimentos sem parâms é só nome que é posto na AST elif ast.type == 'function' and len(head.args) == 2: # Nome e tipo params = [] # Nas funções sem parâmetros, é só nome e tipo de retorno else: params = get_params(head.args[1]) code = ast.args[1] ftype = types.function(return_type, [ i[1] for i in params ]) f = Function.new(self.module, ftype, name) fb = Builder.new(f.append_basic_block("entry")) self.context_stack.push(Context(f, fb)) b = self.get_builder() for i,p in enumerate(params): x = f.args[i]; x.name = p[0] type_name = types.reverse_translation[x.type] v = var_init(self.module, b, x.name, type_name) self.set_param(p[0],v) b.store(x, v) if ast.type == 'function': # Criar uma variável para guardar o retorno type_name = types.reverse_translation[return_type] v = var_init(self.module, b, 'result', type_name) self.set_var('result',v) self.descend(code) b = self.get_builder() if ast.type == 'procedure': b.ret_void() else: (ref, isGlobal) = self.get_var('result') b.ret(b.load(ref)) self.context_stack.pop() # WHILE elif ast.type == "while": self.counter += 1 now = self.get_function() builder = self.get_builder() loop = now.append_basic_block("loop_%d" % self.counter) body = now.append_basic_block("body_%d" % self.counter) tail = now.append_basic_block("tail_%d" % self.counter) # do while code self.context_stack.push(Context(loop)) b = self.get_builder() cond = self.descend(ast.args[0]) b.cbranch(cond,body,tail) self.context_stack.pop() self.context_stack.push(Context(body)) b = self.get_builder() self.descend(ast.args[1]) # repeat b.branch(loop) self.context_stack.pop() # start loop builder.branch(loop) self.context_stack.top().builder = Builder.new(tail) # DO elif ast.type == "do": cond = Node('not',ast.lineno,ast.args[1]) body = ast.args[0] while_b = Node('while',ast.lineno,cond,body) final = Node('statement_list',ast.lineno,body,while_b) return self.descend(final) # FOR elif ast.type == "for": direction = self.descend(ast.args[1]) # Se é TO ou DOWNTO limit = ast.args[2] # O extremo direito a atingir if len(ast.args) == 5: # Se consiste em for com incremento diferente de 1 inc = int(ast.args[4].args[0].args[0]) # Valor de incremento else: inc = 1 builder = self.get_builder() # Declaração da variável contador varname = self.descend(ast.args[0].args[0]) vartype = "int" v = var_init(self.module, builder, varname, vartype) self.set_var(varname,v) # var init variable = self.descend(ast.args[0]) # cond var1 = Node('element',ast.lineno,Node('identifier',ast.lineno,varname)) var1_name = Node('identifier',ast.lineno,varname) # body if (direction == "to" and inc > 0) or (direction == "downto" and inc < 0): sign_term = '<=' op_term = '+' elif (direction == "to" and inc < 0) or (direction == "downto" and inc > 0): sign_term = '>=' op_term = '-' else: raise_exception("Invalid increment value on 'for' statement") sign = Node('sign',ast.lineno,sign_term) op = Node('sign',ast.lineno,op_term) comp = Node('op',ast.lineno,sign,var1,limit) varvalue = Node('op',ast.lineno,op,var1,Node('element',ast.lineno,Node('int',ast.lineno,abs(inc)))) increment = Node('assign',ast.lineno,var1_name,varvalue) body = Node('statement_list',ast.lineno,ast.args[3],increment) # do while while_block = Node('while',ast.lineno,comp,body) self.descend(while_block) # IF elif ast.type == "if": now = self.get_function() builder = self.get_builder() #if cond = self.descend(ast.args[0]) # the rest self.counter += 1 tail = now.append_basic_block("tail_%d" % self.counter) # then then_block = now.append_basic_block("if_%d" % self.counter) self.context_stack.push( Context(then_block) ) self.descend(ast.args[1]) b = self.get_builder() b.branch(tail) b.position_at_end(tail) self.context_stack.pop() # else else_block = now.append_basic_block("else_%d" % self.counter) self.context_stack.push( Context(else_block) ) if len(ast.args) > 2: self.descend(ast.args[2]) b = self.get_builder() b.branch(tail) b.position_at_end(tail) self.context_stack.pop() builder.cbranch(cond,then_block,else_block) self.context_stack.top().builder = Builder.new(tail) # UNLESS elif ast.type == "unless": # Transformar a condição 'unless' num 'if' cond = self.descend(ast.args[1]) neg_cond = Node('not',ast.lineno,cond) node = Node('if',ast.lineno,neg_cond,ast.args[0]) self.descend(node) # SIGN, AND-OR elif ast.type in ["sign","and_or"]: return ast.args[0] # OP elif ast.type == "op": sign = self.descend(ast.args[0]) v1 = self.descend(ast.args[1]) v2 = self.descend(ast.args[2]) builder = self.get_builder() if sign == "+": return builder.add(v1, v2) elif sign == "-": return builder.sub(v1, v2) elif sign == "*": return builder.mul(v1, v2) # elif sign == "**": # print "v1", v1 # print "v2", v2 # base = ast.args[1].args[0].args[0] # Base # exp = ast.args[2].args[0].args[0] # Expoente # print "base", base # print "exp", exp # if ast.args[1].args[0].type == 'int': # return c_int(int(base) ** int(exp)) # else: # Ambos base e expoente são float # return c_real(float(base) ** float(exp)) elif sign == "/" and str(v1.type) == 'i32' and str(v2.type) == 'i32': return builder.sdiv(v1, v2) # Divisão de inteiros elif sign == "/": # Divisão de floats return builder.fdiv(v1, v2) elif sign in ["mod", "%"]: return builder.urem(v1, v2) elif sign in [">",">=","==","<=","<","<>"]: return compare(sign,v1,v2,builder) elif sign == "and": return builder.and_(v1,v2) elif sign == "or": return builder.or_(v1,v2) else: raise_exception("undefined operator %s" % sign) # ELEMENT elif ast.type == "element": builder = self.get_builder() e = ast.args[0] if e.type == "identifier": var_name = ast.args[0].args[0] # Nome da variável (ref, isGlobal) = self.get_var(self.descend(e)) if isGlobal: return ref.initializer elif ref.__class__ == Argument: return ref return builder.load(ref) else: return self.descend(ast.args[0]) # NOT elif ast.type == 'not': # O nó é do tipo Node('not',ln(p),p[2]) logo p[2] == ast.args[0] v = self.descend(ast.args[0]) # A expressão a ser negada return self.get_builder().not_(v) # Negação da expressão v # STRING elif ast.type == "string": b = self.get_builder() s = c_string(self.module, ast.args[0]) return pointer(b,s) # INT elif ast.type == "int": return c_int(int(ast.args[0])) # REAL elif ast.type == "real": return c_real(float(ast.args[0])) # CHAR elif ast.type == "char": char = ast.args[0][1] # Preciso [1] prq vem 'a' e queremos a (sem plicas) return c_char(char) # BOOL elif ast.type == "bool": if ast.args[0] == "false": return c_bool(False) else: return c_bool(True) else: # Se for encontrado um outro tipo de nó inesperado (só acontece se o # rules.py foi modificado) raise_exception("unknown: %s" % ast.type)