modifications to importing
This commit is contained in:
7
cell2.md
7
cell2.md
@@ -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.
|
||||
|
||||
|
||||
@@ -187,8 +187,6 @@ function mount(source, name) {
|
||||
}
|
||||
|
||||
mounts.push(mount_info)
|
||||
|
||||
log.console(`Mounted ${source} ${name ? 'as @' + name : ''}`)
|
||||
}
|
||||
|
||||
// Unmount
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`)
|
||||
|
||||
})()
|
||||
Reference in New Issue
Block a user