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

View File

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

View File

@@ -211,7 +211,7 @@ function benchStringOps() {
var splitTime = measureTime(function() { var splitTime = measureTime(function() {
var str = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p"; 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++) { 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 // Calculate statistics
function getStats(arr) { 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 min = min(...arr);
def max = max(...arr); def max = max(...arr);
return { avg, min, max }; return { avg, min, max };

View File

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

View File

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

View File

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

View File

@@ -24,14 +24,14 @@ function normalize_path(path) {
function dirname(path) { function dirname(path) {
var idx = path.lastIndexOf("/") var idx = path.lastIndexOf("/")
if (idx == -1) return "" if (idx == -1) return ""
return path.substring(0, idx) return text(path, 0, idx)
} }
// Helper to get basename from path // Helper to get basename from path
function basename(path) { function basename(path) {
var idx = path.lastIndexOf("/") var idx = path.lastIndexOf("/")
if (idx == -1) return path if (idx == -1) return path
return path.substring(idx + 1) return text(path, idx + 1)
} }
// Helper to join paths // Helper to join paths
@@ -102,17 +102,17 @@ function resolve(path, must_exist) {
path = normalize_path(path) path = normalize_path(path)
// Check for named mount // Check for named mount
if (path.startsWith("@")) { if (starts_with(path, "@")) {
var idx = path.indexOf("/") var idx = path.indexOf("/")
var mount_name = "" var mount_name = ""
var rel_path = "" var rel_path = ""
if (idx == -1) { if (idx == -1) {
mount_name = path.substring(1) mount_name = text(path, 1)
rel_path = "" rel_path = ""
} else { } else {
mount_name = path.substring(1, idx) mount_name = text(path, 1, idx)
rel_path = path.substring(idx + 1) rel_path = text(path, idx + 1)
} }
// Find named mount // Find named mount
@@ -229,7 +229,7 @@ function slurpwrite(path, data) {
// Check existence // Check existence
function exists(path) { function exists(path) {
var res = resolve(path, false) var res = resolve(path, false)
if (path.startsWith("@")) { if (starts_with(path, "@")) {
return mount_exists(res.mount, res.path) return mount_exists(res.mount, res.path)
} }
return res != null return res != null
@@ -365,14 +365,14 @@ function enumerate(path, recurse) {
var seen = {} var seen = {}
for (var p of all) { for (var p of all) {
if (p.startsWith(prefix)) { if (starts_with(p, prefix)) {
var rel = p.substring(prefix_len) var rel = text(p, prefix_len)
if (rel.length == 0) continue if (rel.length == 0) continue
if (!recurse) { if (!recurse) {
var slash = rel.indexOf('/') var slash = rel.indexOf('/')
if (slash != -1) { 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) { function check_neg(path) {
for (var g of globs) { 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; return false;
} }
function check_pos(path) { function check_pos(path) {
for (var g of globs) { 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; return false;
} }
@@ -442,10 +442,10 @@ function globfs(globs, dir) {
var prefix_len = prefix.length var prefix_len = prefix.length
for (var p of all) { for (var p of all) {
if (p.startsWith(prefix)) { if (starts_with(p, prefix)) {
var rel = p.substring(prefix_len) var rel = text(p, prefix_len)
if (rel.length == 0) continue if (rel.length == 0) continue
if (!check_neg(rel) && check_pos(rel)) { if (!check_neg(rel) && check_pos(rel)) {
results.push(rel) results.push(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(" --deep Apply to full dependency closure")
log.console(" --dry-run Show what would be deleted") log.console(" --dry-run Show what would be deleted")
$stop() $stop()
} else if (!args[i].startsWith('-')) { } else if (!starts_with(args[i], '-')) {
scope = args[i] scope = args[i]
} }
} }
@@ -73,7 +73,7 @@ var is_shop_scope = (scope == 'shop')
var is_world_scope = (scope == 'world') var is_world_scope = (scope == 'world')
if (!is_shop_scope && !is_world_scope) { 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) var resolved = fd.realpath(scope)
if (resolved) { if (resolved) {
scope = resolved scope = resolved

View File

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

View File

@@ -31,7 +31,7 @@ function print_help() {
// Parse a dot-notation key into path segments // Parse a dot-notation key into path segments
function parse_key(key) { function parse_key(key) {
return key.split('.') return array(key, '.')
} }
// Get a value from nested object using path // Get a value from nested object using path
@@ -161,7 +161,7 @@ switch (command) {
'ar_timer', 'actor_memory', 'net_service', 'ar_timer', 'actor_memory', 'net_service',
'reply_timeout', 'actor_max', 'stack_max' '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, ', ')) log.error("Invalid system key. Valid keys: " + text(valid_system_keys, ', '))
$stop() $stop()
return return

4
fd.cm
View File

@@ -16,14 +16,14 @@ fd.globfs = function(globs, dir) {
function check_neg(path) { function check_neg(path) {
for (var g of globs) { 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; return false;
} }
function check_pos(path) { function check_pos(path) {
for (var g of globs) { 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; 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("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.") log.console("the lock file. For local packages, this is a no-op.")
$stop() $stop()
} else if (!args[i].startsWith('-')) { } else if (!starts_with(args[i], '-')) {
target_pkg = args[i] target_pkg = args[i]
} }
} }
@@ -35,7 +35,7 @@ var packages_to_fetch = []
if (target_pkg) { if (target_pkg) {
// Fetch specific package // Fetch specific package
if (!all_packages.includes(target_pkg)) { if (find(all_packages, target_pkg) == null) {
log.error("Package not found: " + target_pkg) log.error("Package not found: " + target_pkg)
$stop() $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(" --locked Show lock view without links")
log.console(" --world Graph all packages in shop") log.console(" --world Graph all packages in shop")
$stop() $stop()
} else if (!args[i].startsWith('-')) { } else if (!starts_with(args[i], '-')) {
target_locator = args[i] target_locator = args[i]
} }
} }
@@ -81,7 +81,7 @@ function add_node(locator) {
effective: get_effective(locator), effective: get_effective(locator),
linked: link_target != null, linked: link_target != null,
local: info == 'local', 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 // 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) var resolved = fd.realpath(target_locator)
if (resolved) { if (resolved) {
target_locator = 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(" --refresh Refresh floating refs before locking")
log.console(" --dry-run Show what would be installed") log.console(" --dry-run Show what would be installed")
$stop() $stop()
} else if (!args[i].startsWith('-')) { } else if (!starts_with(args[i], '-')) {
locator = args[i] locator = args[i]
} }
} }
@@ -63,7 +63,7 @@ if (!locator) {
// Resolve relative paths to absolute paths // Resolve relative paths to absolute paths
// Local paths like '.' or '../foo' need to be converted 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) var resolved = fd.realpath(locator)
if (resolved) { if (resolved) {
locator = resolved locator = resolved
@@ -87,7 +87,7 @@ function gather_packages(pkg_locator) {
visited[pkg_locator] = true visited[pkg_locator] = true
// Check if this is a local path that doesn't exist // 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) skipped_packages.push(pkg_locator)
log.console(" Skipping missing local package: " + pkg_locator) log.console(" Skipping missing local package: " + pkg_locator)
return return

View File

@@ -37,6 +37,22 @@ globalThis.logical = function(val1)
return null; 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 js = use_embed('js')
var fd = use_embed('fd') var fd = use_embed('fd')
@@ -104,7 +120,7 @@ function caller_data(depth = 0)
var file = "nofile" var file = "nofile"
var line = 0 var line = 0
var caller = Error().stack.split("\n")[1+depth] var caller = array(Error().stack, "\n")[1+depth]
if (caller) { if (caller) {
var md = caller.match(/\((.*)\:/) var md = caller.match(/\((.*)\:/)
var m = md ? md[1] : "SCRIPT" var m = md ? md[1] : "SCRIPT"
@@ -778,7 +794,7 @@ $_.clock(_ => {
var vals = [] var vals = []
for (var i = 0; i < inject.length; i++) { for (var i = 0; i < inject.length; i++) {
var key = inject[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) if (key == 'fd') vals.push(fd)
else vals.push($_[key]) else vals.push($_[key])
} }

View File

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

View File

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

10
link.ce
View File

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

18
link.cm
View File

@@ -21,7 +21,7 @@ function get_packages_dir() {
// return the safe path for the package // return the safe path for the package
function safe_package_path(pkg) { function safe_package_path(pkg) {
// For absolute paths, replace / with _ to create a valid directory name // 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('/', '_').replaceAll('@', '_')
return pkg.replaceAll('@', '_') return pkg.replaceAll('@', '_')
} }
@@ -32,8 +32,8 @@ function get_package_abs_dir(package) {
function ensure_dir(path) { function ensure_dir(path) {
if (fd.stat(path).isDirectory) return if (fd.stat(path).isDirectory) return
var parts = path.split('/') var parts = array(path, '/')
var current = path.startsWith('/') ? '/' : '' var current = starts_with(path, '/') ? '/' : ''
for (var i = 0; i < parts.length; i++) { for (var i = 0; i < parts.length; i++) {
if (parts[i] == '') continue if (parts[i] == '') continue
current += parts[i] + '/' 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 local path (starts with /), return it directly
// If target is a package name, return the package directory // If target is a package name, return the package directory
function resolve_link_target(target) { function resolve_link_target(target) {
if (target.startsWith('/')) { if (starts_with(target, '/')) {
return target return target
} }
// Target is another package - resolve to its directory // Target is another package - resolve to its directory
@@ -94,7 +94,7 @@ Link.add = function(canonical, target, shop) {
} }
// Validate target is a valid package // Validate target is a valid package
if (target.startsWith('/')) { if (starts_with(target, '/')) {
// Local path - must have cell.toml // Local path - must have cell.toml
if (!fd.is_file(target + '/cell.toml')) { if (!fd.is_file(target + '/cell.toml')) {
throw Error('Target ' + target + ' is not a valid package (no 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 // Install dependencies of the linked package
// Read the target's cell.toml to find its dependencies // 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' var toml_path = target_path + '/cell.toml'
if (fd.is_file(toml_path)) { if (fd.is_file(toml_path)) {
try { try {
@@ -123,7 +123,7 @@ Link.add = function(canonical, target, shop) {
for (var alias in cfg.dependencies) { for (var alias in cfg.dependencies) {
var dep_locator = cfg.dependencies[alias] var dep_locator = cfg.dependencies[alias]
// Skip local dependencies that don't exist // 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) log.console(" Skipping missing local dependency: " + dep_locator)
continue continue
} }
@@ -184,7 +184,7 @@ Link.sync_one = function(canonical, target, shop) {
var link_target = resolve_link_target(target) var link_target = resolve_link_target(target)
// Ensure parent directories exist // 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) ensure_dir(parent)
// Check current state // Check current state
@@ -241,7 +241,7 @@ Link.sync_all = function(shop) {
for (var alias in cfg.dependencies) { for (var alias in cfg.dependencies) {
var dep_locator = cfg.dependencies[alias] var dep_locator = cfg.dependencies[alias]
// Skip local dependencies that don't exist // 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 continue
} }
// Install the dependency if not already in shop // 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] target_pkg = args[0]
// Resolve local paths // 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) var resolved = fd.realpath(target_pkg)
if (resolved) { if (resolved) {
target_pkg = resolved target_pkg = resolved
@@ -60,7 +60,7 @@ function print_deps(ctx, indent) {
var aliases = [] var aliases = []
for (var k in deps) aliases.push(k) for (var k in deps) aliases.push(k)
aliases.sort() aliases = sort(aliases)
if (aliases.length == 0) { if (aliases.length == 0) {
log.console(indent + " (none)") log.console(indent + " (none)")
@@ -84,7 +84,7 @@ function print_deps(ctx, indent) {
status.push("linked -> " + link_target) status.push("linked -> " + link_target)
} }
if (lock_entry && lock_entry.commit) { 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') { if (lock_entry && lock_entry.type == 'local') {
status.push("local") status.push("local")
@@ -115,7 +115,7 @@ if (mode == 'local') {
if (packages.length == 0) { if (packages.length == 0) {
log.console(" (none)") log.console(" (none)")
} else { } else {
packages.sort() packages = sort(packages)
// Group by type // Group by type
var local_pkgs = [] var local_pkgs = []
@@ -157,7 +157,7 @@ if (mode == 'local') {
log.console("Remote packages:") log.console("Remote packages:")
for (var p of remote_pkgs) { for (var p of remote_pkgs) {
var lock_entry = lock[p] 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(" " + p + commit)
} }
log.console("") log.console("")

4
ls.ce
View File

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

View File

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

View File

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

View File

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

View File

@@ -52,10 +52,10 @@ function unpack(archive_path) {
var data = archive.read(f) var data = archive.read(f)
if (data) { if (data) {
// Ensure directory exists // Ensure directory exists
var dir = f.substring(0, f.lastIndexOf('/')) var dir = text(f, 0, f.lastIndexOf('/'))
if (dir) { if (dir) {
// recursive mkdir // recursive mkdir
var parts = dir.split('/') var parts = array(dir, '/')
var curr = "." var curr = "."
for (var p of parts) { for (var p of parts) {
curr += "/" + p 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(" --prune Also remove packages no longer needed by any root")
log.console(" --dry-run Show what would be removed") log.console(" --dry-run Show what would be removed")
$stop() $stop()
} else if (!args[i].startsWith('-')) { } else if (!starts_with(args[i], '-')) {
target_pkg = args[i] target_pkg = args[i]
} }
} }
@@ -42,7 +42,7 @@ if (!target_pkg) {
} }
// Resolve relative paths to absolute paths // 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) var resolved = fd.realpath(target_pkg)
if (resolved) { if (resolved) {
target_pkg = resolved target_pkg = resolved
@@ -77,7 +77,7 @@ if (prune) {
// Find packages that are NOT needed // Find packages that are NOT needed
for (var p of all_packages) { for (var p of all_packages) {
if (p == 'core') continue 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) 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(" --locked Show lock state without applying links")
log.console(" --refresh Refresh floating refs before printing") log.console(" --refresh Refresh floating refs before printing")
$stop() $stop()
} else if (!args[i].startsWith('-')) { } else if (!starts_with(args[i], '-')) {
target_locator = args[i] target_locator = args[i]
} }
} }
@@ -54,7 +54,7 @@ if (!target_locator) {
} }
// Resolve local paths // 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) var resolved = fd.realpath(target_locator)
if (resolved) { if (resolved) {
target_locator = resolved target_locator = resolved
@@ -114,10 +114,9 @@ var sorted = []
for (var locator in all_deps) { for (var locator in all_deps) {
sorted.push({ locator: locator, depth: all_deps[locator].depth }) sorted.push({ locator: locator, depth: all_deps[locator].depth })
} }
sorted.sort(function(a, b) {
if (a.depth != b.depth) return a.depth - b.depth sorted = sort(sorted, "locator")
return a.locator < b.locator ? -1 : 1 sorted = sort(sorted, "depth")
})
for (var i = 0; i < sorted.length; i++) { for (var i = 0; i < sorted.length; i++) {
var locator = sorted[i].locator var locator = sorted[i].locator
@@ -158,7 +157,7 @@ for (var i = 0; i < sorted.length; i++) {
var commit_str = "" var commit_str = ""
if (lock_entry && lock_entry.commit) { 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') { } else if (lock_entry && lock_entry.type == 'local') {
commit_str = " (local)" commit_str = " (local)"
} }

View File

@@ -11,7 +11,7 @@ if (args.length < 1) {
return return
} }
var query = args[0].toLowerCase() var query = args[0])
var found_packages = [] var found_packages = []
var found_modules = [] var found_modules = []
var found_actors = [] var found_actors = []
@@ -21,7 +21,7 @@ var packages = shop.list_packages()
for (var package_name of packages) { for (var package_name of packages) {
// Check if package name matches // Check if package name matches
if (package_name.toLowerCase().includes(query)) { if (search(package_name), query) != null) {
found_packages.push(package_name) found_packages.push(package_name)
} }
@@ -29,14 +29,14 @@ for (var package_name of packages) {
try { try {
var modules = pkg.list_modules(package_name) var modules = pkg.list_modules(package_name)
for (var mod of modules) { for (var mod of modules) {
if (mod.toLowerCase().includes(query)) { if (search(mod), query) != null) {
found_modules.push(package_name + ':' + mod) found_modules.push(package_name + ':' + mod)
} }
} }
var actors = pkg.list_programs(package_name) var actors = pkg.list_programs(package_name)
for (var actor of actors) { for (var actor of actors) {
if (actor.toLowerCase().includes(query)) { if (search(actor), query) != null) {
found_actors.push(package_name + ':' + actor) 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() var lock = shop.load_lock()
if (lock[name]) { if (lock[name]) {
target_pkg = name target_pkg = name
} else if (name.startsWith('/') && is_valid_package(name)) { } else if (starts_with(name, '/') && is_valid_package(name)) {
target_pkg = name target_pkg = name
} else { } else {
// Try to resolve as dependency alias from current package // Try to resolve as dependency alias from current package
@@ -115,7 +115,7 @@ function parse_args() {
var test_path = args[0] var test_path = args[0]
// Normalize path - add tests/ prefix if not present and doesn't start with / // 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 // Check if file exists as-is first
if (!fd.is_file(test_path + '.cm') && !fd.is_file(test_path)) { if (!fd.is_file(test_path + '.cm') && !fd.is_file(test_path)) {
// Try with tests/ prefix // Try with tests/ prefix
@@ -144,8 +144,8 @@ if (!parse_args()) {
function ensure_dir(path) { function ensure_dir(path) {
if (fd.is_dir(path)) return true if (fd.is_dir(path)) return true
var parts = path.split('/') var parts = array(path, '/')
var current = path.startsWith('/') ? '/' : '' var current = starts_with(path, '/') ? '/' : ''
for (var i = 0; i < parts.length; i++) { for (var i = 0; i < parts.length; i++) {
if (parts[i] == '') continue if (parts[i] == '') continue
current += parts[i] + '/' current += parts[i] + '/'
@@ -161,7 +161,7 @@ function get_pkg_dir(package_name) {
if (!package_name) { if (!package_name) {
return fd.realpath('.') return fd.realpath('.')
} }
if (package_name.startsWith('/')) { if (starts_with(package_name, '/')) {
return package_name return package_name
} }
return shop.get_package_dir(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++) { for (var i = 0; i < files.length; i++) {
var f = files[i] var f = files[i]
// Check if file is in tests/ folder and is a .ce actor // 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 requested, filter
if (specific_test) { 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 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
if (!match_name.endsWith('.ce')) match_name = match_name if (!ends_with(match_name, '.ce')) match_name = match_name
// Match without extension // Match without extension
var test_base = test_name 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 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 // Spawn an actor test and track it
function spawn_actor_test(test_info) { 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}`) log.console(` [ACTOR] ${test_info.file}`)
var entry = { var entry = {
@@ -218,7 +218,7 @@ function spawn_actor_test(test_info) {
try { try {
// Spawn the actor test - it should send back results // 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) entry.actor = $start(actor_path)
pending_actor_tests.push(entry) pending_actor_tests.push(entry)
} catch (e) { } catch (e) {
@@ -250,14 +250,14 @@ function run_tests(package_name, specific_test) {
for (var i = 0; i < files.length; i++) { for (var i = 0; i < files.length; i++) {
var f = files[i] var f = files[i]
// Check if file is in tests/ folder and is a .cm module (not .ce - those are actor tests) // 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 requested, filter
if (specific_test) { 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 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 // 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 if (test_name != match_base) continue
} }
test_files.push(f) test_files.push(f)
@@ -271,7 +271,7 @@ function run_tests(package_name, specific_test) {
for (var i = 0; i < test_files.length; i++) { for (var i = 0; i < test_files.length; i++) {
var f = test_files[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 = { var file_result = {
name: f, name: f,
@@ -336,7 +336,7 @@ function run_tests(package_name, specific_test) {
log.console(` FAIL ${t.name} ${test_entry.error.message}`) log.console(` FAIL ${t.name} ${test_entry.error.message}`)
if (test_entry.error.stack) { 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++ pkg_result.failed++
@@ -602,7 +602,7 @@ Total: ${totals.total}, Passed: ${totals.passed}, Failed: ${totals.failed}
if (t.error) { if (t.error) {
txt_report += ` Message: ${t.error.message}\n` txt_report += ` Message: ${t.error.message}\n`
if (t.error.stack) { 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` txt_report += `\n`

View File

@@ -15,7 +15,7 @@ return {
} }
$receiver(tree => { $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") $start(e => send(e.actor, child, cb), "tests/comments")
}) })

View File

@@ -9,7 +9,7 @@ function load_comment_from_api_requestor(id) {
} }
$receiver(tree => { $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" $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 // We should probably change this to "tests/comments_actor" if it's recursive
}) })

View File

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

View File

@@ -65,8 +65,8 @@ function deepCompare(expected, actual, path) {
} }
if (is_object(expected) && is_object(actual)) { if (is_object(expected) && is_object(actual)) {
var expKeys = array(expected).sort(); var expKeys = sort(array(expected))
var actKeys = array(actual).sort(); var actKeys = sort(array(actual))
if (JSON.stringify(expKeys) != JSON.stringify(actKeys)) if (JSON.stringify(expKeys) != JSON.stringify(actKeys))
return { return {
passed: false, 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)) { if (is_object(expected) && is_object(actual)) {
var expKeys = array(expected).sort() var expKeys = sort(array(expected))
var actKeys = array(actual).sort() var actKeys = sort(array(actual))
if (JSON.stringify(expKeys) != JSON.stringify(actKeys)) if (JSON.stringify(expKeys) != JSON.stringify(actKeys))
return { passed: false, messages: [`Object keys mismatch at ${path}: ${expKeys} vs ${actKeys}`] } return { passed: false, messages: [`Object keys mismatch at ${path}: ${expKeys} vs ${actKeys}`] }
var msgs = [] var msgs = []

View File

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

View File

@@ -42,10 +42,10 @@ for (var i = 0; i < args.length; i++) {
} }
} else if (args[i] == '--follow-links') { } else if (args[i] == '--follow-links') {
follow_links = true follow_links = true
} else if (!args[i].startsWith('-')) { } else if (!starts_with(args[i], '-')) {
target_pkg = args[i] target_pkg = args[i]
// Resolve relative paths to absolute paths // 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) var resolved = fd.realpath(target_pkg)
if (resolved) { if (resolved) {
target_pkg = resolved target_pkg = resolved
@@ -81,8 +81,8 @@ function update_and_fetch(pkg)
if (new_entry) { if (new_entry) {
if (new_entry.commit) { if (new_entry.commit) {
var old_str = old_commit ? old_commit.substring(0, 8) : "(new)" var old_str = old_commit ? text(old_commit, 0, 8) : "(new)"
log.console(" " + effective_pkg + " " + old_str + " -> " + new_entry.commit.substring(0, 8)) log.console(" " + effective_pkg + " " + old_str + " -> " + text(new_entry.commit, 0, 8))
shop.fetch(effective_pkg) shop.fetch(effective_pkg)
} else { } else {
// Local package - just ensure symlink is correct // 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(" --deep Traverse full dependency closure")
log.console(" --target <triple> Verify builds for specific target") log.console(" --target <triple> Verify builds for specific target")
$stop() $stop()
} else if (!args[i].startsWith('-')) { } else if (!starts_with(args[i], '-')) {
scope = args[i] scope = args[i]
} }
} }
@@ -103,7 +103,7 @@ function verify_package(locator) {
// For linked packages, verify link target // For linked packages, verify link target
if (link_target) { if (link_target) {
if (link_target.startsWith('/')) { if (starts_with(link_target, '/')) {
// Local path target // Local path target
if (!fd.is_dir(link_target)) { if (!fd.is_dir(link_target)) {
add_error(locator + ": link target does not exist: " + link_target) add_error(locator + ": link target does not exist: " + link_target)
@@ -121,7 +121,7 @@ function verify_package(locator) {
// Check symlink is correct // Check symlink is correct
if (fd.is_link(pkg_dir)) { if (fd.is_link(pkg_dir)) {
var current_target = fd.readlink(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) { if (current_target != expected_target) {
add_warning(locator + ": symlink target mismatch (expected " + expected_target + ", got " + current_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) { for (var origin in links) {
var target = links[origin] var target = links[origin]
if (target.startsWith('/')) { if (starts_with(target, '/')) {
if (!fd.is_dir(target)) { if (!fd.is_dir(target)) {
add_error("Dangling link: " + origin + " -> " + target + " (target does not exist)") add_error("Dangling link: " + origin + " -> " + target + " (target does not exist)")
} }
@@ -202,7 +202,7 @@ if (scope == 'shop') {
var locator = scope var locator = scope
// Resolve local paths // 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) var resolved = fd.realpath(locator)
if (resolved) { if (resolved) {
locator = resolved locator = resolved

8
why.ce
View File

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