refactor passToFunction

This commit is contained in:
Umur Ozkul 2022-04-25 08:17:44 +02:00
parent d214bddc82
commit 1fb9218a94
4 changed files with 80 additions and 52 deletions

View File

@ -34,25 +34,25 @@ let rec replaceSymbols = (expression: expression, bindings: ExpressionT.bindings
): ExpressionT.bindings => ): ExpressionT.bindings =>
Belt.Map.String.set(bindings, "$parameters", ExpressionT.EParameters(parameters)) Belt.Map.String.set(bindings, "$parameters", ExpressionT.EParameters(parameters))
let answerBindingIfNotParameter = (aSymbol, defaultExpression, parameters, bindings) => let answerBindingIfNotParameter = (aSymbol, defaultExpression, parameters, bindings) =>
switch Js.Array2.some(parameters, a => a == aSymbol) { switch Js.Array2.some(parameters, a => a == aSymbol) {
| true => defaultExpression->Ok // We cannot bind the parameters with global values | true => defaultExpression->Ok // We cannot bind the parameters with global values
| false => | false =>
switch bindings->Belt.Map.String.get(aSymbol) { switch bindings->Belt.Map.String.get(aSymbol) {
| Some(boundExpression) => boundExpression->Ok | Some(boundExpression) => boundExpression->Ok
| None => RESymbolNotFound(aSymbol)->Error | None => RESymbolNotFound(aSymbol)->Error
}
} }
}
let answerCallBindingIfNotParameter = (aSymbol, defaultExpression, parameters, bindings) => let answerCallBindingIfNotParameter = (aSymbol, defaultExpression, parameters, bindings) =>
switch Js.Array2.some(parameters, a => a == aSymbol) { switch Js.Array2.some(parameters, a => a == aSymbol) {
| true => defaultExpression->Ok // We cannot bind the parameters with global values | true => defaultExpression->Ok // We cannot bind the parameters with global values
| false => | false =>
switch bindings->Belt.Map.String.get(aSymbol) { switch bindings->Belt.Map.String.get(aSymbol) {
| Some(boundExpression) => boundExpression->Ok | Some(boundExpression) => boundExpression->Ok
| None => defaultExpression->Ok | None => defaultExpression->Ok
}
} }
}
switch expression { switch expression {
| ExpressionT.EValue(EvSymbol(aSymbol)) => { | ExpressionT.EValue(EvSymbol(aSymbol)) => {

View File

@ -12,7 +12,7 @@ type internalCode = ExpressionValue.internalCode
type t = expression type t = expression
external castExpressionToInternalCode: expression => internalCode = "%identity" external castExpressionToInternalCode: expression => internalCode = "%identity"
external castInternalCodeToInternalCode: internalCode => expression = "%identity" external castInternalCodeToExpression: internalCode => expression = "%identity"
/* /*
Shows the expression as text of expression Shows the expression as text of expression
@ -64,12 +64,36 @@ let rec reduceExpression = (expression: t, bindings: T.bindings): result<express
let doMacroCall = (list: list<t>, bindings: T.bindings): result<t, 'e> => let doMacroCall = (list: list<t>, bindings: T.bindings): result<t, 'e> =>
Reducer_Dispatch_BuiltInMacros.dispatchMacroCall(list, bindings, reduceExpression) Reducer_Dispatch_BuiltInMacros.dispatchMacroCall(list, bindings, reduceExpression)
let applyParametersToLambda = (
internal: internalCode,
parameters: array<string>,
args: list<expressionValue>,
): result<expressionValue, 'e> => {
let expr = castInternalCodeToExpression(internal)
let parameterList = parameters->Belt.List.fromArray
let zippedParameterList = parameterList->Belt.List.zip(args)
let bindings = Belt.List.reduce(zippedParameterList, defaultBindings, (a, (p, e)) =>
a->Belt.Map.String.set(p, e->EValue)
)
Js.log(`applyParametersToLambda: ${toString(expr)}`)
let inspectBindings =
bindings
->Belt.Map.String.mapWithKey((k, v) => `${k}: ${toString(v)}`)
->Belt.Map.String.valuesToArray
->Js.Array2.toString
Js.log(` inspectBindings: ${inspectBindings}`)
reduceExpression(expr, bindings)
}
/* /*
After reducing each level of expression(Lisp AST), we have a value list to evaluate After reducing each level of expression(Lisp AST), we have a value list to evaluate
*/ */
let reduceValueList = (valueList: list<expressionValue>): result<expressionValue, 'e> => let reduceValueList = (valueList: list<expressionValue>): result<expressionValue, 'e> =>
switch valueList { switch valueList {
| list{EvCall(fName), ...args} => (fName, args->Belt.List.toArray)->BuiltIn.dispatch | list{EvCall(fName), ...args} => (fName, args->Belt.List.toArray)->BuiltIn.dispatch
// "(lambda(x=>internal) param)"
| list{EvLambda(parameters, internal), ...args} =>
applyParametersToLambda(internal, parameters, args)
| _ => valueList->Belt.List.toArray->ExpressionValue.EvArray->Ok | _ => valueList->Belt.List.toArray->ExpressionValue.EvArray->Ok
} }
@ -97,11 +121,8 @@ let rec reduceExpression = (expression: t, bindings: T.bindings): result<express
let rec reduceExpandedExpression = (expression: t): result<expressionValue, 'e> => let rec reduceExpandedExpression = (expression: t): result<expressionValue, 'e> =>
switch expression { switch expression {
| T.EList(list{ | T.EList(list{T.EValue(EvCall("$lambda")), T.EParameters(parameters), functionDefinition}) =>
T.EValue(EvCall("$lambda")), EvLambda(parameters, functionDefinition->castExpressionToInternalCode)->Ok
T.EParameters(parameters),
functionDefinition,
}) => EvLambda(parameters, functionDefinition->castExpressionToInternalCode)->Ok
| T.EValue(value) => value->Ok | T.EValue(value) => value->Ok
| T.EList(list) => { | T.EList(list) => {
let racc: result<list<expressionValue>, 'e> = list->Belt.List.reduceReverse(Ok(list{}), ( let racc: result<list<expressionValue>, 'e> = list->Belt.List.reduceReverse(Ok(list{}), (

View File

@ -0,0 +1,16 @@
module ErrorValue = Reducer_ErrorValue
module ExpressionT = Reducer_Expression_T
module ExpressionValue = ReducerInterface.ExpressionValue
module Result = Belt.Result
type errorValue = ErrorValue.errorValue
type expression = ExpressionT.expression
let passToFunction = (fName: string, lispArgs: list<expression>): expression => {
let toEvCallValue = (name: string): expression => name->ExpressionValue.EvCall->ExpressionT.EValue
let fn = fName->toEvCallValue
list{fn, ...lispArgs}->ExpressionT.EList
}
let toEvSymbolValue = (name: string): expression =>
name->ExpressionValue.EvSymbol->ExpressionT.EValue

View File

@ -1,6 +1,7 @@
module Builder = Reducer_Expression_Builder
module ErrorValue = Reducer_ErrorValue module ErrorValue = Reducer_ErrorValue
module ExpressionValue = ReducerInterface.ExpressionValue
module ExpressionT = Reducer_Expression_T module ExpressionT = Reducer_Expression_T
module ExpressionValue = ReducerInterface.ExpressionValue
module JavaScript = Reducer_Js module JavaScript = Reducer_Js
module Parse = Reducer_MathJs_Parse module Parse = Reducer_MathJs_Parse
module Result = Belt.Result module Result = Belt.Result
@ -9,13 +10,6 @@ type expression = ExpressionT.expression
type expressionValue = ExpressionValue.expressionValue type expressionValue = ExpressionValue.expressionValue
type errorValue = ErrorValue.errorValue type errorValue = ErrorValue.errorValue
let passToFunction = (fName: string, rLispArgs): result<expression, errorValue> => {
let toEvCallValue = (name: string): expression => name->ExpressionValue.EvCall->ExpressionT.EValue
let fn = fName->toEvCallValue
rLispArgs->Result.flatMap(lispArgs => list{fn, ...lispArgs}->ExpressionT.EList->Ok)
}
type blockTag = type blockTag =
| ImportVariablesStatement | ImportVariablesStatement
| ExportVariablesExpression | ExportVariablesExpression
@ -34,12 +28,11 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> =>
) )
) )
let toEvSymbolValue = (name: string): expression =>
name->ExpressionValue.EvSymbol->ExpressionT.EValue
let caseFunctionNode = fNode => { let caseFunctionNode = fNode => {
let lispArgs = fNode["args"]->Belt.List.fromArray->fromNodeList let rLispArgs = fNode["args"]->Belt.List.fromArray->fromNodeList
passToFunction(fNode->Parse.nameOfFunctionNode, lispArgs) rLispArgs->Result.flatMap(lispArgs =>
Builder.passToFunction(fNode->Parse.nameOfFunctionNode, lispArgs)->Ok
)
} }
let caseObjectNode = oNode => { let caseObjectNode = oNode => {
@ -60,8 +53,8 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> =>
) )
) )
rargs->Result.flatMap(args => rargs->Result.flatMap(args =>
passToFunction("$constructRecord", list{ExpressionT.EList(args)}->Ok) Builder.passToFunction("$constructRecord", list{ExpressionT.EList(args)})->Ok
) // $consturctRecord gets a single argument: List of key-value paiers ) // $constructRecord gets a single argument: List of key-value paiers
} }
oNode["properties"]->Js.Dict.entries->Belt.List.fromArray->fromObjectEntries oNode["properties"]->Js.Dict.entries->Belt.List.fromArray->fromObjectEntries
@ -85,30 +78,27 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> =>
let caseAccessorNode = (objectNode, indexNode) => { let caseAccessorNode = (objectNode, indexNode) => {
caseIndexNode(indexNode)->Result.flatMap(indexCode => { caseIndexNode(indexNode)->Result.flatMap(indexCode => {
fromNode(objectNode)->Result.flatMap(objectCode => fromNode(objectNode)->Result.flatMap(objectCode =>
passToFunction("$atIndex", list{objectCode, indexCode}->Ok) Builder.passToFunction("$atIndex", list{objectCode, indexCode})->Ok
) )
}) })
} }
let caseAssignmentNode = aNode => { let caseAssignmentNode = aNode => {
let symbol = aNode["object"]["name"]->toEvSymbolValue let symbol = aNode["object"]["name"]->Builder.toEvSymbolValue
let rValueExpression = fromNode(aNode["value"]) let rValueExpression = fromNode(aNode["value"])
rValueExpression->Result.flatMap(valueExpression => { rValueExpression->Result.flatMap(valueExpression =>
let lispArgs = list{symbol, valueExpression}->Ok Builder.passToFunction("$let", list{symbol, valueExpression})->Ok
passToFunction("$let", lispArgs) )
})
} }
let caseFunctionAssignmentNode = faNode => { let caseFunctionAssignmentNode = faNode => {
let symbol = faNode["name"]->toEvSymbolValue let symbol = faNode["name"]->Builder.toEvSymbolValue
let rValueExpression = fromNode(faNode["expr"]) let rValueExpression = fromNode(faNode["expr"])
rValueExpression->Result.flatMap(valueExpression => { rValueExpression->Result.flatMap(valueExpression => {
let lispParams = faNode["params"]->ExpressionT.EParameters let lispParams = faNode["params"]->ExpressionT.EParameters
let rLambda = passToFunction("$lambda", list{lispParams, valueExpression}->Ok) let lambda = Builder.passToFunction("$lambda", list{lispParams, valueExpression})
rLambda->Result.flatMap(lambda => { Builder.passToFunction("$let", list{symbol, lambda})->Ok
passToFunction("$let", list{symbol, lambda}->Ok)
})
}) })
} }
@ -121,7 +111,7 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> =>
| MjArrayNode(aNode) => caseArrayNode(aNode) | MjArrayNode(aNode) => caseArrayNode(aNode)
| MjAssignmentNode(aNode) => caseAssignmentNode(aNode) | MjAssignmentNode(aNode) => caseAssignmentNode(aNode)
| MjSymbolNode(sNode) => { | MjSymbolNode(sNode) => {
let expr: expression = toEvSymbolValue(sNode["name"]) let expr: expression = Builder.toEvSymbolValue(sNode["name"])
let rExpr: result<expression, errorValue> = expr->Ok let rExpr: result<expression, errorValue> = expr->Ok
rExpr rExpr
} }
@ -138,7 +128,7 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> =>
rFinalExpression rFinalExpression
}) })
and caseTagOrNodes = (tagOrNodes): result<expression, errorValue> => { and caseTagOrNodes = (tagOrNodes): result<expression, errorValue> => {
let initialBindings = passToFunction("$$bindings", list{}->Ok) let initialBindings = Builder.passToFunction("$$bindings", list{})->Ok
let lastIndex = Belt.Array.length(tagOrNodes) - 1 let lastIndex = Belt.Array.length(tagOrNodes) - 1
tagOrNodes->Belt.Array.reduceWithIndex(initialBindings, (rPreviousBindings, tagOrNode, i) => { tagOrNodes->Belt.Array.reduceWithIndex(initialBindings, (rPreviousBindings, tagOrNode, i) => {
rPreviousBindings->Result.flatMap(previousBindings => { rPreviousBindings->Result.flatMap(previousBindings => {
@ -146,8 +136,10 @@ and caseTagOrNodes = (tagOrNodes): result<expression, errorValue> => {
| BlockNode(node) => fromNode(node) | BlockNode(node) => fromNode(node)
| BlockTag(tag) => | BlockTag(tag) =>
switch tag { switch tag {
| ImportVariablesStatement => passToFunction("$importVariablesStatement", list{}->Ok) | ImportVariablesStatement =>
| ExportVariablesExpression => passToFunction("$exportVariablesExpression", list{}->Ok) Builder.passToFunction("$importVariablesStatement", list{})->Ok
| ExportVariablesExpression =>
Builder.passToFunction("$exportVariablesExpression", list{})->Ok
} }
} }
@ -158,8 +150,7 @@ and caseTagOrNodes = (tagOrNodes): result<expression, errorValue> => {
} }
rStatement->Result.flatMap((statement: expression) => { rStatement->Result.flatMap((statement: expression) => {
let lispArgs = list{previousBindings, statement}->Ok Builder.passToFunction(bindName, list{previousBindings, statement})->Ok
passToFunction(bindName, lispArgs)
}) })
}) })
}) })