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 open Expect
let unwrapRecord = rValue => let unwrapRecord = rValue =>
rValue->Belt.Result.flatMap(value => switch value { rValue->Belt.Result.flatMap(value =>
| ExpressionValue.EvRecord(aRecord) => Ok(aRecord) switch value {
| _ => ErrorValue.RETodo("TODO: External bindings must be returned")->Error | ExpressionValue.EvRecord(aRecord) => Ok(aRecord)
} | _ => ErrorValue.RETodo("TODO: External bindings must be returned")->Error
) }
)
let expectParseToBe = (expr: string, answer: string) => let expectParseToBe = (expr: string, answer: string) =>
Reducer.parse(expr)->Expression.toStringResult->expect->toBe(answer) 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) Reducer.evaluate(expr)->ExpressionValue.toStringResult->expect->toBe(answer)
let expectEvalBindingsToBe = (expr: string, bindings: Reducer.externalBindings, answer: string) => 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 ->ExpressionValue.toStringResult
->expect ->expect
->toBe(answer) ->toBe(answer)
@ -35,7 +41,12 @@ let expectEvalPartialBindingsToBe = (
bindings: Reducer.externalBindings, bindings: Reducer.externalBindings,
answer: string, 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 ->unwrapRecord
->ExpressionValue.toStringResultRecord ->ExpressionValue.toStringResultRecord
->expect ->expect

View File

@ -5,27 +5,23 @@ module Extra = Reducer_Extra
module Js = Reducer_Js module Js = Reducer_Js
module MathJs = Reducer_MathJs module MathJs = Reducer_MathJs
@genType @genType
type environment = ReducerInterface_ExpressionValue.environment type environment = ReducerInterface_ExpressionValue.environment
@genType @genType
type errorValue = Reducer_ErrorValue.errorValue type errorValue = Reducer_ErrorValue.errorValue
@genType @genType
type expressionValue = ReducerInterface_ExpressionValue.expressionValue type expressionValue = ReducerInterface_ExpressionValue.expressionValue
@genType @genType
type externalBindings = ReducerInterface_ExpressionValue.externalBindings type externalBindings = ReducerInterface_ExpressionValue.externalBindings
@genType @genType
let evaluateUsingOptions: ( let evaluateUsingOptions: (
~environment: option< ~environment: option<QuriSquiggleLang.ReducerInterface_ExpressionValue.environment>,
QuriSquiggleLang.ReducerInterface_ExpressionValue.environment, ~externalBindings: option<QuriSquiggleLang.ReducerInterface_ExpressionValue.externalBindings>,
>,
~externalBindings: option<
QuriSquiggleLang.ReducerInterface_ExpressionValue.externalBindings,
>,
~isPartial: option<bool>, ~isPartial: option<bool>,
string, string,
) => result<expressionValue, errorValue> ) => result<expressionValue, errorValue>
@genType @genType
let evaluate: string => result<expressionValue, errorValue> let evaluate: string => result<expressionValue, errorValue>
let parse: string => result<Expression.expression, 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 NOTE: This function is cancelled. The related issue is
https://github.com/webpack/webpack/issues/13435 https://github.com/webpack/webpack/issues/13435
*/ */
let inspectPerformance = (value: expressionValue, label: string) => { let inspectPerformance = (value: expressionValue, label: string) => {
// let _ = %raw("{performance} = require('perf_hooks')") // let _ = %raw("{performance} = require('perf_hooks')")
// let start = %raw(`performance.now()`) // 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) 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, Macros are like functions but instead of taking values as parameters,
they take expressions as parameters and return a new expression. they take expressions as parameters and return a new expression.
Macros are used to define language building blocks. They are like Lisp macros. 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) Reducer_Dispatch_BuiltInMacros.dispatchMacroCall(list, bindings, environment, reduceExpression)
let applyParametersToLambda = ( let applyParametersToLambda = (
internal: internalCode, internal: internalCode,
parameters: array<string>, parameters: array<string>,
args: list<expressionValue>, args: list<expressionValue>,
environment environment,
): result<expressionValue, 'e> => { ): result<expressionValue, 'e> => {
let expr = castInternalCodeToExpression(internal) let expr = castInternalCodeToExpression(internal)
let parameterList = parameters->Belt.List.fromArray 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 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 { 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)" // "(lambda(x=>internal) param)"
| list{EvLambda((parameters, internal)), ...args} => | list{EvLambda((parameters, internal)), ...args} =>
applyParametersToLambda(internal, parameters, args, environment) 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> => let evalUsingExternalBindingsExpression_ = (aExpression, bindings, environment): result<
reduceExpression(aExpression, bindings, environment) expressionValue,
'e,
> => reduceExpression(aExpression, bindings, environment)
/* /*
Evaluates MathJs code via Reducer using bindings and answers the result. Evaluates MathJs code via Reducer using bindings and answers the result.
@ -187,24 +199,24 @@ let externalBindingsToBindings = (externalBindings: externalBindings): T.binding
} }
let evaluateUsingOptions = ( let evaluateUsingOptions = (
~environment: option<ReducerInterface_ExpressionValue.environment>, ~environment: option<ReducerInterface_ExpressionValue.environment>,
~externalBindings: option<ReducerInterface_ExpressionValue.externalBindings>, ~externalBindings: option<ReducerInterface_ExpressionValue.externalBindings>,
~isPartial: option<bool>, ~isPartial: option<bool>,
code: string): result<expressionValue, errorValue> => { code: string,
): result<expressionValue, errorValue> => {
let anEnvironment = switch environment { let anEnvironment = switch environment {
| Some(env) => env | Some(env) => env
| None => ReducerInterface_ExpressionValue.defaultEnvironment | None => ReducerInterface_ExpressionValue.defaultEnvironment
} }
let anExternalBindings = switch externalBindings { let anExternalBindings = switch externalBindings {
| Some(bindings) => bindings | Some(bindings) => bindings
| None => ReducerInterface_ExpressionValue.defaultExternalBindings | None => ReducerInterface_ExpressionValue.defaultExternalBindings
} }
let anIsPartial = switch isPartial { let anIsPartial = switch isPartial {
| Some(isPartial) => isPartial | Some(isPartial) => isPartial
| None => false | None => false
} }
let bindings = anExternalBindings->externalBindingsToBindings let bindings = anExternalBindings->externalBindingsToBindings

View File

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

View File

@ -14,8 +14,13 @@ type expressionValue = ExpressionValue.expressionValue
Map external calls of Reducer Map external calls of Reducer
*/ */
let dispatch = (call: ExpressionValue.functionCall, environment, chain): result<expressionValue, 'e> => let dispatch = (call: ExpressionValue.functionCall, environment, chain): result<
ReducerInterface_GenericDistribution.dispatch(call, environment) |> E.O.default(chain(call, environment)) 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. 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< let dispatch: (
result<ReducerInterface_ExpressionValue.expressionValue, Reducer_ErrorValue.errorValue>, ReducerInterface_ExpressionValue.functionCall,
> ReducerInterface_ExpressionValue.environment,
) => option<result<ReducerInterface_ExpressionValue.expressionValue, Reducer_ErrorValue.errorValue>>