foo test
This commit is contained in:
parent
c0329dc73d
commit
6edacc78e4
|
@ -0,0 +1,94 @@
|
|||
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||
module ExpressionT = Reducer_Expression_T
|
||||
module Module = Reducer_Module
|
||||
module Bindings = Reducer_Module
|
||||
module ErrorValue = Reducer_ErrorValue
|
||||
|
||||
open Jest
|
||||
open Expect
|
||||
|
||||
// ----------------------
|
||||
// --- Start of Module File
|
||||
// ----------------------
|
||||
|
||||
module FooImplementation = {
|
||||
let fooNumber = 0.0
|
||||
let fooString = "Foo String"
|
||||
let fooBool = true
|
||||
let makeFoo = (a: string, b: string, _environment): string => `I am ${a}-foo and I am ${b}-foo`
|
||||
let makeBar = (a: float, b: float, _environment): string =>
|
||||
`I am ${a->Js.Float.toString}-bar and I am ${b->Js.Float.toString}-bar`
|
||||
}
|
||||
|
||||
module FooFFI = {
|
||||
let makeFoo: ExpressionT.optionFfiFn = (args: array<InternalExpressionValue.t>, environment) => {
|
||||
switch args {
|
||||
| [IEvString(a), IEvString(b)] => FooImplementation.makeFoo(a, b, environment)->IEvString->Some
|
||||
| _ => None
|
||||
}
|
||||
}
|
||||
let makeBar: ExpressionT.optionFfiFn = (args: array<InternalExpressionValue.t>, environment) =>
|
||||
switch args {
|
||||
| [IEvNumber(a), IEvNumber(b)] => FooImplementation.makeBar(a, b, environment)->IEvString->Some
|
||||
| _ => None
|
||||
}
|
||||
}
|
||||
|
||||
let fooModule: Module.t =
|
||||
Module.emptyStdLib
|
||||
->Module.defineNumber("fooNumber", FooImplementation.fooNumber)
|
||||
->Module.defineString("fooString", FooImplementation.fooString)
|
||||
->Module.defineBool("fooBool", FooImplementation.fooBool)
|
||||
->Module.defineFunction("makeFoo", FooFFI.makeFoo)
|
||||
->Module.defineFunction("makeBar", FooFFI.makeBar)
|
||||
|
||||
let makeBindings = (prevBindings: Bindings.t): Bindings.t =>
|
||||
prevBindings->Module.defineModule("Foo", fooModule)
|
||||
|
||||
// ----------------------
|
||||
// --- End of Module File
|
||||
// ----------------------
|
||||
|
||||
let stdLibWithFoo = Bindings.emptyBindings->makeBindings
|
||||
let evalWithFoo = sourceCode =>
|
||||
Reducer_Expression.parse(sourceCode)->Belt.Result.flatMap(expr =>
|
||||
Reducer_Expression.reduceExpression(
|
||||
expr,
|
||||
stdLibWithFoo,
|
||||
InternalExpressionValue.defaultEnvironment,
|
||||
)
|
||||
)
|
||||
let evalToStringResultWithFoo = sourceCode =>
|
||||
evalWithFoo(sourceCode)->InternalExpressionValue.toStringResult
|
||||
|
||||
describe("Module", () => {
|
||||
test("fooNumber", () => {
|
||||
let result = evalToStringResultWithFoo("Foo.fooNumber")
|
||||
expect(result)->toEqual("Ok(0)")
|
||||
})
|
||||
test("fooString", () => {
|
||||
let result = evalToStringResultWithFoo("Foo.fooString")
|
||||
expect(result)->toEqual("Ok('Foo String')")
|
||||
})
|
||||
test("fooBool", () => {
|
||||
let result = evalToStringResultWithFoo("Foo.fooBool")
|
||||
expect(result)->toEqual("Ok(true)")
|
||||
})
|
||||
test("fooBool", () => {
|
||||
let result = evalToStringResultWithFoo("Foo.fooBool")
|
||||
expect(result)->toEqual("Ok(true)")
|
||||
})
|
||||
test("makeFoo", () => {
|
||||
let result = evalToStringResultWithFoo("Foo.makeFoo('a', 'b')")
|
||||
expect(result)->toEqual("Ok('I am a-foo and I am b-foo')")
|
||||
})
|
||||
test("makeFoo wrong arguments", () => {
|
||||
let result = evalToStringResultWithFoo("Foo.makeFoo(1, 2)")
|
||||
// Notice the error with types
|
||||
expect(result)->toEqual("Error(Function not found: makeFoo(Number,Number))")
|
||||
})
|
||||
test("makeBar", () => {
|
||||
let result = evalToStringResultWithFoo("Foo.makeBar(1, 2)")
|
||||
expect(result)->toEqual("Ok('I am 1-bar and I am 2-bar')")
|
||||
})
|
||||
})
|
|
@ -19,12 +19,19 @@ let checkArity = (
|
|||
lambdaValue: ExpressionValue.lambdaValue,
|
||||
args: list<internalExpressionValue>,
|
||||
) => {
|
||||
let argsLength = Belt.List.length(args)
|
||||
let parametersLength = Js.Array2.length(lambdaValue.parameters)
|
||||
if argsLength !== parametersLength {
|
||||
ErrorValue.REArityError(None, parametersLength, argsLength)->Error
|
||||
} else {
|
||||
args->Ok
|
||||
let reallyCheck = {
|
||||
let argsLength = Belt.List.length(args)
|
||||
let parametersLength = Js.Array2.length(lambdaValue.parameters)
|
||||
if argsLength !== parametersLength {
|
||||
ErrorValue.REArityError(None, parametersLength, argsLength)->Error
|
||||
} else {
|
||||
args->Ok
|
||||
}
|
||||
}
|
||||
let exprOrFFI = castInternalCodeToExpression(lambdaValue.body)
|
||||
switch exprOrFFI {
|
||||
| NotFFI(_) => reallyCheck
|
||||
| FFI(_) => args->Ok
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,8 @@ type ffiFn = (
|
|||
environment,
|
||||
) => result<internalExpressionValue, Reducer_ErrorValue.errorValue>
|
||||
|
||||
type optionFfiFn = (array<internalExpressionValue>, environment) => option<internalExpressionValue>
|
||||
|
||||
type expressionOrFFI =
|
||||
| NotFFI(expression)
|
||||
| FFI(ffiFn)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
module ExpressionT = Reducer_Expression_T
|
||||
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||
open Reducer_ErrorValue
|
||||
open ReducerInterface_InternalExpressionValue
|
||||
|
||||
let expressionValueToString = toString
|
||||
|
@ -68,6 +70,7 @@ let set = (nameSpace: t, id: string, value): t => {
|
|||
}
|
||||
|
||||
let emptyModule: t = NameSpace(emptyMap)
|
||||
let emptyBindings = emptyModule
|
||||
|
||||
let fromTypeScriptBindings = ReducerInterface_InternalExpressionValue.nameSpaceFromTypeScriptBindings
|
||||
let toTypeScriptBindings = ReducerInterface_InternalExpressionValue.nameSpaceToTypeScriptBindings
|
||||
|
@ -110,16 +113,50 @@ let eLambdaFFIValue = (ffiFn: ExpressionT.ffiFn) => {
|
|||
})
|
||||
}
|
||||
|
||||
let functionNotFoundError = (call: functionCall) =>
|
||||
REFunctionNotFound(call->functionCallToCallSignature->functionCallSignatureToString)->Error
|
||||
|
||||
let functionNotFoundErrorFFIFn = (functionName: string): ExpressionT.ffiFn => {
|
||||
(args: array<internalExpressionValue>, _environment: environment): result<
|
||||
internalExpressionValue,
|
||||
errorValue,
|
||||
> => {
|
||||
let call = (functionName, args)
|
||||
functionNotFoundError(call)
|
||||
}
|
||||
}
|
||||
|
||||
let convertOptionToFfiFn = (
|
||||
myFunctionName: string,
|
||||
myFunction: ExpressionT.optionFfiFn,
|
||||
): ExpressionT.ffiFn => {
|
||||
(args: array<InternalExpressionValue.t>, environment) => {
|
||||
myFunction(args, environment)
|
||||
->Belt.Option.map(v => v->Ok)
|
||||
->Belt.Option.getWithDefault(functionNotFoundErrorFFIFn(myFunctionName)(args, environment))
|
||||
}
|
||||
}
|
||||
|
||||
// -- Module definition
|
||||
let define = (nameSpace: t, identifier: string, ev: internalExpressionValue): t => {
|
||||
let NameSpace(container) = nameSpace
|
||||
Belt.Map.String.set(container, identifier, ev)->NameSpace
|
||||
}
|
||||
|
||||
let defineNumber = (nameSpace: t, identifier: string, value: float): t =>
|
||||
nameSpace->define(identifier, IEvNumber(value))
|
||||
|
||||
let defineString = (nameSpace: t, identifier: string, value: string): t =>
|
||||
nameSpace->define(identifier, IEvString(value))
|
||||
|
||||
let defineBool = (nameSpace: t, identifier: string, value: bool): t =>
|
||||
nameSpace->define(identifier, IEvBool(value))
|
||||
|
||||
let defineModule = (nameSpace: t, identifier: string, value: t): t =>
|
||||
nameSpace->define(identifier, toExpressionValue(value))
|
||||
|
||||
let defineFFI = (nameSpace: t, identifier: string, value: ExpressionT.ffiFn): t =>
|
||||
nameSpace->define(identifier, value->eLambdaFFIValue)
|
||||
let defineFunction = (nameSpace: t, identifier: string, value: ExpressionT.optionFfiFn): t => {
|
||||
nameSpace->define(identifier, convertOptionToFfiFn(identifier, value)->eLambdaFFIValue)
|
||||
}
|
||||
|
||||
let emptyStdLib: t = emptyModule->defineBool("stdlib", true)
|
||||
|
|
|
@ -1,25 +1,11 @@
|
|||
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
|
||||
module ExpressionT = Reducer_Expression_T
|
||||
open Reducer_ErrorValue
|
||||
open ReducerInterface_InternalExpressionValue
|
||||
// open ReducerInterface_InternalExpressionValue
|
||||
|
||||
type expression = ExpressionT.expression
|
||||
|
||||
let defaultCase = (call: functionCall) =>
|
||||
REFunctionNotFound(call->functionCallToCallSignature->functionCallSignatureToString)->Error
|
||||
|
||||
let defaultCaseFFIFn = (functionName: string): ExpressionT.ffiFn => {
|
||||
(args: array<internalExpressionValue>, _environment: environment): result<
|
||||
internalExpressionValue,
|
||||
errorValue,
|
||||
> => {
|
||||
let call = (functionName, args)
|
||||
defaultCase(call)
|
||||
}
|
||||
}
|
||||
|
||||
let defaultCaseFFI = (functionName: string): expression => {
|
||||
ExpressionBuilder.eLambdaFFI(defaultCaseFFIFn(functionName))
|
||||
ExpressionBuilder.eLambdaFFI(Reducer_Module.functionNotFoundErrorFFIFn(functionName))
|
||||
}
|
||||
|
||||
let addGuard = (
|
||||
|
|
Loading…
Reference in New Issue
Block a user