diff options
Diffstat (limited to 'js/baba-yaga/runner.js')
-rw-r--r-- | js/baba-yaga/runner.js | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/js/baba-yaga/runner.js b/js/baba-yaga/runner.js new file mode 100644 index 0000000..da9830a --- /dev/null +++ b/js/baba-yaga/runner.js @@ -0,0 +1,52 @@ +// runner.js +// Provides a host-agnostic evaluate(source, host) entrypoint that lexes, parses, and interprets. + +import { createLexer } from './src/core/lexer.js'; +import { createParser } from './src/core/parser.js'; +import { createInterpreter } from './src/core/interpreter.js'; + +/** + * Evaluate source code in the toy language and return a result object. + * @param {string} source - The program source code. + * @param {object} host - Optional host bindings, e.g. { io: { out, in } }. + * @returns {object} Result object with { ok: boolean, value?: any, error?: string } + */ +export function evaluate(source, host = {}) { + try { + const lexer = createLexer(source); + const tokens = lexer.allTokens(); + const parser = createParser(tokens, false, source); + const ast = parser.parse(); + const interpreter = createInterpreter(ast, host); + const result = interpreter.interpret(); + return { ok: true, value: result }; + } catch (error) { + return { ok: false, error: error.message }; + } +} + +/** + * Create a code frame showing the error location in source code + * @param {string} source - The source code + * @param {object} location - Location object with line/column + * @param {string} message - Error message + * @returns {string} Formatted code frame + */ +export function makeCodeFrame(source, location, message) { + if (!location || !location.line) { + return message; + } + + const lines = source.split('\n'); + const lineIndex = location.line - 1; + const line = lines[lineIndex]; + + if (!line) { + return message; + } + + const column = location.column || 1; + const pointer = ' '.repeat(Math.max(0, column - 1)) + '^'; + + return `${message}\n ${location.line} | ${line}\n | ${pointer}`; +} |