diff --git a/docs/language.js b/docs/language.js index f5c4847a..249efb5e 100644 --- a/docs/language.js +++ b/docs/language.js @@ -95,9 +95,10 @@ var data = [ }, { - "parameter" : "while bool condition [code c1] [code c2] ... [code cN]", + "parameter" : "while bool condition [code code1] [code code2] ... [code codeN]", "output" : "*", - "description" : "Each time the condition evaluates to true, it runs each of the code trees sequentially, looping. Evaluates to the last codeN or null if the condition was initially false or if it encounters a conclude, it will halt processing and evaluate to the value returned by conclude.", + "new target scope": true, + "description" : "Each time the condition evaluates to true, it runs each of the code trees sequentially, looping. Evaluates to the last codeN or null if the condition was initially false or if it encounters a conclude, it will halt processing and evaluate to the value returned by conclude. For iteration of the loop, pushes a new target scope onto the target stack, with current_index being the iteration count, and previous_result being the last evaluated codeN of the previous loop.", "example" : "(let (assoc zz 1)\n (while (< zz 10)\n (print zz)\n (assign (assoc zz (+ zz 1)))\n )\n)" }, @@ -470,8 +471,8 @@ var data = [ "output" : "*", "new value" : "new", "new target scope": true, - "description" : "Rewrites target by applying the function in a bottom-up manner. For each node in the target tree, pushes a new target scope onto the target stack, with target_value being the current node and target_index being to the index to the current node relative to the node passed into rewrite accessed via target, and evaluates function. Returns the resulting tree, after have been rewritten by function.", - "example" : "(print (rewrite\n (lambda (if (~ (target_value) 0) (+ (target_value) 1) (target_value)) )\n (list (assoc \"a\" 13)) ) )\n ;rewrite all integer additions into multiplies and then fold constants\n(print (rewrite\n (lambda\n ;find any nodes with a + and where its list is filled to its size with integers\n (if (and \n (= (get_type (target_value)) \"+\")\n (= (size (target_value)) (size (filter (lambda (~ (target_value) 0)) (target_value))) )\n )\n (reduce (lambda (* (target_value 1) (target_value)) ) (target_value))\n (target_value))\n )\n ;original code with additions to be rewritten\n (lambda\n (list (assoc \"a\" (+ 3 (+ 13 4 2)) )) )\n) )\n(print (rewrite\n (lambda\n (if (and \n (= (get_type (target_value)) \"+\")\n (= (size (target_value)) (size (filter (lambda (~ (target_value) 0)) (target_value))) )\n )\n (reduce (lambda (+ (target_value 1) (target_value)) ) (target_value))\n (target_value))\n )\n (lambda\n (+ (+ 13 4) (target_value 1)) )\n) )" + "description" : "Rewrites target by applying the function in a bottom-up manner. For each node in the target tree, pushes a new target scope onto the target stack, with current_value being the current node and current_index being to the index to the current node relative to the node passed into rewrite accessed via target, and evaluates function. Returns the resulting tree, after have been rewritten by function.", + "example" : "(print (rewrite\n (lambda (if (~ (current_value) 0) (+ (current_value) 1) (current_value)) )\n (list (assoc \"a\" 13)) ) )\n ;rewrite all integer additions into multiplies and then fold constants\n(print (rewrite\n (lambda\n ;find any nodes with a + and where its list is filled to its size with integers\n (if (and \n (= (get_type (current_value)) \"+\")\n (= (size (current_value)) (size (filter (lambda (~ (current_value) 0)) (current_value))) )\n )\n (reduce (lambda (* (previous_result) (current_value)) ) (current_value))\n (current_value))\n )\n ;original code with additions to be rewritten\n (lambda\n (list (assoc \"a\" (+ 3 (+ 13 4 2)) )) )\n) )\n(print (rewrite\n (lambda\n (if (and \n (= (get_type (current_value)) \"+\")\n (= (size (current_value)) (size (filter (lambda (~ (current_value) 0)) (current_value))) )\n )\n (reduce (lambda (+ (previous_result) (current_value)) ) (current_value))\n (current_value))\n )\n (lambda\n (+ (+ 13 4) (current_value 1)) )\n) )" }, { @@ -480,8 +481,8 @@ var data = [ "new value" : "new", "concurrency" : true, "new target scope": true, - "description" : "For each element in the collection, pushes a new target scope onto the stack, so that target_value accesses the element or elements in the list and target_index accesses the list or assoc index, with target representing the outer set of lists or assocs, and evaluates the function. Returns the list of results, mapping the list via the specified function. If multiple lists or assocs are specified, then it pulls from each list or assoc simultaneously (null if overrun or index does not exist) and (target_value) contains an array of the values in parameter order. Note that concurrency is only available when one collection is specified.", - "example" : "(print (map (lambda (* (target_value) 2)) (list 1 2 3 4)))\n(print (map (lambda (+ (target_value) (target_index))) (assoc 10 1 20 2 30 3 40 4)))\n(print (map\n (lambda\n (+ (get (target_value) 0) (get (target_value) 1) (get (target_value) 2))\n )\n (assoc \"0\" 0 \"1\" 1 \"a\" 3)\n (assoc \"a\" 1 \"b\" 4)\n (list 2 2 2 2)\n))" + "description" : "For each element in the collection, pushes a new target scope onto the stack, so that current_value accesses the element or elements in the list and current_index accesses the list or assoc index, with target representing the outer set of lists or assocs, and evaluates the function. Returns the list of results, mapping the list via the specified function. If multiple lists or assocs are specified, then it pulls from each list or assoc simultaneously (null if overrun or index does not exist) and (current_value) contains an array of the values in parameter order. Note that concurrency is only available when one collection is specified.", + "example" : "(print (map (lambda (* (current_value) 2)) (list 1 2 3 4)))\n(print (map (lambda (+ (current_value) (current_index))) (assoc 10 1 20 2 30 3 40 4)))\n(print (map\n (lambda\n (+ (get (current_value) 0) (get (current_value) 1) (get (current_value) 2))\n )\n (assoc \"0\" 0 \"1\" 1 \"a\" 3)\n (assoc \"a\" 1 \"b\" 4)\n (list 2 2 2 2)\n))" }, { @@ -490,16 +491,16 @@ var data = [ "new value" : "new", "concurrency" : true, "new target scope": true, - "description" : "For each element in the collection, pushes a new target scope onto the stack, so that target_value accesses the element in the list and target_index accesses the list or assoc index, with target representing the original list or assoc, and evaluates the function. If function evaluates to true, then the element is put in a new list or assoc (matching the input type) that is returned. If function is omitted, then it will remove any elements in the collection that are null, .nan, or .nas string.", - "example" : "(print (filter (lambda (> (target_value) 2)) (list 1 2 3 4)))" + "description" : "For each element in the collection, pushes a new target scope onto the stack, so that current_value accesses the element in the list and current_index accesses the list or assoc index, with target representing the original list or assoc, and evaluates the function. If function evaluates to true, then the element is put in a new list or assoc (matching the input type) that is returned. If function is omitted, then it will remove any elements in the collection that are null, .nan, or .nas string.", + "example" : "(print (filter (lambda (> (current_value) 2)) (list 1 2 3 4)))" }, { "parameter" : "weave [* function] list|immediate values1 [list|immediate values2] [list|immediate values3]...", "output" : "list", "new target scope": true, - "description" : "Interleaves the values lists optionally by applying a function. If only values1 is passed in, then it evaluates to values1. If values1 and values2 are passed in, or, if more values are passed in but function is null, it interleaves the two lists out to whichever list is longer, filling in the remainder with null, and if any value is an immediate, then it will repeat the immediate value. If the function is specified and not nulll, it pushes a new target scope onto the stack, so that target_value accesses a list of elements to be woven together from the list, and target_index accesses the list or assoc index, with target representing the original list or assoc. The function should evaluate to a list, and weave will evaluate to a concatenated list of all of the lists that the function evaluated to.", - "example" : "(print (weave (list 1 3 5) (list 2 4 6)) \"\\n\")\n(print (weave (lambda (list (apply \"min\" (target_value) ) ) (list 1 3 4 5 5 6) (list 2 2 3 4 6 7) )\"\\n\")\n(print (weave (lambda (if (<= (get (target_value) 0) 4) (list (apply \"min\" (target_value 1)) ) (target_value)) ) (list 1 3 4 5 5 6) (list 2 2 3 4 6 7) )\"\\n\")\n(print (weave (null) (list 2 4 6) (null) ) \"\\n\")" + "description" : "Interleaves the values lists optionally by applying a function. If only values1 is passed in, then it evaluates to values1. If values1 and values2 are passed in, or, if more values are passed in but function is null, it interleaves the two lists out to whichever list is longer, filling in the remainder with null, and if any value is an immediate, then it will repeat the immediate value. If the function is specified and not nulll, it pushes a new target scope onto the stack, so that current_value accesses a list of elements to be woven together from the list, and current_index accesses the list or assoc index, with target representing the original list or assoc. The function should evaluate to a list, and weave will evaluate to a concatenated list of all of the lists that the function evaluated to.", + "example" : "(print (weave (list 1 3 5) (list 2 4 6)) \"\\n\")\n(print (weave (lambda (list (apply \"min\" (current_value) ) ) (list 1 3 4 5 5 6) (list 2 2 3 4 6 7) )\"\\n\")\n(print (weave (lambda (if (<= (get (current_value) 0) 4) (list (apply \"min\" (current_value 1)) ) (current_value)) ) (list 1 3 4 5 5 6) (list 2 2 3 4 6 7) )\"\\n\")\n(print (weave (null) (list 2 4 6) (null) ) \"\\n\")" }, { @@ -507,8 +508,8 @@ var data = [ "output" : "*", "new value" : "new", "new target scope": true, - "description" : "For each element in the collection after the first one, it pushes a pair of new target scope onto the stack, so that target_value accesses a list of elements from the list, and target_index accesses the list or assoc index if it is not already reduced, with target representing the original list or assoc, and evaluates function. If the collection is empty, null is returned. if the collection is of size one, the single element is returned.", - "example" : "(print (reduce (lambda (* (target_value 1) (target_value))) (list 1 2 3 4)))" + "description" : "For each element in the collection after the first one, it evaluates function with a new target scope on the stack where current_value accesses each of the elements from the collection, current_index accesses the list or assoc index, target accesses the original list or assoc, and previous_result accesses the previously reduced result. If the collection is empty, null is returned. if the collection is of size one, the single element is returned.", + "example" : "(print (reduce (lambda (* (previous_result) (current_value))) (list 1 2 3 4)))" }, { @@ -532,8 +533,8 @@ var data = [ "output" : "list", "new value" : "new", "new target scope": true, - "description" : "Returns a new list containing the list with its elements sorted in increasing order. Numerical values come before strings, and code will be evaluated as the representative strings. If function is specified, it pushes a pair of new target scope onto the stack, so that target_value accesses a list of elements to from the list, and target_index accesses the list or assoc index if it is not already reduced, with target representing the original list or assoc, and evaluates function. The function should return a number, positive if \"(target_value)\" is greater, negative if \"(target_value 1)\" is greater, 0 if equal.", - "example" : "(print (sort (list 4 9 3 5 1)))\n(print (sort (list \"n\" \"b\" \"hello\" 4 1 3.2 (list 1 2 3))))\n(print (sort (list 1 \"1x\" \"10\" 20 \"z2\" \"z10\" \"z100\")))\n(print (sort (lambda (- (target_value) (target_value 1))) (list 4 9 3 5 1)))" + "description" : "Returns a new list containing the list with its elements sorted in increasing order. Numerical values come before strings, and code will be evaluated as the representative strings. If function is specified, it pushes a pair of new target scope onto the stack, so that current_value accesses a list of elements to from the list, and current_index accesses the list or assoc index if it is not already reduced, with target representing the original list or assoc, and evaluates function. The function should return a number, positive if \"(current_value)\" is greater, negative if \"(current_value 1)\" is greater, 0 if equal.", + "example" : "(print (sort (list 4 9 3 5 1)))\n(print (sort (list \"n\" \"b\" \"hello\" 4 1 3.2 (list 1 2 3))))\n(print (sort (list 1 \"1x\" \"10\" 20 \"z2\" \"z10\" \"z100\")))\n(print (sort (lambda (- (current_value) (current_value 1))) (list 4 9 3 5 1)))" }, { @@ -589,7 +590,7 @@ var data = [ "new value" : "new", "concurrency" : true, "new target scope": true, - "description" : "Evaluates to the assoc, where each pair of parameters (e.g., index1 and value1) comprises a index/value pair. Pushes a new target scope such that (target), (target_index), and (target_value) access the assoc, the current index, and the current value.", + "description" : "Evaluates to the assoc, where each pair of parameters (e.g., index1 and value1) comprises a index/value pair. Pushes a new target scope such that (target), (current_index), and (current_value) access the assoc, the current index, and the current value.", "example" : "(print (assoc \"a\" 1 \"b\" 2 \"c\" 3 4 \"d\"))" }, @@ -598,7 +599,7 @@ var data = [ "output" : "assoc", "new value" : "new", "new target scope": true, - "description" : "Evaluates to a new assoc where the indices are the keys and the values are the values, with corresponding positions in the list matched. If the values is omitted, then it will use nulls for each of the values. If values is not a list, then all of the values in the assoc returned are set to the same value. When one parameter is specified, it is the list of indices. When two parameters are specified, it is the indices and values. When three values are specified, it is the function, indices and values. Values defaults to (null) and function defaults to (lambda (target_value)). When there is a collision of indices, the function is called, it pushes a pair of new target scope onto the stack, so that target_value accesses a list of elements from the list, target_index accesses the list or assoc index if it is not already reduced, with target representing the original list or assoc, evaluates function if one exists, and (target_value) is the new value attempted to be inserted over (target_value 1).", + "description" : "Evaluates to a new assoc where the indices are the keys and the values are the values, with corresponding positions in the list matched. If the values is omitted, then it will use nulls for each of the values. If values is not a list, then all of the values in the assoc returned are set to the same value. When one parameter is specified, it is the list of indices. When two parameters are specified, it is the indices and values. When three values are specified, it is the function, indices and values. Values defaults to (null) and function defaults to (lambda (current_value)). When there is a collision of indices, the function is called, it pushes a pair of new target scope onto the stack, so that current_value accesses a list of elements from the list, current_index accesses the list or assoc index if it is not already reduced, with target representing the original list or assoc, evaluates function if one exists, and (current_value) is the new value attempted to be inserted over (current_value 1).", "example" : "(print (zip (list \"a\" \"b\" \"c\" \"d\") (list 1 2 3 4)))" }, @@ -630,8 +631,8 @@ var data = [ "output" : "*", "new value" : "new", "new target scope": true, - "description" : "Performs a deep copy on data (a copy of all data structures referenced by it and its references), then looks at the remaining parameters as pairs. For each pair, the first is any of: a number, representing an index, with negative numbers representing backward traversal from the end of the list; a string, representing the index; or a list, representing a way to walk into the structure as the aforementioned values. function1 to functionN represent a function that will be used to replace in place of whatever is in the location, and will be passed the current node in (target_value). The function does not need to be a function and can just be a constant (which it will be evaluated as). If a particular location does not exist, it will be created assuming the most generic type that will support the index (as a null, list, or assoc). Note that the target operation will evaluate to the new copy of data, which is the base of the newly constructed data; this is useful for creating circular references.", - "example" : "(print (replace (list (assoc \"a\" 13)) ))\n(print (replace\n (list (assoc \"a\" 1))\n (list 2) 1\n (list 0) (list 4 5 6)))\n\n(print (replace\n (list (assoc \"a\" 1))\n (list 0) (lambda (set (target_value) \"b\" 2))\n ))" + "description" : "Performs a deep copy on data (a copy of all data structures referenced by it and its references), then looks at the remaining parameters as pairs. For each pair, the first is any of: a number, representing an index, with negative numbers representing backward traversal from the end of the list; a string, representing the index; or a list, representing a way to walk into the structure as the aforementioned values. function1 to functionN represent a function that will be used to replace in place of whatever is in the location, and will be passed the current node in (current_value). The function does not need to be a function and can just be a constant (which it will be evaluated as). If a particular location does not exist, it will be created assuming the most generic type that will support the index (as a null, list, or assoc). Note that the target operation will evaluate to the new copy of data, which is the base of the newly constructed data; this is useful for creating circular references.", + "example" : "(print (replace (list (assoc \"a\" 13)) ))\n(print (replace\n (list (assoc \"a\" 1))\n (list 2) 1\n (list 0) (list 4 5 6)))\n\n(print (replace\n (list (assoc \"a\" 1))\n (list 0) (lambda (set (current_value) \"b\" 2))\n ))" }, { @@ -642,18 +643,25 @@ var data = [ }, { - "parameter" : "target_index [number stack_distance]", + "parameter" : "current_index [number stack_distance]", "output" : "*", "new value" : "new", "description" : "Like target, but evaluates to the index of the current node being iterated on within target.", - "example" : "(list 1 2 3 (print (target_index)) 4)" + "example" : "(list 1 2 3 (print (current_index)) 4)" }, { - "parameter" : "target_value [number stack_distance]", + "parameter" : "current_value [number stack_distance]", "output" : "*", "description" : "Like target, but evaluates to the current node being iterated on within target.", - "example" : "(list 1 2 3 (print (target_value)) 4)" + "example" : "(list 1 2 3 (print (current_value)) 4)" + }, + + { + "parameter" : "previous_result [number stack_distance]", + "output" : "*", + "description" : "Like target, but evaluates to the resulting node of the previous iteration for applicable opcodes.", + "example" : "(while (< (target_index) 3) (print (previous_result)) (target_index))" }, { @@ -845,7 +853,7 @@ var data = [ "new value" : "new", "concurrency" : true, "new target scope": true, - "description" : "Evaluates to the list specified by the parameters. Pushes a new target scope such that (target), (target_index), and (target_value) access the list, the current index, and the current value.", + "description" : "Evaluates to the list specified by the parameters. Pushes a new target scope such that (target), (current_index), and (current_value) access the list, the current index, and the current value.", "example" : "(print (list \"a\" 1 \"b\"))" }, @@ -855,7 +863,7 @@ var data = [ "new value" : "new", "concurrency" : true, "new target scope": true, - "description" : "Evaluates to the associative list, where each pair of parameters (e.g., index1 and value1) comprises a index/value pair. Pushes a new target scope such that (target), (target_index), and (target_value) access the assoc, the current index, and the current value. If any of the bstrings do not have reserved characters or spaces, then quotes are optional; if spaces or reserved characters are present, then quotes are required.", + "description" : "Evaluates to the associative list, where each pair of parameters (e.g., index1 and value1) comprises a index/value pair. Pushes a new target scope such that (target), (current_index), and (current_value) access the assoc, the current index, and the current value. If any of the bstrings do not have reserved characters or spaces, then quotes are optional; if spaces or reserved characters are present, then quotes are required.", "example" : "(print (assoc b 2 c 3))\n(print (assoc a 1 \"b\\ttab\" 2 c 3 4 \"d\"))" }, diff --git a/src/Amalgam/Opcodes.cpp b/src/Amalgam/Opcodes.cpp index 2d94cc4b..42b01695 100644 --- a/src/Amalgam/Opcodes.cpp +++ b/src/Amalgam/Opcodes.cpp @@ -46,8 +46,9 @@ void StringInternPool::InitializeStaticStrings() //stack and node manipulation EmplaceStaticString(GetStringIdFromNodeTypeFromString(ENT_TARGET), "target"); - EmplaceStaticString(GetStringIdFromNodeTypeFromString(ENT_TARGET_INDEX), "target_index"); - EmplaceStaticString(GetStringIdFromNodeTypeFromString(ENT_TARGET_VALUE), "target_value"); + EmplaceStaticString(GetStringIdFromNodeTypeFromString(ENT_CURRENT_INDEX), "current_index"); + EmplaceStaticString(GetStringIdFromNodeTypeFromString(ENT_CURRENT_VALUE), "current_value"); + EmplaceStaticString(GetStringIdFromNodeTypeFromString(ENT_PREVIOUS_RESULT), "previous_result"); EmplaceStaticString(GetStringIdFromNodeTypeFromString(ENT_STACK), "stack"); EmplaceStaticString(GetStringIdFromNodeTypeFromString(ENT_ARGS), "args"); diff --git a/src/Amalgam/Opcodes.h b/src/Amalgam/Opcodes.h index c45b1360..e89b2f09 100644 --- a/src/Amalgam/Opcodes.h +++ b/src/Amalgam/Opcodes.h @@ -38,8 +38,9 @@ enum EvaluableNodeType : uint8_t //stack and node manipulation ENT_TARGET, - ENT_TARGET_INDEX, - ENT_TARGET_VALUE, + ENT_CURRENT_INDEX, + ENT_CURRENT_VALUE, + ENT_PREVIOUS_RESULT, ENT_STACK, ENT_ARGS, @@ -372,7 +373,7 @@ constexpr OrderedChildNodeType GetInstructionOrderedChildNodeType(EvaluableNodeT case ENT_CALL: case ENT_CALL_SANDBOXED: case ENT_RETRIEVE: case ENT_GET: - case ENT_TARGET: case ENT_TARGET_INDEX: case ENT_TARGET_VALUE: + case ENT_TARGET: case ENT_CURRENT_INDEX: case ENT_CURRENT_VALUE: case ENT_PREVIOUS_RESULT: case ENT_STACK: case ENT_ARGS: case ENT_RAND: case ENT_WEIGHTED_RAND: case ENT_GET_RAND_SEED: case ENT_SET_RAND_SEED: case ENT_SYSTEM_TIME: diff --git a/src/Amalgam/amlg_code/full_test.amlg b/src/Amalgam/amlg_code/full_test.amlg index 70572db2..ace84eea 100644 --- a/src/Amalgam/amlg_code/full_test.amlg +++ b/src/Amalgam/amlg_code/full_test.amlg @@ -507,12 +507,12 @@ (print (range 12 0 5 1)) (print (range - (lambda (+ (target_index) 1)) + (lambda (+ (current_index) 1)) 0 5 1 )) (print ||(range - (lambda (+ (target_index) 1)) + (lambda (+ (current_index) 1)) 0 5 1 )) @@ -532,12 +532,12 @@ (print (replace (list (associate "a" 1)) - (list 0) (lambda (set (target_value) "b" 2)) + (list 0) (lambda (set (current_value) "b" 2)) )) (print "--rewrite--\n") (print (rewrite - (lambda (if (~ (target_value) 0) (+ (target_value) 1) (target_value)) ) + (lambda (if (~ (current_value) 0) (+ (current_value) 1) (current_value)) ) (list (associate "a" 13)) )) ;rewrite all integer additions into multiplies and then fold constants @@ -545,11 +545,11 @@ (lambda ;find any nodes with a + and where its list is filled to its size with integers (if (and - (= (get_type (target_value)) (lambda (+))) - (= (size (target_value)) (size (filter (lambda (~ (target_value) 0)) (target_value))) ) + (= (get_type (current_value)) (lambda (+))) + (= (size (current_value)) (size (filter (lambda (~ (current_value) 0)) (current_value))) ) ) - (reduce (lambda (* (target_value 1) (target_value)) ) (target_value)) - (target_value) + (reduce (lambda (* (previous_result) (current_value)) ) (current_value)) + (current_value) ) ) ;original code with additions to be rewritten @@ -562,11 +562,11 @@ (lambda ;find any nodes with a + and where its list is filled to its size with integers (if - (= (get_type_string (target_value)) "number") + (= (get_type_string (current_value)) "number") - (+ (target_value) (get_value (target_index))) + (+ (current_value) (get_value (current_index))) - (target_value) + (current_value) ) ) ;original code with additions to be rewritten @@ -577,11 +577,11 @@ (print (rewrite (lambda (if (and - (= (get_type (target_value)) (lambda (+))) - (= (size (target_value)) (size (filter (lambda (~ (target_value) 0)) (target_value))) ) + (= (get_type (current_value)) (lambda (+))) + (= (size (current_value)) (size (filter (lambda (~ (current_value) 0)) (current_value))) ) ) - (reduce (lambda (+ (target_value 1) (target_value)) ) (target_value)) - (target_value) + (reduce (lambda (+ (previous_result) (current_value)) ) (current_value)) + (current_value) ) ) (lambda @@ -589,13 +589,13 @@ ) (print "--map--\n") - (print (map (lambda (* (target_value) 2)) (list 1 2 3 4))) - (print (map (lambda (+ (target_value) (target_index) )) (list 10 1 20 2 30 3 40 4))) - (print (map (lambda (+ (target_value) (target_index) )) (associate 10 1 20 2 30 3 40 4))) + (print (map (lambda (* (current_value) 2)) (list 1 2 3 4))) + (print (map (lambda (+ (current_value) (current_index) )) (list 10 1 20 2 30 3 40 4))) + (print (map (lambda (+ (current_value) (current_index) )) (associate 10 1 20 2 30 3 40 4))) (print (map (lambda - (+ (get (target_value) 0) (get (target_value) 1)) + (+ (get (current_value) 0) (get (current_value) 1)) ) (list 1 2 3 4 5 6) (list 2 2 2 2 2 2) @@ -604,7 +604,7 @@ (print (map (lambda - (+ (get (target_value) 0) (get (target_value) 1)) + (+ (get (current_value) 0) (get (current_value) 1)) ) (list 1 2 3 4 5) (list 2 2 2 2 2 2) @@ -612,7 +612,7 @@ (print (map (lambda - (+ (get (target_value) 0) (get (target_value) 1) (get (target_value) 2)) + (+ (get (current_value) 0) (get (current_value) 1) (get (current_value) 2)) ) (associate "0" 0 "1" 1 "a" 3) (associate "0" 1 "a" 4) @@ -620,9 +620,9 @@ )) (print "--filter--\n") - (print (filter (lambda (> (target_value) 2)) (list 1 2 3 4))) - (print (filter (lambda (< (target_index) 3)) (list 10 1 20 2 30 3 40 4))) - (print (filter (lambda (< (target_index) 20)) (associate 10 1 20 2 30 3 40 4))) + (print (filter (lambda (> (current_value) 2)) (list 1 2 3 4))) + (print (filter (lambda (< (current_index) 3)) (list 10 1 20 2 30 3 40 4))) + (print (filter (lambda (< (current_index) 20)) (associate 10 1 20 2 30 3 40 4))) (print (filter (list 10 1 20 (null) 30 .nan .nas 40 4))) (print (filter (list 10 1 20 (null) 30 "" 40 4))) @@ -641,7 +641,7 @@ (print (weave (lambda - (target_value) + (current_value) ) (list 1 3 5 7 9 11) (list 2 4 6 8 10 12) @@ -650,9 +650,9 @@ (print (weave (lambda (map (lambda - (* 2 (target_value)) + (* 2 (current_value)) ) - (target_value) + (current_value) ) ) (list 1 3 5 7 9 11) @@ -661,7 +661,7 @@ (print (weave (lambda - (list (apply "min" (target_value 1)) ) + (list (apply "min" (current_value 1)) ) ) (list 1 3 4 5 5 6) (list 2 2 3 4 6 7) @@ -669,9 +669,9 @@ (print (weave (lambda - (if (<= (get (target_value) 0) 4) - (list (apply "min" (target_value 1)) ) - (target_value) + (if (<= (get (current_value) 0) 4) + (list (apply "min" (current_value 1)) ) + (current_value) ) ) (list 1 3 4 5 5 6) @@ -681,8 +681,8 @@ (print (weave (lambda - (if (>= (first (target_value)) 3) - (list (first (target_value 1))) + (if (>= (first (current_value)) 3) + (list (first (current_value 1))) (list) ) ) @@ -692,8 +692,8 @@ ) (print "--reduce--\n") - (print (reduce (lambda (* (target_value) (target_value 1))) (list 1 2 3 4)) "\n") - (print (reduce (lambda (* (target_value) (target_value 1))) (associate "a" 1 "b" 2 "c" 3 "d" 4)) "\n") + (print (reduce (lambda (* (current_value) (previous_result))) (list 1 2 3 4)) "\n") + (print (reduce (lambda (* (current_value) (previous_result))) (associate "a" 1 "b" 2 "c" 3 "d" 4)) "\n") (print "--apply--\n") (print (apply (lambda (+)) (list 1 2 3 4)) "\n") @@ -708,7 +708,7 @@ (print (sort (list "n" "b" "hello" "soy" 4 1 3.2 (list 1 2 3)))) (print (sort (list 1 "1x" "10" 20 "z2" "z10" "z100"))) (print (sort (list 1 "001x" "010" 20 "z002" "z010" "z100"))) - (print (sort (lambda (- (target_value) (target_value 1))) (list 4 9 3 5 1))) + (print (sort (lambda (- (current_value) (current_value 1))) (list 4 9 3 5 1))) (print (sort (lambda (- (rand) (rand)) ) (range 0 10) )) (print (sort (list @@ -799,9 +799,9 @@ (print (zip (list "a" "b" "c" "d") (list 1 2 3 4))) (print (zip (list "a" "b" "c" "d") )) (print (zip (list "a" "b" "c" "d") 3)) - (print (zip (lambda (target_value)) (list "a" "b" "c" "d" "a") (list 1 2 3 4 4))) - (print (zip (lambda (+ (target_value 1) (target_value))) (list "a" "b" "c" "d" "a") (list 1 2 3 4 4))) - (print (zip (lambda (+ (target_value 1) (target_value))) (list "a" "b" "c" "d" "a") 1)) + (print (zip (lambda (current_value)) (list "a" "b" "c" "d" "a") (list 1 2 3 4 4))) + (print (zip (lambda (+ (current_value 1) (current_value))) (list "a" "b" "c" "d" "a") (list 1 2 3 4 4))) + (print (zip (lambda (+ (current_value 1) (current_value))) (list "a" "b" "c" "d" "a") 1)) (print "--unzip--\n") (print (unzip (associate "a" 1 "b" 2 "c" 3) (list "a" "b"))) @@ -840,14 +840,21 @@ (print "--target--\n") (list 1 2 3 (print (target)) 4) - (print "--target_index--\n") - (list 1 2 3 (print (target_index) "\n") 4) - (list 1 2 3 (print (target_index 1) "\n") 4) - (list 1 2 3 (print (target_index 2) "\n") 4) - (list 1 2 3 (print (target_index 3) "\n") 4) + (print "--current_index--\n") + (list 1 2 3 (print (current_index) "\n") 4) + (list 1 2 3 (print (current_index 1) "\n") 4) + (list 1 2 3 (print (current_index 2) "\n") 4) + (list 1 2 3 (print (current_index 3) "\n") 4) - (print "--target_value--\n") - (list 1 2 3 (print (target_value) "\n") 4) + (print "--current_value--\n") + (list 1 2 3 (print (current_value) "\n") 4) + + (print "--previous_result--\n") + (while (< (current_index) 3) + (print "current_index: " (current_index) "\n") + (print (previous_result) "\n") + (current_index) + ) (print "--stack--\n") (print (stack)) @@ -955,10 +962,10 @@ (print "infinity test c or d: " (weighted_rand (list (list "a" "b" "c" "d") (list .25 .75 .infinity .infinity)) 4) "\n") ;these should come out somewhere near the correct proportions - (print (zip (lambda (+ (target_value 1) (target_value))) (weighted_rand (associate "a" .25 "b" .5 "c" .25) 100) 1) "\n") + (print (zip (lambda (+ (current_value 1) (current_value))) (weighted_rand (associate "a" .25 "b" .5 "c" .25) 100) 1) "\n") ;these should come out somewhere near the correct proportions - (print (zip (lambda (+ (target_value 1) (target_value))) (weighted_rand (list (list "a" "b" "c") (list .25 .5 .25)) 100) 1) "\n") + (print (zip (lambda (+ (current_value 1) (current_value))) (weighted_rand (list (list "a" "b" "c") (list .25 .5 .25)) 100) 1) "\n") ;these should be weighted toward smaller numbers (print @@ -966,7 +973,7 @@ (zip (range 1 10) (map (lambda - (/ (/ 1 (target_value)) 2) + (/ (/ 1 (current_value)) 2) ) (range 1 10) ) @@ -1041,7 +1048,7 @@ (print "--format--\n") (print (map (lambda - (format (target_value) "int8" "number") + (format (current_value) "int8" "number") ) (explode "abcdefgﬗꭖϡ" 1) ) @@ -1721,8 +1728,8 @@ (print (retrieve_entity_root "AndedEntities")) (map (lambda (seq - (print (target_value) "\n") - (print (retrieve_entity_root (list "AndedEntities" (target_value 1)))) + (print (current_value) "\n") + (print (retrieve_entity_root (list "AndedEntities" (current_value 1)))) )) (contained_entities "AndedEntities") ) @@ -1734,8 +1741,8 @@ (print (retrieve_entity_root "OredEntities")) (map (lambda (seq - (print (target_value) "\n") - (print (retrieve_entity_root (list "OredEntities" (target_value 1)))) + (print (current_value) "\n") + (print (retrieve_entity_root (list "OredEntities" (current_value 1)))) )) (contained_entities "OredEntities") ) @@ -1755,8 +1762,8 @@ (print (retrieve_entity_root "ComplexOredEntities")) (map (lambda (seq - (print (target_value) "\n") - (print (retrieve_entity_root (list "ComplexOredEntities" (target_value 1)))) + (print (current_value) "\n") + (print (retrieve_entity_root (list "ComplexOredEntities" (current_value 1)))) )) (contained_entities "ComplexOredEntities") ) @@ -1828,8 +1835,8 @@ (print (retrieve_entity_root "MixedEntities")) (map (lambda (seq - (print (target_value) "\n") - (print (retrieve_entity_root (list "MixedEntities" (target_value 1)))) + (print (current_value) "\n") + (print (retrieve_entity_root (list "MixedEntities" (current_value 1)))) )) (contained_entities "MixedEntities") ) @@ -1870,9 +1877,9 @@ (map (lambda (assoc "description" - (target_value 1) + (current_value 1) "parameters" - (get_entity_comments (null) (target_index 1) (true)) + (get_entity_comments (null) (current_index 1) (true)) ) ) (get_entity_comments (null) (null) (true)) @@ -2890,7 +2897,7 @@ ) (print - (map (lambda (retrieve_entity_root (list "eq_distance_test" (target_value 1)))) + (map (lambda (retrieve_entity_root (list "eq_distance_test" (current_value 1)))) (contained_entities "eq_distance_test" (list (query_within_generalized_distance 1 (list "x" "y") (list 0.0 0.0)) @@ -2907,7 +2914,7 @@ ) (print - (map (lambda (retrieve_entity_root (list "eq_distance_test" (target_value 1)))) + (map (lambda (retrieve_entity_root (list "eq_distance_test" (current_value 1)))) (contained_entities "eq_distance_test" (list (query_within_generalized_distance 1 (list "x" "y") (list 0.0 0.0)) @@ -2920,7 +2927,7 @@ (destroy_entities (list "eq_distance_test" "to_delete1")) (print - (map (lambda (retrieve_entity_root (list "eq_distance_test" (target_value 1)))) + (map (lambda (retrieve_entity_root (list "eq_distance_test" (current_value 1)))) (contained_entities "eq_distance_test" (list (query_within_generalized_distance 1 (list "x" "y") (list 0.0 0.0)) @@ -3173,7 +3180,7 @@ )) (print "cyclic test expected: 155, 200, 190 ... deg values of 0 8 and 12:\n") - (map (lambda (print (target_index) ": " (target_value) " " (retrieve_entity_root (list "CyclicTestEntity" (target_index 1))))) buds) + (map (lambda (print (current_index) ": " (current_value) " " (retrieve_entity_root (list "CyclicTestEntity" (current_index 1))))) buds) (print "--contains_label--\n") (print (contains_label "label3") "\n") @@ -3357,12 +3364,12 @@ (pow (reduce (lambda - (+ (target_value 1) (target_value)) + (+ (previous_result) (current_value)) ) (map (lambda (pow - (- (get (target_value) 0) (get (target_value) 1)) + (- (get (current_value) 0) (get (current_value) 1)) 2 ) ) @@ -3956,18 +3963,18 @@ (print "list : " ||(list (+ 1 0) 1 1 2) "\n") (print "associate : " ||(associate "a" 1 "b" 1 "c" 1 "d" 2) "\n") (print "assoc : " ||(assoc a (+ 1 0) b 1 c 1 d 2) "\n") - (print "map list : " ||(map (lambda (* (target_value) 2)) (list 1 2 3 4)) "\n") - (print "map assoc : " ||(map (lambda (* (target_value) 2)) (associate "a" 1 "b" 2 "c" 3 "d" 4)) "\n") - (print "filter list : " ||(filter (lambda (> (target_value) 2)) (list 1 2 3 4)) "\n") - (print "filter assoc : " ||(filter (lambda (< (target_index) 20)) (associate 10 1 20 2 30 3 40 4)) "\n") - (print "filter assoc 2 : " ||(filter (lambda (<= (target_value) 2)) (associate 10 1 20 2 30 3 40 4)) "\n") + (print "map list : " ||(map (lambda (* (current_value) 2)) (list 1 2 3 4)) "\n") + (print "map assoc : " ||(map (lambda (* (current_value) 2)) (associate "a" 1 "b" 2 "c" 3 "d" 4)) "\n") + (print "filter list : " ||(filter (lambda (> (current_value) 2)) (list 1 2 3 4)) "\n") + (print "filter assoc : " ||(filter (lambda (< (current_index) 20)) (associate 10 1 20 2 30 3 40 4)) "\n") + (print "filter assoc 2 : " ||(filter (lambda (<= (current_value) 2)) (associate 10 1 20 2 30 3 40 4)) "\n") ;nested concurrency ||(map (lambda - (let (assoc index (target_value 1)) + (let (assoc index (current_value 1)) ||(map - (lambda (+ (target_index))) + (lambda (+ (current_index))) (range 1 100) ) ) @@ -3978,7 +3985,7 @@ ;writing outside of concurrency (let (assoc x (list)) ||(map (lambda - (let (assoc y (target_value 1) ) + (let (assoc y (current_value 1) ) (accum "x" (null) y) ) ) @@ -3991,7 +3998,7 @@ (print "--concurrent entity writes--\n") #concurrent_ent_writes (list) ||(map (lambda - (accum_to_entities (assoc concurrent_ent_writes (list (target_value 2)))) + (accum_to_entities (assoc concurrent_ent_writes (list (current_value 2)))) ) (range 1 1000) ) diff --git a/src/Amalgam/amlg_code/module_test.json b/src/Amalgam/amlg_code/module_test.json index 585086bb..5ebc1778 100644 --- a/src/Amalgam/amlg_code/module_test.json +++ b/src/Amalgam/amlg_code/module_test.json @@ -1 +1 @@ -[{"b":4,"a":3},{"c":"c","d":null}] \ No newline at end of file +[{"a":3,"b":4},{"d":null,"c":"c"}] \ No newline at end of file diff --git a/src/Amalgam/amlg_code/module_test2.amlg b/src/Amalgam/amlg_code/module_test2.amlg index 00a38d62..3f90ac17 100644 --- a/src/Amalgam/amlg_code/module_test2.amlg +++ b/src/Amalgam/amlg_code/module_test2.amlg @@ -1,8 +1,8 @@ (assoc + a #a 1 hello #hello (print "hello\n") - b #b (true) - a #a 1 - c #c 0.1 d #d 100000000 + c #c 0.1 + b #b (true) ) diff --git a/src/Amalgam/evaluablenode/EvaluableNodeTreeDifference.cpp b/src/Amalgam/evaluablenode/EvaluableNodeTreeDifference.cpp index 081c08fa..bf78a773 100644 --- a/src/Amalgam/evaluablenode/EvaluableNodeTreeDifference.cpp +++ b/src/Amalgam/evaluablenode/EvaluableNodeTreeDifference.cpp @@ -159,10 +159,10 @@ EvaluableNode *EvaluableNodeTreeDifference::DifferenceTrees(EvaluableNodeManager } else { - //build (get (target_value 1) ...) + //build (get (current_value 1) ...) EvaluableNode *retrieval = enm->AllocNode(ENT_GET); replacement->AppendOrderedChildNode(retrieval); - EvaluableNode *target = enm->AllocNode(ENT_TARGET_VALUE); + EvaluableNode *target = enm->AllocNode(ENT_CURRENT_VALUE); target->AppendOrderedChildNode(enm->AllocNode(1.0)); retrieval->AppendOrderedChildNode(target); @@ -193,10 +193,10 @@ EvaluableNode *EvaluableNodeTreeDifference::DifferenceTrees(EvaluableNodeManager } else { - //build (get (target_value 1) ...) + //build (get (current_value 1) ...) EvaluableNode *retrieval = enm->AllocNode(ENT_GET); replacement->AppendOrderedChildNode(retrieval); - EvaluableNode *target = enm->AllocNode(ENT_TARGET_VALUE); + EvaluableNode *target = enm->AllocNode(ENT_CURRENT_VALUE); target->AppendOrderedChildNode(enm->AllocNode(1.0)); retrieval->AppendOrderedChildNode(target); diff --git a/src/Amalgam/evaluablenode/EvaluableNodeTreeManipulation.cpp b/src/Amalgam/evaluablenode/EvaluableNodeTreeManipulation.cpp index 2efddf97..c1bd92f6 100644 --- a/src/Amalgam/evaluablenode/EvaluableNodeTreeManipulation.cpp +++ b/src/Amalgam/evaluablenode/EvaluableNodeTreeManipulation.cpp @@ -1970,8 +1970,9 @@ CompactHashMap EvaluableNodeTreeManipulation::evaluab //stack and node manipulation {ENT_TARGET, 0.1}, - {ENT_TARGET_INDEX, 0.1}, - {ENT_TARGET_VALUE, 0.1}, + {ENT_CURRENT_INDEX, 0.1}, + {ENT_CURRENT_VALUE, 0.1}, + {ENT_PREVIOUS_RESULT, 0.05}, {ENT_STACK, 0.05}, {ENT_ARGS, 0.08}, diff --git a/src/Amalgam/interpreter/Interpreter.cpp b/src/Amalgam/interpreter/Interpreter.cpp index 9479e64e..b897e749 100644 --- a/src/Amalgam/interpreter/Interpreter.cpp +++ b/src/Amalgam/interpreter/Interpreter.cpp @@ -60,8 +60,9 @@ std::array Interpreter //stack and node manipulation &Interpreter::InterpretNode_ENT_TARGET, // ENT_TARGET - &Interpreter::InterpretNode_ENT_TARGET_INDEX, // ENT_TARGET_INDEX - &Interpreter::InterpretNode_ENT_TARGET_VALUE, // ENT_TARGET_VALUE + &Interpreter::InterpretNode_ENT_CURRENT_INDEX, // ENT_CURRENT_INDEX + &Interpreter::InterpretNode_ENT_CURRENT_VALUE, // ENT_CURRENT_VALUE + &Interpreter::InterpretNode_ENT_PREVIOUS_RESULT, // ENT_PREVIOUS_RESULT &Interpreter::InterpretNode_ENT_STACK, // ENT_STACK &Interpreter::InterpretNode_ENT_ARGS, // ENT_ARGS @@ -335,12 +336,12 @@ Interpreter::Interpreter(EvaluableNodeManager *enm, #ifdef MULTITHREAD_SUPPORT EvaluableNodeReference Interpreter::ExecuteNode(EvaluableNode *en, EvaluableNode *call_stack, EvaluableNode *interpreter_node_stack, - EvaluableNode *construction_stack, std::vector *construction_stack_indices, + EvaluableNode *construction_stack, std::vector *construction_stack_indices, Concurrency::SingleMutex *call_stack_write_mutex) #else EvaluableNodeReference Interpreter::ExecuteNode(EvaluableNode *en, EvaluableNode *call_stack, EvaluableNode *interpreter_node_stack, - EvaluableNode *construction_stack, std::vector *construction_stack_indices) + EvaluableNode *construction_stack, std::vector *construction_stack_indices) #endif { @@ -374,7 +375,7 @@ EvaluableNodeReference Interpreter::ExecuteNode(EvaluableNode *en, constructionStackNodes = &construction_stack->GetOrderedChildNodes(); if(construction_stack_indices != nullptr) - constructionStackIndices = *construction_stack_indices; + constructionStackIndicesAndUniqueness = *construction_stack_indices; //protect all of the stacks with needing cycle free checks // in case a node is added to one which isn't cycle free @@ -734,8 +735,8 @@ EvaluableNode *Interpreter::RewriteByFunction(EvaluableNodeReference function, E for(auto &[e_id, e] : n->GetMappedChildNodesReference()) { - SetTopTargetValueIndexInConstructionStack(e_id); - SetTopTargetValueReferenceInConstructionStack(e); + SetTopCurrentIndexInConstructionStack(e_id); + SetTopCurrentValueInConstructionStack(e); e = RewriteByFunction(function, top_node, e, references); } @@ -751,8 +752,8 @@ EvaluableNode *Interpreter::RewriteByFunction(EvaluableNodeReference function, E //rewrite child nodes before rewriting this one for(size_t i = 0; i < ocn.size(); i++) { - SetTopTargetValueIndexInConstructionStack(static_cast(i)); - SetTopTargetValueReferenceInConstructionStack(ocn[i]); + SetTopCurrentIndexInConstructionStack(static_cast(i)); + SetTopCurrentValueInConstructionStack(ocn[i]); ocn[i] = RewriteByFunction(function, top_node, ocn[i], references); } @@ -799,7 +800,7 @@ bool Interpreter::InterpretEvaluableNodesConcurrently(EvaluableNode *parent_node evaluableNodeManager->AllocListNode(callStackNodes), evaluableNodeManager->AllocListNode(interpreterNodeStackNodes), evaluableNodeManager->AllocListNode(constructionStackNodes), - &constructionStackIndices, + &constructionStackIndicesAndUniqueness, concurrency_manager.GetCallStackWriteMutex()); evaluableNodeManager->KeepNodeReference(result); diff --git a/src/Amalgam/interpreter/Interpreter.h b/src/Amalgam/interpreter/Interpreter.h index 82e2a816..f8e70aac 100644 --- a/src/Amalgam/interpreter/Interpreter.h +++ b/src/Amalgam/interpreter/Interpreter.h @@ -27,6 +27,18 @@ class Interpreter { public: + //used with construction stack to store the index and whether previous_result is unique + struct ConstructionStackIndexAndPreviousResultUniqueness + { + inline ConstructionStackIndexAndPreviousResultUniqueness(EvaluableNodeImmediateValueWithType _index, + bool _unique) + : index(_index), unique(_unique) + { } + + EvaluableNodeImmediateValueWithType index; + bool unique; + }; + //Creates a new interpreter to run code and to store labels. // If no entity is specified via nullptr, then it will run sandboxed // Uses max_num_steps as the maximum number of operations that can be executed by this and any subordinate operations called. If max_num_steps is 0, then it will execute unlimeted steps @@ -48,12 +60,14 @@ class Interpreter // and call_stack_write_mutex is the mutex needed to lock for writing EvaluableNodeReference ExecuteNode(EvaluableNode *en, EvaluableNode *call_stack = nullptr, EvaluableNode *interpreter_node_stack = nullptr, - EvaluableNode *construction_stack = nullptr, std::vector *construction_stack_indices = nullptr, + EvaluableNode *construction_stack = nullptr, + std::vector *construction_stack_indices = nullptr, Concurrency::SingleMutex *call_stack_write_mutex = nullptr); #else EvaluableNodeReference ExecuteNode(EvaluableNode *en, EvaluableNode *call_stack = nullptr, EvaluableNode *interpreter_node_stack = nullptr, - EvaluableNode *construction_stack = nullptr, std::vector *construction_stack_indices = nullptr); + EvaluableNode *construction_stack = nullptr, + std::vector *construction_stack_indices = nullptr); #endif //changes debugging state to debugging_enabled @@ -113,27 +127,33 @@ class Interpreter //pushes a new construction context on the stack, which is assumed to not be nullptr //the stack is indexed via the constructionStackOffset* constants - //returns the new size + //target_origin is the original node of target useful for keeping track of the reference static inline void PushNewConstructionContextToStack(std::vector &stack_nodes, - std::vector &stack_node_indices, - EvaluableNode *target_origin, EvaluableNode *target, EvaluableNodeImmediateValueWithType target_index, EvaluableNode *target_value) + std::vector &stack_node_indices, + EvaluableNode *target_origin, EvaluableNode *target, + EvaluableNodeImmediateValueWithType current_index, EvaluableNode *current_value, + EvaluableNodeReference previous_result) { size_t new_size = stack_nodes.size() + constructionStackOffsetStride; stack_nodes.resize(new_size, nullptr); stack_nodes[new_size + constructionStackOffsetTargetOrigin] = target_origin; stack_nodes[new_size + constructionStackOffsetTarget] = target; - stack_nodes[new_size + constructionStackOffsetTargetValue] = target_value; + stack_nodes[new_size + constructionStackOffsetCurrentValue] = current_value; + stack_nodes[new_size + constructionStackOffsetPreviousResult] = previous_result.reference; - stack_node_indices.emplace_back(target_index); + stack_node_indices.emplace_back(current_index, previous_result.unique); } //pushes a new construction context on the stack //the stack is indexed via the constructionStackOffset* constants - //returns the new size - __forceinline void PushNewConstructionContext(EvaluableNode *target_origin, EvaluableNode *target, EvaluableNodeImmediateValueWithType target_index, EvaluableNode *target_value) + //target_origin is the original node of target useful for keeping track of the reference + __forceinline void PushNewConstructionContext(EvaluableNode *target_origin, EvaluableNode *target, + EvaluableNodeImmediateValueWithType current_index, EvaluableNode *current_value, + EvaluableNodeReference previous_result = EvaluableNodeReference::Null()) { - return PushNewConstructionContextToStack(*constructionStackNodes, constructionStackIndices, target_origin, target, target_index, target_value); + return PushNewConstructionContextToStack(*constructionStackNodes, constructionStackIndicesAndUniqueness, + target_origin, target, current_index, current_value, previous_result); } //pops the top construction context off the stack @@ -147,27 +167,60 @@ class Interpreter constructionStackNodes->resize(new_size); - if(constructionStackIndices.size() > 0) - constructionStackIndices.pop_back(); + if(constructionStackIndicesAndUniqueness.size() > 0) + constructionStackIndicesAndUniqueness.pop_back(); } //updates the construction index at top of the stack to the new value - __forceinline void SetTopTargetValueIndexInConstructionStack(double new_index) + //assumes there is at least one construction stack entry + __forceinline void SetTopCurrentIndexInConstructionStack(double new_index) { - constructionStackIndices.back() = EvaluableNodeImmediateValueWithType(new_index); + constructionStackIndicesAndUniqueness.back().index = EvaluableNodeImmediateValueWithType(new_index); } - __forceinline void SetTopTargetValueIndexInConstructionStack(StringInternPool::StringID new_index) + __forceinline void SetTopCurrentIndexInConstructionStack(StringInternPool::StringID new_index) { - constructionStackIndices.back() = EvaluableNodeImmediateValueWithType(new_index); + constructionStackIndicesAndUniqueness.back().index = EvaluableNodeImmediateValueWithType(new_index); } //sets the value node for the top reference on the construction stack //used for updating the current target value - //assumes there is at least one construction stack - __forceinline void SetTopTargetValueReferenceInConstructionStack(EvaluableNode *value) + //assumes there is at least one construction stack entry + __forceinline void SetTopCurrentValueInConstructionStack(EvaluableNode *value) + { + constructionStackNodes->at(constructionStackNodes->size() + constructionStackOffsetCurrentValue) = value; + } + + //sets the previous_result node for the top reference on the construction stack + //assumes there is at least one construction stack entry + __forceinline void SetTopPreviousResultInConstructionStack(EvaluableNodeReference previous_result) + { + constructionStackNodes->at(constructionStackNodes->size() + constructionStackOffsetPreviousResult) = previous_result.reference; + constructionStackIndicesAndUniqueness.back().unique = previous_result.unique; + } + + //gets the previous_result node for the reference at depth on the construction stack + //assumes there is at least one construction stack entry and depth is a valid depth + __forceinline EvaluableNodeReference GetAndClearPreviousResultInConstructionStack(size_t depth) + { + size_t uniqueness_offset = constructionStackIndicesAndUniqueness.size() - depth - 1; + bool previous_result_unique = constructionStackIndicesAndUniqueness[uniqueness_offset].unique; + + //clear previous result + size_t prev_result_offset = constructionStackNodes->size() + - (constructionStackOffsetStride * depth) + constructionStackOffsetPreviousResult; + auto &previous_result_loc = constructionStackNodes->at(prev_result_offset); + EvaluableNode *previous_result = nullptr; + std::swap(previous_result, previous_result_loc); + + return EvaluableNodeReference(previous_result, previous_result_unique); + } + + //clears all uniqueness of previous_results in construction stack in case the construction stack is copied across threads + inline void RemoveUniquenessFromPreviousResultsInConstructionStack() { - (*constructionStackNodes)[constructionStackNodes->size() + constructionStackOffsetTargetValue] = value; + for(auto &entry : constructionStackIndicesAndUniqueness) + entry.unique = false; } //Makes sure that args is an active associative array is proper for execution context, meaning initialized assoc and a unique reference. @@ -349,6 +402,10 @@ class Interpreter if(parentInterpreter->maxNumExecutionSteps > 0) max_execution_steps_per_element = (parentInterpreter->maxNumExecutionSteps - parentInterpreter->GetNumStepsExecuted()) / numElements; + //since each thread has a copy of the constructionStackNodes, it's possible that more than one of the threads + //obtains previous_results, so they must all be marked as not unique + parentInterpreter->RemoveUniquenessFromPreviousResultsInConstructionStack(); + //set up all the interpreters // do this as its own loop to make sure that the vector memory isn't reallocated once the threads have kicked off for(size_t element_index = 0; element_index < numElements; element_index++) @@ -365,30 +422,33 @@ class Interpreter //Enqueues a concurrent task resultFutures that needs a construction stack, using the relative interpreter // executes node_to_execute with the following parameters matching those of pushing on the construction stack - // will allocate an approrpiate node matching the type of target_index_type and target_index + // will allocate an approrpiate node matching the type of current_index void PushTaskToResultFuturesWithConstructionStack(EvaluableNode *node_to_execute, - EvaluableNode *target_origin, EvaluableNode *target, EvaluableNodeImmediateValueWithType target_index, EvaluableNode *target_value) + EvaluableNode *target_origin, EvaluableNode *target, + EvaluableNodeImmediateValueWithType current_index, + EvaluableNode *current_value, EvaluableNodeReference previous_result = EvaluableNodeReference::Null()) { //get the interpreter corresponding to the resultFutures Interpreter *interpreter = interpreters[resultFutures.size()].get(); resultFutures.emplace_back( Concurrency::threadPool.EnqueueBatchTask( - [this, interpreter, node_to_execute, target_origin, target, target_index, target_value] + [this, interpreter, node_to_execute, target_origin, target, current_index, current_value, previous_result] { EvaluableNodeManager *enm = interpreter->evaluableNodeManager; interpreter->memoryModificationLock = Concurrency::ReadLock(enm->memoryModificationMutex); //build new construction stack EvaluableNode *construction_stack = enm->AllocListNode(parentInterpreter->constructionStackNodes); - std::vector construction_stack_indices(parentInterpreter->constructionStackIndices); - interpreter->PushNewConstructionContextToStack(construction_stack->GetOrderedChildNodes(), construction_stack_indices, target_origin, target, target_index, target_value); + std::vector csiau(parentInterpreter->constructionStackIndicesAndUniqueness); + interpreter->PushNewConstructionContextToStack(construction_stack->GetOrderedChildNodes(), + csiau, target_origin, target, current_index, current_value, previous_result); auto result = interpreter->ExecuteNode(node_to_execute, enm->AllocListNode(parentInterpreter->callStackNodes), enm->AllocListNode(parentInterpreter->interpreterNodeStackNodes), construction_stack, - &construction_stack_indices, + &csiau, GetCallStackWriteMutex()); enm->KeepNodeReference(result); @@ -642,8 +702,9 @@ class Interpreter //stack and node manipulation EvaluableNodeReference InterpretNode_ENT_TARGET(EvaluableNode *en); - EvaluableNodeReference InterpretNode_ENT_TARGET_INDEX(EvaluableNode *en); - EvaluableNodeReference InterpretNode_ENT_TARGET_VALUE(EvaluableNode *en); + EvaluableNodeReference InterpretNode_ENT_CURRENT_INDEX(EvaluableNode *en); + EvaluableNodeReference InterpretNode_ENT_CURRENT_VALUE(EvaluableNode *en); + EvaluableNodeReference InterpretNode_ENT_PREVIOUS_RESULT(EvaluableNode *en); EvaluableNodeReference InterpretNode_ENT_STACK(EvaluableNode *en); EvaluableNodeReference InterpretNode_ENT_ARGS(EvaluableNode *en); @@ -811,7 +872,7 @@ class Interpreter //current index for each level of constructionStackNodes; //note, this should always be the same size as constructionStackNodes - std::vector constructionStackIndices; + std::vector constructionStackIndicesAndUniqueness; //buffer to use as for parsing and querying conditions //one per thread to save memory on Interpreter objects @@ -866,10 +927,12 @@ class Interpreter static bool _label_profiling_enabled; //number of items in each level of the constructionStack - static constexpr int64_t constructionStackOffsetStride = 3; + static constexpr int64_t constructionStackOffsetStride = 4; //index of each item for a given level in the constructionStack relative to the size of the stack minus the level * constructionStackOffsetStride - static constexpr int64_t constructionStackOffsetTargetOrigin = -3; - static constexpr int64_t constructionStackOffsetTarget = -2; - static constexpr int64_t constructionStackOffsetTargetValue = -1; + //target origin is the original node of target useful for keeping track of the reference + static constexpr int64_t constructionStackOffsetTargetOrigin = -4; + static constexpr int64_t constructionStackOffsetTarget = -3; + static constexpr int64_t constructionStackOffsetCurrentValue = -2; + static constexpr int64_t constructionStackOffsetPreviousResult = -1; }; diff --git a/src/Amalgam/interpreter/InterpreterOpcodesBase.cpp b/src/Amalgam/interpreter/InterpreterOpcodesBase.cpp index b8cc1e6a..4a2e002e 100644 --- a/src/Amalgam/interpreter/InterpreterOpcodesBase.cpp +++ b/src/Amalgam/interpreter/InterpreterOpcodesBase.cpp @@ -363,7 +363,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_PARALLEL(EvaluableNode *en evaluableNodeManager->AllocListNode(callStackNodes), evaluableNodeManager->AllocListNode(interpreterNodeStackNodes), evaluableNodeManager->AllocListNode(constructionStackNodes), - &constructionStackIndices, + &constructionStackIndicesAndUniqueness, concurrency_manager.GetCallStackWriteMutex()); interpreter.evaluableNodeManager->FreeNodeTreeIfPossible(result); @@ -574,15 +574,22 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_WHILE(EvaluableNode *en) { auto &ocn = en->GetOrderedChildNodes(); - if(ocn.size() == 0) + size_t ocn_size = ocn.size(); + if(ocn_size == 0) return EvaluableNodeReference::Null(); - EvaluableNodeReference result = EvaluableNodeReference::Null(); + EvaluableNodeReference previous_result = EvaluableNodeReference::Null(); + + PushNewConstructionContext(nullptr, nullptr, EvaluableNodeImmediateValueWithType(0.0), nullptr); + auto node_stack = CreateInterpreterNodeStackStateSaver(); + size_t loop_iteration = 0; for(;;) { + SetTopCurrentIndexInConstructionStack(static_cast(loop_iteration++)); + //keep the result before testing condition - node_stack.PushEvaluableNode(result); + node_stack.PushEvaluableNode(previous_result); bool condition_true = InterpretNodeIntoBoolValue(ocn[0]); node_stack.PopEvaluableNode(); @@ -592,18 +599,38 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_WHILE(EvaluableNode *en) if(AreExecutionResourcesExhausted()) return EvaluableNodeReference::Null(); + SetTopPreviousResultInConstructionStack(previous_result); + //run each step within the loop - for(size_t i = 1; i < ocn.size(); i++) + EvaluableNodeReference new_result; + for(size_t i = 1; i < ocn_size; i++) { - if(result != nullptr && result->GetType() == ENT_CONCLUDE) - return RemoveConcludeFromConclusion(result, evaluableNodeManager); + new_result = InterpretNode(ocn[i]); - evaluableNodeManager->FreeNodeTreeIfPossible(result); - result = InterpretNode(ocn[i]); + if(new_result != nullptr && new_result->GetType() == ENT_CONCLUDE) + { + //if previous result is unconsumed, free if possible + previous_result = GetAndClearPreviousResultInConstructionStack(0); + evaluableNodeManager->FreeNodeTreeIfPossible(previous_result); + + PopConstructionContext(); + return RemoveConcludeFromConclusion(new_result, evaluableNodeManager); + } + + //don't free the last new_result + if(i < ocn_size - 1) + evaluableNodeManager->FreeNodeTreeIfPossible(new_result); } + + //if previous result is unconsumed, free if possible + previous_result = GetAndClearPreviousResultInConstructionStack(0); + evaluableNodeManager->FreeNodeTreeIfPossible(previous_result); + + previous_result = new_result; } - return result; + PopConstructionContext(); + return previous_result; } EvaluableNodeReference Interpreter::InterpretNode_ENT_LET(EvaluableNode *en) @@ -1187,14 +1214,14 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_TARGET(EvaluableNode *en) } //make sure have a large enough stack - if(depth >= constructionStackIndices.size()) + if(depth >= constructionStackIndicesAndUniqueness.size()) return EvaluableNodeReference::Null(); size_t offset = constructionStackNodes->size() - (constructionStackOffsetStride * depth) + constructionStackOffsetTarget; - return EvaluableNodeReference( (*constructionStackNodes)[offset], false); + return EvaluableNodeReference(constructionStackNodes->at(offset), false); } -EvaluableNodeReference Interpreter::InterpretNode_ENT_TARGET_INDEX(EvaluableNode *en) +EvaluableNodeReference Interpreter::InterpretNode_ENT_CURRENT_INDEX(EvaluableNode *en) { auto &ocn = en->GetOrderedChildNodes(); @@ -1209,15 +1236,15 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_TARGET_INDEX(EvaluableNode } //make sure have a large enough stack - if(depth >= constructionStackIndices.size()) + if(depth >= constructionStackIndicesAndUniqueness.size()) return EvaluableNodeReference::Null(); //depth is 1-based - size_t offset = constructionStackIndices.size() - depth - 1; + size_t offset = constructionStackIndicesAndUniqueness.size() - depth - 1; //build the index node to return EvaluableNode *index_node = nullptr; - EvaluableNodeImmediateValueWithType enivwt = constructionStackIndices[offset]; + EvaluableNodeImmediateValueWithType enivwt = constructionStackIndicesAndUniqueness[offset].index; if(enivwt.nodeType == ENIVT_NUMBER) index_node = evaluableNodeManager->AllocNode(enivwt.nodeValue.number); else if(enivwt.nodeType == ENIVT_STRING_ID) @@ -1226,7 +1253,29 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_TARGET_INDEX(EvaluableNode return EvaluableNodeReference(index_node, true); } -EvaluableNodeReference Interpreter::InterpretNode_ENT_TARGET_VALUE(EvaluableNode *en) +EvaluableNodeReference Interpreter::InterpretNode_ENT_CURRENT_VALUE(EvaluableNode *en) +{ + auto &ocn = en->GetOrderedChildNodes(); + + size_t depth = 0; + if(ocn.size() > 0) + { + double value = InterpretNodeIntoNumberValue(ocn[0]); + if(value >= 0) + depth = static_cast(value); + else + return EvaluableNodeReference::Null(); + } + + //make sure have a large enough stack + if(depth >= constructionStackIndicesAndUniqueness.size()) + return EvaluableNodeReference::Null(); + + size_t offset = constructionStackNodes->size() - (constructionStackOffsetStride * depth) + constructionStackOffsetCurrentValue; + return EvaluableNodeReference(constructionStackNodes->at(offset), false); +} + +EvaluableNodeReference Interpreter::InterpretNode_ENT_PREVIOUS_RESULT(EvaluableNode *en) { auto &ocn = en->GetOrderedChildNodes(); @@ -1241,11 +1290,10 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_TARGET_VALUE(EvaluableNode } //make sure have a large enough stack - if(depth >= constructionStackIndices.size()) + if(depth >= constructionStackIndicesAndUniqueness.size()) return EvaluableNodeReference::Null(); - size_t offset = constructionStackNodes->size() - (constructionStackOffsetStride * depth) + constructionStackOffsetTargetValue; - return EvaluableNodeReference( (*constructionStackNodes)[offset], false); + return GetAndClearPreviousResultInConstructionStack(depth); } EvaluableNodeReference Interpreter::InterpretNode_ENT_STACK(EvaluableNode *en) diff --git a/src/Amalgam/interpreter/InterpreterOpcodesDataTypes.cpp b/src/Amalgam/interpreter/InterpreterOpcodesDataTypes.cpp index f2d54dee..29964a19 100644 --- a/src/Amalgam/interpreter/InterpreterOpcodesDataTypes.cpp +++ b/src/Amalgam/interpreter/InterpreterOpcodesDataTypes.cpp @@ -91,7 +91,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_LIST(EvaluableNode *en) for(size_t i = 0; i < ocn.size(); i++) { - SetTopTargetValueIndexInConstructionStack(static_cast(i)); + SetTopCurrentIndexInConstructionStack(static_cast(i)); auto value = InterpretNode(ocn[i]); //add it to the list @@ -163,7 +163,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_ASSOC(EvaluableNode *en) for(auto &[cn_id, cn] : new_mcn) { - SetTopTargetValueIndexInConstructionStack(cn_id); + SetTopCurrentIndexInConstructionStack(cn_id); //compute the value EvaluableNodeReference element_result = InterpretNode(cn); diff --git a/src/Amalgam/interpreter/InterpreterOpcodesListManipulation.cpp b/src/Amalgam/interpreter/InterpreterOpcodesListManipulation.cpp index bf209872..f2d0a0f4 100644 --- a/src/Amalgam/interpreter/InterpreterOpcodesListManipulation.cpp +++ b/src/Amalgam/interpreter/InterpreterOpcodesListManipulation.cpp @@ -670,7 +670,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_RANGE(EvaluableNode *en) for(size_t i = 0; i < num_nodes; i++) { //pass index of list to be mapped -- leave value at nullptr - SetTopTargetValueIndexInConstructionStack(i * range_step_size + range_start); + SetTopCurrentIndexInConstructionStack(i * range_step_size + range_start); EvaluableNodeReference element_result = InterpretNode(function); result_ocn[i] = element_result; diff --git a/src/Amalgam/interpreter/InterpreterOpcodesTransformations.cpp b/src/Amalgam/interpreter/InterpreterOpcodesTransformations.cpp index 42e190e1..5feeb58e 100644 --- a/src/Amalgam/interpreter/InterpreterOpcodesTransformations.cpp +++ b/src/Amalgam/interpreter/InterpreterOpcodesTransformations.cpp @@ -123,8 +123,8 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_MAP(EvaluableNode *en) for(size_t i = 0; i < list_ocn.size(); i++) { //pass value of list to be mapped - SetTopTargetValueIndexInConstructionStack(static_cast(i)); - SetTopTargetValueReferenceInConstructionStack(list_ocn[i]); + SetTopCurrentIndexInConstructionStack(static_cast(i)); + SetTopCurrentValueInConstructionStack(list_ocn[i]); EvaluableNodeReference element_result = InterpretNode(function); result_ocn[i] = element_result; @@ -177,8 +177,8 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_MAP(EvaluableNode *en) for(auto &[cn_id, cn] : result_mcn) { - SetTopTargetValueIndexInConstructionStack(cn_id); - SetTopTargetValueReferenceInConstructionStack(cn); + SetTopCurrentIndexInConstructionStack(cn_id); + SetTopCurrentValueInConstructionStack(cn); EvaluableNodeReference element_result = InterpretNode(function); cn = element_result; @@ -236,7 +236,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_MAP(EvaluableNode *en) for(size_t index = 0; index < largest_size; index++) { //set index value - SetTopTargetValueIndexInConstructionStack(static_cast(index)); + SetTopCurrentIndexInConstructionStack(static_cast(index)); //combine input slices together into value EvaluableNode *input_slice = evaluableNodeManager->AllocNode(ENT_LIST); @@ -251,7 +251,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_MAP(EvaluableNode *en) } is_ocn[i] = inputs[i]->GetOrderedChildNodes()[index]; } - SetTopTargetValueReferenceInConstructionStack(input_slice); + SetTopCurrentValueInConstructionStack(input_slice); EvaluableNodeReference element_result = InterpretNode(function); result->GetOrderedChildNodes()[index] = element_result; @@ -271,7 +271,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_MAP(EvaluableNode *en) for(size_t index = 0; index < largest_size; index++) { //set index value - SetTopTargetValueIndexInConstructionStack(static_cast(index)); + SetTopCurrentIndexInConstructionStack(static_cast(index)); //combine input slices together into value EvaluableNode *input_slice = evaluableNodeManager->AllocNode(ENT_LIST); @@ -296,7 +296,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_MAP(EvaluableNode *en) is_ocn[i] = inputs[i]->GetOrderedChildNodes()[index]; } } - SetTopTargetValueReferenceInConstructionStack(input_slice); + SetTopCurrentValueInConstructionStack(input_slice); EvaluableNodeReference element_result = InterpretNode(function); std::string index_string = EvaluableNode::NumberToString(index); @@ -314,7 +314,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_MAP(EvaluableNode *en) for(auto &index_sid : all_keys) { //set index value - SetTopTargetValueIndexInConstructionStack(index_sid); + SetTopCurrentIndexInConstructionStack(index_sid); //combine input slices together into value EvaluableNode *input_slice = evaluableNodeManager->AllocNode(ENT_LIST); @@ -332,7 +332,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_MAP(EvaluableNode *en) is_ocn[i] = *found; } } - SetTopTargetValueReferenceInConstructionStack(input_slice); + SetTopCurrentValueInConstructionStack(input_slice); EvaluableNodeReference element_result = InterpretNode(function); result->SetMappedChildNode(index_sid, element_result); @@ -491,8 +491,8 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_FILTER(EvaluableNode *en) { EvaluableNode *cur_value = list_ocn[i]; - SetTopTargetValueIndexInConstructionStack(static_cast(i)); - SetTopTargetValueReferenceInConstructionStack(cur_value); + SetTopCurrentIndexInConstructionStack(static_cast(i)); + SetTopCurrentValueInConstructionStack(cur_value); //check current element if(InterpretNodeIntoBoolValue(function)) @@ -574,8 +574,8 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_FILTER(EvaluableNode *en) //result_list is a copy of list, so it should already be the same size (no need to reserve) for(auto &[cn_id, cn] : list_mcn) { - SetTopTargetValueIndexInConstructionStack(cn_id); - SetTopTargetValueReferenceInConstructionStack(cn); + SetTopCurrentIndexInConstructionStack(cn_id); + SetTopCurrentValueInConstructionStack(cn); //if contained, add to result_list (and let SetMappedChildNode create the string reference) if(InterpretNodeIntoBoolValue(function)) @@ -725,58 +725,50 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_REDUCE(EvaluableNode *en) if(list == nullptr) return EvaluableNodeReference::Null(); - EvaluableNodeReference cur_value = EvaluableNodeReference::Null(); + EvaluableNodeReference previous_result = EvaluableNodeReference::Null(); + + PushNewConstructionContext(nullptr, list, EvaluableNodeImmediateValueWithType(), nullptr, previous_result); if(list->IsAssociativeArray()) { - bool first_node = (cur_value == nullptr); + bool first_node = true; //iterate over list for(auto &[n_id, n] : list->GetMappedChildNodesReference()) { //grab a value if first one if(first_node) { - cur_value = EvaluableNodeReference(n, false); //can't make any guarantees because used in a function + //can't make any guarantees about the first term because function may retrieve it + previous_result = EvaluableNodeReference(n, false); first_node = false; continue; } - //pass values to be mapped - PushNewConstructionContext(nullptr, list, EvaluableNodeImmediateValueWithType(), cur_value); - PushNewConstructionContext(nullptr, list, EvaluableNodeImmediateValueWithType(n_id), n); - - EvaluableNodeReference new_value = InterpretNode(function); - - PopConstructionContext(); - PopConstructionContext(); - - //move the current value over - cur_value = new_value; + SetTopCurrentIndexInConstructionStack(n_id); + SetTopCurrentValueInConstructionStack(n); + SetTopPreviousResultInConstructionStack(previous_result); + previous_result = InterpretNode(function); } } else if(list->GetOrderedChildNodes().size() >= 1) { auto &list_ocn = list->GetOrderedChildNodes(); - cur_value = EvaluableNodeReference(list_ocn[0], false); //can't make any guarantees because used in a function + //can't make any guarantees about the first term because function may retrieve it + previous_result = EvaluableNodeReference(list_ocn[0], false); //iterate over list for(size_t i = 1; i < list_ocn.size(); i++) { - //pass values to be mapped - PushNewConstructionContext(nullptr, list, EvaluableNodeImmediateValueWithType(), cur_value); - PushNewConstructionContext(nullptr, list, EvaluableNodeImmediateValueWithType(static_cast(i)), list_ocn[i]); - - EvaluableNodeReference new_value = InterpretNode(function); - - PopConstructionContext(); - PopConstructionContext(); - - //move the current value over - cur_value = new_value; + SetTopCurrentIndexInConstructionStack(static_cast(i)); + SetTopCurrentValueInConstructionStack(list_ocn[i]); + SetTopPreviousResultInConstructionStack(previous_result); + previous_result = InterpretNode(function); } } - return cur_value; + PopConstructionContext(); + + return previous_result; } EvaluableNodeReference Interpreter::InterpretNode_ENT_APPLY(EvaluableNode *en) @@ -1523,7 +1515,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_ASSOCIATE(EvaluableNode *e //get key StringInternPool::StringID key_sid = InterpretNodeIntoStringIDValueWithReference(ocn[i]); - SetTopTargetValueIndexInConstructionStack(key_sid); + SetTopCurrentIndexInConstructionStack(key_sid); //compute the value, but make sure have another node EvaluableNodeReference value; diff --git a/src/Amalgam/out.txt b/src/Amalgam/out.txt index b31ba7ce..dcc89439 100644 --- a/src/Amalgam/out.txt +++ b/src/Amalgam/out.txt @@ -65,6 +65,8 @@ notakeyword create_entities 0.1 crypto_sign 0.01 crypto_sign_verify 0.01 + current_index 0.1 + current_value 0.1 declare 0.5 decrypt 0.01 destroy_entities 0.1 @@ -131,6 +133,7 @@ notakeyword parallel 0.5 parse 0.05 pow 0.2 + previous_result 0.05 print 0.01 query_among 0.2 query_between 0.2 @@ -199,8 +202,6 @@ notakeyword tan 0.2 tanh 0.07 target 0.1 - target_index 0.1 - target_value 0.1 tgamma 0.07 total_entity_size 0.02 total_size 0.2 @@ -232,11 +233,11 @@ notakeyword (print "hello") (list .nan .nan .infinity -.infinity) -(assoc b 2 a 1 c (list "alpha" "beta" "gamma")) +(assoc a 1 c (list "alpha" "beta" "gamma") b 2) (assoc - b 2 a 1 c (list "alpha" "beta" "gamma") + b 2 ) --if-- @@ -585,7 +586,7 @@ abcdef 0.14384103622589045 --first-- 4 -2 +1 1 0 a @@ -600,18 +601,18 @@ a (list 1 2 3 4 5 6) (list) (assoc - a 1 b 2 c 3 d 4 e 5 + f 6 ) -(assoc c 3 d 4) +(assoc b 2 f 6) (assoc - a 1 + b 2 c 3 d 4 - e 5 + f 6 ) (assoc a 1 @@ -634,7 +635,7 @@ abcdef .nas --last-- this -2 +1 1 0 c @@ -649,18 +650,18 @@ c (list 1 2 3 4 5 6) (list) (assoc - a 1 b 2 c 3 d 4 e 5 + f 6 ) -(assoc c 3 d 4) +(assoc b 2 f 6) (assoc - a 1 + b 2 c 3 d 4 - e 5 + f 6 ) (assoc a 1 @@ -1006,7 +1007,7 @@ abcdef "2020-06-08 lunes 11.33.48" ) --indices-- -(list "4" "b" "a" "c") +(list "4" "a" "c" "b") (list 0 1 @@ -1018,7 +1019,7 @@ abcdef 7 ) --values-- -(list "d" 2 1 3) +(list "d" 1 3 2) (list "a" 1 @@ -1039,7 +1040,7 @@ abcdef 4 "d" ) -(list "d" 2 1 0 3) +(list "d" 1 0 3 2) (list 1 2 @@ -1198,13 +1199,20 @@ abcdef (assoc a 3 b 2) --target-- (list 1 2 3) ---target_index-- +--current_index-- 3 (null) (null) (null) ---target_value-- +--current_value-- (null) +--previous_result-- +current_index: 0 +(null) +current_index: 1 +0 +current_index: 2 +1 --stack-- (list (assoc @@ -1243,7 +1251,7 @@ abcdef interpreter "C:\\Users\\Chris Hazard\\Desktop\\Howso_repos\\amalgam\\x64\\MT_Release_EXE\\Amalgam.exe" raaa 2 rwww 1 - start_time 1699158667.067612 + start_time 1699368539.269825 www 1 x 12 zz 10 @@ -1286,7 +1294,7 @@ abcdef interpreter "C:\\Users\\Chris Hazard\\Desktop\\Howso_repos\\amalgam\\x64\\MT_Release_EXE\\Amalgam.exe" raaa 2 rwww 1 - start_time 1699158667.067612 + start_time 1699368539.269825 www 1 x 12 zz 10 @@ -1328,7 +1336,7 @@ abcdef interpreter "C:\\Users\\Chris Hazard\\Desktop\\Howso_repos\\amalgam\\x64\\MT_Release_EXE\\Amalgam.exe" raaa 2 rwww 1 - start_time 1699158667.067612 + start_time 1699368539.269825 www 1 x 12 zz 10 @@ -1461,7 +1469,7 @@ true --weighted_rand-- b -(list "b" "b" "b" "b") +(list "b" "b" "a" "b") b (list "a" "b" @(get (target 0) 0) @(get (target 0) 1)) @@ -1472,11 +1480,11 @@ infinity test c or d: (list "d" "d" "d" "c") infinity test c or d: (list "c" @(get (target 0) 0) "d" @(get (target 0) 0)) -(assoc a 30 b 46 c 24) +(assoc a 25 b 45 c 30) (assoc a 29 b 44 c 27) -(list "2" "4" "1") +(list "3" "8" "1") --get_rand_seed-- ȼ\KOaVT z @@ -1523,8 +1531,8 @@ infinity test c or d: (list "c" @(get (target 0) 0) "d" @(get (target 0) 0)) string --set_type-- (- 3 4) -(list "b" 3 "a" 4) -(list "b" 3 "a" 4) +(list "a" 4 "b" 3) +(list "a" 4 "b" 3) (assoc a 4 b 3) 8.7 (parallel @@ -1573,17 +1581,17 @@ string (assoc a 3 b 4) (assoc c "c") ) -21: [{"b":4,"a":3},{"c":"c","d":null}] +21: [{"a":3,"b":4},{"d":null,"c":"c"}] 22: [{"a":3,"b":4},{"c":"c","d":null}] -23: b: 2 -a: 1 +23: a: 1 e: - a - b - .nan - .inf -c: 3 d: 4 +c: 3 +b: 2 24: a: 1 b: 2 @@ -1596,7 +1604,7 @@ e: - .inf 25: (assoc a 1) -current date-time in epoch: 2023-11-05-00.31.07.3323480 +current date-time in epoch: 2023-11-07-09.48.59.6796740 2020-06-07 00:22:59 1391230800 1391230800 @@ -1874,33 +1882,33 @@ decrypted: hello 1 b 3 - (list) - (if) - (append) + (contains_value) + (compute_entity_group_kl_divergence) + (assoc) 7 8 9 - 3.813073356447116 - 11 - 12 b - (query_min_difference) - (associate "a" (seq) b b) + (set_value) + 12 + (values) + (append) + (associate b 1 (mutate) 2) ) (list 1 2 - 3 + (-) 4 (associate "alpha" 5 "beta" 6) (associate "nest" (associate - "count" - (list 7 8 (-)) + (-) + (list 7 8 9) ) "end" - (list (*) (+) 12) + (list 10 11 12) ) ) --commonality-- @@ -2079,21 +2087,21 @@ decrypted: hello (lambda (list (get - (target_value 1) + (current_value 1) 1 ) (get - (target_value 1) + (current_value 1) 2 ) 6 8 (get - (target_value 1) + (current_value 1) 4 ) (get - (target_value 1) + (current_value 1) 5 ) 14 @@ -2127,7 +2135,7 @@ decrypted: hello (lambda (list (get - (target_value 1) + (current_value 1) 0 ) 4 @@ -2150,7 +2158,7 @@ decrypted: hello (lambda (list (get - (target_value 1) + (current_value 1) 0 ) 4 @@ -2164,7 +2172,7 @@ decrypted: hello 2 g (get - (target_value 1) + (current_value 1) 3 ) ) @@ -2216,7 +2224,7 @@ decrypted: hello (lambda (list (get - (target_value 1) + (current_value 1) 0 ) 4 @@ -2227,7 +2235,7 @@ decrypted: hello (list 7 (get - (target_value 1) + (current_value 1) 1 ) ) @@ -2246,7 +2254,7 @@ decrypted: hello (lambda (list (get - (target_value 1) + (current_value 1) 0 ) 4 @@ -2273,7 +2281,7 @@ decrypted: hello (lambda (list (get - (target_value 1) + (current_value 1) 0 ) "x" @@ -2283,11 +2291,11 @@ decrypted: hello (lambda (list (get - (target_value 1) + (current_value 1) 0 ) (get - (target_value 1) + (current_value 1) 1 ) 4 @@ -2298,7 +2306,7 @@ decrypted: hello (list 7 (get - (target_value 1) + (current_value 1) 1 ) ) @@ -2318,10 +2326,10 @@ decrypted: hello 1 3.5 5.5 - 7.5 + 8 9.5 11.5 - 13.5 + 13 ) (list @@ -2331,37 +2339,55 @@ decrypted: hello ;comment 4 1 3.5 - 5.5 - 8 - 9.5 + 6 + 7.5 + 10 11.5 + 13.5 ) (list 1 + 5 2.5 (associate "a" 3 "b" 4) (lambda (if true 1 - (parallel (get_entity_comments) 1) + (parallel + (get_entity_comments) + 1 + (lambda + (print + (list 9) + ) + ) + ) ) ) - (list 5 6) + (list 6) ) (list 1 5 2.5 - (associate "b" 4) + (associate "a" 3 "b" 4) (lambda (if true 1 - (seq (get_entity_comments) 1) + (seq + (get_entity_comments) + (lambda + (print + (list 2 9) + ) + ) + 1 + ) ) ) - (list 6) + (list 5 6) ) (list (true) @@ -2375,19 +2401,19 @@ decrypted: hello (list 2 3 - 5 8 - 10 + 7 + 9 14 13 ) -4 -4 +1 +1 2.5 2.5 -abcdemxyz -abcomxyz abcdeomxyz +abcdexyz +abcdoxyz --mix_labels-- (list 1 @@ -2617,39 +2643,57 @@ flatten restore with parallel --mutate_entity-- (list 1 - 1 + (get) 3 4 - a - NKofOe - 7 + 5 + (floor) + (assoc) + (set_type) + (call) + 10 + 11 + b + 13 + 14 + (associate "a" (contains_index) b 2) +) + +(list + 1 + (dot_product) + 3 + (null) + 5 + 6 + (query_not_exists) 8 9 - (sqrt) - 11 + 10 + XXWA6ez 12 - 13 + (call_entity) 14 - (associate "a" (contains_value) "b" 2) + (associate b 1 "b" b) ) -a (list 1 - (-) (+) + 3 4 - (-) + (+) 6 7 + 8 (-) - 9 10 11 - 12 - (-) + (+) + (*) 14 - (associate (-) 1 (+) 2) + (associate "a" 1 "b" (+)) + (*) ) --commonality_entities-- @@ -2709,26 +2753,26 @@ _2280722175 ##p (list "_3990396532" "_3330773578" "_3990396532" "_3330773578") ) -_3990396532 +_3330773578 (associate - "E" + "e" 3 - "F" + "f" 4 - "G" + "g" 5 - "H" + "h" 6 ) -_3330773578 +_3990396532 (associate - "e" + "E" 3 - "f" + "F" 4 - "g" + "G" 5 - "h" + "H" 6 ) --difference_entities-- @@ -2755,13 +2799,13 @@ _3330773578 "c" 3 (get - (target_value + (current_value 1 ) 2 ) (get - (target_value + (current_value 1 ) 3 @@ -2796,19 +2840,19 @@ _3330773578 (set_type (list (get - (target_value 1) + (current_value 1) 0 ) (get - (target_value 1) + (current_value 1) 1 ) (get - (target_value 1) + (current_value 1) 2 ) (get - (target_value 1) + (current_value 1) 3 ) "z" @@ -2846,19 +2890,19 @@ _3330773578 (set_type (list (get - (target_value 1) + (current_value 1) 0 ) (get - (target_value 1) + (current_value 1) 1 ) (get - (target_value 1) + (current_value 1) 2 ) (get - (target_value 1) + (current_value 1) 3 ) "u" @@ -2900,19 +2944,19 @@ _3330773578 (set_type (list (get - (target_value 1) + (current_value 1) 0 ) (get - (target_value 1) + (current_value 1) 1 ) (get - (target_value 1) + (current_value 1) 2 ) (get - (target_value 1) + (current_value 1) 3 ) "G" @@ -2952,19 +2996,19 @@ _3330773578 (set_type (list (get - (target_value 1) + (current_value 1) 0 ) (get - (target_value 1) + (current_value 1) 1 ) (get - (target_value 1) + (current_value 1) 2 ) (get - (target_value 1) + (current_value 1) 3 ) ) @@ -3008,13 +3052,13 @@ _432807187 "c" 3 (get - (target_value + (current_value 1 ) 2 ) (get - (target_value + (current_value 1 ) 3 @@ -3049,23 +3093,23 @@ _432807187 (set_type (list (get - (target_value 1) + (current_value 1) 0 ) (get - (target_value 1) + (current_value 1) 1 ) (get - (target_value 1) + (current_value 1) 2 ) (get - (target_value 1) + (current_value 1) 3 ) (get - (target_value 1) + (current_value 1) 4 ) 5 @@ -3129,19 +3173,19 @@ _432807187 (set_type (list (get - (target_value 1) + (current_value 1) 0 ) (get - (target_value 1) + (current_value 1) 1 ) (get - (target_value 1) + (current_value 1) 2 ) (get - (target_value 1) + (current_value 1) 3 ) "G" @@ -3181,19 +3225,19 @@ _432807187 (set_type (list (get - (target_value 1) + (current_value 1) 0 ) (get - (target_value 1) + (current_value 1) 1 ) (get - (target_value 1) + (current_value 1) 2 ) (get - (target_value 1) + (current_value 1) 3 ) ) @@ -3249,13 +3293,13 @@ _41032496 "c" 3 (get - (target_value + (current_value 1 ) 2 ) (get - (target_value + (current_value 1 ) 3 @@ -3317,19 +3361,19 @@ _41032496 (set_type (list (get - (target_value 1) + (current_value 1) 0 ) (get - (target_value 1) + (current_value 1) 1 ) (get - (target_value 1) + (current_value 1) 2 ) (get - (target_value 1) + (current_value 1) 3 ) "G" @@ -3369,19 +3413,19 @@ _41032496 (set_type (list (get - (target_value 1) + (current_value 1) 0 ) (get - (target_value 1) + (current_value 1) 1 ) (get - (target_value 1) + (current_value 1) 2 ) (get - (target_value 1) + (current_value 1) 3 ) ) @@ -3426,26 +3470,17 @@ MergeEntityChild2 3 "q" 4 - "u" - 5 "v" 6 + "w" + 7 ) MergeEntityChild1 (associate "x" 3 "y" 4) _2169689611 -(associate - "e" - 3 - "f" - 4 - "g" - 5 - "h" - 6 -) +(associate "e" 3 "f" 4) _2280722175 -(associate "E" 3 "F" 4 "H" 6) +(associate "E" 3 "F" 4 "G" 5) --get_entity_comments-- Full test This is a suite of unit tests. @@ -3500,7 +3535,7 @@ deep sets --set_entity_root_permission-- RootTest -1699158667.574166 +1699368539.937534 (true) RootTest @@ -3730,7 +3765,7 @@ hello ) ) ) - (set_entity_rand_seed new_entity "=?f'0є-I") + (set_entity_rand_seed new_entity "JF3:0є-I") (set_entity_rand_seed (first (create_entities @@ -3743,7 +3778,7 @@ hello ) ) ) - "I<,ɪ(߁߂" + "e 3B?'0" ) (set_entity_rand_seed (first @@ -3779,7 +3814,7 @@ hello ) ) ) - (set_entity_rand_seed new_entity "=?f'0є-I") + (set_entity_rand_seed new_entity "JF3:0є-I") (set_entity_rand_seed (first (create_entities @@ -3887,74 +3922,74 @@ store to .json normally (list "Child2" "Child7") (list "Child1" "Child5") (list "Child3" "Child4") -(list "Child1" "Child2" "Child3" "Child5") -(list "Child2" "Child5" "Child6" "Child7") +(list "Child1" "Child4" "Child6" "Child7") +(list "Child2" "Child3" "Child6" "Child7") (list "Child4" "Child6") --query_sample-- -(list "Child4") -(list "Child1" "Child1") +(list "Child3") +(list "Child5" "Child2") +(list "Child6") (list "Child6") -(list "Child7") --query_weighted_sample-- -(list "Child7") -(list "Child7") +(list "Child1") +(list "Child1") (list "Child1" - "Child1" - "Child1" + "Child6" "Child1" "Child2" "Child2" "Child2" "Child2" "Child1" + "Child6" "Child2" "Child2" - "Child1" - "Child6" "Child2" "Child1" "Child1" - "Child1" "Child2" + "Child2" + "Child4" "Child1" "Child1" + "Child2" ) (list + "Child7" + "Child5" + "Child1" "Child2" "Child2" - "Child2" - "Child2" - "Child2" + "Child4" "Child1" "Child1" "Child2" "Child2" - "Child5" - "Child1" - "Child1" - "Child1" - "Child1" "Child2" + "Child1" "Child2" + "Child4" + "Child1" "Child2" "Child2" - "Child5" "Child2" + "Child4" + "Child1" ) (list - "Child6" "Child2" "Child2" "Child2" "Child2" "Child2" + "Child5" "Child2" "Child5" "Child2" "Child2" ) -(list "Child2" "Child6") +(list "Child2") --query_in_entity_list-- (list "Child6" "Child7") --query_not_in_entity_list-- @@ -4317,15 +4352,15 @@ case conviction:(assoc ) cyclic feature nearest neighbors: (assoc cyclic1 1 cyclic5 0.5) cyclic test expected: 155, 200, 190 ... deg values of 0 8 and 12: -155: 0.1 (null - ##deg 0 -) 200: 0.05555555555555555 (null ##deg 8 ) 190: 0.045454545454545456 (null ##deg 12 ) +155: 0.1 (null + ##deg 0 +) --contains_label-- (true) @@ -4502,13 +4537,13 @@ distance symmetry tests (list (list "B" - "I" "C" "D" - "F" "A" - "H" + "I" + "F" "J" + "E" ) (list 0 @@ -4525,10 +4560,10 @@ distance symmetry tests (list "B" "A" - "F" "C" - "I" + "F" "D" + "I" "H" "J" ) @@ -4723,4 +4758,4 @@ Expecting 1000: 1000 concurrent entity writes successful: (true) --total execution time-- -1.107090950012207 +1.6134569644927979