// compare_aot.ce — compile a .ce/.cm file via both paths and compare results // // Usage: // cell --dev compare_aot.ce var build = use('build') var fd_mod = use('fd') var os = use('internal/os') var json = use('json') var time = use('time') var show = function(v) { if (v == null) return "null" return json.encode(v) } if (length(args) < 1) { log.compile('usage: cell --dev compare_aot.ce ') return } var file = args[0] if (!fd_mod.is_file(file)) { if (!ends_with(file, '.ce') && fd_mod.is_file(file + '.ce')) file = file + '.ce' else if (!ends_with(file, '.cm') && fd_mod.is_file(file + '.cm')) file = file + '.cm' else { log.error('file not found: ' + file) return } } var abs = fd_mod.realpath(file) // Shared compilation front-end — uses raw modules for per-stage timing var tokenize = use('tokenize') var parse_mod = use('parse') var fold = use('fold') var mcode_mod = use('mcode') var streamline_mod = use('streamline') var t0 = time.number() var src = text(fd_mod.slurp(abs)) var t1 = time.number() var tok = tokenize(src, abs) var t2 = time.number() var ast = parse_mod(tok.tokens, src, abs, tokenize) var t3 = time.number() var folded = fold(ast) var t4 = time.number() var compiled = mcode_mod(folded) var t5 = time.number() var optimized = streamline_mod(compiled) var t6 = time.number() log.compile('--- front-end timing ---') log.compile(' read: ' + text(t1 - t0) + 's') log.compile(' tokenize: ' + text(t2 - t1) + 's') log.compile(' parse: ' + text(t3 - t2) + 's') log.compile(' fold: ' + text(t4 - t3) + 's') log.compile(' mcode: ' + text(t5 - t4) + 's') log.compile(' streamline: ' + text(t6 - t5) + 's') log.compile(' total: ' + text(t6 - t0) + 's') // Shared env for both paths — only non-intrinsic runtime functions. // Intrinsics (starts_with, ends_with, logical, some, every, etc.) live on // the stoned global and are found via GETINTRINSIC/cell_rt_get_intrinsic. var env = stone({ log: log, fallback: fallback, parallel: parallel, race: race, sequence: sequence, use }) // --- Interpreted (mach VM) --- var result_interp = null var interp_ok = false var run_interp = function() { log.compile('--- interpreted ---') var mcode_json = json.encode(optimized) var mach_blob = mach_compile_mcode_bin(abs, mcode_json) result_interp = mach_load(mach_blob, env) interp_ok = true log.compile('result: ' + show(result_interp)) } disruption { interp_ok = true log.compile('(disruption escaped from interpreted run)') } run_interp() // --- Native (AOT via QBE) --- var result_native = null var native_ok = false var run_native = function() { log.compile('\n--- native ---') var dylib_path = build.compile_native_ir(optimized, abs, null) log.compile('dylib: ' + dylib_path) var handle = os.dylib_open(dylib_path) if (!handle) { log.error('failed to open dylib') return } result_native = os.native_module_load(handle, env) native_ok = true log.compile('result: ' + show(result_native)) } disruption { native_ok = true log.compile('(disruption escaped from native run)') } run_native() // --- Comparison --- log.compile('\n--- comparison ---') var s_interp = show(result_interp) var s_native = show(result_native) if (interp_ok && native_ok) { if (s_interp == s_native) { log.compile('MATCH') } else { log.error('MISMATCH') log.error(' interp: ' + s_interp) log.error(' native: ' + s_native) } } else { if (!interp_ok) log.error('interpreted run failed') if (!native_ok) log.error('native run failed') }