├── LICENSE ├── README.md ├── package.json ├── tsconfig.json └── types.ts /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 devNegative-asm 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hi, this is TypeLisp. 2 | 3 | I was looking at typelang, and thought that was cool, but I also thought it needed more turing completeness, so I made typelisp. 4 | 5 | ## Installation: 6 | 7 | Linux & mac: 8 | ``` 9 | git clone https://github.com/devNegative-asm/TypeLisp.git 10 | cd TypeLisp 11 | npm i 12 | npm run test 13 | ``` 14 | 15 | Windows: 16 | ``` 17 | git clone https://github.com/devNegative-asm/TypeLisp.git 18 | cd TypeLisp 19 | npm i 20 | open up node_modules/typescript/lib/tsc.js in notepad, and replace line 6444 with `Type_instantiation_is_excessively_deep_and_possibly_infinite:diag(2589,3,\"\",\"Tsc pretends to be too good for this code\"),` 21 | npx tsc 22 | ``` 23 | 24 | The install does mess with the tsc executable a bit, but that's because tsc lies about what it can and can't type check. 25 | 26 | ## Running typelisp: 27 | 28 | create a variable with type `Eval` where code is a compiletime constant string. assign it to something it isn't, and typescript will run the calculation and tell you what it is. 29 | 30 | If you're familiar with lisps, you might recognize some of the features. 31 | 32 | ## Features 33 | 34 | 1. lists created with `cons` and `[]`. 35 | 2. Signed BigInts 36 | 3. lambdas 37 | 4. currying 38 | 5. error handling 39 | 6. string operations (`explode` and `implode`) for converting to lists of single-char strings 40 | 7. surprisingly robust == and != comparison 41 | 8. `<=` `>=` `<` and `>` all work on integers 42 | 9. `#` operator converts back and forth between strings and ints 43 | 10. recursion 44 | 1. recursion 45 | 1. recursion 46 | 47 | ## Examples 48 | 49 | read types.ts -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typelisp", 3 | "version": "1.0.0", 4 | "main": "types.js", 5 | "scripts": { 6 | "test": "sed -i '6444s/.*/Type_instantiation_is_excessively_deep_and_possibly_infinite:diag(2589,3,\"\",\"Tsc pretends to be too good for this code\"),/' node_modules/typescript/lib/tsc.js; npx tsc" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/devNegative-asm/TypeLisp.git" 11 | }, 12 | "author": "devnegative-asm", 13 | "license": "MIT", 14 | "bugs": { 15 | "url": "https://github.com/devNegative-asm/TypeLisp/issues" 16 | }, 17 | "homepage": "https://github.com/devNegative-asm/TypeLisp#readme", 18 | "description": "", 19 | "dependencies": { 20 | "typescript": "5.5.4" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 4 | "module": "commonjs", /* Specify what module code is generated. */ 5 | "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 6 | "noEmit": true, /* Disable emitting files from a compilation. */ 7 | "strict": true, /* Enable all strict type-checking options. */ 8 | "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 9 | "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 10 | "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 11 | "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 12 | "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 13 | "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 14 | "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 15 | "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 16 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /types.ts: -------------------------------------------------------------------------------- 1 | 2 | //numbers are represented in base-2 using an array of 1s and 0s. 3 | //0 is [], 1 is [1], 2 is [1,0] 4 | //signed numbers don't use 2's complement, but instead use a sign flag. 5 | 6 | type Bit = 0|1 7 | type UInt = Bit[] 8 | type Compl = T extends 0 ? 1 : 0 9 | type Not = T extends true ? false : true 10 | type Xor = T extends true ? Not : U 11 | type And = T extends true ? U : false 12 | type Or = T extends true ? true : U 13 | type StringToUInt = N extends "" ? [] 14 | : N extends `${infer U}0` ? UMul,Ten> 15 | : N extends `${infer U}1` ? UAdd<[1],UMul,Ten>> 16 | : N extends `${infer U}2` ? UAdd<[1, 0],UMul,Ten>> 17 | : N extends `${infer U}3` ? UAdd<[1, 1],UMul,Ten>> 18 | : N extends `${infer U}4` ? UAdd<[1, 0, 0],UMul,Ten>> 19 | : N extends `${infer U}5` ? UAdd<[1, 0, 1],UMul,Ten>> 20 | : N extends `${infer U}6` ? UAdd<[1, 1, 0],UMul,Ten>> 21 | : N extends `${infer U}7` ? UAdd<[1, 1, 1],UMul,Ten>> 22 | : N extends `${infer U}8` ? UAdd<[1, 0, 0, 0],UMul,Ten>> 23 | : N extends `${infer U}9` ? UAdd<[1, 0, 0, 1],UMul,Ten>> 24 | : never 25 | type N = StringToUInt<`${N}`> 26 | type LowBit> = T extends [] ? 0 : T extends [any] ? 1 : T extends [any, ...infer Rest extends Array] ? LowBit extends 1 ? 0 : 1 : never 27 | type HalfArray> = T extends [] ? [] : T extends [infer B, infer _, ...infer Rest] ? [B, ...HalfArray] : never 28 | type Len> = T extends [] ? [] : LowBit extends 0 ? [...Len>, 0] : T extends [any, ...infer rest extends Array] ? [...Len>, 1] : never 29 | type UInc = T extends [] ? [1] : T extends [0] ? [1] : T extends [...infer U, 0] ? [...U, 1] : T extends [...infer U extends UInt, 1] ? [...UInc, 0] : never 30 | type UAdd = A extends [] ? B : B extends [] ? A : 31 | A extends [...infer UA extends UInt, 0] ? B extends [...infer UB extends UInt, 0] ? [...UAdd, 0] : 32 | B extends [...infer UB extends UInt, 1] ? [...UAdd, 1] : never : 33 | A extends [...infer UA extends UInt, 1] ? B extends [...infer UB extends UInt, 0] ? [...UAdd, 1] : 34 | B extends [...infer UB extends UInt, 1] ? [...UInc>, 0] : never : never 35 | 36 | type UMul = A extends [] ? [] : B extends [] ? [] : 37 | A extends [...infer UA extends UInt, 0] ? [...UMul, 0] : 38 | A extends [...infer UA extends UInt, 1] ? UAdd, 0]> : never 39 | type Mul = INorm<{ 40 | neg: Xor, 41 | mag: UMul 42 | }> 43 | type Div = INorm<{ 44 | neg: Xor, 45 | mag: UDiv 46 | }> 47 | type LessThanOrEqual = false extends Sub["neg"] ? true : false 48 | type LessThan = true extends Sub["neg"] ? true : false 49 | 50 | type UDec = N extends [] ? never : N extends [1] ? [] : N extends [...infer U extends UInt,1] ? [...U, 0] : N extends [...infer U extends UInt, 0] ? [...UDec, 1] : never 51 | type TwoExp = N extends [] ? [1] : [...TwoExp>, 0] 52 | type Equal = B extends A ? A extends B ? true : false : false 53 | type NEqual = B extends A ? A extends B ? false : true : true 54 | type USub = B extends [] ? A 55 | : B extends A ? [] 56 | : B extends [...infer HB extends UInt, 0] 57 | ? A extends [...infer HA extends UInt, infer LA extends Bit] ? [...USub, LA] : never 58 | : B extends [...infer HB extends UInt, 1] 59 | ? A extends [...infer HA extends UInt, 1] ? [...USub, 0] 60 | : A extends [...infer HA extends UInt, 0] ? [...USub, HB>, 1] : never 61 | : never 62 | //cut leading zeroes 63 | type UNorm = T extends [0, ...infer LT extends UInt] ? UNorm : T 64 | type ULessThanOrEqual = true extends Equal ? true 65 | : A extends N<0> ? true 66 | : B extends N<0> ? false 67 | : A extends N<1> ? true 68 | : B extends N<1> ? false 69 | : A extends N<2> ? true 70 | : B extends N<2> ? false 71 | : true extends Equal,Len> 72 | ? A extends [1, ...infer LA extends UInt] ? B extends [1, ...infer LB extends UInt] ? ULessThanOrEqual,UNorm> : never 73 | : never 74 | : ULessThanOrEqual,Len> 75 | type ULessThan = true extends ULessThanOrEqual ? false extends Equal ? true : false : false 76 | type UDiv = true extends ULessThan 77 | ? [] 78 | : true extends ULessThan ? [1] 79 | : UDiv extends infer U extends UInt 80 | ? true extends ULessThanOrEqual, A> 81 | ? [...U, 1] 82 | : [...U, 0] 83 | : never 84 | type UMod = USub,D>> 85 | 86 | type Ten = [1,0,1,0] 87 | type UintToString = Num extends N<0> 88 | ? "0" 89 | : Num extends N<1> ? "1" 90 | : Num extends N<2> ? "2" 91 | : Num extends N<3> ? "3" 92 | : Num extends N<4> ? "4" 93 | : Num extends N<5> ? "5" 94 | : Num extends N<6> ? "6" 95 | : Num extends N<7> ? "7" 96 | : Num extends N<8> ? "8" 97 | : Num extends N<9> ? "9" 98 | : UintToString> extends infer Upper extends string ? 99 | UintToString> extends infer Lower extends string ? `${Upper}${Lower}` : never 100 | : never 101 | 102 | type Int = {neg: boolean, mag:UInt} 103 | type List = { 104 | items: T 105 | } 106 | type Str = { 107 | type: "string", 108 | value: T 109 | } 110 | //Fix signed arithmetic by making -0 into +0 111 | type INorm = {mag: [], neg: true} extends I ? {mag: [], neg: false} : I 112 | type IntToString = I extends {neg: infer Sign, mag: infer M extends UInt} ? 113 | UintToString extends infer Magnitude extends string ? 114 | Sign extends true ? `-${Magnitude}` : `${Magnitude}` 115 | : never 116 | : never 117 | type StringToInt = T extends `-${infer Mag extends string}` 118 | ? INorm<{mag: StringToUInt, neg: true}> 119 | : StringToUInt extends infer Mag extends UInt ? {mag: Mag, neg: false} 120 | : never 121 | type I = StringToInt<`${Num}`> 122 | 123 | type UMax = true extends ULessThanOrEqual ? B : A 124 | type UMin = true extends ULessThanOrEqual ? A : B 125 | 126 | type UMaxInd = true extends ULessThanOrEqual ? 1 : 0 127 | type UMinInd = true extends ULessThanOrEqual ? 0 : 1 128 | 129 | type Add = 130 | [A,B] extends [{neg: infer SA extends boolean, mag: infer MA extends UInt}, {neg: infer SB extends boolean, mag: infer MB extends UInt}] 131 | ? SA extends SB ? INorm<{neg: SA, mag: UAdd}> 132 | : INorm<{neg: [A,B][UMaxInd]["neg"], mag: USub, UMin>}> 133 | : never 134 | 135 | type Neg = T extends {neg: infer Sign extends boolean, mag: infer Mag extends UInt} ? INorm<{neg: Not, mag: Mag}> : never 136 | type Sub = Add> 137 | type Push> = [Elem, ...Arr] 138 | 139 | //might use for global variables eventually 140 | type Bindings = {[key:string] : any}[] 141 | 142 | type Token = {TType: T, value: U} 143 | type TIdent = Token<"Ident",Name> 144 | type TLitInt = Token<"LitInt",Val> 145 | type TLambda = Token<"lambda","lambda"> 146 | type TEmptyList = Token<"[]","[]"> 147 | type TTry = Token<"try","try"> 148 | type TIf = Token<"if","if"> 149 | type TTrue = Token<"true","true"> 150 | type TFalse = Token<"false","false"> 151 | type TOpenParen = Token<"(","("> 152 | type TCloseParen = Token<")",")"> 153 | type TPlus = Token<"+","+"> 154 | type TMinus = Token<"-","-"> 155 | type TTimes = Token<"*","*"> 156 | type TDiv = Token<"/","/"> 157 | type TLTE = Token<"<=","<="> 158 | type TLT = Token<"<","<"> 159 | type TGTE = Token<">=",">="> 160 | type TGT = Token<">",">"> 161 | type TEQ = Token<"==","=="> 162 | type TNE = Token<"!=","!="> 163 | type TNot = Token<"~","~"> 164 | type TCond = Token<"cond","cond"> 165 | type TCons = Token<"cons","cons"> 166 | type THead = Token<"head","head"> 167 | type TTail = Token<"tail","tail"> 168 | type TApply = Token<"apply","apply"> 169 | type TNum = Token<"#","#"> 170 | type TLen = Token<"len","len"> 171 | type TExplode = Token<"explode","explode"> 172 | type TImplode = Token<"implode","implode"> 173 | type TStringLit = Token<"string",Val> 174 | type TCurry = Token<"curry","curry"> 175 | type TInvalid = Token<"Invalid",""> 176 | 177 | type TokenizeString = T extends `"${infer rest extends string}` ? [TStringLit, ...Tokenize] 178 | //escape sequences 179 | : T extends `\\"${infer rest extends string}` ? TokenizeString 180 | : T extends `\\n${infer rest extends string}` ? TokenizeString 181 | : T extends `\\r${infer rest extends string}` ? TokenizeString 182 | : T extends `\\t${infer rest extends string}` ? TokenizeString 183 | : T extends `${infer char extends string}${infer rest extends string}` ? TokenizeString 184 | : [TInvalid] 185 | 186 | type Tokenize = T extends "lambda" 187 | ? [TLambda] 188 | : T extends "" ? [] 189 | : T extends "~" ? [TNot] 190 | : T extends "try" ? [TTry] 191 | : T extends "len" ? [TLen] 192 | : T extends "curry" ? [TCurry] 193 | : T extends "apply" ? [TApply] 194 | : T extends "explode" ? [TExplode] 195 | : T extends "implode" ? [TImplode] 196 | : T extends "cond" ? [TCond] 197 | : T extends "cons" ? [TCons] 198 | : T extends "head" ? [THead] 199 | : T extends "tail" ? [TTail] 200 | : T extends "if" ? [TIf] 201 | : T extends "true" ? [TTrue] 202 | : T extends "false" ? [TFalse] 203 | : T extends "[]" ? [TEmptyList] 204 | : T extends "#" ? [TNum] 205 | : T extends "*" ? [TTimes] 206 | : T extends "/" ? [TDiv] 207 | : T extends "+" ? [TPlus] 208 | : T extends "-" ? [TMinus] 209 | : T extends "<" ? [TLT] 210 | : T extends "<=" ? [TLTE] 211 | : T extends ">" ? [TGT] 212 | : T extends ">=" ? [TGTE] 213 | : T extends "==" ? [TEQ] 214 | : T extends "!=" ? [TNE] 215 | : T extends `"${infer data extends string}` ? [...TokenizeString] 216 | : T extends `(${infer rest extends string}` ? [TOpenParen, ...Tokenize] 217 | : T extends `)${infer rest extends string}` ? [TCloseParen, ...Tokenize] 218 | : T extends `${infer pk extends string})${infer rest extends string}` ? [...Tokenize, TCloseParen, ...Tokenize] 219 | : T extends `${infer t1 extends string} ${infer rest extends string}` ? [...Tokenize, ...Tokenize] 220 | : T extends `-${infer _}` ? [TLitInt] 221 | : T extends `0${infer _}` ? [TLitInt] 222 | : T extends `1${infer _}` ? [TLitInt] 223 | : T extends `2${infer _}` ? [TLitInt] 224 | : T extends `3${infer _}` ? [TLitInt] 225 | : T extends `4${infer _}` ? [TLitInt] 226 | : T extends `5${infer _}` ? [TLitInt] 227 | : T extends `6${infer _}` ? [TLitInt] 228 | : T extends `7${infer _}` ? [TLitInt] 229 | : T extends `8${infer _}` ? [TLitInt] 230 | : T extends `9${infer _}` ? [TLitInt] 231 | : [TIdent] 232 | 233 | type SubSelect[], Depth extends UInt> = 234 | Depth extends N<0> ? [[],T] 235 | : [Depth, T] extends [N<1>, [TCloseParen, ...infer rest extends Token[]]] ? [[], rest] 236 | : T extends [TOpenParen, ...infer rest extends Token[]] ? SubSelect> extends infer SubSq extends [Token[], Token[]] ? [[TOpenParen, ...SubSq[0]], SubSq[1]] : never 237 | : T extends [TCloseParen, ...infer rest extends Token[]] ? SubSelect> extends infer SubSq extends [Token[], Token[]] ? [[TCloseParen, ...SubSq[0]], SubSq[1]] : never 238 | : T extends [infer First extends Token, ...infer rest extends Token[]] ? [[First, ...SubSelect[0]], SubSelect[1]] 239 | : never 240 | 241 | type Value = true|false|Int|Lambda|Str|List|{error: any, errorType: any} 242 | type SyntaxTree = Value|Token|((SyntaxTree|Token)[]) 243 | type Parse[]> = 244 | T extends [TOpenParen, ...infer rest extends Token[]] ? 245 | SubSelect> extends infer sub extends [Token[],Token[]] ? [Parse, ...Parse] 246 | : never 247 | : T extends [infer F extends Token, ...infer rest extends Token[]] ? [F, ...Parse] 248 | : T extends [] ? [] 249 | : never 250 | 251 | type EvalCond = 252 | Trees extends [] ? undefined 253 | : Trees extends [[infer Condition extends SyntaxTree, infer Value extends SyntaxTree], ...infer rest extends [SyntaxTree, SyntaxTree][]] ? 254 | true extends EvalTree ? EvalTree 255 | : EvalCond 256 | : {errorType: "cond", error: Trees} 257 | 258 | type Lambda = {head: Head, body:Body} 259 | 260 | //zips together one array of keys, and one array of values, stopping when one runs out 261 | type Zip = 262 | [Keys, Values] extends [[infer FKey extends string, ...infer rKeys extends string[]], [infer FVal, ...infer rVals extends any[]]] ? 263 | Zip 264 | : acc 265 | 266 | //attempts to zip keys and values, but instead of returning the dict, return the leftovers that weren't included 267 | type UnZip = 268 | [Keys, Values] extends [[any, ...infer rKeys extends any[]], [any, ...infer rVals extends any[]]] ? 269 | UnZip 270 | : [Keys, Values] 271 | 272 | // map TIdent[] -> x[] 273 | type GetNames[], acc extends string[]=[]> = 274 | Names extends [] ? acc 275 | : Names extends [TIdent, ...infer rest extends TIdent[]] ? GetNames 276 | : never 277 | 278 | type UnionOf = T extends [] ? never : T extends [infer A, ...infer rest extends any[]] ? A|UnionOf : never 279 | 280 | type ReplaceIdents = Body extends TIdent ? G extends keyof LookupMap ? LookupMap[G] : Body 281 | : Body extends [] ? [] 282 | : Body extends Value ? Body 283 | : Body extends Token ? Body 284 | : Body extends [TLambda, infer TArgs extends TIdent[], infer SubBody extends SyntaxTree] ? 285 | GetNames extends infer Names extends string[] ? [TLambda, TArgs, ReplaceIdents>>] : never 286 | : Body extends [infer Tok extends SyntaxTree, ...infer RTree extends SyntaxTree[]] ? [ReplaceIdents,...ReplaceIdents] 287 | : never 288 | 289 | type Explode[]=[]> = S extends "" ? Barr 290 | : S extends `${infer C1 extends string}${infer C2 extends string}` ? Explode]> 291 | : never 292 | 293 | type Implode[], Barr extends string=""> = S extends [] ? Barr 294 | : S extends [Str, ...infer Rest extends Str[]] ? Implode 295 | : never 296 | 297 | type EvalTreesZipNames = 298 | [Trees, Names] extends [[infer T1 extends SyntaxTree, ...infer Tres extends SyntaxTree[]], [infer S1 extends string, ...infer Strs extends string[]]] ? EvalTreesZipNames}> 299 | : Completed 300 | 301 | type EvalTree = 302 | Tree extends TTrue ? true 303 | : Tree extends TFalse ? false 304 | : Tree extends Value ? Tree 305 | : Tree extends TEmptyList ? List<[]> 306 | : Tree extends TStringLit ? Str 307 | : Tree extends TLitInt ? StringToInt 308 | : Tree extends [TPlus, infer A extends SyntaxTree, infer B extends SyntaxTree] ? 309 | [EvalTree, EvalTree] extends infer Pair ? 310 | Pair extends Int[] ? Add 311 | : Pair extends [Str, Str] ? Str<`${S1}${S2}`> 312 | : {errorType: "+", error: Pair} 313 | : {errorType: "+", error: Tree} 314 | : Tree extends [TMinus, infer A extends SyntaxTree, infer B extends SyntaxTree] ? 315 | [EvalTree, EvalTree] extends infer Pair extends Int[] ? Sub 316 | : {errorType: "-", error: Tree} 317 | : Tree extends [TMinus, infer A extends SyntaxTree] ? 318 | EvalTree extends infer Num extends Int ? Neg 319 | : {errorType: "unary -", error: Tree} 320 | : Tree extends [TLen, infer A extends SyntaxTree] ? 321 | EvalTree extends List ? {neg: false, mag: Len} 322 | : {errorType: "len", error: Tree} 323 | : Tree extends [TNum, infer Num extends SyntaxTree] ? 324 | EvalTree extends infer Val ? 325 | Val extends Int ? Str> 326 | : Val extends Str ? StringToInt 327 | : {errorType: "#", error: Val} 328 | : {errorType: "#", error: Tree} 329 | : Tree extends [TTimes, infer A extends SyntaxTree, infer B extends SyntaxTree] ? 330 | [EvalTree, EvalTree] extends infer Pair extends Int[] ? Mul 331 | : {errorType: "*", error: Tree} 332 | : Tree extends [TDiv, infer A extends SyntaxTree, infer B extends SyntaxTree] ? 333 | [EvalTree, EvalTree] extends infer Pair extends Int[] ? Div 334 | : {errorType: "/", error: Tree} 335 | : Tree extends [TIf, infer Cond extends SyntaxTree, infer TB extends SyntaxTree, infer FB extends SyntaxTree] ? 336 | EvalTree extends true ? EvalTree : EvalTree extends false ? EvalTree : {errorType: "if", tree: Tree} 337 | : Tree extends [TLTE, infer A extends SyntaxTree, infer B extends SyntaxTree] ? 338 | [EvalTree, EvalTree] extends infer Pair extends Int[] ? LessThanOrEqual 339 | : {errorType: "<=", error: Tree} 340 | : Tree extends [TGTE, infer A extends SyntaxTree, infer B extends SyntaxTree] ? 341 | [EvalTree, EvalTree] extends infer Pair extends Int[] ? LessThanOrEqual 342 | : {errorType: ">=", error: Tree} 343 | : Tree extends [TLT, infer A extends SyntaxTree, infer B extends SyntaxTree] ? 344 | [EvalTree, EvalTree] extends infer Pair extends Int[] ? LessThan 345 | : {errorType: "<", error: Tree} 346 | : Tree extends [TGT, infer A extends SyntaxTree, infer B extends SyntaxTree] ? 347 | [EvalTree, EvalTree] extends infer Pair extends Int[] ? LessThan 348 | : {errorType: ">", error: Tree} 349 | : Tree extends [TEQ, infer A extends SyntaxTree, infer B extends SyntaxTree] ? 350 | [EvalTree, EvalTree] extends infer Pair extends [any,any]? Equal 351 | : {errorType: "==", error: Tree} 352 | : Tree extends [TNE, infer A extends SyntaxTree, infer B extends SyntaxTree] ? 353 | [EvalTree, EvalTree] extends infer Pair extends [any,any]? NEqual 354 | : {errorType: "!=", error: Tree} 355 | : Tree extends [TExplode, infer A extends SyntaxTree] ? 356 | EvalTree extends Str ? List> 357 | : {errorType: "explode", error: Tree} 358 | : Tree extends [TImplode, infer A extends SyntaxTree] ? 359 | EvalTree extends List[]> ? Str> 360 | : {errorType: "implode", error: Tree} 361 | : Tree extends [TNot, infer A extends SyntaxTree] ? 362 | EvalTree extends infer Bool extends boolean? Not 363 | : {errorType: "~", error: Tree} 364 | : Tree extends [TTry, infer ExBlock extends SyntaxTree, infer ErrBlock extends SyntaxTree] ? 365 | EvalTree extends infer Res ? 366 | Res extends {error: any, errorType: any} ? EvalTree : Res 367 | : {errorType: "try", error: ExBlock} 368 | : Tree extends [THead, infer Ls extends SyntaxTree] ? EvalTree extends List<[infer Head extends Value, ...Value[]]> ? Head : {errorType: "head", error: Tree} 369 | : Tree extends [TTail, infer Ls extends SyntaxTree] ? EvalTree extends List<[Value, ...infer Tail extends Value[]]> ? List : {errorType: "tail", error: Tree} 370 | : Tree extends [TCons, infer V extends SyntaxTree, infer Ls extends SyntaxTree] ? EvalTree extends List<[...infer Elems extends Value[]]> ? List<[EvalTree, ...Elems]> : {errorType: "cons", error: Tree} 371 | : Tree extends [TCond, ...infer CondList extends SyntaxTree[]] ? EvalCond 372 | : Tree extends [TCurry, infer Lamb extends SyntaxTree, ...infer Vals extends SyntaxTree[]] ? 373 | EvalTree extends Lambda[], infer Body extends SyntaxTree> ? 374 | Lambda[0], ReplaceIdents>>> 375 | : {errorType: "curry", error:EvalTree} 376 | : Tree extends [TApply, infer Lamb extends SyntaxTree, infer ls extends SyntaxTree] ? 377 | [EvalTree, EvalTree] extends [infer Lmb extends Lambda, List] ? 378 | EvalTree<[Lmb, ...Arguments]> 379 | : {errorType: "apply", error: Tree} 380 | : Tree extends [TLambda, infer Argnames extends TIdent[], infer Body extends SyntaxTree] ? Lambda 381 | : Tree extends [Lambda[], infer Body extends SyntaxTree>, ...infer Args extends SyntaxTree[]] ? 382 | EvalTree>>> 383 | : Tree extends [infer Lamb extends SyntaxTree, ...infer Arguments extends SyntaxTree[]] ? EvalTree extends infer L extends Lambda ? EvalTree<[L, ...Arguments]> : {errorType: "function call", error: Tree} 384 | : {errorType: "ukn", error: Tree} 385 | 386 | type Displays = T extends [] ? [] 387 | : T extends [infer A, ...infer B extends any[]] ? [Display, ...Displays] 388 | : [{errorType: "display error"}] 389 | 390 | type Display = T extends Int ? IntToString extends `${infer N extends number}` ? N : {errorType: "parse int", error:T} 391 | : T extends Str ? R 392 | : T extends Lambda[], infer Body> ? [Display, "->", Display] 393 | : T extends [...infer stuff extends any[]] ? Displays 394 | : T extends List<[...infer Elems]> ? Displays 395 | : T extends TIdent ? `var{${str}}` 396 | : T extends Token ? `op{${Val}}` 397 | : T 398 | 399 | type Eval = Parse> extends infer T ? 400 | T extends {errorType: "parse error"} ? T : T extends [infer Tree extends SyntaxTree] ? Display> : T : T 401 | 402 | //examples: 403 | const mixedLists: Eval<"((lambda (a b c d) (cons a (cons b (cons c (cons d []))))) 1 \"5\" 9 [] )"> = [1, "5", 9, []] 404 | const reverse: Eval<'(implode ((lambda (self arg) (self self arg [])) (lambda (self ls acc) (if (== ls []) acc (self self (tail ls) (cons (head ls) acc))) ) (explode "hello, world")))'> = "dlrow ,olleh" 405 | 406 | 407 | const tryCatch2: Eval<'(try (+ "4" 4) "error")'> = "error" 408 | const binaryTree: Eval<'((lambda (self arg) (self self arg)) (lambda (self depth) (if (== depth 0) [] (cons (self self (- depth 1)) (cons (self self (- depth 1)) [])))) 3)'> = [[[[],[]],[[],[]]],[[[],[]],[[],[]]]] 409 | const cond1: Eval<'(cond ((> 1 0) "case 1") ((== 3 4) "case 2") (true "default"))'> = "case 1" 410 | const condDefault: Eval<'(cond ((< 1 0) "case 1") ((== 3 4) "case 2") (true "default"))'> = "default" 411 | const lambda: Eval<'((lambda (a) (+ "hello, " a)) "world!")'> = "hello, world!" 412 | const apply: Eval<'(apply (lambda (a b c) (* (+ a b) c)) (cons 1 (cons 2 (cons 3 []))))'> = 9 413 | const curry: Eval<'((curry (lambda (a b) (+ a b)) 1) 4)'> = 5 414 | const tryCatch: Eval<'(try (+ (# "4") 4) "error")'> = 8 415 | const recursion: Eval<"((lambda (self arg) (self self arg)) (lambda (self arg) (if (== 0 arg) 1 (* arg (self self (- arg 1))))) 6)"> = 720 416 | const lists: Eval<"((lambda (self arg) (self self arg)) (lambda (self arg) (if (== arg -1) [] (cons arg (self self (- arg 1))))) 10)"> = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 417 | const deepCompare: Eval<'(== (cons "blah" (cons 4 [])) (cons "blah" (cons 4 [])))'> = true 418 | const listLength: Eval<'(len (cons 3 (cons true (cons [] []))))'> = 3 419 | const lambdaDebug: Eval<'(curry (lambda (a b) (* a b)) 2)'> = [["var{b}"], "->", ["op{*}", 2, "var{b}"]] --------------------------------------------------------------------------------