123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575 |
- class PrimitiveFinished(Exception):
- """Exception to indicate the result value of a primitive, as a return cannot be used."""
- def __init__(self, value):
- Exception.__init__(self)
- self.result = value
- class InterpretedFunctionFinished(Exception):
- """Exception to indicate the result value of an interpreted function, as a return
- cannot be used."""
- def __init__(self, value):
- Exception.__init__(self)
- self.result = value
- # Functions annotated with __exception_return use the JIT's calling convention instead of
- # the kernel's: returns are handled by throwing a PrimitiveFinished exception; the caller's
- # returnvalue is not modified.
- #
- # ### Rationale for __exception_return
- #
- # __exception_return is a useful mechanism because it allows us to have a __call_function
- # implementation that has O(1) state read overhead. A previous implementation of
- # __call_function checked if the caller's frame had been popped whenever
- # ModelverseKernel.execute_yield threw a StopIteration exception. However, that incurs O(n) overhead
- # _per call,_ where n is the number of StopIteration exceptions that are thrown during the call.
- # O(n) is pretty bad, but this actually becomes O(n * m) when m calls to __call_function are
- # nested. And that's just not acceptable.
- # __exception_return requires kernel support, but I think the complexity gains are well worth it;
- # I reckon JIT-to-interpreter switches aren't going to get a whole lot cheaper than this.
- EXCEPTION_RETURN_KEY = "__exception_return"
- """A dictionary key for functions which request that the kernel throw a InterpretedFunctionFinished
- exception with the return value instead of injecting the return value in the caller's frame."""
- def integer_subtraction(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [a_value - b_value])]
- raise PrimitiveFinished(result)
- def integer_addition(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [a_value + b_value])]
- raise PrimitiveFinished(result)
- def integer_multiplication(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [a_value * b_value])]
- raise PrimitiveFinished(result)
- def integer_division(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [int(a_value) / b_value])]
- raise PrimitiveFinished(result)
- def integer_gt(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [a_value > b_value])]
- raise PrimitiveFinished(result)
- def integer_lt(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [a_value < b_value])]
- raise PrimitiveFinished(result)
- def integer_neg(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [-a_value])]
- raise PrimitiveFinished(result)
- def bool_and(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [a_value and b_value])]
- raise PrimitiveFinished(result)
- def bool_or(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [a_value or b_value])]
- raise PrimitiveFinished(result)
- def bool_not(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [not a_value])]
- raise PrimitiveFinished(result)
- def float_subtraction(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [a_value - b_value])]
- raise PrimitiveFinished(result)
- def float_addition(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [a_value + b_value])]
- raise PrimitiveFinished(result)
- def float_multiplication(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [a_value * b_value])]
- raise PrimitiveFinished(result)
- def float_division(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [float(a_value) / float(b_value)])]
- raise PrimitiveFinished(result)
- def float_gt(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [a_value > b_value])]
- raise PrimitiveFinished(result)
- def float_lt(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [a_value < b_value])]
- raise PrimitiveFinished(result)
- def float_neg(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [-a_value])]
- raise PrimitiveFinished(result)
- def string_join(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [str(a_value) + str(b_value)])]
- raise PrimitiveFinished(result)
- def string_split(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result = a_value.split(b_value)
- elems = yield [("CN", [])] + [("CNV", [v]) for v in result]
- new_val = elems[0]
- yield [("CD", [new_val, i, v]) for i, v in enumerate(elems[1:])]
- raise PrimitiveFinished(new_val)
- def string_get(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [a_value[b_value]])]
- raise PrimitiveFinished(result)
- def string_len(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [len(a_value)])]
- raise PrimitiveFinished(result)
- def value_eq(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [a_value == b_value])]
- raise PrimitiveFinished(result)
- def value_neq(a, b, **remainder):
- a_value, b_value = yield [("RV", [a]), ("RV", [b])]
- result, = yield [("CNV", [a_value != b_value])]
- raise PrimitiveFinished(result)
- def element_eq(a, b, **remainder):
- result, = yield [("CNV", [a == b])]
- raise PrimitiveFinished(result)
- def element_neq(a, b, **remainder):
- result, = yield [("CNV", [a != b])]
- raise PrimitiveFinished(result)
- def cast_a2s(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [str(a_value["value"])])]
- raise PrimitiveFinished(result)
- def cast_i2f(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [float(a_value)])]
- raise PrimitiveFinished(result)
- def cast_i2s(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [str(a_value)])]
- raise PrimitiveFinished(result)
- def cast_i2b(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [bool(a_value)])]
- raise PrimitiveFinished(result)
- def cast_f2i(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [int(a_value)])]
- raise PrimitiveFinished(result)
- def cast_f2s(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [str(a_value)])]
- raise PrimitiveFinished(result)
- def cast_f2b(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [bool(a_value)])]
- raise PrimitiveFinished(result)
- def cast_s2i(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [int(a_value)])]
- raise PrimitiveFinished(result)
- def cast_s2f(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [float(a_value)])]
- raise PrimitiveFinished(result)
- def cast_s2b(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [bool(a_value)])]
- raise PrimitiveFinished(result)
- def cast_b2i(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [int(a_value)])]
- raise PrimitiveFinished(result)
- def cast_b2f(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [float(a_value)])]
- raise PrimitiveFinished(result)
- def cast_b2s(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [str(a_value)])]
- raise PrimitiveFinished(result)
- def cast_e2s(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", ["{ID: %s, value: %s}" % (a, a_value)])]
- raise PrimitiveFinished(result)
- def cast_v2s(a, **remainder):
- a_value, = yield [("RV", [a])]
- if isinstance(a_value, (str, unicode)):
- # String should be encoded to distinguish between 3 and "3"
- a_value = '"%s"' % a_value
- elif isinstance(a_value, dict):
- # Action or type
- a_value = a_value["value"]
- result, = yield [("CNV", ["%s" % (a_value)])]
- raise PrimitiveFinished(result)
- def cast_id2s(a, **remainder):
- result, = yield [("CNV", ["%s" % (a)])]
- raise PrimitiveFinished(result)
- def list_append(a, b, **remainder):
- a_outgoing, = yield [("RO", [a])]
- _ = yield [("CD", [a, len(a_outgoing), b])]
- raise PrimitiveFinished(a)
- def list_insert(a, b, c, **remainder):
- a_outgoing, c_value = yield [("RO", [a]), ("RV", [c])]
- links = yield [("RD", [a, i]) for i in range(c_value, len(a_outgoing))] + \
- [("RDE", [a, i]) for i in range(c_value, len(a_outgoing))]
- values = links[:len(links)/2]
- edges = links[len(links)/2:]
- yield [("CD", [a, c_value, b])] + \
- [("CD", [a, c_value + 1 + index, value]) for index, value in enumerate(values)] + \
- [("DE", [i]) for i in edges]
- raise PrimitiveFinished(a)
- def list_delete(a, b, **remainder):
- a_outgoing, b_value = yield [("RO", [a]), ("RV", [b])]
- links = yield [("RD", [a, i]) for i in range(b_value, len(a_outgoing))] + \
- [("RDE", [a, i]) for i in range(b_value, len(a_outgoing))]
- values = links[:len(links)/2]
- edges = links[len(links)/2:]
- yield [("CD", [a, b_value + index, value]) for index, value in enumerate(values[1:])] + \
- [("DE", [i]) for i in edges]
- raise PrimitiveFinished(a)
- def list_read(a, b, **remainder):
- b_value, = yield [("RV", [b])]
- result, = yield [("RD", [a, b_value])]
- if result is None:
- raise Exception("List read out of bounds: %s" % b_value)
- raise PrimitiveFinished(result)
- def list_len(a, **remainder):
- outgoings, = yield [("RO", [a])]
- result, = yield [("CNV", [len(outgoings)])]
- raise PrimitiveFinished(result)
- def dict_add(a, b, c, **remainder):
- new_edge, = yield [("CE", [a, c])]
- yield [("CE", [new_edge, b])]
- raise PrimitiveFinished(a)
- def dict_delete(a, b, **remainder):
- b_value, = yield [("RV", [b])]
- edge, = yield [("RDE", [a, b_value])]
- if edge is None:
- print("Failed dict_delete for value %s!" % b_value)
- keys, = yield [("RDK", [a])]
- keys = yield [("RV", [i]) for i in keys]
- print("Keys: " + str(keys))
- yield [("DE", [edge])]
- raise PrimitiveFinished(a)
- def dict_delete_node(a, b, **remainder):
- edge, = yield [("RDNE", [a, b])]
- if edge is None:
- print("Failed dict_delete_node!")
- yield [("DE", [edge])]
- raise PrimitiveFinished(a)
- def dict_read(a, b, **remainder):
- b_value, = yield [("RV", [b])]
- result, = yield [("RD", [a, b_value])]
- raise PrimitiveFinished(result)
- def dict_read_edge(a, b, **remainder):
- b_value, = yield [("RV", [b])]
- result, = yield [("RDE", [a, b_value])]
- raise PrimitiveFinished(result)
- def dict_read_node(a, b, **remainder):
- result, = yield [("RDN", [a, b])]
- raise PrimitiveFinished(result)
- def dict_in(a, b, **remainder):
- b_value, = yield [("RV", [b])]
- value, = yield [("RD", [a, b_value])]
- is_in = value is not None
- result, = yield [("CNV", [is_in])]
- raise PrimitiveFinished(result)
- def dict_in_node(a, b, **remainder):
- value, = yield [("RDN", [a, b])]
- result, = yield [("CNV", [value is not None])]
- raise PrimitiveFinished(result)
- def dict_len(a, **remainder):
- outgoings, = yield [("RO", [a])]
- result, = yield [("CNV", [len(outgoings)])]
- raise PrimitiveFinished(result)
- def dict_keys(a, **remainder):
- keys, result = yield [("RDK", [a]), ("CN", [])]
- yield [("CE", [result, v]) for v in keys]
- raise PrimitiveFinished(result)
- def dict_reverse(a, b, **remainder):
- edges, = yield [("RO", [a])]
- expanded_edges, = yield [("RE", [i]) for i in edges]
- for i, edge in enumerate(expanded_edges):
- if b == edge[1]:
- # Found our edge: edges[i]
- outgoing, = yield [("RO", [edges[i]])]
- result, = yield [("RE", [outgoing[0]])]
- raise PrimitiveFinished(result[1])
- result, = yield [("CNV", ["(unknown: %s)" % b])]
- raise PrimitiveFinished(result)
- def is_physical_int(a, **remainder):
- t, = yield [("RV", [a])]
- result, = yield [("CNV", [isinstance(t, int) or isinstance(t, long)])]
- raise PrimitiveFinished(result)
- def is_physical_string(a, **remainder):
- t, = yield [("RV", [a])]
- result, = yield [("CNV", [isinstance(t, str) or isinstance(t, unicode)])]
- raise PrimitiveFinished(result)
- def is_physical_float(a, **remainder):
- t, = yield [("RV", [a])]
- result, = yield [("CNV", [isinstance(t, float)])]
- raise PrimitiveFinished(result)
- def is_physical_boolean(a, **remainder):
- t, = yield [("RV", [a])]
- result, = yield [("CNV", [isinstance(t, bool)])]
- raise PrimitiveFinished(result)
- def is_physical_action(a, **remainder):
- t, = yield [("RV", [a])]
- result, = yield [("CNV", [isinstance(t, dict) and t["value"] in ["if", "while", "assign", "call", "break", "continue", "return", "resolve", "access", "constant", "global", "declare"]])]
- raise PrimitiveFinished(result)
- def create_node(**remainder):
- result, = yield [("CN", [])]
- raise PrimitiveFinished(result)
- def create_edge(a, b, **remainder):
- result, = yield [("CE", [a, b])]
- raise PrimitiveFinished(result)
- def create_value(a, **remainder):
- a_value, = yield [("RV", [a])]
- result, = yield [("CNV", [a_value])]
- raise PrimitiveFinished(result)
- def read_nr_out(a, **remainder):
- outgoing, = yield [("RO", [a])]
- result, = yield [("CNV", [len(outgoing)])]
- raise PrimitiveFinished(result)
- def read_out(a, b, **remainder):
- outgoing, b_value = yield [("RO", [a]), ("RV", [b])]
- raise PrimitiveFinished(sorted(outgoing)[b_value])
- def read_nr_in(a, **remainder):
- incoming, = yield [("RI", [a])]
- result, = yield [("CNV", [len(incoming)])]
- raise PrimitiveFinished(result)
- def read_in(a, b, **remainder):
- incoming, b_value = yield [("RI", [a]), ("RV", [b])]
- raise PrimitiveFinished(sorted(incoming)[b_value])
- def read_edge_src(a, **remainder):
- result, = yield [("RE", [a])]
- raise PrimitiveFinished(result[0])
- def read_edge_dst(a, **remainder):
- result, = yield [("RE", [a])]
- raise PrimitiveFinished(result[1])
- def delete_element(a, **remainder):
- edge, = yield [("RE", [a])]
- if edge[0] is None:
- # Not an edge:
- yield [("DN", [a])]
- result, = yield [("CNV", [False])]
- raise PrimitiveFinished(result)
- else:
- yield [("DE", [a])]
- result, = yield [("CNV", [True])]
- raise PrimitiveFinished(result)
- def read_root(root, **remainder):
- raise PrimitiveFinished(root)
- def set_add(a, b, **remainder):
- yield [("CE", [a, b])]
- raise PrimitiveFinished(a)
- def set_pop(a, **remainder):
- outgoing, = yield [("RO", [a])]
- v, _ = yield [("RE", [outgoing[0]]), ("DE", [outgoing[0]])]
- raise PrimitiveFinished(v[1])
- def set_remove(a, b, **remainder):
- outgoing, b_value = yield [("RO", [a]), ("RV", [b])]
- elements = yield [("RE", [i]) for i in outgoing]
- values = yield [("RV", [i[1]]) for i in elements]
- yield [("DE", [identifier]) for identifier, edge in zip(outgoing, values) if edge == b_value]
- raise PrimitiveFinished(a)
- def set_remove_node(a, b, **remainder):
- outgoing, = yield [("RO", [a])]
- elements = yield [("RE", [i]) for i in outgoing]
- elements = [elements] if not isinstance(elements[0], list) else elements
- yield [("DE", [identifier]) for identifier, edge in zip(outgoing, elements) if edge[1] == b]
- raise PrimitiveFinished(a)
- def set_in(a, b, **remainder):
- outgoing, b_value = yield [("RO", [a]), ("RV", [b])]
- if outgoing:
- elements = yield [("RE", [i]) for i in outgoing]
- values = yield [("RV", [i[1]]) for i in elements]
- if b_value in [v for v in values]:
- result, = yield [("CNV", [True])]
- else:
- result, = yield [("CNV", [False])]
- else:
- result, = yield [("CNV", [False])]
- raise PrimitiveFinished(result)
- def set_in_node(a, b, **remainder):
- outgoing, = yield [("RO", [a])]
- if outgoing:
- elements = yield [("RE", [i]) for i in outgoing]
- if b in [v[1] for v in elements]:
- result, = yield [("CNV", [True])]
- else:
- result, = yield [("CNV", [False])]
- else:
- result, = yield [("CNV", [False])]
- raise PrimitiveFinished(result)
- def is_edge(a, **remainder):
- edge, = yield [("RE", [a])]
- result, = yield [("CNV", [edge[0] is not None])]
- raise PrimitiveFinished(result)
- #TODO deprecate
- def deserialize(a, root, **remainder):
- value, = yield [("RV", [a])]
- id_mappings = {}
- complex_primitives = frozenset(["if", "while", "assign", "call", "break", "continue", "return","resolve","access", "constant", "input", "output", "declare", "global"])
- for l in value.split("\n"):
- try:
- graph_type, constructor = l.split(None, 1)
- except:
- continue
- if graph_type == "N":
- # Node
- id_mappings[constructor], = yield [("CN", [])]
- elif graph_type == "V":
- # Node with Value
- name, temp = constructor.split("(", 1)
- string_value = temp[:-1]
- if string_value in complex_primitives:
- value = {"value": string_value}
- else:
- #TODO this is very dangerous!
- value = eval(string_value)
- id_mappings[name], = yield [("CNV", [value])]
- elif graph_type == "E":
- # Edge
- name, temp = constructor.split("(", 1)
- source, target = temp[:-1].split(",", 1)
- if target[0] == "?" and target not in id_mappings:
- hierarchy = target[1:].split("/")
- current, = yield [("RD", [root, "__hierarchy"])]
- for i in hierarchy:
- current, = yield [("RD", [current, i])]
- id_mappings[target] = current
- try:
- source = int(source)
- except:
- source = id_mappings[source]
- try:
- target = int(target)
- except:
- target = id_mappings[target]
- # Both nodes will normally be already present in the matching dictionary, so can just pass them along
- id_mappings[name], = yield [("CE", [source, target])]
- elif graph_type == "D":
- source, value, target = constructor.split(",",3)
- if value in complex_primitives:
- value = {"value": value}
- else:
- #TODO this is very dangerous!
- value = eval(value)
- if target[0] == "?" and target not in id_mappings:
- hierarchy = target[1:].split("/")
- current, = yield [("RD", [root, "__hierarchy"])]
- for i in hierarchy:
- current, = yield [("RD", [current, i])]
- id_mappings[target] = current
- try:
- source = int(source)
- except:
- source = id_mappings[source]
- try:
- target = int(target)
- except:
- target = id_mappings[target]
- yield [("CD", [source, value, target])]
- else:
- print("Unknown graph type: " + str(graph_type))
- raise PrimitiveFinished(id_mappings["auto_initial_IP"])
- def log(a, **remainder):
- a_value, = yield [("RV", [a])]
- print("== LOG == " + str(a_value))
- raise PrimitiveFinished(a)
- def read_taskroot(task_root, **remainder):
- raise PrimitiveFinished(task_root)
- def time(**remainder):
- import time
- a, = yield [("CNV", [time.time()])]
- raise PrimitiveFinished(a)
- def hash(a, **remainder):
- a_value, = yield [("RV", [a])]
- import hashlib
- b_value = hashlib.sha512(a_value).hexdigest()
- b, = yield [("CNV", [b_value])]
- raise PrimitiveFinished(b)
|