modifications to importing

This commit is contained in:
2025-11-29 18:34:37 -06:00
parent 0ddbc3e953
commit 1d295d11e5
4 changed files with 90 additions and 96 deletions

View File

@@ -19,11 +19,18 @@ prosperon/
prosperon/sprite.cm prosperon/sprite.cm
prosperon/render.cm prosperon/render.cm
prosperon/_help.cm prosperon/_help.cm
prosperon/render.c
prosperon/ui/ prosperon/ui/
prosperon/ui/button.cm prosperon/ui/button.cm
sprite.cm can use(render); but an outside package must use(prosperon/render). sprite can use(help), but an outside package cannot use(prosperon/help). sprite.cm can use(render); but an outside package must use(prosperon/render). sprite can use(help), but an outside package cannot use(prosperon/help).
A file like render.c above will be compiled into a dynamic library for the target platform (ie, on macos a .dylib), named the name of the package, 'prosperon.dylib'. For a local package, it will be local.dylib.
In the case above, the js_prosperon_render_use function will be found in the prosperon.dylib, and the result of that will be passed to render.cm as 'this', allowing for trivial extension.
If a C function OR a .cm file is found for a particular import, searching stops, preventing, for example, accidentally applying a .cm file from a local find to a package that has one which is similarly named.
### Importing packages ### Importing packages
Each package has a list of packages it depends on. They can use their own naming convention for them. Packages are imported from URLs, so, gitea.pockle.world/john/prosperon imports 'prosperon'; but, when importing, you can say, 'renderer = gitea.pockle.world/john/prosperon', and that means you can use(renderer/sprite), etc. Each package has a list of packages it depends on. They can use their own naming convention for them. Packages are imported from URLs, so, gitea.pockle.world/john/prosperon imports 'prosperon'; but, when importing, you can say, 'renderer = gitea.pockle.world/john/prosperon', and that means you can use(renderer/sprite), etc.

View File

@@ -187,8 +187,6 @@ function mount(source, name) {
} }
mounts.push(mount_info) mounts.push(mount_info)
log.console(`Mounted ${source} ${name ? 'as @' + name : ''}`)
} }
// Unmount // Unmount

View File

@@ -2,8 +2,6 @@
var os = use('os') var os = use('os')
var io = use('cellfs') var io = use('cellfs')
log.console(json.encode(cell.config))
var project_name = cell.config.project.name var project_name = cell.config.project.name
if (!project_name) { if (!project_name) {
@@ -29,7 +27,7 @@ for (var i = 0; i < files.length; i++) {
var safe_path = path_no_ext.replace(/\//g, '_').replace(/\\/g, '_') var safe_path = path_no_ext.replace(/\//g, '_').replace(/\\/g, '_')
if (safe_path.startsWith('._')) safe_path = safe_path.substring(2) if (safe_path.startsWith('._')) safe_path = safe_path.substring(2)
var use_name = 'js_' + project_name + '_' + safe_path + '_use' var use_name = 'js_local_' + safe_path + '_use'
var obj_file = '.cell/build/' + file + '.o' var obj_file = '.cell/build/' + file + '.o'
var obj_dir = io.realdir(obj_file) var obj_dir = io.realdir(obj_file)
@@ -69,7 +67,12 @@ if (os.platform() == 'macOS') {
lib_ext = '.dll' lib_ext = '.dll'
} }
var lib_name = project_name + lib_ext // Ensure .cell/local exists
if (!io.exists('.cell/local')) {
io.mkdir('.cell/local')
}
var lib_name = '.cell/local/local' + lib_ext
log.console("Linking " + lib_name) log.console("Linking " + lib_name)
var link_cmd = 'cc ' + link_flags + ' ' + objects.join(' ') + ' -lcell -o ' + lib_name var link_cmd = 'cc ' + link_flags + ' ' + objects.join(' ') + ' -lcell -o ' + lib_name

View File

@@ -8,11 +8,11 @@ var hidden = cell.hidden
var os = hidden.os; var os = hidden.os;
cell.os = null cell.os = null
var dylib_ext var dylib_ext
switch(os.platform()) { switch(os.platform()) {
case 'Windows': dylib_ext = '.dll'; break; case 'Windows': dylib_ext = '.dll'; break;
case 'Darwin': dylib_ext = '.dylib'; break; case 'macOS': dylib_ext = '.dylib'; break;
case 'Linux': dylib_ext = '.so'; break; case 'Linux': dylib_ext = '.so'; break;
} }
@@ -204,34 +204,39 @@ function get_package_from_path(path) {
return null return null
} }
// Config is loaded later, but we need to access it in resolve_module_path
// This will be set after shop.load_config() is called
var config = null var config = null
// Unified path resolution function
// Unified path resolution function
function resolve_path(requested, pkg_context, ext) {
// Scope definitions
var SCOPE_LOCAL = 0
var SCOPE_DEPENDENCY = 1
var SCOPE_CORE = 2
function resolve_path(requested, pkg_context, ext) {
if (requested.endsWith(ext)) ext = '' if (requested.endsWith(ext)) ext = ''
var dependencies = (config && config.dependencies) ? config.dependencies : {} var dependencies = (config && config.dependencies) ? config.dependencies : {}
// Helper to check file existence and return result object // Helper to check file existence and return result object
function check(path, pkg, isCore) { function check(path, pkg, isCore, scope) {
if (isCore) { if (isCore) {
try { try {
var blob = core_qop.read(path) var blob = core_qop.read(path)
if (blob) { if (blob) {
// log.console("check: found in core: " + path) return { path: path, package_name: null, isCore: true, scope: scope }
return { path: path, package_name: null, isCore: true }
} }
return null return null
} catch (e) { return null } } catch (e) { return null }
} }
// Check for private files if accessing from a different package
if (pkg && current_package && pkg != current_package) {
var filename = path.substring(path.lastIndexOf('/') + 1)
if (filename.startsWith('_')) return null
}
if (fd.is_file(path)) { if (fd.is_file(path)) {
// log.console("check: found file: " + path) return { path: path, package_name: pkg, isCore: false, scope: scope }
return { path: path, package_name: pkg, isCore: false }
} }
return null return null
} }
@@ -239,20 +244,20 @@ function resolve_path(requested, pkg_context, ext) {
// Step 1: current package (Local) // Step 1: current package (Local)
if (pkg_context) { if (pkg_context) {
var pkg_path = '.cell/modules/' + pkg_context + '/' + requested + ext var pkg_path = '.cell/modules/' + pkg_context + '/' + requested + ext
var res = check(pkg_path, pkg_context, false) var res = check(pkg_path, pkg_context, false, SCOPE_LOCAL)
if (res) return res if (res) return res
// Check if package is locally replaced // Check if package is locally replaced
if (config && config.replace && config.replace[pkg_context]) { if (config && config.replace && config.replace[pkg_context]) {
var replace_path = config.replace[pkg_context] var replace_path = config.replace[pkg_context]
var full_path = replace_path + '/' + requested + ext var full_path = replace_path + '/' + requested + ext
res = check(full_path, pkg_context, false) res = check(full_path, pkg_context, false, SCOPE_LOCAL)
if (res) return res if (res) return res
} }
} else { } else {
// Top-level local // Top-level local
var project_path = requested + ext var project_path = requested + ext
var res = check(project_path, null, false) var res = check(project_path, null, false, SCOPE_LOCAL)
if (res) return res if (res) return res
} }
@@ -266,17 +271,17 @@ function resolve_path(requested, pkg_context, ext) {
if (config && config.replace && config.replace[pkg_alias]) { if (config && config.replace && config.replace[pkg_alias]) {
var replace_path = config.replace[pkg_alias] var replace_path = config.replace[pkg_alias]
var full_path = replace_path + '/' + (sub_path || pkg_alias) + ext var full_path = replace_path + '/' + (sub_path || pkg_alias) + ext
var res = check(full_path, pkg_alias, false) var res = check(full_path, pkg_alias, false, SCOPE_DEPENDENCY)
if (res) return res if (res) return res
} else if (dependencies[pkg_alias]) { } else if (dependencies[pkg_alias]) {
var dep_path = '.cell/modules/' + pkg_alias + '/' + sub_path + ext var dep_path = '.cell/modules/' + pkg_alias + '/' + sub_path + ext
var res = check(dep_path, pkg_alias, false) var res = check(dep_path, pkg_alias, false, SCOPE_DEPENDENCY)
if (res) return res if (res) return res
} }
// Also check if it's just a module in .cell/modules even if not in dependencies (implicit) // Also check if it's just a module in .cell/modules even if not in dependencies (implicit)
var implicit_path = '.cell/modules/' + requested + ext var implicit_path = '.cell/modules/' + requested + ext
var res = check(implicit_path, pkg_alias, false) var res = check(implicit_path, pkg_alias, false, SCOPE_DEPENDENCY)
if (res) return res if (res) return res
} else { } else {
@@ -284,27 +289,26 @@ function resolve_path(requested, pkg_context, ext) {
if (config && config.replace && config.replace[requested]) { if (config && config.replace && config.replace[requested]) {
var replace_path = config.replace[requested] var replace_path = config.replace[requested]
var full_path = replace_path + '/' + requested + ext var full_path = replace_path + '/' + requested + ext
var res = check(full_path, requested, false) var res = check(full_path, requested, false, SCOPE_DEPENDENCY)
if (res) return res if (res) return res
} }
// Check dependencies for simple names // Check dependencies for simple names
for (var alias in dependencies) { for (var alias in dependencies) {
if (alias == requested) { if (alias == requested) {
var dep_simple = '.cell/modules/' + alias + '/' + requested + ext var dep_simple = '.cell/modules/' + alias + '/' + requested + ext
var res = check(dep_simple, alias, false) var res = check(dep_simple, alias, false, SCOPE_DEPENDENCY)
if (res) return res if (res) return res
} }
} }
// Implicit check // Implicit check
var implicit_path = '.cell/modules/' + requested + '/' + requested + ext var implicit_path = '.cell/modules/' + requested + '/' + requested + ext
var res = check(implicit_path, requested, false) var res = check(implicit_path, requested, false, SCOPE_DEPENDENCY)
if (res) return res if (res) return res
} }
// Step 3: core // Step 3: core
var core_res = check(requested + ext, null, true) var core_res = check(requested + ext, null, true, SCOPE_CORE)
if (core_res) log.console(`resolve_path: found core ${requested}`)
return core_res return core_res
} }
@@ -329,7 +333,6 @@ function get_compiled_path(resolved) {
} }
var open_dl = {} var open_dl = {}
function get_c_symbol(requested, pkg_context) { function get_c_symbol(requested, pkg_context) {
// Construct symbol name: js_x_y_z_use // Construct symbol name: js_x_y_z_use
var symname = `js_${requested.replace(/\//g, '_')}_use` var symname = `js_${requested.replace(/\//g, '_')}_use`
@@ -348,9 +351,15 @@ function get_c_symbol(requested, pkg_context) {
} }
if (dl) { if (dl) {
try { try {
var sym = os.dylib_symbol(dl, symname) // For local symbols, use js_local_<name>_use
if (sym) return sym var local_symname = `js_local_${requested.replace(/\//g, '_')}_use`
} catch(e) {} var sym = os.dylib_symbol(dl, local_symname)
if (sym) {
return { symbol: sym, scope: SCOPE_LOCAL }
} else {
}
} catch(e) {
}
} }
} }
} }
@@ -375,65 +384,62 @@ function get_c_symbol(requested, pkg_context) {
if (dl) { if (dl) {
try { try {
var sym = os.dylib_symbol(dl, symname) var sym = os.dylib_symbol(dl, symname)
if (sym) return sym if (sym) return { symbol: sym, scope: SCOPE_DEPENDENCY }
} catch(e) {} } catch(e) {}
} }
} }
} }
// 3. Check Core (Internal)
var internal_sym = load_internal(symname)
if (internal_sym) return { symbol: internal_sym, scope: SCOPE_CORE }
return null return null
} }
function get_module(name, pkg_context) {
return resolve_path(name, pkg_context, MOD_EXT)
}
function get_actor_script(name, pkg_context) {
return resolve_path(name, pkg_context, ACTOR_EXT)
}
globalThis.use = function use(file, ...args) { globalThis.use = function use(file, ...args) {
var requested = file var requested = file
log.console(`use: ${file}`)
// 1. Check Local // Find C symbol
// Check for C symbol locally var c_res = get_c_symbol(requested, current_package)
// Find Module
var mod_res = get_module(requested, current_package)
var c_mod = null var c_mod = null
if (!current_package) {
c_mod = get_c_symbol(requested, null)
}
var resolved = null var resolved = null
// Check for local file // Decision logic
if (!current_package) { if (c_res && mod_res) {
resolved = resolve_path(requested, null, MOD_EXT) if (c_res.scope < mod_res.scope) {
// If we found a core module but we were looking for local, ignore it for now // C symbol is more specific
if (resolved && resolved.isCore) resolved = null c_mod = c_res.symbol
} resolved = null
} else if (mod_res.scope < c_res.scope) {
// If we found something locally (C or Script), stop looking elsewhere // Module is more specific
if (c_mod || resolved) { c_mod = null
// Proceed with local resolved = mod_res
} else { } else {
// 2. Check Modules // Same scope - use both (C symbol as context)
// Check for C symbol in modules c_mod = c_res.symbol
// We need to guess the package name if not in a package context resolved = mod_res
var pkg_guess = requested.split('/')[0]
c_mod = get_c_symbol(requested, pkg_guess)
if (!c_mod) {
// Check for module file
resolved = resolve_path(requested, null, MOD_EXT) // resolve_path handles module lookup if we pass null context but path has /
if (resolved && resolved.isCore) resolved = null
} }
} } else if (c_res) {
c_mod = c_res.symbol
// 3. Check Core } else if (mod_res) {
if (!c_mod && !resolved) { resolved = mod_res
} else {
// Try embed as fallback for core
var embed_mod = use_embed(requested) var embed_mod = use_embed(requested)
if (embed_mod) c_mod = embed_mod if (embed_mod) c_mod = embed_mod
var res = resolve_path(requested, null, MOD_EXT)
if (res && res.isCore) resolved = res
}
// If still nothing
if (!c_mod && !resolved) {
// Try load_internal as last resort for core C
c_mod = load_internal(`js_${requested}_use`)
} }
if (!c_mod && !resolved) if (!c_mod && !resolved)
@@ -452,14 +458,12 @@ globalThis.use = function use(file, ...args) {
var context = {} var context = {}
if (c_mod) { if (c_mod) {
context = c_mod context = c_mod
log.console("use: using c_mod as context")
} }
// If we have a script, run it // If we have a script, run it
var ret = c_mod var ret = c_mod
if (resolved) { if (resolved) {
log.console("use: running script " + resolved.path)
var path = resolved.path var path = resolved.path
var isCore = resolved.isCore var isCore = resolved.isCore
var module_package = resolved.package_name var module_package = resolved.package_name
@@ -523,7 +527,6 @@ globalThis.use = function use(file, ...args) {
} }
ret = fn.call(context, args, $_) ret = fn.call(context, args, $_)
log.console("use: script returned " + (typeof ret))
current_package = prev_package current_package = prev_package
loadingStack.pop() loadingStack.pop()
@@ -541,12 +544,10 @@ globalThis.use = function use(file, ...args) {
} }
globalThis.json = use('json') globalThis.json = use('json')
log.console(json.encode(cell))
var time = use('time') var time = use('time')
var st_now = time.number() var st_now = time.number()
var shop = use('shop') var shop = use('shop')
log.console(`use shop in ${time.number() - st_now} seconds`)
config = shop.load_config() config = shop.load_config()
var default_config = { var default_config = {
ar_timer: 60, ar_timer: 60,
@@ -565,8 +566,6 @@ cell.config = config
ENETSERVICE = config.system.net_service ENETSERVICE = config.system.net_service
REPLYTIMEOUT = config.system.reply_timeout REPLYTIMEOUT = config.system.reply_timeout
log.console(`config loaded in ${time.number()-st_now} seconds`)
globalThis.text = use('text') globalThis.text = use('text')
// Load actor-specific configuration // Load actor-specific configuration
@@ -609,8 +608,6 @@ function deepFreeze(object) {
return Object.freeze(object); return Object.freeze(object);
} }
log.console(`stone initialized in ${time.number()-st_now} seconds`)
globalThis.stone = deepFreeze globalThis.stone = deepFreeze
stone.p = function(object) stone.p = function(object)
{ {
@@ -997,8 +994,6 @@ load_actor_config(cell.args.program)
actor_mod.register_actor(cell.id, turn, cell.args.main, config.system.ar_timer) actor_mod.register_actor(cell.id, turn, cell.args.main, config.system.ar_timer)
log.console(`actor registered in ${time.number()-st_now} seconds`)
if (config.system.actor_memory) if (config.system.actor_memory)
js.mem_limit(config.system.actor_memory) js.mem_limit(config.system.actor_memory)
@@ -1123,7 +1118,6 @@ function enet_check()
// enet_check(); // enet_check();
var init_end = time.number() var init_end = time.number()
log.console(`initialization completed in ${init_end-st_now} seconds`)
var load_program_start = time.number() var load_program_start = time.number()
@@ -1183,10 +1177,6 @@ if (useCompiled) {
startfn = js.eval_compile(fn) startfn = js.eval_compile(fn)
} }
log.console(`program compiled in ${time.number()-load_program_start} seconds`)
var exec_start = time.number()
$_.clock(_ => { $_.clock(_ => {
var val = startfn($_, cell.args.arg); var val = startfn($_, cell.args.arg);
@@ -1194,8 +1184,4 @@ $_.clock(_ => {
throw new Error('Program must not return anything'); throw new Error('Program must not return anything');
}) })
log.console(`program queued in ${time.number()-exec_start} seconds`)
log.console(`program executed in ${time.number()-st_now} seconds`)
})() })()