include "primitives.alh" include "conformance_scd.alh" include "library.alh" include "io.alh" include "modelling.alh" include "utils.alh" include "object_operations.alh" Element while_stack = ? Element variable_map = ? Element function construct_function_list(list : Element): String command Element result String main_function Boolean continue String prev_element String first_element Element model model = instantiate_model(import_node("models/ActionLanguage")) list = list_reverse(list) // Initialize variables prev_element = read_root() main_function = read_root() // Clear global variables while_stack = list_create() variable_map = dict_create() continue = True while (continue): command = list_pop_final(list) if (command == "global"): result = construct_global(model, list) elif (command == "funcdef"): result = construct_funcdef(model, list, False) elif (command == "mutable_funcdef"): result = construct_funcdef(model, list, True) else: log("ERROR (1): did not understand command " + cast_value(command)) output("ERROR: compiled code not understood: " + cast_value(command)) return read_root()! continue = list_pop_final(list) if (element_neq(prev_element, read_root())): create_al_link(model, "Statement_next", prev_element, result["start"], "next") else: first_element = result["start"] if (bool_and(element_eq(main_function, read_root()), command != "global")): // In case no main function is defined, it is the first defined function // This is mostly there to ensure backwards compatibility main_function = result["instruction"] prev_element = result["end"] if (value_eq(result["name"], "main")): // It was the function that we want to call main_function = result["instruction"] if (element_eq(main_function, read_root())): log("ERROR (2): no main function found") output("ERROR: no main function found") return read_root()! // Overwrite the main function with our declaration function prev_element = set_pop(allAssociationDestinations(model, main_function, "funcdef_body")) model_delete_element(model, set_pop(allOutgoingAssociationInstances(model, main_function, "funcdef_body"))) create_al_link(model, "funcdef_body", main_function, first_element, "body") create_al_link(model, "Statement_next", result["end"], prev_element, "next") instantiate_link(model, "initial_funcdef", "", instantiate_node(model, "Initial", ""), main_function) return model! Void function create_al_link(model : Element, linktype : String, source : String, target : String, dictname : String): instantiate_attribute(model, instantiate_link(model, linktype, "", source, target), "name", dictname) return! String function construct_global(model : Element, list : Element): String this_element String declared_element String op this_element = instantiate_value(model, "global", "", create_value(!global)) declared_element = instantiate_value(model, "String", "", create_value(list_pop_final(list))) create_al_link(model, "global_var", this_element, declared_element, "var") op = list_pop_final(list) if (op != "none"): // Defines String assign String resolve String value assign = instantiate_value(model, "assign", "", create_value(!assign)) create_al_link(model, "Statement_next", this_element, assign, "next") resolve = instantiate_value(model, "resolve", "", create_value(!resolve)) create_al_link(model, "assign_var", assign, resolve, "var") create_al_link(model, "resolve_var", resolve, declared_element, "var") if (op == "deref"): value = instantiate_value(model, "constant", "", create_value(!constant)) create_al_link(model, "constant_node", this_element, value, "node") elif (op == "empty"): value = instantiate_value(model, "call", "", create_value(!call)) String res String acc res = instantiate_value(model, "resolve", "", create_value(!resolve)) acc = instantiate_value(model, "access", "", create_value(!access)) create_al_link(model, "call_func", value, acc, "func") create_al_link(model, "access_var", acc, res, "var") create_al_link(model, "resolve_var", res, instantiate_value(model, "String", "", "create_node"), "var") elif (op == "const"): value = instantiate_value(model, "constant", "", create_value(!constant)) create_al_link(model, "constant_node", value, list_pop_final(list), "node") create_al_link(model, "assign_value", assign, value, "value") Element result result = dict_create() dict_add_fast(result, "name", "") dict_add_fast(result, "instruction", this_element) dict_add_fast(result, "start", this_element) dict_add_fast(result, "end", assign) return result! else: Element result result = dict_create() dict_add_fast(result, "name", "") dict_add_fast(result, "instruction", this_element) dict_add_fast(result, "start", this_element) dict_add_fast(result, "end", this_element) return result! String function construct_funcdef(model : Element, list : Element, mutable : Boolean): String assign String resolve String constant String formal String func String params String declare String name declare = instantiate_value(model, "global", "", create_value(!global)) assign = instantiate_value(model, "assign", "", create_value(!assign)) resolve = instantiate_value(model, "resolve", "", create_value(!resolve)) constant = instantiate_value(model, "constant", "", create_value(!constant)) name = list_pop_final(list) if (dict_in(variable_map, name)): formal = dict_read(variable_map, name) else: formal = instantiate_value(model, "String", "", name) func = instantiate_node(model, "funcdef", "") params = instantiate_node(model, "param_dict", "") create_al_link(model, "global_var", declare, formal, "var") create_al_link(model, "Statement_next", declare, assign, "next") create_al_link(model, "assign_var", assign, resolve, "var") create_al_link(model, "assign_value", assign, constant, "value") create_al_link(model, "resolve_var", resolve, formal, "var") create_al_link(model, "constant_node", constant, func, "node") create_al_link(model, "funcdef_params", func, params, "params") if (mutable): create_al_link(model, "funcdef_mutable", func, instantiate_node(model, "Element", ""), "mutable") Integer nrParams nrParams = list_pop_final(list) Integer counter counter = 0 Element param String arg_names_decl arg_names_decl = "abcdefghijklmnopqrstuvwxyz" while (counter < nrParams): param = instantiate_node(model, "Element", "") create_al_link(model, "param_dict_link", params, param, string_get(arg_names_decl, counter)) dict_add_fast(variable_map, list_pop_final(list), param) // Output each parameter in turn counter = counter + 1 // Now add the body create_al_link(model, "funcdef_body", func, construct_unknown(model, list), "body") Element result result = dict_create() dict_add_fast(result, "name", name) dict_add_fast(result, "instruction", func) dict_add_fast(result, "start", declare) dict_add_fast(result, "end", assign) return result! Element function construct_unknown(model : Element, list : Element): String elem Element new_model Element new_model_model elem = list_pop_final(list) if (elem == "if"): return construct_if(model, list)! elif (elem == "while"): return construct_while(model, list)! elif (elem == "access"): return construct_access(model, list)! elif (elem == "resolve"): return construct_resolve(model, list)! elif (elem == "assign"): return construct_assign(model, list)! elif (elem == "call"): return construct_call(model, list)! elif (elem == "return"): return construct_return(model, list)! elif (elem == "const"): return construct_const(model, list)! elif (elem == "declare"): return construct_declare(model, list)! elif (elem == "output"): return construct_output(model, list)! elif (elem == "input"): return construct_input(model, list)! elif (elem == "deref"): return construct_deref(model, list)! elif (elem == "break"): return construct_break(model, list)! elif (elem == "continue"): return construct_continue(model, list)! else: log("ERROR (2): did not understand command " + cast_value(elem)) output("ERROR: compiled code not understood: " + cast_value(elem)) return read_root()! String function construct_if(model : Element, list : Element): String this_element this_element = instantiate_value(model, "if", "", create_value(!if)) create_al_link(model, "if_cond", this_element, construct_unknown(model, list), "cond") create_al_link(model, "if_then", this_element, construct_unknown(model, list), "then") if (list_pop_final(list)): create_al_link(model, "if_else", this_element, construct_unknown(model, list), "else") if (list_pop_final(list)): create_al_link(model, "Statement_next", this_element, construct_unknown(model, list), "next") return this_element! String function construct_while(model : Element, list : Element): String this_element this_element = instantiate_value(model, "while", "", create_value(!while)) create_al_link(model, "while_cond", this_element, construct_unknown(model, list), "cond") list_append(while_stack, this_element) create_al_link(model, "while_body", this_element, construct_unknown(model, list), "body") list_delete(while_stack, list_len(while_stack) - 1) if (list_pop_final(list)): create_al_link(model, "Statement_next", this_element, construct_unknown(model, list), "next") return this_element! String function construct_access(model : Element, list : Element): String this_element this_element = instantiate_value(model, "access", "", create_value(!access)) create_al_link(model, "access_var", this_element, construct_unknown(model, list), "var") return this_element! String function construct_resolve(model : Element, list : Element): String this_element Element linked_element String name this_element = instantiate_value(model, "resolve", "", create_value(!resolve)) name = list_pop_final(list) // TODO might have to check if this is to be added if dict_in(variable_map, name): linked_element = variable_map[name] else: linked_element = instantiate_value(model, "String", "", name) create_al_link(model, "resolve_var", this_element, linked_element, "var") return this_element! String function construct_assign(model : Element, list : Element): String this_element this_element = instantiate_value(model, "assign", "", create_value(!assign)) create_al_link(model, "assign_var", this_element, construct_unknown(model, list), "var") create_al_link(model, "assign_value", this_element, construct_unknown(model, list), "value") if (list_pop_final(list)): create_al_link(model, "Statement_next", this_element, construct_unknown(model, list), "next") return this_element! String function construct_call(model : Element, list : Element): String this_element this_element = instantiate_value(model, "call", "", create_value(!call)) create_al_link(model, "call_func", this_element, construct_unknown(model, list), "func") Integer nrParams nrParams = list_pop_final(list) Integer counter counter = 0 Element param Element prev_param String arg_names_call arg_names_call = "abcdefghijklmnopqrstuvwxyz" while (counter < nrParams): param = instantiate_node(model, "param", "") create_al_link(model, "param_name", param, instantiate_value(model, "String", "", string_get(arg_names_call, counter)), "name") create_al_link(model, "param_value", param, construct_unknown(model, list), "value") if (counter == 0): create_al_link(model, "call_params", this_element, param, "params") else: create_al_link(model, "param_next_param", prev_param, param, "next_param") prev_param = param counter = counter + 1 if (nrParams > 0): create_al_link(model, "call_last_param", this_element, prev_param, "last_param") if (list_pop_final(list)): create_al_link(model, "Statement_next", this_element, construct_unknown(model, list), "next") return this_element! String function construct_return(model : Element, list : Element): if (list_pop_final(list)): String this_element this_element = instantiate_value(model, "return", "", create_value(!return)) create_al_link(model, "return_value", this_element, construct_unknown(model, list), "value") return this_element! else: return instantiate_value(model, "return", "", create_value(!return))! String function construct_const(model : Element, list : Element): String this_element this_element = instantiate_value(model, "constant", "", create_value(!constant)) create_al_link(model, "constant_node", this_element, instantiate_value(model, "Element", "", list_pop_final(list)), "node") return this_element! String function construct_declare(model : Element, list : Element): String this_element Element declared_element String name this_element = instantiate_value(model, "declare", "", create_value(!declare)) declared_element = instantiate_node(model, "Element", "") create_al_link(model, "declare_var", this_element, declared_element, "var") name = list_pop_final(list) dict_add_fast(variable_map, name, declared_element) // Assign value String op op = list_pop_final(list) if (op != "none"): String assign String resolve String value assign = instantiate_value(model, "assign", "", create_value(!assign)) create_al_link(model, "Statement_next", this_element, assign, "next") resolve = instantiate_value(model, "resolve", "", create_value(!resolve)) create_al_link(model, "assign_var", assign, resolve, "var") create_al_link(model, "resolve_var", resolve, declared_element, "var") if (op == "deref"): value = instantiate_value(model, "constant", "", create_value(!constant)) create_al_link(model, "constant_node", value, reuse_element(model, "Element", "", import_node(list_pop_final(list))), "node") elif (op == "empty"): value = instantiate_value(model, "call", "", create_value(!call)) Element res Element acc res = instantiate_value(model, "resolve", "", create_value(!resolve)) acc = instantiate_value(model, "access", "", create_value(!access)) create_al_link(model, "call_func", value, acc, "func") create_al_link(model, "access_var", acc, res, "var") create_al_link(model, "resolve_var", res, instantiate_value(model, "String", "", "create_node"), "var") elif (op == "const"): value = instantiate_value(model, "constant", "", create_value(!constant)) create_al_link(model, "constant_node", value, instantiate_value(model, "Element", "", list_pop_final(list)), "node") create_al_link(model, "assign_value", assign, value, "value") if (list_pop_final(list)): create_al_link(model, "Statement_next", assign, construct_unknown(model, list), "next") else: if (list_pop_final(list)): create_al_link(model, "Statement_next", this_element, construct_unknown(model, list), "next") return this_element! String function construct_input(model : Element, list : Element): return instantiate_value(model, "input", "", create_value(!input))! String function construct_output(model : Element, list : Element): String this_element this_element = instantiate_value(model, "output", "", create_value(!output)) create_al_link(model, "output_value", this_element, construct_unknown(model, list), "value") if (list_pop_final(list)): create_al_link(model, "Statement_next", this_element, construct_unknown(model, list), "next") return this_element! String function construct_deref(model : Element, list : Element): String this_element this_element = instantiate_value(model, "constant", "", create_value(!constant)) create_al_link(model, "constant_node", this_element, reuse_element(model, "Element", "", import_node(list_pop_final(list))), "node") return this_element! String function construct_break(model : Element, list : Element): String this_element this_element = instantiate_value(model, "break", "", create_value(!break)) create_al_link(model, "break_while", this_element, while_stack[list_len(while_stack) - 1], "while") return this_element! String function construct_continue(model : Element, list : Element): String this_element this_element = instantiate_value(model, "continue", "", create_value(!continue)) create_al_link(model, "continue_while", this_element, while_stack[list_len(while_stack) - 1], "while") return this_element!