@tsukiroku/tiny
Version:
Tiny interpreter
113 lines (112 loc) • 3.95 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.stderr = exports.stdout = exports.stdin = void 0;
const tiny_1 = require("./tiny");
__exportStar(require("./tiny"), exports);
const stdin = (...x) => tiny_1.NULL;
exports.stdin = stdin;
const stdout = (...x) => process.stdout.write(x.join(' '));
exports.stdout = stdout;
const stderr = (...x) => process.stderr.write(`${x.join(' ')}\n`);
exports.stderr = stderr;
const defaultFilename = '<Tiny>';
class Tiny {
x;
option;
builtins = new Map();
stdio = { stdin, stdout, stderr };
constructor(x, option) {
this.x = x;
this.option = { ...option };
}
tokenizer() {
return new tiny_1.Lexer(this.x, {
...this.option,
stderr: this.stdio.stderr,
}, this.option.filename ?? defaultFilename);
}
parser() {
return new tiny_1.Parser(this.tokenizer(), this.option);
}
parseProgram() {
const program = this.parser().parseProgram();
program.errors.forEach((error) => (0, tiny_1.printError)(error, this.option.filename ?? defaultFilename, this.stdio.stderr, {
...this.option,
}));
return program;
}
includeStdlib(env) {
if (this.option.useStdLibAutomatically)
new tiny_1.Evaluator(new tiny_1.Parser(new tiny_1.Lexer(`import('@std/lib');`, {
...this.option,
stderr: this.stdio.stderr,
}, this.option.filename ?? defaultFilename), this.option).parseProgram(), env, {
...this.option,
stdio: this.stdio,
filename: this.option.filename ?? defaultFilename,
root: this.option.root ?? './',
}).eval();
}
evaluate(program, env) {
const result = new tiny_1.Evaluator(program, env, {
...this.option,
stdio: this.stdio,
filename: this.option.filename ?? defaultFilename,
root: this.option.root ?? './',
}).eval();
return result;
}
eval() {
const env = this.option.enviroment ?? new tiny_1.Enviroment();
this.includeStdlib(env);
return (0, tiny_1.objectStringify)(this.evaluate(this.parseProgram(), env));
}
evalProgram(program) {
const env = this.option.enviroment ?? new tiny_1.Enviroment();
this.includeStdlib(env);
return (0, tiny_1.objectStringify)(this.evaluate(program, env));
}
setBuiltin(name, func) {
this.builtins.set(name, func);
return this;
}
setBuiltins(builtins) {
builtins.forEach((func, name) => this.setBuiltin(name, func));
return this;
}
applyBuiltins() {
this.builtins.forEach((func, name) => tiny_1.builtinsEval.set(name, func));
return this;
}
setStdin(func) {
this.stdio = { ...this.stdio, stdin: func };
return this;
}
setStdout(func) {
this.stdio = { ...this.stdio, stdout: func };
return this;
}
setStderr(func) {
this.stdio = { ...this.stdio, stderr: func };
return this;
}
setFileName(filename) {
this.option.filename = filename;
return this;
}
}
exports.default = Tiny;