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, |   expression, | ||||||
|   errorValue, |   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 { |   switch expression { | ||||||
|   | ExpressionT.EValue(EvSymbol(aSymbol)) => { |   | ExpressionT.EValue(EvSymbol(aSymbol)) => | ||||||
|       let parameters = getParameters(bindings) |     ExpressionT.Bindings.getResultIfNotInParameters(bindings, aSymbol)->E.O2.default(Ok(expression)) | ||||||
|       answerBindingIfNotParameter(aSymbol, expression, parameters, bindings) |   | ExpressionT.EValue(EvCall(aSymbol)) => | ||||||
|     } |     ExpressionT.Bindings.getIfNotInParameters(bindings, aSymbol)->E.O2.default(expression)->Ok | ||||||
|   | ExpressionT.EValue(EvCall(aSymbol)) => { |  | ||||||
|       let parameters = getParameters(bindings) |  | ||||||
|       answerCallBindingIfNotParameter(aSymbol, expression, parameters, bindings) |  | ||||||
|     } |  | ||||||
|   | ExpressionT.EValue(_) => expression->Ok |   | ExpressionT.EValue(_) => expression->Ok | ||||||
|   | ExpressionT.EBindings(_) => expression->Ok |   | ExpressionT.EBindings(_) => expression->Ok | ||||||
|   | ExpressionT.EParameters(_) => expression->Ok |   | ExpressionT.EParameters(_) => expression->Ok | ||||||
|  | @ -71,9 +33,7 @@ let rec replaceSymbols = (expression: expression, bindings: ExpressionT.bindings | ||||||
|       ExpressionT.EParameters(parameters), |       ExpressionT.EParameters(parameters), | ||||||
|       expr, |       expr, | ||||||
|     }) => { |     }) => { | ||||||
|       let oldParameters = getParameters(bindings) |       let newBindings = ExpressionT.Bindings.Parameters.setArray(bindings, parameters) | ||||||
|       let newParameters = oldParameters->Js.Array2.concat(parameters) |  | ||||||
|       let newBindings = putParameters(bindings, newParameters) |  | ||||||
|       let rNewExpr = replaceSymbols(expr, newBindings) |       let rNewExpr = replaceSymbols(expr, newBindings) | ||||||
|       rNewExpr->Result.flatMap(newExpr => |       rNewExpr->Result.flatMap(newExpr => | ||||||
|         ExpressionT.EList(list{ |         ExpressionT.EList(list{ | ||||||
|  | @ -119,7 +79,7 @@ let dispatchMacroCall = ( | ||||||
| 
 | 
 | ||||||
|         let rNewExpression = rNewValue->Result.map(newValue => ExpressionT.EValue(newValue)) |         let rNewExpression = rNewValue->Result.map(newValue => ExpressionT.EValue(newValue)) | ||||||
|         rNewExpression->Result.map(newExpression => |         rNewExpression->Result.map(newExpression => | ||||||
|           Belt.Map.String.set(bindings, aSymbol, newExpression)->ExpressionT.EBindings |           ExpressionT.Bindings.set(bindings, aSymbol, newExpression)->ExpressionT.EBindings | ||||||
|         ) |         ) | ||||||
|       } |       } | ||||||
|     | _ => REAssignmentExpected->Error |     | _ => REAssignmentExpected->Error | ||||||
|  |  | ||||||
|  | @ -6,11 +6,14 @@ module Result = Belt.Result | ||||||
| type errorValue = ErrorValue.errorValue | type errorValue = ErrorValue.errorValue | ||||||
| type expression = ExpressionT.expression | type expression = ExpressionT.expression | ||||||
| 
 | 
 | ||||||
| let passToFunction = (fName: string, lispArgs: list<expression>): expression => { | let toEvCallValue = (name: string): expression => ExpressionT.EValue(ExpressionValue.EvCall(name)) | ||||||
|   let toEvCallValue = (name: string): expression => name->ExpressionValue.EvCall->ExpressionT.EValue |  | ||||||
|   let fn = fName->toEvCallValue |  | ||||||
|   list{fn, ...lispArgs}->ExpressionT.EList |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| let toEvSymbolValue = (name: string): expression => | let toEvSymbolValue = (name: string): expression => ExpressionT.EValue( | ||||||
|   name->ExpressionValue.EvSymbol->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. |   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. |   The act of defining the semantics of a functional language is to write it in terms of Lisp AST. | ||||||
| */ | */ | ||||||
|  | 
 | ||||||
| type rec expression = | type rec expression = | ||||||
|   | EList(list<expression>) // A list to map-reduce |   | EList(list<expression>) // A list to map-reduce | ||||||
|   | EValue(expressionValue) // Irreducible built-in value. Reducer should not know the internals. External libraries are responsible |   | 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 |   | EBindings(bindings) // $let kind of statements return bindings; for internal use only | ||||||
|   | EParameters(array<string>) // for $defun; for internal use only |   | EParameters(array<string>) // for $defun; for internal use only | ||||||
| and bindings = Belt.Map.String.t<expression> | 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 ErrorValue = Reducer_ErrorValue | ||||||
| module ExpressionT = Reducer_Expression_T | module ExpressionT = Reducer_Expression_T | ||||||
| module ExpressionValue = ReducerInterface.ExpressionValue | module ExpressionValue = ReducerInterface.ExpressionValue | ||||||
|  | @ -31,7 +31,7 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> => | ||||||
|     let caseFunctionNode = fNode => { |     let caseFunctionNode = fNode => { | ||||||
|       let rLispArgs = fNode["args"]->Belt.List.fromArray->fromNodeList |       let rLispArgs = fNode["args"]->Belt.List.fromArray->fromNodeList | ||||||
|       rLispArgs->Result.flatMap(lispArgs => |       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 => |         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 |         ) // $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) => { |     let caseAccessorNode = (objectNode, indexNode) => { | ||||||
|       caseIndexNode(indexNode)->Result.flatMap(indexCode => { |       caseIndexNode(indexNode)->Result.flatMap(indexCode => { | ||||||
|         fromNode(objectNode)->Result.flatMap(objectCode => |         fromNode(objectNode)->Result.flatMap(objectCode => | ||||||
|           Builder.passToFunction("$atIndex", list{objectCode, indexCode})->Ok |           ExpressionBuilder.passToFunction("$atIndex", list{objectCode, indexCode})->Ok | ||||||
|         ) |         ) | ||||||
|       }) |       }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     let caseAssignmentNode = aNode => { |     let caseAssignmentNode = aNode => { | ||||||
|       let symbol = aNode["object"]["name"]->Builder.toEvSymbolValue |       let symbol = aNode["object"]["name"]->ExpressionBuilder.toEvSymbolValue | ||||||
|       let rValueExpression = fromNode(aNode["value"]) |       let rValueExpression = fromNode(aNode["value"]) | ||||||
|       rValueExpression->Result.flatMap(valueExpression => |       rValueExpression->Result.flatMap(valueExpression => | ||||||
|         Builder.passToFunction("$let", list{symbol, valueExpression})->Ok |         ExpressionBuilder.passToFunction("$let", list{symbol, valueExpression})->Ok | ||||||
|       ) |       ) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     let caseFunctionAssignmentNode = faNode => { |     let caseFunctionAssignmentNode = faNode => { | ||||||
|       let symbol = faNode["name"]->Builder.toEvSymbolValue |       let symbol = faNode["name"]->ExpressionBuilder.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 lambda = Builder.passToFunction("$lambda", list{lispParams, valueExpression}) |         let lambda = ExpressionBuilder.passToFunction("$lambda", list{lispParams, valueExpression}) | ||||||
|         Builder.passToFunction("$let", list{symbol, lambda})->Ok |         ExpressionBuilder.passToFunction("$let", list{symbol, lambda})->Ok | ||||||
|       }) |       }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -111,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 = Builder.toEvSymbolValue(sNode["name"]) |         let expr: expression = ExpressionBuilder.toEvSymbolValue(sNode["name"]) | ||||||
|         let rExpr: result<expression, errorValue> = expr->Ok |         let rExpr: result<expression, errorValue> = expr->Ok | ||||||
|         rExpr |         rExpr | ||||||
|       } |       } | ||||||
|  | @ -128,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 = Builder.passToFunction("$$bindings", list{})->Ok |   let initialBindings = ExpressionBuilder.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 => { | ||||||
|  | @ -137,9 +137,9 @@ and caseTagOrNodes = (tagOrNodes): result<expression, errorValue> => { | ||||||
|       | BlockTag(tag) => |       | BlockTag(tag) => | ||||||
|         switch tag { |         switch tag { | ||||||
|         | ImportVariablesStatement => |         | ImportVariablesStatement => | ||||||
|           Builder.passToFunction("$importVariablesStatement", list{})->Ok |           ExpressionBuilder.passToFunction("$importVariablesStatement", list{})->Ok | ||||||
|         | ExportVariablesExpression => |         | 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) => { |       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 { |   switch x { | ||||||
|   | Ok(a) => `Ok(${toStringRecord(a)})` |   | Ok(a) => `Ok(${toStringRecord(a)})` | ||||||
|   | Error(m) => `Error(${ErrorValue.errorToString(m)})` |   | Error(m) => `Error(${ErrorValue.errorToString(m)})` | ||||||
|   } |   } | ||||||
|  | @ -338,6 +338,7 @@ module A = { | ||||||
|   let getBy = Belt.Array.getBy |   let getBy = Belt.Array.getBy | ||||||
|   let last = a => get(a, length(a) - 1) |   let last = a => get(a, length(a) - 1) | ||||||
|   let first = get(_, 0) |   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 hasBy = (r, fn) => Belt.Array.getBy(r, fn) |> O.isSome | ||||||
|   let fold_left = Array.fold_left |   let fold_left = Array.fold_left | ||||||
|   let fold_right = Array.fold_right |   let fold_right = Array.fold_right | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user