refactor macro definitions

This commit is contained in:
Umur Ozkul 2022-04-14 18:17:45 +02:00
parent 1fa1867470
commit 53c44cdc9d
3 changed files with 82 additions and 57 deletions

View File

@ -1 +1,2 @@
module Builtin = Reducer_Dispatch_BuiltIn
module BuiltinMacros = Reducer_Dispatch_BuiltInMacros

View File

@ -0,0 +1,79 @@
module ExpressionValue = ReducerInterface.ExpressionValue
module Result = Belt.Result
module ExpressionT = Reducer_Expression_T
open Reducer_ErrorValue
type expression = ExpressionT.expression
let dispatchMacroCall = (list: list<expression>, bindings: ExpressionT.bindings): result<
expression,
'e,
> => {
let rec replaceSymbols = (expression: expression, bindings: ExpressionT.bindings): result<
expression,
errorValue,
> =>
switch expression {
| ExpressionT.EValue(EvSymbol(aSymbol)) =>
switch bindings->Belt.Map.String.get(aSymbol) {
| Some(boundExpression) => boundExpression->Ok
| None => RESymbolNotFound(aSymbol)->Error
}
| ExpressionT.EValue(_) => expression->Ok
| ExpressionT.EBindings(_) => expression->Ok
| ExpressionT.EList(list) => {
let racc = list->Belt.List.reduceReverse(Ok(list{}), (racc, each: expression) =>
racc->Result.flatMap(acc => {
each
->replaceSymbols(bindings)
->Result.flatMap(newNode => {
acc->Belt.List.add(newNode)->Ok
})
})
)
racc->Result.map(acc => acc->ExpressionT.EList)
}
}
let doBindStatement = (statement: expression, bindings: ExpressionT.bindings) => {
switch statement {
| ExpressionT.EList(list{
ExpressionT.EValue(EvCall("$let")),
ExpressionT.EValue(EvSymbol(aSymbol)),
expression,
}) => {
let rNewExpression = replaceSymbols(expression, bindings)
rNewExpression->Result.map(newExpression =>
Belt.Map.String.set(bindings, aSymbol, newExpression)->ExpressionT.EBindings
)
}
| _ => REAssignmentExpected->Error
}
}
let doBindExpression = (expression: expression, bindings: ExpressionT.bindings) => {
switch expression {
| ExpressionT.EList(list{ExpressionT.EValue(EvCall("$let")), ..._}) =>
REExpressionExpected->Error
| _ => replaceSymbols(expression, bindings)
}
}
switch list {
| list{ExpressionT.EValue(EvCall("$$bindings"))} => bindings->ExpressionT.EBindings->Ok
| list{
ExpressionT.EValue(EvCall("$$bindStatement")),
ExpressionT.EBindings(bindings),
statement,
} =>
doBindStatement(statement, bindings)
| list{
ExpressionT.EValue(EvCall("$$bindExpression")),
ExpressionT.EBindings(bindings),
expression,
} =>
doBindExpression(expression, bindings)
| _ => list->ExpressionT.EList->Ok
}
}

View File

@ -59,63 +59,8 @@ let reduceExpression = (expression: t, bindings: T.bindings): result<expressionV
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> => {
let dispatchMacroCall = (list: list<t>, bindings: T.bindings): result<t, 'e> => {
let rec replaceSymbols = (expression: t, bindings: T.bindings): result<t, errorValue> =>
switch expression {
| T.EValue(EvSymbol(aSymbol)) =>
switch bindings->Belt.Map.String.get(aSymbol) {
| Some(boundExpression) => boundExpression->Ok
| None => RESymbolNotFound(aSymbol)->Error
}
| T.EValue(_) => expression->Ok
| T.EBindings(_) => expression->Ok
| T.EList(list) => {
let racc = list->Belt.List.reduceReverse(Ok(list{}), (racc, each: expression) =>
racc->Result.flatMap(acc => {
each
->replaceSymbols(bindings)
->Result.flatMap(newNode => {
acc->Belt.List.add(newNode)->Ok
})
})
)
racc->Result.map(acc => acc->T.EList)
}
}
let doBindStatement = (statement: t, bindings: T.bindings) => {
switch statement {
| T.EList(list{T.EValue(EvCall("$let")), T.EValue(EvSymbol(aSymbol)), expression}) => {
let rNewExpression = replaceSymbols(expression, bindings)
rNewExpression->Result.map(newExpression =>
Belt.Map.String.set(bindings, aSymbol, newExpression)->T.EBindings
)
}
| _ => REAssignmentExpected->Error
}
}
let doBindExpression = (expression: t, bindings: T.bindings) => {
switch expression {
| T.EList(list{T.EValue(EvCall("$let")), ..._}) => REExpressionExpected->Error
| _ => replaceSymbols(expression, bindings)
}
}
switch list {
| list{T.EValue(EvCall("$$bindings"))} => bindings->T.EBindings->Ok
| list{T.EValue(EvCall("$$bindStatement")), T.EBindings(bindings), statement} =>
doBindStatement(statement, bindings)
| list{T.EValue(EvCall("$$bindExpression")), T.EBindings(bindings), expression} =>
doBindExpression(expression, bindings)
| _ => list->T.EList->Ok
}
}
list->dispatchMacroCall(bindings)
}
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> =>
switch expression {