include "primitives.alh" Boolean function value_neq(a : Element, b : Element): return bool_not(value_eq(a, b))! Boolean function element_neq(a : Element, b : Element): return bool_not(element_eq(a, b))! Integer function dict_len(a : Element): return read_nr_out(a)! Integer function list_len(a : Element): return read_nr_out(a)! Integer function set_len(a : Element): return read_nr_out(a)! Float function float_neg(a : Float): return float_subtraction(0, a)! Integer function integer_neg(a : Integer): return integer_subtraction(0, a)! Element function list_read(a : Element, b : Integer): return dict_read(a, b)! Element function list_append(a : Element, b : Element): dict_add(a, integer_addition(list_len(a), 1), b) return a! Element function set_add(a : Element, b : Element): if (bool_not(set_in(a, b))): create_edge(a, b) return a! Element function set_pop(a : Element): if (integer_gt(set_len(a), 0)): Element edge edge = read_out(a, 0) edge = read_edge_dst(edge) delete_element(edge) return edge! else: return read_root() Element function set_read(a : Element): if (integer_gt(set_len(a), 0)): return read_edge_dst(read_out(a, 0))! else: return read_root() Void function sleep(a : Float): __sleep(a, False) return! Void function interruptable_sleep(a : Float): __sleep(a, True) return! Element function exec(first_instr : Element): // This does very ugly things, so beware! // Basically, we dynamically construct an if True condition with as body the provided instructions // after the if conditional, we append a return of an empty element, as we need a return at the end // returns in the code are therefore allowed (and will be the return value), but not necessarily Element n Element exec_if Element exec_const_true Element exec_return n = create_node() exec_if = create_value(!if) exec_const_true = create_value(!constant) exec_return = create_value(!return) dict_add(n, "params", create_node()) dict_add(exec_const_true, "node", create_value(True)) dict_add(exec_if, "cond", exec_const_true) dict_add(exec_if, "then", first_instr) dict_add(n, "body", exec_if) dict_add(exec_if, "next", exec_return) return n()! Boolean function string_startswith(a: String, b: String): Integer i i = 0 if (string_len(b) > string_len(a)): return False! while (i < string_len(b)): if (string_get(a, i) != string_get(b, i)): return False! i = i + 1 return True! Boolean function has_value(a: Element): return bool_or(bool_or(bool_or(is_physical_action, is_physical_int(a)), is_physical_float(a)), bool_or(is_physical_string(a), is_physical_boolean(a)))! Boolean function float_gte(a: Float, b: Float): return bool_or(float_gt(a, b), value_eq(a, b))! Boolean function float_lte(a: Float, b: Float): return bool_or(float_lt(a, b), value_eq(a, b))! Boolean function integer_lte(a: Integer, b: Integer): return bool_or(integer_lt(a, b), value_eq(a, b))! Boolean function integer_gte(a: Integer, b: Integer): return bool_or(integer_gt(a, b), value_eq(a, b))! String function string_substr(a: String, b: Integer, c: Integer): String result Integer i // First handle corner cases! // If the string is too short for b to even start, return empty if (b > string_len(a)): return ""! // If the part we want to snip is negative, we return empty if (b > c): return ""! i = 0 result = "" while (i < string_len(a)): if (bool_and(i >= b, i <= c)): result = result + string_get(a, i) if (i > c): return result! i = i + 1 return result! Element function resolve(name : String): // Could directly access it through introspection // But seems safer to create some code and execute it... Element task_root task_root = read_taskroot() task_root = task_root["globals"][name]["value"] return task_root! Integer function integer_modulo(a : Integer, b : Integer): return a - b * (a / b)! Boolean function has_input(): return dict_in(dict_read(read_taskroot(), "input"), "value")! Element function list_pop(lst : Element, index : Integer): Element v v = list_read(lst, index) list_delete(lst, index) return v! Element function set_copy(a : Element): Element b Integer i Integer count b = create_node() i = 0 count = read_nr_out(a) while (i < count): set_add(b, read_edge_dst(read_out(a, i))) i = i + 1 return b! String function set_to_string(s : Element): String result Integer i result = "{" i = 0 while (i < read_nr_out(s)): result = result + cast_v2s(read_edge_dst(read_out(s, i))) result = result + ", " i = i + 1 result = result + "}" return result! String function list_to_string(s : Element): String result Integer i result = "[" i = 0 while (i < read_nr_out(s)): result = result + cast_v2s(dict_read(s, i)) result = result + ", " i = i + 1 result = result + "]" return result! Element function create_tuple(a : Element, b : Element): Element tuple tuple = create_node() list_append(tuple, a) list_append(tuple, b) return tuple! String function dict_to_string(d : Element): String result Element keys Element key result = "{" keys = dict_keys(d) while (read_nr_out(keys) > 0): key = set_pop(keys) result = result + cast_v2s(key) result = result + ": " result = result + cast_v2s(dict_read_node(d, key)) result = result + ", " result = result + "}" return result! Element function set_overlap(sa : Element, sb : Element): Element result Integer i if (read_nr_out(sa) > read_nr_out(sb)): // Pick the smallest set to iterate over, so switch if sa is not the smallest result = sa sa = sb sb = result result = create_node() i = 0 // Iterate over each element of sa and only add it to the result if it is also in sb while (i < read_nr_out(sa)): if (set_in(sb, read_edge_dst(read_out(sa, i)))): // Shared between both set_add(result, read_edge_dst(read_out(sa, i))) i = i + 1 return result! Boolean function set_equality(sa : Element, sb : Element): if (read_nr_out(sa) != read_nr_out(sb)): return False! Integer i i = 0 while (i < read_nr_out(sa)): if (set_in(sb, read_edge_dst(read_out(sa, i)))): // Shared between both, so all is fine i = i + 1 else: // Not shared return False! return True! Boolean function dict_eq(da : Element, db : Element): if (bool_not(set_equality(dict_keys(da), dict_keys(db)))): // They don't even share the same keys return False! Element keys Element key keys = dict_keys(da) while (read_nr_out(keys) > 0): key = set_pop(keys) if (value_neq(da[key], db[key])): // Value that is not equal return False! return True! Element function dict_copy(d : Element): String result Element keys Element key result = create_node() keys = dict_keys(d) while (read_nr_out(keys) > 0): key = set_pop(keys) dict_add_fast(result, key, dict_read_node(d, key)) return result! Element function set_to_list(s : Element): Element result Element tmp result = create_node() tmp = set_copy(s) while (read_nr_out(tmp) > 0): list_append(result, set_pop(tmp)) return result! Void function dict_overwrite(d : Element, key : Element, value : Element): if (dict_in(d, key)): dict_delete(d, key) if (dict_in_node(d, key)): dict_delete_node(d, key) dict_add(d, key, value) return ! Void function set_merge(a : Element, b : Element): b = set_copy(b) while (read_nr_out(b) > 0): set_add(a, set_pop(b)) return! Element function make_reverse_dictionary(dict : Element): Element keys Element reverse String key String value reverse = create_node() keys = dict_keys(dict) while (read_nr_out(keys) > 0): key = set_pop(keys) value = cast_id2s(dict[key]) if (dict_in(reverse, value)): dict_delete(reverse, value) dict_add(reverse, value, key) return reverse!