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/render.cm
prosperon/_help.cm
prosperon/render.c
prosperon/ui/
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).
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
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)
log.console(`Mounted ${source} ${name ? 'as @' + name : ''}`)
}
// Unmount

View File

@@ -2,8 +2,6 @@
var os = use('os')
var io = use('cellfs')
log.console(json.encode(cell.config))
var project_name = cell.config.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, '_')
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_dir = io.realdir(obj_file)
@@ -69,7 +67,12 @@ if (os.platform() == 'macOS') {
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)
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;
cell.os = null
var dylib_ext
switch(os.platform()) {
case 'Windows': dylib_ext = '.dll'; break;
case 'Darwin': dylib_ext = '.dylib'; break;
case 'macOS': dylib_ext = '.dylib'; break;
case 'Linux': dylib_ext = '.so'; break;
}
@@ -204,34 +204,39 @@ function get_package_from_path(path) {
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
// 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 = ''
var dependencies = (config && config.dependencies) ? config.dependencies : {}
// Helper to check file existence and return result object
function check(path, pkg, isCore) {
function check(path, pkg, isCore, scope) {
if (isCore) {
try {
var blob = core_qop.read(path)
if (blob) {
// log.console("check: found in core: " + path)
return { path: path, package_name: null, isCore: true }
return { path: path, package_name: null, isCore: true, scope: scope }
}
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)) {
// log.console("check: found file: " + path)
return { path: path, package_name: pkg, isCore: false }
return { path: path, package_name: pkg, isCore: false, scope: scope }
}
return null
}
@@ -239,20 +244,20 @@ function resolve_path(requested, pkg_context, ext) {
// Step 1: current package (Local)
if (pkg_context) {
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
// Check if package is locally replaced
if (config && config.replace && config.replace[pkg_context]) {
var replace_path = config.replace[pkg_context]
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
}
} else {
// Top-level local
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
}
@@ -266,17 +271,17 @@ function resolve_path(requested, pkg_context, ext) {
if (config && config.replace && config.replace[pkg_alias]) {
var replace_path = config.replace[pkg_alias]
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
} else if (dependencies[pkg_alias]) {
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
}
// 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 res = check(implicit_path, pkg_alias, false)
var res = check(implicit_path, pkg_alias, false, SCOPE_DEPENDENCY)
if (res) return res
} else {
@@ -284,27 +289,26 @@ function resolve_path(requested, pkg_context, ext) {
if (config && config.replace && config.replace[requested]) {
var replace_path = config.replace[requested]
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
}
// Check dependencies for simple names
for (var alias in dependencies) {
if (alias == requested) {
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
}
}
// Implicit check
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
}
// Step 3: core
var core_res = check(requested + ext, null, true)
if (core_res) log.console(`resolve_path: found core ${requested}`)
var core_res = check(requested + ext, null, true, SCOPE_CORE)
return core_res
}
@@ -329,7 +333,6 @@ function get_compiled_path(resolved) {
}
var open_dl = {}
function get_c_symbol(requested, pkg_context) {
// Construct symbol name: js_x_y_z_use
var symname = `js_${requested.replace(/\//g, '_')}_use`
@@ -348,9 +351,15 @@ function get_c_symbol(requested, pkg_context) {
}
if (dl) {
try {
var sym = os.dylib_symbol(dl, symname)
if (sym) return sym
} catch(e) {}
// For local symbols, use js_local_<name>_use
var local_symname = `js_local_${requested.replace(/\//g, '_')}_use`
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) {
try {
var sym = os.dylib_symbol(dl, symname)
if (sym) return sym
if (sym) return { symbol: sym, scope: SCOPE_DEPENDENCY }
} catch(e) {}
}
}
}
// 3. Check Core (Internal)
var internal_sym = load_internal(symname)
if (internal_sym) return { symbol: internal_sym, scope: SCOPE_CORE }
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) {
var requested = file
log.console(`use: ${file}`)
// 1. Check Local
// Check for C symbol locally
// Find C symbol
var c_res = get_c_symbol(requested, current_package)
// Find Module
var mod_res = get_module(requested, current_package)
var c_mod = null
if (!current_package) {
c_mod = get_c_symbol(requested, null)
}
var resolved = null
// Check for local file
if (!current_package) {
resolved = resolve_path(requested, null, MOD_EXT)
// If we found a core module but we were looking for local, ignore it for now
if (resolved && resolved.isCore) resolved = null
}
// If we found something locally (C or Script), stop looking elsewhere
if (c_mod || resolved) {
// Proceed with local
} else {
// 2. Check Modules
// Check for C symbol in modules
// We need to guess the package name if not in a package context
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
// Decision logic
if (c_res && mod_res) {
if (c_res.scope < mod_res.scope) {
// C symbol is more specific
c_mod = c_res.symbol
resolved = null
} else if (mod_res.scope < c_res.scope) {
// Module is more specific
c_mod = null
resolved = mod_res
} else {
// Same scope - use both (C symbol as context)
c_mod = c_res.symbol
resolved = mod_res
}
}
// 3. Check Core
if (!c_mod && !resolved) {
} else if (c_res) {
c_mod = c_res.symbol
} else if (mod_res) {
resolved = mod_res
} else {
// Try embed as fallback for core
var embed_mod = use_embed(requested)
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)
@@ -452,14 +458,12 @@ globalThis.use = function use(file, ...args) {
var context = {}
if (c_mod) {
context = c_mod
log.console("use: using c_mod as context")
}
// If we have a script, run it
var ret = c_mod
if (resolved) {
log.console("use: running script " + resolved.path)
var path = resolved.path
var isCore = resolved.isCore
var module_package = resolved.package_name
@@ -523,7 +527,6 @@ globalThis.use = function use(file, ...args) {
}
ret = fn.call(context, args, $_)
log.console("use: script returned " + (typeof ret))
current_package = prev_package
loadingStack.pop()
@@ -541,12 +544,10 @@ globalThis.use = function use(file, ...args) {
}
globalThis.json = use('json')
log.console(json.encode(cell))
var time = use('time')
var st_now = time.number()
var shop = use('shop')
log.console(`use shop in ${time.number() - st_now} seconds`)
config = shop.load_config()
var default_config = {
ar_timer: 60,
@@ -565,8 +566,6 @@ cell.config = config
ENETSERVICE = config.system.net_service
REPLYTIMEOUT = config.system.reply_timeout
log.console(`config loaded in ${time.number()-st_now} seconds`)
globalThis.text = use('text')
// Load actor-specific configuration
@@ -609,8 +608,6 @@ function deepFreeze(object) {
return Object.freeze(object);
}
log.console(`stone initialized in ${time.number()-st_now} seconds`)
globalThis.stone = deepFreeze
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)
log.console(`actor registered in ${time.number()-st_now} seconds`)
if (config.system.actor_memory)
js.mem_limit(config.system.actor_memory)
@@ -1123,7 +1118,6 @@ function enet_check()
// enet_check();
var init_end = time.number()
log.console(`initialization completed in ${init_end-st_now} seconds`)
var load_program_start = time.number()
@@ -1183,10 +1177,6 @@ if (useCompiled) {
startfn = js.eval_compile(fn)
}
log.console(`program compiled in ${time.number()-load_program_start} seconds`)
var exec_start = time.number()
$_.clock(_ => {
var val = startfn($_, cell.args.arg);
@@ -1194,8 +1184,4 @@ $_.clock(_ => {
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`)
})()