Quellcode durchsuchen

Merge branch 'yentl' of msdl.uantwerpen.be:yentl/modelverse into yentl

Yentl Van Tendeloo vor 9 Jahren
Ursprung
Commit
a1b8822697

+ 0 - 1
bootstrap/bootstrap.py

@@ -67,7 +67,6 @@ def bootstrap():
                     "dict_in": ["Boolean", "Element", "Element"],
                     "dict_in_node": ["Boolean", "Element", "Element"],
                     "dict_keys": ["Element", "Element"],
-                    "dict_reverse": ["Element", "Element", "Element"],
                     "set_add": ["Element", "Element", "Element"],
                     "set_pop": ["Element", "Element"],
                     "set_remove": ["Element", "Element", "Element"],

+ 63 - 35
bootstrap/conformance_scd.alc

@@ -4,6 +4,21 @@ include "object_operations.alh"
 include "constructors.alh"
 include "modelling.alh"
 
+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
+
 Boolean function is_direct_instance(model : Element, instance : String, type : String):
 	// Just check whether or not the type mapping specifies the type as the type of the instance
 	return element_eq(dict_read_node(model["type_mapping"], model["model"][instance]), model["metamodel"]["model"][type])
@@ -49,6 +64,43 @@ Boolean function is_nominal_subtype(metamodel : Element, subclass : String, supe
 	
 	return False
 
+Element function precompute_cardinalities(model : Element):
+	Integer slc
+	Integer suc
+	Integer tlc
+	Integer tuc
+	String key
+	Element tmp_dict
+	Element cardinalities
+	Element keys
+	Element metamodel
+
+	metamodel = model["metamodel"]
+	keys = allInstances(metamodel, "Association")
+
+	cardinalities = create_node()
+	while (0 < list_len(keys)):
+		key = set_pop(keys)
+		tmp_dict = create_node()
+		slc = read_attribute(metamodel, key, "source_lower_cardinality")
+		suc = read_attribute(metamodel, key, "source_upper_cardinality")
+		tlc = read_attribute(metamodel, key, "target_lower_cardinality")
+		tuc = read_attribute(metamodel, key, "target_upper_cardinality")
+
+		if (element_neq(slc, read_root())):
+			dict_add(tmp_dict, "slc", slc)
+		if (element_neq(suc, read_root())):
+			dict_add(tmp_dict, "suc", suc)
+		if (element_neq(tlc, read_root())):
+			dict_add(tmp_dict, "tlc", tlc)
+		if (element_neq(tuc, read_root())):
+			dict_add(tmp_dict, "tuc", tuc)
+
+		if (list_len(tmp_dict) > 0):
+			dict_add(cardinalities, key, tmp_dict)
+
+	return cardinalities
+
 String function conformance_scd(model : Element):
 	// Initialization
 	Element keys
@@ -65,7 +117,7 @@ String function conformance_scd(model : Element):
 	Element cardinalities
 	Element scd
 	Integer instances
-
+	String type_name
 	Element spo_cache
 	Element spi_cache
 
@@ -76,46 +128,19 @@ String function conformance_scd(model : Element):
 	scd = import_node("models/SimpleClassDiagrams")
 	metamodel = model["metamodel"]
 	typing = model["type_mapping"]
-	cardinalities = create_node()
+
 
 	// Create dictionary with all associations and allowed cardinalities
 	if (list_len(model["model"]) > 0):
-		Integer slc
-		Integer suc
-		Integer tlc
-		Integer tuc
-		String key
-		Element tmp_dict
-		String type_name
-
-		keys = allInstances(metamodel, "Association")
-		while (0 < list_len(keys)):
-			key = set_pop(keys)
-			tmp_dict = create_node()
-			slc = read_attribute(metamodel, key, "source_lower_cardinality")
-			suc = read_attribute(metamodel, key, "source_upper_cardinality")
-			tlc = read_attribute(metamodel, key, "target_lower_cardinality")
-			tuc = read_attribute(metamodel, key, "target_upper_cardinality")
-
-			if (element_neq(slc, read_root())):
-				dict_add(tmp_dict, "slc", slc)
-			if (element_neq(suc, read_root())):
-				dict_add(tmp_dict, "suc", suc)
-			if (element_neq(tlc, read_root())):
-				dict_add(tmp_dict, "tlc", tlc)
-			if (element_neq(tuc, read_root())):
-				dict_add(tmp_dict, "tuc", tuc)
-
-			if (list_len(tmp_dict) > 0):
-				dict_add(cardinalities, key, tmp_dict)
+		cardinalities = precompute_cardinalities(model)
 
 		// Iterate over each element of the model, finding out whether everything is fine
 		keys = dict_keys(model["model"])
 		while (0 < list_len(keys)):
 			model_name = set_pop(keys)
-			log("Check " + model_name)
 			element = model["model"][model_name]
 			type_name = reverseKeyLookup(metamodel["model"], dict_read_node(typing, element))
+			log((("Check " + model_name) + " : ") + type_name)
 
 			if (bool_not(dict_in_node(typing, element))):
 				return "Model has no type specified: " + model_name
@@ -123,8 +148,9 @@ String function conformance_scd(model : Element):
 			if (bool_not(set_in_node(metamodel["model"], dict_read_node(typing, element)))):
 				return "Type of element not in specified metamodel: " + model_name
 
-			if (bool_not(is_nominal_instance(model, model_name, type_name))):
-				return "Element is not an instance of its specified type: " + model_name
+			// This is true by definition of is_nominal_instance
+			//if (bool_not(is_nominal_instance(model, model_name, type_name))):
+			//	return "Element is not an instance of its specified type: " + model_name
 
 			if (is_edge(element)):
 				src_model = reverseKeyLookup(model["model"], read_edge_src(element))
@@ -146,7 +172,8 @@ String function conformance_scd(model : Element):
 			// First the incoming, so we are at B in the above figure
 			if (bool_not(dict_in(spo_cache, type_name))):
 				dict_add(spo_cache, type_name, selectPossibleOutgoing(metamodel, type_name, dict_keys(cardinalities)))
-			check_list = spo_cache[type_name]
+
+			check_list = set_copy(spo_cache[type_name])
 			while (0 < list_len(check_list)):
 				check_type = set_pop(check_list)
 				if (dict_in(cardinalities, check_type)):
@@ -171,7 +198,8 @@ String function conformance_scd(model : Element):
 			// Identical, but for outgoing, and thus for A in the figure
 			if (bool_not(dict_in(spi_cache, type_name))):
 				dict_add(spi_cache, type_name, selectPossibleIncoming(metamodel, type_name, dict_keys(cardinalities)))
-			check_list = spi_cache[type_name]
+
+			check_list = set_copy(spi_cache[type_name])
 			while (0 < list_len(check_list)):
 				check_type = set_pop(check_list)
 				if (dict_in(cardinalities, check_type)):

+ 1 - 0
bootstrap/constructors.alc

@@ -84,6 +84,7 @@ Action function construct_top_funcdef():
 	while (counter < nrParams):
 		param = create_node()
 		dict_add(params, string_get(arg_names_decl, counter), param)
+		dict_add(param, "name", string_get(arg_names_decl, counter))
 		output(param)
 		// Output each parameter in turn
 		counter = counter + 1

+ 4 - 6
bootstrap/metamodels.alc

@@ -323,6 +323,10 @@ Element function initialize_SCD(location : String):
 	instantiate_attribute(scd, "call_params", "target_upper_cardinality", 1)
 	instantiate_attribute(scd, "call_last_param", "target_upper_cardinality", 1)
 
+	// Now still allow for constraints on classes
+	instantiate_link(scd, "Association", "constraint", "Class", "funcdef")
+	instantiate_attribute(scd, "constraint", "name", "constraint")
+
 	// Add constraints to all primitive classes
 	//add_constraint(scd, "if", constraint_if)
 	//add_constraint(scd, "while", constraint_while)
@@ -339,14 +343,8 @@ Element function initialize_SCD(location : String):
 	//add_constraint(scd, "resolve", constraint_resolve)
 	//add_constraint(scd, "call", constraint_call)
 
-	// Now still allow for constraints on classes
-	instantiate_link(scd, "Association", "constraint", "Class", "funcdef")
-	instantiate_attribute(scd, "constraint", "name", "constraint")
-
 	// And add some, to enforce correct physical types
-	log("Add Natural constraint")
 	add_constraint(scd, "Natural", constraint_natural)
-	log("Add String constraint")
 	add_constraint(scd, "String", constraint_string)
 
 	// Finally done, so export!

+ 21 - 38
bootstrap/object_operations.alc

@@ -66,50 +66,36 @@ Element function selectPossibleOutgoing(model : Element, source : String, limit_
 
 Element function allOutgoingAssociationInstances(model : Element, source_name : String, assoc_name : String):
 	// Read out all outgoing edges of the model and select those that are typed by the specified association
-	Integer nr_out
-	Integer i
-	Element out
-	String out_name
+	Element assocs
+	String assoc
 	Element result
+	Element source
 
-	result = create_node()
-	nr_out = read_nr_out(model["model"][source_name])
-	i = 0
-
-	log("Searching for instances of " + assoc_name)
-	log("  starting from " + source_name)
-	while (i < nr_out):
-		out = read_out(model["model"][source_name], i)
-		if (set_in_node(model["model"], out)):
-			out_name = reverseKeyLookup(model["model"], out)
-			log("     checking " + out_name)
-			log("        typed by: " + reverseKeyLookup(model["metamodel"]["model"], dict_read_node(model["type_mapping"], out)))
-			if (is_nominal_instance(model, out_name, assoc_name)):
-				set_add(result, out_name)
-		else:
-			log("     skipping link typed by: " + reverseKeyLookup(model["metamodel"]["model"], dict_read_node(model["type_mapping"], out)))
-		i = i + 1
+	assocs = allInstances(model, assoc_name)
+	source = model["model"][source_name]
 
+	result = create_node()
+	while (0 < list_len(assocs)):
+		assoc = set_pop(assocs)
+		if (element_eq(source, read_edge_src(model["model"][assoc]))):
+			set_add(result, assoc)
 	return result
 
 Element function allIncomingAssociationInstances(model : Element, target_name : String, assoc_name : String):
 	// Read out all outgoing edges of the model and select those that are typed by the specified association
-	Integer nr_in
-	Integer i
-	Element in
-	String in_name
+	Element assocs
+	String assoc
 	Element result
-	result = create_node()
-	nr_in = read_nr_in(model["model"][target_name])
-	i = 0
-	while (i < nr_in):
-		in = read_in(model["model"][target_name], i)
-		if (set_in_node(model["model"], in)):
-			in_name = reverseKeyLookup(model["model"], in)
-			if (is_nominal_instance(model, in_name, assoc_name)):
-				set_add(result, in_name)
-		i = i + 1
+	Element target
 
+	assocs = allInstances(model, assoc_name)
+	target = model["model"][target_name]
+
+	result = create_node()
+	while (0 < list_len(assocs)):
+		assoc = set_pop(assocs)
+		if (element_eq(target, read_edge_dst(model["model"][assoc]))):
+			set_add(result, assoc)
 	return result
 
 Element function getAttributeList(model : Element, element : String):
@@ -155,9 +141,6 @@ Element function getInstantiatableAttributes(model : Element, element : String):
 
 // TODO Utility functions!
 String function reverseKeyLookup(dict : Element, element : Element):
-	return dict_reverse(dict, element)
-
-	// TODO this code makes everything very inefficient; wait to enable this for once the compilation is implemented
 	Element elements
 	String name
 

+ 0 - 1
bootstrap/primitives.alc

@@ -78,7 +78,6 @@ Boolean function is_physical_float(a: Element) = ?primitives/is_physical_float
 Boolean function is_physical_string(a: Element) = ?primitives/is_physical_string
 Boolean function is_physical_boolean(a: Element) = ?primitives/is_physical_boolean
 Boolean function is_physical_action(a: Element) = ?primitives/is_physical_action
-Element function dict_reverse(a: Element, b: Element) = ?primitives/dict_reverse
 
 Element function exec(first_instr : Element):
 	// This does very ugly things, so beware!

+ 24 - 0
integration/test_constructors_models.py

@@ -133,6 +133,30 @@ action_language = [
         '"instantiate_link"', 1, '"Association"', '"call_last_param"', '"call"', '"param"',
         '"instantiate_attribute"', 1, '"call_last_param"', '"name"', '"last_param"',
 
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"statement_next"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"if_cond"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"if_then"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"if_else"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"while_cond"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"while_body"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"assign_var"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"assign_value"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"break_while"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"continue_while"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"return_value"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"resolve_var"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"access_var"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"constant_node"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"output_node"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"global_var"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"param_name"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"param_value"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"param_next_param"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"funcdef_body"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"call_func"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"call_params"', '"dict_link"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"call_last_param"', '"dict_link"',
+
         '"instantiate_link"', 1, '"Association"', '"constraint"', '"Class"', '"funcdef"',
         '"instantiate_attribute"', 1, '"constraint"', '"name"', '"constraint"',
         '"exit"',

+ 11 - 0
integration/test_pn_interface.py

@@ -381,3 +381,14 @@ class TestPetrinetInterface(unittest.TestCase):
             attr_add + prompt + \
             ["OK"] + prompt,
             mode))
+
+    def test_po_pn_interface_verify_PN_OK(self):
+        self.pn_interface_verify_PN_OK("PO")
+
+    def test_co_pn_interface_verify_PN_OK(self):
+        self.pn_interface_verify_PN_OK("CO")
+
+    def pn_interface_verify_PN_OK(self, mode):
+        self.assertTrue(run_file(all_files,
+            ["load", "PetriNets", "verify"],
+            init + load + loaded + ["OK"], mode))

+ 2 - 2
integration/utils.py

@@ -67,7 +67,7 @@ def flush_data(address, data):
 def compile_file(address, mod_filename, filename, mode, proc):
     # Load in the file required
     try:
-        timeout_val = 120
+        timeout_val = 240
         import random
         username = str(random.random())
         while 1:
@@ -157,7 +157,7 @@ def run_file(files, parameters, expected, mode):
         for e in expected:
             c = len(e) if isinstance(e, set) else 1
             for _ in range(c):
-                val = urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "username": username})), timeout=120).read()
+                val = urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "username": username})), timeout=240).read()
 
                 if proc.returncode is not None:
                     # Modelverse has already terminated, which isn't a good sign!

+ 3 - 0
interface/HUTN/hutn_compiler/primitives_visitor.py

@@ -360,6 +360,9 @@ class PrimitivesVisitor(Visitor):
                 for i in range(len(parameters)):
                     n = self.get_primitive(parameters[i])
                     self.dict(ps, string.ascii_lowercase[i], n)
+
+                    # Add the name in case we want to pre-compile in the MvK
+                    self.dict(n, "name", self.value('"%s"' % string.ascii_lowercase[i]))
             b = self.get_primitive(func_body)
             self.dict(vf, "body", b)
         else:

+ 0 - 1
interface/HUTN/includes/primitives.alh

@@ -87,6 +87,5 @@ Boolean function is_physical_string(a : Element)
 Boolean function is_physical_action(a : Element)
 Boolean function is_physical_boolean(a : Element)
 Boolean function has_value(a : Element)
-Element function dict_reverse(a : Element, b : Element)
 
 Element function exec(a : Element)

+ 74 - 72
interface/HUTN/test/graph_compilation_action_language/expected/factorial

@@ -46,46 +46,47 @@ V auto_49(access)
 V auto_5(assign)
 V auto_50(resolve)
 N auto_51
-V auto_52(return)
-V auto_53(call)
-V auto_54(access)
-V auto_55(resolve)
-N auto_56
-V auto_57("b")
-V auto_58(call)
-V auto_59(access)
+V auto_52("a")
+V auto_53(return)
+V auto_54(call)
+V auto_55(access)
+V auto_56(resolve)
+N auto_57
+V auto_58("b")
+V auto_59(call)
 V auto_6(global)
-V auto_60(resolve)
-N auto_61
-V auto_62("a")
-V auto_63(call)
-V auto_64(access)
-V auto_65(resolve)
-N auto_66
-V auto_67("b")
-V auto_68(constant)
-V auto_69(1)
+V auto_60(access)
+V auto_61(resolve)
+N auto_62
+V auto_63("a")
+V auto_64(call)
+V auto_65(access)
+V auto_66(resolve)
+N auto_67
+V auto_68("b")
+V auto_69(constant)
 V auto_7(assign)
-N auto_70
-V auto_71("a")
-V auto_72(access)
-V auto_73(resolve)
-N auto_74
-V auto_75("a")
-V auto_76(access)
-V auto_77(resolve)
-V auto_78(return)
-V auto_79(constant)
+V auto_70(1)
+N auto_71
+V auto_72("a")
+V auto_73(access)
+V auto_74(resolve)
+N auto_75
+V auto_76("a")
+V auto_77(access)
+V auto_78(resolve)
+V auto_79(return)
 V auto_8(global)
-V auto_80(1)
-N auto_81
-V auto_82(resolve)
+V auto_80(constant)
+V auto_81(1)
+N auto_82
+V auto_83(resolve)
 V auto_9(assign)
 D auto_initial_IP,"next",auto_1
 D auto_initial_IP,"var",auto_29
 D auto_1,"next",auto_2
 D auto_1,"value",auto_37
-D auto_1,"var",auto_82
+D auto_1,"var",auto_83
 D auto_10,"node",auto_11
 D auto_12,"var",auto_13
 D auto_14,"node",auto_15
@@ -113,10 +114,10 @@ D auto_33,"node",auto_34
 D auto_35,"var",auto_36
 D auto_37,"node",auto_38
 D auto_38,"body",auto_39
-D auto_38,"params",auto_81
+D auto_38,"params",auto_82
 D auto_39,"cond",auto_40
-D auto_39,"else",auto_52
-D auto_39,"then",auto_78
+D auto_39,"else",auto_53
+D auto_39,"then",auto_79
 D auto_4,"next",auto_5
 D auto_4,"var",auto_21
 D auto_40,"func",auto_41
@@ -135,49 +136,50 @@ D auto_5,"next",auto_6
 D auto_5,"value",auto_18
 D auto_5,"var",auto_20
 D auto_50,"var",auto_51
-D auto_52,"value",auto_53
-D auto_53,"func",auto_54
-D auto_53,"last_param",auto_56
-D auto_53,"params",auto_74
-D auto_54,"var",auto_55
-D auto_55,"var",auto_21
-D auto_56,"name",auto_57
-D auto_56,"value",auto_58
-D auto_58,"func",auto_59
-D auto_58,"last_param",auto_61
-D auto_58,"params",auto_61
-D auto_59,"var",auto_60
+D auto_51,"name",auto_52
+D auto_53,"value",auto_54
+D auto_54,"func",auto_55
+D auto_54,"last_param",auto_57
+D auto_54,"params",auto_75
+D auto_55,"var",auto_56
+D auto_56,"var",auto_21
+D auto_57,"name",auto_58
+D auto_57,"value",auto_59
+D auto_59,"func",auto_60
+D auto_59,"last_param",auto_62
+D auto_59,"params",auto_62
 D auto_6,"next",auto_7
 D auto_6,"var",auto_17
-D auto_60,"var",auto_29
-D auto_61,"name",auto_62
-D auto_61,"value",auto_63
-D auto_63,"func",auto_64
-D auto_63,"last_param",auto_66
-D auto_63,"params",auto_70
-D auto_64,"var",auto_65
-D auto_65,"var",auto_13
-D auto_66,"name",auto_67
-D auto_66,"value",auto_68
-D auto_68,"node",auto_69
+D auto_60,"var",auto_61
+D auto_61,"var",auto_29
+D auto_62,"name",auto_63
+D auto_62,"value",auto_64
+D auto_64,"func",auto_65
+D auto_64,"last_param",auto_67
+D auto_64,"params",auto_71
+D auto_65,"var",auto_66
+D auto_66,"var",auto_13
+D auto_67,"name",auto_68
+D auto_67,"value",auto_69
+D auto_69,"node",auto_70
 D auto_7,"next",auto_8
 D auto_7,"value",auto_14
 D auto_7,"var",auto_16
-D auto_70,"name",auto_71
-D auto_70,"next_param",auto_66
-D auto_70,"value",auto_72
-D auto_72,"var",auto_73
-D auto_73,"var",auto_51
-D auto_74,"name",auto_75
-D auto_74,"next_param",auto_56
-D auto_74,"value",auto_76
-D auto_76,"var",auto_77
-D auto_77,"var",auto_51
-D auto_78,"value",auto_79
-D auto_79,"node",auto_80
+D auto_71,"name",auto_72
+D auto_71,"next_param",auto_67
+D auto_71,"value",auto_73
+D auto_73,"var",auto_74
+D auto_74,"var",auto_51
+D auto_75,"name",auto_76
+D auto_75,"next_param",auto_57
+D auto_75,"value",auto_77
+D auto_77,"var",auto_78
+D auto_78,"var",auto_51
+D auto_79,"value",auto_80
 D auto_8,"next",auto_9
 D auto_8,"var",auto_13
-D auto_81,"a",auto_51
-D auto_82,"var",auto_29
+D auto_80,"node",auto_81
+D auto_82,"a",auto_51
+D auto_83,"var",auto_29
 D auto_9,"value",auto_10
 D auto_9,"var",auto_12

+ 106 - 104
interface/HUTN/test/graph_compilation_action_language/expected/fibonacci

@@ -46,60 +46,61 @@ V auto_49(access)
 V auto_5(assign)
 V auto_50(resolve)
 N auto_51
-V auto_52(return)
-V auto_53(call)
-V auto_54(access)
-V auto_55(resolve)
-N auto_56
-V auto_57("b")
-V auto_58(call)
-V auto_59(access)
+V auto_52("a")
+V auto_53(return)
+V auto_54(call)
+V auto_55(access)
+V auto_56(resolve)
+N auto_57
+V auto_58("b")
+V auto_59(call)
 V auto_6(global)
-V auto_60(resolve)
-N auto_61
-V auto_62("a")
-V auto_63(call)
-V auto_64(access)
-V auto_65(resolve)
-N auto_66
-V auto_67("b")
-V auto_68(constant)
-V auto_69(2)
+V auto_60(access)
+V auto_61(resolve)
+N auto_62
+V auto_63("a")
+V auto_64(call)
+V auto_65(access)
+V auto_66(resolve)
+N auto_67
+V auto_68("b")
+V auto_69(constant)
 V auto_7(assign)
-N auto_70
-V auto_71("a")
-V auto_72(access)
-V auto_73(resolve)
-N auto_74
-V auto_75("a")
-V auto_76(call)
-V auto_77(access)
-V auto_78(resolve)
-N auto_79
+V auto_70(2)
+N auto_71
+V auto_72("a")
+V auto_73(access)
+V auto_74(resolve)
+N auto_75
+V auto_76("a")
+V auto_77(call)
+V auto_78(access)
+V auto_79(resolve)
 V auto_8(global)
-V auto_80("a")
-V auto_81(call)
-V auto_82(access)
-V auto_83(resolve)
-N auto_84
-V auto_85("b")
-V auto_86(constant)
-V auto_87(1)
-N auto_88
-V auto_89("a")
+N auto_80
+V auto_81("a")
+V auto_82(call)
+V auto_83(access)
+V auto_84(resolve)
+N auto_85
+V auto_86("b")
+V auto_87(constant)
+V auto_88(1)
+N auto_89
 V auto_9(assign)
-V auto_90(access)
-V auto_91(resolve)
-V auto_92(return)
-V auto_93(constant)
-V auto_94(1)
-N auto_95
-V auto_96(resolve)
+V auto_90("a")
+V auto_91(access)
+V auto_92(resolve)
+V auto_93(return)
+V auto_94(constant)
+V auto_95(1)
+N auto_96
+V auto_97(resolve)
 D auto_initial_IP,"next",auto_1
 D auto_initial_IP,"var",auto_29
 D auto_1,"next",auto_2
 D auto_1,"value",auto_37
-D auto_1,"var",auto_96
+D auto_1,"var",auto_97
 D auto_10,"node",auto_11
 D auto_12,"var",auto_13
 D auto_14,"node",auto_15
@@ -127,10 +128,10 @@ D auto_33,"node",auto_34
 D auto_35,"var",auto_36
 D auto_37,"node",auto_38
 D auto_38,"body",auto_39
-D auto_38,"params",auto_95
+D auto_38,"params",auto_96
 D auto_39,"cond",auto_40
-D auto_39,"else",auto_52
-D auto_39,"then",auto_92
+D auto_39,"else",auto_53
+D auto_39,"then",auto_93
 D auto_4,"next",auto_5
 D auto_4,"var",auto_21
 D auto_40,"func",auto_41
@@ -149,67 +150,68 @@ D auto_5,"next",auto_6
 D auto_5,"value",auto_18
 D auto_5,"var",auto_20
 D auto_50,"var",auto_51
-D auto_52,"value",auto_53
-D auto_53,"func",auto_54
-D auto_53,"last_param",auto_56
-D auto_53,"params",auto_74
-D auto_54,"var",auto_55
-D auto_55,"var",auto_21
-D auto_56,"name",auto_57
-D auto_56,"value",auto_58
-D auto_58,"func",auto_59
-D auto_58,"last_param",auto_61
-D auto_58,"params",auto_61
-D auto_59,"var",auto_60
+D auto_51,"name",auto_52
+D auto_53,"value",auto_54
+D auto_54,"func",auto_55
+D auto_54,"last_param",auto_57
+D auto_54,"params",auto_75
+D auto_55,"var",auto_56
+D auto_56,"var",auto_21
+D auto_57,"name",auto_58
+D auto_57,"value",auto_59
+D auto_59,"func",auto_60
+D auto_59,"last_param",auto_62
+D auto_59,"params",auto_62
 D auto_6,"next",auto_7
 D auto_6,"var",auto_17
-D auto_60,"var",auto_29
-D auto_61,"name",auto_62
-D auto_61,"value",auto_63
-D auto_63,"func",auto_64
-D auto_63,"last_param",auto_66
-D auto_63,"params",auto_70
-D auto_64,"var",auto_65
-D auto_65,"var",auto_13
-D auto_66,"name",auto_67
-D auto_66,"value",auto_68
-D auto_68,"node",auto_69
+D auto_60,"var",auto_61
+D auto_61,"var",auto_29
+D auto_62,"name",auto_63
+D auto_62,"value",auto_64
+D auto_64,"func",auto_65
+D auto_64,"last_param",auto_67
+D auto_64,"params",auto_71
+D auto_65,"var",auto_66
+D auto_66,"var",auto_13
+D auto_67,"name",auto_68
+D auto_67,"value",auto_69
+D auto_69,"node",auto_70
 D auto_7,"next",auto_8
 D auto_7,"value",auto_14
 D auto_7,"var",auto_16
-D auto_70,"name",auto_71
-D auto_70,"next_param",auto_66
-D auto_70,"value",auto_72
-D auto_72,"var",auto_73
-D auto_73,"var",auto_51
-D auto_74,"name",auto_75
-D auto_74,"next_param",auto_56
-D auto_74,"value",auto_76
-D auto_76,"func",auto_77
-D auto_76,"last_param",auto_79
-D auto_76,"params",auto_79
-D auto_77,"var",auto_78
-D auto_78,"var",auto_29
-D auto_79,"name",auto_80
-D auto_79,"value",auto_81
+D auto_71,"name",auto_72
+D auto_71,"next_param",auto_67
+D auto_71,"value",auto_73
+D auto_73,"var",auto_74
+D auto_74,"var",auto_51
+D auto_75,"name",auto_76
+D auto_75,"next_param",auto_57
+D auto_75,"value",auto_77
+D auto_77,"func",auto_78
+D auto_77,"last_param",auto_80
+D auto_77,"params",auto_80
+D auto_78,"var",auto_79
+D auto_79,"var",auto_29
 D auto_8,"next",auto_9
 D auto_8,"var",auto_13
-D auto_81,"func",auto_82
-D auto_81,"last_param",auto_84
-D auto_81,"params",auto_88
-D auto_82,"var",auto_83
-D auto_83,"var",auto_13
-D auto_84,"name",auto_85
-D auto_84,"value",auto_86
-D auto_86,"node",auto_87
-D auto_88,"name",auto_89
-D auto_88,"next_param",auto_84
-D auto_88,"value",auto_90
+D auto_80,"name",auto_81
+D auto_80,"value",auto_82
+D auto_82,"func",auto_83
+D auto_82,"last_param",auto_85
+D auto_82,"params",auto_89
+D auto_83,"var",auto_84
+D auto_84,"var",auto_13
+D auto_85,"name",auto_86
+D auto_85,"value",auto_87
+D auto_87,"node",auto_88
+D auto_89,"name",auto_90
+D auto_89,"next_param",auto_85
+D auto_89,"value",auto_91
 D auto_9,"value",auto_10
 D auto_9,"var",auto_12
-D auto_90,"var",auto_91
-D auto_91,"var",auto_51
-D auto_92,"value",auto_93
-D auto_93,"node",auto_94
-D auto_95,"a",auto_51
-D auto_96,"var",auto_29
+D auto_91,"var",auto_92
+D auto_92,"var",auto_51
+D auto_93,"value",auto_94
+D auto_94,"node",auto_95
+D auto_96,"a",auto_51
+D auto_97,"var",auto_29

+ 56 - 54
interface/HUTN/test/graph_compilation_action_language/expected/fibonacci_smart

@@ -90,32 +90,33 @@ V auto_178(access)
 V auto_179(resolve)
 V auto_18(global)
 N auto_180
-V auto_181(return)
-V auto_182(call)
-V auto_183(access)
-V auto_184(resolve)
-N auto_185
-V auto_186("b")
-V auto_187(call)
-V auto_188(access)
-V auto_189(resolve)
+V auto_181("a")
+V auto_182(return)
+V auto_183(call)
+V auto_184(access)
+V auto_185(resolve)
+N auto_186
+V auto_187("b")
+V auto_188(call)
+V auto_189(access)
 V auto_19(assign)
-N auto_190
-V auto_191("b")
-V auto_192(constant)
-V auto_193(1)
-N auto_194
-V auto_195("a")
-V auto_196(access)
-V auto_197(resolve)
-N auto_198
-V auto_199("a")
+V auto_190(resolve)
+N auto_191
+V auto_192("b")
+V auto_193(constant)
+V auto_194(1)
+N auto_195
+V auto_196("a")
+V auto_197(access)
+V auto_198(resolve)
+N auto_199
 V auto_2(global)
 V auto_20(constant)
-V auto_200(access)
-V auto_201(resolve)
-N auto_202
-V auto_203(resolve)
+V auto_200("a")
+V auto_201(access)
+V auto_202(resolve)
+N auto_203
+V auto_204(resolve)
 N auto_21
 V auto_22(resolve)
 V auto_23("numbers")
@@ -206,7 +207,7 @@ D auto_initial_IP,"next",auto_1
 D auto_initial_IP,"var",auto_74
 D auto_1,"next",auto_2
 D auto_1,"value",auto_94
-D auto_1,"var",auto_203
+D auto_1,"var",auto_204
 D auto_10,"next",auto_11
 D auto_10,"var",auto_39
 D auto_100,"var",auto_101
@@ -329,39 +330,40 @@ D auto_178,"var",auto_179
 D auto_179,"var",auto_180
 D auto_18,"next",auto_19
 D auto_18,"var",auto_23
-D auto_181,"value",auto_182
-D auto_182,"func",auto_183
-D auto_182,"last_param",auto_185
-D auto_182,"params",auto_198
-D auto_183,"var",auto_184
-D auto_184,"var",auto_31
-D auto_185,"name",auto_186
-D auto_185,"value",auto_187
-D auto_187,"func",auto_188
-D auto_187,"last_param",auto_190
-D auto_187,"params",auto_194
-D auto_188,"var",auto_189
-D auto_189,"var",auto_35
+D auto_180,"name",auto_181
+D auto_182,"value",auto_183
+D auto_183,"func",auto_184
+D auto_183,"last_param",auto_186
+D auto_183,"params",auto_199
+D auto_184,"var",auto_185
+D auto_185,"var",auto_31
+D auto_186,"name",auto_187
+D auto_186,"value",auto_188
+D auto_188,"func",auto_189
+D auto_188,"last_param",auto_191
+D auto_188,"params",auto_195
+D auto_189,"var",auto_190
 D auto_19,"value",auto_20
 D auto_19,"var",auto_22
-D auto_190,"name",auto_191
-D auto_190,"value",auto_192
-D auto_192,"node",auto_193
-D auto_194,"name",auto_195
-D auto_194,"next_param",auto_190
-D auto_194,"value",auto_196
-D auto_196,"var",auto_197
-D auto_197,"var",auto_180
-D auto_198,"name",auto_199
-D auto_198,"next_param",auto_185
-D auto_198,"value",auto_200
+D auto_190,"var",auto_35
+D auto_191,"name",auto_192
+D auto_191,"value",auto_193
+D auto_193,"node",auto_194
+D auto_195,"name",auto_196
+D auto_195,"next_param",auto_191
+D auto_195,"value",auto_197
+D auto_197,"var",auto_198
+D auto_198,"var",auto_180
+D auto_199,"name",auto_200
+D auto_199,"next_param",auto_186
+D auto_199,"value",auto_201
 D auto_2,"next",auto_3
 D auto_2,"var",auto_93
 D auto_20,"node",auto_21
-D auto_200,"var",auto_201
-D auto_201,"var",auto_23
-D auto_202,"a",auto_180
-D auto_203,"var",auto_74
+D auto_201,"var",auto_202
+D auto_202,"var",auto_23
+D auto_203,"a",auto_180
+D auto_204,"var",auto_74
 D auto_22,"var",auto_23
 D auto_24,"node",auto_25
 D auto_26,"var",auto_27
@@ -446,12 +448,12 @@ D auto_91,"var",auto_23
 D auto_92,"var",auto_93
 D auto_94,"node",auto_95
 D auto_95,"body",auto_96
-D auto_95,"params",auto_202
+D auto_95,"params",auto_203
 D auto_96,"next",auto_97
 D auto_96,"var",auto_125
 D auto_97,"body",auto_98
 D auto_97,"cond",auto_164
-D auto_97,"next",auto_181
+D auto_97,"next",auto_182
 D auto_98,"next",auto_99
 D auto_98,"value",auto_156
 D auto_98,"var",auto_163

+ 8 - 6
interface/HUTN/test/graph_compilation_action_language/expected/funccall_params

@@ -14,8 +14,9 @@ V auto_2(global)
 V auto_20(1)
 V auto_21(resolve)
 N auto_22
-N auto_23
-V auto_24(resolve)
+V auto_23("a")
+N auto_24
+V auto_25(resolve)
 V auto_3(assign)
 V auto_4(constant)
 N auto_5
@@ -27,22 +28,23 @@ D auto_initial_IP,"next",auto_1
 D auto_initial_IP,"var",auto_9
 D auto_1,"next",auto_2
 D auto_1,"value",auto_16
-D auto_1,"var",auto_24
+D auto_1,"var",auto_25
 D auto_10,"name",auto_11
 D auto_10,"value",auto_12
 D auto_12,"node",auto_13
 D auto_14,"var",auto_15
 D auto_16,"node",auto_17
 D auto_17,"body",auto_18
-D auto_17,"params",auto_23
+D auto_17,"params",auto_24
 D auto_18,"value",auto_19
 D auto_18,"var",auto_21
 D auto_19,"node",auto_20
 D auto_2,"next",auto_3
 D auto_2,"var",auto_15
 D auto_21,"var",auto_22
-D auto_23,"a",auto_22
-D auto_24,"var",auto_9
+D auto_22,"name",auto_23
+D auto_24,"a",auto_22
+D auto_25,"var",auto_9
 D auto_3,"value",auto_4
 D auto_3,"var",auto_14
 D auto_4,"node",auto_5

+ 10 - 8
interface/HUTN/test/graph_compilation_action_language/expected/funcdef_params

@@ -1,7 +1,8 @@
 V auto_initial_IP(global)
 V auto_1(assign)
-V auto_10(resolve)
-V auto_11("abc")
+N auto_10
+V auto_11(resolve)
+V auto_12("abc")
 V auto_2(constant)
 N auto_3
 V auto_4(assign)
@@ -9,17 +10,18 @@ V auto_5(constant)
 V auto_6(1)
 V auto_7(resolve)
 N auto_8
-N auto_9
+V auto_9("a")
 D auto_initial_IP,"next",auto_1
-D auto_initial_IP,"var",auto_11
+D auto_initial_IP,"var",auto_12
 D auto_1,"value",auto_2
-D auto_1,"var",auto_10
-D auto_10,"var",auto_11
+D auto_1,"var",auto_11
+D auto_10,"a",auto_8
+D auto_11,"var",auto_12
 D auto_2,"node",auto_3
 D auto_3,"body",auto_4
-D auto_3,"params",auto_9
+D auto_3,"params",auto_10
 D auto_4,"value",auto_5
 D auto_4,"var",auto_7
 D auto_5,"node",auto_6
 D auto_7,"var",auto_8
-D auto_9,"a",auto_8
+D auto_8,"name",auto_9

+ 5 - 4
interface/HUTN/test/graph_compilation_action_language/test_real.py

@@ -9,10 +9,11 @@ def compile_file(obj, filename):
     expected = open(util.get_expected_path(filename)).read()
     result = postproc(result)
     expected = postproc(expected)
-    #if result != expected:
-    #    f = open(util.get_expected_path(filename), 'w')
-    #    f.write(result)
-    #    f.close()
+    if result != expected:
+        #f = open(util.get_expected_path(filename), 'w')
+        #f.write(result)
+        #f.close()
+        pass
     assert result == expected
 
 class TestReal(unittest.TestCase):

+ 181 - 0
kernel/modelverse_kernel/compiled.py

@@ -0,0 +1,181 @@
+from modelverse_kernel.primitives import PrimitiveFinished
+
+def reverseKeyLookup(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 read_attribute(a, b, c, **remainder):
+    def make_list(v, l):
+        return [v] if l else v
+
+    #TODO this can be optimized even further...
+    model_dict, b_val, c_val, type_mapping = \
+                    yield [("RD", [a, "model"]),
+                           ("RV", [b]),
+                           ("RV", [c]),
+                           ("RD", [a, "type_mapping"]),
+                           ]
+    model_instance = \
+                    yield [("RD", [model_dict, b_val])]
+    edges =         yield [("RO", [model_instance])]
+    edge_types =    yield [("RDN", [type_mapping, i]) for i in edges]
+    edge_types = make_list(edge_types, len(edges) == 1)
+    type_edge_val = yield [("RE", [i]) for i in edge_types]
+    type_edge_val = make_list(type_edge_val, len(edges) == 1)
+
+    src_nodes = set([i[0] for i in type_edge_val])
+
+    found_edges =   yield [("RDE", [i, c_val]) for i in src_nodes]
+    found_edges = make_list(found_edges, len(src_nodes) == 1)
+
+    for e1 in found_edges:
+        if e1 is not None:
+            # Found an edge!
+            for i, e2 in enumerate(edge_types):
+                if e1 == e2:
+                    # The instance of this edge is the one we want!
+                    edge = edges[i]
+                    edge_val = yield [("RE", [edge])]
+                    result = edge_val[1]
+                    raise PrimitiveFinished(result)
+    else:
+        result = yield [("RR", [])]
+        raise PrimitiveFinished(result)
+
+    raise Exception("Error in reading edge!")
+
+def precompute_cardinalities(a, **remainder):
+    result =        yield [("CN", [])]
+
+    # Read out all edges from the metamodel
+    a =             yield [("RD", [a, "metamodel"])]
+    model_dict =    yield [("RD", [a, "model"])]
+    model_keys =    yield [("RDK", [model_dict])]
+    type_mapping =  yield [("RD", [a, "type_mapping"])]
+    elems =         yield [("RDN", [model_dict, k]) for k in model_keys]
+    model_keys_str= yield [("RV", [i]) for i in model_keys]
+    elem_to_name =  dict(zip(elems, model_keys_str))
+    edges =         yield [("RE", [i]) for i in elems]
+    elems = [elems[i] for i, edge_val in enumerate(edges) if edge_val is not None]
+    # Now we have all edges in the metamodel
+
+    # Read out the type of the Association defining all cardinalities
+    metamodel =     yield [("RD", [a, "metamodel"])]
+    metametamodel = yield [("RD", [metamodel, "metamodel"])]
+    metametamodel_dict = \
+                    yield [("RD", [metametamodel, "model"])]
+    assoc =         yield [("RD", [metametamodel_dict, "Association"])]
+    slc, suc, tlc, tuc = \
+                    yield [("RDE", [assoc, "source_lower_cardinality"]),
+                           ("RDE", [assoc, "source_upper_cardinality"]),
+                           ("RDE", [assoc, "target_lower_cardinality"]),
+                           ("RDE", [assoc, "target_upper_cardinality"]),
+                          ]
+
+    # All that we now have to do is find, for each edge, whether or not it has an edge typed by any of these links!
+    # Just find all links typed by these links!
+    types =         yield [("RDN", [type_mapping, i]) for i in elems]
+
+    cardinalities = {}
+    for i, edge_type in enumerate(types):
+        if edge_type == slc:
+            t = "slc"
+        elif edge_type == suc:
+            t = "suc"
+        elif edge_type == tlc:
+            t = "tlc"
+        elif edge_type == tuc:
+            t = "tuc"
+        else:
+            continue
+        
+        # Found a link, so add it
+        source, destination = yield [("RE", [elems[i]])]
+        # The edge gives the "source" the cardinality found in "destination"
+        cardinalities.setdefault(elem_to_name[source], {})[t] = destination
+
+    # Now we have to translate the "cardinalities" Python dictionary to a Modelverse dictionary
+    nodes = yield [("CN", []) for i in cardinalities]
+    yield [("CD", [result, i, node]) for i, node in zip(cardinalities.keys(), nodes)]
+    l = cardinalities.keys()
+    values = yield [("RD", [result, i]) for i in l]
+
+    for i, value in enumerate(values):
+        cards = cardinalities[l[i]]
+        yield [("CD", [value, card_type, cards[card_type]]) for card_type in cards]
+
+    raise PrimitiveFinished(result)
+
+def set_copy(a, **remainder):
+    b =         yield [("CN", [])]
+    links =     yield [("RO", [a])]
+    exp_links = yield [("RE", [i]) for i in links]
+    if len(links) == 1:
+        exp_links = [exp_links]
+    _ =         yield [("CE", [b, i[1]]) for i in exp_links]
+    raise PrimitiveFinished(b)
+
+def allInstances(a, b, **remainder):
+    b_val =     yield [("RV", [b])]
+    model_dict= yield [("RD", [a, "model"])]
+    metamodel = yield [("RD", [a, "metamodel"])]
+    mm_dict =   yield [("RD", [metamodel, "model"])]
+    typing =    yield [("RD", [a, "type_mapping"])]
+    elem_keys = yield [("RDK", [model_dict])]
+    elems =     yield [("RDN", [model_dict, i]) for i in elem_keys]
+    mms =       yield [("RDN", [typing, i]) for i in elems]
+
+    # Have the type for each name
+    types_to_name_nodes = {}
+    for key, mm in zip(elem_keys, mms):
+        types_to_name_nodes.setdefault(mm, set()).add(key)
+    # And now we have the inverse mapping: for each type, we have the node containing the name
+
+    # Get the inheritance link type
+    inheritance_type =  yield [("RD", [metamodel, "inheritance"])]
+
+    # Now we figure out which types are valid for the specified model
+    desired_types = set()
+    mm_element =    yield [("RD", [mm_dict, b_val])]
+    work_list = []
+    work_list.append(mm_element)
+    mm_typing =     yield [("RD", [metamodel, "type_mapping"])]
+
+    while work_list:
+        mm_element = work_list.pop()
+        if mm_element in desired_types:
+            # Already been here, so stop
+            continue
+
+        # New element, so continue
+        desired_types.add(mm_element)
+
+        # Follow all inheritance links that COME IN this node, as all these are subtypes and should also match
+        incoming =  yield [("RI", [mm_element])]
+        for i in incoming:
+            t =     yield [("RDN", [mm_typing, i])]
+            if t == inheritance_type:
+                e = yield [("RE", [i])]
+                # Add the source of the inheritance link to the work list
+                work_list.append(e[0])
+
+    # Now desired_types holds all the direct types that we are interested in!
+    # Construct the result out of all models that are direct instances of our specified type
+    final = set()
+    for t in desired_types:
+        final |= types_to_name_nodes.get(t, set())
+
+    # Result is a Python set with nodes, so just make this a Mv set
+    result =    yield [("CN", [])]
+    v =         yield [("RV", [i]) for i in final]
+    _ =    yield [("CE", [result, i]) for i in final]
+    raise PrimitiveFinished(result)

+ 26 - 8
kernel/modelverse_kernel/main.py

@@ -1,4 +1,5 @@
 import modelverse_kernel.primitives as primitive_functions
+import modelverse_kernel.compiled as compiled_functions
 import sys
 import time
 
@@ -11,9 +12,12 @@ class ModelverseKernel(object):
     def __init__(self, root):
         self.root = root
         self.primitives = {}
+        self.compiled = {}
         self.returnvalue = None
         self.success = True
         self.generators = {}
+        self.allow_compiled = True
+        #self.allow_compiled = False
         self.debug_info = "(no debug information found)"
 
     def execute_yields(self, username, operation, params, reply):
@@ -54,12 +58,11 @@ class ModelverseKernel(object):
         if phase_v == "finish":
             gen = self.helper_init(user_root)
         elif isinstance(phase_v, string_types):
-            if phase_v == "init" and inst_v is None:
-                #print("%-30s(%s)" % ("PRIMITIVE " + str(self.primitives[inst]), phase_v))
-                try:
-                    gen = self.execute_primitive(user_root, inst)
-                except:
-                    raise Exception("%s: error: IP points to undefined element and is not executable as primitive.")
+            if phase_v == "init" and inst in self.compiled:
+                #print("%-30s(%s)" % ("COMPILED " + str(self.primitives[inst]), phase_v))
+                gen = self.execute_primitive(user_root, inst)
+            elif inst_v is None:
+                raise Exception("%s: error understanding command (%s, %s)" % (self.debug_info, inst_v, phase_v))
             else:
                 #print("%-30s(%s)" % (inst_v["value"], phase_v))
                 gen = getattr(self, "%s_%s" % (inst_v["value"], phase_v))(user_root)
@@ -91,6 +94,7 @@ class ModelverseKernel(object):
         bodies =        yield [("RD", [f, "body"]) for f in signatures]
         for i in range(len(keys)):
             self.primitives[bodies[i]] = getattr(primitive_functions, function_names[i])
+        self.compiled.update(self.primitives)
 
     def execute_primitive(self, user_root, inst):
         # execute_primitive
@@ -122,7 +126,7 @@ class ModelverseKernel(object):
         try:
             # Forward the message we get to this generator
             # Sometimes it might not even be a generator, in which case this should already be in the except block (i.e., for the Read Root operation)
-            prim = self.primitives[inst](**parameters)
+            prim = self.compiled[inst](**parameters)
             inp = None
             while 1:
                 inp = yield prim.send(inp)
@@ -134,7 +138,7 @@ class ModelverseKernel(object):
             result = e.result
 
             #if result is None:
-            #    raise Exception("Primitive raised exception: value of None for operation %s with parameters %s" % (self.primitives[inst], str(parameters)))
+            #    raise Exception("Primitive raised exception: value of None for operation %s with parameters %s" % (self.compiled[inst], str(parameters)))
 
         # Clean up the current stack, as if a return happened
         old_frame =     yield [("RD", [user_frame, "prev"])]
@@ -425,6 +429,20 @@ class ModelverseKernel(object):
                                   ]
             if variable is None:
                 raise Exception("%s: not found as global: %s" % (self.debug_info, var_name))
+
+            # Resolved a global, so this is a string
+            # Potentially, this might even be a function that we have precompiled already!
+            # So check whether this is the case or not
+            if self.allow_compiled:
+                compiled_function = getattr(compiled_functions, var_name, None)
+                if compiled_function is not None:
+                    # We have a compiled function ready!
+                    # Now we have to bind the ID to the compiled functions
+                    # For this, we read out the body of the resolved data
+                    compiler_val = yield [("RD", [variable, "value"])]
+                    compiler_body = yield [("RD", [compiler_val, "body"])]
+                    self.compiled[compiler_body] = compiled_function
+
         else:
             phase_link, returnvalue_link, new_phase = \
                             yield [("RDE", [user_frame, "phase"]),

+ 75 - 16
scripts/prompt.py

@@ -3,6 +3,38 @@ import urllib2
 import threading
 import subprocess
 import os
+import sys
+
+sys.path.append("../interface/HUTN")
+sys.path.append("interface/HUTN")
+from hutn_compiler.compiler import main as hutn_compile
+
+memory = {}
+
+def send_data(commands, address, username):
+    def flush_data(data):
+        if data:
+            urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "data": json.dumps(data), "username": username}))).read()
+        return []
+
+    var_list = {}
+    data = []
+    for p in v:
+        if isinstance(p, int):
+            if p not in var_list:
+                data = flush_data(data)
+                val = urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "username": username}))).read()
+                val = val.split("=", 2)[1].split("&", 1)[0]
+                var_list[p] = val
+                continue
+            else:
+                val = var_list[p]
+                t = "R"
+        else:
+            val = p
+            t = "V"
+        data.append([t, val])
+    flush_data(data)
 
 def local_print(string):
     if os.name == "posix":
@@ -21,10 +53,7 @@ local_print("Please specify Modelverse location (default: 127.0.0.1:8001)")
 
 location = raw_input()
 if location == "":
-    address = "127.0.0.1"
-    port = 8001
-else:
-    address, port = location.strip().split(":")
+    address = "http://127.0.0.1:8001/"
 
 local_print("Username (default: test)")
 username = raw_input()
@@ -34,14 +63,16 @@ else:
     username = username.strip()
 
 # If user shouldn't exist yet, we create it
-urllib2.urlopen(urllib2.Request("http://%s:%s/" % (address, port), urllib.urlencode({"op": "set_input", "element_type": "V", "value": '"%s"' % username, "username": "user_manager"}))).read()
+urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "element_type": "V", "value": '"%s"' % username, "username": "user_manager"}))).read()
 
 local_print("Switching context to Modelverse: all data is piped.")
+local_print("Use command $ to switch to HUTN parsing mode.")
+local_print("Use \\ before the value to use a primitive value different from a string, which is already JSON serialized.")
 local_print("To quit: execute command 'quit'")
 
 def print_output():
     while 1:
-        output = urllib2.urlopen(urllib2.Request("http://%s:%s/" % (address, port), urllib.urlencode({"op": "get_output", "username": username}))).read()
+        output = urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "username": username}))).read()
         l, r = output.split("&", 1)
         if "value" in l:
             output = l
@@ -59,15 +90,43 @@ while 1:
     if command == "quit":
         local_print("Received quit: breaking connection to Modelverse immediately!")
         break
-    try:
-        # Could be a number
-        _ = float(command)
-        command = str(command)
-        local_print("Interpreting value as a number")
-    except:
-        if len(command) > 0 and command[0] == "\\":
-            command = '{"value": "%s"}' % command[1:]
+
+    if command.startswith("$"):
+        # Invoke the HUTN parser
+        tmp_file = "__constraint.al"
+        with open(tmp_file, 'w') as f:
+            f.write("Element function constraint(model : Element, element_name : String):\n")
+        local_print("Entering HUTN coding environment.")
+        local_print("There is no nice editor right now, so please just modify the file '__constraint.al' in this folder.")
+        while 1:
+            local_print("When you are done, press <return> to continue.")
+            raw_input()
+            local_print("File contents:")
+            with open(tmp_file, 'r') as f:
+                local_print(f.read())
+            local_print("Sending file through parser!")
+
+            try:
+                commands = hutn_compile(tmp_file, grammar_file, "CS")
+                local_print("Compilation succesfully terminated!")
+                local_print("Upload this file? [Y/n]")
+                i = raw_input()
+                if i == "n\n":
+                    continue
+                send_data(commands, address)
+            except:
+                local_print("Error during compilation!")
+                local_print("Do you want to try again? [Y/n]")
+                i = raw_input()
+                if i == "n\n":
+                    break
+
+            local_print("HUTN input finished, going back to regular prompt!")
+    else:
+        # Just send a normal request
+        if command.startswith("\\"):
+            command = command
         else:
             command = '"%s"' % command
-        local_print("Got command string: " + str(command))
-    urllib2.urlopen(urllib2.Request("http://%s:%s/" % (address, port), urllib.urlencode({"op": "set_input", "element_type": "V", "value": command, "username": username}))).read()
+
+        urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "element_type": "V", "value": command, "username": username}))).read()