|
@@ -33,6 +33,13 @@ UNARY_INTRINSICS = {
|
|
|
'float_neg' : '-'
|
|
|
}
|
|
|
|
|
|
+def create_get_length(expression):
|
|
|
+ """Creates an expression that evaluates the given expression, and then
|
|
|
+ computes the length of its result."""
|
|
|
+ return tree_ir.CallInstruction(
|
|
|
+ tree_ir.LoadGlobalInstruction('len'),
|
|
|
+ [expression])
|
|
|
+
|
|
|
# Don't compain about the variable names, pylint. It's important that we
|
|
|
# get them right.
|
|
|
# pylint: disable=I0011,C0103
|
|
@@ -54,6 +61,65 @@ def __dict_add(a, b, c):
|
|
|
b_tmp.create_load()),
|
|
|
a_tmp.create_load())
|
|
|
|
|
|
+def __list_read(a, b):
|
|
|
+ # The statements in this function generate the following code:
|
|
|
+ #
|
|
|
+ # a_tmp = a # To make sure a is evaluated before b.
|
|
|
+ # b_value, = yield [("RV", [b])]
|
|
|
+ # result, = yield [("RD", [a_tmp, b_value])]
|
|
|
+ # if result is None:
|
|
|
+ # raise Exception("List read out of bounds: %s" % b_value)
|
|
|
+ # result
|
|
|
+
|
|
|
+ a_tmp = tree_ir.StoreLocalInstruction(None, a)
|
|
|
+ b_val = tree_ir.StoreLocalInstruction(
|
|
|
+ None,
|
|
|
+ tree_ir.ReadValueInstruction(b))
|
|
|
+ result = tree_ir.StoreLocalInstruction(
|
|
|
+ None,
|
|
|
+ tree_ir.ReadDictionaryValueInstruction(
|
|
|
+ a_tmp.create_load(), b_val.create_load()))
|
|
|
+
|
|
|
+ return tree_ir.create_block(
|
|
|
+ a_tmp,
|
|
|
+ b_val,
|
|
|
+ result,
|
|
|
+ tree_ir.SelectInstruction(
|
|
|
+ tree_ir.BinaryInstruction(
|
|
|
+ result.create_load(),
|
|
|
+ 'is',
|
|
|
+ tree_ir.LiteralInstruction(None)),
|
|
|
+ tree_ir.RaiseInstruction(
|
|
|
+ tree_ir.CallInstruction(
|
|
|
+ tree_ir.LoadGlobalInstruction('Exception'),
|
|
|
+ [tree_ir.BinaryInstruction(
|
|
|
+ tree_ir.LiteralInstruction('List read out of bounds: %s'),
|
|
|
+ '%',
|
|
|
+ b_val.create_load())])),
|
|
|
+ tree_ir.NopInstruction()),
|
|
|
+ result.create_load())
|
|
|
+
|
|
|
+def __list_append(a, b):
|
|
|
+ # We want to generate code that is more or less equivalent to:
|
|
|
+ #
|
|
|
+ # a_tmp = a
|
|
|
+ # b_tmp = b
|
|
|
+ # a_outgoing, = yield [("RO", [a_tmp])]
|
|
|
+ # _ = yield [("CD", [a_tmp, len(a_outgoing), b_tmp])]
|
|
|
+ # a
|
|
|
+
|
|
|
+ a_tmp = tree_ir.StoreLocalInstruction(None, a)
|
|
|
+ b_tmp = tree_ir.StoreLocalInstruction(None, b)
|
|
|
+ return tree_ir.create_block(
|
|
|
+ a_tmp,
|
|
|
+ tree_ir.CreateDictionaryEdgeInstruction(
|
|
|
+ a_tmp.create_load(),
|
|
|
+ create_get_length(
|
|
|
+ tree_ir.ReadOutgoingEdgesInstruction(
|
|
|
+ a_tmp.create_load())),
|
|
|
+ b_tmp),
|
|
|
+ a_tmp.create_load())
|
|
|
+
|
|
|
MISC_INTRINSICS = {
|
|
|
# Reference equality
|
|
|
'element_eq' :
|
|
@@ -159,9 +225,10 @@ MISC_INTRINSICS = {
|
|
|
'list_len' :
|
|
|
lambda a:
|
|
|
tree_ir.CreateNodeWithValueInstruction(
|
|
|
- tree_ir.CallInstruction(
|
|
|
- tree_ir.LoadGlobalInstruction('len'),
|
|
|
- [tree_ir.ReadOutgoingEdgesInstruction(a)]))
|
|
|
+ create_get_length(tree_ir.ReadOutgoingEdgesInstruction(a))),
|
|
|
+
|
|
|
+ 'list_read' : __list_read,
|
|
|
+ 'list_append' : __list_append
|
|
|
}
|
|
|
|
|
|
def register_intrinsics(target_jit):
|