better compiler warnings adn errors
This commit is contained in:
@@ -182,9 +182,99 @@ function analyze(src, filename) {
|
||||
// Lazy-loaded verify_ir module (loaded on first use)
|
||||
var _verify_ir_mod = null
|
||||
|
||||
// Module summary extraction for cross-program analysis.
|
||||
// Scans mcode IR for use() call patterns and attaches summaries.
|
||||
// _summary_resolver is set after shop loads (null during bootstrap).
|
||||
var _summary_resolver = null
|
||||
|
||||
function extract_module_summaries(compiled) {
|
||||
if (_summary_resolver == null) return null
|
||||
var instrs = null
|
||||
var summaries = []
|
||||
var i = 0
|
||||
var j = 0
|
||||
var n = 0
|
||||
var instr = null
|
||||
var prev = null
|
||||
var op = null
|
||||
var use_slots = {}
|
||||
var frame_map = {}
|
||||
var arg_map = {}
|
||||
var val_slot = 0
|
||||
var f_slot = 0
|
||||
var path = null
|
||||
var result_slot = 0
|
||||
var summary = null
|
||||
|
||||
if (compiled.main == null) return null
|
||||
instrs = compiled.main.instructions
|
||||
if (instrs == null) return null
|
||||
n = length(instrs)
|
||||
|
||||
// Pass 1: find access(slot, {make:"intrinsic", name:"use"})
|
||||
i = 0
|
||||
while (i < n) {
|
||||
instr = instrs[i]
|
||||
if (is_array(instr) && instr[0] == "access") {
|
||||
if (is_object(instr[2]) && instr[2].make == "intrinsic" && instr[2].name == "use") {
|
||||
use_slots[text(instr[1])] = true
|
||||
}
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
// Pass 2: find frame(frame_slot, use_slot), setarg with string, invoke
|
||||
i = 0
|
||||
while (i < n) {
|
||||
instr = instrs[i]
|
||||
if (is_array(instr)) {
|
||||
op = instr[0]
|
||||
if (op == "frame" || op == "goframe") {
|
||||
if (use_slots[text(instr[2])] == true) {
|
||||
frame_map[text(instr[1])] = true
|
||||
}
|
||||
} else if (op == "setarg") {
|
||||
if (frame_map[text(instr[1])] == true) {
|
||||
val_slot = instr[3]
|
||||
j = i - 1
|
||||
while (j >= 0) {
|
||||
prev = instrs[j]
|
||||
if (is_array(prev) && prev[0] == "access" && prev[1] == val_slot && is_text(prev[2])) {
|
||||
arg_map[text(instr[1])] = prev[2]
|
||||
break
|
||||
}
|
||||
j = j - 1
|
||||
}
|
||||
}
|
||||
} else if (op == "invoke" || op == "tail_invoke") {
|
||||
f_slot = instr[1]
|
||||
path = arg_map[text(f_slot)]
|
||||
if (path != null) {
|
||||
result_slot = instr[2]
|
||||
summary = _summary_resolver(path)
|
||||
if (summary != null) {
|
||||
summaries[] = {slot: result_slot, summary: summary}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
if (length(summaries) > 0) return summaries
|
||||
return null
|
||||
}
|
||||
|
||||
// Run AST through mcode pipeline -> register VM
|
||||
function run_ast_fn(name, ast, env) {
|
||||
var compiled = mcode_mod(ast)
|
||||
var ms = null
|
||||
var optimized = null
|
||||
var _di = 0
|
||||
var _diag = null
|
||||
var _has_errors = false
|
||||
var mcode_json = null
|
||||
var mach_blob = null
|
||||
if (os._verify_ir) {
|
||||
if (_verify_ir_mod == null) {
|
||||
_verify_ir_mod = load_pipeline_module('verify_ir', pipeline_env)
|
||||
@@ -192,13 +282,31 @@ function run_ast_fn(name, ast, env) {
|
||||
compiled._verify = true
|
||||
compiled._verify_mod = _verify_ir_mod
|
||||
}
|
||||
var optimized = streamline_mod(compiled)
|
||||
if (!_no_warn) {
|
||||
compiled._warn = true
|
||||
ms = extract_module_summaries(compiled)
|
||||
if (ms != null) {
|
||||
compiled._module_summaries = ms
|
||||
}
|
||||
}
|
||||
optimized = streamline_mod(compiled)
|
||||
if (optimized._verify) {
|
||||
delete optimized._verify
|
||||
delete optimized._verify_mod
|
||||
}
|
||||
var mcode_json = json.encode(optimized)
|
||||
var mach_blob = mach_compile_mcode_bin(name, mcode_json)
|
||||
if (optimized._diagnostics != null && length(optimized._diagnostics) > 0) {
|
||||
_di = 0
|
||||
_has_errors = false
|
||||
while (_di < length(optimized._diagnostics)) {
|
||||
_diag = optimized._diagnostics[_di]
|
||||
print(`${_diag.file}:${text(_diag.line)}:${text(_diag.col)}: ${_diag.severity}: ${_diag.message}\n`)
|
||||
if (_diag.severity == "error") _has_errors = true
|
||||
_di = _di + 1
|
||||
}
|
||||
if (_has_errors) disrupt
|
||||
}
|
||||
mcode_json = json.encode(optimized)
|
||||
mach_blob = mach_compile_mcode_bin(name, mcode_json)
|
||||
return mach_load(mach_blob, env)
|
||||
}
|
||||
|
||||
@@ -227,6 +335,9 @@ var _init = init
|
||||
if (_init != null && _init.native_mode)
|
||||
native_mode = true
|
||||
|
||||
// Inherit warn mode from init (set by C for --no-warn)
|
||||
var _no_warn = (_init != null && _init.no_warn) ? true : false
|
||||
|
||||
// CLI path: convert args to init record
|
||||
if (args != null && (_init == null || !_init.program)) {
|
||||
_program = args[0]
|
||||
@@ -424,6 +535,19 @@ core_extras.native_mode = native_mode
|
||||
// NOW load shop -- it receives all of the above via env
|
||||
var shop = use_core('internal/shop')
|
||||
use_core('build')
|
||||
|
||||
// Wire up module summary resolver now that shop is available
|
||||
_summary_resolver = function(path) {
|
||||
var resolved = shop.resolve_use_path(path, null)
|
||||
if (resolved == null) return null
|
||||
var summary_fn = function() {
|
||||
return shop.summary_file(resolved)
|
||||
} disruption {
|
||||
return null
|
||||
}
|
||||
return summary_fn()
|
||||
}
|
||||
|
||||
var time = use_core('time')
|
||||
var toml = use_core('toml')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user