├── .gitignore ├── README.md ├── files ├── fib.json ├── fib.rinha ├── if.json └── if.rinha ├── index.ts ├── interpreter.ts ├── package.json ├── tsconfig.json ├── types.ts └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rinha-ts 2 | # rinha-ts 3 | -------------------------------------------------------------------------------- /files/fib.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "files/fib.rinha", 3 | "expression": { 4 | "kind": "Let", 5 | "name": { 6 | "text": "fib", 7 | "location": { "start": 4, "end": 7, "filename": "files/fib.rinha" } 8 | }, 9 | "value": { 10 | "kind": "Function", 11 | "parameters": [ 12 | { 13 | "text": "n", 14 | "location": { "start": 14, "end": 15, "filename": "files/fib.rinha" } 15 | } 16 | ], 17 | "value": { 18 | "kind": "If", 19 | "condition": { 20 | "kind": "Binary", 21 | "lhs": { 22 | "kind": "Var", 23 | "text": "n", 24 | "location": { 25 | "start": 28, 26 | "end": 29, 27 | "filename": "files/fib.rinha" 28 | } 29 | }, 30 | "op": "Lt", 31 | "rhs": { 32 | "kind": "Int", 33 | "value": 2, 34 | "location": { 35 | "start": 32, 36 | "end": 33, 37 | "filename": "files/fib.rinha" 38 | } 39 | }, 40 | "location": { "start": 28, "end": 33, "filename": "files/fib.rinha" } 41 | }, 42 | "then": { 43 | "kind": "Var", 44 | "text": "n", 45 | "location": { "start": 41, "end": 42, "filename": "files/fib.rinha" } 46 | }, 47 | "otherwise": { 48 | "kind": "Binary", 49 | "lhs": { 50 | "kind": "Call", 51 | "callee": { 52 | "kind": "Var", 53 | "text": "fib", 54 | "location": { 55 | "start": 58, 56 | "end": 61, 57 | "filename": "files/fib.rinha" 58 | } 59 | }, 60 | "arguments": [ 61 | { 62 | "kind": "Binary", 63 | "lhs": { 64 | "kind": "Var", 65 | "text": "n", 66 | "location": { 67 | "start": 62, 68 | "end": 63, 69 | "filename": "files/fib.rinha" 70 | } 71 | }, 72 | "op": "Sub", 73 | "rhs": { 74 | "kind": "Int", 75 | "value": 1, 76 | "location": { 77 | "start": 66, 78 | "end": 67, 79 | "filename": "files/fib.rinha" 80 | } 81 | }, 82 | "location": { 83 | "start": 62, 84 | "end": 67, 85 | "filename": "files/fib.rinha" 86 | } 87 | } 88 | ], 89 | "location": { 90 | "start": 58, 91 | "end": 68, 92 | "filename": "files/fib.rinha" 93 | } 94 | }, 95 | "op": "Add", 96 | "rhs": { 97 | "kind": "Call", 98 | "callee": { 99 | "kind": "Var", 100 | "text": "fib", 101 | "location": { 102 | "start": 71, 103 | "end": 74, 104 | "filename": "files/fib.rinha" 105 | } 106 | }, 107 | "arguments": [ 108 | { 109 | "kind": "Binary", 110 | "lhs": { 111 | "kind": "Var", 112 | "text": "n", 113 | "location": { 114 | "start": 75, 115 | "end": 76, 116 | "filename": "files/fib.rinha" 117 | } 118 | }, 119 | "op": "Sub", 120 | "rhs": { 121 | "kind": "Int", 122 | "value": 2, 123 | "location": { 124 | "start": 79, 125 | "end": 80, 126 | "filename": "files/fib.rinha" 127 | } 128 | }, 129 | "location": { 130 | "start": 75, 131 | "end": 80, 132 | "filename": "files/fib.rinha" 133 | } 134 | } 135 | ], 136 | "location": { 137 | "start": 71, 138 | "end": 81, 139 | "filename": "files/fib.rinha" 140 | } 141 | }, 142 | "location": { "start": 58, "end": 81, "filename": "files/fib.rinha" } 143 | }, 144 | "location": { "start": 24, "end": 85, "filename": "files/fib.rinha" } 145 | }, 146 | "location": { "start": 10, "end": 87, "filename": "files/fib.rinha" } 147 | }, 148 | "next": { 149 | "kind": "Print", 150 | "value": { 151 | "kind": "Call", 152 | "callee": { 153 | "kind": "Var", 154 | "text": "fib", 155 | "location": { "start": 97, "end": 100, "filename": "files/fib.rinha" } 156 | }, 157 | "arguments": [ 158 | { 159 | "kind": "Int", 160 | "value": 10, 161 | "location": { 162 | "start": 101, 163 | "end": 103, 164 | "filename": "files/fib.rinha" 165 | } 166 | } 167 | ], 168 | "location": { "start": 97, "end": 104, "filename": "files/fib.rinha" } 169 | }, 170 | "location": { "start": 90, "end": 105, "filename": "files/fib.rinha" } 171 | }, 172 | "location": { "start": 0, "end": 105, "filename": "files/fib.rinha" } 173 | }, 174 | "location": { "start": 0, "end": 105, "filename": "files/fib.rinha" } 175 | } 176 | -------------------------------------------------------------------------------- /files/fib.rinha: -------------------------------------------------------------------------------- 1 | let fib = fn (n) => { 2 | if (n < 2) { 3 | n 4 | } else { 5 | fib(n - 1) + fib(n - 2) 6 | } 7 | }; 8 | 9 | print (fib(10)) -------------------------------------------------------------------------------- /files/if.json: -------------------------------------------------------------------------------- 1 | {"name":"files/fib.rinha","expression":{"kind":"Let","name":{"text":"fib","location":{"start":4,"end":7,"filename":"files/fib.rinha"}},"value":{"kind":"Function","parameters":[{"text":"n","location":{"start":14,"end":15,"filename":"files/fib.rinha"}}],"value":{"kind":"If","condition":{"kind":"Binary","lhs":{"kind":"Var","text":"n","location":{"start":28,"end":29,"filename":"files/fib.rinha"}},"op":"Lt","rhs":{"kind":"Int","value":2,"location":{"start":32,"end":33,"filename":"files/fib.rinha"}},"location":{"start":28,"end":33,"filename":"files/fib.rinha"}},"then":{"kind":"Var","text":"n","location":{"start":41,"end":42,"filename":"files/fib.rinha"}},"otherwise":{"kind":"Binary","lhs":{"kind":"Call","callee":{"kind":"Var","text":"fib","location":{"start":58,"end":61,"filename":"files/fib.rinha"}},"arguments":[{"kind":"Binary","lhs":{"kind":"Var","text":"n","location":{"start":62,"end":63,"filename":"files/fib.rinha"}},"op":"Sub","rhs":{"kind":"Int","value":1,"location":{"start":66,"end":67,"filename":"files/fib.rinha"}},"location":{"start":62,"end":67,"filename":"files/fib.rinha"}}],"location":{"start":58,"end":68,"filename":"files/fib.rinha"}},"op":"Add","rhs":{"kind":"Call","callee":{"kind":"Var","text":"fib","location":{"start":71,"end":74,"filename":"files/fib.rinha"}},"arguments":[{"kind":"Binary","lhs":{"kind":"Var","text":"n","location":{"start":75,"end":76,"filename":"files/fib.rinha"}},"op":"Sub","rhs":{"kind":"Int","value":2,"location":{"start":79,"end":80,"filename":"files/fib.rinha"}},"location":{"start":75,"end":80,"filename":"files/fib.rinha"}}],"location":{"start":71,"end":81,"filename":"files/fib.rinha"}},"location":{"start":58,"end":81,"filename":"files/fib.rinha"}},"location":{"start":24,"end":85,"filename":"files/fib.rinha"}},"location":{"start":10,"end":87,"filename":"files/fib.rinha"}},"next":{"kind":"Print","value":{"kind":"Call","callee":{"kind":"Var","text":"fib","location":{"start":97,"end":100,"filename":"files/fib.rinha"}},"arguments":[{"kind":"Int","value":10,"location":{"start":101,"end":103,"filename":"files/fib.rinha"}}],"location":{"start":97,"end":104,"filename":"files/fib.rinha"}},"location":{"start":90,"end":105,"filename":"files/fib.rinha"}},"location":{"start":0,"end":105,"filename":"files/fib.rinha"}},"location":{"start":0,"end":105,"filename":"files/fib.rinha"}} 2 | -------------------------------------------------------------------------------- /files/if.rinha: -------------------------------------------------------------------------------- 1 | let a = 2 + 2; 2 | print(a) -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import { interpretFile } from "./interpreter"; 2 | 3 | import json from "./files/fib.json" 4 | 5 | interpretFile(json as any) -------------------------------------------------------------------------------- /interpreter.ts: -------------------------------------------------------------------------------- 1 | import * as t from "./types" 2 | 3 | // Maps variable names to values 4 | type Env = { 5 | objects: Record 6 | } 7 | 8 | // Clones the environment 9 | let cloneEnv = (env: Env) : Env => 10 | ({objects: {...env.objects}}) 11 | 12 | // A function value. 13 | type Closure = { 14 | body: t.Term, 15 | parameters: string[] 16 | env: Env 17 | } 18 | 19 | // A value is the result of the interpretation 20 | 21 | type Value 22 | = { kind: "boolean", value: boolean } 23 | | { kind: "string", value: string } 24 | | { kind: "number", value: number } 25 | | { kind: "closure", value: Closure } 26 | | { kind: "tuple", fst: Value, snd: Value }; 27 | 28 | // Interpreter 29 | 30 | let unimplemented = () : never => { 31 | throw new Error("unimplemented yet") 32 | } 33 | 34 | export let interpretFile = (file: t.File) : Value => { 35 | let env = { objects: {} } 36 | return interpret(file.expression, env) 37 | } 38 | 39 | let typeMismatch = (type: string) : never => { 40 | throw new Error(`not a ${type}`) 41 | } 42 | 43 | let assertInt = (value: Value) : number => 44 | value.kind == "number" ? value.value : typeMismatch("int") 45 | 46 | let assertTuple = (value: Value) : [Value, Value] => 47 | value.kind == "tuple" ? [value.fst, value.snd] : typeMismatch("tuple") 48 | 49 | let assertClosure = (value: Value) : Closure => 50 | value.kind == "closure" ? value.value : typeMismatch("closure") 51 | 52 | let assertBool = (value: Value) : boolean => 53 | value.kind == "boolean" ? value.value : typeMismatch("closure") 54 | 55 | let castToString = (value: Value) : string => 56 | value.kind == "number" || value.kind == "string" ? value.value.toString() : typeMismatch("string or int") 57 | 58 | let isEqual = (left: Value, right: Value) : boolean => { 59 | if (left.kind == "number" && right.kind == "number") { 60 | return left.value == right.value 61 | } else if (left.kind == "string" && right.kind == "string") { 62 | return left.value == right.value 63 | } if (left.kind == "boolean" && right.kind == "boolean") { 64 | return left.value == right.value 65 | } else { 66 | return typeMismatch("number or string or boolean") 67 | } 68 | } 69 | 70 | let interpretBinary = (left: Value, right: Value, op: t.BinaryOp) : Value => { 71 | switch (op) { 72 | case "Add": { 73 | if (left.kind == "number" && right.kind == "number") { 74 | return { kind: "number", value: left.value + right.value } 75 | } else { 76 | let leftVal = castToString(left); 77 | let rightVal = castToString(right); 78 | return { kind: "string", value: leftVal + rightVal } 79 | } 80 | } 81 | case "Eq": { 82 | let value = isEqual(left, right); 83 | return { kind: "boolean", value } 84 | } 85 | case "Neq": { 86 | let value = !isEqual(left, right); 87 | return { kind: "boolean", value } 88 | } 89 | case "Sub": { 90 | let leftVal = assertInt(left); 91 | let rightVal = assertInt(right); 92 | return { kind: "number", value: leftVal - rightVal } 93 | } 94 | case "Mul": { 95 | let leftVal = assertInt(left); 96 | let rightVal = assertInt(right); 97 | return { kind: "number", value: leftVal * rightVal } 98 | } 99 | case "Div": { 100 | let leftVal = assertInt(left); 101 | let rightVal = assertInt(right); 102 | return { kind: "number", value: Math.floor(leftVal / rightVal) } 103 | } 104 | case "Rem": { 105 | let leftVal = assertInt(left); 106 | let rightVal = assertInt(right); 107 | return { kind: "number", value: Math.floor(leftVal % rightVal) } 108 | } 109 | case "Lt": { 110 | let leftVal = assertInt(left); 111 | let rightVal = assertInt(right); 112 | return { kind: "boolean", value: leftVal < rightVal } 113 | } 114 | case "Gt": { 115 | let leftVal = assertInt(left); 116 | let rightVal = assertInt(right); 117 | return { kind: "boolean", value: leftVal > rightVal } 118 | } 119 | case "Lte": { 120 | let leftVal = assertInt(left); 121 | let rightVal = assertInt(right); 122 | return { kind: "boolean", value: leftVal <= rightVal } 123 | } 124 | case "Gte": { 125 | let leftVal = assertInt(left); 126 | let rightVal = assertInt(right); 127 | return { kind: "boolean", value: leftVal >= rightVal } 128 | } 129 | case "And": { 130 | let leftVal = assertBool(left); 131 | let rightVal = assertBool(right); 132 | return { kind: "boolean", value: leftVal && rightVal } 133 | } 134 | case "Or": { 135 | let leftVal = assertBool(left); 136 | let rightVal = assertBool(right); 137 | return { kind: "boolean", value: leftVal || rightVal } 138 | } 139 | } 140 | } 141 | 142 | let showValue = (value: Value) : string => { 143 | switch (value.kind) { 144 | case "number": return value.value.toString() 145 | case "boolean": return value.value ? "true" : "false" 146 | case "string": return value.value 147 | case "closure": return "<#closure>" 148 | case "tuple": return `(${showValue(value.fst)},${showValue(value.snd)})` 149 | } 150 | } 151 | 152 | let interpret = (term: t.Term, env: Env) : Value => { 153 | switch (term.kind) { 154 | case "Str": { 155 | return { kind: "string", value: term.value } 156 | } 157 | case "Bool": { 158 | return { kind: "boolean", value: term.value } 159 | } 160 | case "Int": { 161 | return { kind: "number", value: term.value } 162 | } 163 | case "If": { 164 | let condition = interpret(term.condition, env) 165 | let boolean = assertBool(condition) 166 | return interpret(boolean ? term.then : term.otherwise, env) 167 | } 168 | case "Tuple": { 169 | let fst = interpret(term.first, env); 170 | let snd = interpret(term.second, env); 171 | return { kind: "tuple", fst, snd } 172 | } 173 | case "First": { 174 | let fst = interpret(term.value, env); 175 | return assertTuple(fst)[0] 176 | } 177 | case "Second": { 178 | let fst = interpret(term.value, env); 179 | return assertTuple(fst)[1] 180 | } 181 | case "Binary": { 182 | let left = interpret(term.lhs, env) 183 | let right = interpret(term.rhs, env) 184 | return interpretBinary(left, right, term.op) 185 | } 186 | case "Print": { 187 | let value = interpret(term.value, env); 188 | console.log(showValue(value)) 189 | return value 190 | } 191 | case "Var": { 192 | let value = env.objects[term.text]; 193 | if (value) { 194 | return value 195 | } else { 196 | throw new Error(`cannot find variable ${term.text}`) 197 | } 198 | } 199 | case "Let": { 200 | let newEnv = cloneEnv(env); 201 | let value = interpret(term.value, newEnv); 202 | newEnv.objects[term.name.text] = value; 203 | return interpret(term.next, newEnv) 204 | } 205 | case "Call": { 206 | let func = interpret(term.callee, env) 207 | let closure = assertClosure(func) 208 | 209 | if (closure.parameters.length != term.arguments.length) { 210 | throw new Error(`expected ${closure.parameters.length} arguments but instead got ${term.arguments.length}`) 211 | } 212 | 213 | let functionEnv = cloneEnv(closure.env); 214 | 215 | for (let i = 0; i < closure.parameters.length; i++) { 216 | functionEnv.objects[closure.parameters[i]] = interpret(term.arguments[i], env) 217 | } 218 | 219 | return interpret(closure.body, functionEnv) 220 | } 221 | case "Function": { 222 | return { 223 | kind: "closure", 224 | value: { 225 | body: term.value, 226 | env, 227 | parameters: term.parameters.map(x => x.text) 228 | } 229 | } 230 | } 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rinha-de-compilers", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "watch": "tsc --watch", 8 | "build": "tsc", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "typescript": "^5.2.2" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "commonjs", /* Specify what module code is generated. */ 29 | // "rootDir": "./", /* Specify the root folder within your source files. */ 30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 42 | "resolveJsonModule": true, /* Enable importing .json files. */ 43 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 44 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 45 | 46 | /* JavaScript Support */ 47 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 48 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 49 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 50 | 51 | /* Emit */ 52 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 53 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 54 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 55 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 56 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 57 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 58 | "outDir": "./dist", /* Specify an output folder for all emitted files. */ 59 | // "removeComments": true, /* Disable emitting comments. */ 60 | // "noEmit": true, /* Disable emitting files from a compilation. */ 61 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 62 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 63 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 64 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 65 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 66 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 67 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 68 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 69 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 70 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 71 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 72 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 73 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 74 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 75 | 76 | /* Interop Constraints */ 77 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 78 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ 79 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 80 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 81 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 82 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 83 | 84 | /* Type Checking */ 85 | "strict": true, /* Enable all strict type-checking options. */ 86 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 87 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 88 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 89 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 90 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 91 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 92 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 93 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 94 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 95 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 96 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 97 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 98 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 99 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 100 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 101 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 102 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 103 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 104 | 105 | 106 | 107 | /* Completeness */ 108 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 109 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /types.ts: -------------------------------------------------------------------------------- 1 | export interface File { 2 | expression: Term, 3 | location: Location, 4 | } 5 | 6 | export interface Location { 7 | start: number, 8 | end: number, 9 | filename: string, 10 | } 11 | 12 | export interface If { 13 | kind: "If", 14 | condition: Term, 15 | then: Term, 16 | otherwise: Term, 17 | location: Location, 18 | } 19 | 20 | export interface Let { 21 | kind: "Let", 22 | name: Parameter, 23 | value: Term, 24 | next: Term, 25 | location: Location, 26 | } 27 | 28 | export interface Str { 29 | kind: "Str", 30 | value: string, 31 | location: Location, 32 | } 33 | 34 | export interface Bool { 35 | kind: "Bool", 36 | value: boolean, 37 | location: Location, 38 | } 39 | 40 | export interface Int { 41 | kind: "Int", 42 | value: number, 43 | location: Location, 44 | } 45 | 46 | export type BinaryOp = 47 | | "Add" 48 | | "Sub" 49 | | "Mul" 50 | | "Div" 51 | | "Rem" 52 | | "Eq" 53 | | "Neq" 54 | | "Lt" 55 | | "Gt" 56 | | "Lte" 57 | | "Gte" 58 | | "And" 59 | | "Or" 60 | 61 | export interface Binary { 62 | kind: "Binary", 63 | lhs: Term, 64 | op: BinaryOp, 65 | rhs: Term, 66 | location: Location, 67 | } 68 | 69 | export interface Call { 70 | kind: "Call", 71 | callee: Term, 72 | arguments: Term[], 73 | location: Location, 74 | } 75 | 76 | export interface Function { 77 | kind: "Function", 78 | parameters: Parameter[], 79 | value: Term, 80 | location: Location, 81 | } 82 | 83 | export interface First { 84 | kind: "First", 85 | value: Term, 86 | location: Location, 87 | } 88 | 89 | export interface Print { 90 | kind: "Print", 91 | value: Term, 92 | location: Location, 93 | } 94 | 95 | export interface Second { 96 | kind: "Second", 97 | value: Term, 98 | location: Location, 99 | } 100 | 101 | export interface Tuple { 102 | kind: "Tuple", 103 | first: Term, 104 | second: Term, 105 | location: Location, 106 | } 107 | 108 | export interface Parameter { 109 | text: string, 110 | location: Location, 111 | } 112 | 113 | export interface Var { 114 | kind: "Var", 115 | text: string, 116 | location: Location, 117 | } 118 | 119 | export type Term = Int | Str | Bool | Call | Binary | Function | Let | If | Print | First | Second | Tuple | Var; 120 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | typescript@^5.2.2: 6 | version "5.2.2" 7 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" 8 | integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== 9 | --------------------------------------------------------------------------------