mach loading
This commit is contained in:
@@ -65,6 +65,7 @@ function check_mach_stale() {
|
||||
"streamline.cm",
|
||||
"qbe.cm",
|
||||
"qbe_emit.cm",
|
||||
"verify_ir.cm",
|
||||
"internal/bootstrap.cm",
|
||||
"internal/engine.cm"
|
||||
]
|
||||
@@ -140,38 +141,11 @@ function analyze(src, filename) {
|
||||
return ast
|
||||
}
|
||||
|
||||
// Load a module from .mach/.mcode bytecode, falling back to source compilation
|
||||
function load_module(name, env) {
|
||||
var mach_path = core_path + '/' + name + ".cm.mach"
|
||||
var mcode_path = core_path + '/' + name + ".cm.mcode"
|
||||
var data = null
|
||||
var mcode_json = null
|
||||
var src_path = null
|
||||
var src = null
|
||||
var ast = null
|
||||
var compiled = null
|
||||
var optimized = null
|
||||
if (fd.is_file(mach_path)) {
|
||||
data = fd.slurp(mach_path)
|
||||
return mach_load(data, env)
|
||||
}
|
||||
if (fd.is_file(mcode_path)) {
|
||||
mcode_json = text(fd.slurp(mcode_path))
|
||||
return mach_eval_mcode(name, mcode_json, env)
|
||||
}
|
||||
src_path = core_path + '/' + name + ".cm"
|
||||
src = text(fd.slurp(src_path))
|
||||
ast = analyze(src, src_path)
|
||||
compiled = mcode_mod(ast)
|
||||
optimized = streamline_mod(compiled)
|
||||
return mach_eval_mcode(name, json.encode(optimized), env)
|
||||
}
|
||||
|
||||
// Load optimization pipeline modules (needs analyze to be defined)
|
||||
streamline_mod = load_module("streamline", boot_env)
|
||||
streamline_mod = boot_load("streamline", boot_env)
|
||||
use_cache['streamline'] = streamline_mod
|
||||
|
||||
// Lazy-loaded verify_ir module (loaded on first use via use_fn)
|
||||
// Lazy-loaded verify_ir module (loaded on first use)
|
||||
var _verify_ir_mod = null
|
||||
|
||||
// Run AST through mcode pipeline → register VM
|
||||
@@ -179,7 +153,7 @@ function run_ast(name, ast, env) {
|
||||
var compiled = mcode_mod(ast)
|
||||
if (os._verify_ir) {
|
||||
if (_verify_ir_mod == null) {
|
||||
_verify_ir_mod = use_fn('verify_ir')
|
||||
_verify_ir_mod = boot_load('verify_ir', boot_env)
|
||||
}
|
||||
compiled._verify = true
|
||||
compiled._verify_mod = _verify_ir_mod
|
||||
@@ -199,60 +173,6 @@ function run_ast_noopt(name, ast, env) {
|
||||
return mach_eval_mcode(name, json.encode(compiled), env)
|
||||
}
|
||||
|
||||
// use() with ƿit pipeline for .cm modules
|
||||
function use_fn(path) {
|
||||
var file_path = null
|
||||
var mach_path = null
|
||||
var mcode_path = null
|
||||
var mcode_json = null
|
||||
var data = null
|
||||
var script = null
|
||||
var ast = null
|
||||
var result = null
|
||||
if (use_cache[path])
|
||||
return use_cache[path]
|
||||
|
||||
// Try .cm.mach bytecode first (CWD then core_path)
|
||||
mach_path = path + '.cm.mach'
|
||||
if (!fd.is_file(mach_path))
|
||||
mach_path = core_path + '/' + path + '.cm.mach'
|
||||
if (fd.is_file(mach_path)) {
|
||||
data = fd.slurp(mach_path)
|
||||
result = mach_load(data, {use: use_fn})
|
||||
use_cache[path] = result
|
||||
return result
|
||||
}
|
||||
|
||||
// Try .cm.mcode JSON IR (CWD then core_path)
|
||||
mcode_path = path + '.cm.mcode'
|
||||
if (!fd.is_file(mcode_path))
|
||||
mcode_path = core_path + '/' + path + '.cm.mcode'
|
||||
if (fd.is_file(mcode_path)) {
|
||||
mcode_json = text(fd.slurp(mcode_path))
|
||||
result = mach_eval_mcode(path, mcode_json, {use: use_fn})
|
||||
use_cache[path] = result
|
||||
return result
|
||||
}
|
||||
|
||||
// Try .cm source (CWD then core_path)
|
||||
file_path = path + '.cm'
|
||||
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_fn})
|
||||
use_cache[path] = result
|
||||
return result
|
||||
}
|
||||
|
||||
// Fallback to embedded C module
|
||||
result = use_embed(replace(path, '/', '_'))
|
||||
use_cache[path] = result
|
||||
return result
|
||||
}
|
||||
|
||||
// Helper to load engine.cm and run it with given env
|
||||
function load_engine(env) {
|
||||
var engine_path = core_path + '/internal/engine.cm.mach'
|
||||
@@ -298,13 +218,15 @@ if (args != null) {
|
||||
os: os, actorsym: actorsym,
|
||||
init: {program: program, arg: user_args},
|
||||
core_path: core_path, shop_path: shop_path, json: json,
|
||||
analyze: analyze, run_ast_fn: run_ast, run_ast_noopt_fn: run_ast_noopt
|
||||
analyze: analyze, run_ast_fn: run_ast, run_ast_noopt_fn: run_ast_noopt,
|
||||
use_cache: use_cache
|
||||
})
|
||||
} else {
|
||||
// Actor spawn mode — load engine.cm with full actor env
|
||||
load_engine({
|
||||
os: os, actorsym: actorsym, init: init,
|
||||
core_path: core_path, shop_path: shop_path, json: json, nota: nota, wota: wota,
|
||||
analyze: analyze, run_ast_fn: run_ast, run_ast_noopt_fn: run_ast_noopt
|
||||
analyze: analyze, run_ast_fn: run_ast, run_ast_noopt_fn: run_ast_noopt,
|
||||
use_cache: use_cache
|
||||
})
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
// Hidden vars (os, actorsym, init, core_path, shop_path, analyze, run_ast_fn, run_ast_noopt_fn, json) come from env
|
||||
// Hidden vars (os, actorsym, init, core_path, shop_path, analyze, run_ast_fn, run_ast_noopt_fn, json, use_cache) come from env
|
||||
// In actor spawn mode, also: nota, wota
|
||||
var ACTORDATA = actorsym
|
||||
var SYSYM = '__SYSTEM__'
|
||||
@@ -53,7 +53,6 @@ var js = use_embed('js')
|
||||
// shop_path may be null if --core was used without --shop
|
||||
var packages_path = shop_path ? shop_path + '/packages' : null
|
||||
|
||||
var use_cache = {}
|
||||
use_cache['core/os'] = os
|
||||
|
||||
// Extra env properties added as engine initializes (log, runtime fns, etc.)
|
||||
@@ -70,11 +69,18 @@ function use_core(path) {
|
||||
var result = null
|
||||
var script = null
|
||||
var ast = null
|
||||
var c_cache_key = null
|
||||
|
||||
// Build env: merge core_extras, include C embed as 'native' if available
|
||||
// If C embed exists, register it so .cm modules can use('internal/<name>_c')
|
||||
if (sym) {
|
||||
c_cache_key = 'core/internal/' + path + '_c'
|
||||
if (!use_cache[c_cache_key])
|
||||
use_cache[c_cache_key] = sym
|
||||
}
|
||||
|
||||
// Build env: merge core_extras
|
||||
env = {use: use_core}
|
||||
arrfor(array(core_extras), function(k) { env[k] = core_extras[k] })
|
||||
if (sym) env.native = sym
|
||||
|
||||
// Check for pre-compiled .cm.mach file first
|
||||
var mach_path = core_path + '/' + path + '.cm.mach'
|
||||
|
||||
11627
internal/engine.cm.mcode
11627
internal/engine.cm.mcode
File diff suppressed because it is too large
Load Diff
@@ -425,6 +425,22 @@ static JSValue js_os_dylib_has_symbol(JSContext *js, JSValue self, int argc, JSV
|
||||
return JS_NewBool(js, symbol != NULL);
|
||||
}
|
||||
|
||||
/* Load a native .cm module from a dylib handle.
|
||||
Uses cell_rt_native_module_load from qbe_helpers.c */
|
||||
extern JSValue cell_rt_native_module_load(JSContext *ctx, void *dl_handle);
|
||||
|
||||
static JSValue js_os_native_module_load(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
if (argc < 1)
|
||||
return JS_ThrowTypeError(js, "native_module_load requires a dylib object");
|
||||
|
||||
void *handle = JS_GetOpaque(argv[0], js_dylib_class_id);
|
||||
if (!handle)
|
||||
return JS_ThrowTypeError(js, "First argument must be a dylib object");
|
||||
|
||||
return cell_rt_native_module_load(js, handle);
|
||||
}
|
||||
|
||||
JSC_CCALL(os_print,
|
||||
size_t len;
|
||||
const char *str = JS_ToCStringLen(js, &len, argv[0]);
|
||||
@@ -552,6 +568,37 @@ JSC_CCALL(os_getenv,
|
||||
ret = JS_NULL;
|
||||
)
|
||||
|
||||
/* --- Embedded module table (generated for static builds) ---
|
||||
Uses dlsym to check if cell_embedded_module_lookup exists at runtime.
|
||||
When linking a static build with a generated module_table.c, the symbol
|
||||
will be found; in dynamic builds it returns NULL gracefully. */
|
||||
|
||||
struct cell_embedded_entry {
|
||||
const char *name;
|
||||
const unsigned char *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
typedef const struct cell_embedded_entry *(*cell_embed_lookup_fn)(const char *);
|
||||
|
||||
static JSValue js_os_embedded_module(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
cell_embed_lookup_fn lookup = (cell_embed_lookup_fn)dlsym(RTLD_DEFAULT, "cell_embedded_module_lookup");
|
||||
if (!lookup)
|
||||
return JS_NULL;
|
||||
|
||||
const char *name = JS_ToCString(js, argv[0]);
|
||||
if (!name) return JS_NULL;
|
||||
|
||||
const struct cell_embedded_entry *entry = lookup(name);
|
||||
JS_FreeCString(js, name);
|
||||
|
||||
if (!entry) return JS_NULL;
|
||||
|
||||
/* Return the mach blob as a stoned blob */
|
||||
return js_new_blob_stoned_copy(js, (void *)entry->data, entry->size);
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_os_funcs[] = {
|
||||
MIST_FUNC_DEF(os, platform, 0),
|
||||
MIST_FUNC_DEF(os, arch, 0),
|
||||
@@ -568,6 +615,8 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||
MIST_FUNC_DEF(os, dylib_open, 1),
|
||||
MIST_FUNC_DEF(os, dylib_symbol, 2),
|
||||
MIST_FUNC_DEF(os, dylib_has_symbol, 2),
|
||||
MIST_FUNC_DEF(os, native_module_load, 1),
|
||||
MIST_FUNC_DEF(os, embedded_module, 1),
|
||||
MIST_FUNC_DEF(os, load_internal, 1),
|
||||
MIST_FUNC_DEF(os, internal_exists, 1),
|
||||
MIST_FUNC_DEF(os, print, 1),
|
||||
|
||||
177
internal/shop.cm
177
internal/shop.cm
@@ -379,6 +379,32 @@ Shop.extract_commit_hash = function(pkg, response) {
|
||||
|
||||
var dylib_visited = {}
|
||||
var open_dls = {}
|
||||
var loaded_manifests = {}
|
||||
|
||||
// Host target detection for native dylib resolution
|
||||
function detect_host_target() {
|
||||
var platform = os.platform()
|
||||
var arch = os.arch ? os.arch() : 'arm64'
|
||||
if (platform == 'macOS' || platform == 'darwin')
|
||||
return arch == 'x86_64' ? 'macos_x86_64' : 'macos_arm64'
|
||||
if (platform == 'Linux' || platform == 'linux')
|
||||
return arch == 'x86_64' ? 'linux' : 'linux_arm64'
|
||||
if (platform == 'Windows' || platform == 'windows')
|
||||
return 'windows'
|
||||
return null
|
||||
}
|
||||
|
||||
var host_target = detect_host_target()
|
||||
|
||||
// Check for a native .cm dylib in the content-addressed cache
|
||||
// Returns the loaded module value, or null if no native dylib exists
|
||||
function try_native_dylib(content_key) {
|
||||
var native_path = hash_path(content_key) + '.' + host_target + dylib_ext
|
||||
if (!fd.is_file(native_path)) return null
|
||||
var handle = os.dylib_open(native_path)
|
||||
if (!handle) return null
|
||||
return os.native_module_load(handle)
|
||||
}
|
||||
|
||||
// Default capabilities injected into scripts
|
||||
// These map to $_ properties in engine.cm
|
||||
@@ -433,7 +459,9 @@ function resolve_mod_fn(path, pkg) {
|
||||
if (!fd.is_file(path)) { print(`path ${path} is not a file`); disrupt }
|
||||
|
||||
var content = text(fd.slurp(path))
|
||||
var cached = pull_from_cache(stone(blob(content)))
|
||||
var content_key = stone(blob(content))
|
||||
var native_result = null
|
||||
var cached = null
|
||||
var ast = null
|
||||
var compiled = null
|
||||
var mach_path = null
|
||||
@@ -441,24 +469,42 @@ function resolve_mod_fn(path, pkg) {
|
||||
var mcode_path = null
|
||||
var ir = null
|
||||
var optimized = null
|
||||
var mcode_json = null
|
||||
var cached_mcode_path = null
|
||||
|
||||
// Check for native .cm dylib first (highest performance)
|
||||
native_result = try_native_dylib(content_key)
|
||||
if (native_result != null) {
|
||||
return {_native: true, value: native_result}
|
||||
}
|
||||
|
||||
// Check cache for pre-compiled .mach blob
|
||||
cached = pull_from_cache(content_key)
|
||||
if (cached) {
|
||||
return cached
|
||||
}
|
||||
|
||||
// Check for cached mcode in content-addressed store
|
||||
cached_mcode_path = hash_path(content_key) + '.mcode'
|
||||
if (fd.is_file(cached_mcode_path)) {
|
||||
mcode_json = text(fd.slurp(cached_mcode_path))
|
||||
compiled = mach_compile_mcode_bin(path, mcode_json)
|
||||
put_into_cache(content_key, compiled)
|
||||
return compiled
|
||||
}
|
||||
|
||||
// Check for pre-compiled .mach or .mcode file alongside .cm source
|
||||
if (ends_with(path, '.cm')) {
|
||||
mach_path = text(path, 0, length(path) - 3) + '.mach'
|
||||
if (fd.is_file(mach_path)) {
|
||||
mach_blob = fd.slurp(mach_path)
|
||||
put_into_cache(stone(blob(content)), mach_blob)
|
||||
put_into_cache(content_key, mach_blob)
|
||||
return mach_blob
|
||||
}
|
||||
mcode_path = path + '.mcode'
|
||||
if (fd.is_file(mcode_path)) {
|
||||
compiled = mach_compile_mcode_bin(path, text(fd.slurp(mcode_path)))
|
||||
put_into_cache(stone(blob(content)), compiled)
|
||||
put_into_cache(content_key, compiled)
|
||||
return compiled
|
||||
}
|
||||
}
|
||||
@@ -469,8 +515,15 @@ function resolve_mod_fn(path, pkg) {
|
||||
ast = analyze(content, path)
|
||||
ir = _mcode_mod(ast)
|
||||
optimized = _streamline_mod(ir)
|
||||
compiled = mach_compile_mcode_bin(path, shop_json.encode(optimized))
|
||||
put_into_cache(stone(blob(content)), compiled)
|
||||
mcode_json = shop_json.encode(optimized)
|
||||
|
||||
// Cache mcode (architecture-independent) in content-addressed store
|
||||
ensure_dir(global_shop_path + '/build')
|
||||
fd.slurpwrite(cached_mcode_path, stone(blob(mcode_json)))
|
||||
|
||||
// Cache mach blob
|
||||
compiled = mach_compile_mcode_bin(path, mcode_json)
|
||||
put_into_cache(content_key, compiled)
|
||||
|
||||
return compiled
|
||||
}
|
||||
@@ -576,7 +629,45 @@ function get_lib_path(pkg) {
|
||||
return global_shop_path + '/lib/' + lib_name + dylib_ext
|
||||
}
|
||||
|
||||
// Open a package's dynamic library and all its dependencies
|
||||
// Load the manifest for a package's per-module dylibs
|
||||
// Returns a map of symbol_name -> dylib_path, or null if no manifest
|
||||
function load_package_manifest(pkg) {
|
||||
if (loaded_manifests[pkg] != null) return loaded_manifests[pkg]
|
||||
|
||||
var lib_name = replace(replace(replace(pkg, '/', '_'), '.', '_'), '-', '_')
|
||||
var manifest_path = global_shop_path + '/lib/' + lib_name + '.manifest.json'
|
||||
if (!fd.is_file(manifest_path)) {
|
||||
loaded_manifests[pkg] = false
|
||||
return null
|
||||
}
|
||||
var content = text(fd.slurp(manifest_path))
|
||||
var manifest = json.decode(content)
|
||||
loaded_manifests[pkg] = manifest
|
||||
return manifest
|
||||
}
|
||||
|
||||
// Open a per-module dylib from a manifest and return the dlopen handle
|
||||
function open_module_dylib(dylib_path) {
|
||||
if (open_dls[dylib_path]) return open_dls[dylib_path]
|
||||
if (!fd.is_file(dylib_path)) return null
|
||||
open_dls[dylib_path] = os.dylib_open(dylib_path)
|
||||
return open_dls[dylib_path]
|
||||
}
|
||||
|
||||
// Resolve a C symbol from per-module dylibs for a package
|
||||
// Returns a loader function or null
|
||||
function resolve_dylib_symbol(sym, pkg) {
|
||||
var manifest = load_package_manifest(pkg)
|
||||
if (!manifest) return null
|
||||
var dylib_path = manifest[sym]
|
||||
if (!dylib_path) return null
|
||||
var handle = open_module_dylib(dylib_path)
|
||||
if (!handle) return null
|
||||
if (!os.dylib_has_symbol(handle, sym)) return null
|
||||
return function() { return os.dylib_symbol(handle, sym) }
|
||||
}
|
||||
|
||||
// Open a package's dynamic libraries (loads manifest + dependency manifests)
|
||||
Shop.open_package_dylib = function(pkg) {
|
||||
if (pkg == 'core' || !pkg) return
|
||||
if (dylib_visited[pkg]) return
|
||||
@@ -606,22 +697,18 @@ Shop.open_package_dylib = function(pkg) {
|
||||
}
|
||||
}
|
||||
|
||||
var dl_path = get_lib_path(pkg)
|
||||
if (fd.is_file(dl_path)) {
|
||||
if (!open_dls[dl_path]) {
|
||||
open_dls[dl_path] = os.dylib_open(dl_path)
|
||||
}
|
||||
}
|
||||
// Pre-load the manifest
|
||||
load_package_manifest(pkg)
|
||||
}
|
||||
|
||||
// Resolve a C symbol by searching:
|
||||
// 1. If package_context is null, only check core internal symbols
|
||||
// 2. Otherwise: own package (internal then dylib) -> other packages (internal then dylib) -> core (internal only)
|
||||
// 2. Otherwise: own package (internal then per-module dylib) -> aliased packages -> core (internal only)
|
||||
// Core is never loaded as a dynamic library via dlopen
|
||||
function resolve_c_symbol(path, package_context) {
|
||||
var explicit = split_explicit_package_import(path)
|
||||
var sym = null
|
||||
var dl_path = null
|
||||
var loader = null
|
||||
var _path = null
|
||||
var core_sym = null
|
||||
var canon_pkg = null
|
||||
@@ -643,10 +730,10 @@ function resolve_c_symbol(path, package_context) {
|
||||
}
|
||||
|
||||
Shop.open_package_dylib(explicit.package)
|
||||
dl_path = get_lib_path(explicit.package)
|
||||
if (open_dls[dl_path] && os.dylib_has_symbol(open_dls[dl_path], sym)) {
|
||||
loader = resolve_dylib_symbol(sym, explicit.package)
|
||||
if (loader) {
|
||||
return {
|
||||
symbol: function() { return os.dylib_symbol(open_dls[dl_path], sym) },
|
||||
symbol: loader,
|
||||
scope: SCOPE_PACKAGE,
|
||||
package: explicit.package,
|
||||
path: sym
|
||||
@@ -668,7 +755,7 @@ function resolve_c_symbol(path, package_context) {
|
||||
return null
|
||||
}
|
||||
|
||||
// 1. Check own package first (internal, then dylib)
|
||||
// 1. Check own package first (internal, then per-module dylib)
|
||||
sym = make_c_symbol(package_context, path)
|
||||
if (os.internal_exists(sym)) {
|
||||
return {
|
||||
@@ -679,11 +766,10 @@ function resolve_c_symbol(path, package_context) {
|
||||
}
|
||||
|
||||
Shop.open_package_dylib(package_context)
|
||||
dl_path = get_lib_path(package_context)
|
||||
|
||||
if (open_dls[dl_path] && os.dylib_has_symbol(open_dls[dl_path], sym)) {
|
||||
loader = resolve_dylib_symbol(sym, package_context)
|
||||
if (loader) {
|
||||
return {
|
||||
symbol: function() { return os.dylib_symbol(open_dls[dl_path], sym) },
|
||||
symbol: loader,
|
||||
scope: SCOPE_LOCAL,
|
||||
path: sym
|
||||
}
|
||||
@@ -700,7 +786,6 @@ function resolve_c_symbol(path, package_context) {
|
||||
mod_name = get_import_name(path)
|
||||
sym = make_c_symbol(canon_pkg, mod_name)
|
||||
|
||||
// Check internal first
|
||||
if (os.internal_exists(sym)) {
|
||||
return {
|
||||
symbol: function() { return os.load_internal(sym) },
|
||||
@@ -710,12 +795,11 @@ function resolve_c_symbol(path, package_context) {
|
||||
}
|
||||
}
|
||||
|
||||
// Then check dylib
|
||||
Shop.open_package_dylib(canon_pkg)
|
||||
dl_path = get_lib_path(canon_pkg)
|
||||
if (open_dls[dl_path] && os.dylib_has_symbol(open_dls[dl_path], sym)) {
|
||||
loader = resolve_dylib_symbol(sym, canon_pkg)
|
||||
if (loader) {
|
||||
return {
|
||||
symbol: function() { return os.dylib_symbol(open_dls[dl_path], sym) },
|
||||
symbol: loader,
|
||||
scope: SCOPE_PACKAGE,
|
||||
package: canon_pkg,
|
||||
path: sym
|
||||
@@ -841,20 +925,20 @@ function execute_module(info)
|
||||
var pkg = null
|
||||
|
||||
if (mod_resolve.scope < 900) {
|
||||
// Build env with runtime fns, capabilities, and use function
|
||||
file_info = Shop.file_info(mod_resolve.path)
|
||||
inject = Shop.script_inject_for(file_info)
|
||||
env = inject_env(inject)
|
||||
pkg = file_info.package
|
||||
env.use = make_use_fn(pkg)
|
||||
// Check if native dylib was resolved
|
||||
if (is_object(mod_resolve.symbol) && mod_resolve.symbol._native) {
|
||||
used = mod_resolve.symbol.value
|
||||
} else {
|
||||
// Build env with runtime fns, capabilities, and use function
|
||||
file_info = Shop.file_info(mod_resolve.path)
|
||||
inject = Shop.script_inject_for(file_info)
|
||||
env = inject_env(inject)
|
||||
pkg = file_info.package
|
||||
env.use = make_use_fn(pkg)
|
||||
|
||||
// Add C module as native context if available
|
||||
if (c_resolve.scope < 900) {
|
||||
env.native = call_c_module(c_resolve)
|
||||
// Load compiled bytecode with env
|
||||
used = mach_load(mod_resolve.symbol, env)
|
||||
}
|
||||
|
||||
// Load compiled bytecode with env
|
||||
used = mach_load(mod_resolve.symbol, env)
|
||||
} else if (c_resolve.scope < 900) {
|
||||
// C only
|
||||
used = call_c_module(c_resolve)
|
||||
@@ -876,6 +960,21 @@ function get_module(path, package_context) {
|
||||
}
|
||||
|
||||
Shop.use = function use(path, package_context) {
|
||||
// Check for embedded module (static builds)
|
||||
var embed_key = 'embedded:' + path
|
||||
var embedded = null
|
||||
var embed_env = null
|
||||
if (use_cache[embed_key]) return use_cache[embed_key]
|
||||
if (os.embedded_module) {
|
||||
embedded = os.embedded_module(path)
|
||||
if (embedded) {
|
||||
embed_env = inject_env(SHOP_DEFAULT_INJECT)
|
||||
embed_env.use = make_use_fn(package_context)
|
||||
use_cache[embed_key] = mach_load(embedded, embed_env)
|
||||
return use_cache[embed_key]
|
||||
}
|
||||
}
|
||||
|
||||
var info = resolve_module_info(path, package_context)
|
||||
if (!info) { print(`Module ${path} could not be found in ${package_context}`); disrupt }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user