aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2023-01-14 17:12:48 +0530
committerAkshay Nair <phenax5@gmail.com>2023-01-14 17:12:48 +0530
commitcd11925707c42843df195d9b2efb3c77b5de793b (patch)
tree0871b0041597096fdbf7c49416f96fa70da00e3c
parentd362ef26db894ea52c6abd34489aa9efdbc0c89b (diff)
downloadts-types-lang-cd11925707c42843df195d9b2efb3c77b5de793b.tar.gz
ts-types-lang-cd11925707c42843df195d9b2efb3c77b5de793b.zip
feat: adds cleanup of result nodes
-rw-r--r--src/context.ts10
-rw-r--r--src/eval-env/builtins.ts71
-rw-r--r--src/eval.ts4
-rw-r--r--src/types.ts1
-rw-r--r--src/util.ts63
-rw-r--r--stdlib/test.ts7
-rw-r--r--tests/builtins.spec.ts138
7 files changed, 152 insertions, 142 deletions
diff --git a/src/context.ts b/src/context.ts
index fe33731..fab6653 100644
--- a/src/context.ts
+++ b/src/context.ts
@@ -56,6 +56,15 @@ export const createContext = (options: CtxOptions): Ctx => {
return [resultKey, node]
}
+ const removeResult = (key?: string) => {
+ if (!key) return
+ resultTypeNode
+ ?.asKind(SyntaxKind.TypeAliasDeclaration)
+ ?.getChildAtIndexIfKind(3, SyntaxKind.TypeLiteral)
+ ?.getProperty(key)
+ ?.remove()
+ }
+
const customEffects: Record<string, (args: Type[], ctx: Ctx) => any> = {}
const getTypeValue = (ty: Type | undefined): any => {
@@ -97,6 +106,7 @@ export const createContext = (options: CtxOptions): Ctx => {
createResult,
getResultExpr,
+ removeResult,
printResultNode: () => console.log(resultTypeNode?.print()),
addCustomEffect: (name, expr) => {
diff --git a/src/eval-env/builtins.ts b/src/eval-env/builtins.ts
index 35f8485..c5b0c82 100644
--- a/src/eval-env/builtins.ts
+++ b/src/eval-env/builtins.ts
@@ -1,63 +1,6 @@
-import { SyntaxKind, Type } from 'ts-morph'
+import { Type } from 'ts-morph'
import { Ctx } from '../types'
-import { evalList } from '../util'
-
-const applyFunc = (ctx: Ctx, fn: Type | undefined, val: string): Type => {
- const resultType = (() => {
- const baseTypes = fn
- ?.getBaseTypes()
- .flatMap((t) => t.getSymbol()?.getName() ?? [])
-
- if (!!fn?.getProperty('return') || baseTypes?.includes('Kind1')) {
- const [_key, resultNode] = ctx.createResult(
- `(${ctx.typeToString(fn)} & { input: ${val} })['return']`
- )
- return resultNode
- ?.getType()
- .getProperty('output')
- ?.getTypeAtLocation(resultNode)
- } else {
- const [_key, resultNode] = ctx.createResult(
- `ReturnType<${ctx.typeToString(fn)}>`
- )
-
- const resValueNode = resultNode
- ?.asKind(SyntaxKind.PropertySignature)
- ?.getChildAtIndexIfKind(2, SyntaxKind.TypeLiteral)
- ?.getProperty('output')
- ?.getChildAtIndexIfKind(2, SyntaxKind.TypeReference)
-
- const functionNode = resValueNode
- ?.getChildAtIndexIfKind(1, SyntaxKind.SyntaxList)
- ?.getFirstChildIfKind(SyntaxKind.FunctionType)
-
- if (functionNode) {
- const typeParameters = functionNode.getTypeParameters() ?? []
-
- if (typeParameters.length > 0) {
- const constraint = typeParameters[0]?.getConstraint()
- if (constraint) {
- constraint?.replaceWithText(val)
- } else {
- typeParameters[0]?.setConstraint(val)
- }
- }
-
- return resValueNode?.getType()
- }
- }
-
- return undefined
- })()
-
- // TODO: Cleanup unwanted result node values
-
- if (!resultType) {
- throw new Error('Couldnt get result for function application')
- }
-
- return resultType
-}
+import { applyFunc, evalList } from '../util'
export default (ctx: Ctx, args: Type[]) => ({
SetEvalEnvironment: async () => {
@@ -129,14 +72,12 @@ export default (ctx: Ctx, args: Type[]) => ({
Bind: ctx.withScope(async () => {
const [inputTyp, chainToKind] = args
- const [resultKey] = inputTyp ? await ctx.evaluateType(ctx, inputTyp) : []
-
- // TODO: Handle resultKey undefined case
+ let [resultKey] = inputTyp ? await ctx.evaluateType(ctx, inputTyp) : []
const resultType = applyFunc(
ctx,
chainToKind,
- `(${ctx.getResultExpr(resultKey)})['output']`
+ resultKey ? `(${ctx.getResultExpr(resultKey)})['output']` : 'never'
)
return ctx.evaluateType(ctx, resultType)
}),
@@ -186,7 +127,7 @@ export default (ctx: Ctx, args: Type[]) => ({
return [resultKey]
},
- Seq: async () => {
+ Seq: ctx.withScope(async () => {
const [effectTyps] = args
const effectResults = await evalList(
ctx,
@@ -196,7 +137,7 @@ export default (ctx: Ctx, args: Type[]) => ({
${effectResults.map(ctx.getResultExpr).join(', ')}
]`)
return [resultKey]
- },
+ }),
Do: ctx.withScope(async () => {
const [effectTyps] = args
diff --git a/src/eval.ts b/src/eval.ts
index 6eb72a1..37a8008 100644
--- a/src/eval.ts
+++ b/src/eval.ts
@@ -32,7 +32,7 @@ export const evaluateType = async (
const name = effTyp.getSymbol()?.getName()
const args = effTyp.getTypeArguments()
- // console.log('>>>>>', name)
+ //console.log('>>>>>', name)
// console.log(ctx.typeToString(effTyp))
// console.log(name, args.map(ctx.typeToString))
@@ -67,7 +67,7 @@ export const evaluateType = async (
return match(name, {
...envEffects(ctx, args),
_: async () => {
- console.log(ctx.typeToString(effTyp))
+ console.log('\n[EffectType]', ctx.typeToString(effTyp), '\n')
throw new Error(`${name} effect is not handled`)
},
})
diff --git a/src/types.ts b/src/types.ts
index 6ea282e..55d2cce 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -14,6 +14,7 @@ export interface Ctx {
getTypeValue: (ty: Type | undefined) => any
createResult: (ty: string) => [string, Node | undefined]
+ removeResult: (key?: string) => void,
getResultExpr: (key?: string) => string
printResultNode: () => void
diff --git a/src/util.ts b/src/util.ts
index f7bb20a..2746746 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -1,4 +1,4 @@
-import { Type } from 'ts-morph'
+import { SyntaxKind, Type } from 'ts-morph'
import { Ctx } from './types'
export const match = <K extends string, R>(
@@ -13,3 +13,64 @@ export const evalList = async (ctx: Ctx, effectTyps: Type[]) => {
}
return effectResults
}
+
+export const applyFunc = (ctx: Ctx, fn: Type | undefined, val: string): Type => {
+ const resultType = (() => {
+ const baseTypes = fn
+ ?.getBaseTypes()
+ .flatMap((t) => t.getSymbol()?.getName() ?? [])
+
+ if (!!fn?.getProperty('return') || baseTypes?.includes('Kind1')) {
+ const [key, resultNode] = ctx.createResult(
+ `(${ctx.typeToString(fn)} & { input: ${val} })['return']`
+ )
+ ctx.removeResult(key)
+
+ return resultNode
+ ?.getType()
+ .getProperty('output')
+ ?.getTypeAtLocation(resultNode)
+ } else {
+ const [key, resultNode] = ctx.createResult(
+ `ReturnType<${ctx.typeToString(fn)}>`
+ )
+ ctx.removeResult(key)
+
+ const resValueNode = resultNode
+ ?.asKind(SyntaxKind.PropertySignature)
+ ?.getChildAtIndexIfKind(2, SyntaxKind.TypeLiteral)
+ ?.getProperty('output')
+ ?.getChildAtIndexIfKind(2, SyntaxKind.TypeReference)
+
+ const functionNode = resValueNode
+ ?.getChildAtIndexIfKind(1, SyntaxKind.SyntaxList)
+ ?.getFirstChildIfKind(SyntaxKind.FunctionType)
+
+ if (functionNode) {
+ const typeParameters = functionNode.getTypeParameters() ?? []
+
+ if (typeParameters.length > 0) {
+ const constraint = typeParameters[0]?.getConstraint()
+ if (constraint) {
+ constraint?.replaceWithText(val)
+ } else {
+ typeParameters[0]?.setConstraint(val)
+ }
+ }
+
+ return resValueNode?.getType()
+ }
+ }
+
+ return undefined
+ })()
+
+ // TODO: Cleanup unwanted result node values
+
+ if (!resultType) {
+ throw new Error('Couldnt get result for function application')
+ }
+
+ return resultType
+}
+
diff --git a/stdlib/test.ts b/stdlib/test.ts
index a592d87..86ed6a9 100644
--- a/stdlib/test.ts
+++ b/stdlib/test.ts
@@ -15,15 +15,12 @@ export interface ShowAssertionError<_L extends unknown, _R extends unknown> exte
export type AssertEquals<Left, Right> = Try<
Assert<Equals<Left, Right>>,
- <e extends string>() => Do<[
+ <m>() => Do<[
ShowAssertionError<Left, Right>,
- Throw<e>,
+ Throw<m>,
]>
>
export interface AssertEqualsK<Right extends unknown> extends Kind1 {
return: AssertEquals<this['input'], Right>
}
-
-// TODO: export interface AssertFails?
-
diff --git a/tests/builtins.spec.ts b/tests/builtins.spec.ts
index cd4b5c4..cbac0d3 100644
--- a/tests/builtins.spec.ts
+++ b/tests/builtins.spec.ts
@@ -4,93 +4,93 @@ import { PutStringLn } from '../stdlib/stdio'
import { DefineEffect, JsExpr, SetEvalEnvironment } from '../stdlib/sys'
import { Test, AssertEqualsK, AssertEquals } from '../stdlib/test'
-type testBind = Do<[
- PutStringLn<'Bind & BindTo'>,
+interface MyEffect<_a extends number, _b extends string, _c extends unknown> extends Effect {}
- Test<'should bind value to function and kind', [
- Bind<Pure<[1,2,3]>, <val extends number[]>() =>
- AssertEquals<val, [1, 2, 3]>>,
+export type main = [
+ SetEvalEnvironment<'test.node'>,
- Bind<Pure<[1,2,3]>, AssertEqualsK<[1,2,3]>>,
- ]>,
+ PutStringLn<'====================='>,
+ PutStringLn<'=== Running tests ==='>,
+ PutStringLn<'=====================\n\n'>,
- Test<'should bind label correctly', [
- BindTo<"value", Pure<{ a: 'b', c: { d: 1 } }>>,
+ Do<[
+ PutStringLn<'Bind & BindTo'>,
- Bind<Label<"value">, AssertEqualsK<{ a: 'b', c: { d: 1 } }>>,
- ]>,
+ Test<'should bind value to function and kind', [
+ Bind<Pure<[1,2,3]>, <val extends number[]>() =>
+ AssertEquals<val, [1, 2, 3]>>,
- Test<'should bind only inside Do scope', [
- Do<[
- BindTo<"value", Pure<"some value">>,
- Bind<Label<"value">, AssertEqualsK<"some value">>,
+ Bind<Pure<[1,2,3]>, AssertEqualsK<[1,2,3]>>,
]>,
- Bind<
- Try<Label<"value">, <_>() => Pure<"none">>,
- AssertEqualsK<"none">
- >,
- ]>,
+ Test<'should bind label correctly', [
+ BindTo<"value", Pure<{ a: 'b', c: { d: 1 } }>>,
- Test<'should bind only inside Bind scope', [
- Bind<
- BindTo<"value", Pure<"some value">>,
- <_>() => Bind<Label<"value">, AssertEqualsK<"some value">>
- >,
+ Bind<Label<"value">, AssertEqualsK<{ a: 'b', c: { d: 1 } }>>,
+ ]>,
- Bind<
- Try<Label<"value">, <_>() => Pure<"none">>,
- AssertEqualsK<"none">
- >,
- ]>,
-]>
+ Test<'should bind only inside Do scope', [
+ Do<[
+ BindTo<"value", Pure<"some value">>,
+ Bind<Label<"value">, AssertEqualsK<"some value">>,
+ ]>,
-type testExcpt = Do<[
- PutStringLn<'Try/Throw'>,
+ Bind<
+ Try<Label<"value">, <_>() => Pure<"none">>,
+ AssertEqualsK<"none">
+ >,
+ ]>,
+
+ 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>>,
+ 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>>,
+ ]>,
-interface MyEffect<_a extends number, _b extends string, _c extends unknown> extends Effect {}
-type testFFI = 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'],
- ]>>,
- ]>,
-]>
+ Do<[
+ PutStringLn<'FFI'>,
-export type main = [
- SetEvalEnvironment<'test.node'>,
+ Test<'should return the result of js expression', [
+ Bind<JsExpr<'69 * 420'>, AssertEqualsK<28980>>,
+ ]>,
- PutStringLn<'====================='>,
- PutStringLn<'=== Running tests ==='>,
- PutStringLn<'=====================\n\n'>,
- testBind,
- testExcpt,
- testFFI,
+ 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'],
+ ]>>,
+ ]>,
+ ]>,
+
+ PutStringLn<"">,
]