This commit is contained in:
Umur Ozkul 2022-04-27 22:24:06 +02:00
parent 5c1ce71a40
commit 7b052ee3c3
7 changed files with 68 additions and 44 deletions

View File

@ -6,11 +6,12 @@ open Jest
open Expect
let unwrapRecord = rValue =>
rValue->Belt.Result.flatMap(value => switch value {
| ExpressionValue.EvRecord(aRecord) => Ok(aRecord)
| _ => ErrorValue.RETodo("TODO: External bindings must be returned")->Error
}
)
rValue->Belt.Result.flatMap(value =>
switch value {
| ExpressionValue.EvRecord(aRecord) => Ok(aRecord)
| _ => ErrorValue.RETodo("TODO: External bindings must be returned")->Error
}
)
let expectParseToBe = (expr: string, answer: string) =>
Reducer.parse(expr)->Expression.toStringResult->expect->toBe(answer)
@ -25,7 +26,12 @@ let expectEvalToBe = (expr: string, answer: string) =>
Reducer.evaluate(expr)->ExpressionValue.toStringResult->expect->toBe(answer)
let expectEvalBindingsToBe = (expr: string, bindings: Reducer.externalBindings, answer: string) =>
Reducer.evaluateUsingOptions(expr, ~externalBindings=Some(bindings), ~isPartial=None, ~environment=None)
Reducer.evaluateUsingOptions(
expr,
~externalBindings=Some(bindings),
~isPartial=None,
~environment=None,
)
->ExpressionValue.toStringResult
->expect
->toBe(answer)
@ -35,7 +41,12 @@ let expectEvalPartialBindingsToBe = (
bindings: Reducer.externalBindings,
answer: string,
) =>
Reducer.evaluateUsingOptions(expr, ~externalBindings=Some(bindings), ~isPartial=Some(true), ~environment=None)
Reducer.evaluateUsingOptions(
expr,
~externalBindings=Some(bindings),
~isPartial=Some(true),
~environment=None,
)
->unwrapRecord
->ExpressionValue.toStringResultRecord
->expect

View File

@ -5,27 +5,23 @@ module Extra = Reducer_Extra
module Js = Reducer_Js
module MathJs = Reducer_MathJs
@genType
@genType
type environment = ReducerInterface_ExpressionValue.environment
@genType
@genType
type errorValue = Reducer_ErrorValue.errorValue
@genType
@genType
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
@genType
@genType
type externalBindings = ReducerInterface_ExpressionValue.externalBindings
@genType
@genType
let evaluateUsingOptions: (
~environment: option<
QuriSquiggleLang.ReducerInterface_ExpressionValue.environment,
>,
~externalBindings: option<
QuriSquiggleLang.ReducerInterface_ExpressionValue.externalBindings,
>,
~environment: option<QuriSquiggleLang.ReducerInterface_ExpressionValue.environment>,
~externalBindings: option<QuriSquiggleLang.ReducerInterface_ExpressionValue.externalBindings>,
~isPartial: option<bool>,
string,
) => result<expressionValue, errorValue>
@genType
@genType
let evaluate: string => result<expressionValue, errorValue>
let parse: string => result<Expression.expression, errorValue>

View File

@ -56,7 +56,7 @@ let callInternal = (call: functionCall, _environment): result<'b, errorValue> =>
/*
NOTE: This function is cancelled. The related issue is
https://github.com/webpack/webpack/issues/13435
*/
*/
let inspectPerformance = (value: expressionValue, label: string) => {
// let _ = %raw("{performance} = require('perf_hooks')")
// let start = %raw(`performance.now()`)

View File

@ -60,20 +60,26 @@ let defaultBindings: T.bindings = Belt.Map.String.empty
/*
Recursively evaluate/reduce the expression (Lisp AST)
*/
let rec reduceExpression = (expression: t, bindings: T.bindings, environment: environment): result<expressionValue, 'e> => {
let rec reduceExpression = (expression: t, bindings: T.bindings, environment: environment): 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, environment: environment): result<t, 'e> =>
let doMacroCall = (list: list<t>, bindings: T.bindings, environment: environment): result<
t,
'e,
> =>
Reducer_Dispatch_BuiltInMacros.dispatchMacroCall(list, bindings, environment, reduceExpression)
let applyParametersToLambda = (
internal: internalCode,
parameters: array<string>,
args: list<expressionValue>,
environment
environment,
): result<expressionValue, 'e> => {
let expr = castInternalCodeToExpression(internal)
let parameterList = parameters->Belt.List.fromArray
@ -91,9 +97,13 @@ let rec reduceExpression = (expression: t, bindings: T.bindings, environment: en
/*
After reducing each level of expression(Lisp AST), we have a value list to evaluate
*/
let reduceValueList = (valueList: list<expressionValue>, environment): result<expressionValue, 'e> =>
let reduceValueList = (valueList: list<expressionValue>, environment): result<
expressionValue,
'e,
> =>
switch valueList {
| list{EvCall(fName), ...args} => (fName, args->Belt.List.toArray)->BuiltIn.dispatch(environment)
| list{EvCall(fName), ...args} =>
(fName, args->Belt.List.toArray)->BuiltIn.dispatch(environment)
// "(lambda(x=>internal) param)"
| list{EvLambda((parameters, internal)), ...args} =>
applyParametersToLambda(internal, parameters, args, environment)
@ -153,8 +163,10 @@ let rec reduceExpression = (expression: t, bindings: T.bindings, environment: en
)
}
let evalUsingExternalBindingsExpression_ = (aExpression, bindings, environment): result<expressionValue, 'e> =>
reduceExpression(aExpression, bindings, environment)
let evalUsingExternalBindingsExpression_ = (aExpression, bindings, environment): result<
expressionValue,
'e,
> => reduceExpression(aExpression, bindings, environment)
/*
Evaluates MathJs code via Reducer using bindings and answers the result.
@ -187,24 +199,24 @@ let externalBindingsToBindings = (externalBindings: externalBindings): T.binding
}
let evaluateUsingOptions = (
~environment: option<ReducerInterface_ExpressionValue.environment>,
~externalBindings: option<ReducerInterface_ExpressionValue.externalBindings>,
~isPartial: option<bool>,
code: string): result<expressionValue, errorValue> => {
~environment: option<ReducerInterface_ExpressionValue.environment>,
~externalBindings: option<ReducerInterface_ExpressionValue.externalBindings>,
~isPartial: option<bool>,
code: string,
): result<expressionValue, errorValue> => {
let anEnvironment = switch environment {
| Some(env) => env
| None => ReducerInterface_ExpressionValue.defaultEnvironment
| Some(env) => env
| None => ReducerInterface_ExpressionValue.defaultEnvironment
}
let anExternalBindings = switch externalBindings {
| Some(bindings) => bindings
| None => ReducerInterface_ExpressionValue.defaultExternalBindings
| Some(bindings) => bindings
| None => ReducerInterface_ExpressionValue.defaultExternalBindings
}
let anIsPartial = switch isPartial {
| Some(isPartial) => isPartial
| None => false
| Some(isPartial) => isPartial
| None => false
}
let bindings = anExternalBindings->externalBindingsToBindings

View File

@ -25,7 +25,6 @@ type externalBindings = Js.Dict.t<expressionValue>
@genType
let defaultExternalBindings: externalBindings = Js.Dict.empty()
type functionCall = (string, array<expressionValue>)
let rec toString = aValue =>

View File

@ -14,8 +14,13 @@ type expressionValue = ExpressionValue.expressionValue
Map external calls of Reducer
*/
let dispatch = (call: ExpressionValue.functionCall, environment, chain): result<expressionValue, 'e> =>
ReducerInterface_GenericDistribution.dispatch(call, environment) |> E.O.default(chain(call, environment))
let dispatch = (call: ExpressionValue.functionCall, environment, chain): result<
expressionValue,
'e,
> =>
ReducerInterface_GenericDistribution.dispatch(call, environment) |> E.O.default(
chain(call, environment),
)
/*
If your dispatch is too big you can divide it into smaller dispatches and pass the call so that it gets called finally.

View File

@ -1,3 +1,4 @@
let dispatch: (ReducerInterface_ExpressionValue.functionCall, ReducerInterface_ExpressionValue.environment) => option<
result<ReducerInterface_ExpressionValue.expressionValue, Reducer_ErrorValue.errorValue>,
>
let dispatch: (
ReducerInterface_ExpressionValue.functionCall,
ReducerInterface_ExpressionValue.environment,
) => option<result<ReducerInterface_ExpressionValue.expressionValue, Reducer_ErrorValue.errorValue>>