From 5ac58dfbb08d2da7bf7db2c4d5cebb139cdeb673 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Sat, 6 Dec 2025 11:33:34 -0600 Subject: [PATCH] reload module --- scripts/shop.cm | 175 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 156 insertions(+), 19 deletions(-) diff --git a/scripts/shop.cm b/scripts/shop.cm index b85e2d9a..e369cfc3 100644 --- a/scripts/shop.cm +++ b/scripts/shop.cm @@ -57,6 +57,84 @@ function get_import_package(name) { return null } +Shop.file_info = function(file) { + var info = { + path: file, + is_module: false, + is_actor: false, + package: null, + name: null + } + + if (file.endsWith(MOD_EXT)) { + info.is_module = true + } else if (file.endsWith(ACTOR_EXT)) { + info.is_actor = true + } + + // Strip extension for name + var name_without_ext = file + if (info.is_module) { + name_without_ext = file.substring(0, file.length - MOD_EXT.length) + } else if (info.is_actor) { + name_without_ext = file.substring(0, file.length - ACTOR_EXT.length) + } + + // Check if file is in a package + if (file.startsWith('.cell/modules/')) { + var rest = file.substring('.cell/modules/'.length) + + // Get all packages and find which one matches this path + var packages = Shop.list_packages() + var matched_pkg = null + var matched_path = null + + for (var i = 0; i < packages.length; i++) { + var pkg = packages[i] + var parsed = Shop.parse_package(pkg) + var pkg_path = parsed.path + + if (rest.startsWith(pkg_path + '/')) { + // Found matching package - use longest match + if (!matched_pkg || pkg_path.length > matched_path.length) { + matched_pkg = pkg + matched_path = pkg_path + } + } + } + + if (matched_path) { + info.package = matched_path + var import_part = rest.substring(matched_path.length + 1) + // Strip extension from import name + if (info.is_module && import_part.endsWith(MOD_EXT)) { + import_part = import_part.substring(0, import_part.length - MOD_EXT.length) + } else if (info.is_actor && import_part.endsWith(ACTOR_EXT)) { + import_part = import_part.substring(0, import_part.length - ACTOR_EXT.length) + } + info.name = import_part + } else { + // Fallback: use first path component as package + var slash_idx = rest.indexOf('/') + if (slash_idx > 0) { + info.package = rest.substring(0, slash_idx) + var import_part = rest.substring(slash_idx + 1) + if (info.is_module && import_part.endsWith(MOD_EXT)) { + import_part = import_part.substring(0, import_part.length - MOD_EXT.length) + } else if (info.is_actor && import_part.endsWith(ACTOR_EXT)) { + import_part = import_part.substring(0, import_part.length - ACTOR_EXT.length) + } + info.name = import_part + } + } + } else { + info.package = 'local' + info.name = name_without_ext + } + + return info +} + function get_import_name(path) { var parts = path.split('/') @@ -654,22 +732,23 @@ function resolve_locator(path, ext, ctx) return null; } +function c_sym_path(path) +{ + return path.replace(/\//g, '_').replace(/\\/g, '_').replace(/\./g, '_').replace(/-/g, '_') +} + function resolve_c_symbol(path, package_context) { var local_path = package_context ? package_context : 'local' - var local_sym_base = path.replace(/\//g, '_').replace(/-/g, '_').replace(/\./g, '_') + var local_sym_base = c_sym_path(path) var local - function symbolify_path(p) { - return p.replace(/\//g, '_').replace(/-/g, '_').replace(/\./g, '_') - } - function symbol_candidates(pkg_path, mod_sym) { var variants = [] var paths = [pkg_path] if (!pkg_path.startsWith('/')) paths.push('/' + pkg_path) for (var i = 0; i < paths.length; i++) { - var candidate = `js_${symbolify_path(paths[i])}_${mod_sym}_use` + var candidate = `js_${c_sym_path(paths[i])}_${mod_sym}_use` if (variants.indexOf(candidate) < 0) variants.push(candidate) } @@ -754,7 +833,6 @@ function resolve_c_symbol(path, package_context) } } } - var core_sym = `js_${path.replace(/\//g, '_')}_use`; if (os.internal_exists(core_sym)) return { @@ -766,18 +844,13 @@ function resolve_c_symbol(path, package_context) return null } -// first looks in local -// then in dependencies -// then in core -// package_context: optional package context to resolve relative paths within -Shop.use = function(path, package_context) { +function resolve_module_info(path, package_context) { var c_resolve = resolve_c_symbol(path, package_context) || {scope:999} var mod_resolve = resolve_locator(path, '.cm', package_context) || {scope:999} - var min_scope = Math.min(c_resolve.scope, mod_resolve.scope) if (min_scope == 999) - throw new Error(`Module ${path} could not be found in ${package_context}`) + return null var resolved_path if (mod_resolve.scope != 999) resolved_path = mod_resolve.path @@ -792,8 +865,31 @@ Shop.use = function(path, package_context) { cache_key = cache_key.replace('//', '/') - if (use_cache[cache_key]) - return use_cache[cache_key] + return { + cache_key: cache_key, + c_resolve: c_resolve, + mod_resolve: mod_resolve, + min_scope: min_scope + } +} + +function get_module_cache_key(path, package_context) { + var info = resolve_module_info(path, package_context) + return info ? info.cache_key : null +} + +Shop.is_loaded = function(path, package_context) { + var cache_key = get_module_cache_key(path, package_context) + log.console(cache_key) + if (!cache_key) return false + return use_cache[cache_key] != null +} + +function execute_module(info) +{ + var c_resolve = info.c_resolve + var mod_resolve = info.mod_resolve + var cache_key = info.cache_key var used @@ -805,12 +901,36 @@ Shop.use = function(path, package_context) { used = mod_resolve.symbol.call(c_resolve.symbol(), $_) if (!used) - throw new Error(`Module ${path} via package ${package_context} returned null`) + throw new Error(`Module ${json.encode(info)} returned null`) - use_cache[cache_key] = used return used } +function get_module(path, package_context) { + var info = resolve_module_info(path, package_context) + + if (!info) + throw new Error(`Module ${path} could not be found in ${package_context}`) + + return execute_module(info) +} + +// first looks in local +// then in dependencies +// then in core +// package_context: optional package context to resolve relative paths within +Shop.use = function(path, package_context) { + var info = resolve_module_info(path, package_context) + if (!info) + throw new Error(`Module ${path} could not be found in ${package_context}`) + + if (use_cache[info.cache_key]) + return use_cache[info.cache_key] + + use_cache[info.cache_key] = execute_module(info) + return use_cache[info.cache_key] +} + Shop.resolve_locator = resolve_locator // Get cache path for a package and commit @@ -1199,6 +1319,23 @@ Shop.compile_module = function(alias) { return true } +Shop.module_reload = function(path, package) { + if (!Shop.is_loaded(path,package)) return + var info = resolve_module_info(path, package) + if (!info) return + + var cache_key = info.cache_key + log.console(`reloading ${cache_key}`) + var old = use_cache[cache_key] + var newmod = get_module(path, package) + + log.console(typeof old) + log.console(typeof newmod) + + for (var i in newmod) + old[i] = newmod[i] +} + Shop.build_package = function(package) { if (package == 'local') package = null @@ -1247,7 +1384,7 @@ Shop.build_package = function(package) var meta_path = obj_path + '.meta' ensure_dir(obj_path.substring(0, obj_path.lastIndexOf('/'))) - var safe_path = file.substring(0, file.lastIndexOf('.')).replace(/\//g, '_').replace(/\\/g, '_').replace(/\./g, '_').replace(/-/g, '_') + var safe_path = c_sym_path(file.substring(0, file.lastIndexOf('.'))) var use_name = use_prefix + safe_path + '_use' var comp_src = file var comp_obj = file + '.o'