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,6 +19,7 @@ let checkArity = ( | ||||||
|   lambdaValue: ExpressionValue.lambdaValue, |   lambdaValue: ExpressionValue.lambdaValue, | ||||||
|   args: list<internalExpressionValue>, |   args: list<internalExpressionValue>, | ||||||
| ) => { | ) => { | ||||||
|  |   let reallyCheck = { | ||||||
|     let argsLength = Belt.List.length(args) |     let argsLength = Belt.List.length(args) | ||||||
|     let parametersLength = Js.Array2.length(lambdaValue.parameters) |     let parametersLength = Js.Array2.length(lambdaValue.parameters) | ||||||
|     if argsLength !== parametersLength { |     if argsLength !== parametersLength { | ||||||
|  | @ -27,6 +28,12 @@ let checkArity = ( | ||||||
|       args->Ok |       args->Ok | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |   let exprOrFFI = castInternalCodeToExpression(lambdaValue.body) | ||||||
|  |   switch exprOrFFI { | ||||||
|  |   | NotFFI(_) => reallyCheck | ||||||
|  |   | FFI(_) => args->Ok | ||||||
|  |   } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| let checkIfReduced = (args: list<internalExpressionValue>) => | let checkIfReduced = (args: list<internalExpressionValue>) => | ||||||
|   args->Belt.List.reduceReverse(Ok(list{}), (rAcc, arg) => |   args->Belt.List.reduceReverse(Ok(list{}), (rAcc, arg) => | ||||||
|  |  | ||||||
|  | @ -71,6 +71,8 @@ type ffiFn = ( | ||||||
|   environment, |   environment, | ||||||
| ) => result<internalExpressionValue, Reducer_ErrorValue.errorValue> | ) => result<internalExpressionValue, Reducer_ErrorValue.errorValue> | ||||||
| 
 | 
 | ||||||
|  | type optionFfiFn = (array<internalExpressionValue>, environment) => option<internalExpressionValue> | ||||||
|  | 
 | ||||||
| type expressionOrFFI = | type expressionOrFFI = | ||||||
|   | NotFFI(expression) |   | NotFFI(expression) | ||||||
|   | FFI(ffiFn) |   | FFI(ffiFn) | ||||||
|  |  | ||||||
|  | @ -1,4 +1,6 @@ | ||||||
| module ExpressionT = Reducer_Expression_T | module ExpressionT = Reducer_Expression_T | ||||||
|  | module InternalExpressionValue = ReducerInterface_InternalExpressionValue | ||||||
|  | open Reducer_ErrorValue | ||||||
| open ReducerInterface_InternalExpressionValue | open ReducerInterface_InternalExpressionValue | ||||||
| 
 | 
 | ||||||
| let expressionValueToString = toString | let expressionValueToString = toString | ||||||
|  | @ -68,6 +70,7 @@ let set = (nameSpace: t, id: string, value): t => { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| let emptyModule: t = NameSpace(emptyMap) | let emptyModule: t = NameSpace(emptyMap) | ||||||
|  | let emptyBindings = emptyModule | ||||||
| 
 | 
 | ||||||
| let fromTypeScriptBindings = ReducerInterface_InternalExpressionValue.nameSpaceFromTypeScriptBindings | let fromTypeScriptBindings = ReducerInterface_InternalExpressionValue.nameSpaceFromTypeScriptBindings | ||||||
| let toTypeScriptBindings = ReducerInterface_InternalExpressionValue.nameSpaceToTypeScriptBindings | 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 | // -- Module definition | ||||||
| let define = (nameSpace: t, identifier: string, ev: internalExpressionValue): t => { | let define = (nameSpace: t, identifier: string, ev: internalExpressionValue): t => { | ||||||
|   let NameSpace(container) = nameSpace |   let NameSpace(container) = nameSpace | ||||||
|   Belt.Map.String.set(container, identifier, ev)->NameSpace |   Belt.Map.String.set(container, identifier, ev)->NameSpace | ||||||
| } | } | ||||||
|  | 
 | ||||||
| let defineNumber = (nameSpace: t, identifier: string, value: float): t => | let defineNumber = (nameSpace: t, identifier: string, value: float): t => | ||||||
|   nameSpace->define(identifier, IEvNumber(value)) |   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 => | let defineModule = (nameSpace: t, identifier: string, value: t): t => | ||||||
|   nameSpace->define(identifier, toExpressionValue(value)) |   nameSpace->define(identifier, toExpressionValue(value)) | ||||||
| 
 | 
 | ||||||
| let defineFFI = (nameSpace: t, identifier: string, value: ExpressionT.ffiFn): t => | let defineFunction = (nameSpace: t, identifier: string, value: ExpressionT.optionFfiFn): t => { | ||||||
|   nameSpace->define(identifier, value->eLambdaFFIValue) |   nameSpace->define(identifier, convertOptionToFfiFn(identifier, value)->eLambdaFFIValue) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | let emptyStdLib: t = emptyModule->defineBool("stdlib", true) | ||||||
|  |  | ||||||
|  | @ -1,25 +1,11 @@ | ||||||
| module ExpressionBuilder = Reducer_Expression_ExpressionBuilder | module ExpressionBuilder = Reducer_Expression_ExpressionBuilder | ||||||
| module ExpressionT = Reducer_Expression_T | module ExpressionT = Reducer_Expression_T | ||||||
| open Reducer_ErrorValue | // open ReducerInterface_InternalExpressionValue | ||||||
| open ReducerInterface_InternalExpressionValue |  | ||||||
| 
 | 
 | ||||||
| type expression = ExpressionT.expression | 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 => { | let defaultCaseFFI = (functionName: string): expression => { | ||||||
|   ExpressionBuilder.eLambdaFFI(defaultCaseFFIFn(functionName)) |   ExpressionBuilder.eLambdaFFI(Reducer_Module.functionNotFoundErrorFFIFn(functionName)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| let addGuard = ( | let addGuard = ( | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user