fable 3.0.134 → 3.0.136

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "type": "node",
9
+ "request": "launch",
10
+ "name": "Launch Program",
11
+ "skipFiles": [
12
+ "<node_internals>/**"
13
+ ],
14
+ "program": "${workspaceFolder}/Math-Solver-Harness.js"
15
+ }
16
+ ]
17
+ }
@@ -15,35 +15,35 @@ _Fable.log.info(`One-liner solve is: ${_Fable.ExpressionParser.solve("Result = 7
15
15
  // Let's put it in a variable for easier exercises
16
16
  const _ExpressionParser = _Fable.ExpressionParser;
17
17
  // Look up somoe variables in an object
18
- _Fable.log.info(`One-liner solve with variables is: ${_ExpressionParser.solve("Volume = Width * Height * Depth", {"Width": 73.5, "Height": 28.8, "Depth": 200.5})}`);
18
+ // _Fable.log.info(`One-liner solve with variables is: ${_ExpressionParser.solve("Volume = Width * Height * Depth", {"Width": 73.5, "Height": 28.8, "Depth": 200.5})}`);
19
19
 
20
20
 
21
- /* * * * * * * * * * * * * * * * *
22
- *
23
- * A simple run through of some mathematical expressions
24
- *
25
- */
26
- _Fable.log.info(`Beginning Run-through for Set of Test Expressions....`);
27
- // An array of equations with expected values
28
- let _Equations = require(`./Equations.json`);
29
- // The application state is a plain javascript object we pass into the solver to pull variables from
30
- let _AppData = require(`./AppData.json`);
31
- // The manifest is a Manyfest which describes hashes for complex addresses in the application state object
32
- // For example you can't use "Student[0].Age" as a variable in the expression
33
- // ...but you can use "Student[0].Age" as an address in the manifest with a hash of "StudentAge"
34
- // ...and then reference "StudentAge" in the expression.
35
- let tmpManifestConfiguration = { "Scope":"None", "Descriptors":[] };
36
- let tmpManifest = _Fable.newManyfest(tmpManifestConfiguration);
37
- // Run each expression in the Equations.json file through the expression parser.
38
- for (let i = 0; i < _Equations.Expressions.length; i++)
39
- {
40
- let tmpResultValue = _ExpressionParser.solve(_Equations.Expressions[i].Equation, _AppData, {}, tmpManifest);
41
- console.log(`Expression [${i}]: [${_Equations.Expressions[i].Equation}] ==> ${tmpResultValue}`);
42
- if (tmpResultValue !== _Equations.Expressions[i].ExpectedResult)
43
- {
44
- console.log(`Error: Equation ${_Equations.Expressions[i].Equation} expected [${_Equations.Expressions[i].ExpectedResult}] but got [${tmpResultValue}]`);
45
- }
46
- }
21
+ // /* * * * * * * * * * * * * * * * *
22
+ // *
23
+ // * A simple run through of some mathematical expressions
24
+ // *
25
+ // */
26
+ // _Fable.log.info(`Beginning Run-through for Set of Test Expressions....`);
27
+ // // An array of equations with expected values
28
+ // let _Equations = require(`./Equations.json`);
29
+ // // The application state is a plain javascript object we pass into the solver to pull variables from
30
+ // let _AppData = require(`./AppData.json`);
31
+ // // The manifest is a Manyfest which describes hashes for complex addresses in the application state object
32
+ // // For example you can't use "Student[0].Age" as a variable in the expression
33
+ // // ...but you can use "Student[0].Age" as an address in the manifest with a hash of "StudentAge"
34
+ // // ...and then reference "StudentAge" in the expression.
35
+ // let tmpManifestConfiguration = { "Scope":"None", "Descriptors":[] };
36
+ // let tmpManifest = _Fable.newManyfest(tmpManifestConfiguration);
37
+ // // Run each expression in the Equations.json file through the expression parser.
38
+ // for (let i = 0; i < _Equations.Expressions.length; i++)
39
+ // {
40
+ // let tmpResultValue = _ExpressionParser.solve(_Equations.Expressions[i].Equation, _AppData, {}, tmpManifest);
41
+ // console.log(`Expression [${i}]: [${_Equations.Expressions[i].Equation}] ==> ${tmpResultValue}`);
42
+ // if (tmpResultValue !== _Equations.Expressions[i].ExpectedResult)
43
+ // {
44
+ // console.log(`Error: Equation ${_Equations.Expressions[i].Equation} expected [${_Equations.Expressions[i].ExpectedResult}] but got [${tmpResultValue}]`);
45
+ // }
46
+ // }
47
47
 
48
48
 
49
49
  /* * * * * * * * * * * * * * * * *
@@ -59,7 +59,7 @@ let _FruitManifest = _Fable.newManyfest(_FruitManifestDescription);
59
59
  _Fable.log.info(`Beginning Manual Solve with Embedded Fruit Data....`);
60
60
 
61
61
  // The expression we pass into the solver is just a string
62
- let tmpExpression = 'HyperMax.HealthIndex = (SUM(Calories) / SUM(Sugar)) * MEDIAN(Fat) + (SQRT(AVG(Protein)) - (PI() + 99)';
62
+ let tmpExpression = 'HyperMax.HealthIndex = (SUM(Calories) / SUM(Sugar)) * MEDIAN(Fat) + (SQRT(AVG(Protein)) - (PI() + 99))';
63
63
  _Fable.log.info(`Solving tmpExpression: [${tmpExpression}]`);
64
64
 
65
65
  // This is an object where the parser will write out the results of each phase of the compiler/parser/solver
@@ -74,15 +74,12 @@ let complexLintedResults = _ExpressionParser.lintTokenizedExpression(complexToke
74
74
  let complexPostfixedResults = _ExpressionParser.buildPostfixedSolveList(complexTokenizedResults, tmpExpressionParseOutcome);
75
75
  // Step 4: Substitute the values references in the tokenized objects representing data within the postfixed expression
76
76
  _ExpressionParser.substituteValuesInTokenizedObjects(tmpExpressionParseOutcome.PostfixTokenObjects, _FruitData, tmpExpressionParseOutcome, _FruitManifest);
77
- // Now that we have a postfixed expression and the mapped-in values, show the user what the solution steps look like
78
- for (let i = 0; i < tmpExpressionParseOutcome.PostfixSolveList.length; i++)
79
- {
80
- let tmpToken = tmpExpressionParseOutcome.PostfixSolveList[i];
81
- console.log(`${i}: ${tmpToken.VirtualSymbolName} = (${tmpToken.LeftValue.Token}::${tmpToken.LeftValue.Value}) ${tmpToken.Operation.Token} (${tmpToken.RightValue.Token}::${tmpToken.RightValue.Value}) `)
82
- }
83
77
  // Step 5: Solve the postfixed expression
84
78
  let tmpResultValue = _ExpressionParser.solvePostfixedExpression(tmpExpressionParseOutcome.PostfixSolveList, tmpSolverResultsObject, tmpExpressionParseOutcome, _FruitManifest);
85
79
 
80
+ // Now that we have a solved expression and the mapped-in values, show the user the solution
81
+ _Fable.ExpressionParser.Messaging.logFunctionOutcome(tmpExpressionParseOutcome);
82
+
86
83
  // Step 6: Look at the results.
87
84
  console.log(`Outcome object: ${JSON.stringify(tmpSolverResultsObject)}`);
88
85
  console.log(`Result of ${tmpExpression} solve: ${tmpResultValue}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fable",
3
- "version": "3.0.134",
3
+ "version": "3.0.136",
4
4
  "description": "A service dependency injection, configuration and logging library.",
5
5
  "main": "source/Fable.js",
6
6
  "scripts": {
@@ -5,7 +5,6 @@ class ExpressionTokenizer extends libExpressionParserOperationBase
5
5
  constructor(pFable, pOptions, pServiceHash)
6
6
  {
7
7
  super(pFable, pOptions, pServiceHash);
8
-
9
8
  this.serviceType = 'ExpressionParser-Tokenizer';
10
9
  }
11
10
 
@@ -5,7 +5,6 @@ class ExpressionParserLinter extends libExpressionParserOperationBase
5
5
  constructor(pFable, pOptions, pServiceHash)
6
6
  {
7
7
  super(pFable, pOptions, pServiceHash);
8
-
9
8
  this.serviceType = 'ExpressionParser-Linter';
10
9
  }
11
10
 
@@ -0,0 +1,159 @@
1
+ const { PE } = require('big.js');
2
+ const libExpressionParserOperationBase = require('./Fable-Service-ExpressionParser-Base.js');
3
+
4
+ /**
5
+ * Represents a user-friendly messaging service for the ExpressionParser compiler output.
6
+ * @class ExpressionParserMessaging
7
+ * @extends libExpressionParserOperationBase
8
+ */
9
+ class ExpressionParserMessaging extends libExpressionParserOperationBase
10
+ {
11
+ constructor(pFable, pOptions, pServiceHash)
12
+ {
13
+ super(pFable, pOptions, pServiceHash);
14
+ this.serviceType = 'ExpressionParser-Messaging';
15
+ }
16
+
17
+ getOperationVirtualSymbolName(pOperationToken)
18
+ {
19
+ return (pOperationToken && ('VirtualSymbolName' in pOperationToken)) ? pOperationToken.VirtualSymbolName
20
+ : (pOperationToken.Type === 'Token.VirtualSymbol') ? pOperationToken.Token
21
+ : 'NO_VIRTUAL_SYMBOL_NAME_FOUND';
22
+ }
23
+
24
+ getVirtualTokenValue(pToken, pOperationResults)
25
+ {
26
+ let tmpVirtualSymbol = this.getOperationVirtualSymbolName(pToken);
27
+ let tmpVirtualSymbolData = ('VirtualSymbols' in pOperationResults) ? pOperationResults.VirtualSymbols : {};
28
+
29
+ if (this.ExpressionParser.GenericManifest.checkAddressExists(tmpVirtualSymbolData, tmpVirtualSymbol))
30
+ {
31
+ let tmpValue = this.ExpressionParser.GenericManifest.getValueAtAddress(tmpVirtualSymbolData, tmpVirtualSymbol);
32
+
33
+ if (typeof(tmpValue) === 'object')
34
+ {
35
+ return `{${Object.keys(tmpValue).length} values}`;
36
+ }
37
+ if (Array.isArray(tmpValue))
38
+ {
39
+ return `[${Object.keys(tmpValue).length} values]`;
40
+ }
41
+ return tmpValue;
42
+ }
43
+
44
+ return 'NO_VALUE_FOUND';
45
+ }
46
+
47
+ getTokenAddressString(pToken)
48
+ {
49
+ return pExpression.Token;
50
+ }
51
+
52
+ getTokenSymbolString(pExpressionToken)
53
+ {
54
+ return pExpressionToken.Token;
55
+ }
56
+
57
+ getOperationSymbolMessage(pOperation)
58
+ {
59
+ if (!pOperation)
60
+ {
61
+ return 'INVALID_OPERATION';
62
+ }
63
+ let tmpOperationVirtualSymbol = this.getOperationVirtualSymbolName(pOperation);
64
+ let tmpOperationLeftValue = this.getTokenSymbolString(pOperation.LeftValue);
65
+ let tmpOperationSymbol = this.getTokenSymbolString(pOperation.Operation);
66
+ let tmpOperationRightValue = this.getTokenSymbolString(pOperation.RightValue);
67
+
68
+ let tmpVirtualSymbolPrefix = tmpOperationVirtualSymbol.substring(0, 3);
69
+
70
+ if (tmpOperationSymbol === '=')
71
+ {
72
+ // Assignment operators are special
73
+ return `${tmpOperationVirtualSymbol} = ${tmpOperationLeftValue}`;
74
+ }
75
+
76
+ if (tmpVirtualSymbolPrefix === 'VFE')
77
+ {
78
+ // Virtual Function Expression
79
+ return `${tmpOperationVirtualSymbol} = ${tmpOperationSymbol}(${tmpOperationRightValue})`;
80
+ }
81
+
82
+ return `${tmpOperationVirtualSymbol} = ${tmpOperationLeftValue} ${tmpOperationSymbol} ${tmpOperationRightValue}`;
83
+ }
84
+
85
+ getOperationValueMessage(pOperation, pResultObject)
86
+ {
87
+ if (!pOperation)
88
+ {
89
+ return 'INVALID_OPERATION';
90
+ }
91
+ let tmpOperationVirtualSymbol = this.getOperationVirtualSymbolName(pOperation);
92
+ let tmpOperationLeftValue = this.getVirtualTokenValue(pOperation.LeftValue, pResultObject);
93
+ let tmpOperationSymbol = this.getTokenSymbolString(pOperation.Operation);
94
+ let tmpOperationRightValue = this.getVirtualTokenValue(pOperation.RightValue, pResultObject);
95
+
96
+ let tmpVirtualSymbolPrefix = tmpOperationVirtualSymbol.substring(0, 3);
97
+
98
+ if (tmpOperationSymbol === '=')
99
+ {
100
+ // Assignment operators are special
101
+ return `${tmpOperationVirtualSymbol} = ${tmpOperationLeftValue}`;
102
+ }
103
+
104
+ if (tmpVirtualSymbolPrefix === 'VFE')
105
+ {
106
+ // Virtual Function Expression
107
+ return `${tmpOperationVirtualSymbol} = ${tmpOperationSymbol}(${tmpOperationLeftValue})`;
108
+ }
109
+
110
+ return `${tmpOperationVirtualSymbol} = ${tmpOperationLeftValue} ${tmpOperationSymbol} ${tmpOperationRightValue}`;
111
+ }
112
+
113
+ logFunctionOutcome(pResultObject)
114
+ {
115
+ if (typeof(pResultObject) !== 'object')
116
+ {
117
+ this.log.error(`Solver results object was not an object. Cannot log outcome.`);
118
+ return;
119
+ }
120
+ let tmpAssignmentAddress = ('PostfixedAssignmentAddress' in pResultObject) ? pResultObject.PostfixedAssignmentAddress : 'NO_ASSIGNMENT_ADDRESS_FOUND';
121
+ let tmpRawExpression = ('RawExpression' in pResultObject) ? pResultObject.RawExpression : 'NO_EXPRESSION_FOUND';
122
+ let tmpRawResult = ('RawResult' in pResultObject) ? pResultObject.RawResult : 'NO_RESULT_FOUND';
123
+
124
+ this.log.info(`Solved f(${tmpAssignmentAddress}) = {${tmpRawExpression}}`);
125
+ for (let i = 0; i < pResultObject.PostfixSolveList.length; i++)
126
+ {
127
+ let tmpToken = pResultObject.PostfixSolveList[i];
128
+ let tmpTokenSymbolMessage = this.getOperationSymbolMessage(tmpToken);
129
+ this.log.info(`${i} Symbols: ${tmpTokenSymbolMessage}`);
130
+ let tmpTokenValueMessage = this.getOperationValueMessage(tmpToken, pResultObject);
131
+ this.log.info(`${i} Values: ${tmpTokenValueMessage}`);
132
+ }
133
+ this.log.info(`{${tmpRawExpression}} = ${tmpRawResult}`);
134
+ }
135
+
136
+ logFunctionSolve(pResultObject)
137
+ {
138
+ if (typeof(pResultObject) !== 'object')
139
+ {
140
+ this.log.error(`Solver results object was not an object. Cannot log the solve.`);
141
+ return;
142
+ }
143
+ if (!('PostfixSolveList' in pResultObject) || !Array.isArray(pResultObject.PostfixSolveList))
144
+ {
145
+ this.log.error(`Solver results object did not contain a PostfixSolveList array. Cannot log the solve.`);
146
+ return;
147
+ }
148
+
149
+ for (let i = 0; i < tmpExpressionParseOutcome.PostfixSolveList.length; i++)
150
+ {
151
+ let tmpToken = tmpExpressionParseOutcome.PostfixSolveList[i];
152
+ console.log(`${i}: ${tmpToken.VirtualSymbolName} = (${tmpToken.LeftValue.Token}::${tmpToken.LeftValue.Value}) ${tmpToken.Operation.Token} (${tmpToken.RightValue.Token}::${tmpToken.RightValue.Value}) `)
153
+ }
154
+
155
+ this.logFunctionOutcome(pResultObject);
156
+ }
157
+ }
158
+
159
+ module.exports = ExpressionParserMessaging;
@@ -5,7 +5,6 @@ class ExpressionParserPostfix extends libExpressionParserOperationBase
5
5
  constructor(pFable, pOptions, pServiceHash)
6
6
  {
7
7
  super(pFable, pOptions, pServiceHash);
8
-
9
8
  this.serviceType = 'ExpressionParser-Postfix';
10
9
  }
11
10
 
@@ -638,9 +637,13 @@ class ExpressionParserPostfix extends libExpressionParserOperationBase
638
637
  }
639
638
 
640
639
  // 7. Lastly set the assignment address.
641
- let tmpAssignmentInstruction = this.getPosfixSolveListOperation(this.getTokenContainerObject('Assign', 'Token.SolverInstruction'), this.getTokenContainerObject('DestinationHash', 'Token.SolverInstruction'), this.getTokenContainerObject('Resulting', 'Token.SolverInstruction'));
642
- tmpAssignmentInstruction.VirtualSymbolName = tmpResults.PostfixedAssignmentAddress;
643
- tmpResults.PostfixSolveList.push(tmpAssignmentInstruction);
640
+ let tmpAbstractAssignToken = this.getTokenContainerObject('=');
641
+ // The address we are assigning to
642
+ tmpAbstractAssignToken.VirtualSymbolName = tmpResults.PostfixedAssignmentAddress;
643
+ // The address it's coming from
644
+ let tmpSolveResultToken = this.getTokenContainerObject('Result', 'Token.LastResult');
645
+ let tmpFinalAssignmentInstruction = this.getPosfixSolveListOperation(tmpAbstractAssignToken, tmpSolveResultToken, this.getTokenContainerObject('SolverMarshal', 'Token.SolverMarshal'));
646
+ tmpResults.PostfixSolveList.push(tmpFinalAssignmentInstruction);
644
647
 
645
648
  return tmpResults.PostfixSolveList;
646
649
  }
@@ -5,7 +5,6 @@ class ExpressionParserSolver extends libExpressionParserOperationBase
5
5
  constructor(pFable, pOptions, pServiceHash)
6
6
  {
7
7
  super(pFable, pOptions, pServiceHash);
8
-
9
8
  this.serviceType = 'ExpressionParser-Solver';
10
9
  }
11
10
 
@@ -48,7 +47,15 @@ class ExpressionParserSolver extends libExpressionParserOperationBase
48
47
  }
49
48
  let tmpStepResultObject = { ExpressionStep: pPostfixedExpression[i], ExpressionStepIndex: i, ResultsObject: tmpResults, Manifest: tmpManifest};
50
49
 
51
- // Resolve the virtual symbols to their actual values
50
+ if (tmpStepResultObject.ExpressionStep.LeftValue.Type === 'Token.LastResult')
51
+ {
52
+ tmpStepResultObject.ExpressionStep.LeftValue.Value = tmpResults.LastResult;
53
+ }
54
+ if (tmpStepResultObject.ExpressionStep.RightValue.Type === 'Token.LastResult')
55
+ {
56
+ tmpStepResultObject.ExpressionStep.RightValue.Value = tmpResults.LastResult;
57
+ }
58
+
52
59
  if (tmpStepResultObject.ExpressionStep.LeftValue.Type === 'Token.VirtualSymbol')
53
60
  {
54
61
  tmpStepResultObject.ExpressionStep.LeftValue.Value = tmpManifest.getValueAtAddress(tmpResults.VirtualSymbols, tmpStepResultObject.ExpressionStep.LeftValue.Token);
@@ -94,9 +101,10 @@ class ExpressionParserSolver extends libExpressionParserOperationBase
94
101
 
95
102
  try
96
103
  {
97
- this.log.trace(`Solving Step ${i} [${tmpStepResultObject.ExpressionStep.VirtualSymbolName}] --> [${tmpStepResultObject.ExpressionStep.Operation.Token}]: ( ${tmpStepResultObject.ExpressionStep.LeftValue.Value} , ${tmpStepResultObject.ExpressionStep.RightValue.Value} )`);
98
- tmpResults.VirtualSymbols[tmpStepResultObject.ExpressionStep.VirtualSymbolName] = tmpManifest.getValueAtAddress(tmpStepResultObject, `${tmpFunctionAddress}(ExpressionStep.LeftValue.Value,ExpressionStep.RightValue.Value)`);
99
- this.log.trace(` ---> Step ${i}: ${tmpResults.VirtualSymbols[tmpStepResultObject.ExpressionStep.VirtualSymbolName]}`)
104
+ //this.log.trace(`Solving Step ${i} [${tmpStepResultObject.ExpressionStep.VirtualSymbolName}] --> [${tmpStepResultObject.ExpressionStep.Operation.Token}]: ( ${tmpStepResultObject.ExpressionStep.LeftValue.Value} , ${tmpStepResultObject.ExpressionStep.RightValue.Value} )`);
105
+ tmpManifest.setValueAtAddress(tmpResults.VirtualSymbols, tmpStepResultObject.ExpressionStep.VirtualSymbolName, tmpManifest.getValueAtAddress(tmpStepResultObject, `${tmpFunctionAddress}(ExpressionStep.LeftValue.Value,ExpressionStep.RightValue.Value)`));
106
+ tmpResults.LastResult = tmpManifest.getValueAtAddress(tmpResults.VirtualSymbols, tmpStepResultObject.ExpressionStep.VirtualSymbolName);
107
+ //this.log.trace(` ---> Step ${i}: ${tmpResults.VirtualSymbols[tmpStepResultObject.ExpressionStep.VirtualSymbolName]}`)
100
108
  }
101
109
  catch (pError)
102
110
  {
@@ -112,17 +120,18 @@ class ExpressionParserSolver extends libExpressionParserOperationBase
112
120
 
113
121
  let tmpSolverResultValue = tmpManifest.getValueAtAddress(tmpResults, `VirtualSymbols.${tmpResults.SolverFinalVirtualSymbol}`);
114
122
 
115
- // Now deal with final assignment
123
+ // Now deal with final assignment(s)
116
124
  for (let i = 0; i < pPostfixedExpression.length; i++)
117
125
  {
118
- if ((pPostfixedExpression[i].Operation.Type === 'Token.SolverInstruction') && (pPostfixedExpression[i].Operation.Token == 'Assign'))
126
+ if (pPostfixedExpression[i].RightValue.Type === 'Token.SolverMarshal')
119
127
  {
120
128
  tmpManifest.setValueAtAddress(tmpResults.VirtualSymbols, pPostfixedExpression[i].VirtualSymbolName, tmpSolverResultValue);
121
129
  tmpManifest.setValueByHash(tmpDataDestinationObject, pPostfixedExpression[i].VirtualSymbolName, tmpSolverResultValue);
122
130
  }
123
-
124
131
  }
125
- // Clean up the reference if we added it to the object.
132
+ tmpResults.RawResult = tmpSolverResultValue;
133
+
134
+ // Clean up the fable reference if we added it to the object.
126
135
  if (!tmpPassedInFable)
127
136
  {
128
137
  delete tmpResults.fable;
@@ -0,0 +1,146 @@
1
+ const libExpressionParserOperationBase = require('./Fable-Service-ExpressionParser-Base.js');
2
+
3
+ class ExpressionParserValueMarshal extends libExpressionParserOperationBase
4
+ {
5
+ constructor(pFable, pOptions, pServiceHash)
6
+ {
7
+ super(pFable, pOptions, pServiceHash);
8
+ this.serviceType = 'ExpressionParser-ValueMarshal';
9
+ }
10
+
11
+ /**
12
+ * Substitutes values in tokenized objects based on the provided data source and manifest.
13
+ *
14
+ * TODO: Move this to its own file in the "Fable-Service-ExpressionParser" directory.
15
+ *
16
+ * @param {Array} pTokenizedObjects - The array of tokenized objects.
17
+ * @param {Object} pDataSource - The data source object where we pull values from.
18
+ * @param {Object} pResultObject - The result object where the algorithm shows its work.
19
+ * @param {Object} pManifest - The manifest object to use for hash resolution.
20
+ * @returns {Array} - The modified tokenized objects array.
21
+ */
22
+ substituteValuesInTokenizedObjects(pTokenizedObjects, pDataSource, pResultObject, pManifest)
23
+ {
24
+ let tmpResults = (typeof(pResultObject) === 'object') ? pResultObject : { ExpressionParserLog: [] };
25
+
26
+ if (!Array.isArray(pTokenizedObjects))
27
+ {
28
+ tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.substituteValuesInTokenizedObjects was passed a non-array tokenized object list.`);
29
+ this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
30
+ return pTokenizedObjects;
31
+ }
32
+ if (typeof(pDataSource) !== 'object')
33
+ {
34
+ tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.substituteValuesInTokenizedObjects either was passed no data source, or was passed a non-object data source.`);
35
+ this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
36
+ return pTokenizedObjects;
37
+ }
38
+
39
+ let tmpDataSource = pDataSource;
40
+
41
+ let tmpManifest = (typeof(pManifest) == 'object') ? pManifest : this.fable.newManyfest(pManifest);
42
+
43
+ for (let i = 0; i < pTokenizedObjects.length; i++)
44
+ {
45
+ if (typeof(pTokenizedObjects[i]) !== 'object')
46
+ {
47
+ tmpResults.ExpressionParserLog.push(`WARNING: ExpressionParser.substituteValuesInTokenizedObjects found a non-object tokenized object at index ${i}`);
48
+ this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
49
+ continue;
50
+ }
51
+ let tmpToken = pTokenizedObjects[i];
52
+ if ((pTokenizedObjects[i].Type === 'Token.Symbol') && !tmpToken.Resolved)
53
+ {
54
+ // Symbols always look up values by hash first
55
+ let tmpValue = tmpManifest.getValueByHash(tmpDataSource, tmpToken.Token);
56
+ // if (!tmpValue)
57
+ // {
58
+ // // If no hash resolves, try by address.
59
+ // tmpValue = tmpManifest.getValueAtAddress(tmpToken.Token, tmpDataSource);
60
+ // }
61
+ if (!tmpValue)
62
+ {
63
+ tmpResults.ExpressionParserLog.push(`WARNING: ExpressionParser.substituteValuesInTokenizedObjects found no value for the symbol hash or address ${tmpToken.Token} at index ${i}`);
64
+ this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
65
+ continue;
66
+ }
67
+ else
68
+ {
69
+ tmpResults.ExpressionParserLog.push(`INFO: ExpressionParser.substituteValuesInTokenizedObjects found a value [${tmpValue}] for the state address ${tmpToken.Token} at index ${i}`);
70
+ if (this.LogNoisiness > 1) this.log.info(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
71
+ try
72
+ {
73
+ let tmpValueParsed = new this.fable.Utility.bigNumber(tmpValue);
74
+ tmpToken.Resolved = true;
75
+ tmpToken.Value = tmpValueParsed.toString();
76
+ }
77
+ catch(pError)
78
+ {
79
+ // TODO: Should we allow this to be a function? Good god the complexity and beauty of that...
80
+ if (Array.isArray(tmpValue) || (typeof(tmpValue) === 'object'))
81
+ {
82
+ tmpToken.Resolved = true;
83
+ tmpToken.Value = tmpValue;
84
+ }
85
+ else
86
+ {
87
+ tmpResults.ExpressionParserLog.push(`INFO: ExpressionParser.substituteValuesInTokenizedObjects found a non-numeric, non-set value for the state address ${tmpToken.Token} at index ${i}`);
88
+ this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
89
+ tmpToken.Resolved = false;
90
+ }
91
+ }
92
+ }
93
+ }
94
+ if ((pTokenizedObjects[i].Type === 'Token.StateAddress') && !tmpToken.Resolved)
95
+ {
96
+ // Symbols are always hashes. This gracefully works for simple shallow objects because hashes default to the address in Manyfest.
97
+ let tmpValue = tmpManifest.getValueAtAddress(tmpDataSource, tmpToken.Token);
98
+ if (!tmpValue)
99
+ {
100
+ tmpResults.ExpressionParserLog.push(`WARNING: ExpressionParser.substituteValuesInTokenizedObjects found no value for the state address ${tmpToken.Token} at index ${i}`);
101
+ this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
102
+ continue;
103
+ }
104
+ else
105
+ {
106
+ //tmpResults.ExpressionParserLog.push(`INFO: ExpressionParser.substituteValuesInTokenizedObjects found a value [${tmpValue}] for the state address ${tmpToken.Token} at index ${i}`);
107
+ this.log.info(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
108
+ try
109
+ {
110
+ let tmpValueParsed = new this.fable.Utility.bigNumber(tmpValue);
111
+ tmpToken.Resolved = true;
112
+ tmpToken.Value = tmpValueParsed.toString();
113
+ }
114
+ catch(pError)
115
+ {
116
+ tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.substituteValuesInTokenizedObjects found a non-numeric value for the state address ${tmpToken.Token} at index ${i}`);
117
+ this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
118
+ tmpToken.Resolved = false;
119
+ }
120
+ }
121
+ }
122
+ if ((pTokenizedObjects[i].Type === 'Token.Constant') && !tmpToken.Resolved)
123
+ {
124
+ tmpResults.ExpressionParserLog.push(`INFO: ExpressionParser.substituteValuesInTokenizedObjects found a value [${tmpToken.Token}] for the constant ${tmpToken.Token} at index ${i}`);
125
+ if (this.LogNoisiness > 1) this.log.info(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
126
+ try
127
+ {
128
+ let tmpValueParsed = new this.fable.Utility.bigNumber(tmpToken.Token);
129
+ tmpToken.Resolved = true;
130
+ tmpToken.Value = tmpValueParsed.toString();
131
+ }
132
+ catch(pError)
133
+ {
134
+ // This constant has the right symbols but apparently isn't a parsable number.
135
+ tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.substituteValuesInTokenizedObjects found a non-numeric value for the state address ${tmpToken.Token} at index ${i}`);
136
+ this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
137
+ tmpToken.Resolved = false;
138
+ }
139
+ }
140
+ }
141
+
142
+ return pTokenizedObjects;
143
+ }
144
+ }
145
+
146
+ module.exports = ExpressionParserValueMarshal;