|
@@ -95,6 +95,19 @@ class AnalysisState(object):
|
|
|
def __init__(self):
|
|
|
self.analyzed_instructions = set()
|
|
|
|
|
|
+ def get_local_name(self, local_id):
|
|
|
+ """Gets the name for a local with the given id."""
|
|
|
+ return 'local%d' % local_id
|
|
|
+
|
|
|
+ def retrieve_user_root(self):
|
|
|
+ """Creates an instruction that stores the user_root variable
|
|
|
+ in a local."""
|
|
|
+ return tree_ir.StoreLocalInstruction(
|
|
|
+ 'user_root',
|
|
|
+ tree_ir.LoadIndexInstruction(
|
|
|
+ tree_ir.LoadLocalInstruction(KWARGS_PARAMETER_NAME),
|
|
|
+ tree_ir.LiteralInstruction('user_root')))
|
|
|
+
|
|
|
def analyze(self, instruction_id):
|
|
|
"""Tries to build an intermediate representation from the instruction with the
|
|
|
given id."""
|
|
@@ -295,11 +308,154 @@ class AnalysisState(object):
|
|
|
|
|
|
raise primitive_functions.PrimitiveFinished(result)
|
|
|
|
|
|
+ def analyze_resolve(self, instruction_id):
|
|
|
+ """Tries to analyze the given 'resolve' instruction."""
|
|
|
+ var_id, = yield [("RD", [instruction_id, "var"])]
|
|
|
+
|
|
|
+ # To resolve a variable, we'll do something along the
|
|
|
+ # lines of:
|
|
|
+ #
|
|
|
+ # if 'local_var' in locals():
|
|
|
+ # tmp = local_var
|
|
|
+ # else:
|
|
|
+ # _globals, var_name = yield [("RD", [user_root, "globals"]),
|
|
|
+ # ("RV", [var_id])
|
|
|
+ # ]
|
|
|
+ # global_var = yield [("RD", [_globals, var_name])]
|
|
|
+ #
|
|
|
+ # if global_var is None:
|
|
|
+ # raise Exception("Runtime error: global '%s' not found" % (var_name))
|
|
|
+ #
|
|
|
+ # tmp = global_var
|
|
|
+
|
|
|
+ user_root = self.retrieve_user_root()
|
|
|
+ var_name = tree_ir.StoreLocalInstruction(
|
|
|
+ 'var_name',
|
|
|
+ tree_ir.ReadValueInstruction(
|
|
|
+ tree_ir.LiteralInstruction(var_id)))
|
|
|
+
|
|
|
+ global_var = tree_ir.StoreLocalInstruction(
|
|
|
+ 'global_var',
|
|
|
+ tree_ir.ReadDictionaryValueInstruction(
|
|
|
+ tree_ir.ReadDictionaryValueInstruction(
|
|
|
+ user_root.create_load(),
|
|
|
+ tree_ir.LiteralInstruction('globals')),
|
|
|
+ var_id.create_load()))
|
|
|
+
|
|
|
+ err_block = tree_ir.SelectInstruction(
|
|
|
+ tree_ir.BinaryInstruction(
|
|
|
+ global_var.create_load(),
|
|
|
+ 'is',
|
|
|
+ tree_ir.LiteralInstruction(None)),
|
|
|
+ tree_ir.RaiseInstruction(
|
|
|
+ tree_ir.CallInstruction(
|
|
|
+ tree_ir.LoadLocalInstruction('Exception'),
|
|
|
+ [tree_ir.BinaryInstruction(
|
|
|
+ tree_ir.LiteralInstruction("Runtime error: global '%s' not found"),
|
|
|
+ '%',
|
|
|
+ var_name.create_load())
|
|
|
+ ])),
|
|
|
+ tree_ir.EmptyInstruction())
|
|
|
+
|
|
|
+ name = self.get_local_name(var_id)
|
|
|
+ raise primitive_functions.PrimitiveFinished(
|
|
|
+ tree_ir.SelectInstruction(
|
|
|
+ tree_ir.LocalExistsInstruction(name),
|
|
|
+ tree_ir.LoadLocalInstruction(name),
|
|
|
+ tree_ir.CompoundInstruction(
|
|
|
+ tree_ir.create_block(
|
|
|
+ user_root,
|
|
|
+ var_name,
|
|
|
+ global_var,
|
|
|
+ err_block),
|
|
|
+ global_var.create_load())))
|
|
|
+
|
|
|
+ def analyze_declare(self, instruction_id):
|
|
|
+ """Tries to analyze the given 'declare' function."""
|
|
|
+ var_id, = yield [("RD", [instruction_id, "var"])]
|
|
|
+
|
|
|
+ name = self.get_local_name(var_id)
|
|
|
+
|
|
|
+ # The following logic declares a local:
|
|
|
+ #
|
|
|
+ # if 'local_name' not in locals():
|
|
|
+ # local_name, = yield [("CN", [])]
|
|
|
+
|
|
|
+ raise primitive_functions.PrimitiveFinished(
|
|
|
+ tree_ir.SelectInstruction(
|
|
|
+ tree_ir.LocalExistsInstruction(name),
|
|
|
+ tree_ir.EmptyInstruction(),
|
|
|
+ tree_ir.StoreLocalInstruction(
|
|
|
+ name,
|
|
|
+ tree_ir.CreateNodeInstruction())))
|
|
|
+
|
|
|
+ def analyze_global(self, instruction_id):
|
|
|
+ """Tries to analyze the given 'global' (declaration) function."""
|
|
|
+ var_id, = yield [("RD", [instruction_id, "var"])]
|
|
|
+
|
|
|
+ # To resolve a variable, we'll do something along the
|
|
|
+ # lines of:
|
|
|
+ #
|
|
|
+ # _globals, var_name = yield [("RD", [user_root, "globals"]),
|
|
|
+ # ("RV", [var_id])
|
|
|
+ # ]
|
|
|
+ # global_var = yield [("RD", [_globals, var_name])]
|
|
|
+ #
|
|
|
+ # if global_var is None:
|
|
|
+ # global_var, = yield [("CN", [])]
|
|
|
+ # yield [("CD", [_globals, var_name, global_var])]
|
|
|
+ #
|
|
|
+ # tmp = global_var
|
|
|
+
|
|
|
+ user_root = self.retrieve_user_root()
|
|
|
+ var_name = tree_ir.StoreLocalInstruction(
|
|
|
+ 'var_name',
|
|
|
+ tree_ir.ReadValueInstruction(
|
|
|
+ tree_ir.LiteralInstruction(var_id)))
|
|
|
+
|
|
|
+ _globals = tree_ir.StoreLocalInstruction(
|
|
|
+ '_globals',
|
|
|
+ tree_ir.ReadDictionaryValueInstruction(
|
|
|
+ user_root.create_load(),
|
|
|
+ tree_ir.LiteralInstruction('globals')))
|
|
|
+
|
|
|
+ global_var = tree_ir.StoreLocalInstruction(
|
|
|
+ 'global_var',
|
|
|
+ tree_ir.ReadDictionaryValueInstruction(
|
|
|
+ _globals.create_load(),
|
|
|
+ var_name.create_load()))
|
|
|
+
|
|
|
+ raise primitive_functions.PrimitiveFinished(
|
|
|
+ tree_ir.CompoundInstruction(
|
|
|
+ tree_ir.create_block(
|
|
|
+ user_root,
|
|
|
+ var_name,
|
|
|
+ _globals,
|
|
|
+ global_var,
|
|
|
+ tree_ir.SelectInstruction(
|
|
|
+ tree_ir.BinaryInstruction(
|
|
|
+ global_var.create_load(),
|
|
|
+ 'is',
|
|
|
+ tree_ir.LiteralInstruction(None)),
|
|
|
+ tree_ir.create_block(
|
|
|
+ global_var.create_store(
|
|
|
+ tree_ir.CreateNodeInstruction()),
|
|
|
+ tree_ir.CreateDictionaryEdgeInstruction(
|
|
|
+ _globals.create_load(),
|
|
|
+ var_name.create_load(),
|
|
|
+ global_var.create_load())),
|
|
|
+ tree_ir.EmptyInstruction())),
|
|
|
+ global_var.create_load())
|
|
|
+ )
|
|
|
+
|
|
|
instruction_analyzers = {
|
|
|
'if' : analyze_if,
|
|
|
'while' : analyze_while,
|
|
|
'return' : analyze_return,
|
|
|
'constant' : analyze_constant,
|
|
|
+ 'resolve' : analyze_resolve,
|
|
|
+ 'declare' : analyze_declare,
|
|
|
+ 'global' : analyze_global,
|
|
|
'output' : analyze_output
|
|
|
}
|
|
|
|