rm top level fns
This commit is contained in:
40
bench.ce
40
bench.ce
@@ -25,8 +25,8 @@ def MAX_BATCH_SIZE = 100000000 // 100M iterations max per batch
|
||||
// Statistical functions
|
||||
function median(arr) {
|
||||
if (arr.length == 0) return 0
|
||||
var sorted = arr.slice().sort(function(a, b) { return a - b })
|
||||
var mid = number.floor(arr.length / 2)
|
||||
var sorted = sort(arr)
|
||||
var mid = floor(arr.length / 2)
|
||||
if (arr.length % 2 == 0) {
|
||||
return (sorted[mid - 1] + sorted[mid]) / 2
|
||||
}
|
||||
@@ -54,8 +54,8 @@ function stddev(arr, mean_val) {
|
||||
|
||||
function percentile(arr, p) {
|
||||
if (arr.length == 0) return 0
|
||||
var sorted = arr.slice().sort(function(a, b) { return a - b })
|
||||
var idx = number.floor(arr.length * p / 100)
|
||||
var sorted = sort(arr)
|
||||
var idx = floor(arr.length * p / 100)
|
||||
if (idx >= arr.length) idx = arr.length - 1
|
||||
return sorted[idx]
|
||||
}
|
||||
@@ -228,7 +228,7 @@ function calibrate_batch_size(bench_fn, is_batch) {
|
||||
if (dt > 0 && dt < TARGET_SAMPLE_NS && is_number(n) && is_number(dt)) {
|
||||
var calc = n * TARGET_SAMPLE_NS / dt
|
||||
if (is_number(calc) && calc > 0) {
|
||||
var target_n = number.floor(calc)
|
||||
var target_n = floor(calc)
|
||||
// Check if floor returned a valid number
|
||||
if (is_number(target_n) && target_n > 0) {
|
||||
if (target_n > MAX_BATCH_SIZE) target_n = MAX_BATCH_SIZE
|
||||
@@ -376,20 +376,20 @@ function run_single_bench(bench_fn, bench_name) {
|
||||
// Calculate ops/s from median
|
||||
var ops_per_sec = 0
|
||||
if (median_ns > 0) {
|
||||
ops_per_sec = number.floor(1000000000 / median_ns)
|
||||
ops_per_sec = floor(1000000000 / median_ns)
|
||||
}
|
||||
|
||||
return {
|
||||
name: bench_name,
|
||||
batch_size: batch_size,
|
||||
samples: SAMPLES,
|
||||
mean_ns: number.round(mean_ns),
|
||||
median_ns: number.round(median_ns),
|
||||
min_ns: number.round(min_ns),
|
||||
max_ns: number.round(max_ns),
|
||||
stddev_ns: number.round(stddev_ns),
|
||||
p95_ns: number.round(p95_ns),
|
||||
p99_ns: number.round(p99_ns),
|
||||
mean_ns: round(mean_ns),
|
||||
median_ns: round(median_ns),
|
||||
min_ns: round(min_ns),
|
||||
max_ns: round(max_ns),
|
||||
stddev_ns: round(stddev_ns),
|
||||
p95_ns: round(p95_ns),
|
||||
p99_ns: round(p99_ns),
|
||||
ops_per_sec: ops_per_sec
|
||||
}
|
||||
}
|
||||
@@ -397,17 +397,17 @@ function run_single_bench(bench_fn, bench_name) {
|
||||
// Format nanoseconds for display
|
||||
function format_ns(ns) {
|
||||
if (ns < 1000) return `${ns}ns`
|
||||
if (ns < 1000000) return `${number.round(ns / 1000 * 100) / 100}µs`
|
||||
if (ns < 1000000000) return `${number.round(ns / 1000000 * 100) / 100}ms`
|
||||
return `${number.round(ns / 1000000000 * 100) / 100}s`
|
||||
if (ns < 1000000) return `${round(ns / 1000 * 100) / 100}µs`
|
||||
if (ns < 1000000000) return `${round(ns / 1000000 * 100) / 100}ms`
|
||||
return `${round(ns / 1000000000 * 100) / 100}s`
|
||||
}
|
||||
|
||||
// Format ops/sec for display
|
||||
function format_ops(ops) {
|
||||
if (ops < 1000) return `${ops} ops/s`
|
||||
if (ops < 1000000) return `${number.round(ops / 1000 * 100) / 100}K ops/s`
|
||||
if (ops < 1000000000) return `${number.round(ops / 1000000 * 100) / 100}M ops/s`
|
||||
return `${number.round(ops / 1000000000 * 100) / 100}G ops/s`
|
||||
if (ops < 1000000) return `${round(ops / 1000 * 100) / 100}K ops/s`
|
||||
if (ops < 1000000000) return `${round(ops / 1000000 * 100) / 100}M ops/s`
|
||||
return `${round(ops / 1000000000 * 100) / 100}G ops/s`
|
||||
}
|
||||
|
||||
// Run benchmarks for a package
|
||||
@@ -525,7 +525,7 @@ log.console(`Benchmarks: ${total_benches} total`)
|
||||
|
||||
// Generate reports
|
||||
function generate_reports() {
|
||||
var timestamp = text(number.floor(time.number()))
|
||||
var timestamp = text(floor(time.number()))
|
||||
var report_dir = shop.get_reports_dir() + '/bench_' + timestamp
|
||||
testlib.ensure_dir(report_dir)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
function mainThread() {
|
||||
var maxDepth = number.max(6, Number(arg[0] || 16));
|
||||
var maxDepth = max(6, Number(arg[0] || 16));
|
||||
|
||||
var stretchDepth = maxDepth + 1;
|
||||
var check = itemCheck(bottomUpTree(stretchDepth));
|
||||
|
||||
@@ -3,7 +3,7 @@ var math = use('math/radians')
|
||||
|
||||
function eratosthenes (n) {
|
||||
var sieve = blob(n, true)
|
||||
var sqrtN = number.whole(math.sqrt(n));
|
||||
var sqrtN = whole(math.sqrt(n));
|
||||
|
||||
for (i = 2; i <= sqrtN; i++)
|
||||
if (sieve.read_logical(i))
|
||||
|
||||
@@ -204,7 +204,7 @@ function benchStringOps() {
|
||||
|
||||
var joinTime = measureTime(function() {
|
||||
for (var i = 0; i < iterations.complex; i++) {
|
||||
var result = strings.join(",");
|
||||
var result = text(strings, ",");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -239,7 +239,7 @@ function benchArithmetic() {
|
||||
var result = 1.5;
|
||||
for (var i = 0; i < iterations.simple; i++) {
|
||||
result = math.sine(result) + math.cosine(i * 0.01);
|
||||
result = math.sqrt(number.abs(result)) + 0.1;
|
||||
result = math.sqrt(abs(result)) + 0.1;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -44,8 +44,8 @@ for (var i = 0; i < 100; i++) {
|
||||
// Calculate statistics
|
||||
function getStats(arr) {
|
||||
def avg = arr.reduce((a, b) => a + b) / arr.length;
|
||||
def min = number.min(...arr);
|
||||
def max = number.max(...arr);
|
||||
def min = min(...arr);
|
||||
def max = max(...arr);
|
||||
return { avg, min, max };
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ def benchmarks = [
|
||||
{
|
||||
name: "Large Array (1k numbers)",
|
||||
// A thousand random numbers
|
||||
data: [ Array.from({length:1000}, (_, i) => i * 0.5) ],
|
||||
data: [ array(1000, i => i *0.5) ],
|
||||
iterations: 1000
|
||||
},
|
||||
{
|
||||
|
||||
@@ -98,7 +98,7 @@ def benchmarks = [
|
||||
},
|
||||
{
|
||||
name: "large_array",
|
||||
data: [ Array.from({length:1000}, (_, i) => i) ],
|
||||
data: [ array(1000, i => i) ],
|
||||
iterations: 1000
|
||||
},
|
||||
];
|
||||
@@ -171,13 +171,13 @@ var bench = benchmarks.find(b => b.name == scenario_name);
|
||||
|
||||
if (!lib) {
|
||||
log.console('Unknown library:', lib_name);
|
||||
log.console('Available libraries:', libraries.map(l => l.name).join(', '));
|
||||
log.console('Available libraries:', text(libraries.map(l => l.name), ', '));
|
||||
$stop()
|
||||
}
|
||||
|
||||
if (!bench) {
|
||||
log.console('Unknown scenario:', scenario_name);
|
||||
log.console('Available scenarios:', benchmarks.map(b => b.name).join(', '));
|
||||
log.console('Available scenarios:', text(benchmarks.map(b => b.name), ', '));
|
||||
$stop()
|
||||
}
|
||||
|
||||
|
||||
2
build.ce
2
build.ce
@@ -80,7 +80,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()
|
||||
}
|
||||
|
||||
|
||||
6
build.cm
6
build.cm
@@ -197,7 +197,7 @@ Build.build_package = function(pkg, target = Build.detect_host_target(), exclude
|
||||
// Compute link key from all inputs that affect the dylib output
|
||||
function compute_link_key(objects, ldflags, target_ldflags, target, cc) {
|
||||
// Sort objects for deterministic hash
|
||||
var sorted_objects = objects.slice().sort()
|
||||
var sorted_objects = sort(objects)
|
||||
|
||||
// Build a string representing all link inputs
|
||||
var parts = []
|
||||
@@ -214,7 +214,7 @@ function compute_link_key(objects, ldflags, target_ldflags, target, cc) {
|
||||
parts.push('target_ldflag:' + target_ldflags[i])
|
||||
}
|
||||
|
||||
return content_hash(parts.join('\n'))
|
||||
return content_hash(text(parts, '\n'))
|
||||
}
|
||||
|
||||
// Build a dynamic library for a package
|
||||
@@ -372,7 +372,7 @@ Build.build_static = function(packages, target = Build.detect_host_target(), out
|
||||
var pkg_dir = shop.get_package_dir(pkg)
|
||||
|
||||
// Deduplicate based on the entire LDFLAGS string for this package
|
||||
var ldflags_key = pkg + ':' + ldflags.join(' ')
|
||||
var ldflags_key = pkg + ':' + text(ldflags, ' ')
|
||||
if (!seen_flags[ldflags_key]) {
|
||||
seen_flags[ldflags_key] = true
|
||||
for (var j = 0; j < ldflags.length; j++) {
|
||||
|
||||
@@ -268,7 +268,7 @@ function stat(path) {
|
||||
|
||||
// Get search paths
|
||||
function searchpath() {
|
||||
return mounts.slice()
|
||||
return array(mounts)
|
||||
}
|
||||
|
||||
// Mount a package using the shop system
|
||||
|
||||
2
clone.ce
2
clone.ce
@@ -97,7 +97,7 @@ try {
|
||||
|
||||
// Skip the first directory (repo-commit prefix)
|
||||
parts.shift()
|
||||
var rel_path = parts.join('/')
|
||||
var rel_path = text(parts, '/')
|
||||
var full_path = target_path + '/' + rel_path
|
||||
var dir_path = full_path.substring(0, full_path.lastIndexOf('/'))
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ switch (command) {
|
||||
'reply_timeout', 'actor_max', 'stack_max'
|
||||
]
|
||||
if (!valid_system_keys.includes(path[1])) {
|
||||
log.error("Invalid system key. Valid keys: " + valid_system_keys.join(', '))
|
||||
log.error("Invalid system key. Valid keys: " + text(valid_system_keys, ', '))
|
||||
$stop()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ cell hello
|
||||
## Standard Library
|
||||
|
||||
- [text](library/text.md) — string manipulation
|
||||
- [number](library/number.md) — numeric operations
|
||||
- [number](library/number.md) — numeric operations (functions are global: `floor()`, `max()`, etc.)
|
||||
- [array](library/array.md) — array utilities
|
||||
- [object](library/object.md) — object utilities
|
||||
- [blob](library/blob.md) — binary data
|
||||
|
||||
@@ -46,98 +46,98 @@ number("0xff", "j") // 255
|
||||
|
||||
## Methods
|
||||
|
||||
### number.abs(n)
|
||||
### abs(n)
|
||||
|
||||
Absolute value.
|
||||
|
||||
```javascript
|
||||
number.abs(-5) // 5
|
||||
number.abs(5) // 5
|
||||
abs(-5) // 5
|
||||
abs(5) // 5
|
||||
```
|
||||
|
||||
### number.sign(n)
|
||||
### sign(n)
|
||||
|
||||
Returns -1, 0, or 1.
|
||||
|
||||
```javascript
|
||||
number.sign(-5) // -1
|
||||
number.sign(0) // 0
|
||||
number.sign(5) // 1
|
||||
sign(-5) // -1
|
||||
sign(0) // 0
|
||||
sign(5) // 1
|
||||
```
|
||||
|
||||
### number.floor(n, place)
|
||||
### floor(n, place)
|
||||
|
||||
Round down.
|
||||
|
||||
```javascript
|
||||
number.floor(4.9) // 4
|
||||
number.floor(4.567, 2) // 4.56
|
||||
floor(4.9) // 4
|
||||
floor(4.567, 2) // 4.56
|
||||
```
|
||||
|
||||
### number.ceiling(n, place)
|
||||
### ceiling(n, place)
|
||||
|
||||
Round up.
|
||||
|
||||
```javascript
|
||||
number.ceiling(4.1) // 5
|
||||
number.ceiling(4.123, 2) // 4.13
|
||||
ceiling(4.1) // 5
|
||||
ceiling(4.123, 2) // 4.13
|
||||
```
|
||||
|
||||
### number.round(n, place)
|
||||
### round(n, place)
|
||||
|
||||
Round to nearest.
|
||||
|
||||
```javascript
|
||||
number.round(4.5) // 5
|
||||
number.round(4.567, 2) // 4.57
|
||||
round(4.5) // 5
|
||||
round(4.567, 2) // 4.57
|
||||
```
|
||||
|
||||
### number.trunc(n, place)
|
||||
### trunc(n, place)
|
||||
|
||||
Truncate toward zero.
|
||||
|
||||
```javascript
|
||||
number.trunc(4.9) // 4
|
||||
number.trunc(-4.9) // -4
|
||||
trunc(4.9) // 4
|
||||
trunc(-4.9) // -4
|
||||
```
|
||||
|
||||
### number.whole(n)
|
||||
### whole(n)
|
||||
|
||||
Get the integer part.
|
||||
|
||||
```javascript
|
||||
number.whole(4.9) // 4
|
||||
number.whole(-4.9) // -4
|
||||
whole(4.9) // 4
|
||||
whole(-4.9) // -4
|
||||
```
|
||||
|
||||
### number.fraction(n)
|
||||
### fraction(n)
|
||||
|
||||
Get the fractional part.
|
||||
|
||||
```javascript
|
||||
number.fraction(4.75) // 0.75
|
||||
fraction(4.75) // 0.75
|
||||
```
|
||||
|
||||
### number.min(...values)
|
||||
### min(...values)
|
||||
|
||||
Return the smallest value.
|
||||
|
||||
```javascript
|
||||
number.min(3, 1, 4, 1, 5) // 1
|
||||
min(3, 1, 4, 1, 5) // 1
|
||||
```
|
||||
|
||||
### number.max(...values)
|
||||
### max(...values)
|
||||
|
||||
Return the largest value.
|
||||
|
||||
```javascript
|
||||
number.max(3, 1, 4, 1, 5) // 5
|
||||
max(3, 1, 4, 1, 5) // 5
|
||||
```
|
||||
|
||||
### number.remainder(dividend, divisor)
|
||||
### remainder(dividend, divisor)
|
||||
|
||||
Compute remainder.
|
||||
|
||||
```javascript
|
||||
number.remainder(17, 5) // 2
|
||||
remainder(17, 5) // 2
|
||||
```
|
||||
|
||||
2
fetch.ce
2
fetch.ce
@@ -84,6 +84,6 @@ if (downloaded_count > 0) parts.push(`${text(downloaded_count)} downloaded`)
|
||||
if (cached_count > 0) parts.push(`${text(cached_count)} cached`)
|
||||
if (fail_count > 0) parts.push(`${text(fail_count)} failed`)
|
||||
if (parts.length == 0) parts.push("nothing to fetch")
|
||||
log.console("Fetch complete: " + parts.join(", "))
|
||||
log.console("Fetch complete: " + text(parts, ", "))
|
||||
|
||||
$stop()
|
||||
|
||||
@@ -118,7 +118,7 @@ function caller_data(depth = 0)
|
||||
}
|
||||
|
||||
function console_rec(line, file, msg) {
|
||||
return `[${_cell.id.slice(0,5)}] [${file}:${line}]: ${msg}\n`
|
||||
return `[${text(_cell.id, 0, 5)}] [${file}:${line}]: ${msg}\n`
|
||||
// time: [${time.text("mb d yyyy h:nn:ss")}]
|
||||
}
|
||||
|
||||
|
||||
@@ -115,8 +115,8 @@ function split_explicit_package_import(path)
|
||||
|
||||
// Find the longest prefix that is an installed package
|
||||
for (var i = parts.length - 1; i >= 1; i--) {
|
||||
var pkg_candidate = parts.slice(0, i).join('/')
|
||||
var mod_path = parts.slice(i).join('/')
|
||||
var pkg_candidate = text(array(parts, 0, i), '/')
|
||||
var mod_path = text(array(parts, i), '/')
|
||||
if (!mod_path || mod_path.length == 0) continue
|
||||
|
||||
var candidate_dir = get_packages_dir() + '/' + safe_package_path(pkg_candidate)
|
||||
@@ -220,7 +220,7 @@ function get_import_name(path)
|
||||
{
|
||||
var parts = path.split('/')
|
||||
if (parts.length < 2) return null
|
||||
return parts.slice(1).join('/')
|
||||
return text(array(parts, 1), '/')
|
||||
}
|
||||
|
||||
// Given a path like 'prosperon/sprite' and a package context,
|
||||
@@ -383,7 +383,7 @@ Shop.get_script_capabilities = function(path) {
|
||||
|
||||
function inject_params(inject) {
|
||||
if (!inject || !inject.length) return ''
|
||||
return ', ' + inject.join(', ')
|
||||
return ', ' + text(inject, ', ')
|
||||
}
|
||||
|
||||
function inject_values(inject) {
|
||||
@@ -707,7 +707,7 @@ function resolve_module_info(path, package_context) {
|
||||
|
||||
var c_resolve = resolve_c_symbol(path, package_context) || {scope:999}
|
||||
var mod_resolve = resolve_locator(path + '.cm', package_context) || {scope:999}
|
||||
var min_scope = number.min(c_resolve.scope, mod_resolve.scope)
|
||||
var min_scope = min(c_resolve.scope, mod_resolve.scope)
|
||||
|
||||
if (min_scope == 999)
|
||||
return null
|
||||
@@ -1104,7 +1104,7 @@ function install_zip(zip_blob, target_dir) {
|
||||
if (parts.length <= 1) continue
|
||||
|
||||
parts.shift()
|
||||
var rel_path = parts.join('/')
|
||||
var rel_path = text(parts, '/')
|
||||
var full_path = target_dir + '/' + rel_path
|
||||
var dir_path = full_path.substring(0, full_path.lastIndexOf('/'))
|
||||
|
||||
|
||||
2
list.ce
2
list.ce
@@ -94,7 +94,7 @@ function print_deps(ctx, indent) {
|
||||
}
|
||||
|
||||
if (status.length > 0) {
|
||||
line += " [" + status.join(", ") + "]"
|
||||
line += " [" + text(status, ", ") + "]"
|
||||
}
|
||||
|
||||
log.console(line)
|
||||
|
||||
6
pack.ce
6
pack.ce
@@ -22,7 +22,7 @@ if (args.length < 1) {
|
||||
log.error(' -t, --target <target> Cross-compile for target platform')
|
||||
log.error(' -b, --buildtype <type> Build type: release, debug, minsize (default: release)')
|
||||
log.error('')
|
||||
log.error('Available targets: ' + build.list_targets().join(', '))
|
||||
log.error('Available targets: ' + text(build.list_targets(), ', '))
|
||||
$stop()
|
||||
return
|
||||
}
|
||||
@@ -63,7 +63,7 @@ for (var i = 1; i < args.length; i++) {
|
||||
log.console(' -t, --target <target> Cross-compile for target platform')
|
||||
log.console(' -b, --buildtype <type> Build type: release, debug, minsize (default: release)')
|
||||
log.console('')
|
||||
log.console('Available targets: ' + build.list_targets().join(', '))
|
||||
log.console('Available targets: ' + text(build.list_targets(), ', '))
|
||||
$stop()
|
||||
} else {
|
||||
log.error('Unknown option: ' + args[i])
|
||||
@@ -109,7 +109,7 @@ for (var package of packages) {
|
||||
shop.extract(package)
|
||||
}
|
||||
|
||||
log.console('Building static binary from ' + text(packages.length) + ' packages: ' + packages.join(', '))
|
||||
log.console('Building static binary from ' + text(packages.length) + ' packages: ' + text(packages, ', '))
|
||||
|
||||
try {
|
||||
var result = build.build_static(packages, target, output_name, buildtype)
|
||||
|
||||
13
package.cm
13
package.cm
@@ -6,9 +6,6 @@ var json = use('json')
|
||||
var os = use('os')
|
||||
var link = use('link')
|
||||
|
||||
// Cache for loaded configs to avoid toml re-parsing corruption
|
||||
var config_cache = {}
|
||||
|
||||
// Convert package name to a safe directory name
|
||||
// For absolute paths (local packages), replace / with _
|
||||
// For remote packages, keep slashes as they use nested directories
|
||||
@@ -47,10 +44,6 @@ package.load_config = function(name)
|
||||
{
|
||||
var config_path = get_path(name) + '/cell.toml'
|
||||
|
||||
// Return cached config if available
|
||||
if (config_cache[config_path])
|
||||
return config_cache[config_path]
|
||||
|
||||
if (!fd.is_file(config_path))
|
||||
throw Error(`${config_path} does not exist`)
|
||||
|
||||
@@ -63,10 +56,6 @@ package.load_config = function(name)
|
||||
return {}
|
||||
}
|
||||
|
||||
// Deep copy to avoid toml module's shared state bug and cache it
|
||||
result = json.decode(json.encode(result))
|
||||
config_cache[config_path] = result
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -169,7 +158,7 @@ package.split_alias = function(name, path)
|
||||
var deps = config.dependencies
|
||||
if (deps && deps[first_part]) {
|
||||
var dep_locator = deps[first_part]
|
||||
var remaining_path = parts.slice(1).join('/')
|
||||
var remaining_path = text(array(parts, 1), '/')
|
||||
return { package: dep_locator, path: remaining_path }
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
@@ -153,7 +153,7 @@ function parallel(requestor_array, throttle, need) {
|
||||
}
|
||||
}
|
||||
|
||||
def concurrent = throttle ? number.min(throttle, length) : length
|
||||
def concurrent = throttle ? min(throttle, length) : length
|
||||
for (var i = 0; i < concurrent; i++) start_one()
|
||||
|
||||
return cancel
|
||||
@@ -238,7 +238,7 @@ function race(requestor_array, throttle, need) {
|
||||
}
|
||||
}
|
||||
|
||||
def concurrent = throttle ? number.min(throttle, length) : length
|
||||
def concurrent = throttle ? min(throttle, length) : length
|
||||
for (var i = 0; i < concurrent; i++) start_one()
|
||||
|
||||
return cancel
|
||||
|
||||
@@ -14,7 +14,7 @@ rnd.random_fit = function()
|
||||
|
||||
rnd.random_whole = function(num)
|
||||
{
|
||||
return number.floor(rnd.random() * num)
|
||||
return floor(rnd.random() * num)
|
||||
}
|
||||
|
||||
rnd.random_range = function(min,max)
|
||||
|
||||
@@ -170,7 +170,7 @@ for (var i = 0; i < sorted.length; i++) {
|
||||
}
|
||||
|
||||
if (status_parts.length > 0) {
|
||||
line += " [" + status_parts.join(", ") + "]"
|
||||
line += " [" + text(status_parts, ", ") + "]"
|
||||
}
|
||||
|
||||
log.console(line)
|
||||
@@ -183,10 +183,10 @@ for (var i = 0; i < sorted.length; i++) {
|
||||
if (cflags.length > 0 || ldflags.length > 0) {
|
||||
log.console(indent + " Compilation inputs:")
|
||||
if (cflags.length > 0) {
|
||||
log.console(indent + " CFLAGS: " + cflags.join(' '))
|
||||
log.console(indent + " CFLAGS: " + text(cflags, ' '))
|
||||
}
|
||||
if (ldflags.length > 0) {
|
||||
log.console(indent + " LDFLAGS: " + ldflags.join(' '))
|
||||
log.console(indent + " LDFLAGS: " + text(ldflags, ' '))
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
317
source/quickjs.c
317
source/quickjs.c
@@ -29533,170 +29533,6 @@ fail:
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
static JSValue js_array_from(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
// from(items, mapfn = void 0, this_arg = void 0)
|
||||
JSValueConst items = argv[0], mapfn, this_arg;
|
||||
JSValueConst args[2];
|
||||
JSValue iter, r, v, v2, arrayLike, next_method, enum_obj;
|
||||
int64_t k, len;
|
||||
int done, mapping;
|
||||
|
||||
mapping = FALSE;
|
||||
mapfn = JS_NULL;
|
||||
this_arg = JS_NULL;
|
||||
r = JS_NULL;
|
||||
arrayLike = JS_NULL;
|
||||
iter = JS_NULL;
|
||||
enum_obj = JS_NULL;
|
||||
next_method = JS_NULL;
|
||||
|
||||
if (argc > 1) {
|
||||
mapfn = argv[1];
|
||||
if (!JS_IsNull(mapfn)) {
|
||||
if (check_function(ctx, mapfn))
|
||||
goto exception;
|
||||
mapping = 1;
|
||||
if (argc > 2)
|
||||
this_arg = argv[2];
|
||||
}
|
||||
}
|
||||
iter = JS_GetProperty(ctx, items, JS_ATOM_Symbol_iterator);
|
||||
if (JS_IsException(iter))
|
||||
goto exception;
|
||||
if (!JS_IsNull(iter) && !JS_IsNull(iter)) {
|
||||
if (!JS_IsFunction(ctx, iter)) {
|
||||
JS_ThrowTypeError(ctx, "value is not iterable");
|
||||
goto exception;
|
||||
}
|
||||
if (JS_IsConstructor(ctx, this_val))
|
||||
r = JS_CallConstructor(ctx, this_val, 0, NULL);
|
||||
else
|
||||
r = JS_NewArray(ctx);
|
||||
if (JS_IsException(r))
|
||||
goto exception;
|
||||
enum_obj = JS_GetIterator2(ctx, items, iter);
|
||||
if (JS_IsException(enum_obj))
|
||||
goto exception;
|
||||
next_method = JS_GetProperty(ctx, enum_obj, JS_ATOM_next);
|
||||
if (JS_IsException(next_method))
|
||||
goto exception;
|
||||
for (k = 0;; k++) {
|
||||
v = JS_IteratorNext(ctx, enum_obj, next_method, 0, NULL, &done);
|
||||
if (JS_IsException(v))
|
||||
goto exception;
|
||||
if (done)
|
||||
break;
|
||||
if (mapping) {
|
||||
args[0] = v;
|
||||
args[1] = JS_NewInt32(ctx, k);
|
||||
v2 = JS_Call(ctx, mapfn, this_arg, 2, args);
|
||||
JS_FreeValue(ctx, v);
|
||||
v = v2;
|
||||
if (JS_IsException(v))
|
||||
goto exception_close;
|
||||
}
|
||||
if (JS_DefinePropertyValueInt64(ctx, r, k, v,
|
||||
JS_PROP_C_W_E | JS_PROP_THROW) < 0)
|
||||
goto exception_close;
|
||||
}
|
||||
} else {
|
||||
arrayLike = JS_ToObject(ctx, items);
|
||||
if (JS_IsException(arrayLike))
|
||||
goto exception;
|
||||
if (js_get_length64(ctx, &len, arrayLike) < 0)
|
||||
goto exception;
|
||||
v = JS_NewInt64(ctx, len);
|
||||
args[0] = v;
|
||||
if (JS_IsConstructor(ctx, this_val)) {
|
||||
r = JS_CallConstructor(ctx, this_val, 1, args);
|
||||
} else {
|
||||
r = js_array_constructor(ctx, JS_NULL, 1, args);
|
||||
}
|
||||
JS_FreeValue(ctx, v);
|
||||
if (JS_IsException(r))
|
||||
goto exception;
|
||||
for(k = 0; k < len; k++) {
|
||||
v = JS_GetPropertyInt64(ctx, arrayLike, k);
|
||||
if (JS_IsException(v))
|
||||
goto exception;
|
||||
if (mapping) {
|
||||
args[0] = v;
|
||||
args[1] = JS_NewInt32(ctx, k);
|
||||
v2 = JS_Call(ctx, mapfn, this_arg, 2, args);
|
||||
JS_FreeValue(ctx, v);
|
||||
v = v2;
|
||||
if (JS_IsException(v))
|
||||
goto exception;
|
||||
}
|
||||
if (JS_DefinePropertyValueInt64(ctx, r, k, v,
|
||||
JS_PROP_C_W_E | JS_PROP_THROW) < 0)
|
||||
goto exception;
|
||||
}
|
||||
}
|
||||
if (JS_SetProperty(ctx, r, JS_ATOM_length, JS_NewUint32(ctx, k)) < 0)
|
||||
goto exception;
|
||||
goto done;
|
||||
|
||||
exception_close:
|
||||
JS_IteratorClose(ctx, enum_obj, TRUE);
|
||||
exception:
|
||||
JS_FreeValue(ctx, r);
|
||||
r = JS_EXCEPTION;
|
||||
done:
|
||||
JS_FreeValue(ctx, arrayLike);
|
||||
JS_FreeValue(ctx, iter);
|
||||
JS_FreeValue(ctx, enum_obj);
|
||||
JS_FreeValue(ctx, next_method);
|
||||
return r;
|
||||
}
|
||||
|
||||
static JSValue js_array_of(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
JSValue obj, args[1];
|
||||
int i;
|
||||
|
||||
if (JS_IsConstructor(ctx, this_val)) {
|
||||
args[0] = JS_NewInt32(ctx, argc);
|
||||
obj = JS_CallConstructor(ctx, this_val, 1, (JSValueConst *)args);
|
||||
} else {
|
||||
obj = JS_NewArray(ctx);
|
||||
}
|
||||
if (JS_IsException(obj))
|
||||
return JS_EXCEPTION;
|
||||
for(i = 0; i < argc; i++) {
|
||||
if (JS_CreateDataPropertyUint32(ctx, obj, i, JS_DupValue(ctx, argv[i]),
|
||||
JS_PROP_THROW) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewUint32(ctx, argc)) < 0) {
|
||||
fail:
|
||||
JS_FreeValue(ctx, obj);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static JSValue js_array_isArray(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
int ret;
|
||||
ret = JS_IsArray(ctx, argv[0]);
|
||||
if (ret < 0)
|
||||
return JS_EXCEPTION;
|
||||
else
|
||||
return JS_NewBool(ctx, ret);
|
||||
}
|
||||
|
||||
static JSValue js_get_this(JSContext *ctx,
|
||||
JSValueConst this_val)
|
||||
{
|
||||
return JS_DupValue(ctx, this_val);
|
||||
}
|
||||
|
||||
static JSValue JS_ArraySpeciesCreate(JSContext *ctx, JSValueConst obj,
|
||||
JSValueConst len_val)
|
||||
{
|
||||
@@ -29743,13 +29579,6 @@ static JSValue JS_ArraySpeciesCreate(JSContext *ctx, JSValueConst obj,
|
||||
}
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_array_funcs[] = {
|
||||
JS_CFUNC_DEF("isArray", 1, js_array_isArray ),
|
||||
JS_CFUNC_DEF("from", 1, js_array_from ),
|
||||
JS_CFUNC_DEF("of", 0, js_array_of ),
|
||||
JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),
|
||||
};
|
||||
|
||||
static int JS_isConcatSpreadable(JSContext *ctx, JSValueConst obj)
|
||||
{
|
||||
JSValue val;
|
||||
@@ -34587,7 +34416,6 @@ done:
|
||||
|
||||
static const JSCFunctionListEntry js_regexp_funcs[] = {
|
||||
JS_CFUNC_DEF("escape", 1, js_regexp_escape ),
|
||||
JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_regexp_proto_funcs[] = {
|
||||
@@ -35779,20 +35607,6 @@ static JSValue js_cell_number_remainder(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_NewFloat64(ctx, dividend - (trunc(dividend / divisor) * divisor));
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_cell_number_funcs[] = {
|
||||
JS_CFUNC_DEF("whole", 1, js_cell_number_whole),
|
||||
JS_CFUNC_DEF("fraction", 1, js_cell_number_fraction),
|
||||
JS_CFUNC_DEF("floor", 2, js_cell_number_floor),
|
||||
JS_CFUNC_DEF("ceiling", 2, js_cell_number_ceiling),
|
||||
JS_CFUNC_DEF("abs", 1, js_cell_number_abs),
|
||||
JS_CFUNC_DEF("round", 2, js_cell_number_round),
|
||||
JS_CFUNC_DEF("sign", 1, js_cell_number_sign),
|
||||
JS_CFUNC_DEF("trunc", 2, js_cell_number_trunc),
|
||||
JS_CFUNC_DEF("min", 0, js_cell_number_min),
|
||||
JS_CFUNC_DEF("max", 0, js_cell_number_max),
|
||||
JS_CFUNC_DEF("remainder", 2, js_cell_number_remainder),
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* text function and sub-functions
|
||||
* ---------------------------------------------------------------------------- */
|
||||
@@ -36093,22 +35907,34 @@ static JSValue js_cell_text(JSContext *ctx, JSValueConst this_val,
|
||||
if (argc == 1)
|
||||
return JS_DupValue(ctx, arg);
|
||||
|
||||
/* text(string, from, to) - substring */
|
||||
if (argc >= 3) {
|
||||
int from, to;
|
||||
JSString *p = JS_VALUE_GET_STRING(arg);
|
||||
int len = p->len;
|
||||
JSString *p = JS_VALUE_GET_STRING(arg);
|
||||
int len = p->len;
|
||||
|
||||
/* text(string, from) - substring from index to end */
|
||||
/* text(string, from, to) - substring */
|
||||
if (argc >= 2 && (JS_VALUE_GET_TAG(argv[1]) == JS_TAG_INT ||
|
||||
JS_VALUE_GET_TAG(argv[1]) == JS_TAG_FLOAT64)) {
|
||||
int from;
|
||||
if (JS_ToInt32(ctx, &from, argv[1]))
|
||||
return JS_NULL;
|
||||
if (JS_ToInt32(ctx, &to, argv[2]))
|
||||
return JS_NULL;
|
||||
|
||||
/* Adjust negative indices */
|
||||
/* Adjust negative index */
|
||||
if (from < 0) from += len;
|
||||
if (to < 0) to += len;
|
||||
if (from < 0) from = 0;
|
||||
if (from > len) from = len;
|
||||
|
||||
if (from < 0 || from > to || to > len)
|
||||
int to = len; /* Default: to end of string */
|
||||
if (argc >= 3) {
|
||||
if (JS_ToInt32(ctx, &to, argv[2]))
|
||||
return JS_NULL;
|
||||
|
||||
/* Adjust negative index */
|
||||
if (to < 0) to += len;
|
||||
if (to < 0) to = 0;
|
||||
if (to > len) to = len;
|
||||
}
|
||||
|
||||
if (from > to)
|
||||
return JS_NULL;
|
||||
|
||||
return js_sub_string(ctx, p, from, to);
|
||||
@@ -36644,15 +36470,6 @@ fail:
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_cell_text_funcs[] = {
|
||||
JS_CFUNC_DEF("lower", 1, js_cell_text_lower),
|
||||
JS_CFUNC_DEF("upper", 1, js_cell_text_upper),
|
||||
JS_CFUNC_DEF("trim", 2, js_cell_text_trim),
|
||||
JS_CFUNC_DEF("codepoint", 1, js_cell_text_codepoint),
|
||||
JS_CFUNC_DEF("search", 3, js_cell_text_search),
|
||||
JS_CFUNC_DEF("replace", 4, js_cell_text_replace),
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* array function and sub-functions
|
||||
* ---------------------------------------------------------------------------- */
|
||||
@@ -37407,14 +37224,6 @@ static JSValue js_cell_array_sort(JSContext *ctx, JSValueConst this_val,
|
||||
return result;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_cell_array_funcs[] = {
|
||||
JS_CFUNC_DEF("reduce", 4, js_cell_array_reduce),
|
||||
JS_CFUNC_DEF("for", 4, js_cell_array_for),
|
||||
JS_CFUNC_DEF("find", 4, js_cell_array_find),
|
||||
JS_CFUNC_DEF("filter", 2, js_cell_array_filter),
|
||||
JS_CFUNC_DEF("sort", 2, js_cell_array_sort),
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* object function and sub-functions
|
||||
* ---------------------------------------------------------------------------- */
|
||||
@@ -37680,10 +37489,6 @@ static JSValue js_cell_fn_apply(JSContext *ctx, JSValueConst this_val,
|
||||
return result;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_cell_fn_funcs[] = {
|
||||
JS_CFUNC_DEF("apply", 2, js_cell_fn_apply),
|
||||
};
|
||||
|
||||
/* ============================================================================
|
||||
* Blob Intrinsic Type
|
||||
* ============================================================================ */
|
||||
@@ -39008,8 +38813,6 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
|
||||
obj = JS_NewGlobalCConstructor(ctx, "Array", js_array_constructor, 1,
|
||||
ctx->class_proto[JS_CLASS_ARRAY]);
|
||||
ctx->array_ctor = JS_DupValue(ctx, obj);
|
||||
JS_SetPropertyFunctionList(ctx, obj, js_array_funcs,
|
||||
countof(js_array_funcs));
|
||||
|
||||
/* XXX: create auto_initializer */
|
||||
{
|
||||
@@ -39090,17 +38893,14 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
|
||||
/* Cell Script global functions: text, number, array, object, fn */
|
||||
{
|
||||
JSValue text_func = JS_NewCFunction(ctx, js_cell_text, "text", 2);
|
||||
JS_SetPropertyFunctionList(ctx, text_func, js_cell_text_funcs, countof(js_cell_text_funcs));
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "text", text_func,
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
|
||||
JSValue number_func = JS_NewCFunction(ctx, js_cell_number, "number", 2);
|
||||
JS_SetPropertyFunctionList(ctx, number_func, js_cell_number_funcs, countof(js_cell_number_funcs));
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "number", number_func,
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
|
||||
JSValue array_func = JS_NewCFunction(ctx, js_cell_array, "array", 4);
|
||||
JS_SetPropertyFunctionList(ctx, array_func, js_cell_array_funcs, countof(js_cell_array_funcs));
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "array", array_func,
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
|
||||
@@ -39110,7 +38910,6 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
|
||||
JSValue fn_obj = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, fn_obj, js_cell_fn_funcs, countof(js_cell_fn_funcs));
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "fn", fn_obj,
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
|
||||
@@ -39186,6 +38985,78 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
|
||||
JS_NewCFunction(ctx, js_cell_is_proto, "is_proto", 2),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "apply",
|
||||
JS_NewCFunction(ctx, js_cell_fn_apply, "apply", 2),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "replace",
|
||||
JS_NewCFunction(ctx, js_cell_text_replace, "replace", 2),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "lower",
|
||||
JS_NewCFunction(ctx, js_cell_text_lower, "lower", 1),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "upper",
|
||||
JS_NewCFunction(ctx, js_cell_text_upper, "upper", 1),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "trim",
|
||||
JS_NewCFunction(ctx, js_cell_text_trim, "trim", 2),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "codepoint",
|
||||
JS_NewCFunction(ctx, js_cell_text_codepoint, "codepoint", 1),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "search",
|
||||
JS_NewCFunction(ctx, js_cell_text_search, "search", 3),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "reduce",
|
||||
JS_NewCFunction(ctx, js_cell_array_reduce, "reduce", 4),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "for",
|
||||
JS_NewCFunction(ctx, js_cell_array_for, "for", 4),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "find",
|
||||
JS_NewCFunction(ctx, js_cell_array_find, "find", 4),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "filter",
|
||||
JS_NewCFunction(ctx, js_cell_array_filter, "filter", 2),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "sort",
|
||||
JS_NewCFunction(ctx, js_cell_array_sort, "sort", 2),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
|
||||
/* Number utility functions as globals */
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "whole",
|
||||
JS_NewCFunction(ctx, js_cell_number_whole, "whole", 1),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "fraction",
|
||||
JS_NewCFunction(ctx, js_cell_number_fraction, "fraction", 1),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "floor",
|
||||
JS_NewCFunction(ctx, js_cell_number_floor, "floor", 2),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "ceiling",
|
||||
JS_NewCFunction(ctx, js_cell_number_ceiling, "ceiling", 2),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "abs",
|
||||
JS_NewCFunction(ctx, js_cell_number_abs, "abs", 1),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "round",
|
||||
JS_NewCFunction(ctx, js_cell_number_round, "round", 2),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "sign",
|
||||
JS_NewCFunction(ctx, js_cell_number_sign, "sign", 1),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "trunc",
|
||||
JS_NewCFunction(ctx, js_cell_number_trunc, "trunc", 2),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "min",
|
||||
JS_NewCFunction(ctx, js_cell_number_min, "min", 0),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "max",
|
||||
JS_NewCFunction(ctx, js_cell_number_max, "max", 0),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "remainder",
|
||||
JS_NewCFunction(ctx, js_cell_number_remainder, "remainder", 2),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
|
||||
/* reverse() - reverse an array */
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "reverse",
|
||||
JS_NewCFunction(ctx, js_cell_reverse, "reverse", 1),
|
||||
|
||||
10
test.ce
10
test.ce
@@ -336,14 +336,14 @@ function run_tests(package_name, specific_test) {
|
||||
|
||||
log.console(` FAIL ${t.name} ${test_entry.error.message}`)
|
||||
if (test_entry.error.stack) {
|
||||
log.console(` ${test_entry.error.stack.split('\n').join('\n ')}`)
|
||||
log.console(` ${text(test_entry.error.stack.split('\n'), '\n ')}`)
|
||||
}
|
||||
|
||||
pkg_result.failed++
|
||||
file_result.failed++
|
||||
}
|
||||
var end_time = time.number()
|
||||
test_entry.duration_ns = number.round((end_time - start_time) * 1000000000)
|
||||
test_entry.duration_ns = round((end_time - start_time) * 1000000000)
|
||||
|
||||
file_result.tests.push(test_entry)
|
||||
pkg_result.total++
|
||||
@@ -415,7 +415,7 @@ function handle_actor_message(msg) {
|
||||
pending_actor_tests.splice(found_idx, 1)
|
||||
|
||||
var end_time = time.number()
|
||||
var duration_ns = number.round((end_time - base_entry.start_time) * 1000000000)
|
||||
var duration_ns = round((end_time - base_entry.start_time) * 1000000000)
|
||||
|
||||
var results = []
|
||||
if (is_array(msg)) {
|
||||
@@ -567,7 +567,7 @@ if (all_actor_tests.length == 0) {
|
||||
|
||||
// Generate Reports function
|
||||
function generate_reports(totals) {
|
||||
var timestamp = text(number.floor(time.number()))
|
||||
var timestamp = text(floor(time.number()))
|
||||
var report_dir = shop.get_reports_dir() + '/test_' + timestamp
|
||||
ensure_dir(report_dir)
|
||||
|
||||
@@ -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${t.error.stack.split('\n').map(function(l){return ` ${l}`}).join('\n')}\n`
|
||||
txt_report += ` Stack:\n${text(t.error.stack.split('\n').map(function(l){return ` ${l}`}), '\n')}\n`
|
||||
}
|
||||
}
|
||||
txt_report += `\n`
|
||||
|
||||
@@ -24,7 +24,7 @@ function deepCompare(expected, actual, path) {
|
||||
if (isNaN(expected) && isNaN(actual))
|
||||
return { passed: true, messages: [] };
|
||||
|
||||
var diff = number.abs(expected - actual);
|
||||
var diff = abs(expected - actual);
|
||||
if (diff <= EPSILON)
|
||||
return { passed: true, messages: [] };
|
||||
|
||||
@@ -104,7 +104,7 @@ function makeTest(test) {
|
||||
|
||||
var compareResult = deepCompare(expected, decoded);
|
||||
if (!compareResult.passed) {
|
||||
throw compareResult.messages.join('; ');
|
||||
throw text(compareResult.messages, '; ');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1556,7 +1556,7 @@ return {
|
||||
|
||||
test_array_slice: function() {
|
||||
var arr = [1, 2, 3, 4, 5]
|
||||
var sliced = arr.slice(1, 3)
|
||||
var sliced = array(arr, 1, 3)
|
||||
if (length(sliced) != 2) throw "array slice length failed"
|
||||
if (sliced[0] != 2) throw "array slice first failed"
|
||||
if (sliced[1] != 3) throw "array slice second failed"
|
||||
@@ -1573,12 +1573,8 @@ return {
|
||||
|
||||
test_array_join: function() {
|
||||
var arr = [1, 2, 3]
|
||||
var caught = false
|
||||
try {
|
||||
var str = arr.join(",")
|
||||
} catch (e) {
|
||||
caught = true
|
||||
}
|
||||
var str = text(arr, ",")
|
||||
if (str != "1,2,3") throw "array join with text() failed"
|
||||
},
|
||||
|
||||
test_array_indexOf: function() {
|
||||
@@ -1620,8 +1616,8 @@ return {
|
||||
|
||||
test_string_slice: function() {
|
||||
var str = "hello"
|
||||
if (str.slice(1, 4) != "ell") throw "string slice failed"
|
||||
if (str.slice(-2) != "lo") throw "string slice negative failed"
|
||||
if (text(str, 1, 4) != "ell") throw "string slice failed"
|
||||
if (text(str, -2) != "lo") throw "string slice negative failed: " + text(str, -2)
|
||||
},
|
||||
|
||||
test_string_indexOf: function() {
|
||||
@@ -2043,8 +2039,8 @@ return {
|
||||
|
||||
test_builtin_function_properties_still_work: function() {
|
||||
// Built-in functions like number, text, array should still have properties
|
||||
var min_result = number.min(5, 3)
|
||||
if (min_result != 3) throw "number.min should work"
|
||||
var min_result = min(5, 3)
|
||||
if (min_result != 3) throw "min should work"
|
||||
},
|
||||
|
||||
// ============================================================================
|
||||
@@ -2108,7 +2104,7 @@ return {
|
||||
|
||||
var proxy = function(name, args) {
|
||||
if (is_function(my_record[name])) {
|
||||
return fn.apply(my_record[name], args)
|
||||
return apply(my_record[name], args)
|
||||
}
|
||||
throw `unknown method: ${name}`
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ function deep_compare(expected, actual, path) {
|
||||
|
||||
if (is_number(expected) && is_number(actual)) {
|
||||
if (isNaN(expected) && isNaN(actual)) return { passed: true, messages: [] }
|
||||
var diff = number.abs(expected - actual)
|
||||
var diff = abs(expected - actual)
|
||||
if (diff <= EPSILON) return { passed: true, messages: [] }
|
||||
return { passed: false, messages: [`Value mismatch at ${path}: ${expected} vs ${actual} (diff ${diff})`] }
|
||||
}
|
||||
@@ -115,7 +115,7 @@ function make_test(t) {
|
||||
var dec = wota.decode(enc)
|
||||
|
||||
var cmp = deep_compare(t.input, dec)
|
||||
if (!cmp.passed) throw cmp.messages.join('; ')
|
||||
if (!cmp.passed) throw text(cmp.messages, '; ')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
18
time.cm
18
time.cm
@@ -47,9 +47,9 @@ time.isleap = function(y) { return time.yearsize(y) == 366; };
|
||||
/* timecode utility */
|
||||
time.timecode = function(t, fps = 24)
|
||||
{
|
||||
var s = number.whole(t);
|
||||
var s = whole(t);
|
||||
var frac = t - s;
|
||||
return `${s}:${number.whole(frac * fps)}`;
|
||||
return `${s}:${whole(frac * fps)}`;
|
||||
};
|
||||
|
||||
/* per-month day counts (non-leap) */
|
||||
@@ -62,7 +62,7 @@ function time_record(num = now(),
|
||||
{
|
||||
if (is_object(num)) return num;
|
||||
|
||||
var monthdays = time.monthdays.slice();
|
||||
var monthdays = array(time.monthdays);
|
||||
var rec = {
|
||||
second : 0, minute : 0, hour : 0,
|
||||
yday : 0, year : 0,
|
||||
@@ -77,13 +77,13 @@ function time_record(num = now(),
|
||||
|
||||
/* split into day + seconds-of-day */
|
||||
var hms = num % time.day;
|
||||
var day = number.floor(num / time.day);
|
||||
var day = floor(num / time.day);
|
||||
if (hms < 0) { hms += time.day; day--; }
|
||||
|
||||
rec.second = hms % time.minute;
|
||||
var tmp = number.floor(hms / time.minute);
|
||||
var tmp = floor(hms / time.minute);
|
||||
rec.minute = tmp % time.minute;
|
||||
rec.hour = number.floor(tmp / time.minute);
|
||||
rec.hour = floor(tmp / time.minute);
|
||||
rec.weekday = (day + 4_503_599_627_370_496 + 2) % 7; /* 2 → 1970-01-01 was Thursday */
|
||||
|
||||
/* year & day-of-year */
|
||||
@@ -171,7 +171,7 @@ function time_text(num = now(),
|
||||
/* BCE/CE */
|
||||
var year = rec.year > 0 ? rec.year : rec.year - 1;
|
||||
if (fmt.includes("c")) {
|
||||
if (year < 0) { year = number.abs(year); fmt = fmt.replaceAll("c", "BC"); }
|
||||
if (year < 0) { year = abs(year); fmt = fmt.replaceAll("c", "BC"); }
|
||||
else fmt = fmt.replaceAll("c", "AD");
|
||||
}
|
||||
|
||||
@@ -193,10 +193,10 @@ function time_text(num = now(),
|
||||
fmt = fmt.replaceAll(/mm[^bB]/g, rec.month + 1);
|
||||
fmt = fmt.replaceAll(/m[^bB]/g, rec.month + 1);
|
||||
fmt = fmt.replaceAll(/v[^bB]/g, rec.weekday);
|
||||
fmt = fmt.replaceAll("mb", time.monthstr[rec.month].slice(0, 3));
|
||||
fmt = fmt.replaceAll("mb", text(time.monthstr[rec.month], 0, 3));
|
||||
fmt = fmt.replaceAll("mB", time.monthstr[rec.month]);
|
||||
fmt = fmt.replaceAll("vB", time.weekdays[rec.weekday]);
|
||||
fmt = fmt.replaceAll("vb", time.weekdays[rec.weekday].slice(0, 3));
|
||||
fmt = fmt.replaceAll("vb", text(time.weekdays[rec.weekday], 0, 3));
|
||||
|
||||
return fmt;
|
||||
}
|
||||
|
||||
233
toml.cm
233
toml.cm
@@ -1,58 +1,88 @@
|
||||
// Simple TOML parser for cell modules
|
||||
// Supports basic TOML features needed for the module system
|
||||
//
|
||||
// Avoids regex .replace(/.../g, ...) so no global-regex state issues.
|
||||
|
||||
function toml_unescape(s) {
|
||||
if (!is_text(s)) return null
|
||||
// Order matters:
|
||||
// "\\\"" (backslash + quote) should become "\"", not just '"'
|
||||
// So: unescape \" first, then unescape \\.
|
||||
s = replace(s, '\\"', '"')
|
||||
s = replace(s, '\\\\', '\\')
|
||||
return s
|
||||
}
|
||||
|
||||
function toml_escape(s) {
|
||||
if (!is_text(s)) return null
|
||||
// Order matters:
|
||||
// escape backslashes first, otherwise escaping quotes introduces new backslashes that would get double-escaped.
|
||||
s = replace(s, '\\', '\\\\')
|
||||
s = replace(s, '"', '\\"')
|
||||
return s
|
||||
}
|
||||
|
||||
function parse_toml(toml_text) {
|
||||
if (!is_text(toml_text)) return null
|
||||
|
||||
// Prefer Misty split if present; fall back to JS split.
|
||||
var lines = array(toml_text, '\n')
|
||||
if (lines == null) lines = toml_text.split('\n')
|
||||
|
||||
function parse_toml(text) {
|
||||
if (!is_text(text)) return null
|
||||
var lines = text.split('\n')
|
||||
var result = {}
|
||||
var current_section = result
|
||||
var current_section_name = ''
|
||||
|
||||
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
var line = lines[i].trim()
|
||||
|
||||
var line = trim(lines[i])
|
||||
if (line == null) line = lines[i]
|
||||
// Skip empty lines and comments
|
||||
if (!line || line.startsWith('#')) continue
|
||||
|
||||
|
||||
// Section header
|
||||
if (line.startsWith('[') && line.endsWith(']')) {
|
||||
var section_path = parse_key_path(line.slice(1, -1))
|
||||
var section_path = parse_key_path(text(line, 1, -1))
|
||||
if (section_path == null) return null
|
||||
|
||||
current_section = result
|
||||
// Reconstruct name for debugging/legacy (not strictly needed for object construction)
|
||||
current_section_name = section_path.join('.')
|
||||
|
||||
current_section_name = text(section_path, '.')
|
||||
|
||||
for (var j = 0; j < section_path.length; j++) {
|
||||
var key = section_path[j]
|
||||
if (!current_section[key]) {
|
||||
|
||||
// Only treat null as "missing"; do not clobber false/0/""
|
||||
if (current_section[key] == null) {
|
||||
current_section[key] = {}
|
||||
} else if (!is_object(current_section[key])) {
|
||||
// Scalar/table collision like: a = 1 then [a.b]
|
||||
return null
|
||||
}
|
||||
|
||||
current_section = current_section[key]
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
// Key-value pair
|
||||
var eq_index = line.indexOf('=')
|
||||
if (eq_index > 0) {
|
||||
var key_part = line.substring(0, eq_index).trim()
|
||||
var value = line.substring(eq_index + 1).trim()
|
||||
|
||||
// Handle quoted keys in key-value pairs too if needed?
|
||||
// For now assuming simple keys or quoted keys
|
||||
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 = parse_key(key_part)
|
||||
|
||||
// Parse value
|
||||
if (key == null) return null
|
||||
|
||||
if (value.startsWith('"') && value.endsWith('"')) {
|
||||
// String - unescape quotes
|
||||
current_section[key] = value.slice(1, -1).replace(/\\"/g, '"')
|
||||
current_section[key] = toml_unescape(text(value, 1, -1))
|
||||
if (current_section[key] == null) return null
|
||||
} else if (value.startsWith('[') && value.endsWith(']')) {
|
||||
// Array
|
||||
current_section[key] = parse_array(value)
|
||||
if (current_section[key] == null) return null
|
||||
} else if (value == 'true' || value == 'false') {
|
||||
// Boolean
|
||||
current_section[key] = value == 'true'
|
||||
} else if (is_number(value)) {
|
||||
// Number
|
||||
current_section[key] = Number(value)
|
||||
} else {
|
||||
// Unquoted string
|
||||
@@ -60,157 +90,160 @@ function parse_toml(text) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
function parse_key(str) {
|
||||
if (str.startsWith('"') && str.endsWith('"')) {
|
||||
return str.slice(1, -1).replace(/\\"/g, '"')
|
||||
}
|
||||
return str
|
||||
if (!is_text(str)) return null
|
||||
|
||||
if (str.startsWith('"') && str.endsWith('"')) {
|
||||
var inner = text(str, 1, -1)
|
||||
return toml_unescape(inner)
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
// Split a key path by dots, respecting quotes
|
||||
function parse_key_path(str) {
|
||||
if (!is_text(str)) return null
|
||||
|
||||
var parts = []
|
||||
var current = ''
|
||||
var in_quote = false
|
||||
|
||||
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
var c = str[i]
|
||||
if (c == '"' && (i==0 || str[i-1] != '\\')) {
|
||||
if (c == '"' && (i == 0 || str[i - 1] != '\\')) {
|
||||
in_quote = !in_quote
|
||||
// We don't verify if it's strictly correct TOML quote usage, just rudimentary
|
||||
} else if (c == '.' && !in_quote) {
|
||||
parts.push(parse_key(current.trim()))
|
||||
var piece = trim(current)
|
||||
if (piece == null) piece = current.trim()
|
||||
parts.push(parse_key(piece))
|
||||
current = ''
|
||||
continue
|
||||
}
|
||||
current += c
|
||||
}
|
||||
if (current.trim().length > 0)
|
||||
parts.push(parse_key(current.trim()))
|
||||
|
||||
|
||||
var tail = trim(current)
|
||||
if (tail == null) tail = current.trim()
|
||||
if (tail.length > 0) parts.push(parse_key(tail))
|
||||
|
||||
return parts
|
||||
}
|
||||
|
||||
function parse_array(str) {
|
||||
// Remove brackets
|
||||
str = str.slice(1, -1).trim()
|
||||
if (!is_text(str)) return null
|
||||
|
||||
// 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 = []
|
||||
var current = ''
|
||||
var in_quotes = false
|
||||
|
||||
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
var char = str[i]
|
||||
|
||||
if (char == '"' && (i == 0 || str[i-1] != '\\')) {
|
||||
var ch = str[i]
|
||||
|
||||
if (ch == '"' && (i == 0 || str[i - 1] != '\\')) {
|
||||
in_quotes = !in_quotes
|
||||
current += char
|
||||
} else if (char == ',' && !in_quotes) {
|
||||
items.push(parse_value(current.trim()))
|
||||
current += ch
|
||||
} else if (ch == ',' && !in_quotes) {
|
||||
var piece = trim(current)
|
||||
if (piece == null) piece = current.trim()
|
||||
items.push(parse_value(piece))
|
||||
current = ''
|
||||
} else {
|
||||
current += char
|
||||
current += ch
|
||||
}
|
||||
}
|
||||
|
||||
if (current.trim()) {
|
||||
items.push(parse_value(current.trim()))
|
||||
}
|
||||
|
||||
|
||||
var last = trim(current)
|
||||
if (last == null) last = current.trim()
|
||||
if (last) items.push(parse_value(last))
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
function parse_value(str) {
|
||||
if (!is_text(str)) return null
|
||||
|
||||
if (str.startsWith('"') && str.endsWith('"')) {
|
||||
return str.slice(1, -1).replace(/\\"/g, '"')
|
||||
} else if (str == 'true' || str == 'false') {
|
||||
return str == 'true'
|
||||
} else if (!isNaN(Number(str))) {
|
||||
return Number(str)
|
||||
} else {
|
||||
return str
|
||||
return toml_unescape(text(str, 1, -1))
|
||||
}
|
||||
if (str == 'true' || str == 'false') return str == 'true'
|
||||
|
||||
// Use your existing numeric test; TOML numeric formats are richer, but this keeps your "module TOML" scope.
|
||||
if (!isNaN(Number(str))) return Number(str)
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
function encode_toml(obj) {
|
||||
var result = []
|
||||
|
||||
|
||||
function encode_value(value) {
|
||||
if (is_text(value)) {
|
||||
return '"' + value.replace(/"/g, '\\"') + '"'
|
||||
} else if (is_logical(value)) {
|
||||
return value ? 'true' : 'false'
|
||||
} else if (is_number(value)) {
|
||||
return text(value)
|
||||
} else if (is_array(value)) {
|
||||
if (is_text(value)) return '"' + toml_escape(value) + '"'
|
||||
if (is_logical(value)) return value ? 'true' : 'false'
|
||||
if (is_number(value)) return text(value)
|
||||
if (is_array(value)) {
|
||||
var items = []
|
||||
for (var i = 0; i < value.length; i++) {
|
||||
items.push(encode_value(value[i]))
|
||||
}
|
||||
return '[' + items.join(', ') + ']'
|
||||
for (var i = 0; i < value.length; i++) items.push(encode_value(value[i]))
|
||||
return '[' + text(items, ', ') + ']'
|
||||
}
|
||||
return text(value)
|
||||
}
|
||||
|
||||
|
||||
function quote_key(k) {
|
||||
if (k.includes('.') || k.includes('"') || k.includes(' ')) {
|
||||
return '"' + k.replace(/"/g, '\\"') + '"'
|
||||
}
|
||||
return k
|
||||
if (k.includes('.') || k.includes('"') || k.includes(' ')) {
|
||||
return '"' + toml_escape(k) + '"'
|
||||
}
|
||||
return k
|
||||
}
|
||||
|
||||
|
||||
// First pass: encode top-level simple values
|
||||
var keys = array(obj)
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i]
|
||||
var value = obj[key]
|
||||
if (!is_object(value)) {
|
||||
result.push(quote_key(key) + ' = ' + encode_value(value))
|
||||
}
|
||||
if (!is_object(value)) result.push(quote_key(key) + ' = ' + encode_value(value))
|
||||
}
|
||||
|
||||
|
||||
// Second pass: encode nested objects
|
||||
function encode_section(obj, path) {
|
||||
var keys = array(obj)
|
||||
|
||||
function encode_section(o, path) {
|
||||
var keys = array(o)
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i]
|
||||
var value = obj[key]
|
||||
|
||||
var value = o[key]
|
||||
|
||||
if (is_object(value)) {
|
||||
// Nested object - create section
|
||||
// We MUST quote the key segment if it has dots, otherwise it becomes a nested table path
|
||||
var quoted = quote_key(key)
|
||||
var section_path = path ? path + '.' + quoted : quoted
|
||||
|
||||
result.push('[' + section_path + ']')
|
||||
|
||||
// First encode direct properties of this section
|
||||
|
||||
// Direct properties
|
||||
var section_keys = array(value)
|
||||
for (var j = 0; j < section_keys.length; j++) {
|
||||
var sk = section_keys[j]
|
||||
var sv = value[sk]
|
||||
if (!is_object(sv)) {
|
||||
result.push(quote_key(sk) + ' = ' + encode_value(sv))
|
||||
}
|
||||
if (!is_object(sv)) result.push(quote_key(sk) + ' = ' + encode_value(sv))
|
||||
}
|
||||
|
||||
// Then encode nested sections
|
||||
|
||||
// Nested sections
|
||||
encode_section(value, section_path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
encode_section(obj, '')
|
||||
return result.join('\n')
|
||||
return text(result, '\n')
|
||||
}
|
||||
|
||||
return {
|
||||
decode: parse_toml,
|
||||
encode: encode_toml
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user