// 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}`; }