Created
April 5, 2021 14:51
-
-
Save thomasvrgn/b0ca8722bc12ad5ae005272657e7502f to your computer and use it in GitHub Desktop.
Lisp interpreter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Based on other parser gist | |
| const tokens = tokenize(code); | |
| const ast = parse(tokens); | |
| run(ast); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const stack = [[]]; | |
| const frame = (stack) => peek(stack).slice(-1)[0]; | |
| const peek = (stack) => stack.slice(-1)[0]; | |
| const variables = (frame) => { | |
| const vars = new Map(); | |
| for (const _frame of frame) { | |
| for (const variable of _frame) { | |
| vars.set(variable[0], variable[1]); | |
| } | |
| } | |
| return vars; | |
| } | |
| const isContainer = (ast) => Array.isArray(ast) | |
| && ast.every((child) => Array.isArray(child)); | |
| function run(ast) { | |
| if (isContainer(ast)) { | |
| let ret; | |
| for (const child of ast) { | |
| ret = run(child); | |
| if (ret && ret[0] === true) { | |
| break; | |
| } | |
| } | |
| return ret; | |
| } else if (Array.isArray(ast)) { | |
| const [_expr, ...args] = ast; | |
| const expr = _expr.value; | |
| if (expr === 'begin') { | |
| peek(stack).push(new Map()); | |
| let ret = run(args); | |
| peek(stack).pop(); | |
| return ret && ret[0] === 1 ? ret[1] : ret; | |
| } else if (expr === 'print') { | |
| console.log(...args.map((x) => run(x).value)) | |
| } else if (expr === 'let') { | |
| frame(stack).set(args[0].value, run(args[1])); | |
| } else if (expr === 'fn') { | |
| return { | |
| type: 'Function', | |
| args: args[0], | |
| body: args[1], | |
| scope: frame(stack), | |
| } | |
| } else if (expr === 'return') { | |
| return [1, args[0]]; | |
| } else { | |
| const func = run(_expr); | |
| if (func !== undefined) { | |
| stack.push([func.scope]); | |
| for (const index in func.args) { | |
| const arg = func.args[index].value; | |
| const callArg = args[index]; | |
| frame(stack).set(arg, run(callArg)); | |
| } | |
| let ret = run(func.body); | |
| stack.pop(); | |
| return ret; | |
| } | |
| } | |
| } else if ('value' in ast) { | |
| if (ast.type === 'Word') { | |
| return variables(peek(stack)).get(ast.value); | |
| } else return ast; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment