def function(self, fun: Function, depth=0) -> Any: trace(depth, 'function') self.scope = self.scope.enter_scope('function') ftype = self.visit(fun.type, depth + 1, mode='type') if self.binding_name is None: name = self.generate_unique_binding_name() self.scope.insert_binding(name, fun) else: name = self.binding_name ir_fun = self.builder.Function(self.module, ftype=ftype, name=name) args = ir_fun.args for arg, larg in zip(fun.args, args): self.scope.insert_binding(arg.name, larg) block = ir_fun.append_basic_block(name='{}_block'.format(name)) old = self.builder old_p = self.parent self.parent = ir_fun self.builder = ir.IRBuilder(block) self.visit(fun.body, depth + 1) self.builder = old self.parent = old_p self.scope = self.scope.exit_scope() return ir_fun
def function(self, fun: Function, depth=0) -> Any: trace(depth, 'function {}'.format('')) if len(self.bind_name) == 0: return self.function_lambda(fun, depth) return self.function_bind(self.bind_name[-1], fun, depth)
def call(self, call: Call, depth=0) -> Any: trace(depth, 'call') lcall = self.visit(call.function, depth + 1) args = [self.visit(expr, depth + 1) for expr in call.args] if isinstance(lcall, Builtin): if lcall.name not in builtins: raise UndefinedBuiltin(lcall) nargs, impl = builtins[lcall.name] if nargs != len(call.args): raise ArgumentSizeMismatch(nargs, call.args) return impl(self.builder, args) # FIXME if isinstance(lcall, ir.LiteralStructType): return lcall(args) if isinstance(lcall, dict): oargs = call.args[0] tag, ncall = lcall[oargs.name] return ncall([ir.Constant(ir.IntType(32), tag)] + args) print(call.function, ' => ', lcall) print(args) return self.builder.call(lcall, args)
def bind(self, bind: Bind, depth=0) -> Any: trace(depth, 'bind `{}`'.format(bind.name)) name = self.binding_name self.binding_name = bind.name expr = self.visit(bind.expr, depth + 1) self.binding_name = name return Bind(bind.name, expr)
def value(self, val: Value, depth=0) -> Any: trace(depth, 'value') # print(val.value, self.b.value) if isinstance(val.value, Expression): self.b = self.b.value return self.visit(val.value, depth + 1) return val.value == self.b.value
def arrow(self, arrow: Arrow, depth=0) -> Any: trace(depth, 'arrow') self.scope = self.scope.enter_scope('arrow') ftype = self.builder.FunctionType( self.visit(arrow.return_type, depth + 1), [self.visit(arg, depth + 1) for arg in arrow.args]) self.scope = self.scope.exit_scope() return ftype
def reference(self, ref: VariableRef, depth=0) -> Any: trace(depth, 'reference `{}`'.format(ref.name)) # Option 1, check if this is a LLVM ref and do not visit v = self.scope.get_expression(ref, depth + 1) if isinstance(v, Expression): return self.visit(v, depth + 1) # print(v) return v
def arrow(self, arrow: Arrow, depth=0) -> Any: trace(depth, 'arrow') if len(arrow.args) != len(self.b.args): return False args = [ self.type_check(a, b, depth + 1) for a, b in zip(arrow.args, self.b.args) ] return self.type_check(arrow.return_type, self.b.return_type, depth + 1) \ and reduce(lambda x, y: x and y, args, True)
def builtin(self, builtin: Builtin, depth=0) -> Any: trace(depth, 'builtin') if builtin.name not in builtins: raise UndefinedBuiltin(builtin) nargs, impl = builtins[builtin.name] if self.mode == 'type': return impl return builtin
def call(self, call: Call, depth=0) -> Any: trace(depth, 'call') fun = self.visit(call.function, depth + 1) args = [] for arg in call.args: arg_val = self.visit(arg, depth + 1) if isinstance(arg, NamedArgument): args.append('{} = {}'.format(arg.name, arg_val)) else: args.append(arg_val) args = ', '.join(args) return '{}({})'.format(fun, args)
def struct(self, struct: Struct, depth=0) -> Any: trace(depth, 'struct') if not self.structural_check: return struct is self.b if len(struct.members) != len(self.b.members): return False args = [ self.type_check(a.type, b.type, depth + 1) and a.name == b.name for a, b in zip(struct.members, self.b.members) ] return reduce(lambda x, y: x and y, args, True)
def block(self, block: Block, depth=0) -> Any: trace(depth, 'block') blk = ir.Block(self.parent) old = self.builder old_p = self.parent self.builder = ir.IRBuilder(block) for expr in block.expressions: self.visit(expr, depth + 1) self.builder = old self.parent = old_p return blk
def arrow(self, arrow: Arrow, depth=0) -> Any: trace(depth, 'arrow') args = ', '.join([self.visit(arg, depth + 1) for arg in arrow.args]) return '({}) -> {}'.format(args, self.visit(arrow.return_type, depth + 1))