Function definition evaluated
This commit is contained in:
parent
1f989de11c
commit
e3ef08839f
|
@ -7,6 +7,6 @@ describe("Parse function assignment", () => {
|
|||
//MathJs does not allow blocks in function definitions
|
||||
})
|
||||
|
||||
Skip.describe("Evaluate function assignment", () => {
|
||||
testParseToBe("f(x)=x; f(1)", "Ok(1)")
|
||||
describe("Evaluate function assignment", () => {
|
||||
testEvalToBe("f(x)=x; f(1)", "Ok(1)")
|
||||
})
|
|
@ -20,23 +20,24 @@ let rec replaceSymbols = (expression: expression, bindings: ExpressionT.bindings
|
|||
expression,
|
||||
errorValue,
|
||||
> => {
|
||||
let getParameters = (bindings: ExpressionT.bindings): list<string> => {
|
||||
let eParameters = Belt.Map.String.getWithDefault(bindings, "$parameters", EParameters(list{}))
|
||||
let getParameters = (bindings: ExpressionT.bindings): array<string> => {
|
||||
let eParameters = Belt.Map.String.getWithDefault(bindings, "$parameters", EParameters([]))
|
||||
switch eParameters {
|
||||
| EParameters(parameters) => parameters
|
||||
| _ => list{}
|
||||
| _ => []
|
||||
}
|
||||
}
|
||||
|
||||
let putParameters = (
|
||||
bindings: ExpressionT.bindings,
|
||||
parameters: list<string>,
|
||||
parameters: array<string>,
|
||||
): ExpressionT.bindings =>
|
||||
Belt.Map.String.set(bindings, "$parameters", ExpressionT.EParameters(parameters))
|
||||
|
||||
switch expression {
|
||||
| ExpressionT.EValue(EvSymbol(aSymbol)) => {
|
||||
let parameters = getParameters(bindings)
|
||||
switch Belt.List.has(parameters, aSymbol, (a, b) => a == b) {
|
||||
switch Js.Array2.some(parameters, a => a == aSymbol) {
|
||||
| true => expression->Ok // We cannot bind the parameters with global values
|
||||
| false =>
|
||||
switch bindings->Belt.Map.String.get(aSymbol) {
|
||||
|
@ -54,14 +55,16 @@ let rec replaceSymbols = (expression: expression, bindings: ExpressionT.bindings
|
|||
expr,
|
||||
}) => {
|
||||
let oldParameters = getParameters(bindings)
|
||||
let newParameters = oldParameters->Belt.List.concat(parameters)
|
||||
let newParameters = oldParameters->Js.Array2.concat(parameters)
|
||||
let newBindings = putParameters(bindings, newParameters)
|
||||
let rNewExpr = replaceSymbols(expr, newBindings)
|
||||
rNewExpr -> Result.flatMap(newExpr => ExpressionT.EList(list{
|
||||
rNewExpr->Result.flatMap(newExpr =>
|
||||
ExpressionT.EList(list{
|
||||
ExpressionT.EValue(EvCall("$lambda")),
|
||||
ExpressionT.EParameters(parameters),
|
||||
newExpr
|
||||
})->Ok)
|
||||
newExpr,
|
||||
})->Ok
|
||||
)
|
||||
}
|
||||
| ExpressionT.EList(list) => {
|
||||
let racc = list->Belt.List.reduceReverse(Ok(list{}), (racc, each: expression) =>
|
||||
|
@ -83,7 +86,6 @@ let dispatchMacroCall = (
|
|||
bindings: ExpressionT.bindings,
|
||||
reduceExpression: reducerFn,
|
||||
): result<expression, 'e> => {
|
||||
|
||||
let doBindStatement = (statement: expression, bindings: ExpressionT.bindings) => {
|
||||
switch statement {
|
||||
| ExpressionT.EList(list{
|
||||
|
|
|
@ -8,15 +8,19 @@ open Reducer_ErrorValue
|
|||
|
||||
type expression = T.expression
|
||||
type expressionValue = ExpressionValue.expressionValue
|
||||
type internalCode = ExpressionValue.internalCode
|
||||
type t = expression
|
||||
|
||||
external castExpressionToInternalCode: expression => internalCode = "%identity"
|
||||
external castInternalCodeToInternalCode: internalCode => expression = "%identity"
|
||||
|
||||
/*
|
||||
Shows the expression as text of expression
|
||||
*/
|
||||
let rec toString = expression =>
|
||||
switch expression {
|
||||
| T.EBindings(_) => "$$bound"
|
||||
| T.EParameters(params) => `(${Js.Array2.toString(params->Belt.List.toArray)})`
|
||||
| T.EParameters(params) => `(${Js.Array2.toString(params)})`
|
||||
| T.EList(aList) =>
|
||||
`(${Belt.List.map(aList, aValue => toString(aValue))
|
||||
->Extra.List.interperse(" ")
|
||||
|
@ -93,9 +97,11 @@ let rec reduceExpression = (expression: t, bindings: T.bindings): result<express
|
|||
|
||||
let rec reduceExpandedExpression = (expression: t): result<expressionValue, 'e> =>
|
||||
switch expression {
|
||||
// | T.EList(list{T.EValue(EvCall("$lambda")), T.EParameters(parameters), functionDefinition}) => {
|
||||
// let lambda = T.ELambda(parameters, functionDefinition)
|
||||
// lambda->Ok}
|
||||
| T.EList(list{
|
||||
T.EValue(EvCall("$lambda")),
|
||||
T.EParameters(parameters),
|
||||
functionDefinition,
|
||||
}) => EvLambda(parameters, functionDefinition->castExpressionToInternalCode)->Ok
|
||||
| T.EValue(value) => value->Ok
|
||||
| T.EList(list) => {
|
||||
let racc: result<list<expressionValue>, 'e> = list->Belt.List.reduceReverse(Ok(list{}), (
|
||||
|
@ -113,7 +119,8 @@ let rec reduceExpression = (expression: t, bindings: T.bindings): result<express
|
|||
racc->Result.flatMap(acc => acc->reduceValueList)
|
||||
}
|
||||
| EBindings(_bindings) => RETodo("Error: Bindings cannot be reduced to values")->Error
|
||||
| EParameters(_parameters) => RETodo("Error: Lambda Parameters cannot be reduced to values")->Error
|
||||
| EParameters(_parameters) =>
|
||||
RETodo("Error: Lambda Parameters cannot be reduced to values")->Error
|
||||
}
|
||||
|
||||
let rExpandedExpression: result<t, 'e> = expression->seekMacros(bindings)
|
||||
|
@ -142,7 +149,9 @@ let evalPartialUsingExternalBindings_ = (codeText: string, bindings: T.bindings)
|
|||
Therefore all statments are assignments.
|
||||
*/
|
||||
let evalOuterWBindings_ = (codeText: string, bindings: T.bindings) => {
|
||||
parseOuter(codeText)->Result.flatMap(expression => expression->evalUsingExternalBindingsExpression_(bindings))
|
||||
parseOuter(codeText)->Result.flatMap(expression =>
|
||||
expression->evalUsingExternalBindingsExpression_(bindings)
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -12,5 +12,5 @@ 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(list<string>) // for $defun; for internal use only
|
||||
| EParameters(array<string>) // for $defun; for internal use only
|
||||
and bindings = Belt.Map.String.t<expression>
|
||||
|
|
|
@ -104,7 +104,7 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> =>
|
|||
let rValueExpression = fromNode(faNode["expr"])
|
||||
|
||||
rValueExpression->Result.flatMap(valueExpression => {
|
||||
let lispParams = faNode["params"]->Belt.List.fromArray->ExpressionT.EParameters
|
||||
let lispParams = faNode["params"]->ExpressionT.EParameters
|
||||
let rLambda = passToFunction("$lambda", list{lispParams, valueExpression}->Ok)
|
||||
rLambda->Result.flatMap(lambda => {
|
||||
passToFunction("$let", list{symbol, lambda}->Ok)
|
||||
|
|
|
@ -56,14 +56,15 @@ and toStringRecord = aRecord => {
|
|||
|
||||
let toStringWithType = aValue =>
|
||||
switch aValue {
|
||||
| EvArray(_) => `Array::${toString(aValue)}`
|
||||
| EvBool(_) => `Bool::${toString(aValue)}`
|
||||
| EvCall(_) => `Call::${toString(aValue)}`
|
||||
| EvDistribution(_) => `Distribution::${toString(aValue)}`
|
||||
| EvLambda(_parameters, _internalCode) => `Lambda::${toString(aValue)}`
|
||||
| EvNumber(_) => `Number::${toString(aValue)}`
|
||||
| EvRecord(_) => `Record::${toString(aValue)}`
|
||||
| EvString(_) => `String::${toString(aValue)}`
|
||||
| EvSymbol(_) => `Symbol::${toString(aValue)}`
|
||||
| EvArray(_) => `Array::${toString(aValue)}`
|
||||
| EvRecord(_) => `Record::${toString(aValue)}`
|
||||
| EvDistribution(_) => `Distribution::${toString(aValue)}`
|
||||
}
|
||||
|
||||
let argsToString = (args: array<expressionValue>): string => {
|
||||
|
|
Loading…
Reference in New Issue
Block a user