130 lines
3.4 KiB
Plaintext
130 lines
3.4 KiB
Plaintext
// Hidden vars (os, args, core_path, use_mcode) come from env
|
|
// args[0] = script name, args[1..] = user args
|
|
var load_internal = os.load_internal
|
|
function use_embed(name) {
|
|
return load_internal("js_" + name + "_use")
|
|
}
|
|
|
|
var fd = use_embed('fd')
|
|
var json = use_embed('json')
|
|
|
|
var use_cache = {}
|
|
use_cache['fd'] = fd
|
|
use_cache['os'] = os
|
|
use_cache['json'] = json
|
|
|
|
// Bootstrap: load tokenize.cm and parse.cm via C pipeline (mach_eval)
|
|
function use_basic(path) {
|
|
if (use_cache[path])
|
|
return use_cache[path]
|
|
var result = use_embed(replace(path, '/', '_'))
|
|
use_cache[path] = result
|
|
return result
|
|
}
|
|
|
|
var tok_path = core_path + "/tokenize.cm"
|
|
var par_path = core_path + "/parse.cm"
|
|
var fold_path = core_path + "/fold.cm"
|
|
var tokenize_mod = mach_eval("tokenize", text(fd.slurp(tok_path)), {use: use_basic})
|
|
var parse_mod = mach_eval("parse", text(fd.slurp(par_path)), {use: use_basic})
|
|
var fold_mod = mach_eval("fold", text(fd.slurp(fold_path)), {use: use_basic})
|
|
|
|
// Optionally load mcode compiler module
|
|
var mcode_mod = null
|
|
var mcode_path = null
|
|
if (use_mcode) {
|
|
mcode_path = core_path + "/mcode.cm"
|
|
mcode_mod = mach_eval("mcode", text(fd.slurp(mcode_path)), {use: use_basic})
|
|
}
|
|
|
|
// analyze: tokenize + parse, check for errors
|
|
function analyze(src, filename) {
|
|
var tok_result = tokenize_mod(src, filename)
|
|
var ast = parse_mod(tok_result.tokens, src, filename, tokenize_mod)
|
|
var _i = 0
|
|
var prev_line = -1
|
|
var prev_msg = null
|
|
var e = null
|
|
var msg = null
|
|
var line = null
|
|
var col = null
|
|
var has_errors = ast.errors != null && length(ast.errors) > 0
|
|
if (has_errors) {
|
|
while (_i < length(ast.errors)) {
|
|
e = ast.errors[_i]
|
|
msg = e.message
|
|
line = e.line
|
|
col = e.column
|
|
if (msg != prev_msg || line != prev_line) {
|
|
if (line != null && col != null) {
|
|
print(`${filename}:${text(line)}:${text(col)}: error: ${msg}`)
|
|
} else {
|
|
print(`${filename}: error: ${msg}`)
|
|
}
|
|
}
|
|
prev_line = line
|
|
prev_msg = msg
|
|
_i = _i + 1
|
|
}
|
|
disrupt
|
|
}
|
|
ast = fold_mod(ast)
|
|
return ast
|
|
}
|
|
|
|
// Run AST through either mcode or mach pipeline
|
|
function run_ast(name, ast, env) {
|
|
var compiled = null
|
|
if (use_mcode) {
|
|
compiled = mcode_mod(ast)
|
|
return mcode_run(name, json.encode(compiled), env)
|
|
}
|
|
return mach_eval_ast(name, json.encode(ast), env)
|
|
}
|
|
|
|
// use() with ƿit pipeline for .cm modules
|
|
function use(path) {
|
|
var file_path = path + '.cm'
|
|
var script = null
|
|
var ast = null
|
|
var result = null
|
|
if (use_cache[path])
|
|
return use_cache[path]
|
|
|
|
// Check CWD first, then core_path
|
|
if (!fd.is_file(file_path))
|
|
file_path = core_path + '/' + path + '.cm'
|
|
|
|
if (fd.is_file(file_path)) {
|
|
script = text(fd.slurp(file_path))
|
|
ast = analyze(script, file_path)
|
|
result = run_ast(path, ast, {use: use})
|
|
use_cache[path] = result
|
|
return result
|
|
}
|
|
|
|
// Fallback to embedded C module
|
|
result = use_embed(replace(path, '/', '_'))
|
|
use_cache[path] = result
|
|
return result
|
|
}
|
|
|
|
// Load and run the user's program
|
|
var program = args[0]
|
|
var script_file = program
|
|
|
|
// Add .ce extension if not already present
|
|
if (!ends_with(script_file, '.ce') && !ends_with(script_file, '.cm'))
|
|
script_file = program + '.ce'
|
|
|
|
var user_args = []
|
|
var _j = 1
|
|
while (_j < length(args)) {
|
|
push(user_args, args[_j])
|
|
_j = _j + 1
|
|
}
|
|
|
|
var script = text(fd.slurp(script_file))
|
|
var ast = analyze(script, script_file)
|
|
run_ast(program, ast, {use: use, args: user_args, json: json})
|