rm js fns

This commit is contained in:
2026-01-16 17:44:14 -06:00
parent ac91495679
commit b46406f755
42 changed files with 1954 additions and 2335 deletions

10
add.ce
View File

@@ -25,7 +25,7 @@ for (var i = 0; i < args.length; i++) {
log.console(" cell add gitea.pockle.world/john/cell-image image")
log.console(" cell add ../local-package")
$stop()
} else if (!args[i].startsWith('-')) {
} else if (!starts_with(args[i], '-')) {
if (!locator) {
locator = args[i]
} else if (!alias) {
@@ -40,7 +40,7 @@ if (!locator) {
}
// Resolve relative paths to absolute paths
if (locator == '.' || locator.startsWith('./') || locator.startsWith('../') || fd.is_dir(locator)) {
if (locator == '.' || starts_with(locator, './') || starts_with(locator, '../') || fd.is_dir(locator)) {
var resolved = fd.realpath(locator)
if (resolved) {
locator = resolved
@@ -50,11 +50,11 @@ if (locator == '.' || locator.startsWith('./') || locator.startsWith('../') || f
// Generate default alias from locator
if (!alias) {
// Use the last component of the locator as alias
var parts = locator.split('/')
var parts = array(locator, '/')
alias = parts[parts.length - 1]
// Remove any version suffix
if (alias.includes('@')) {
alias = alias.split('@')[0]
if (search(alias, '@') != null) {
alias = array(alias, '@')[0]
}
}

View File

@@ -115,7 +115,7 @@ function parse_args() {
var lock = shop.load_lock()
if (lock[name]) {
target_pkg = name
} else if (name.startsWith('/') && testlib.is_valid_package(name)) {
} else if (starts_with(name, '/') && testlib.is_valid_package(name)) {
target_pkg = name
} else {
if (testlib.is_valid_package('.')) {
@@ -144,7 +144,7 @@ function parse_args() {
var bench_path = args[0]
// Normalize path - add benches/ prefix if not present
if (!bench_path.startsWith('benches/') && !bench_path.startsWith('/')) {
if (!starts_with(bench_path, 'benches/') && !starts_with(bench_path, '/')) {
if (!fd.is_file(bench_path + '.cm') && !fd.is_file(bench_path)) {
if (fd.is_file('benches/' + bench_path + '.cm') || fd.is_file('benches/' + bench_path)) {
bench_path = 'benches/' + bench_path
@@ -179,12 +179,12 @@ function collect_benches(package_name, specific_bench) {
var bench_files = []
for (var i = 0; i < files.length; i++) {
var f = files[i]
if (f.startsWith("benches/") && f.endsWith(".cm")) {
if (starts_with(f, "benches/") && ends_with(f, ".cm")) {
if (specific_bench) {
var bench_name = f.substring(0, f.length - 3)
var bench_name = text(f, 0, -3)
var match_name = specific_bench
if (!match_name.startsWith('benches/')) match_name = 'benches/' + match_name
var match_base = match_name.endsWith('.cm') ? match_name.substring(0, match_name.length - 3) : match_name
if (!starts_with(match_name, 'benches/')) match_name = 'benches/' + match_name
var match_base = ends_with(match_name, '.cm') ? text(match_name, 0, -3) : match_name
if (bench_name != match_base) continue
}
bench_files.push(f)
@@ -427,7 +427,7 @@ function run_benchmarks(package_name, specific_bench) {
for (var i = 0; i < bench_files.length; i++) {
var f = bench_files[i]
var mod_path = f.substring(0, f.length - 3)
var mod_path = text(f, 0, -3)
var file_result = {
name: f,

View File

@@ -211,7 +211,7 @@ function benchStringOps() {
var splitTime = measureTime(function() {
var str = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p";
for (var i = 0; i < iterations.medium; i++) {
var parts = str.split(",");
var parts = array(str, ",");
}
});

View File

@@ -43,7 +43,7 @@ for (var i = 0; i < 100; i++) {
// Calculate statistics
function getStats(arr) {
def avg = arr.reduce((a, b) => a + b) / arr.length;
def avg = reduce(arr, (a,b) => a+b, 0) / length(arr)
def min = min(...arr);
def max = max(...arr);
return { avg, min, max };

View File

@@ -166,18 +166,18 @@ function runBenchmarkForLibrary(lib, bench) {
////////////////////////////////////////////////////////////////////////////////
// Find the requested library and scenario
var lib = libraries.find(l => l.name == lib_name);
var bench = benchmarks.find(b => b.name == scenario_name);
var lib = libraries[find(libraries, l => l.name == lib_name)];
var bench = benchmarks[find(benchmarks, b => b.name == scenario_name)];
if (!lib) {
log.console('Unknown library:', lib_name);
log.console('Available libraries:', text(libraries.map(l => l.name), ', '));
log.console('Available libraries:', text(array(libraries, l => l.name), ', '));
$stop()
}
if (!bench) {
log.console('Unknown scenario:', scenario_name);
log.console('Available scenarios:', text(benchmarks.map(b => b.name), ', '));
log.console('Available scenarios:', text(array(benchmarks, b => b.name), ', '));
$stop()
}

View File

@@ -56,7 +56,7 @@ for (var i = 0; i < args.length; i++) {
log.console(' ' + targets[t])
}
$stop()
} else if (!args[i].startsWith('-') && !target_package) {
} else if (!starts_with(args[i], '-') && !target_package) {
// Positional argument - treat as package locator
target_package = args[i]
}
@@ -64,7 +64,7 @@ for (var i = 0; i < args.length; i++) {
// Resolve local paths to absolute paths
if (target_package) {
if (target_package == '.' || target_package.startsWith('./') || target_package.startsWith('../') || fd.is_dir(target_package)) {
if (target_package == '.' || starts_with(target_package, './') || starts_with(target_package, '../') || fd.is_dir(target_package)) {
var resolved = fd.realpath(target_package)
if (resolved) {
target_package = resolved

View File

@@ -83,8 +83,8 @@ function get_build_dir() {
function ensure_dir(path) {
if (fd.stat(path).isDirectory) return
var parts = path.split('/')
var current = path.startsWith('/') ? '/' : ''
var parts = array(path, '/')
var current = starts_with(path, '/') ? '/' : ''
for (var i = 0; i < parts.length; i++) {
if (parts[i] == '') continue
current += parts[i] + '/'
@@ -136,8 +136,8 @@ Build.compile_file = function(pkg, file, target, buildtype = 'release') {
// Add package CFLAGS (resolve relative -I paths)
for (var i = 0; i < cflags.length; i++) {
var flag = cflags[i]
if (flag.startsWith('-I') && !flag.startsWith('-I/')) {
flag = '-I"' + pkg_dir + '/' + flag.substring(2) + '"'
if (starts_with(flag, '-I') && !starts_with(flag, '-I/')) {
flag = '-I"' + pkg_dir + '/' + text(flag, 2) + '"'
}
cmd_parts.push(flag)
}
@@ -149,7 +149,7 @@ Build.compile_file = function(pkg, file, target, buildtype = 'release') {
cmd_parts.push('"' + src_path + '"')
var cmd_str = cmd_parts.join(' ')
var cmd_str = text(cmd_parts, ' ')
// Content hash: command + file content
var file_content = fd.slurp(src_path)
@@ -250,8 +250,8 @@ Build.build_dynamic = function(pkg, target = Build.detect_host_target(), buildty
var resolved_ldflags = []
for (var i = 0; i < ldflags.length; i++) {
var flag = ldflags[i]
if (flag.startsWith('-L') && !flag.startsWith('-L/')) {
flag = '-L"' + pkg_dir + '/' + flag.substring(2) + '"'
if (starts_with(flag, '-L') && !starts_with(flag, '-L/')) {
flag = '-L"' + pkg_dir + '/' + text(flag, 2) + '"'
}
resolved_ldflags.push(flag)
}
@@ -324,7 +324,7 @@ Build.build_dynamic = function(pkg, target = Build.detect_host_target(), buildty
cmd_parts.push('-o', '"' + store_path + '"')
var cmd_str = cmd_parts.join(' ')
var cmd_str = text(cmd_parts, ' ')
log.console('Linking ' + lib_name + dylib_ext)
var ret = os.system(cmd_str)
@@ -378,8 +378,8 @@ Build.build_static = function(packages, target = Build.detect_host_target(), out
for (var j = 0; j < ldflags.length; j++) {
var flag = ldflags[j]
// Resolve relative -L paths
if (flag.startsWith('-L') && !flag.startsWith('-L/')) {
flag = '-L"' + pkg_dir + '/' + flag.substring(2) + '"'
if (starts_with(flag, '-L') && !starts_with(flag, '-L/')) {
flag = '-L"' + pkg_dir + '/' + text(flag, 2) + '"'
}
all_ldflags.push(flag)
}
@@ -395,7 +395,7 @@ Build.build_static = function(packages, target = Build.detect_host_target(), out
var target_ldflags = toolchains[target].c_link_args || []
var exe_ext = toolchains[target].system == 'windows' ? '.exe' : ''
if (!output.endsWith(exe_ext) && exe_ext) {
if (!ends_with(output, exe_ext) && exe_ext) {
output = output + exe_ext
}
@@ -415,7 +415,7 @@ Build.build_static = function(packages, target = Build.detect_host_target(), out
cmd_parts.push('-o', '"' + output + '"')
var cmd_str = cmd_parts.join(' ')
var cmd_str = text(cmd_parts, ' ')
log.console('Linking ' + output)
var ret = os.system(cmd_str)
@@ -439,7 +439,7 @@ Build.build_all_dynamic = function(target, buildtype = 'release') {
var results = []
// Build core first
if (packages.indexOf('core') >= 0) {
if (find(packages, 'core') != null) {
try {
var lib = Build.build_dynamic('core', target, buildtype)
results.push({ package: 'core', library: lib })

View File

@@ -24,14 +24,14 @@ function normalize_path(path) {
function dirname(path) {
var idx = path.lastIndexOf("/")
if (idx == -1) return ""
return path.substring(0, idx)
return text(path, 0, idx)
}
// Helper to get basename from path
function basename(path) {
var idx = path.lastIndexOf("/")
if (idx == -1) return path
return path.substring(idx + 1)
return text(path, idx + 1)
}
// Helper to join paths
@@ -102,17 +102,17 @@ function resolve(path, must_exist) {
path = normalize_path(path)
// Check for named mount
if (path.startsWith("@")) {
if (starts_with(path, "@")) {
var idx = path.indexOf("/")
var mount_name = ""
var rel_path = ""
if (idx == -1) {
mount_name = path.substring(1)
mount_name = text(path, 1)
rel_path = ""
} else {
mount_name = path.substring(1, idx)
rel_path = path.substring(idx + 1)
mount_name = text(path, 1, idx)
rel_path = text(path, idx + 1)
}
// Find named mount
@@ -229,7 +229,7 @@ function slurpwrite(path, data) {
// Check existence
function exists(path) {
var res = resolve(path, false)
if (path.startsWith("@")) {
if (starts_with(path, "@")) {
return mount_exists(res.mount, res.path)
}
return res != null
@@ -365,14 +365,14 @@ function enumerate(path, recurse) {
var seen = {}
for (var p of all) {
if (p.startsWith(prefix)) {
var rel = p.substring(prefix_len)
if (starts_with(p, prefix)) {
var rel = text(p, prefix_len)
if (rel.length == 0) continue
if (!recurse) {
var slash = rel.indexOf('/')
if (slash != -1) {
rel = rel.substring(0, slash)
rel = text(rel, 0, slash)
}
}
@@ -394,14 +394,14 @@ function globfs(globs, dir) {
function check_neg(path) {
for (var g of globs) {
if (g.startsWith("!") && wildstar.match(g.substring(1), path, wildstar.WM_WILDSTAR)) return true;
if (starts_with(g, "!") && wildstar.match(text(g, 1), path, wildstar.WM_WILDSTAR)) return true;
}
return false;
}
function check_pos(path) {
for (var g of globs) {
if (!g.startsWith("!") && wildstar.match(g, path, wildstar.WM_WILDSTAR)) return true;
if (!starts_with(g, "!") && wildstar.match(g, path, wildstar.WM_WILDSTAR)) return true;
}
return false;
}
@@ -442,8 +442,8 @@ function globfs(globs, dir) {
var prefix_len = prefix.length
for (var p of all) {
if (p.startsWith(prefix)) {
var rel = p.substring(prefix_len)
if (starts_with(p, prefix)) {
var rel = text(p, prefix_len)
if (rel.length == 0) continue
if (!check_neg(rel) && check_pos(rel)) {

View File

@@ -53,7 +53,7 @@ for (var i = 0; i < args.length; i++) {
log.console(" --deep Apply to full dependency closure")
log.console(" --dry-run Show what would be deleted")
$stop()
} else if (!args[i].startsWith('-')) {
} else if (!starts_with(args[i], '-')) {
scope = args[i]
}
}
@@ -73,7 +73,7 @@ var is_shop_scope = (scope == 'shop')
var is_world_scope = (scope == 'world')
if (!is_shop_scope && !is_world_scope) {
if (scope == '.' || scope.startsWith('./') || scope.startsWith('../') || fd.is_dir(scope)) {
if (scope == '.' || starts_with(scope, './') || starts_with(scope, '../') || fd.is_dir(scope)) {
var resolved = fd.realpath(scope)
if (resolved) {
scope = resolved

View File

@@ -18,7 +18,7 @@ var origin = args[0]
var target_path = args[1]
// Resolve target path to absolute
if (target_path == '.' || target_path.startsWith('./') || target_path.startsWith('../')) {
if (target_path == '.' || starts_with(target_path, './') || starts_with(target_path, '../')) {
var resolved = fd.realpath(target_path)
if (resolved) {
target_path = resolved
@@ -27,12 +27,12 @@ if (target_path == '.' || target_path.startsWith('./') || target_path.startsWith
var cwd = fd.realpath('.')
if (target_path == '.') {
target_path = cwd
} else if (target_path.startsWith('./')) {
target_path = cwd + target_path.substring(1)
} else if (target_path.startsWith('../')) {
} else if (starts_with(target_path, './')) {
target_path = cwd + text(target_path, 1)
} else if (starts_with(target_path, '../')) {
// Go up one directory from cwd
var parent = cwd.substring(0, cwd.lastIndexOf('/'))
target_path = parent + target_path.substring(2)
var parent = text(cwd, 0, cwd.lastIndexOf('/'))
target_path = parent + text(target_path, 2)
}
}
}
@@ -92,14 +92,14 @@ try {
for (var i = 0; i < count; i++) {
if (zip.is_directory(i)) continue
var filename = zip.get_filename(i)
var parts = filename.split('/')
var parts = array(filename, '/')
if (parts.length <= 1) continue
// Skip the first directory (repo-commit prefix)
parts.shift()
var rel_path = text(parts, '/')
var full_path = target_path + '/' + rel_path
var dir_path = full_path.substring(0, full_path.lastIndexOf('/'))
var dir_path = text(full_path, 0, full_path.lastIndexOf('/'))
// Ensure directory exists
if (!fd.is_dir(dir_path)) {

View File

@@ -31,7 +31,7 @@ function print_help() {
// Parse a dot-notation key into path segments
function parse_key(key) {
return key.split('.')
return array(key, '.')
}
// Get a value from nested object using path
@@ -161,7 +161,7 @@ switch (command) {
'ar_timer', 'actor_memory', 'net_service',
'reply_timeout', 'actor_max', 'stack_max'
]
if (!valid_system_keys.includes(path[1])) {
if (find(valid_system_keys, path[1]) == null) {
log.error("Invalid system key. Valid keys: " + text(valid_system_keys, ', '))
$stop()
return

4
fd.cm
View File

@@ -16,14 +16,14 @@ fd.globfs = function(globs, dir) {
function check_neg(path) {
for (var g of globs) {
if (g.startsWith("!") && wildstar.match(g.substring(1), path, wildstar.WM_WILDSTAR)) return true;
if (starts_with(g, "!") && wildstar.match(text(g, 1), path, wildstar.WM_WILDSTAR)) return true;
}
return false;
}
function check_pos(path) {
for (var g of globs) {
if (!g.startsWith("!") && wildstar.match(g, path, wildstar.WM_WILDSTAR)) return true;
if (!starts_with(g, "!") && wildstar.match(g, path, wildstar.WM_WILDSTAR)) return true;
}
return false;
}

View File

@@ -24,7 +24,7 @@ for (var i = 0; i < args.length; i++) {
log.console("This command ensures that the zip files on disk match what's in")
log.console("the lock file. For local packages, this is a no-op.")
$stop()
} else if (!args[i].startsWith('-')) {
} else if (!starts_with(args[i], '-')) {
target_pkg = args[i]
}
}
@@ -35,7 +35,7 @@ var packages_to_fetch = []
if (target_pkg) {
// Fetch specific package
if (!all_packages.includes(target_pkg)) {
if (find(all_packages, target_pkg) == null) {
log.error("Package not found: " + target_pkg)
$stop()
}

View File

@@ -52,7 +52,7 @@ for (var i = 0; i < args.length; i++) {
log.console(" --locked Show lock view without links")
log.console(" --world Graph all packages in shop")
$stop()
} else if (!args[i].startsWith('-')) {
} else if (!starts_with(args[i], '-')) {
target_locator = args[i]
}
}
@@ -81,7 +81,7 @@ function add_node(locator) {
effective: get_effective(locator),
linked: link_target != null,
local: info == 'local',
commit: lock_entry && lock_entry.commit ? lock_entry.commit.substring(0, 8) : null
commit: lock_entry && lock_entry.commit ? text(lock_entry.commit, 0, 8) : null
}
}
@@ -124,7 +124,7 @@ if (show_world) {
}
// Resolve local paths
if (target_locator == '.' || target_locator.startsWith('./') || target_locator.startsWith('../') || fd.is_dir(target_locator)) {
if (target_locator == '.' || starts_with(target_locator, './') || starts_with(target_locator, '../') || fd.is_dir(target_locator)) {
var resolved = fd.realpath(target_locator)
if (resolved) {
target_locator = resolved

View File

@@ -51,7 +51,7 @@ for (var i = 0; i < args.length; i++) {
log.console(" --refresh Refresh floating refs before locking")
log.console(" --dry-run Show what would be installed")
$stop()
} else if (!args[i].startsWith('-')) {
} else if (!starts_with(args[i], '-')) {
locator = args[i]
}
}
@@ -63,7 +63,7 @@ if (!locator) {
// Resolve relative paths to absolute paths
// Local paths like '.' or '../foo' need to be converted to absolute paths
if (locator == '.' || locator.startsWith('./') || locator.startsWith('../') || fd.is_dir(locator)) {
if (locator == '.' || starts_with(locator, './') || starts_with(locator, '../') || fd.is_dir(locator)) {
var resolved = fd.realpath(locator)
if (resolved) {
locator = resolved
@@ -87,7 +87,7 @@ function gather_packages(pkg_locator) {
visited[pkg_locator] = true
// Check if this is a local path that doesn't exist
if (pkg_locator.startsWith('/') && !fd.is_dir(pkg_locator)) {
if (starts_with(pkg_locator, '/') && !fd.is_dir(pkg_locator)) {
skipped_packages.push(pkg_locator)
log.console(" Skipping missing local package: " + pkg_locator)
return

View File

@@ -37,6 +37,22 @@ globalThis.logical = function(val1)
return null;
}
globalThis.some = function(arr, pred) {
return find(arr, pred) != null
}
globalThis.every = function(arr, pred) {
return find(arr, x => not(pred(x))) == null
}
globalThis.starts_with = function(str, prefix) {
return search(str, prefix) == 0
}
globalThis.ends_with = function(str, suffix) {
return search(str, suffix, -length(suffix)) != null
}
var js = use_embed('js')
var fd = use_embed('fd')
@@ -104,7 +120,7 @@ function caller_data(depth = 0)
var file = "nofile"
var line = 0
var caller = Error().stack.split("\n")[1+depth]
var caller = array(Error().stack, "\n")[1+depth]
if (caller) {
var md = caller.match(/\((.*)\:/)
var m = md ? md[1] : "SCRIPT"
@@ -778,7 +794,7 @@ $_.clock(_ => {
var vals = []
for (var i = 0; i < inject.length; i++) {
var key = inject[i]
if (key && key[0] == '$') key = key.substring(1)
if (key && key[0] == '$') key = text(key, 1)
if (key == 'fd') vals.push(fd)
else vals.push($_[key])
}

View File

@@ -28,8 +28,8 @@ function put_into_cache(content, obj)
function ensure_dir(path) {
if (fd.stat(path).isDirectory) return
var parts = path.split('/')
var current = path.startsWith('/') ? '/' : ''
var parts = array(path, '/')
var current = starts_with(path, '/') ? '/' : ''
for (var i = 0; i < parts.length; i++) {
if (parts[i] == '') continue
current += parts[i] + '/'
@@ -91,7 +91,7 @@ Shop.get_reports_dir = function() {
}
function get_import_package(name) {
var parts = name.split('/')
var parts = array(name, '/')
if (parts.length > 1)
return parts[0]
@@ -100,17 +100,17 @@ function get_import_package(name) {
function is_internal_path(path)
{
return path && path.startsWith('internal/')
return path && starts_with(path, 'internal/')
}
function split_explicit_package_import(path)
{
if (!path) return null
var parts = path.split('/')
var parts = array(path, '/')
if (parts.length < 2) return null
var looks_explicit = path.startsWith('/') || (parts[0] && parts[0].includes('.'))
var looks_explicit = starts_with(path, '/') || (parts[0] && search(parts[0], '.') != null)
if (!looks_explicit) return null
// Find the longest prefix that is an installed package
@@ -158,8 +158,8 @@ function abs_path_to_package(package_dir)
}
}
if (package_dir.startsWith(packages_prefix))
return package_dir.substring(packages_prefix.length)
if (starts_with(package_dir, packages_prefix))
return text(package_dir, packages_prefix.length)
// Check if this local path is the target of a link
// If so, return the canonical package name (link origin) instead
@@ -195,9 +195,9 @@ Shop.file_info = function(file) {
name: null
}
if (file.endsWith(MOD_EXT))
if (ends_with(file, MOD_EXT))
info.is_module = true
else if (file.endsWith(ACTOR_EXT))
else if (ends_with(file, ACTOR_EXT))
info.is_actor = true
// Find package directory and determine package name
@@ -206,11 +206,11 @@ Shop.file_info = function(file) {
info.package = abs_path_to_package(pkg_dir)
if (info.is_actor)
info.name = file.substring(pkg_dir.length + 1, file.length - ACTOR_EXT.length)
info.name = text(file, pkg_dir.length + 1, file.length - ACTOR_EXT.length)
else if (info.is_module)
info.name = file.substring(pkg_dir.length + 1, file.length - MOD_EXT.length)
info.name = text(file, pkg_dir.length + 1, file.length - MOD_EXT.length)
else
info.name = file.substring(pkg_dir.length + 1)
info.name = text(file, pkg_dir.length + 1)
}
return info
@@ -218,7 +218,7 @@ Shop.file_info = function(file) {
function get_import_name(path)
{
var parts = path.split('/')
var parts = array(path, '/')
if (parts.length < 2) return null
return text(array(parts, 1), '/')
}
@@ -246,7 +246,7 @@ function safe_package_path(pkg)
{
// For absolute paths, replace / with _ to create a valid directory name
// Also replace @ with _
if (pkg && pkg.startsWith('/'))
if (pkg && starts_with(pkg, '/'))
return pkg.replaceAll('/', '_').replaceAll('@', '_')
return pkg.replaceAll('@', '_')
}
@@ -290,8 +290,8 @@ Shop.save_lock = function(lock) {
// Get information about how to resolve a package
// Local packages always start with /
Shop.resolve_package_info = function(pkg) {
if (pkg.startsWith('/')) return 'local'
if (pkg.includes('gitea')) return 'gitea'
if (starts_with(pkg, '/')) return 'local'
if (search(pkg, 'gitea') != null) return 'gitea'
return null
}
@@ -301,8 +301,8 @@ Shop.verify_package_name = function(pkg) {
if (pkg == 'local') throw Error("local is not a valid package name")
if (pkg == 'core') throw Error("core is not a valid package name")
if (pkg.includes('://'))
throw Error(`Invalid package name: ${pkg}; did you mean ${pkg.split('://')[1]}?`)
if (search(pkg, '://') != null)
throw Error(`Invalid package name: ${pkg}; did you mean ${array(pkg, '://')[1]}?`)
}
// Convert module package to download URL
@@ -310,7 +310,7 @@ Shop.get_download_url = function(pkg, commit_hash) {
var info = Shop.resolve_package_info(pkg)
if (info == 'gitea') {
var parts = pkg.split('/')
var parts = array(pkg, '/')
var host = parts[0]
var user = parts[1]
var repo = parts[2]
@@ -326,7 +326,7 @@ Shop.get_api_url = function(pkg) {
var info = Shop.resolve_package_info(pkg)
if (info == 'gitea') {
var parts = pkg.split('/')
var parts = array(pkg, '/')
var host = parts[0]
var user = parts[1]
var repo = parts[2]
@@ -361,7 +361,7 @@ var open_dls = {}
var SHOP_DEFAULT_INJECT = ['$self', '$overling', '$clock', '$delay', '$start', '$receiver', '$contact', '$portal', '$time_limit', '$couple', '$stop', '$unneeded', '$connection', '$fd']
function strip_dollar(name) {
if (name && name[0] == '$') return name.substring(1)
if (name && name[0] == '$') return text(name, 1)
return name
}
@@ -470,7 +470,7 @@ function resolve_locator(path, ctx)
// If ctx is an absolute path (starts with /), use it directly
// Otherwise, look it up in the packages directory
var ctx_dir
if (ctx.startsWith('/')) {
if (starts_with(ctx, '/')) {
ctx_dir = ctx
} else {
ctx_dir = get_packages_dir() + '/' + safe_package_path(ctx)
@@ -541,7 +541,7 @@ Shop.open_package_dylib = function(pkg) {
var resolved_pkg = link_target ? link_target : pkg
var pkg_dir;
if (resolved_pkg.startsWith('/')) {
if (starts_with(resolved_pkg, '/')) {
pkg_dir = resolved_pkg
} else {
pkg_dir = get_packages_dir() + '/' + safe_package_path(resolved_pkg)
@@ -990,7 +990,7 @@ Shop.extract = function(pkg) {
if (lock_entry && lock_entry.commit) {
var extracted_commit_file = target_dir + '/.cell_commit'
if (fd.is_file(extracted_commit_file)) {
var extracted_commit = text(fd.slurp(extracted_commit_file)).trim()
var extracted_commit = trim(text(fd.slurp(extracted_commit_file)))
if (extracted_commit == lock_entry.commit) {
// Already extracted at this commit, skip
return true
@@ -1100,13 +1100,13 @@ function install_zip(zip_blob, target_dir) {
for (var i = 0; i < count; i++) {
if (zip.is_directory(i)) continue
var filename = zip.get_filename(i)
var parts = filename.split('/')
var parts = array(filename, '/')
if (parts.length <= 1) continue
parts.shift()
var rel_path = text(parts, '/')
var full_path = target_dir + '/' + rel_path
var dir_path = full_path.substring(0, full_path.lastIndexOf('/'))
var dir_path = text(full_path, 0, full_path.lastIndexOf('/'))
if (!created_dirs[dir_path]) {
ensure_dir(dir_path)
@@ -1203,7 +1203,7 @@ function get_package_scripts(package)
for (var i = 0; i < files.length; i++) {
var file = files[i]
if (file.endsWith('.cm') || file.endsWith('.ce')) {
if (ends_with(file, '.cm') || ends_with(file, '.ce')) {
scripts.push(file)
}
}
@@ -1251,7 +1251,7 @@ Shop.get_package_dir = function(pkg) {
// -> 'js_gitea_pockle_world_john_prosperon_sprite_use'
Shop.c_symbol_for_file = function(pkg, file) {
var pkg_safe = pkg.replaceAll(/\//g, '_').replaceAll(/\./g, '_').replaceAll(/-/g, '_')
var file_safe = file.substring(0, file.lastIndexOf('.')).replaceAll(/\//g, '_').replaceAll(/\./g, '_').replaceAll(/-/g, '_')
var file_safe = text(file, 0, file.lastIndexOf('.')).replaceAll(/\//g, '_').replaceAll(/\./g, '_').replaceAll(/-/g, '_')
return 'js_' + pkg_safe + '_' + file_safe + '_use'
}
@@ -1291,15 +1291,15 @@ Shop.parse_package = function(locator) {
// Strip version suffix if present
var clean = locator
if (locator.includes('@')) {
clean = locator.split('@')[0]
if (search(locator, '@') != null) {
clean = array(locator, '@')[0]
}
var info = Shop.resolve_package_info(clean)
if (!info) return null
// Extract package name (last component of path)
var parts = clean.split('/')
var parts = array(clean, '/')
var name = parts[parts.length - 1]
return {

View File

@@ -24,7 +24,7 @@ function get_pkg_dir(package_name) {
if (!package_name) {
return fd.realpath('.')
}
if (package_name.startsWith('/')) {
if (starts_with(package_name, '/')) {
return package_name
}
var shop = use('internal/shop')
@@ -35,8 +35,8 @@ function get_pkg_dir(package_name) {
function ensure_dir(path) {
if (fd.is_dir(path)) return true
var parts = path.split('/')
var current = path.startsWith('/') ? '/' : ''
var parts = array(path, '/')
var current = starts_with(path, '/') ? '/' : ''
for (var i = 0; i < parts.length; i++) {
if (parts[i] == '') continue
current += parts[i] + '/'

10
link.ce
View File

@@ -108,11 +108,11 @@ if (cmd == 'list') {
// Resolve target if it's a local path
if (target == '.' || fd.is_dir(target)) {
target = fd.realpath(target)
} else if (target.startsWith('./') || target.startsWith('../')) {
} else if (starts_with(target, './') || starts_with(target, '../')) {
// Relative path that doesn't exist yet - try to resolve anyway
var cwd = fd.realpath('.')
if (target.startsWith('./')) {
target = cwd + target.substring(1)
if (starts_with(target, './')) {
target = cwd + text(target, 1)
} else {
// For ../ paths, var fd.realpath handle it if possible
target = fd.realpath(target) || target
@@ -127,7 +127,7 @@ if (cmd == 'list') {
// Resolve path
if (target == '.' || fd.is_dir(target)) {
target = fd.realpath(target)
} else if (target.startsWith('./') || target.startsWith('../')) {
} else if (starts_with(target, './') || starts_with(target, '../')) {
target = fd.realpath(target) || target
}
@@ -158,7 +158,7 @@ if (cmd == 'list') {
}
// Validate: if target is a local path, it must have cell.toml
if (target.startsWith('/')) {
if (starts_with(target, '/')) {
if (!fd.is_file(target + '/cell.toml')) {
log.console("Error: " + target + " is not a valid package (no cell.toml)")
$stop()

18
link.cm
View File

@@ -21,7 +21,7 @@ function get_packages_dir() {
// return the safe path for the package
function safe_package_path(pkg) {
// For absolute paths, replace / with _ to create a valid directory name
if (pkg && pkg.startsWith('/'))
if (pkg && starts_with(pkg, '/'))
return pkg.replaceAll('/', '_').replaceAll('@', '_')
return pkg.replaceAll('@', '_')
}
@@ -32,8 +32,8 @@ function get_package_abs_dir(package) {
function ensure_dir(path) {
if (fd.stat(path).isDirectory) return
var parts = path.split('/')
var current = path.startsWith('/') ? '/' : ''
var parts = array(path, '/')
var current = starts_with(path, '/') ? '/' : ''
for (var i = 0; i < parts.length; i++) {
if (parts[i] == '') continue
current += parts[i] + '/'
@@ -47,7 +47,7 @@ function ensure_dir(path) {
// If target is a local path (starts with /), return it directly
// If target is a package name, return the package directory
function resolve_link_target(target) {
if (target.startsWith('/')) {
if (starts_with(target, '/')) {
return target
}
// Target is another package - resolve to its directory
@@ -94,7 +94,7 @@ Link.add = function(canonical, target, shop) {
}
// Validate target is a valid package
if (target.startsWith('/')) {
if (starts_with(target, '/')) {
// Local path - must have cell.toml
if (!fd.is_file(target + '/cell.toml')) {
throw Error('Target ' + target + ' is not a valid package (no cell.toml)')
@@ -113,7 +113,7 @@ Link.add = function(canonical, target, shop) {
// Install dependencies of the linked package
// Read the target's cell.toml to find its dependencies
var target_path = target.startsWith('/') ? target : get_package_abs_dir(target)
var target_path = starts_with(target, '/') ? target : get_package_abs_dir(target)
var toml_path = target_path + '/cell.toml'
if (fd.is_file(toml_path)) {
try {
@@ -123,7 +123,7 @@ Link.add = function(canonical, target, shop) {
for (var alias in cfg.dependencies) {
var dep_locator = cfg.dependencies[alias]
// Skip local dependencies that don't exist
if (dep_locator.startsWith('/') && !fd.is_dir(dep_locator)) {
if (starts_with(dep_locator, '/') && !fd.is_dir(dep_locator)) {
log.console(" Skipping missing local dependency: " + dep_locator)
continue
}
@@ -184,7 +184,7 @@ Link.sync_one = function(canonical, target, shop) {
var link_target = resolve_link_target(target)
// Ensure parent directories exist
var parent = target_dir.substring(0, target_dir.lastIndexOf('/'))
var parent = text(target_dir, 0, target_dir.lastIndexOf('/'))
ensure_dir(parent)
// Check current state
@@ -241,7 +241,7 @@ Link.sync_all = function(shop) {
for (var alias in cfg.dependencies) {
var dep_locator = cfg.dependencies[alias]
// Skip local dependencies that don't exist
if (dep_locator.startsWith('/') && !fd.is_dir(dep_locator)) {
if (starts_with(dep_locator, '/') && !fd.is_dir(dep_locator)) {
continue
}
// Install the dependency if not already in shop

10
list.ce
View File

@@ -31,7 +31,7 @@ if (args && args.length > 0) {
target_pkg = args[0]
// Resolve local paths
if (target_pkg == '.' || target_pkg.startsWith('./') || target_pkg.startsWith('../') || fd.is_dir(target_pkg)) {
if (target_pkg == '.' || starts_with(target_pkg, './') || starts_with(target_pkg, '../') || fd.is_dir(target_pkg)) {
var resolved = fd.realpath(target_pkg)
if (resolved) {
target_pkg = resolved
@@ -60,7 +60,7 @@ function print_deps(ctx, indent) {
var aliases = []
for (var k in deps) aliases.push(k)
aliases.sort()
aliases = sort(aliases)
if (aliases.length == 0) {
log.console(indent + " (none)")
@@ -84,7 +84,7 @@ function print_deps(ctx, indent) {
status.push("linked -> " + link_target)
}
if (lock_entry && lock_entry.commit) {
status.push("@" + lock_entry.commit.substring(0, 8))
status.push("@" + text(lock_entry.commit, 0, 8))
}
if (lock_entry && lock_entry.type == 'local') {
status.push("local")
@@ -115,7 +115,7 @@ if (mode == 'local') {
if (packages.length == 0) {
log.console(" (none)")
} else {
packages.sort()
packages = sort(packages)
// Group by type
var local_pkgs = []
@@ -157,7 +157,7 @@ if (mode == 'local') {
log.console("Remote packages:")
for (var p of remote_pkgs) {
var lock_entry = lock[p]
var commit = lock_entry && lock_entry.commit ? " @" + lock_entry.commit.substring(0, 8) : ""
var commit = lock_entry && lock_entry.commit ? " @" + text(lock_entry.commit, 0, 8) : ""
log.console(" " + p + commit)
}
log.console("")

4
ls.ce
View File

@@ -11,7 +11,7 @@ var modules = package.list_modules(pkg)
var programs = package.list_programs(pkg)
log.console("Modules in " + pkg + ":")
modules.sort()
modules = sort(modules)
if (modules.length == 0) {
log.console(" (none)")
} else {
@@ -22,7 +22,7 @@ if (modules.length == 0) {
log.console("")
log.console("Programs in " + pkg + ":")
programs.sort()
programs = sort(programs)
if (programs.length == 0) {
log.console(" (none)")
} else {

View File

@@ -79,7 +79,7 @@ if (!target) {
if (target && !build.has_target(target)) {
log.error('Invalid target: ' + target)
log.console('Available targets: ' + build.list_targets().join(', '))
log.console('Available targets: ' + text(build.list_targets(), ', '))
$stop()
}

View File

@@ -11,7 +11,7 @@ var link = use('link')
// For remote packages, keep slashes as they use nested directories
function safe_package_path(pkg) {
if (!pkg) return pkg
if (pkg.startsWith('/'))
if (starts_with(pkg, '/'))
return pkg.replaceAll('/', '_').replaceAll('@', '_')
return pkg.replaceAll('@', '_')
}
@@ -22,7 +22,7 @@ function get_path(name)
if (!name)
return fd.realpath('.')
// If name is already an absolute path, use it directly
if (name.startsWith('/'))
if (starts_with(name, '/'))
return name
// Check if this package is linked - if so, use the link target directly
@@ -30,7 +30,7 @@ function get_path(name)
var link_target = link.get_target(name)
if (link_target) {
// If link target is a local path, use it directly
if (link_target.startsWith('/'))
if (starts_with(link_target, '/'))
return link_target
// Otherwise it's another package name, resolve that
return os.global_shop_path + '/packages/' + link_target.replaceAll('@', '_')
@@ -44,11 +44,12 @@ package.load_config = function(name)
{
var config_path = get_path(name) + '/cell.toml'
if (!fd.is_file(config_path))
if (!fd.is_file(config_path)) {
throw Error(`${config_path} does not exist`)
}
var content = text(fd.slurp(config_path))
if (!content || content.trim().length == 0)
if (!content || length(trim(content)) == 0)
return {}
var result = toml.decode(content)
@@ -121,7 +122,7 @@ package.find_package_dir = function(file)
var dir = absolute
if (fd.is_file(dir)) {
var last_slash = dir.lastIndexOf('/')
if (last_slash > 0) dir = dir.substring(0, last_slash)
if (last_slash > 0) dir = text(dir, 0, last_slash)
}
while (dir && dir.length > 0) {
@@ -131,7 +132,7 @@ package.find_package_dir = function(file)
}
var last_slash = dir.lastIndexOf('/')
if (last_slash <= 0) break
dir = dir.substring(0, last_slash)
dir = text(dir, 0, last_slash)
}
return null
@@ -148,7 +149,7 @@ package.split_alias = function(name, path)
return null
}
var parts = path.split('/')
var parts = array(path, '/')
var first_part = parts[0]
try {
@@ -205,7 +206,7 @@ package.list_files = function(pkg) {
for (var i = 0; i < list.length; i++) {
var item = list[i]
if (item == '.' || item == '..') continue
if (item.startsWith('.')) continue
if (starts_with(item, '.')) continue
// Skip build directories in root
@@ -231,8 +232,8 @@ package.list_modules = function(name) {
var files = package.list_files(name)
var modules = []
for (var i = 0; i < files.length; i++) {
if (files[i].endsWith('.cm')) {
modules.push(files[i].substring(0, files[i].length - 3))
if (ends_with(files[i], '.cm')) {
modules.push(text(files[i], 0, -3))
}
}
return modules
@@ -242,8 +243,8 @@ package.list_programs = function(name) {
var files = package.list_files(name)
var programs = []
for (var i = 0; i < files.length; i++) {
if (files[i].endsWith('.ce')) {
programs.push(files[i].substring(0, files[i].length - 3))
if (ends_with(files[i], '.ce')) {
programs.push(text(files[i], 0, -3))
}
}
return programs
@@ -260,13 +261,13 @@ package.get_flags = function(name, flag_type, target) {
// Base flags
if (config.compilation && config.compilation[flag_type]) {
var base = config.compilation[flag_type]
flags = flags.concat(base.split(/\s+/).filter(function(f) { return f.length > 0 }))
flags = flags.concat(filter(array(base, /\s+/), function(f) { return f.length > 0 }))
}
// Target-specific flags
if (target && config.compilation && config.compilation[target] && config.compilation[target][flag_type]) {
var target_flags = config.compilation[target][flag_type]
flags = flags.concat(target_flags.split(/\s+/).filter(function(f) { return f.length > 0 }))
flags = flags.concat(filter(array(target_flags, /\s+/), function(f) { return f.length > 0 }))
}
return flags
@@ -285,16 +286,16 @@ package.get_c_files = function(name, target, exclude_main) {
for (var i = 0; i < files.length; i++) {
var file = files[i]
if (!file.endsWith('.c') && !file.endsWith('.cpp')) continue
if (!ends_with(file, '.c') && !ends_with(file, '.cpp')) continue
var ext = file.endsWith('.cpp') ? '.cpp' : '.c'
var base = file.substring(0, file.length - ext.length)
var ext = ends_with(file, '.cpp') ? '.cpp' : '.c'
var base = text(file, 0, -ext.length)
var dir = ''
var name_part = base
var slash = base.lastIndexOf('/')
if (slash >= 0) {
dir = base.substring(0, slash + 1)
name_part = base.substring(slash + 1)
dir = text(base, 0, slash + 1)
name_part = text(base, slash + 1)
}
// Check for target suffix
@@ -304,10 +305,10 @@ package.get_c_files = function(name, target, exclude_main) {
for (var t = 0; t < known_targets.length; t++) {
var suffix = '_' + known_targets[t]
if (name_part.endsWith(suffix)) {
if (ends_with(name_part, suffix)) {
is_variant = true
variant_target = known_targets[t]
generic_name = name_part.substring(0, name_part.length - suffix.length)
generic_name = text(name_part, 0, -suffix.length)
break
}
}
@@ -342,8 +343,8 @@ package.get_c_files = function(name, target, exclude_main) {
if (exclude_main) {
var basename = selected
var s = selected.lastIndexOf('/')
if (s >= 0) basename = selected.substring(s + 1)
if (basename == 'main.c' || basename.startsWith('main_')) continue
if (s >= 0) basename = text(selected, s + 1)
if (basename == 'main.c' || starts_with(basename, 'main_')) continue
}
result.push(selected)
}

View File

@@ -14,7 +14,7 @@ function is_requestor(fn) {
}
function check_requestors(list, factory) {
if (!is_array(list) || list.some(r => !is_requestor(r)))
if (!is_array(list) || some(list, r => !is_requestor(r)))
throw make_reason(factory, 'Bad requestor array.', list)
}
@@ -106,7 +106,7 @@ function parallel(requestor_array, throttle, need) {
function cancel(reason) {
if (finished) return
finished = true
cancel_list.forEach(c => {
arrfor(cancel_list, c => {
try { if (is_function(c)) c(reason) } catch (_) {}
})
}
@@ -153,6 +153,7 @@ function parallel(requestor_array, throttle, need) {
}
}
def concurrent = throttle ? min(throttle, length) : length
for (var i = 0; i < concurrent; i++) start_one()
@@ -188,7 +189,7 @@ function race(requestor_array, throttle, need) {
function cancel(reason) {
if (finished) return
finished = true
cancel_list.forEach(c => {
arrfor(cancel_list, c => {
try { if (is_function(c)) c(reason) } catch (_) {}
})
}
@@ -330,7 +331,7 @@ function objectify(factory_fn) {
throw make_reason(factory, 'Expected an object.', object_of_requestors)
def keys = array(object_of_requestors)
def requestor_array = keys.map(k => object_of_requestors[k])
def requestor_array = array(keys, k => object_of_requestors[k])
def inner_requestor = factory_fn(requestor_array, ...rest)
@@ -340,7 +341,7 @@ function objectify(factory_fn) {
callback(null, reason)
} else if (is_array(results)) {
def obj = {}
keys.forEach((k, i) => { obj[k] = results[i] })
arrfor(keys, (k, i) => { obj[k] = results[i] })
callback(obj, reason)
} else {
callback(results, reason)

View File

@@ -52,10 +52,10 @@ function unpack(archive_path) {
var data = archive.read(f)
if (data) {
// Ensure directory exists
var dir = f.substring(0, f.lastIndexOf('/'))
var dir = text(f, 0, f.lastIndexOf('/'))
if (dir) {
// recursive mkdir
var parts = dir.split('/')
var parts = array(dir, '/')
var curr = "."
for (var p of parts) {
curr += "/" + p

View File

@@ -31,7 +31,7 @@ for (var i = 0; i < args.length; i++) {
log.console(" --prune Also remove packages no longer needed by any root")
log.console(" --dry-run Show what would be removed")
$stop()
} else if (!args[i].startsWith('-')) {
} else if (!starts_with(args[i], '-')) {
target_pkg = args[i]
}
}
@@ -42,7 +42,7 @@ if (!target_pkg) {
}
// Resolve relative paths to absolute paths
if (target_pkg == '.' || target_pkg.startsWith('./') || target_pkg.startsWith('../') || fd.is_dir(target_pkg)) {
if (target_pkg == '.' || starts_with(target_pkg, './') || starts_with(target_pkg, '../') || fd.is_dir(target_pkg)) {
var resolved = fd.realpath(target_pkg)
if (resolved) {
target_pkg = resolved
@@ -77,7 +77,7 @@ if (prune) {
// Find packages that are NOT needed
for (var p of all_packages) {
if (p == 'core') continue
if (!needed[p] && packages_to_remove.indexOf(p) < 0) {
if (!needed[p] && find(packages_to_remove, p) == null) {
packages_to_remove.push(p)
}
}

View File

@@ -43,7 +43,7 @@ for (var i = 0; i < args.length; i++) {
log.console(" --locked Show lock state without applying links")
log.console(" --refresh Refresh floating refs before printing")
$stop()
} else if (!args[i].startsWith('-')) {
} else if (!starts_with(args[i], '-')) {
target_locator = args[i]
}
}
@@ -54,7 +54,7 @@ if (!target_locator) {
}
// Resolve local paths
if (target_locator == '.' || target_locator.startsWith('./') || target_locator.startsWith('../') || fd.is_dir(target_locator)) {
if (target_locator == '.' || starts_with(target_locator, './') || starts_with(target_locator, '../') || fd.is_dir(target_locator)) {
var resolved = fd.realpath(target_locator)
if (resolved) {
target_locator = resolved
@@ -114,10 +114,9 @@ var sorted = []
for (var locator in all_deps) {
sorted.push({ locator: locator, depth: all_deps[locator].depth })
}
sorted.sort(function(a, b) {
if (a.depth != b.depth) return a.depth - b.depth
return a.locator < b.locator ? -1 : 1
})
sorted = sort(sorted, "locator")
sorted = sort(sorted, "depth")
for (var i = 0; i < sorted.length; i++) {
var locator = sorted[i].locator
@@ -158,7 +157,7 @@ for (var i = 0; i < sorted.length; i++) {
var commit_str = ""
if (lock_entry && lock_entry.commit) {
commit_str = " @" + lock_entry.commit.substring(0, 8)
commit_str = " @" + text(lock_entry.commit, 0, 8)
} else if (lock_entry && lock_entry.type == 'local') {
commit_str = " (local)"
}

View File

@@ -11,7 +11,7 @@ if (args.length < 1) {
return
}
var query = args[0].toLowerCase()
var query = args[0])
var found_packages = []
var found_modules = []
var found_actors = []
@@ -21,7 +21,7 @@ var packages = shop.list_packages()
for (var package_name of packages) {
// Check if package name matches
if (package_name.toLowerCase().includes(query)) {
if (search(package_name), query) != null) {
found_packages.push(package_name)
}
@@ -29,14 +29,14 @@ for (var package_name of packages) {
try {
var modules = pkg.list_modules(package_name)
for (var mod of modules) {
if (mod.toLowerCase().includes(query)) {
if (search(mod), query) != null) {
found_modules.push(package_name + ':' + mod)
}
}
var actors = pkg.list_programs(package_name)
for (var actor of actors) {
if (actor.toLowerCase().includes(query)) {
if (search(actor), query) != null) {
found_actors.push(package_name + ':' + actor)
}
}

File diff suppressed because it is too large Load Diff

38
test.ce
View File

@@ -84,7 +84,7 @@ function parse_args() {
var lock = shop.load_lock()
if (lock[name]) {
target_pkg = name
} else if (name.startsWith('/') && is_valid_package(name)) {
} else if (starts_with(name, '/') && is_valid_package(name)) {
target_pkg = name
} else {
// Try to resolve as dependency alias from current package
@@ -115,7 +115,7 @@ function parse_args() {
var test_path = args[0]
// Normalize path - add tests/ prefix if not present and doesn't start with /
if (!test_path.startsWith('tests/') && !test_path.startsWith('/')) {
if (!starts_with(test_path, 'tests/') && !starts_with(test_path, '/')) {
// Check if file exists as-is first
if (!fd.is_file(test_path + '.cm') && !fd.is_file(test_path)) {
// Try with tests/ prefix
@@ -144,8 +144,8 @@ if (!parse_args()) {
function ensure_dir(path) {
if (fd.is_dir(path)) return true
var parts = path.split('/')
var current = path.startsWith('/') ? '/' : ''
var parts = array(path, '/')
var current = starts_with(path, '/') ? '/' : ''
for (var i = 0; i < parts.length; i++) {
if (parts[i] == '') continue
current += parts[i] + '/'
@@ -161,7 +161,7 @@ function get_pkg_dir(package_name) {
if (!package_name) {
return fd.realpath('.')
}
if (package_name.startsWith('/')) {
if (starts_with(package_name, '/')) {
return package_name
}
return shop.get_package_dir(package_name)
@@ -179,16 +179,16 @@ function collect_actor_tests(package_name, specific_test) {
for (var i = 0; i < files.length; i++) {
var f = files[i]
// Check if file is in tests/ folder and is a .ce actor
if (f.startsWith("tests/") && f.endsWith(".ce")) {
if (starts_with(f, "tests/") && ends_with(f, ".ce")) {
// If specific test requested, filter
if (specific_test) {
var test_name = f.substring(0, f.length - 3) // remove .ce
var test_name = text(f, 0, -3) // remove .ce
var match_name = specific_test
if (!match_name.startsWith('tests/')) match_name = 'tests/' + match_name
if (!match_name.endsWith('.ce')) match_name = match_name
if (!starts_with(match_name, 'tests/')) match_name = 'tests/' + match_name
if (!ends_with(match_name, '.ce')) match_name = match_name
// Match without extension
var test_base = test_name
var match_base = match_name.endsWith('.ce') ? match_name.substring(0, match_name.length - 3) : match_name
var match_base = ends_with(match_name, '.ce') ? text(match_name, 0, -3) : match_name
if (test_base != match_base) continue
}
@@ -204,7 +204,7 @@ function collect_actor_tests(package_name, specific_test) {
// Spawn an actor test and track it
function spawn_actor_test(test_info) {
var test_name = test_info.file.substring(6, test_info.file.length - 3) // remove "tests/" and ".ce"
var test_name = text(test_info.file, 6, -3) // remove "tests/" and ".ce"
log.console(` [ACTOR] ${test_info.file}`)
var entry = {
@@ -218,7 +218,7 @@ function spawn_actor_test(test_info) {
try {
// Spawn the actor test - it should send back results
var actor_path = test_info.path.substring(0, test_info.path.length - 3) // remove .ce
var actor_path = text(test_info.path, 0, -3) // remove .ce
entry.actor = $start(actor_path)
pending_actor_tests.push(entry)
} catch (e) {
@@ -250,14 +250,14 @@ function run_tests(package_name, specific_test) {
for (var i = 0; i < files.length; i++) {
var f = files[i]
// Check if file is in tests/ folder and is a .cm module (not .ce - those are actor tests)
if (f.startsWith("tests/") && f.endsWith(".cm")) {
if (starts_with(f, "tests/") && ends_with(f, ".cm")) {
// If specific test requested, filter
if (specific_test) {
var test_name = f.substring(0, f.length - 3) // remove .cm
var test_name = text(f, 0, -3) // remove .cm
var match_name = specific_test
if (!match_name.startsWith('tests/')) match_name = 'tests/' + match_name
if (!starts_with(match_name, 'tests/')) match_name = 'tests/' + match_name
// Match without extension
var match_base = match_name.endsWith('.cm') ? match_name.substring(0, match_name.length - 3) : match_name
var match_base = ends_with(match_name, '.cm') ? text(match_name, 0, -3) : match_name
if (test_name != match_base) continue
}
test_files.push(f)
@@ -271,7 +271,7 @@ function run_tests(package_name, specific_test) {
for (var i = 0; i < test_files.length; i++) {
var f = test_files[i]
var mod_path = f.substring(0, f.length - 3) // remove .cm
var mod_path = text(f, 0, -3) // remove .cm
var file_result = {
name: f,
@@ -336,7 +336,7 @@ function run_tests(package_name, specific_test) {
log.console(` FAIL ${t.name} ${test_entry.error.message}`)
if (test_entry.error.stack) {
log.console(` ${text(test_entry.error.stack.split('\n'), '\n ')}`)
log.console(` ${text(array(test_entry.error.stack, '\n'), '\n ')}`)
}
pkg_result.failed++
@@ -602,7 +602,7 @@ Total: ${totals.total}, Passed: ${totals.passed}, Failed: ${totals.failed}
if (t.error) {
txt_report += ` Message: ${t.error.message}\n`
if (t.error.stack) {
txt_report += ` Stack:\n${text(t.error.stack.split('\n').map(function(l){return ` ${l}`}), '\n')}\n`
txt_report += ` Stack:\n${text(array(array(t.error.stack, '\n'), l => ` ${l}`), '\n')}\n`
}
}
txt_report += `\n`

View File

@@ -15,7 +15,7 @@ return {
}
$receiver(tree => {
var child_reqs = tree.children.map(child => cb => {
var child_reqs = array(tree.children, child => cb => {
$start(e => send(e.actor, child, cb), "tests/comments")
})

View File

@@ -9,7 +9,7 @@ function load_comment_from_api_requestor(id) {
}
$receiver(tree => {
var child_reqs = tree.children.map(child => cb => {
var child_reqs = array(tree.children, child => cb => {
$start(e => send(e.actor, child, cb), "tests/comments") // Note: recursively calls itself? Original used "tests/comments"
// We should probably change this to "tests/comments_actor" if it's recursive
})

View File

@@ -11,7 +11,7 @@ return {
guid = text(guid,'h')
st = time.number()-st
log.console(`took ${btime*1000000} us to make blob; took ${st*1000000} us to make it text`)
log.console(guid.toLowerCase())
log.console(lower(guid))
log.console(guid.length)
}
}

View File

@@ -65,8 +65,8 @@ function deepCompare(expected, actual, path) {
}
if (is_object(expected) && is_object(actual)) {
var expKeys = array(expected).sort();
var actKeys = array(actual).sort();
var expKeys = sort(array(expected))
var actKeys = sort(array(actual))
if (JSON.stringify(expKeys) != JSON.stringify(actKeys))
return {
passed: false,

File diff suppressed because it is too large Load Diff

View File

@@ -44,8 +44,8 @@ function deep_compare(expected, actual, path) {
}
if (is_object(expected) && is_object(actual)) {
var expKeys = array(expected).sort()
var actKeys = array(actual).sort()
var expKeys = sort(array(expected))
var actKeys = sort(array(actual))
if (JSON.stringify(expKeys) != JSON.stringify(actKeys))
return { passed: false, messages: [`Object keys mismatch at ${path}: ${expKeys} vs ${actKeys}`] }
var msgs = []

View File

@@ -161,7 +161,7 @@ function time_text(num = now(),
dst = rec.dst;
/* am/pm */
if (fmt.includes("a")) {
if (search(fmt, "a") != null) {
if (rec.hour >= 13) { rec.hour -= 12; fmt = fmt.replaceAll("a", "PM"); }
else if (rec.hour == 12) { fmt = fmt.replaceAll("a", "PM"); }
else if (rec.hour == 0) { rec.hour = 12; fmt = fmt.replaceAll("a", "AM"); }
@@ -170,7 +170,7 @@ function time_text(num = now(),
/* BCE/CE */
var year = rec.year > 0 ? rec.year : rec.year - 1;
if (fmt.includes("c")) {
if (search(fmt, "c") != null) {
if (year < 0) { year = abs(year); fmt = fmt.replaceAll("c", "BC"); }
else fmt = fmt.replaceAll("c", "AD");
}

39
toml.cm
View File

@@ -27,7 +27,7 @@ function parse_toml(toml_text) {
// Prefer Misty split if present; fall back to JS split.
var lines = array(toml_text, '\n')
if (lines == null) lines = toml_text.split('\n')
if (lines == null) lines = array(toml_text, '\n')
var result = {}
var current_section = result
@@ -37,11 +37,12 @@ function parse_toml(toml_text) {
var line = trim(lines[i])
if (line == null) line = lines[i]
// Skip empty lines and comments
if (!line || line.startsWith('#')) continue
if (!line || starts_with(line, '#')) continue
// Section header
if (line.startsWith('[') && line.endsWith(']')) {
var section_path = parse_key_path(text(line, 1, -1))
if (starts_with(line, '[') && ends_with(line, ']')) {
var inner = text(line, 1, -1)
var section_path = parse_key_path(inner)
if (section_path == null) return null
current_section = result
@@ -66,18 +67,19 @@ function parse_toml(toml_text) {
// Key-value pair
var eq_index = line.indexOf('=')
if (eq_index > 0) {
var key_part = trim(line.substring(0, eq_index))
var value = trim(line.substring(eq_index + 1))
if (key_part == null) key_part = line.substring(0, eq_index).trim()
if (value == null) value = line.substring(eq_index + 1).trim()
var key_part = trim(text(line, 0, eq_index))
var value = trim(text(line, eq_index + 1))
if (key_part == null) key_part = trim(text(line, 0, eq_index))
if (value == null) value = trim(text(line, eq_index + 1))
var key = parse_key(key_part)
if (key == null) return null
if (value.startsWith('"') && value.endsWith('"')) {
current_section[key] = toml_unescape(text(value, 1, -1))
if (starts_with(value, '"') && ends_with(value, '"')) {
var unquoted = text(value, 1, -1)
current_section[key] = toml_unescape(unquoted)
if (current_section[key] == null) return null
} else if (value.startsWith('[') && value.endsWith(']')) {
} else if (starts_with(value, '[') && ends_with(value, ']')) {
current_section[key] = parse_array(value)
if (current_section[key] == null) return null
} else if (value == 'true' || value == 'false') {
@@ -97,7 +99,7 @@ function parse_toml(toml_text) {
function parse_key(str) {
if (!is_text(str)) return null
if (str.startsWith('"') && str.endsWith('"')) {
if (starts_with(str, '"') && ends_with(str, '"')) {
var inner = text(str, 1, -1)
return toml_unescape(inner)
}
@@ -118,7 +120,7 @@ function parse_key_path(str) {
in_quote = !in_quote
} else if (c == '.' && !in_quote) {
var piece = trim(current)
if (piece == null) piece = current.trim()
if (piece == null) piece = trim(current)
parts.push(parse_key(piece))
current = ''
continue
@@ -127,7 +129,7 @@ function parse_key_path(str) {
}
var tail = trim(current)
if (tail == null) tail = current.trim()
if (tail == null) tail = trim(current)
if (tail.length > 0) parts.push(parse_key(tail))
return parts
@@ -139,7 +141,6 @@ function parse_array(str) {
// Remove brackets and trim
str = text(str, 1, -1)
str = trim(str)
if (str == null) str = text(str, 1, -1).trim()
if (!str) return []
var items = []
@@ -154,7 +155,7 @@ function parse_array(str) {
current += ch
} else if (ch == ',' && !in_quotes) {
var piece = trim(current)
if (piece == null) piece = current.trim()
if (piece == null) piece = trim(current)
items.push(parse_value(piece))
current = ''
} else {
@@ -163,7 +164,7 @@ function parse_array(str) {
}
var last = trim(current)
if (last == null) last = current.trim()
if (last == null) last = trim(current)
if (last) items.push(parse_value(last))
return items
@@ -172,7 +173,7 @@ function parse_array(str) {
function parse_value(str) {
if (!is_text(str)) return null
if (str.startsWith('"') && str.endsWith('"')) {
if (starts_with(str, '"') && ends_with(str, '"')) {
return toml_unescape(text(str, 1, -1))
}
if (str == 'true' || str == 'false') return str == 'true'
@@ -199,7 +200,7 @@ function encode_toml(obj) {
}
function quote_key(k) {
if (k.includes('.') || k.includes('"') || k.includes(' ')) {
if (search(k, '.') != null || search(k, '"') != null || search(k, ' ') != null) {
return '"' + toml_escape(k) + '"'
}
return k

View File

@@ -42,10 +42,10 @@ for (var i = 0; i < args.length; i++) {
}
} else if (args[i] == '--follow-links') {
follow_links = true
} else if (!args[i].startsWith('-')) {
} else if (!starts_with(args[i], '-')) {
target_pkg = args[i]
// Resolve relative paths to absolute paths
if (target_pkg == '.' || target_pkg.startsWith('./') || target_pkg.startsWith('../') || fd.is_dir(target_pkg)) {
if (target_pkg == '.' || starts_with(target_pkg, './') || starts_with(target_pkg, '../') || fd.is_dir(target_pkg)) {
var resolved = fd.realpath(target_pkg)
if (resolved) {
target_pkg = resolved
@@ -81,8 +81,8 @@ function update_and_fetch(pkg)
if (new_entry) {
if (new_entry.commit) {
var old_str = old_commit ? old_commit.substring(0, 8) : "(new)"
log.console(" " + effective_pkg + " " + old_str + " -> " + new_entry.commit.substring(0, 8))
var old_str = old_commit ? text(old_commit, 0, 8) : "(new)"
log.console(" " + effective_pkg + " " + old_str + " -> " + text(new_entry.commit, 0, 8))
shop.fetch(effective_pkg)
} else {
// Local package - just ensure symlink is correct

View File

@@ -45,7 +45,7 @@ for (var i = 0; i < args.length; i++) {
log.console(" --deep Traverse full dependency closure")
log.console(" --target <triple> Verify builds for specific target")
$stop()
} else if (!args[i].startsWith('-')) {
} else if (!starts_with(args[i], '-')) {
scope = args[i]
}
}
@@ -103,7 +103,7 @@ function verify_package(locator) {
// For linked packages, verify link target
if (link_target) {
if (link_target.startsWith('/')) {
if (starts_with(link_target, '/')) {
// Local path target
if (!fd.is_dir(link_target)) {
add_error(locator + ": link target does not exist: " + link_target)
@@ -121,7 +121,7 @@ function verify_package(locator) {
// Check symlink is correct
if (fd.is_link(pkg_dir)) {
var current_target = fd.readlink(pkg_dir)
var expected_target = link_target.startsWith('/') ? link_target : shop.get_package_dir(link_target)
var expected_target = starts_with(link_target, '/') ? link_target : shop.get_package_dir(link_target)
if (current_target != expected_target) {
add_warning(locator + ": symlink target mismatch (expected " + expected_target + ", got " + current_target + ")")
}
@@ -180,7 +180,7 @@ function check_dangling_links() {
for (var origin in links) {
var target = links[origin]
if (target.startsWith('/')) {
if (starts_with(target, '/')) {
if (!fd.is_dir(target)) {
add_error("Dangling link: " + origin + " -> " + target + " (target does not exist)")
}
@@ -202,7 +202,7 @@ if (scope == 'shop') {
var locator = scope
// Resolve local paths
if (locator == '.' || locator.startsWith('./') || locator.startsWith('../') || fd.is_dir(locator)) {
if (locator == '.' || starts_with(locator, './') || starts_with(locator, '../') || fd.is_dir(locator)) {
var resolved = fd.realpath(locator)
if (resolved) {
locator = resolved

8
why.ce
View File

@@ -11,7 +11,7 @@ var target = args[0]
log.console("Searching for '" + target + "'...")
var target_clean = target
if (target_clean.startsWith('/')) target_clean = target_clean.substring(1)
if (starts_with(target_clean, '/')) target_clean = text(target_clean, 1)
var found = false
@@ -23,9 +23,7 @@ function search(current_pkg, stack) {
var deps = pkg.dependencies(current_pkg)
// Sort for consistent output
var aliases = []
for (var k in deps) aliases.push(k)
aliases.sort()
var aliases = sort(array(deps))
for (var i = 0; i < aliases.length; i++) {
var alias = aliases[i]
@@ -36,7 +34,7 @@ function search(current_pkg, stack) {
var canon = parsed.path
var locator_clean = locator
if (locator.includes('@')) locator_clean = locator.split('@')[0]
if (search(locator, '@') != null) locator_clean = array(locator, '@')[0]
// Check if match
// 1. Alias matches