fable 3.0.140 → 3.0.142
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.
- package/debug/Harness.js +30 -30
- package/dist/fable.compatible.js +27 -10
- package/dist/fable.compatible.min.js +2 -2
- package/dist/fable.compatible.min.js.map +1 -1
- package/dist/fable.js +27 -10
- package/dist/fable.min.js +2 -2
- package/dist/fable.min.js.map +1 -1
- package/example_applications/mathematical_playground/Equations.json +1 -1
- package/example_applications/mathematical_playground/Math-Solver-Harness.js +30 -27
- package/package.json +2 -2
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-FunctionMap.json +4 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-Messaging.js +22 -2
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-Postfix.js +1 -1
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-SolvePostfixedExpression.js +62 -9
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-TokenMap.json +8 -0
- package/source/services/Fable-Service-Math.js +17 -1
- package/test/ExpressionParser_tests.js +17 -0
package/dist/fable.js
CHANGED
|
@@ -1592,7 +1592,7 @@ else if(tmpInTranslationTable){tmpAddress=this.hashTranslations.translate(pHash)
|
|
|
1592
1592
|
else{tmpAddress=pHash;}return tmpAddress;}// Get the value of an element by its hash
|
|
1593
1593
|
getValueByHash(pObject,pHash){let tmpValue=this.getValueAtAddress(pObject,this.resolveHashAddress(pHash));if(typeof tmpValue=='undefined'){// Try to get a default if it exists
|
|
1594
1594
|
tmpValue=this.getDefaultValue(this.getDescriptorByHash(pHash));}return tmpValue;}// Get the value of an element at an address
|
|
1595
|
-
getValueAtAddress(pObject,pAddress){let tmpValue=this.objectAddressGetValue.getValueAtAddress(pObject,pAddress);if(typeof tmpValue=='undefined'){// Try to get a default if it exists
|
|
1595
|
+
getValueAtAddress(pObject,pAddress){let tmpLintedAddress=pAddress.trim();if(tmpLintedAddress==''){this.logError("(".concat(this.scope,") Error getting value at address; address is an empty string."),pObject);return undefined;}let tmpValue=this.objectAddressGetValue.getValueAtAddress(pObject,pAddress);if(typeof tmpValue=='undefined'){// Try to get a default if it exists
|
|
1596
1596
|
tmpValue=this.getDefaultValue(this.getDescriptor(pAddress));}return tmpValue;}// Set the value of an element by its hash
|
|
1597
1597
|
setValueByHash(pObject,pHash,pValue){return this.setValueAtAddress(pObject,this.resolveHashAddress(pHash),pValue);}// Set the value of an element at an address
|
|
1598
1598
|
setValueAtAddress(pObject,pAddress,pValue){return this.objectAddressSetValue.setValueAtAddress(pObject,pAddress,pValue);}// Delete the value of an element by its hash
|
|
@@ -3493,7 +3493,7 @@ tmpCurrentTokenType='Value';tmpCurrentToken+=tmpCharacter;// continue;
|
|
|
3493
3493
|
// }
|
|
3494
3494
|
// tmpResults.ExpressionParserLog.push(`ExpressionParser.tokenize found an unknown character code ${tmpCharCode} character ${tmpCharacter} in the expression: ${pExpression} at index ${i}`);
|
|
3495
3495
|
// this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
|
|
3496
|
-
}if(tmpCurrentTokenType&&tmpCurrentToken.length>0){tmpResults.RawTokens.push(tmpCurrentToken);}return tmpResults.RawTokens;}}module.exports=ExpressionTokenizer;},{"./Fable-Service-ExpressionParser-Base.js":136}],138:[function(require,module,exports){module.exports={"sqrt":{"Name":"Square Root","Address":"fable.Math.sqrtPrecise"},"abs":{"Name":"Absolute Value","Address":"fable.Math.absPrecise"},"rad":{"Name":"Degrees to Radians","Address":"fable.Math.radPrecise"},"pi":{"Name":"Pi","Address":"fable.Math.piPrecise"},"sin":{"Name":"Sine","Address":"fable.Math.sin"},"cos":{"Name":"Cosine","Address":"fable.Math.cos"},"tan":{"Name":"Tangent","Address":"fable.Math.tan"},"count":{"Name":"Count Set Elements","Address":"fable.Math.countSetElements"},"sortset":{"Name":"Sort Set","Address":"fable.Math.sortSetPrecise"},"bucketset":{"Name":"Bucket Set","Address":"fable.Math.bucketSetPrecise"},"sorthistogram":{"Name":"Sort Histogram","Address":"fable.Math.sortHistogramPrecise"},"max":{"Name":"Maximum","Address":"fable.Math.maxPrecise"},"min":{"Name":"Minimum","Address":"fable.Math.minPrecise"},"sum":{"Name":"Sum","Address":"fable.Math.sumPrecise"},"avg":{"Name":"Average","Address":"fable.Math.averagePrecise"},"mean":{"Name":"Mean","Address":"fable.Math.meanPrecise"},"median":{"Name":"Median","Address":"fable.Math.medianPrecise"},"mode":{"Name":"Mode","Address":"fable.Math.modePrecise"}};},{}],139:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionParserLinter extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-Linter';}lintTokenizedExpression(pTokenizedExpression,pResultObject){let tmpResults=typeof pResultObject==='object'?pResultObject:{ExpressionParserLog:[]};tmpResults.LinterResults=[];// Guard against bad data being passed in
|
|
3496
|
+
}if(tmpCurrentTokenType&&tmpCurrentToken.length>0){tmpResults.RawTokens.push(tmpCurrentToken);}return tmpResults.RawTokens;}}module.exports=ExpressionTokenizer;},{"./Fable-Service-ExpressionParser-Base.js":136}],138:[function(require,module,exports){module.exports={"sqrt":{"Name":"Square Root","Address":"fable.Math.sqrtPrecise"},"abs":{"Name":"Absolute Value","Address":"fable.Math.absPrecise"},"rad":{"Name":"Degrees to Radians","Address":"fable.Math.radPrecise"},"pi":{"Name":"Pi","Address":"fable.Math.piPrecise"},"sin":{"Name":"Sine","Address":"fable.Math.sin"},"cos":{"Name":"Cosine","Address":"fable.Math.cos"},"tan":{"Name":"Tangent","Address":"fable.Math.tan"},"count":{"Name":"Count Set Elements","Address":"fable.Math.countSetElements"},"sortset":{"Name":"Sort Set","Address":"fable.Math.sortSetPrecise"},"bucketset":{"Name":"Bucket Set","Address":"fable.Math.bucketSetPrecise"},"sorthistogram":{"Name":"Sort Histogram","Address":"fable.Math.sortHistogramPrecise"},"max":{"Name":"Maximum","Address":"fable.Math.maxPrecise"},"min":{"Name":"Minimum","Address":"fable.Math.minPrecise"},"sum":{"Name":"Sum","Address":"fable.Math.sumPrecise"},"avg":{"Name":"Average","Address":"fable.Math.averagePrecise"},"mean":{"Name":"Mean","Address":"fable.Math.meanPrecise"},"median":{"Name":"Median","Address":"fable.Math.medianPrecise"},"mode":{"Name":"Mode","Address":"fable.Math.modePrecise"},"round":{"Name":"Round","Address":"fable.Math.roundPrecise"}};},{}],139:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionParserLinter extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-Linter';}lintTokenizedExpression(pTokenizedExpression,pResultObject){let tmpResults=typeof pResultObject==='object'?pResultObject:{ExpressionParserLog:[]};tmpResults.LinterResults=[];// Guard against bad data being passed in
|
|
3497
3497
|
if(!Array.isArray(pTokenizedExpression)){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.lintTokenizedExpression was passed a non-array tokenized expression.");tmpResults.LinterResults.push(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return pTokenizedExpression;}if(pTokenizedExpression.length<1){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.lintTokenizedExpression was passed an empty tokenized expression.");tmpResults.LinterResults.push(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return pTokenizedExpression;}// 1. Check for balanced parenthesis
|
|
3498
3498
|
let tmpParenthesisDepth=0;// If it is in a state address, we don't care about the parenthesis
|
|
3499
3499
|
// State addresses are between squiggly brackets
|
|
@@ -3516,11 +3516,11 @@ if(pTokenizedExpression[i]!=='+'&&pTokenizedExpression[i]!=='-'){tmpResults.Expr
|
|
|
3516
3516
|
* Represents a user-friendly messaging service for the ExpressionParser compiler output.
|
|
3517
3517
|
* @class ExpressionParserMessaging
|
|
3518
3518
|
* @extends libExpressionParserOperationBase
|
|
3519
|
-
*/class ExpressionParserMessaging extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-Messaging';}getOperationVirtualSymbolName(pOperationToken){return pOperationToken&&'VirtualSymbolName'in pOperationToken?pOperationToken.VirtualSymbolName:pOperationToken.Type==='Token.VirtualSymbol'?pOperationToken.Token:'NO_VIRTUAL_SYMBOL_NAME_FOUND';}getVirtualTokenValue(pToken,pOperationResults){let tmpVirtualSymbol=this.getOperationVirtualSymbolName(pToken);let tmpVirtualSymbolData='VirtualSymbols'in pOperationResults?pOperationResults.VirtualSymbols:{};if(this.ExpressionParser.GenericManifest.checkAddressExists(tmpVirtualSymbolData,tmpVirtualSymbol)){let tmpValue=this.ExpressionParser.GenericManifest.getValueAtAddress(tmpVirtualSymbolData,tmpVirtualSymbol);if(typeof tmpValue==='object'){return"{".concat(Object.keys(tmpValue).length," values}");}if(Array.isArray(tmpValue)){return"[".concat(Object.keys(tmpValue).length," values]");}return tmpValue;}return'NO_VALUE_FOUND';}getTokenAddressString(pToken){return pExpression.Token;}getTokenSymbolString(pExpressionToken){return pExpressionToken.Token;}getOperationSymbolMessage(pOperation){if(!pOperation){return'INVALID_OPERATION';}let tmpOperationVirtualSymbol=this.getOperationVirtualSymbolName(pOperation);let tmpOperationLeftValue=this.getTokenSymbolString(pOperation.LeftValue);let tmpOperationSymbol=this.getTokenSymbolString(pOperation.Operation);let tmpOperationRightValue=this.getTokenSymbolString(pOperation.RightValue);let tmpVirtualSymbolPrefix=tmpOperationVirtualSymbol.substring(0,3);if(tmpOperationSymbol==='='){// Assignment operators are special
|
|
3519
|
+
*/class ExpressionParserMessaging extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-Messaging';}getOperationVirtualSymbolName(pOperationToken){return pOperationToken&&'VirtualSymbolName'in pOperationToken?pOperationToken.VirtualSymbolName:pOperationToken.Type==='Token.VirtualSymbol'?pOperationToken.Token:'NO_VIRTUAL_SYMBOL_NAME_FOUND';}getVirtualTokenValue(pToken,pOperationResults){let tmpVirtualSymbol=this.getOperationVirtualSymbolName(pToken);if(pToken.Type=='Token.Constant'&&pToken.Value){return pToken.Value.toString();}let tmpVirtualSymbolData='VirtualSymbols'in pOperationResults?pOperationResults.VirtualSymbols:{};if(this.ExpressionParser.GenericManifest.checkAddressExists(tmpVirtualSymbolData,tmpVirtualSymbol)){let tmpValue=this.ExpressionParser.GenericManifest.getValueAtAddress(tmpVirtualSymbolData,tmpVirtualSymbol);if(typeof tmpValue==='object'){return"{".concat(Object.keys(tmpValue).length," values}");}if(Array.isArray(tmpValue)){return"[".concat(Object.keys(tmpValue).length," values]");}return tmpValue;}return'NO_VALUE_FOUND';}getTokenAddressString(pToken){return pExpression.Token;}getTokenSymbolString(pExpressionToken){return pExpressionToken.Token;}getOperationSymbolMessage(pOperation){if(!pOperation){return'INVALID_OPERATION';}let tmpOperationVirtualSymbol=this.getOperationVirtualSymbolName(pOperation);let tmpOperationLeftValue=this.getTokenSymbolString(pOperation.LeftValue);let tmpOperationSymbol=this.getTokenSymbolString(pOperation.Operation);let tmpOperationRightValue=this.getTokenSymbolString(pOperation.RightValue);let tmpVirtualSymbolPrefix=tmpOperationVirtualSymbol.substring(0,3);if(tmpOperationSymbol==='='){// Assignment operators are special
|
|
3520
3520
|
return"".concat(tmpOperationVirtualSymbol," = ").concat(tmpOperationLeftValue);}if(tmpVirtualSymbolPrefix==='VFE'){// Virtual Function Expression
|
|
3521
|
-
return"".concat(tmpOperationVirtualSymbol," = ").concat(tmpOperationSymbol,"(").concat(
|
|
3521
|
+
return"".concat(tmpOperationVirtualSymbol," = ").concat(tmpOperationSymbol,"(").concat(tmpOperationLeftValue,")");}return"".concat(tmpOperationVirtualSymbol," = ").concat(tmpOperationLeftValue," ").concat(tmpOperationSymbol," ").concat(tmpOperationRightValue);}getOperationValueMessage(pOperation,pResultObject){if(!pOperation){return'INVALID_OPERATION';}let tmpOperationVirtualSymbol=this.getOperationVirtualSymbolName(pOperation);let tmpOperationLeftValue=this.getVirtualTokenValue(pOperation.LeftValue,pResultObject);let tmpOperationSymbol=this.getTokenSymbolString(pOperation.Operation);let tmpOperationRightValue=this.getVirtualTokenValue(pOperation.RightValue,pResultObject);let tmpVirtualSymbolPrefix=tmpOperationVirtualSymbol.substring(0,3);if(tmpOperationSymbol==='='){// Assignment operators are special
|
|
3522
3522
|
return"".concat(tmpOperationVirtualSymbol," = ").concat(tmpOperationLeftValue);}if(tmpVirtualSymbolPrefix==='VFE'){// Virtual Function Expression
|
|
3523
|
-
return"".concat(tmpOperationVirtualSymbol," = ").concat(tmpOperationSymbol,"(").concat(tmpOperationLeftValue,")");}return"".concat(tmpOperationVirtualSymbol," = ").concat(tmpOperationLeftValue," ").concat(tmpOperationSymbol," ").concat(tmpOperationRightValue);}logFunctionOutcome(pResultObject){if(typeof pResultObject!=='object'){this.log.error("Solver results object was not an object. Cannot log outcome.");return;}let tmpAssignmentAddress='PostfixedAssignmentAddress'in pResultObject?pResultObject.PostfixedAssignmentAddress:'NO_ASSIGNMENT_ADDRESS_FOUND';let tmpRawExpression='RawExpression'in pResultObject?pResultObject.RawExpression:'NO_EXPRESSION_FOUND';let tmpRawResult='RawResult'in pResultObject?pResultObject.RawResult:'NO_RESULT_FOUND';this.log.info("Solved f(".concat(tmpAssignmentAddress,") = {").concat(tmpRawExpression,"}"));for(let i=0;i<pResultObject.PostfixSolveList.length;i++){let tmpToken=pResultObject.PostfixSolveList[i];let tmpTokenSymbolMessage=this.getOperationSymbolMessage(tmpToken);this.log.info("".concat(i," Symbols: ").concat(tmpTokenSymbolMessage));let tmpTokenValueMessage=this.getOperationValueMessage(tmpToken,pResultObject);this.log.info("".concat(i," Values: ").concat(tmpTokenValueMessage));}this.log.info("{".concat(tmpRawExpression,"} = ").concat(tmpRawResult));}logFunctionSolve(pResultObject){if(typeof pResultObject!=='object'){this.log.error("Solver results object was not an object. Cannot log the solve.");return;}if(!('PostfixSolveList'in pResultObject)||!Array.isArray(pResultObject.PostfixSolveList)){this.log.error("Solver results object did not contain a PostfixSolveList array. Cannot log the solve.");return;}for(let i=0;i<tmpExpressionParseOutcome.PostfixSolveList.length;i++){let tmpToken=tmpExpressionParseOutcome.PostfixSolveList[i];console.log("".concat(i,": ").concat(tmpToken.VirtualSymbolName," = (").concat(tmpToken.LeftValue.Token,"::").concat(tmpToken.LeftValue.Value,") ").concat(tmpToken.Operation.Token," (").concat(tmpToken.RightValue.Token,"::").concat(tmpToken.RightValue.Value,") "));}this.logFunctionOutcome(pResultObject);}}module.exports=ExpressionParserMessaging;},{"./Fable-Service-ExpressionParser-Base.js":136,"big.js":17}],141:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionParserPostfix extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-Postfix';}getPosfixSolveListOperation(pOperation,pLeftValue,pRightValue,pDepthSolveList,pDepthSolveIndex){let tmpOperation={VirtualSymbolName:pOperation.VirtualSymbolName,Operation:pOperation,LeftValue:pLeftValue,RightValue:pRightValue};let tmpDepthSolveList=Array.isArray(pDepthSolveList)?pDepthSolveList:false;/* These two if blocks are very complex -- they basically provide a
|
|
3523
|
+
return"".concat(tmpOperationVirtualSymbol," = ").concat(tmpOperationSymbol,"(").concat(tmpOperationLeftValue,")");}return"".concat(tmpOperationVirtualSymbol," = ").concat(tmpOperationLeftValue," ").concat(tmpOperationSymbol," ").concat(tmpOperationRightValue);}getOperationOutcomeMessage(pToken,pOperationResults){if(!pToken){return'INVALID_TOKEN';}let tmpOperationVirtualSymbol=this.getOperationVirtualSymbolName(pToken);let tmpOperationOutcomeValue=this.getVirtualTokenValue(pToken,pOperationResults);return"".concat(tmpOperationVirtualSymbol," = ").concat(tmpOperationOutcomeValue);}logFunctionOutcome(pResultObject){if(typeof pResultObject!=='object'){this.log.error("Solver results object was not an object. Cannot log outcome.");return;}let tmpAssignmentAddress='PostfixedAssignmentAddress'in pResultObject?pResultObject.PostfixedAssignmentAddress:'NO_ASSIGNMENT_ADDRESS_FOUND';let tmpRawExpression='RawExpression'in pResultObject?pResultObject.RawExpression:'NO_EXPRESSION_FOUND';let tmpRawResult='RawResult'in pResultObject?pResultObject.RawResult:'NO_RESULT_FOUND';this.log.info("Solved f(".concat(tmpAssignmentAddress,") = {").concat(tmpRawExpression,"}"));for(let i=0;i<pResultObject.PostfixSolveList.length;i++){let tmpToken=pResultObject.PostfixSolveList[i];let tmpTokenSymbolMessage=this.getOperationSymbolMessage(tmpToken);this.log.info("".concat(i," Symbols: ").concat(tmpTokenSymbolMessage));let tmpTokenValueMessage=this.getOperationValueMessage(tmpToken,pResultObject);this.log.info("".concat(i," Values: ").concat(tmpTokenValueMessage));let tmpTokenOutcome=this.getOperationOutcomeMessage(tmpToken,pResultObject);this.log.info("".concat(i," Outcome: ").concat(tmpTokenOutcome));}this.log.info("{".concat(tmpRawExpression,"} = ").concat(tmpRawResult));}logFunctionSolve(pResultObject){if(typeof pResultObject!=='object'){this.log.error("Solver results object was not an object. Cannot log the solve.");return;}if(!('PostfixSolveList'in pResultObject)||!Array.isArray(pResultObject.PostfixSolveList)){this.log.error("Solver results object did not contain a PostfixSolveList array. Cannot log the solve.");return;}for(let i=0;i<tmpExpressionParseOutcome.PostfixSolveList.length;i++){let tmpToken=tmpExpressionParseOutcome.PostfixSolveList[i];console.log("".concat(i,": ").concat(tmpToken.VirtualSymbolName," = (").concat(tmpToken.LeftValue.Token,"::").concat(tmpToken.LeftValue.Value,") ").concat(tmpToken.Operation.Token," (").concat(tmpToken.RightValue.Token,"::").concat(tmpToken.RightValue.Value,") "));}this.logFunctionOutcome(pResultObject);}}module.exports=ExpressionParserMessaging;},{"./Fable-Service-ExpressionParser-Base.js":136,"big.js":17}],141:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionParserPostfix extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-Postfix';}getPosfixSolveListOperation(pOperation,pLeftValue,pRightValue,pDepthSolveList,pDepthSolveIndex){let tmpOperation={VirtualSymbolName:pOperation.VirtualSymbolName,Operation:pOperation,LeftValue:pLeftValue,RightValue:pRightValue};let tmpDepthSolveList=Array.isArray(pDepthSolveList)?pDepthSolveList:false;/* These two if blocks are very complex -- they basically provide a
|
|
3524
3524
|
* way to deal with recursion that can be expressed to the user in
|
|
3525
3525
|
* a meaningful way.
|
|
3526
3526
|
*
|
|
@@ -3591,7 +3591,7 @@ tmpVirtualSymbolName="VP_".concat(tmpVirtualSymbolIndex);tmpVirtualSymbolIndex++
|
|
|
3591
3591
|
else if(tmpPostfixTokenObject.Token==='('){// ... supporting a function
|
|
3592
3592
|
if(tmpResults.PostfixTokenObjects[i-1].Type==='Token.Function'){tmpPostfixTokenObject.IsFunction=true;tmpPostfixTokenObject.Function=tmpResults.PostfixTokenObjects[i-1];let tmpVirtualSymbolName=tmpResults.PostfixLayerstackMap[tmpPostfixTokenObject.VirtualSymbolName];if(!tmpVirtualSymbolName){// ... this parenthesis group has no operators in it; make a virtual symbol name.
|
|
3593
3593
|
tmpVirtualSymbolName="VFP_".concat(tmpVirtualSymbolIndex);tmpVirtualSymbolIndex++;}tmpPostfixTokenObject.VirtualSymbolName=tmpVirtualSymbolName;}else{tmpPostfixTokenObject.IsFunction=false;let tmpVirtualSymbolName=tmpResults.PostfixLayerstackMap[tmpPostfixTokenObject.VirtualSymbolName];if(!tmpVirtualSymbolName){// This is a parenthesis group with no operators in it; make a virtual symbol name.
|
|
3594
|
-
tmpVirtualSymbolName="VP_".concat(tmpVirtualSymbolIndex);tmpVirtualSymbolIndex++;}tmpPostfixTokenObject.VirtualSymbolName=tmpVirtualSymbolName;}tmpFunctionCacheLIFOStack.push(tmpPostfixTokenObject);}if(tmpPostfixTokenObject.Token===')'){let tmpOpenParenthesis=tmpFunctionCacheLIFOStack.pop();if(tmpOpenParenthesis.IsFunction){tmpPostfixTokenObject.IsFunction=true;tmpPostfixTokenObject.VirtualSymbolName=tmpOpenParenthesis.Function.VirtualSymbolName;}else{tmpPostfixTokenObject.IsFunction=false;tmpPostfixTokenObject.VirtualSymbolName=tmpOpenParenthesis.VirtualSymbolName;}}}}// X. Postprocess the parenthesis groups to ensure they respect the order of operations for their boundaries
|
|
3594
|
+
tmpVirtualSymbolName="VP_".concat(tmpVirtualSymbolIndex);tmpVirtualSymbolIndex++;}tmpPostfixTokenObject.VirtualSymbolName=tmpVirtualSymbolName;}tmpFunctionCacheLIFOStack.push(tmpPostfixTokenObject);}else if(tmpPostfixTokenObject.Token===')'){let tmpOpenParenthesis=tmpFunctionCacheLIFOStack.pop();if(tmpOpenParenthesis.IsFunction){tmpPostfixTokenObject.IsFunction=true;tmpPostfixTokenObject.VirtualSymbolName=tmpOpenParenthesis.Function.VirtualSymbolName;}else{tmpPostfixTokenObject.IsFunction=false;tmpPostfixTokenObject.VirtualSymbolName=tmpOpenParenthesis.VirtualSymbolName;}}}}// X. Postprocess the parenthesis groups to ensure they respect the order of operations for their boundaries
|
|
3595
3595
|
for(let tmpSolveLayerIndex=0;tmpSolveLayerIndex<tmpSolveLayerKeys.length;tmpSolveLayerIndex++){let tmpParenthesisStack=[];let tmpLastOperator=false;let tmpSolveLayerTokens=tmpSolveLayerMap[tmpSolveLayerKeys[tmpSolveLayerIndex]];for(let i=0;i<tmpSolveLayerTokens.length;i++){let tmpPostfixTokenObject=tmpSolveLayerTokens[i];// Keep track of the last operator
|
|
3596
3596
|
if(tmpPostfixTokenObject.Type==='Token.Operator'){tmpLastOperator=tmpPostfixTokenObject;}// This is only important to do at the close parenthesis.
|
|
3597
3597
|
if(tmpPostfixTokenObject.Type==='Token.Function'){tmpPostfixTokenObject.PreviousOperator=tmpLastOperator;}else if(tmpPostfixTokenObject.Type==='Token.Parenthesis'&&tmpPostfixTokenObject.Token==='('&&tmpPostfixTokenObject.IsFunction){tmpParenthesisStack.push(tmpPostfixTokenObject);if(tmpPostfixTokenObject.Function.PreviousOperator){tmpPostfixTokenObject.PreviousOperator=tmpPostfixTokenObject.Function.PreviousOperator;}}else if(tmpPostfixTokenObject.Type==='Token.Parenthesis'&&tmpPostfixTokenObject.Token==='('){tmpPostfixTokenObject.PreviousOperator=tmpLastOperator;tmpParenthesisStack.push(tmpPostfixTokenObject);}else if(tmpPostfixTokenObject.Type==='Token.Parenthesis'&&tmpPostfixTokenObject.Token===')'){// This is ultra complex, and binds the order of operations logic to the open parenthesis for the group
|
|
@@ -3627,12 +3627,19 @@ tmpResults.VirtualSymbols={};for(let i=0;i<pPostfixedExpression.length;i++){if(p
|
|
|
3627
3627
|
if(tmpStepResultObject.ExpressionStep.LeftValue.Type==='Token.Parenthesis'){tmpStepResultObject.ExpressionStep.LeftValue.Value=tmpManifest.getValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.LeftValue.VirtualSymbolName);}if(tmpStepResultObject.ExpressionStep.RightValue.Type==='Token.Parenthesis'){tmpStepResultObject.ExpressionStep.RightValue.Value=tmpManifest.getValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.RightValue.VirtualSymbolName);}// Virtual Constants
|
|
3628
3628
|
if(tmpStepResultObject.ExpressionStep.LeftValue.Type==='Token.Constant'&&!('Value'in tmpStepResultObject.ExpressionStep.LeftValue)){tmpStepResultObject.ExpressionStep.LeftValue.Value=tmpStepResultObject.ExpressionStep.LeftValue.Token;}if(tmpStepResultObject.ExpressionStep.RightValue.Type==='Token.Constant'&&!('Value'in tmpStepResultObject.ExpressionStep.RightValue)){tmpStepResultObject.ExpressionStep.RightValue.Value=tmpStepResultObject.ExpressionStep.RightValue.Token;}if(tmpStepResultObject.ExpressionStep.Operation.Type='Operator'){// TODO: This can be optimized. A lot. If necessary. Seems pretty fast honestly for even thousands of operations. Slowest part is arbitrary precision.
|
|
3629
3629
|
// An operator always has a left and right value.
|
|
3630
|
-
let tmpFunctionAddress=false
|
|
3630
|
+
let tmpFunctionAddress=false;// Note: There are easier, passive ways of managing this state. But this is complex.
|
|
3631
|
+
let tmpIsFunction=false;if(tmpStepResultObject.ExpressionStep.Operation.Token in this.ExpressionParser.tokenMap){tmpFunctionAddress="ResultsObject.".concat(tmpStepResultObject.ExpressionStep.Operation.Descriptor.Function);}else if(tmpStepResultObject.ExpressionStep.Operation.Token.toLowerCase()in this.ExpressionParser.functionMap){tmpIsFunction=true;tmpFunctionAddress="ResultsObject.".concat(this.ExpressionParser.functionMap[tmpStepResultObject.ExpressionStep.Operation.Token.toLowerCase()].Address);}if(tmpIsFunction){try{//this.log.trace(`Solving Function Step ${i} [${tmpStepResultObject.ExpressionStep.VirtualSymbolName}] --> [${tmpStepResultObject.ExpressionStep.Operation.Token}]: ( ${tmpStepResultObject.ExpressionStep.LeftValue.Value} , ${tmpStepResultObject.ExpressionStep.RightValue.Value} )`);
|
|
3632
|
+
// Build the set of arguments to send to the functions.
|
|
3633
|
+
tmpStepResultObject.ExpressionStep.LeftValue.ArgumentString='';if(typeof tmpStepResultObject.ExpressionStep.LeftValue.Value==='undefined'){tmpStepResultObject.ExpressionStep.LeftValue.Arguments=[];}else if(Array.isArray(tmpStepResultObject.ExpressionStep.LeftValue.Value)){// Allow for array-based math sets to just be pased through
|
|
3634
|
+
tmpStepResultObject.ExpressionStep.LeftValue.Arguments=tmpStepResultObject.ExpressionStep.LeftValue.Value;tmpStepResultObject.ExpressionStep.LeftValue.ArgumentString='ExpressionStep.LeftValue.Arguments';}else if(typeof tmpStepResultObject.ExpressionStep.LeftValue.Value==='object'){// Allow for array-based math sets to just be pased through
|
|
3635
|
+
tmpStepResultObject.ExpressionStep.LeftValue.Arguments=tmpStepResultObject.ExpressionStep.LeftValue.Value;tmpStepResultObject.ExpressionStep.LeftValue.ArgumentString='ExpressionStep.LeftValue.Arguments';}else{// Allow for string-based math sets.
|
|
3636
|
+
tmpStepResultObject.ExpressionStep.LeftValue.Arguments=tmpStepResultObject.ExpressionStep.LeftValue.Value.toString().split(',');for(let j=0;j<tmpStepResultObject.ExpressionStep.LeftValue.Arguments.length;j++){if(tmpStepResultObject.ExpressionStep.LeftValue.ArgumentString!==''){tmpStepResultObject.ExpressionStep.LeftValue.ArgumentString+=',';}tmpStepResultObject.ExpressionStep.LeftValue.ArgumentString+="ExpressionStep.LeftValue.Arguments[".concat(j,"]");}}tmpManifest.setValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.VirtualSymbolName,tmpManifest.getValueAtAddress(tmpStepResultObject,"".concat(tmpFunctionAddress,"(").concat(tmpStepResultObject.ExpressionStep.LeftValue.ArgumentString,")")));tmpResults.LastResult=tmpManifest.getValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.VirtualSymbolName);//this.log.trace(` ---> Step ${i}: ${tmpResults.VirtualSymbols[tmpStepResultObject.ExpressionStep.VirtualSymbolName]}`)
|
|
3637
|
+
}catch(pError){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.solvePostfixedExpression failed to solve step ".concat(i," with function ").concat(tmpStepResultObject.ExpressionStep.Operation.Token,": ").concat(pError));this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return false;}}else{try{//this.log.trace(`Solving Step ${i} [${tmpStepResultObject.ExpressionStep.VirtualSymbolName}] --> [${tmpStepResultObject.ExpressionStep.Operation.Token}]: ( ${tmpStepResultObject.ExpressionStep.LeftValue.Value} , ${tmpStepResultObject.ExpressionStep.RightValue.Value} )`);
|
|
3631
3638
|
tmpManifest.setValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.VirtualSymbolName,tmpManifest.getValueAtAddress(tmpStepResultObject,"".concat(tmpFunctionAddress,"(ExpressionStep.LeftValue.Value,ExpressionStep.RightValue.Value)")));tmpResults.LastResult=tmpManifest.getValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.VirtualSymbolName);//this.log.trace(` ---> Step ${i}: ${tmpResults.VirtualSymbols[tmpStepResultObject.ExpressionStep.VirtualSymbolName]}`)
|
|
3632
|
-
}catch(pError){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.solvePostfixedExpression failed to solve step ".concat(i," with function ").concat(tmpStepResultObject.ExpressionStep.Operation.Token,": ").concat(pError));this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return false;}// Equations don't always solve in virtual symbol order.
|
|
3639
|
+
}catch(pError){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.solvePostfixedExpression failed to solve step ".concat(i," with function ").concat(tmpStepResultObject.ExpressionStep.Operation.Token,": ").concat(pError));this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return false;}}// Equations don't always solve in virtual symbol order.
|
|
3633
3640
|
tmpResults.SolverFinalVirtualSymbol=tmpStepResultObject.ExpressionStep.VirtualSymbolName;}}let tmpSolverResultValue=tmpManifest.getValueAtAddress(tmpResults,"VirtualSymbols.".concat(tmpResults.SolverFinalVirtualSymbol));// Now deal with final assignment(s)
|
|
3634
3641
|
for(let i=0;i<pPostfixedExpression.length;i++){if(pPostfixedExpression[i].RightValue.Type==='Token.SolverMarshal'){tmpManifest.setValueAtAddress(tmpResults.VirtualSymbols,pPostfixedExpression[i].VirtualSymbolName,tmpSolverResultValue);tmpManifest.setValueByHash(tmpDataDestinationObject,pPostfixedExpression[i].VirtualSymbolName,tmpSolverResultValue);}}tmpResults.RawResult=tmpSolverResultValue;// Clean up the fable reference if we added it to the object.
|
|
3635
|
-
if(!tmpPassedInFable){delete tmpResults.fable;}return tmpSolverResultValue.toString();}}module.exports=ExpressionParserSolver;},{"./Fable-Service-ExpressionParser-Base.js":136}],143:[function(require,module,exports){module.exports={"=":{"Name":"Equals","Token":"=","Function":"fable.Math.assignValue","Precedence":0,"Type":"Assignment"},"(":{"Name":"Left Parenthesis","Token":"(","Precedence":0,"Type":"Parenthesis"},")":{"Name":"Right Parenthesis","Token":")","Precedence":0,"Type":"Parenthesis"},"*":{"Name":"Multiply","Token":"*","Function":"fable.Math.multiplyPrecise","Precedence":3,"Type":"Operator"},"/":{"Name":"Divide","Token":"/","Function":"fable.Math.dividePrecise","Precedence":3,"Type":"Operator"},"^":{"Name":"Exponent","Token":"^","Function":"fable.Math.powerPrecise","Precedence":1,"Type":"Operator"},"%":{"Name":"Modulus","Token":"%","Function":"fable.Math.modPrecise","Precedence":3,"Type":"Operator"},"+":{"Name":"Add","Token":"+","Function":"fable.Math.addPrecise","Precedence":4,"Type":"Operator"},"-":{"Name":"Subtract","Token":"-","Function":"fable.Math.subtractPrecise","Precedence":4,"Type":"Operator"}};},{}],144:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionParserValueMarshal extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-ValueMarshal';}/**
|
|
3642
|
+
if(!tmpPassedInFable){delete tmpResults.fable;}return tmpSolverResultValue.toString();}}module.exports=ExpressionParserSolver;},{"./Fable-Service-ExpressionParser-Base.js":136}],143:[function(require,module,exports){module.exports={"=":{"Name":"Equals","Token":"=","Function":"fable.Math.assignValue","Precedence":0,"Type":"Assignment"},"(":{"Name":"Left Parenthesis","Token":"(","Precedence":0,"Type":"Parenthesis"},")":{"Name":"Right Parenthesis","Token":")","Precedence":0,"Type":"Parenthesis"},",":{"Name":"Set Concatenate","Token":",","Function":"fable.Math.setConcatenate","Precedence":4,"Type":"Operator"},"*":{"Name":"Multiply","Token":"*","Function":"fable.Math.multiplyPrecise","Precedence":3,"Type":"Operator"},"/":{"Name":"Divide","Token":"/","Function":"fable.Math.dividePrecise","Precedence":3,"Type":"Operator"},"^":{"Name":"Exponent","Token":"^","Function":"fable.Math.powerPrecise","Precedence":1,"Type":"Operator"},"%":{"Name":"Modulus","Token":"%","Function":"fable.Math.modPrecise","Precedence":3,"Type":"Operator"},"+":{"Name":"Add","Token":"+","Function":"fable.Math.addPrecise","Precedence":4,"Type":"Operator"},"-":{"Name":"Subtract","Token":"-","Function":"fable.Math.subtractPrecise","Precedence":4,"Type":"Operator"}};},{}],144:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionParserValueMarshal extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-ValueMarshal';}/**
|
|
3636
3643
|
* Substitutes values in tokenized objects based on the provided data source and manifest.
|
|
3637
3644
|
*
|
|
3638
3645
|
* TODO: Move this to its own file in the "Fable-Service-ExpressionParser" directory.
|
|
@@ -3699,13 +3706,23 @@ return this.makeFolderRecursive(tmpParameters,fCallback);}else{console.log(pCrea
|
|
|
3699
3706
|
* @param {number} pOf - The value to calculate the percentage against.
|
|
3700
3707
|
* @returns {string} The precise percentage as a string.
|
|
3701
3708
|
*/percentagePrecise(pIs,pOf){let tmpLeftValue=isNaN(pIs)?0:pIs;let tmpRightValue=isNaN(pOf)?0:pOf;if(tmpRightValue==0){return'0';}let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.div(tmpRightValue);tmpResult=tmpResult.times(100);return tmpResult.toString();}/**
|
|
3709
|
+
* Concatenates two value sets and returns the result as a string.
|
|
3710
|
+
*
|
|
3711
|
+
* Value sets are comma separated.
|
|
3712
|
+
*
|
|
3713
|
+
* Used for arbitrary precision set generation.
|
|
3714
|
+
*
|
|
3715
|
+
* @param {any} pLeftValue - The left value to append.
|
|
3716
|
+
* @param {any} pRightValue - The right value to append.
|
|
3717
|
+
* @returns {string} The concatenated string of the left and right values.
|
|
3718
|
+
*/setConcatenate(pLeftValue,pRightValue){return"".concat(pLeftValue,",").concat(pRightValue);}/**
|
|
3702
3719
|
* Rounds a value to a specified number of decimal places using a specified rounding method.
|
|
3703
3720
|
*
|
|
3704
3721
|
* @param {number} pValue - The value to be rounded.
|
|
3705
3722
|
* @param {number} pDecimals - The number of decimal places to round to.
|
|
3706
3723
|
* @param {function} [pRoundingMethod] - The rounding method to use. Defaults to `this.roundHalfUp`.
|
|
3707
3724
|
* @returns {string} - The rounded value as a string.
|
|
3708
|
-
*/roundPrecise(pValue,pDecimals,pRoundingMethod){let tmpValue=isNaN(pValue)?0:pValue;let tmpDecimals=isNaN(pDecimals)?0:pDecimals;let tmpRoundingMethod=typeof pRoundingMethod==='undefined'?this.roundHalfUp:pRoundingMethod;let tmpArbitraryValue=new this.fable.Utility.bigNumber(tmpValue);let tmpResult=tmpArbitraryValue.round(tmpDecimals,tmpRoundingMethod);return tmpResult.toString();}/**
|
|
3725
|
+
*/roundPrecise(pValue,pDecimals,pRoundingMethod){let tmpValue=isNaN(pValue)?0:pValue;let tmpDecimals=isNaN(pDecimals)?0:parseInt(pDecimals,10);let tmpRoundingMethod=typeof pRoundingMethod==='undefined'?this.roundHalfUp:pRoundingMethod;let tmpArbitraryValue=new this.fable.Utility.bigNumber(tmpValue);let tmpResult=tmpArbitraryValue.round(tmpDecimals,tmpRoundingMethod);return tmpResult.toString();}/**
|
|
3709
3726
|
* Returns a string representation of a number with a specified number of decimals.
|
|
3710
3727
|
*
|
|
3711
3728
|
* @param {number} pValue - The number to be formatted.
|