Attempt of refactor for Bindings and Paramaters
This commit is contained in:
		
							parent
							
								
									7d4e3072b8
								
							
						
					
					
						commit
						d4025e7f02
					
				|  | @ -20,49 +20,11 @@ let rec replaceSymbols = (expression: expression, bindings: ExpressionT.bindings | |||
|   expression, | ||||
|   errorValue, | ||||
| > => { | ||||
|   let getParameters = (bindings: ExpressionT.bindings): array<string> => { | ||||
|     let eParameters = Belt.Map.String.getWithDefault(bindings, "$parameters", EParameters([])) | ||||
|     switch eParameters { | ||||
|     | EParameters(parameters) => parameters | ||||
|     | _ => [] | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   let putParameters = ( | ||||
|     bindings: ExpressionT.bindings, | ||||
|     parameters: array<string>, | ||||
|   ): ExpressionT.bindings => | ||||
|     Belt.Map.String.set(bindings, "$parameters", ExpressionT.EParameters(parameters)) | ||||
| 
 | ||||
|   let answerBindingIfNotParameter = (aSymbol, defaultExpression, parameters, bindings) => | ||||
|     switch Js.Array2.some(parameters, a => a == aSymbol) { | ||||
|     | true => defaultExpression->Ok // We cannot bind the parameters with global values | ||||
|     | false => | ||||
|       switch bindings->Belt.Map.String.get(aSymbol) { | ||||
|       | Some(boundExpression) => boundExpression->Ok | ||||
|       | None => RESymbolNotFound(aSymbol)->Error | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|   let answerCallBindingIfNotParameter = (aSymbol, defaultExpression, parameters, bindings) => | ||||
|     switch Js.Array2.some(parameters, a => a == aSymbol) { | ||||
|     | true => defaultExpression->Ok // We cannot bind the parameters with global values | ||||
|     | false => | ||||
|       switch bindings->Belt.Map.String.get(aSymbol) { | ||||
|       | Some(boundExpression) => boundExpression->Ok | ||||
|       | None => defaultExpression->Ok | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|   switch expression { | ||||
|   | ExpressionT.EValue(EvSymbol(aSymbol)) => { | ||||
|       let parameters = getParameters(bindings) | ||||
|       answerBindingIfNotParameter(aSymbol, expression, parameters, bindings) | ||||
|     } | ||||
|   | ExpressionT.EValue(EvCall(aSymbol)) => { | ||||
|       let parameters = getParameters(bindings) | ||||
|       answerCallBindingIfNotParameter(aSymbol, expression, parameters, bindings) | ||||
|     } | ||||
|   | ExpressionT.EValue(EvSymbol(aSymbol)) => | ||||
|     ExpressionT.Bindings.getResultIfNotInParameters(bindings, aSymbol)->E.O2.default(Ok(expression)) | ||||
|   | ExpressionT.EValue(EvCall(aSymbol)) => | ||||
|     ExpressionT.Bindings.getIfNotInParameters(bindings, aSymbol)->E.O2.default(expression)->Ok | ||||
|   | ExpressionT.EValue(_) => expression->Ok | ||||
|   | ExpressionT.EBindings(_) => expression->Ok | ||||
|   | ExpressionT.EParameters(_) => expression->Ok | ||||
|  | @ -71,9 +33,7 @@ let rec replaceSymbols = (expression: expression, bindings: ExpressionT.bindings | |||
|       ExpressionT.EParameters(parameters), | ||||
|       expr, | ||||
|     }) => { | ||||
|       let oldParameters = getParameters(bindings) | ||||
|       let newParameters = oldParameters->Js.Array2.concat(parameters) | ||||
|       let newBindings = putParameters(bindings, newParameters) | ||||
|       let newBindings = ExpressionT.Bindings.Parameters.setArray(bindings, parameters) | ||||
|       let rNewExpr = replaceSymbols(expr, newBindings) | ||||
|       rNewExpr->Result.flatMap(newExpr => | ||||
|         ExpressionT.EList(list{ | ||||
|  | @ -119,7 +79,7 @@ let dispatchMacroCall = ( | |||
| 
 | ||||
|         let rNewExpression = rNewValue->Result.map(newValue => ExpressionT.EValue(newValue)) | ||||
|         rNewExpression->Result.map(newExpression => | ||||
|           Belt.Map.String.set(bindings, aSymbol, newExpression)->ExpressionT.EBindings | ||||
|           ExpressionT.Bindings.set(bindings, aSymbol, newExpression)->ExpressionT.EBindings | ||||
|         ) | ||||
|       } | ||||
|     | _ => REAssignmentExpected->Error | ||||
|  |  | |||
|  | @ -6,11 +6,14 @@ 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 toEvCallValue = (name: string): expression => ExpressionT.EValue(ExpressionValue.EvCall(name)) | ||||
| 
 | ||||
| let toEvSymbolValue = (name: string): expression => | ||||
|   name->ExpressionValue.EvSymbol->ExpressionT.EValue | ||||
| let toEvSymbolValue = (name: string): expression => ExpressionT.EValue( | ||||
|   ExpressionValue.EvSymbol(name), | ||||
| ) | ||||
| 
 | ||||
| //From Ozzie: I think this could really use a more descriptive name. | ||||
| let passToFunction = (fName: string, lispArgs: list<expression>): expression => { | ||||
|   let fn = toEvCallValue(fName) | ||||
|   ExpressionT.EList(list{fn, ...lispArgs}) | ||||
| } | ||||
|  | @ -8,9 +8,60 @@ open ReducerInterface.ExpressionValue | |||
|   A Lisp AST contains only expressions/primitive values to apply to their left. | ||||
|   The act of defining the semantics of a functional language is to write it in terms of Lisp AST. | ||||
| */ | ||||
| 
 | ||||
| type rec expression = | ||||
|   | EList(list<expression>) // A list to map-reduce | ||||
|   | EValue(expressionValue) // Irreducible built-in value. Reducer should not know the internals. External libraries are responsible | ||||
|   | EBindings(bindings) // $let kind of statements return bindings; for internal use only | ||||
|   | EParameters(array<string>) // for $defun; for internal use only | ||||
| and bindings = Belt.Map.String.t<expression> | ||||
| 
 | ||||
| module Bindings = { | ||||
|   type t = bindings | ||||
|   let get = (t: t, str: string) => Belt.Map.String.get(t, str) | ||||
| 
 | ||||
|   let set = (t: t, key: string, value: expression): t => { | ||||
|     Belt.Map.String.set(t, key, value) | ||||
|   } | ||||
| 
 | ||||
|   let getResult = (t: t, str: string): result<expression, Reducer_ErrorValue.errorValue> => | ||||
|     get(t, str) |> E.O.toResult(Reducer_ErrorValue.RESymbolNotFound(str)) | ||||
| 
 | ||||
|   module Parameters = { | ||||
|     let parametersKey = "$parameters" | ||||
|     let default = EParameters([]) | ||||
|     let get = (t: t): array<string> => { | ||||
|       let expressionParameters = Belt.Map.String.getWithDefault(t, parametersKey, default) | ||||
|       switch expressionParameters { | ||||
|       | EParameters(parameters) => parameters | ||||
|       | _ => [] | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     let has = (t: t, s: string): bool => E.A.has(get(t), s) | ||||
| 
 | ||||
|     let setArray = (t: t, newParameters: array<string>): t => { | ||||
|       let oldParameters = get(t) | ||||
|       let updatedParameters = Js.Array2.concat(oldParameters, newParameters) | ||||
|       Belt.Map.String.set(t, parametersKey, EParameters(updatedParameters)) | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // We cannot bind the parameters with global values | ||||
|   let getIfNotInParameters = (t: t, aSymbol: string):option<expression> => { | ||||
|     if Parameters.has(t, aSymbol) { | ||||
|       None | ||||
|     } else { | ||||
|       get(t, aSymbol) | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // We cannot bind the parameters with global values | ||||
|   let getResultIfNotInParameters = (t: t, aSymbol: string) => { | ||||
|     if Parameters.has(t, aSymbol) { | ||||
|       None | ||||
|     } else { | ||||
|       Some(getResult(t, aSymbol)) | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| module Builder = Reducer_Expression_Builder | ||||
| module ExpressionBuilder = Reducer_Expression_Builder | ||||
| module ErrorValue = Reducer_ErrorValue | ||||
| module ExpressionT = Reducer_Expression_T | ||||
| module ExpressionValue = ReducerInterface.ExpressionValue | ||||
|  | @ -31,7 +31,7 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> => | |||
|     let caseFunctionNode = fNode => { | ||||
|       let rLispArgs = fNode["args"]->Belt.List.fromArray->fromNodeList | ||||
|       rLispArgs->Result.flatMap(lispArgs => | ||||
|         Builder.passToFunction(fNode->Parse.nameOfFunctionNode, lispArgs)->Ok | ||||
|         ExpressionBuilder.passToFunction(fNode->Parse.nameOfFunctionNode, lispArgs)->Ok | ||||
|       ) | ||||
|     } | ||||
| 
 | ||||
|  | @ -53,7 +53,7 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> => | |||
|           ) | ||||
|         ) | ||||
|         rargs->Result.flatMap(args => | ||||
|           Builder.passToFunction("$constructRecord", list{ExpressionT.EList(args)})->Ok | ||||
|           ExpressionBuilder.passToFunction("$constructRecord", list{ExpressionT.EList(args)})->Ok | ||||
|         ) // $constructRecord gets a single argument: List of key-value paiers | ||||
|       } | ||||
| 
 | ||||
|  | @ -78,27 +78,27 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> => | |||
|     let caseAccessorNode = (objectNode, indexNode) => { | ||||
|       caseIndexNode(indexNode)->Result.flatMap(indexCode => { | ||||
|         fromNode(objectNode)->Result.flatMap(objectCode => | ||||
|           Builder.passToFunction("$atIndex", list{objectCode, indexCode})->Ok | ||||
|           ExpressionBuilder.passToFunction("$atIndex", list{objectCode, indexCode})->Ok | ||||
|         ) | ||||
|       }) | ||||
|     } | ||||
| 
 | ||||
|     let caseAssignmentNode = aNode => { | ||||
|       let symbol = aNode["object"]["name"]->Builder.toEvSymbolValue | ||||
|       let symbol = aNode["object"]["name"]->ExpressionBuilder.toEvSymbolValue | ||||
|       let rValueExpression = fromNode(aNode["value"]) | ||||
|       rValueExpression->Result.flatMap(valueExpression => | ||||
|         Builder.passToFunction("$let", list{symbol, valueExpression})->Ok | ||||
|         ExpressionBuilder.passToFunction("$let", list{symbol, valueExpression})->Ok | ||||
|       ) | ||||
|     } | ||||
| 
 | ||||
|     let caseFunctionAssignmentNode = faNode => { | ||||
|       let symbol = faNode["name"]->Builder.toEvSymbolValue | ||||
|       let symbol = faNode["name"]->ExpressionBuilder.toEvSymbolValue | ||||
|       let rValueExpression = fromNode(faNode["expr"]) | ||||
| 
 | ||||
|       rValueExpression->Result.flatMap(valueExpression => { | ||||
|         let lispParams = faNode["params"]->ExpressionT.EParameters | ||||
|         let lambda = Builder.passToFunction("$lambda", list{lispParams, valueExpression}) | ||||
|         Builder.passToFunction("$let", list{symbol, lambda})->Ok | ||||
|         let lambda = ExpressionBuilder.passToFunction("$lambda", list{lispParams, valueExpression}) | ||||
|         ExpressionBuilder.passToFunction("$let", list{symbol, lambda})->Ok | ||||
|       }) | ||||
|     } | ||||
| 
 | ||||
|  | @ -111,7 +111,7 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> => | |||
|     | MjArrayNode(aNode) => caseArrayNode(aNode) | ||||
|     | MjAssignmentNode(aNode) => caseAssignmentNode(aNode) | ||||
|     | MjSymbolNode(sNode) => { | ||||
|         let expr: expression = Builder.toEvSymbolValue(sNode["name"]) | ||||
|         let expr: expression = ExpressionBuilder.toEvSymbolValue(sNode["name"]) | ||||
|         let rExpr: result<expression, errorValue> = expr->Ok | ||||
|         rExpr | ||||
|       } | ||||
|  | @ -128,7 +128,7 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> => | |||
|     rFinalExpression | ||||
|   }) | ||||
| and caseTagOrNodes = (tagOrNodes): result<expression, errorValue> => { | ||||
|   let initialBindings = Builder.passToFunction("$$bindings", list{})->Ok | ||||
|   let initialBindings = ExpressionBuilder.passToFunction("$$bindings", list{})->Ok | ||||
|   let lastIndex = Belt.Array.length(tagOrNodes) - 1 | ||||
|   tagOrNodes->Belt.Array.reduceWithIndex(initialBindings, (rPreviousBindings, tagOrNode, i) => { | ||||
|     rPreviousBindings->Result.flatMap(previousBindings => { | ||||
|  | @ -137,9 +137,9 @@ and caseTagOrNodes = (tagOrNodes): result<expression, errorValue> => { | |||
|       | BlockTag(tag) => | ||||
|         switch tag { | ||||
|         | ImportVariablesStatement => | ||||
|           Builder.passToFunction("$importVariablesStatement", list{})->Ok | ||||
|           ExpressionBuilder.passToFunction("$importVariablesStatement", list{})->Ok | ||||
|         | ExportVariablesExpression => | ||||
|           Builder.passToFunction("$exportVariablesExpression", list{})->Ok | ||||
|           ExpressionBuilder.passToFunction("$exportVariablesExpression", list{})->Ok | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|  | @ -150,7 +150,7 @@ and caseTagOrNodes = (tagOrNodes): result<expression, errorValue> => { | |||
|       } | ||||
| 
 | ||||
|       rStatement->Result.flatMap((statement: expression) => { | ||||
|         Builder.passToFunction(bindName, list{previousBindings, statement})->Ok | ||||
|         ExpressionBuilder.passToFunction(bindName, list{previousBindings, statement})->Ok | ||||
|       }) | ||||
|     }) | ||||
|   }) | ||||
|  |  | |||
|  | @ -83,4 +83,4 @@ let toStringResultRecord = x => | |||
|   switch x { | ||||
|   | Ok(a) => `Ok(${toStringRecord(a)})` | ||||
|   | Error(m) => `Error(${ErrorValue.errorToString(m)})` | ||||
|   } | ||||
|   } | ||||
|  | @ -338,6 +338,7 @@ module A = { | |||
|   let getBy = Belt.Array.getBy | ||||
|   let last = a => get(a, length(a) - 1) | ||||
|   let first = get(_, 0) | ||||
|   let has = (r, el) => Belt.Array.some(r, (x) => x == el) | ||||
|   let hasBy = (r, fn) => Belt.Array.getBy(r, fn) |> O.isSome | ||||
|   let fold_left = Array.fold_left | ||||
|   let fold_right = Array.fold_right | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user