aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2023-01-14 17:38:24 +0530
committerAkshay Nair <phenax5@gmail.com>2023-01-14 17:39:24 +0530
commitf31caa5baad20553cac0330ae9ff279b8f88f340 (patch)
tree52c7e6e0b2acdece8f013b64e3dbb2b70f5b14f5
parentaee5d90a2397e68a753ab05e20566d0a23604931 (diff)
downloadts-types-lang-f31caa5baad20553cac0330ae9ff279b8f88f340.tar.gz
ts-types-lang-f31caa5baad20553cac0330ae9ff279b8f88f340.zip
feat: adds test cases for do and seq + fixes behavior with empty results
-rw-r--r--src/context.ts4
-rw-r--r--src/eval-env/builtins.ts14
-rw-r--r--src/util.ts7
-rw-r--r--stdlib/effect.ts2
-rw-r--r--tests/builtins.spec.ts263
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']]>
+ >
+ ]
+ >
+ ]
+>