diff options
| -rw-r--r-- | src/context.ts | 4 | ||||
| -rw-r--r-- | src/eval-env/builtins.ts | 14 | ||||
| -rw-r--r-- | src/util.ts | 7 | ||||
| -rw-r--r-- | stdlib/effect.ts | 2 | ||||
| -rw-r--r-- | tests/builtins.spec.ts | 263 |
5 files changed, 176 insertions, 114 deletions
diff --git a/src/context.ts b/src/context.ts index fab6653..f70a17d 100644 --- a/src/context.ts +++ b/src/context.ts @@ -39,7 +39,9 @@ export const createContext = (options: CtxOptions): Ctx => { ) const getResultExpr = (resultKey?: string) => - `(${RESULT_TYPE_NAME}[${JSON.stringify(resultKey)})` + resultKey + ? `((${RESULT_TYPE_NAME}[${JSON.stringify(resultKey)})['output'])` + : 'undefined' const addResult = (name: string, ty: string): Node | undefined => resultTypeNode diff --git a/src/eval-env/builtins.ts b/src/eval-env/builtins.ts index c5b0c82..d90bc2e 100644 --- a/src/eval-env/builtins.ts +++ b/src/eval-env/builtins.ts @@ -49,6 +49,8 @@ export default (ctx: Ctx, args: Type[]) => ({ return [resultKey] }, + Noop: async () => [], + Print: async () => { console.log(...args.map(ctx.typeToString)) return [] @@ -77,7 +79,7 @@ export default (ctx: Ctx, args: Type[]) => ({ const resultType = applyFunc( ctx, chainToKind, - resultKey ? `(${ctx.getResultExpr(resultKey)})['output']` : 'never' + resultKey ? `${ctx.getResultExpr(resultKey)}` : 'never' ) return ctx.evaluateType(ctx, resultType) }), @@ -102,7 +104,7 @@ export default (ctx: Ctx, args: Type[]) => ({ return [value] }, - Try: async () => { + Try: ctx.withScope(async () => { const [effTyp, catchK] = args try { @@ -113,7 +115,7 @@ export default (ctx: Ctx, args: Type[]) => ({ const resultType = applyFunc(ctx, catchK, error) return ctx.evaluateType(ctx, resultType) } - }, + }), Throw: async () => { throw args[0] && ctx.getTypeValue(args[0]) @@ -134,8 +136,8 @@ export default (ctx: Ctx, args: Type[]) => ({ effectTyps?.getTupleElements() ?? [] ) const [resultKey, _] = ctx.createResult(`[ - ${effectResults.map(ctx.getResultExpr).join(', ')} - ]`) + ${effectResults.map(ctx.getResultExpr).join(', ')} + ]`) return [resultKey] }), @@ -148,7 +150,7 @@ export default (ctx: Ctx, args: Type[]) => ({ // TODO: Use last type's result instead of last result key const lastResKey = effectResults[effectResults.length - 1] const [resultKey, _] = ctx.createResult( - `(${ctx.getResultExpr(lastResKey)})['output']` + `${ctx.getResultExpr(lastResKey)}` ) return [resultKey] }), diff --git a/src/util.ts b/src/util.ts index a486294..b7d4efe 100644 --- a/src/util.ts +++ b/src/util.ts @@ -7,9 +7,10 @@ export const match = <K extends string, R>( ) => (k && pattern[k] ? pattern[k]() : pattern._()) export const evalList = async (ctx: Ctx, effectTyps: Type[]) => { - const effectResults: string[] = [] + const effectResults: (string | undefined)[] = [] for (const item of effectTyps ?? []) { - effectResults.push(...(await ctx.evaluateType(ctx, item))) + const [resultKey] = await ctx.evaluateType(ctx, item) + effectResults.push(resultKey ? resultKey : undefined) } return effectResults } @@ -69,8 +70,6 @@ export const applyFunc = ( return undefined })() - // TODO: Cleanup unwanted result node values - if (!resultType) { throw new Error('Couldnt get result for function application') } diff --git a/stdlib/effect.ts b/stdlib/effect.ts index d53b6b6..9b19197 100644 --- a/stdlib/effect.ts +++ b/stdlib/effect.ts @@ -22,3 +22,5 @@ export interface Seq<_Effs extends Effect[]> extends Effect {} export interface Do<_Effs extends Effect[]> extends Effect {} export interface Pure<V> extends Effect<V> {} + +export interface Noop extends Effect {} diff --git a/tests/builtins.spec.ts b/tests/builtins.spec.ts index 31e2cc0..1c833c0 100644 --- a/tests/builtins.spec.ts +++ b/tests/builtins.spec.ts @@ -1,6 +1,15 @@ -import { Bind, BindTo, Do, Effect, Label, Pure } from '../stdlib/effect' +import { + Bind, + BindTo, + Do, + Effect, + Label, + Noop, + Pure, + Seq, +} from '../stdlib/effect' import { Throw, Try } from '../stdlib/exception' -import { PutStringLn } from '../stdlib/stdio' +import { Print, PutStringLn } from '../stdlib/stdio' import { DefineEffect, JsExpr, SetEvalEnvironment } from '../stdlib/sys' import { Test, AssertEqualsK, AssertEquals } from '../stdlib/test' @@ -14,121 +23,169 @@ export type main = [ PutStringLn<'=== Running tests ==='>, PutStringLn<'=====================\n\n'>, - Do< - [ - PutStringLn<'Bind & BindTo'>, + testDo, + testSeq, + testBind, + testException, + testFFI, - Test< - 'should bind value to function and kind', - [ - Bind< - Pure<[1, 2, 3]>, - <val extends number[]>() => AssertEquals<val, [1, 2, 3]> - >, + PutStringLn<''> +] + +type testSeq = Do< + [ + PutStringLn<'Seq'>, + + Test< + 'should run a sequence of effects and all results', + [ + BindTo<'result', Seq<[Pure<1>, Pure<2>, Pure<3>, Pure<4>]>>, + + Bind<Label<'result'>, AssertEqualsK<[1, 2, 3, 4]>> + ] + >, + + Test< + 'should produce undefined for effects with no result', + [ + BindTo<'result', Seq<[Pure<1>, Noop, Pure<3>, Noop]>>, + + Bind<Label<'result'>, AssertEqualsK<[1, undefined, 3, undefined]>> + ] + > + ] +> + +type testDo = Do< + [ + PutStringLn<'Do'>, - Bind<Pure<[1, 2, 3]>, AssertEqualsK<[1, 2, 3]>> - ] - >, + Test< + 'should run a sequence of effects and return the last effect', + [ + BindTo<'result', Do<[Pure<1>, Pure<2>, Pure<3>, Pure<4>]>>, - Test< - 'should bind label correctly', - [ - BindTo<'value', Pure<{ a: 'b'; c: { d: 1 } }>>, + Bind<Label<'result'>, AssertEqualsK<4>> + ] + >, - Bind<Label<'value'>, AssertEqualsK<{ a: 'b'; c: { d: 1 } }>> - ] - >, + Test< + 'should return undefined if last effect doesnt produce a result', + [ + BindTo<'result', Do<[Pure<1>, Noop, Pure<3>, Noop]>>, - Test< - 'should bind only inside Do scope', - [ - Do< - [ - BindTo<'value', Pure<'some value'>>, - Bind<Label<'value'>, AssertEqualsK<'some value'>> - ] - >, + Bind<Label<'result'>, AssertEqualsK<undefined>> + ] + > + ] +> - Bind< - Try<Label<'value'>, <_>() => Pure<'none'>>, - AssertEqualsK<'none'> - > - ] - >, +type testBind = Do< + [ + PutStringLn<'Bind & BindTo'>, - Test< - 'should bind only inside Bind scope', - [ - Bind< + Test< + 'should bind value to function and kind', + [ + Bind< + Pure<[1, 2, 3]>, + <val extends number[]>() => AssertEquals<val, [1, 2, 3]> + >, + + Bind<Pure<[1, 2, 3]>, AssertEqualsK<[1, 2, 3]>> + ] + >, + + Test< + 'should bind label correctly', + [ + BindTo<'value', Pure<{ a: 'b'; c: { d: 1 } }>>, + + Bind<Label<'value'>, AssertEqualsK<{ a: 'b'; c: { d: 1 } }>> + ] + >, + + Test< + 'should bind only inside Do scope', + [ + Do< + [ BindTo<'value', Pure<'some value'>>, - <_>() => Bind<Label<'value'>, AssertEqualsK<'some value'>> - >, + Bind<Label<'value'>, AssertEqualsK<'some value'>> + ] + >, - Bind< - Try<Label<'value'>, <_>() => Pure<'none'>>, - AssertEqualsK<'none'> - > - ] - > - ] - >, + Bind<Try<Label<'value'>, <_>() => Pure<'none'>>, AssertEqualsK<'none'>> + ] + >, - Do< - [ - PutStringLn<'Try/Throw'>, + Test< + 'should bind only inside Bind scope', + [ + Bind< + BindTo<'value', Pure<'some value'>>, + <_>() => Bind<Label<'value'>, AssertEqualsK<'some value'>> + >, - Test< - 'should return the result of effect', - [Bind<Try<Pure<20>, <_>() => Pure<0>>, AssertEqualsK<20>>] - >, + Bind<Try<Label<'value'>, <_>() => Pure<'none'>>, AssertEqualsK<'none'>> + ] + > + ] +> - Test< - 'should return the result of error handler', - [ - Bind< - Try<Do<[Throw<'wow'>, Pure<20>]>, <_>() => Pure<0>>, - AssertEqualsK<0> - >, +type testException = Do< + [ + PutStringLn<'Try/Throw'>, - Bind< - Try<Do<[Throw<'wow'>, Pure<20>]>, <e>() => Pure<e>>, - AssertEqualsK<'wow'> - > - ] - > - ] - >, + Test< + 'should return the result of effect', + [Bind<Try<Pure<20>, <_>() => Pure<0>>, AssertEqualsK<20>>] + >, - Do< - [ - PutStringLn<'FFI'>, + Test< + 'should return the result of error handler', + [ + Bind< + Try<Do<[Throw<'wow'>, Pure<20>]>, <_>() => Pure<0>>, + AssertEqualsK<0> + >, - Test< - 'should return the result of js expression', - [Bind<JsExpr<'69 * 420'>, AssertEqualsK<28980>>] - >, + Bind< + Try<Do<[Throw<'wow'>, Pure<20>]>, <e>() => Pure<e>>, + AssertEqualsK<'wow'> + > + ] + > + ] +> - Test< - 'should test custom effect', - [ - DefineEffect< - 'MyEffect', - `([a, b, c], ctx) => { - return [ - ctx.getTypeValue(a) * 2, - ctx.getTypeValue(b) + '!', - [...ctx.getTypeValue(c), 'wow'], - ] - }` - >, - Bind< - MyEffect<4, 'hey', [1, 2]>, - AssertEqualsK<[8, 'hey!', [1, 2, 'wow']]> - > - ] - > - ] - >, +type testFFI = Do< + [ + PutStringLn<'FFI'>, - PutStringLn<''> -] + Test< + 'should return the result of js expression', + [Bind<JsExpr<'69 * 420'>, AssertEqualsK<28980>>] + >, + + Test< + 'should test custom effect', + [ + DefineEffect< + 'MyEffect', + `([a, b, c], ctx) => { + return [ + ctx.getTypeValue(a) * 2, + ctx.getTypeValue(b) + '!', + [...ctx.getTypeValue(c), 'wow'], + ] + }` + >, + Bind< + MyEffect<4, 'hey', [1, 2]>, + AssertEqualsK<[8, 'hey!', [1, 2, 'wow']]> + > + ] + > + ] +> |
