Add an explicit ARTIQ IR instruction to create a closure.

This commit is contained in:
whitequark 2015-07-18 09:27:34 +03:00
parent 5ad02d5282
commit 8e1cc8d985
2 changed files with 32 additions and 12 deletions

View File

@ -344,14 +344,13 @@ class Argument(NamedValue):
def __str__(self):
return self.as_operand()
class Function(Value):
class Function:
"""
A function containing SSA IR.
"""
def __init__(self, typ, name, arguments):
super().__init__(typ)
self.name = name
self.type, self.name = typ, name
self.names, self.arguments, self.basic_blocks = set(), [], []
self.set_arguments(arguments)
@ -389,10 +388,6 @@ class Function(Value):
return [block for block in self.basic_blocks
if block.is_terminated() and successor in block.successors()]
def as_operand(self):
return "{} @{}".format(types.TypePrinter().name(self.type),
escape_name(self.name))
def __str__(self):
printer = types.TypePrinter()
lines = []
@ -766,6 +761,30 @@ class Builtin(Instruction):
def opcode(self):
return "builtin({})".format(self.op)
class Closure(Instruction):
"""
A closure creation operation.
:ivar target_function: (:class:`Function`) function to invoke
"""
"""
:param func: (:class:`Function`) function
:param env: (:class:`Value`) outer environment
"""
def __init__(self, func, env, name=""):
assert isinstance(func, Function)
assert isinstance(env, Value)
assert is_environment(env.type)
super().__init__([env], func.type, name)
self.target_function = func
def opcode(self):
return "closure({})".format(self.target_function.name)
def get_environment(self):
return self.operands[0]
class Call(Instruction):
"""
A function call operation.
@ -776,7 +795,6 @@ class Call(Instruction):
:param args: (list of :class:`Value`) function arguments
"""
def __init__(self, func, args, name=""):
print(func)
assert isinstance(func, Value)
for arg in args: assert isinstance(arg, Value)
super().__init__([func] + args, func.type.ret, name)

View File

@ -131,7 +131,8 @@ class IRGenerator(algorithm.Visitor):
env = self.append(ir.Alloc([], ir.TEnvironment(node.typing_env), name="env"))
old_env, self.current_env = self.current_env, env
priv_env = self.append(ir.Alloc([], ir.TEnvironment({ ".return": typ.ret })))
priv_env = self.append(ir.Alloc([], ir.TEnvironment({ ".return": typ.ret }),
name="privenv"))
old_priv_env, self.current_private_env = self.current_private_env, priv_env
self.generic_visit(node)
@ -193,7 +194,8 @@ class IRGenerator(algorithm.Visitor):
old_env, self.current_env = self.current_env, env
if not is_lambda:
priv_env = self.append(ir.Alloc([], ir.TEnvironment({ ".return": typ.ret })))
priv_env = self.append(ir.Alloc([], ir.TEnvironment({ ".return": typ.ret }),
name="privenv"))
old_priv_env, self.current_private_env = self.current_private_env, priv_env
self.append(ir.SetLocal(env, ".outer", env_arg))
@ -215,8 +217,6 @@ class IRGenerator(algorithm.Visitor):
else:
if not self.current_block.is_terminated():
self.current_block.append(ir.Unreachable())
return func
finally:
self.name = old_name
self.current_function = old_func
@ -226,6 +226,8 @@ class IRGenerator(algorithm.Visitor):
if not is_lambda:
self.current_private_env = old_priv_env
return self.append(ir.Closure(func, self.current_env))
def visit_FunctionDefT(self, node):
func = self.visit_function(node, is_lambda=False)
self._set_local(node.name, func)