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