eval partial tested
This commit is contained in:
parent
a02bc27852
commit
5038e2c691
|
@ -14,6 +14,9 @@ describe("Parse for Bindings", () => {
|
||||||
"y = x+1; y",
|
"y = x+1; y",
|
||||||
"Ok((:$$bindExpression (:$$bindStatement (:$$bindings) (:$let :y (:add :x 1))) :y))",
|
"Ok((:$$bindExpression (:$$bindStatement (:$$bindings) (:$let :y (:add :x 1))) :y))",
|
||||||
)
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("Parse for Bindings", () => {
|
||||||
testParsePartialToBe(
|
testParsePartialToBe(
|
||||||
"x",
|
"x",
|
||||||
"Ok((:$$bindExpression (:$$bindStatement (:$$bindings) :x) (:$exportVariablesExpression)))",
|
"Ok((:$$bindExpression (:$$bindStatement (:$$bindings) :x) (:$exportVariablesExpression)))",
|
||||||
|
@ -50,8 +53,12 @@ describe("Eval with Bindings", () => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
Partial code is a partial code fragment that is cut out from a larger code.
|
||||||
|
Therefore it does not end with an expression.
|
||||||
|
*/
|
||||||
Only.describe("Eval Partial", () => {
|
Only.describe("Eval Partial", () => {
|
||||||
MyOnly.testEvalPartialBindingsToBe(
|
testEvalPartialBindingsToBe(
|
||||||
// A partial cannot end with an expression
|
// A partial cannot end with an expression
|
||||||
"x",
|
"x",
|
||||||
list{("x", ExpressionValue.EvNumber(1.))},
|
list{("x", ExpressionValue.EvNumber(1.))},
|
||||||
|
@ -60,17 +67,17 @@ Only.describe("Eval Partial", () => {
|
||||||
testEvalPartialBindingsToBe(
|
testEvalPartialBindingsToBe(
|
||||||
"y=x",
|
"y=x",
|
||||||
list{("x", ExpressionValue.EvNumber(1.))},
|
list{("x", ExpressionValue.EvNumber(1.))},
|
||||||
"????",
|
"Ok({x: 1, y: 1})",
|
||||||
)
|
)
|
||||||
testEvalBindingsToBe(
|
testEvalPartialBindingsToBe(
|
||||||
"y=x+1",
|
"y=x+1",
|
||||||
list{("x", ExpressionValue.EvNumber(1.))},
|
list{("x", ExpressionValue.EvNumber(1.))},
|
||||||
"????",
|
"Ok({x: 1, y: 2})",
|
||||||
)
|
)
|
||||||
testEvalBindingsToBe(
|
MyOnly.testEvalPartialBindingsToBe(
|
||||||
"y = x+1; z = y",
|
"y = x+1; z = y",
|
||||||
list{("x", ExpressionValue.EvNumber(1.))},
|
list{("x", ExpressionValue.EvNumber(1.))},
|
||||||
"????",
|
"Ok({x: 1, y: 2, z: 2})",
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,26 @@
|
||||||
|
/*
|
||||||
|
Macros are like functions but instead of taking values as parameters,
|
||||||
|
they take expressions as parameters and return a new expression.
|
||||||
|
Macros are used to define language building blocks. They are like Lisp macros.
|
||||||
|
*/
|
||||||
|
module ExpressionT = Reducer_Expression_T
|
||||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
module ExpressionValue = ReducerInterface.ExpressionValue
|
||||||
module Result = Belt.Result
|
module Result = Belt.Result
|
||||||
module ExpressionT = Reducer_Expression_T
|
|
||||||
open Reducer_ErrorValue
|
open Reducer_ErrorValue
|
||||||
|
|
||||||
type expression = ExpressionT.expression
|
type expression = ExpressionT.expression
|
||||||
|
|
||||||
let dispatchMacroCall = (list: list<expression>, bindings: ExpressionT.bindings): result<
|
type reducerFn = (
|
||||||
expression,
|
expression,
|
||||||
'e,
|
ExpressionT.bindings,
|
||||||
> => {
|
) => result<ExpressionValue.expressionValue, errorValue>
|
||||||
|
|
||||||
|
let dispatchMacroCall = (
|
||||||
|
list: list<expression>,
|
||||||
|
bindings: ExpressionT.bindings,
|
||||||
|
reduceExpression: reducerFn,
|
||||||
|
): result<expression, 'e> => {
|
||||||
let rec replaceSymbols = (expression: expression, bindings: ExpressionT.bindings): result<
|
let rec replaceSymbols = (expression: expression, bindings: ExpressionT.bindings): result<
|
||||||
expression,
|
expression,
|
||||||
errorValue,
|
errorValue,
|
||||||
|
@ -40,9 +52,16 @@ let dispatchMacroCall = (list: list<expression>, bindings: ExpressionT.bindings)
|
||||||
| ExpressionT.EList(list{
|
| ExpressionT.EList(list{
|
||||||
ExpressionT.EValue(EvCall("$let")),
|
ExpressionT.EValue(EvCall("$let")),
|
||||||
ExpressionT.EValue(EvSymbol(aSymbol)),
|
ExpressionT.EValue(EvSymbol(aSymbol)),
|
||||||
expression,
|
expressionToReduce,
|
||||||
}) => {
|
}) => {
|
||||||
let rNewExpression = replaceSymbols(expression, bindings)
|
let rNewExpressionToReduce = replaceSymbols(expressionToReduce, bindings)
|
||||||
|
|
||||||
|
let rNewValue =
|
||||||
|
rNewExpressionToReduce->Result.flatMap(newExpressionToReduce =>
|
||||||
|
reduceExpression(newExpressionToReduce, bindings)
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
Belt.Map.String.set(bindings, aSymbol, newExpression)->ExpressionT.EBindings
|
||||||
)
|
)
|
||||||
|
@ -51,35 +70,37 @@ let dispatchMacroCall = (list: list<expression>, bindings: ExpressionT.bindings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let doBindExpression = (expression: expression, bindings: ExpressionT.bindings) => {
|
let doExportVariableExpression = (bindings: ExpressionT.bindings) => {
|
||||||
|
let emptyDictionary: Js.Dict.t<ExpressionValue.expressionValue> = Js.Dict.empty()
|
||||||
|
let reducedBindings = bindings->Belt.Map.String.keep((key, value) =>
|
||||||
|
switch value {
|
||||||
|
| ExpressionT.EValue(_) => true
|
||||||
|
| _ => false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
let externalBindings = reducedBindings->Belt.Map.String.reduce(emptyDictionary, (
|
||||||
|
acc,
|
||||||
|
key,
|
||||||
|
expressionValue,
|
||||||
|
) => {
|
||||||
|
let value = switch expressionValue {
|
||||||
|
| EValue(aValue) => aValue
|
||||||
|
| _ => EvSymbol("internal")
|
||||||
|
}
|
||||||
|
Js.Dict.set(acc, key, value)
|
||||||
|
acc
|
||||||
|
})
|
||||||
|
externalBindings->EvRecord->ExpressionT.EValue->Ok
|
||||||
|
}
|
||||||
|
|
||||||
|
let doBindExpression = (expression: expression, bindings: ExpressionT.bindings) =>
|
||||||
switch expression {
|
switch expression {
|
||||||
| ExpressionT.EList(list{ExpressionT.EValue(EvCall("$let")), ..._}) =>
|
| ExpressionT.EList(list{ExpressionT.EValue(EvCall("$let")), ..._}) =>
|
||||||
REExpressionExpected->Error
|
REExpressionExpected->Error
|
||||||
|
| ExpressionT.EList(list{ExpressionT.EValue(EvCall("$exportVariablesExpression"))}) =>
|
||||||
|
doExportVariableExpression(bindings)
|
||||||
| _ => replaceSymbols(expression, bindings)
|
| _ => replaceSymbols(expression, bindings)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let doExportVariableExpression = (bindings: ExpressionT.bindings) => {
|
|
||||||
let emptyDictionary: Js.Dict.t<ExpressionValue.expressionValue> = Js.Dict.empty()
|
|
||||||
let reducedBindings = bindings->Belt.Map.String.keep (
|
|
||||||
(key, value) =>
|
|
||||||
switch value {
|
|
||||||
| ExpressionT.EValue(_) => true
|
|
||||||
| _ => false
|
|
||||||
}
|
|
||||||
)
|
|
||||||
let externalBindings = reducedBindings->Belt.Map.String.reduce(
|
|
||||||
emptyDictionary,
|
|
||||||
(acc, key, expressionValue) => {
|
|
||||||
let value = switch expressionValue {
|
|
||||||
| EValue(aValue) => aValue
|
|
||||||
| _ => EvSymbol("internal")
|
|
||||||
}
|
|
||||||
Js.Dict.set(acc, key, value); acc
|
|
||||||
}
|
|
||||||
)
|
|
||||||
externalBindings->EvRecord->ExpressionT.EValue->Ok
|
|
||||||
}
|
|
||||||
|
|
||||||
switch list {
|
switch list {
|
||||||
| list{ExpressionT.EValue(EvCall("$$bindings"))} => bindings->ExpressionT.EBindings->Ok
|
| list{ExpressionT.EValue(EvCall("$$bindings"))} => bindings->ExpressionT.EBindings->Ok
|
||||||
|
@ -90,11 +111,6 @@ let dispatchMacroCall = (list: list<expression>, bindings: ExpressionT.bindings)
|
||||||
statement,
|
statement,
|
||||||
} =>
|
} =>
|
||||||
doBindStatement(statement, bindings)
|
doBindStatement(statement, bindings)
|
||||||
| list{
|
|
||||||
ExpressionT.EValue(EvCall("$$bindExpression")),
|
|
||||||
ExpressionT.EBindings(bindings),
|
|
||||||
ExpressionT.EList(list{EValue(EvCall("$exportVariableExpression")), ..._}),
|
|
||||||
} => doExportVariableExpression(bindings)
|
|
||||||
| list{
|
| list{
|
||||||
ExpressionT.EValue(EvCall("$$bindExpression")),
|
ExpressionT.EValue(EvCall("$$bindExpression")),
|
||||||
ExpressionT.EBindings(bindings),
|
ExpressionT.EBindings(bindings),
|
||||||
|
|
|
@ -50,7 +50,15 @@ let defaultBindings: T.bindings = Belt.Map.String.empty
|
||||||
/*
|
/*
|
||||||
Recursively evaluate/reduce the expression (Lisp AST)
|
Recursively evaluate/reduce the expression (Lisp AST)
|
||||||
*/
|
*/
|
||||||
let reduceExpression = (expression: t, bindings: T.bindings): result<expressionValue, 'e> => {
|
let rec reduceExpression = (expression: t, bindings: T.bindings): result<expressionValue, 'e> => {
|
||||||
|
/*
|
||||||
|
Macros are like functions but instead of taking values as parameters,
|
||||||
|
they take expressions as parameters and return a new expression.
|
||||||
|
Macros are used to define language building blocks. They are like Lisp macros.
|
||||||
|
*/
|
||||||
|
let doMacroCall = (list: list<t>, bindings: T.bindings): result<t, 'e> =>
|
||||||
|
Reducer_Dispatch_BuiltInMacros.dispatchMacroCall(list, bindings, reduceExpression)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
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
|
||||||
*/
|
*/
|
||||||
|
@ -60,14 +68,6 @@ let reduceExpression = (expression: t, bindings: T.bindings): result<expressionV
|
||||||
| _ => valueList->Belt.List.toArray->ExpressionValue.EvArray->Ok
|
| _ => valueList->Belt.List.toArray->ExpressionValue.EvArray->Ok
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Macros are like functions but instead of taking values as parameters,
|
|
||||||
they take expressions as parameters and return a new expression.
|
|
||||||
Macros are used to define language building blocks. They are like Lisp macros.
|
|
||||||
*/
|
|
||||||
let doMacroCall = (list: list<t>, bindings: T.bindings): result<t, 'e> =>
|
|
||||||
list->Reducer_Dispatch_BuiltInMacros.dispatchMacroCall(bindings)
|
|
||||||
|
|
||||||
let rec seekMacros = (expression: t, bindings: T.bindings): result<t, 'e> =>
|
let rec seekMacros = (expression: t, bindings: T.bindings): result<t, 'e> =>
|
||||||
switch expression {
|
switch expression {
|
||||||
| T.EValue(_value) => expression->Ok
|
| T.EValue(_value) => expression->Ok
|
||||||
|
|
Loading…
Reference in New Issue
Block a user