Compare commits
5 Commits
957b964d9d
...
a1b41d5ecf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1b41d5ecf | ||
|
|
eb19b18594 | ||
|
|
e203700d37 | ||
|
|
c56444556d | ||
|
|
080e675d18 |
4
audit.ce
4
audit.ce
@@ -114,13 +114,13 @@ var run = function() {
|
||||
total_scripts = total_scripts + result.total
|
||||
|
||||
arrfor(result.errors, function(e) {
|
||||
push(all_failures, p + ": " + e)
|
||||
all_failures[] = p + ": " + e
|
||||
})
|
||||
|
||||
// Check use() resolution
|
||||
resolution = shop.audit_use_resolution(p)
|
||||
arrfor(resolution.unresolved, function(u) {
|
||||
push(all_unresolved, p + '/' + u.script + ": use('" + u.module + "') cannot be resolved")
|
||||
all_unresolved[] = p + '/' + u.script + ": use('" + u.module + "') cannot be resolved"
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
30
bench.ce
30
bench.ce
@@ -28,7 +28,7 @@ function strip_mode_flags() {
|
||||
} else if (a == '--compare') {
|
||||
bench_mode = "compare"
|
||||
} else {
|
||||
push(filtered, a)
|
||||
filtered[] = a
|
||||
}
|
||||
})
|
||||
_args = filtered
|
||||
@@ -197,7 +197,7 @@ function collect_benches(package_name, specific_bench) {
|
||||
match_base = ends_with(match_name, '.cm') ? text(match_name, 0, -3) : match_name
|
||||
if (bench_name != match_base) return
|
||||
}
|
||||
push(bench_files, f)
|
||||
bench_files[] = f
|
||||
}
|
||||
})
|
||||
return bench_files
|
||||
@@ -355,7 +355,7 @@ function run_single_bench(bench_fn, bench_name) {
|
||||
if (teardown_fn) teardown_fn(state)
|
||||
|
||||
ns_per_op = is_batch ? duration / batch_size : duration
|
||||
push(timings_per_op, ns_per_op)
|
||||
timings_per_op[] = ns_per_op
|
||||
} else {
|
||||
start = os.now()
|
||||
if (is_batch) {
|
||||
@@ -366,7 +366,7 @@ function run_single_bench(bench_fn, bench_name) {
|
||||
duration = os.now() - start
|
||||
|
||||
ns_per_op = is_batch ? duration / batch_size : duration
|
||||
push(timings_per_op, ns_per_op)
|
||||
timings_per_op[] = ns_per_op
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,11 +442,11 @@ function load_bench_module(f, package_name, mode) {
|
||||
function collect_bench_fns(bench_mod) {
|
||||
var benches = []
|
||||
if (is_function(bench_mod)) {
|
||||
push(benches, {name: 'main', fn: bench_mod})
|
||||
benches[] = {name: 'main', fn: bench_mod}
|
||||
} else if (is_object(bench_mod)) {
|
||||
arrfor(array(bench_mod), function(k) {
|
||||
if (is_function(bench_mod[k]))
|
||||
push(benches, {name: k, fn: bench_mod[k]})
|
||||
benches[] = {name: k, fn: bench_mod[k]}
|
||||
})
|
||||
}
|
||||
return benches
|
||||
@@ -524,7 +524,7 @@ function run_benchmarks(package_name, specific_bench) {
|
||||
result = run_single_bench(b.fn, b.name)
|
||||
result.package = pkg_result.package
|
||||
result.mode = bench_mode == "compare" ? "bytecode" : bench_mode
|
||||
push(file_result.benchmarks, result)
|
||||
file_result.benchmarks[] = result
|
||||
pkg_result.total++
|
||||
|
||||
log.console(` ${result.name}`)
|
||||
@@ -538,7 +538,7 @@ function run_benchmarks(package_name, specific_bench) {
|
||||
nat_result = run_single_bench(native_benches[nat_b].fn, b.name)
|
||||
nat_result.package = pkg_result.package
|
||||
nat_result.mode = "native"
|
||||
push(file_result.benchmarks, nat_result)
|
||||
file_result.benchmarks[] = nat_result
|
||||
pkg_result.total++
|
||||
print_bench_result(nat_result, "native ")
|
||||
|
||||
@@ -570,7 +570,7 @@ function run_benchmarks(package_name, specific_bench) {
|
||||
name: b.name,
|
||||
error: "benchmark disrupted"
|
||||
}
|
||||
push(file_result.benchmarks, error_result)
|
||||
file_result.benchmarks[] = error_result
|
||||
pkg_result.total++
|
||||
}
|
||||
})
|
||||
@@ -586,12 +586,12 @@ function run_benchmarks(package_name, specific_bench) {
|
||||
name: "load_module",
|
||||
error: "error loading module"
|
||||
}
|
||||
push(file_result.benchmarks, error_result)
|
||||
file_result.benchmarks[] = error_result
|
||||
pkg_result.total++
|
||||
}
|
||||
|
||||
if (length(file_result.benchmarks) > 0) {
|
||||
push(pkg_result.files, file_result)
|
||||
pkg_result.files[] = file_result
|
||||
}
|
||||
})
|
||||
|
||||
@@ -604,15 +604,15 @@ var packages = null
|
||||
|
||||
if (all_pkgs) {
|
||||
if (testlib.is_valid_package('.')) {
|
||||
push(all_results, run_benchmarks(null, null))
|
||||
all_results[] = run_benchmarks(null, null)
|
||||
}
|
||||
|
||||
packages = shop.list_packages()
|
||||
arrfor(packages, function(p) {
|
||||
push(all_results, run_benchmarks(p, null))
|
||||
all_results[] = run_benchmarks(p, null)
|
||||
})
|
||||
} else {
|
||||
push(all_results, run_benchmarks(target_pkg, target_bench))
|
||||
all_results[] = run_benchmarks(target_pkg, target_bench)
|
||||
}
|
||||
|
||||
// Calculate totals
|
||||
@@ -688,7 +688,7 @@ Total benchmarks: ${total_benches}
|
||||
var pkg_benches = []
|
||||
arrfor(pkg_res.files, function(f) {
|
||||
arrfor(f.benchmarks, function(benchmark) {
|
||||
push(pkg_benches, benchmark)
|
||||
pkg_benches[] = benchmark
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -27,13 +27,13 @@ function send(mailbox, msg) {
|
||||
function receive(mailbox) {
|
||||
if (length(mailbox.queue) == 0) return null
|
||||
mailbox.delivered++
|
||||
return pop(mailbox.queue)
|
||||
return mailbox.queue[]
|
||||
}
|
||||
|
||||
function drain(mailbox) {
|
||||
var count = 0
|
||||
while (length(mailbox.queue) > 0) {
|
||||
pop(mailbox.queue)
|
||||
mailbox.queue[]
|
||||
count++
|
||||
}
|
||||
return count
|
||||
|
||||
@@ -13,13 +13,13 @@ function generate_records(n) {
|
||||
var dept_vals = ["eng", "sales", "ops", "hr", "marketing"]
|
||||
for (i = 0; i < n; i++) {
|
||||
x = ((x * 1103515245 + 12345) & 0x7FFFFFFF) | 0
|
||||
push(records, {
|
||||
records[] = {
|
||||
id: i + 1,
|
||||
name: `user_${i}`,
|
||||
score: (x % 1000) / 10,
|
||||
status: status_vals[i % 4],
|
||||
department: dept_vals[i % 5]
|
||||
})
|
||||
}
|
||||
}
|
||||
return records
|
||||
}
|
||||
@@ -30,7 +30,7 @@ function filter_records(records, field, value) {
|
||||
var i = 0
|
||||
for (i = 0; i < length(records); i++) {
|
||||
if (records[i][field] == value) {
|
||||
push(result, records[i])
|
||||
result[] = records[i]
|
||||
}
|
||||
}
|
||||
return result
|
||||
@@ -45,7 +45,7 @@ function group_by(records, field) {
|
||||
key = records[i][field]
|
||||
if (!key) key = "unknown"
|
||||
if (!groups[key]) groups[key] = []
|
||||
push(groups[key], records[i])
|
||||
groups[key][] = records[i]
|
||||
}
|
||||
return groups
|
||||
}
|
||||
@@ -70,13 +70,13 @@ function aggregate(groups) {
|
||||
if (grp[j].score < mn) mn = grp[j].score
|
||||
if (grp[j].score > mx) mx = grp[j].score
|
||||
}
|
||||
push(result, {
|
||||
result[] = {
|
||||
group: keys[i],
|
||||
count: length(grp),
|
||||
average: total / length(grp),
|
||||
low: mn,
|
||||
high: mx
|
||||
})
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ function build_chain(n) {
|
||||
var constraints = []
|
||||
var i = 0
|
||||
for (i = 0; i < n; i++) {
|
||||
push(vars, make_variable(`v${i}`, 0))
|
||||
vars[] = make_variable(`v${i}`, 0)
|
||||
}
|
||||
|
||||
// Set first variable
|
||||
@@ -69,8 +69,8 @@ function build_chain(n) {
|
||||
self.variables[1].value = self.variables[0].value + 1
|
||||
self.output = self.variables[1]
|
||||
})
|
||||
push(constraints, c)
|
||||
push(vars[i].constraints, c)
|
||||
constraints[] = c
|
||||
vars[i].constraints[] = c
|
||||
}
|
||||
|
||||
return {vars: vars, constraints: constraints}
|
||||
@@ -83,8 +83,8 @@ function build_projection(n) {
|
||||
var constraints = []
|
||||
var i = 0
|
||||
for (i = 0; i < n; i++) {
|
||||
push(src, make_variable(`src${i}`, i * 10))
|
||||
push(dst, make_variable(`dst${i}`, 0))
|
||||
src[] = make_variable(`src${i}`, i * 10)
|
||||
dst[] = make_variable(`dst${i}`, 0)
|
||||
}
|
||||
|
||||
var scale_c = null
|
||||
@@ -93,8 +93,8 @@ function build_projection(n) {
|
||||
self.variables[1].value = self.variables[0].value * 2 + 1
|
||||
self.output = self.variables[1]
|
||||
})
|
||||
push(constraints, scale_c)
|
||||
push(dst[i].constraints, scale_c)
|
||||
constraints[] = scale_c
|
||||
dst[i].constraints[] = scale_c
|
||||
}
|
||||
|
||||
return {src: src, dst: dst, constraints: constraints}
|
||||
|
||||
@@ -12,7 +12,7 @@ function make_words(count) {
|
||||
var words = []
|
||||
var i = 0
|
||||
for (i = 0; i < count; i++) {
|
||||
push(words, base_words[i % length(base_words)])
|
||||
words[] = base_words[i % length(base_words)]
|
||||
}
|
||||
return words
|
||||
}
|
||||
@@ -39,7 +39,7 @@ function top_n(freq, n) {
|
||||
var pairs = []
|
||||
var i = 0
|
||||
for (i = 0; i < length(keys); i++) {
|
||||
push(pairs, {word: keys[i], count: freq[keys[i]]})
|
||||
pairs[] = {word: keys[i], count: freq[keys[i]]}
|
||||
}
|
||||
var sorted = sort(pairs, "count")
|
||||
// Return last N (highest counts)
|
||||
@@ -47,7 +47,7 @@ function top_n(freq, n) {
|
||||
var start = length(sorted) - n
|
||||
if (start < 0) start = 0
|
||||
for (i = start; i < length(sorted); i++) {
|
||||
push(result, sorted[i])
|
||||
result[] = sorted[i]
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -62,7 +62,7 @@ function group_by_length(words) {
|
||||
w = words[i]
|
||||
k = text(length(w))
|
||||
if (!groups[k]) groups[k] = []
|
||||
push(groups[k], w)
|
||||
groups[k][] = w
|
||||
}
|
||||
return groups
|
||||
}
|
||||
|
||||
@@ -27,13 +27,13 @@ function make_array_data(size) {
|
||||
var arr = []
|
||||
var i = 0
|
||||
for (i = 0; i < size; i++) {
|
||||
push(arr, {
|
||||
arr[] = {
|
||||
id: i,
|
||||
name: `item_${i}`,
|
||||
active: i % 2 == 0,
|
||||
score: i * 1.5,
|
||||
tags: [`tag_${i % 5}`, `tag_${(i + 1) % 5}`]
|
||||
})
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ function make_obj_yx(x, y) {
|
||||
function make_packed_array(n) {
|
||||
var a = []
|
||||
var i = 0
|
||||
for (i = 0; i < n; i++) push(a, i)
|
||||
for (i = 0; i < n; i++) a[] = i
|
||||
return a
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ return {
|
||||
var a = null
|
||||
for (j = 0; j < n; j++) {
|
||||
a = []
|
||||
for (i = 0; i < 256; i++) push(a, i)
|
||||
for (i = 0; i < 256; i++) a[] = i
|
||||
x = (x + length(a)) | 0
|
||||
}
|
||||
return blackhole(sink, x)
|
||||
|
||||
@@ -272,7 +272,7 @@ return {
|
||||
for (i = 0; i < n; i++) {
|
||||
push(a, i)
|
||||
if (length(a) > 64) {
|
||||
v = pop(a)
|
||||
v = a[]
|
||||
x = (x + v) | 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,21 +16,21 @@ function tokenize(src) {
|
||||
ch = chars[i]
|
||||
if (ch == " " || ch == "\n" || ch == "\t") {
|
||||
if (length(buf) > 0) {
|
||||
push(tokens, buf)
|
||||
tokens[] = buf
|
||||
buf = ""
|
||||
}
|
||||
} else if (ch == "(" || ch == ")" || ch == "+" || ch == "-"
|
||||
|| ch == "*" || ch == "=" || ch == ";" || ch == ",") {
|
||||
if (length(buf) > 0) {
|
||||
push(tokens, buf)
|
||||
tokens[] = buf
|
||||
buf = ""
|
||||
}
|
||||
push(tokens, ch)
|
||||
tokens[] = ch
|
||||
} else {
|
||||
buf = buf + ch
|
||||
}
|
||||
}
|
||||
if (length(buf) > 0) push(tokens, buf)
|
||||
if (length(buf) > 0) tokens[] = buf
|
||||
return tokens
|
||||
}
|
||||
|
||||
@@ -49,21 +49,21 @@ function parse_tokens(tokens) {
|
||||
i++ // skip =
|
||||
i++
|
||||
if (i < length(tokens)) node.value = tokens[i]
|
||||
push(ast, node)
|
||||
ast[] = node
|
||||
} else if (tok == "return") {
|
||||
node = {type: "return", value: null}
|
||||
i++
|
||||
if (i < length(tokens)) node.value = tokens[i]
|
||||
push(ast, node)
|
||||
ast[] = node
|
||||
} else if (tok == "function") {
|
||||
node = {type: "func", name: null, body: []}
|
||||
i++
|
||||
if (i < length(tokens)) node.name = tokens[i]
|
||||
// Skip to matching )
|
||||
while (i < length(tokens) && tokens[i] != ")") i++
|
||||
push(ast, node)
|
||||
ast[] = node
|
||||
} else {
|
||||
push(ast, {type: "expr", value: tok})
|
||||
ast[] = {type: "expr", value: tok}
|
||||
}
|
||||
}
|
||||
return ast
|
||||
@@ -121,7 +121,7 @@ function simulate_build(n_modules, deps_per_module) {
|
||||
// Generate all module sources
|
||||
for (i = 0; i < n_modules; i++) {
|
||||
src = generate_module(i, deps_per_module)
|
||||
push(modules, src)
|
||||
modules[] = src
|
||||
}
|
||||
|
||||
// "Load" each module: tokenize → parse → evaluate
|
||||
@@ -173,7 +173,7 @@ function topo_sort(n_modules, deps_per_module) {
|
||||
for (j = 0; j < deps_per_module; j++) {
|
||||
if (j < i) {
|
||||
dep = "mod_" + text(j)
|
||||
push(adj[dep], name)
|
||||
adj[dep][] = name
|
||||
in_degree[name] = in_degree[name] + 1
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,7 @@ function topo_sort(n_modules, deps_per_module) {
|
||||
var queue = []
|
||||
var keys = array(in_degree)
|
||||
for (i = 0; i < length(keys); i++) {
|
||||
if (in_degree[keys[i]] == 0) push(queue, keys[i])
|
||||
if (in_degree[keys[i]] == 0) queue[] = keys[i]
|
||||
}
|
||||
|
||||
var order = []
|
||||
@@ -193,12 +193,12 @@ function topo_sort(n_modules, deps_per_module) {
|
||||
while (qi < length(queue)) {
|
||||
current = queue[qi]
|
||||
qi++
|
||||
push(order, current)
|
||||
order[] = current
|
||||
neighbors = adj[current]
|
||||
if (neighbors) {
|
||||
for (i = 0; i < length(neighbors); i++) {
|
||||
in_degree[neighbors[i]] = in_degree[neighbors[i]] - 1
|
||||
if (in_degree[neighbors[i]] == 0) push(queue, neighbors[i])
|
||||
if (in_degree[neighbors[i]] == 0) queue[] = neighbors[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ function make_random_array(n, seed) {
|
||||
var i = 0
|
||||
for (i = 0; i < n; i++) {
|
||||
x = ((x * 1103515245 + 12345) & 0x7FFFFFFF) | 0
|
||||
push(a, x % 10000)
|
||||
a[] = x % 10000
|
||||
}
|
||||
return a
|
||||
}
|
||||
@@ -15,7 +15,7 @@ function make_random_array(n, seed) {
|
||||
function make_descending(n) {
|
||||
var a = []
|
||||
var i = 0
|
||||
for (i = n - 1; i >= 0; i--) push(a, i)
|
||||
for (i = n - 1; i >= 0; i--) a[] = i
|
||||
return a
|
||||
}
|
||||
|
||||
@@ -58,19 +58,19 @@ function merge(a, b) {
|
||||
var j = 0
|
||||
while (i < length(a) && j < length(b)) {
|
||||
if (a[i] <= b[j]) {
|
||||
push(result, a[i])
|
||||
result[] = a[i]
|
||||
i++
|
||||
} else {
|
||||
push(result, b[j])
|
||||
result[] = b[j]
|
||||
j++
|
||||
}
|
||||
}
|
||||
while (i < length(a)) {
|
||||
push(result, a[i])
|
||||
result[] = a[i]
|
||||
i++
|
||||
}
|
||||
while (j < length(b)) {
|
||||
push(result, b[j])
|
||||
result[] = b[j]
|
||||
j++
|
||||
}
|
||||
return result
|
||||
@@ -97,7 +97,7 @@ function sort_records(n) {
|
||||
var i = 0
|
||||
for (i = 0; i < n; i++) {
|
||||
x = ((x * 1103515245 + 12345) & 0x7FFFFFFF) | 0
|
||||
push(records, {id: i, score: x % 10000, name: `item_${i}`})
|
||||
records[] = {id: i, score: x % 10000, name: `item_${i}`}
|
||||
}
|
||||
return sort(records, "score")
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ function build_index(txt) {
|
||||
if (!index[w]) {
|
||||
index[w] = []
|
||||
}
|
||||
push(index[w], i)
|
||||
index[w][] = i
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ function tree_map(node, fn) {
|
||||
function tree_flatten(node, result) {
|
||||
if (!node) return null
|
||||
tree_flatten(node.left, result)
|
||||
push(result, node.val)
|
||||
result[] = node.val
|
||||
tree_flatten(node.right, result)
|
||||
return null
|
||||
}
|
||||
@@ -126,7 +126,7 @@ return {
|
||||
// Build a balanced BST of 1024 elements
|
||||
var data = []
|
||||
var i = 0
|
||||
for (i = 0; i < 1024; i++) push(data, i)
|
||||
for (i = 0; i < 1024; i++) data[] = i
|
||||
var bst = build_balanced(data, 0, 1023)
|
||||
var found = 0
|
||||
for (i = 0; i < n; i++) {
|
||||
|
||||
@@ -95,12 +95,12 @@ function benchArrayOps() {
|
||||
var arr = [];
|
||||
var j = 0
|
||||
for (j = 0; j < iterations.medium; j++) {
|
||||
push(arr, j);
|
||||
arr[] = j;
|
||||
}
|
||||
});
|
||||
|
||||
var arr = [];
|
||||
for (i = 0; i < 10000; i++) push(arr, i);
|
||||
for (i = 0; i < 10000; i++) arr[] = i;
|
||||
|
||||
var accessTime = measureTime(function() {
|
||||
var sum = 0;
|
||||
@@ -188,7 +188,7 @@ function benchStringOps() {
|
||||
});
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
push(strings, "string" + i);
|
||||
strings[] = "string" + i;
|
||||
}
|
||||
|
||||
var joinTime = measureTime(function() {
|
||||
@@ -261,13 +261,13 @@ function benchClosures() {
|
||||
var funcs = [];
|
||||
var j = 0
|
||||
for (j = 0; j < iterations.medium; j++) {
|
||||
push(funcs, makeAdder(j));
|
||||
funcs[] = makeAdder(j);
|
||||
}
|
||||
});
|
||||
|
||||
var adders = [];
|
||||
for (i = 0; i < 1000; i++) {
|
||||
push(adders, makeAdder(i));
|
||||
adders[] = makeAdder(i);
|
||||
}
|
||||
|
||||
var closureCallTime = measureTime(function() {
|
||||
|
||||
@@ -15,7 +15,7 @@ var nll = null
|
||||
var oll = null
|
||||
for (i = 0; i < 10000; i++) {
|
||||
accstr += i;
|
||||
push(newarr, text(i))
|
||||
newarr[] = text(i)
|
||||
}
|
||||
var jsonDecodeTimes = [];
|
||||
var jsonEncodeTimes = [];
|
||||
@@ -26,19 +26,19 @@ var notaSizes = [];
|
||||
for (i = 0; i < 100; i++) {
|
||||
start = os.now();
|
||||
jll = json.decode(ll);
|
||||
push(jsonDecodeTimes, (os.now() - start) * 1000);
|
||||
jsonDecodeTimes[] = (os.now() - start) * 1000;
|
||||
|
||||
start = os.now();
|
||||
jsonStr = JSON.stringify(jll);
|
||||
push(jsonEncodeTimes, (os.now() - start) * 1000);
|
||||
jsonEncodeTimes[] = (os.now() - start) * 1000;
|
||||
|
||||
start = os.now();
|
||||
nll = nota.encode(jll);
|
||||
push(notaEncodeTimes, (os.now() - start) * 1000);
|
||||
notaEncodeTimes[] = (os.now() - start) * 1000;
|
||||
|
||||
start = os.now();
|
||||
oll = nota.decode(nll);
|
||||
push(notaDecodeTimes, (os.now() - start) * 1000);
|
||||
notaDecodeTimes[] = (os.now() - start) * 1000;
|
||||
}
|
||||
|
||||
function getStats(arr) {
|
||||
|
||||
@@ -99,7 +99,7 @@ function runBenchmarkForLibrary(lib, bench) {
|
||||
for (j = 0; j < length(bench.data); j++) {
|
||||
e = lib.encode(bench.data[j]);
|
||||
if (i == 0) {
|
||||
push(encodedList, e);
|
||||
encodedList[] = e;
|
||||
totalSize += lib.getSize(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5251,88 +5251,54 @@
|
||||
["add", 29, 29, 7, 260, 17],
|
||||
["jump", "while_start_360", 260, 17],
|
||||
"while_end_361",
|
||||
["access", 7, "bootstrap: native cache seeded\n", 262, 12],
|
||||
[
|
||||
"access",
|
||||
11,
|
||||
{
|
||||
"name": "os",
|
||||
"kind": "name",
|
||||
"make": "intrinsic"
|
||||
},
|
||||
262,
|
||||
3
|
||||
],
|
||||
["is_proxy", 12, 11, 262, 3],
|
||||
["jump_false", 12, "record_path_368", 262, 3],
|
||||
["null", 12, 262, 3],
|
||||
["access", 14, "print", 262, 3],
|
||||
["array", 31, 0, 262, 3],
|
||||
["stone_text", 7],
|
||||
["push", 31, 7, 262, 3],
|
||||
["frame", 32, 11, 2, 262, 3],
|
||||
["setarg", 32, 0, 12, 262, 3],
|
||||
["stone_text", 14],
|
||||
["setarg", 32, 1, 14, 262, 3],
|
||||
["setarg", 32, 2, 31, 262, 3],
|
||||
["invoke", 32, 12, 262, 3],
|
||||
["jump", "call_done_369", 262, 3],
|
||||
"record_path_368",
|
||||
["load_field", 14, 11, "print", 262, 3],
|
||||
["frame", 31, 14, 1, 262, 3],
|
||||
["setarg", 31, 0, 11, 262, 3],
|
||||
["stone_text", 7],
|
||||
["setarg", 31, 1, 7, 262, 3],
|
||||
["invoke", 31, 12, 262, 3],
|
||||
"call_done_369",
|
||||
["jump", "if_end_350", 262, 3],
|
||||
["jump", "if_end_350", 260, 17],
|
||||
"if_else_349",
|
||||
["record", 7, 2],
|
||||
["access", 11, "tokenize", 266, 12],
|
||||
["store_field", 7, 11, "name", 266, 12],
|
||||
["access", 11, "tokenize.cm", 266, 30],
|
||||
["store_field", 7, 11, "path", 266, 30],
|
||||
["access", 11, "tokenize", 265, 12],
|
||||
["store_field", 7, 11, "name", 265, 12],
|
||||
["access", 11, "tokenize.cm", 265, 30],
|
||||
["store_field", 7, 11, "path", 265, 30],
|
||||
["record", 11, 2],
|
||||
["access", 12, "parse", 267, 12],
|
||||
["store_field", 11, 12, "name", 267, 12],
|
||||
["access", 12, "parse.cm", 267, 27],
|
||||
["store_field", 11, 12, "path", 267, 27],
|
||||
["access", 12, "parse", 266, 12],
|
||||
["store_field", 11, 12, "name", 266, 12],
|
||||
["access", 12, "parse.cm", 266, 27],
|
||||
["store_field", 11, 12, "path", 266, 27],
|
||||
["record", 12, 2],
|
||||
["access", 14, "fold", 268, 12],
|
||||
["store_field", 12, 14, "name", 268, 12],
|
||||
["access", 14, "fold.cm", 268, 26],
|
||||
["store_field", 12, 14, "path", 268, 26],
|
||||
["access", 14, "fold", 267, 12],
|
||||
["store_field", 12, 14, "name", 267, 12],
|
||||
["access", 14, "fold.cm", 267, 26],
|
||||
["store_field", 12, 14, "path", 267, 26],
|
||||
["record", 14, 2],
|
||||
["access", 31, "mcode", 269, 12],
|
||||
["store_field", 14, 31, "name", 269, 12],
|
||||
["access", 31, "mcode.cm", 269, 27],
|
||||
["store_field", 14, 31, "path", 269, 27],
|
||||
["access", 31, "mcode", 268, 12],
|
||||
["store_field", 14, 31, "name", 268, 12],
|
||||
["access", 31, "mcode.cm", 268, 27],
|
||||
["store_field", 14, 31, "path", 268, 27],
|
||||
["record", 31, 2],
|
||||
["access", 32, "streamline", 270, 12],
|
||||
["store_field", 31, 32, "name", 270, 12],
|
||||
["access", 32, "streamline.cm", 270, 32],
|
||||
["store_field", 31, 32, "path", 270, 32],
|
||||
["access", 32, "streamline", 269, 12],
|
||||
["store_field", 31, 32, "name", 269, 12],
|
||||
["access", 32, "streamline.cm", 269, 32],
|
||||
["store_field", 31, 32, "path", 269, 32],
|
||||
["record", 32, 2],
|
||||
["access", 33, "engine", 271, 12],
|
||||
["store_field", 32, 33, "name", 271, 12],
|
||||
["access", 33, "internal/engine.cm", 271, 28],
|
||||
["store_field", 32, 33, "path", 271, 28],
|
||||
["array", 33, 6, 271, 28],
|
||||
["push", 33, 7, 271, 28],
|
||||
["push", 33, 11, 271, 28],
|
||||
["push", 33, 12, 271, 28],
|
||||
["push", 33, 14, 271, 28],
|
||||
["push", 33, 31, 271, 28],
|
||||
["push", 33, 32, 271, 28],
|
||||
["move", 28, 33, 271, 28],
|
||||
["access", 29, 0, 273, 9],
|
||||
"while_start_370",
|
||||
["length", 7, 28, 274, 23],
|
||||
["lt", 11, 29, 7, 274, 23],
|
||||
["jump_false", 11, "while_end_371", 274, 23],
|
||||
["load_dynamic", 7, 28, 29, 275, 20],
|
||||
["move", 30, 7, 275, 20],
|
||||
["load_field", 11, 7, "name", 276, 23],
|
||||
["access", 33, "engine", 270, 12],
|
||||
["store_field", 32, 33, "name", 270, 12],
|
||||
["access", 33, "internal/engine.cm", 270, 28],
|
||||
["store_field", 32, 33, "path", 270, 28],
|
||||
["array", 33, 6, 270, 28],
|
||||
["push", 33, 7, 270, 28],
|
||||
["push", 33, 11, 270, 28],
|
||||
["push", 33, 12, 270, 28],
|
||||
["push", 33, 14, 270, 28],
|
||||
["push", 33, 31, 270, 28],
|
||||
["push", 33, 32, 270, 28],
|
||||
["move", 28, 33, 270, 28],
|
||||
["access", 29, 0, 272, 9],
|
||||
"while_start_368",
|
||||
["length", 7, 28, 273, 23],
|
||||
["lt", 11, 29, 7, 273, 23],
|
||||
["jump_false", 11, "while_end_369", 273, 23],
|
||||
["load_dynamic", 7, 28, 29, 274, 20],
|
||||
["move", 30, 7, 274, 20],
|
||||
["load_field", 11, 7, "name", 275, 23],
|
||||
[
|
||||
"access",
|
||||
7,
|
||||
@@ -5341,24 +5307,24 @@
|
||||
"kind": "name",
|
||||
"make": "intrinsic"
|
||||
},
|
||||
276,
|
||||
275,
|
||||
33
|
||||
],
|
||||
["access", 12, "/", 276, 45],
|
||||
["is_text", 14, 7, 276, 45],
|
||||
["jump_false", 14, "add_cn_373", 276, 45],
|
||||
["access", 12, "/", 275, 45],
|
||||
["is_text", 14, 7, 275, 45],
|
||||
["jump_false", 14, "add_cn_371", 275, 45],
|
||||
"_nop_tc_7",
|
||||
"_nop_tc_8",
|
||||
["concat", 31, 7, 12, 276, 45],
|
||||
["jump", "add_done_372", 276, 45],
|
||||
"add_cn_373",
|
||||
["is_num", 14, 7, 276, 45],
|
||||
["jump_false", 14, "add_err_374", 276, 45],
|
||||
["concat", 31, 7, 12, 275, 45],
|
||||
["jump", "add_done_370", 275, 45],
|
||||
"add_cn_371",
|
||||
["is_num", 14, 7, 275, 45],
|
||||
["jump_false", 14, "add_err_372", 275, 45],
|
||||
"_nop_tc_9",
|
||||
"_nop_dj_3",
|
||||
"_nop_ucfg_6",
|
||||
"_nop_ucfg_7",
|
||||
"add_err_374",
|
||||
"add_err_372",
|
||||
[
|
||||
"access",
|
||||
7,
|
||||
@@ -5367,38 +5333,38 @@
|
||||
"kind": "name",
|
||||
"make": "intrinsic"
|
||||
},
|
||||
276,
|
||||
275,
|
||||
45
|
||||
],
|
||||
["access", 12, "error", 276, 45],
|
||||
["access", 14, "cannot apply '+': operands must both be text or both be numbers", 276, 45],
|
||||
["array", 32, 0, 276, 45],
|
||||
["access", 12, "error", 275, 45],
|
||||
["access", 14, "cannot apply '+': operands must both be text or both be numbers", 275, 45],
|
||||
["array", 32, 0, 275, 45],
|
||||
["stone_text", 14],
|
||||
["push", 32, 14, 276, 45],
|
||||
["frame", 14, 7, 2, 276, 45],
|
||||
["null", 7, 276, 45],
|
||||
["setarg", 14, 0, 7, 276, 45],
|
||||
["push", 32, 14, 275, 45],
|
||||
["frame", 14, 7, 2, 275, 45],
|
||||
["null", 7, 275, 45],
|
||||
["setarg", 14, 0, 7, 275, 45],
|
||||
["stone_text", 12],
|
||||
["setarg", 14, 1, 12, 276, 45],
|
||||
["setarg", 14, 2, 32, 276, 45],
|
||||
["invoke", 14, 7, 276, 45],
|
||||
["disrupt", 276, 45],
|
||||
"add_done_372",
|
||||
["load_field", 7, 30, "path", 276, 51],
|
||||
["setarg", 14, 1, 12, 275, 45],
|
||||
["setarg", 14, 2, 32, 275, 45],
|
||||
["invoke", 14, 7, 275, 45],
|
||||
["disrupt", 275, 45],
|
||||
"add_done_370",
|
||||
["load_field", 7, 30, "path", 275, 51],
|
||||
"_nop_tc_4",
|
||||
"_nop_tc_5",
|
||||
["is_text", 12, 7, 276, 51],
|
||||
["jump_false", 12, "add_cn_376", 276, 51],
|
||||
["concat", 12, 31, 7, 276, 51],
|
||||
["jump", "add_done_375", 276, 51],
|
||||
"add_cn_376",
|
||||
["is_text", 12, 7, 275, 51],
|
||||
["jump_false", 12, "add_cn_374", 275, 51],
|
||||
["concat", 12, 31, 7, 275, 51],
|
||||
["jump", "add_done_373", 275, 51],
|
||||
"add_cn_374",
|
||||
"_nop_tc_6",
|
||||
["jump", "add_err_377", 276, 51],
|
||||
["jump", "add_err_375", 275, 51],
|
||||
"_nop_ucfg_5",
|
||||
"_nop_ucfg_6",
|
||||
"_nop_ucfg_7",
|
||||
"_nop_ucfg_8",
|
||||
"add_err_377",
|
||||
"add_err_375",
|
||||
[
|
||||
"access",
|
||||
7,
|
||||
@@ -5407,71 +5373,37 @@
|
||||
"kind": "name",
|
||||
"make": "intrinsic"
|
||||
},
|
||||
276,
|
||||
275,
|
||||
51
|
||||
],
|
||||
["access", 14, "error", 276, 51],
|
||||
["access", 31, "cannot apply '+': operands must both be text or both be numbers", 276, 51],
|
||||
["array", 32, 0, 276, 51],
|
||||
["access", 14, "error", 275, 51],
|
||||
["access", 31, "cannot apply '+': operands must both be text or both be numbers", 275, 51],
|
||||
["array", 32, 0, 275, 51],
|
||||
["stone_text", 31],
|
||||
["push", 32, 31, 276, 51],
|
||||
["frame", 31, 7, 2, 276, 51],
|
||||
["null", 7, 276, 51],
|
||||
["setarg", 31, 0, 7, 276, 51],
|
||||
["push", 32, 31, 275, 51],
|
||||
["frame", 31, 7, 2, 275, 51],
|
||||
["null", 7, 275, 51],
|
||||
["setarg", 31, 0, 7, 275, 51],
|
||||
["stone_text", 14],
|
||||
["setarg", 31, 1, 14, 276, 51],
|
||||
["setarg", 31, 2, 32, 276, 51],
|
||||
["invoke", 31, 7, 276, 51],
|
||||
["disrupt", 276, 51],
|
||||
"add_done_375",
|
||||
["frame", 7, 10, 2, 276, 5],
|
||||
["setarg", 7, 1, 11, 276, 5],
|
||||
["setarg", 31, 1, 14, 275, 51],
|
||||
["setarg", 31, 2, 32, 275, 51],
|
||||
["invoke", 31, 7, 275, 51],
|
||||
["disrupt", 275, 51],
|
||||
"add_done_373",
|
||||
["frame", 7, 10, 2, 275, 5],
|
||||
["setarg", 7, 1, 11, 275, 5],
|
||||
["stone_text", 12],
|
||||
["setarg", 7, 2, 12, 276, 5],
|
||||
["invoke", 7, 11, 276, 5],
|
||||
["access", 7, 1, 277, 17],
|
||||
["add", 29, 29, 7, 277, 17],
|
||||
["jump", "while_start_370", 277, 17],
|
||||
"while_end_371",
|
||||
["access", 7, "bootstrap: cache seeded\n", 279, 12],
|
||||
[
|
||||
"access",
|
||||
10,
|
||||
{
|
||||
"name": "os",
|
||||
"kind": "name",
|
||||
"make": "intrinsic"
|
||||
},
|
||||
279,
|
||||
3
|
||||
],
|
||||
["is_proxy", 11, 10, 279, 3],
|
||||
["jump_false", 11, "record_path_378", 279, 3],
|
||||
["null", 11, 279, 3],
|
||||
["access", 12, "print", 279, 3],
|
||||
["array", 14, 0, 279, 3],
|
||||
["stone_text", 7],
|
||||
["push", 14, 7, 279, 3],
|
||||
["frame", 28, 10, 2, 279, 3],
|
||||
["setarg", 28, 0, 11, 279, 3],
|
||||
["stone_text", 12],
|
||||
["setarg", 28, 1, 12, 279, 3],
|
||||
["setarg", 28, 2, 14, 279, 3],
|
||||
["invoke", 28, 11, 279, 3],
|
||||
["jump", "call_done_379", 279, 3],
|
||||
"record_path_378",
|
||||
["load_field", 12, 10, "print", 279, 3],
|
||||
["frame", 14, 12, 1, 279, 3],
|
||||
["setarg", 14, 0, 10, 279, 3],
|
||||
["stone_text", 7],
|
||||
["setarg", 14, 1, 7, 279, 3],
|
||||
["invoke", 14, 11, 279, 3],
|
||||
"call_done_379",
|
||||
["setarg", 7, 2, 12, 275, 5],
|
||||
["invoke", 7, 11, 275, 5],
|
||||
["access", 7, 1, 276, 17],
|
||||
["add", 29, 29, 7, 276, 17],
|
||||
["jump", "while_start_368", 276, 17],
|
||||
"while_end_369",
|
||||
"if_end_350",
|
||||
["null", 7, 279, 3],
|
||||
["return", 7, 279, 3]
|
||||
["null", 7, 276, 17],
|
||||
["return", 7, 276, 17]
|
||||
],
|
||||
"_write_types": [null, null, null, "bool", null, null, null, null, "function", "function", "function", null, "function", null, null, null, null, null, "function", null, null, null, "function", "function", null, null, "int", "function", "function", "function", "function", "function", "function", "function", "function", "function", "function", "function", "function", "function", "function", "function", "function", null, null, "text", null, null, "text", null, null, "text", null, null, "text", null, null, "text", null, null, "text", null, null, "text", null, null, "text", null, null, "function", null, null, "text", null, null, "text", null, null, null, null, null, null, null, null, null, "null", "text", "array", null, null, null, "text", null, "text", null, null, null, "null", "text", "array", null, null, null, "text", null, "text", "text", "bool", null, null, "text", "text", "array", null, null, "null", null, null, "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "array", "int", "bool", null, null, null, "text", "text", "bool", null, null, "text", "text", "array", null, null, "null", null, null, "bool", "bool", null, "text", "text", "array", null, null, "null", null, null, "int", "text", null, null, null, "null", "text", "array", null, null, null, "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "array", "int", "bool", null, null, null, "text", "text", "bool", null, null, "text", "text", "array", null, null, "null", null, null, "bool", "bool", null, "text", "text", "array", null, null, "null", null, null, "int", "text", null, null, null, "null", "text", "array", null, null, null, "null"],
|
||||
"_write_types": [null, null, null, "bool", null, null, null, null, "function", "function", "function", null, "function", null, null, null, null, null, "function", null, null, null, "function", "function", null, null, "int", "function", "function", "function", "function", "function", "function", "function", "function", "function", "function", "function", "function", "function", "function", "function", "function", null, null, "text", null, null, "text", null, null, "text", null, null, "text", null, null, "text", null, null, "text", null, null, "text", null, null, "text", null, null, "function", null, null, "text", null, null, "text", null, null, null, null, null, null, null, null, null, "null", "text", "array", null, null, null, "text", null, "text", null, null, null, "null", "text", "array", null, null, null, "text", null, "text", "text", "bool", null, null, "text", "text", "array", null, null, "null", null, null, "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "array", "int", "bool", null, null, null, "text", "text", "bool", null, null, "text", "text", "array", null, null, "null", null, null, "bool", "bool", null, "text", "text", "array", null, null, "null", null, null, "int", "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "record", "text", "text", "array", "int", "bool", null, null, null, "text", "text", "bool", null, null, "text", "text", "array", null, null, "null", null, null, "bool", "bool", null, "text", "text", "array", null, null, "null", null, null, "int", "null"],
|
||||
"nr_args": 0,
|
||||
"closure_written": {
|
||||
"7": true,
|
||||
|
||||
17499
boot/mcode.cm.mcode
17499
boot/mcode.cm.mcode
File diff suppressed because one or more lines are too long
@@ -3348,7 +3348,7 @@
|
||||
{
|
||||
"_closure_slot_types": {},
|
||||
"disruption_pc": 0,
|
||||
"nr_slots": 7,
|
||||
"nr_slots": 8,
|
||||
"nr_close_slots": 0,
|
||||
"instructions": [
|
||||
["get", 2, 14, 2, 1167, 15],
|
||||
@@ -3356,23 +3356,35 @@
|
||||
["invoke", 3, 2, 1167, 15],
|
||||
["move", 3, 2, 1167, 15],
|
||||
["access", 2, 8, 1, 13],
|
||||
"_nop_tc_1",
|
||||
"_nop_tc_2",
|
||||
["is_num", 4, 1, 1, 13],
|
||||
["jump_false", 4, "num_err_160", 1, 13],
|
||||
["multiply", 4, 1, 2, 1, 13],
|
||||
["jump", "num_done_161", 1, 13],
|
||||
"num_err_160",
|
||||
"_nop_ucfg_1",
|
||||
"_nop_ucfg_2",
|
||||
"_nop_ucfg_3",
|
||||
"_nop_ucfg_4",
|
||||
"_nop_ucfg_5",
|
||||
"_nop_ucfg_6",
|
||||
"_nop_ucfg_7",
|
||||
"_nop_ucfg_8",
|
||||
"_nop_ucfg_9",
|
||||
"_nop_ucfg_10",
|
||||
"_nop_ucfg_11",
|
||||
"_nop_ucfg_12",
|
||||
[
|
||||
"access",
|
||||
2,
|
||||
{
|
||||
"name": "log",
|
||||
"kind": "name",
|
||||
"make": "intrinsic"
|
||||
},
|
||||
1,
|
||||
13
|
||||
],
|
||||
["access", 5, "error", 1, 13],
|
||||
["access", 6, "operands must be numbers", 1, 13],
|
||||
["array", 7, 0, 1, 13],
|
||||
["stone_text", 6],
|
||||
["push", 7, 6, 1, 13],
|
||||
["frame", 6, 2, 2, 1, 13],
|
||||
["null", 2, 1, 13],
|
||||
["setarg", 6, 0, 2, 1, 13],
|
||||
["stone_text", 5],
|
||||
["setarg", 6, 1, 5, 1, 13],
|
||||
["setarg", 6, 2, 7, 1, 13],
|
||||
["invoke", 6, 2, 1, 13],
|
||||
["disrupt", 1, 13],
|
||||
"num_done_161",
|
||||
[
|
||||
"access",
|
||||
@@ -3459,7 +3471,7 @@
|
||||
"_nop_ur_1",
|
||||
"_nop_ur_2"
|
||||
],
|
||||
"_write_types": [null, null, null, null, null, null, "int", "num", null, null, null, null, null, null, null, null, null, null, null, "array", null, "text", null, null, null, null, null, "array", null, "text", null, null, null, null, null, "array", null, "text", null, null, null],
|
||||
"_write_types": [null, null, null, null, null, null, "int", "num", "bool", null, "text", "text", "array", null, null, "null", null, null, null, "array", null, "text", null, null, null, null, null, "array", null, "text", null, null, null, null, null, "array", null, "text", null, null, null],
|
||||
"name": "<anonymous>",
|
||||
"filename": ".cell/packages/core/qbe_emit.cm",
|
||||
"nr_args": 1
|
||||
@@ -3467,7 +3479,7 @@
|
||||
{
|
||||
"_closure_slot_types": {},
|
||||
"disruption_pc": 0,
|
||||
"nr_slots": 9,
|
||||
"nr_slots": 10,
|
||||
"nr_close_slots": 0,
|
||||
"instructions": [
|
||||
["get", 3, 14, 2, 1174, 15],
|
||||
@@ -3541,23 +3553,35 @@
|
||||
"if_else_162",
|
||||
"if_end_163",
|
||||
["access", 5, 8, 1, 13],
|
||||
"_nop_tc_1",
|
||||
"_nop_tc_2",
|
||||
["is_num", 6, 1, 1, 13],
|
||||
["jump_false", 6, "num_err_164", 1, 13],
|
||||
["multiply", 6, 1, 5, 1, 13],
|
||||
["jump", "num_done_165", 1, 13],
|
||||
"num_err_164",
|
||||
"_nop_ucfg_1",
|
||||
"_nop_ucfg_2",
|
||||
"_nop_ucfg_3",
|
||||
"_nop_ucfg_4",
|
||||
"_nop_ucfg_5",
|
||||
"_nop_ucfg_6",
|
||||
"_nop_ucfg_7",
|
||||
"_nop_ucfg_8",
|
||||
"_nop_ucfg_9",
|
||||
"_nop_ucfg_10",
|
||||
"_nop_ucfg_11",
|
||||
"_nop_ucfg_12",
|
||||
[
|
||||
"access",
|
||||
5,
|
||||
{
|
||||
"name": "log",
|
||||
"kind": "name",
|
||||
"make": "intrinsic"
|
||||
},
|
||||
1,
|
||||
13
|
||||
],
|
||||
["access", 7, "error", 1, 13],
|
||||
["access", 8, "operands must be numbers", 1, 13],
|
||||
["array", 9, 0, 1, 13],
|
||||
["stone_text", 8],
|
||||
["push", 9, 8, 1, 13],
|
||||
["frame", 8, 5, 2, 1, 13],
|
||||
["null", 5, 1, 13],
|
||||
["setarg", 8, 0, 5, 1, 13],
|
||||
["stone_text", 7],
|
||||
["setarg", 8, 1, 7, 1, 13],
|
||||
["setarg", 8, 2, 9, 1, 13],
|
||||
["invoke", 8, 5, 1, 13],
|
||||
["disrupt", 1, 13],
|
||||
"num_done_165",
|
||||
[
|
||||
"access",
|
||||
@@ -3624,7 +3648,7 @@
|
||||
["null", 3, 1181, 7],
|
||||
["return", 3, 1181, 7]
|
||||
],
|
||||
"_write_types": [null, null, null, null, null, null, null, null, "text", "bool", null, null, null, "array", null, "text", null, "array", null, "text", null, null, null, null, null, "int", "num", null, null, null, null, null, null, null, null, null, null, null, "array", null, "text", null, null, null, null, null, "array", null, "text", null, null, null, null, null, "null"],
|
||||
"_write_types": [null, null, null, null, null, null, null, null, "text", "bool", null, null, null, "array", null, "text", null, "array", null, "text", null, null, null, null, null, "int", "num", "bool", null, "text", "text", "array", null, null, "null", null, null, null, "array", null, "text", null, null, null, null, null, "array", null, "text", null, null, null, null, null, "null"],
|
||||
"name": "<anonymous>",
|
||||
"filename": ".cell/packages/core/qbe_emit.cm",
|
||||
"nr_args": 2
|
||||
|
||||
20117
boot/streamline.cm.mcode
20117
boot/streamline.cm.mcode
File diff suppressed because one or more lines are too long
140
build.cm
140
build.cm
@@ -65,7 +65,7 @@ function replace_sigils(str, pkg_dir) {
|
||||
function replace_sigils_array(flags, pkg_dir) {
|
||||
var result = []
|
||||
arrfor(flags, function(flag) {
|
||||
push(result, replace_sigils(flag, pkg_dir))
|
||||
result[] = replace_sigils(flag, pkg_dir)
|
||||
})
|
||||
return result
|
||||
}
|
||||
@@ -179,7 +179,7 @@ function bmfst_save(cmd_str, src_path, deps, obj_path) {
|
||||
arrfor(deps, function(dep_path) {
|
||||
var st = memo_stat(dep_path)
|
||||
if (st)
|
||||
push(entries, {p: dep_path, m: st.m, s: st.s})
|
||||
entries[] = {p: dep_path, m: st.m, s: st.s}
|
||||
})
|
||||
var mf = {o: obj_path, d: entries}
|
||||
var mf_path = bmfst_path(cmd_str, src_path)
|
||||
@@ -191,16 +191,16 @@ function bmfst_save(cmd_str, src_path, deps, obj_path) {
|
||||
|
||||
function bmfst_dl_key(setup, link_info) {
|
||||
var parts = [setup.cmd_str, setup.src_path]
|
||||
push(parts, 'target:' + text(link_info.target))
|
||||
push(parts, 'cc:' + text(link_info.cc))
|
||||
parts[] = 'target:' + text(link_info.target)
|
||||
parts[] = 'cc:' + text(link_info.cc)
|
||||
arrfor(link_info.extra_objects, function(obj) {
|
||||
if (obj != null) push(parts, 'extra:' + text(obj))
|
||||
if (obj != null) parts[] = 'extra:' + text(obj)
|
||||
})
|
||||
arrfor(link_info.ldflags, function(flag) {
|
||||
push(parts, 'ldflag:' + text(flag))
|
||||
parts[] = 'ldflag:' + text(flag)
|
||||
})
|
||||
arrfor(link_info.target_ldflags, function(flag) {
|
||||
push(parts, 'target_ldflag:' + text(flag))
|
||||
parts[] = 'target_ldflag:' + text(flag)
|
||||
})
|
||||
return text(parts, '\n')
|
||||
}
|
||||
@@ -227,7 +227,7 @@ function bmfst_dl_save(setup, link_info, deps, dylib_path) {
|
||||
arrfor(deps, function(dep_path) {
|
||||
var st = memo_stat(dep_path)
|
||||
if (st)
|
||||
push(entries, {p: dep_path, m: st.m, s: st.s})
|
||||
entries[] = {p: dep_path, m: st.m, s: st.s}
|
||||
})
|
||||
var mf = {dylib: dylib_path, d: entries}
|
||||
var mf_path = cache_path(bmfst_dl_key(setup, link_info), SALT_BMFST_DL)
|
||||
@@ -259,7 +259,7 @@ function get_c_deps(cc, flags, src_path) {
|
||||
var dep_file = '/tmp/cell_deps_' + content_hash(src_path) + '.d'
|
||||
var dep_cmd = [cc, '-MM', '-MG', '-MF', '"' + dep_file + '"']
|
||||
dep_cmd = array(dep_cmd, flags)
|
||||
push(dep_cmd, '"' + src_path + '"')
|
||||
dep_cmd[] = '"' + src_path + '"'
|
||||
var ret = os.system(text(dep_cmd, ' ') + ' 2>/dev/null')
|
||||
if (ret != 0) return [src_path]
|
||||
if (!fd.is_file(dep_file)) return [src_path]
|
||||
@@ -274,9 +274,9 @@ function hash_all_deps(cmd_str, deps) {
|
||||
arrfor(deps, function(dep_path) {
|
||||
var content = memo_read(dep_path)
|
||||
if (content != null)
|
||||
push(parts, dep_path + '\n' + content)
|
||||
parts[] = dep_path + '\n' + content
|
||||
else
|
||||
push(parts, dep_path + '\n<missing>')
|
||||
parts[] = dep_path + '\n<missing>'
|
||||
})
|
||||
return text(parts, '\n')
|
||||
}
|
||||
@@ -310,16 +310,16 @@ function compile_setup(pkg, file, target, opts) {
|
||||
common_flags = array(common_flags, ['-Os', '-DNDEBUG'])
|
||||
}
|
||||
|
||||
push(common_flags, '-DCELL_USE_NAME=' + sym_name)
|
||||
push(common_flags, '-I"' + pkg_dir + '"')
|
||||
common_flags[] = '-DCELL_USE_NAME=' + sym_name
|
||||
common_flags[] = '-I"' + pkg_dir + '"'
|
||||
|
||||
if (fd.is_dir(pkg_dir + '/include')) {
|
||||
push(common_flags, '-I"' + pkg_dir + '/include"')
|
||||
common_flags[] = '-I"' + pkg_dir + '/include"'
|
||||
}
|
||||
|
||||
if (pkg != 'core') {
|
||||
core_dir = shop.get_package_dir('core')
|
||||
push(common_flags, '-I"' + core_dir + '/source"')
|
||||
common_flags[] = '-I"' + core_dir + '/source"'
|
||||
}
|
||||
|
||||
arrfor(cflags, function(flag) {
|
||||
@@ -331,16 +331,16 @@ function compile_setup(pkg, file, target, opts) {
|
||||
f = '-I"' + pkg_dir + '/' + ipath + '"'
|
||||
}
|
||||
}
|
||||
push(common_flags, f)
|
||||
common_flags[] = f
|
||||
})
|
||||
|
||||
arrfor(target_cflags, function(flag) {
|
||||
push(common_flags, flag)
|
||||
common_flags[] = flag
|
||||
})
|
||||
|
||||
var cmd_parts = [cc, '-c', '-fPIC']
|
||||
cmd_parts = array(cmd_parts, common_flags)
|
||||
push(cmd_parts, '"' + src_path + '"')
|
||||
cmd_parts[] = '"' + src_path + '"'
|
||||
|
||||
return {
|
||||
cmd_str: text(cmd_parts, ' '),
|
||||
@@ -513,7 +513,7 @@ Build.build_package = function(pkg, target, exclude_main, buildtype) {
|
||||
|
||||
arrfor(c_files, function(file) {
|
||||
var obj = Build.compile_file(pkg, file, _target, {buildtype: _buildtype, cflags: cached_cflags})
|
||||
push(objects, obj)
|
||||
objects[] = obj
|
||||
})
|
||||
|
||||
return objects
|
||||
@@ -527,16 +527,16 @@ Build.build_package = function(pkg, target, exclude_main, buildtype) {
|
||||
// link_opts: {extra_objects, ldflags, target_ldflags, target, cc}
|
||||
function compute_dylib_content(full_content, link_opts) {
|
||||
var parts = [full_content]
|
||||
push(parts, 'target:' + text(link_opts.target))
|
||||
push(parts, 'cc:' + text(link_opts.cc))
|
||||
parts[] = 'target:' + text(link_opts.target)
|
||||
parts[] = 'cc:' + text(link_opts.cc)
|
||||
arrfor(link_opts.extra_objects, function(obj) {
|
||||
if (obj != null) push(parts, 'extra:' + text(obj))
|
||||
if (obj != null) parts[] = 'extra:' + text(obj)
|
||||
})
|
||||
arrfor(link_opts.ldflags, function(flag) {
|
||||
push(parts, 'ldflag:' + text(flag))
|
||||
parts[] = 'ldflag:' + text(flag)
|
||||
})
|
||||
arrfor(link_opts.target_ldflags, function(flag) {
|
||||
push(parts, 'target_ldflag:' + text(flag))
|
||||
parts[] = 'target_ldflag:' + text(flag)
|
||||
})
|
||||
return text(parts, '\n')
|
||||
}
|
||||
@@ -570,7 +570,7 @@ Build.build_module_dylib = function(pkg, file, target, opts) {
|
||||
f = '-L"' + setup.pkg_dir + '/' + lpath + '"'
|
||||
}
|
||||
}
|
||||
push(resolved_ldflags, f)
|
||||
resolved_ldflags[] = f
|
||||
})
|
||||
|
||||
var build_dir = get_build_dir()
|
||||
@@ -683,18 +683,18 @@ Build.build_module_dylib = function(pkg, file, target, opts) {
|
||||
'-Wl,-rpath,' + local_dir
|
||||
])
|
||||
} else if (tc.system == 'windows') {
|
||||
push(cmd_parts, '-Wl,--allow-shlib-undefined')
|
||||
cmd_parts[] = '-Wl,--allow-shlib-undefined'
|
||||
}
|
||||
|
||||
push(cmd_parts, '-L"' + local_dir + '"')
|
||||
push(cmd_parts, '"' + text(obj) + '"')
|
||||
cmd_parts[] = '-L"' + local_dir + '"'
|
||||
cmd_parts[] = '"' + text(obj) + '"'
|
||||
arrfor(_extra, function(extra_obj) {
|
||||
if (extra_obj != null) push(cmd_parts, '"' + text(extra_obj) + '"')
|
||||
if (extra_obj != null) cmd_parts[] = '"' + text(extra_obj) + '"'
|
||||
})
|
||||
cmd_parts = array(cmd_parts, resolved_ldflags)
|
||||
cmd_parts = array(cmd_parts, target_ldflags)
|
||||
push(cmd_parts, '-o')
|
||||
push(cmd_parts, '"' + dylib_path + '"')
|
||||
cmd_parts[] = '-o'
|
||||
cmd_parts[] = '"' + dylib_path + '"'
|
||||
|
||||
cmd_str = text(cmd_parts, ' ')
|
||||
if (_opts.verbose) log.build('[verbose] link: ' + cmd_str)
|
||||
@@ -737,7 +737,7 @@ Build.compile_c_module = function(pkg, file, target, opts) {
|
||||
if (pkg != 'core') {
|
||||
arrfor(sources, function(src_file) {
|
||||
var obj = Build.compile_file(pkg, src_file, _target, {buildtype: _buildtype, cflags: cached_cflags})
|
||||
if (obj != null) push(support_objects, obj)
|
||||
if (obj != null) support_objects[] = obj
|
||||
})
|
||||
}
|
||||
|
||||
@@ -767,27 +767,23 @@ Build.build_dynamic = function(pkg, target, buildtype, opts) {
|
||||
if (pkg != 'core') {
|
||||
arrfor(sources, function(src_file) {
|
||||
var obj = Build.compile_file(pkg, src_file, _target, {buildtype: _buildtype, cflags: cached_cflags, verbose: _opts.verbose, force: _opts.force})
|
||||
if (obj != null) push(support_objects, obj)
|
||||
if (obj != null) support_objects[] = obj
|
||||
})
|
||||
}
|
||||
|
||||
if (total > 0)
|
||||
os.print(' Building C modules ')
|
||||
|
||||
arrfor(c_files, function(file) {
|
||||
var sym_name = shop.c_symbol_for_file(pkg, file)
|
||||
var dylib = Build.build_module_dylib(pkg, file, _target, {buildtype: _buildtype, extra_objects: support_objects, cflags: cached_cflags, verbose: _opts.verbose, force: _opts.force})
|
||||
if (dylib) {
|
||||
push(results, {file: file, symbol: sym_name, dylib: dylib})
|
||||
results[] = {file: file, symbol: sym_name, dylib: dylib}
|
||||
} else {
|
||||
failed = failed + 1
|
||||
}
|
||||
done = done + 1
|
||||
os.print('.')
|
||||
})
|
||||
|
||||
if (total > 0)
|
||||
os.print(` ${text(done)}/${text(total)}${failed > 0 ? `, ${text(failed)} failed` : ''}\n`)
|
||||
log.build(` Building C modules (${text(done)} ok${failed > 0 ? `, ${text(failed)} failed` : ''})`)
|
||||
|
||||
// Write manifest so runtime can find dylibs without the build module
|
||||
var mpath = manifest_path(pkg)
|
||||
@@ -818,7 +814,7 @@ Build.build_static = function(packages, target, output, buildtype) {
|
||||
var objects = Build.build_package(pkg, _target, !is_core, _buildtype)
|
||||
|
||||
arrfor(objects, function(obj) {
|
||||
push(all_objects, obj)
|
||||
all_objects[] = obj
|
||||
})
|
||||
|
||||
// Collect LDFLAGS (with sigil replacement)
|
||||
@@ -838,7 +834,7 @@ Build.build_static = function(packages, target, output, buildtype) {
|
||||
f = '-L"' + pkg_dir + '/' + lpath + '"'
|
||||
}
|
||||
}
|
||||
push(all_ldflags, f)
|
||||
all_ldflags[] = f
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -860,18 +856,18 @@ Build.build_static = function(packages, target, output, buildtype) {
|
||||
var cmd_parts = [cc]
|
||||
|
||||
arrfor(all_objects, function(obj) {
|
||||
push(cmd_parts, '"' + obj + '"')
|
||||
cmd_parts[] = '"' + obj + '"'
|
||||
})
|
||||
|
||||
arrfor(all_ldflags, function(flag) {
|
||||
push(cmd_parts, flag)
|
||||
cmd_parts[] = flag
|
||||
})
|
||||
|
||||
arrfor(target_ldflags, function(flag) {
|
||||
push(cmd_parts, flag)
|
||||
cmd_parts[] = flag
|
||||
})
|
||||
|
||||
push(cmd_parts, '-o', '"' + out_path + '"')
|
||||
cmd_parts[] = '-o', '"' + out_path + '"'
|
||||
|
||||
var cmd_str = text(cmd_parts, ' ')
|
||||
|
||||
@@ -925,7 +921,7 @@ function qbe_insert_dead_labels(il_text) {
|
||||
line = lines[i]
|
||||
trimmed = trim(line)
|
||||
if (need_label && !starts_with(trimmed, '@') && !starts_with(trimmed, '}') && length(trimmed) > 0) {
|
||||
push(result, "@_dead_" + text(dead_id))
|
||||
result[] = "@_dead_" + text(dead_id)
|
||||
dead_id = dead_id + 1
|
||||
need_label = false
|
||||
}
|
||||
@@ -935,7 +931,7 @@ function qbe_insert_dead_labels(il_text) {
|
||||
if (starts_with(trimmed, 'ret ') || starts_with(trimmed, 'jmp ')) {
|
||||
need_label = true
|
||||
}
|
||||
push(result, line)
|
||||
result[] = line
|
||||
i = i + 1
|
||||
}
|
||||
return text(result, "\n")
|
||||
@@ -1126,16 +1122,16 @@ Build.compile_cm_to_mach = function(src_path) {
|
||||
// output: path to write the generated .c file
|
||||
Build.generate_module_table = function(modules, output) {
|
||||
var lines = []
|
||||
push(lines, '/* Generated module table — do not edit */')
|
||||
push(lines, '#include <stddef.h>')
|
||||
push(lines, '#include <string.h>')
|
||||
push(lines, '')
|
||||
push(lines, 'struct cell_embedded_entry {')
|
||||
push(lines, ' const char *name;')
|
||||
push(lines, ' const unsigned char *data;')
|
||||
push(lines, ' size_t size;')
|
||||
push(lines, '};')
|
||||
push(lines, '')
|
||||
lines[] = '/* Generated module table — do not edit */'
|
||||
lines[] = '#include <stddef.h>'
|
||||
lines[] = '#include <string.h>'
|
||||
lines[] = ''
|
||||
lines[] = 'struct cell_embedded_entry {'
|
||||
lines[] = ' const char *name;'
|
||||
lines[] = ' const unsigned char *data;'
|
||||
lines[] = ' size_t size;'
|
||||
lines[] = '};'
|
||||
lines[] = ''
|
||||
|
||||
var entries = []
|
||||
arrfor(modules, function(mod) {
|
||||
@@ -1144,27 +1140,27 @@ Build.generate_module_table = function(modules, output) {
|
||||
var bytes = array(mach)
|
||||
var hex = []
|
||||
arrfor(bytes, function(b) {
|
||||
push(hex, '0x' + text(b, 'h2'))
|
||||
hex[] = '0x' + text(b, 'h2')
|
||||
})
|
||||
push(lines, 'static const unsigned char mod_' + safe + '_data[] = {')
|
||||
push(lines, ' ' + text(hex, ', '))
|
||||
push(lines, '};')
|
||||
push(lines, '')
|
||||
push(entries, safe)
|
||||
lines[] = 'static const unsigned char mod_' + safe + '_data[] = {'
|
||||
lines[] = ' ' + text(hex, ', ')
|
||||
lines[] = '};'
|
||||
lines[] = ''
|
||||
entries[] = safe
|
||||
log.console('Embedded: ' + mod.name + ' (' + text(length(bytes)) + ' bytes)')
|
||||
})
|
||||
|
||||
// Lookup function
|
||||
push(lines, 'const struct cell_embedded_entry *cell_embedded_module_lookup(const char *name) {')
|
||||
lines[] = 'const struct cell_embedded_entry *cell_embedded_module_lookup(const char *name) {'
|
||||
arrfor(modules, function(mod, i) {
|
||||
var safe = entries[i]
|
||||
push(lines, ' if (strcmp(name, "' + mod.name + '") == 0) {')
|
||||
push(lines, ' static const struct cell_embedded_entry e = {"' + mod.name + '", mod_' + safe + '_data, sizeof(mod_' + safe + '_data)};')
|
||||
push(lines, ' return &e;')
|
||||
push(lines, ' }')
|
||||
lines[] = ' if (strcmp(name, "' + mod.name + '") == 0) {'
|
||||
lines[] = ' static const struct cell_embedded_entry e = {"' + mod.name + '", mod_' + safe + '_data, sizeof(mod_' + safe + '_data)};'
|
||||
lines[] = ' return &e;'
|
||||
lines[] = ' }'
|
||||
})
|
||||
push(lines, ' return (void *)0;')
|
||||
push(lines, '}')
|
||||
lines[] = ' return (void *)0;'
|
||||
lines[] = '}'
|
||||
|
||||
var c_text = text(lines, '\n')
|
||||
fd.slurpwrite(output, stone(blob(c_text)))
|
||||
@@ -1192,14 +1188,14 @@ Build.build_all_dynamic = function(target, buildtype, opts) {
|
||||
// Build core first
|
||||
if (find(packages, function(p) { return p == 'core' }) != null) {
|
||||
core_mods = Build.build_dynamic('core', _target, _buildtype, _opts)
|
||||
push(results, {package: 'core', modules: core_mods})
|
||||
results[] = {package: 'core', modules: core_mods}
|
||||
}
|
||||
|
||||
// Build other packages
|
||||
arrfor(packages, function(pkg) {
|
||||
if (pkg == 'core') return
|
||||
var pkg_mods = Build.build_dynamic(pkg, _target, _buildtype, _opts)
|
||||
push(results, {package: pkg, modules: pkg_mods})
|
||||
results[] = {package: pkg, modules: pkg_mods}
|
||||
})
|
||||
|
||||
// Print build report
|
||||
|
||||
12
cellfs.cm
12
cellfs.cm
@@ -152,7 +152,7 @@ function mount(source, name) {
|
||||
})
|
||||
}
|
||||
}
|
||||
push(mounts, mount_info)
|
||||
mounts[] = mount_info
|
||||
return
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ function mount(source, name) {
|
||||
log.error("Unsupported mount source type: " + source); disrupt
|
||||
}
|
||||
|
||||
push(mounts, mount_info)
|
||||
mounts[] = mount_info
|
||||
}
|
||||
|
||||
function unmount(name_or_source) {
|
||||
@@ -356,7 +356,7 @@ function enumerate(_path, recurse) {
|
||||
arrfor(list, function(item) {
|
||||
var item_rel = rel_prefix ? rel_prefix + "/" + item : item
|
||||
var child_st = null
|
||||
push(results, item_rel)
|
||||
results[] = item_rel
|
||||
|
||||
if (recurse) {
|
||||
child_st = fd.stat(fd.join_paths(curr_full, item))
|
||||
@@ -396,7 +396,7 @@ function enumerate(_path, recurse) {
|
||||
|
||||
if (!seen[rel]) {
|
||||
seen[rel] = true
|
||||
push(results, rel)
|
||||
results[] = rel
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -455,7 +455,7 @@ function globfs(globs, _dir) {
|
||||
}
|
||||
} else {
|
||||
if (!check_neg(item_rel) && check_pos(item_rel)) {
|
||||
push(results, item_rel)
|
||||
results[] = item_rel
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -479,7 +479,7 @@ function globfs(globs, _dir) {
|
||||
if (length(rel) == 0) return
|
||||
|
||||
if (!check_neg(rel) && check_pos(rel)) {
|
||||
push(results, rel)
|
||||
results[] = rel
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
18
cfg.ce
18
cfg.ce
@@ -168,7 +168,7 @@ var run = function() {
|
||||
if (is_array(instr)) {
|
||||
if (block_start_pcs[text(pc)]) {
|
||||
if (current_block != null) {
|
||||
push(blocks, current_block)
|
||||
blocks[] = current_block
|
||||
}
|
||||
current_block = {
|
||||
id: length(blocks),
|
||||
@@ -184,7 +184,7 @@ var run = function() {
|
||||
}
|
||||
|
||||
if (current_block != null) {
|
||||
push(current_block.instrs, {pc: pc, instr: instr})
|
||||
current_block.instrs[] = {pc: pc, instr: instr}
|
||||
current_block.end_pc = pc
|
||||
n = length(instr)
|
||||
line_num = instr[n - 2]
|
||||
@@ -200,7 +200,7 @@ var run = function() {
|
||||
ii = ii + 1
|
||||
}
|
||||
if (current_block != null) {
|
||||
push(blocks, current_block)
|
||||
blocks[] = current_block
|
||||
}
|
||||
|
||||
// Build block index
|
||||
@@ -235,19 +235,19 @@ var run = function() {
|
||||
if (target_bi <= bi) {
|
||||
edge_type = "loop back-edge"
|
||||
}
|
||||
push(blk.edges, {target: target_bi, kind: edge_type})
|
||||
blk.edges[] = {target: target_bi, kind: edge_type}
|
||||
}
|
||||
|
||||
if (is_conditional_jump(last_op)) {
|
||||
if (bi + 1 < length(blocks)) {
|
||||
push(blk.edges, {target: bi + 1, kind: "fallthrough"})
|
||||
blk.edges[] = {target: bi + 1, kind: "fallthrough"}
|
||||
}
|
||||
}
|
||||
} else if (is_terminator(last_op)) {
|
||||
push(blk.edges, {target: -1, kind: "EXIT (" + last_op + ")"})
|
||||
blk.edges[] = {target: -1, kind: "EXIT (" + last_op + ")"}
|
||||
} else {
|
||||
if (bi + 1 < length(blocks)) {
|
||||
push(blk.edges, {target: bi + 1, kind: "fallthrough"})
|
||||
blk.edges[] = {target: bi + 1, kind: "fallthrough"}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,7 +308,7 @@ var run = function() {
|
||||
parts = []
|
||||
j = 1
|
||||
while (j < n - 2) {
|
||||
push(parts, fmt_val(instr[j]))
|
||||
parts[] = fmt_val(instr[j])
|
||||
j = j + 1
|
||||
}
|
||||
operands = text(parts, ", ")
|
||||
@@ -381,7 +381,7 @@ var run = function() {
|
||||
parts = []
|
||||
j = 1
|
||||
while (j < n - 2) {
|
||||
push(parts, fmt_val(instr[j]))
|
||||
parts[] = fmt_val(instr[j])
|
||||
j = j + 1
|
||||
}
|
||||
operands = text(parts, ", ")
|
||||
|
||||
12
clean.ce
12
clean.ce
@@ -93,13 +93,13 @@ if (is_shop_scope) {
|
||||
packages_to_clean = shop.list_packages()
|
||||
} else {
|
||||
// Single package
|
||||
push(packages_to_clean, scope)
|
||||
packages_to_clean[] = scope
|
||||
|
||||
if (deep) {
|
||||
_gather = function() {
|
||||
deps = pkg.gather_dependencies(scope)
|
||||
arrfor(deps, function(dep) {
|
||||
push(packages_to_clean, dep)
|
||||
packages_to_clean[] = dep
|
||||
})
|
||||
} disruption {
|
||||
// Skip if can't read dependencies
|
||||
@@ -116,11 +116,11 @@ var packages_dir = replace(shop.get_package_dir(''), /\/$/, '') // Get base pack
|
||||
if (clean_build) {
|
||||
// Nuke entire build cache (content-addressed, per-package clean impractical)
|
||||
if (fd.is_dir(build_dir)) {
|
||||
push(dirs_to_delete, build_dir)
|
||||
dirs_to_delete[] = build_dir
|
||||
}
|
||||
// Clean orphaned lib/ directory if it exists (legacy)
|
||||
if (fd.is_dir(lib_dir)) {
|
||||
push(dirs_to_delete, lib_dir)
|
||||
dirs_to_delete[] = lib_dir
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ if (clean_fetch) {
|
||||
if (is_shop_scope) {
|
||||
// Clean entire packages directory (dangerous!)
|
||||
if (fd.is_dir(packages_dir)) {
|
||||
push(dirs_to_delete, packages_dir)
|
||||
dirs_to_delete[] = packages_dir
|
||||
}
|
||||
} else {
|
||||
// Clean specific package directories
|
||||
@@ -137,7 +137,7 @@ if (clean_fetch) {
|
||||
|
||||
var pkg_dir = shop.get_package_dir(p)
|
||||
if (fd.is_dir(pkg_dir) || fd.is_link(pkg_dir)) {
|
||||
push(dirs_to_delete, pkg_dir)
|
||||
dirs_to_delete[] = pkg_dir
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
24
diff.ce
24
diff.ce
@@ -55,7 +55,7 @@ function collect_tests(specific_test) {
|
||||
match_base = ends_with(match_name, '.cm') ? text(match_name, 0, -3) : match_name
|
||||
if (test_name != match_base) continue
|
||||
}
|
||||
push(test_files, f)
|
||||
test_files[] = f
|
||||
}
|
||||
}
|
||||
return test_files
|
||||
@@ -100,7 +100,7 @@ function diff_test_file(file_path) {
|
||||
src = text(fd.slurp(src_path))
|
||||
ast = analyze(src, src_path)
|
||||
} disruption {
|
||||
push(results.errors, `failed to parse ${file_path}`)
|
||||
results.errors[] = `failed to parse ${file_path}`
|
||||
return results
|
||||
}
|
||||
_read()
|
||||
@@ -124,14 +124,14 @@ function diff_test_file(file_path) {
|
||||
|
||||
// Compare module-level behavior
|
||||
if (opt_error != noopt_error) {
|
||||
push(results.errors, `module load mismatch: opt=${opt_error != null ? opt_error : "ok"} noopt=${noopt_error != null ? noopt_error : "ok"}`)
|
||||
results.errors[] = `module load mismatch: opt=${opt_error != null ? opt_error : "ok"} noopt=${noopt_error != null ? noopt_error : "ok"}`
|
||||
results.failed = results.failed + 1
|
||||
return results
|
||||
}
|
||||
if (opt_error != null) {
|
||||
// Both disrupted during load — that's consistent
|
||||
results.passed = results.passed + 1
|
||||
push(results.tests, {name: "<module>", status: "passed"})
|
||||
results.tests[] = {name: "<module>", status: "passed"}
|
||||
return results
|
||||
}
|
||||
|
||||
@@ -161,15 +161,15 @@ function diff_test_file(file_path) {
|
||||
_run_one_noopt()
|
||||
|
||||
if (opt_err != noopt_err) {
|
||||
push(results.tests, {name: k, status: "failed"})
|
||||
push(results.errors, `${k}: disruption mismatch opt=${opt_err != null ? opt_err : "ok"} noopt=${noopt_err != null ? noopt_err : "ok"}`)
|
||||
results.tests[] = {name: k, status: "failed"}
|
||||
results.errors[] = `${k}: disruption mismatch opt=${opt_err != null ? opt_err : "ok"} noopt=${noopt_err != null ? noopt_err : "ok"}`
|
||||
results.failed = results.failed + 1
|
||||
} else if (!values_equal(opt_result, noopt_result)) {
|
||||
push(results.tests, {name: k, status: "failed"})
|
||||
push(results.errors, `${k}: result mismatch opt=${describe(opt_result)} noopt=${describe(noopt_result)}`)
|
||||
results.tests[] = {name: k, status: "failed"}
|
||||
results.errors[] = `${k}: result mismatch opt=${describe(opt_result)} noopt=${describe(noopt_result)}`
|
||||
results.failed = results.failed + 1
|
||||
} else {
|
||||
push(results.tests, {name: k, status: "passed"})
|
||||
results.tests[] = {name: k, status: "passed"}
|
||||
results.passed = results.passed + 1
|
||||
}
|
||||
}
|
||||
@@ -178,11 +178,11 @@ function diff_test_file(file_path) {
|
||||
} else {
|
||||
// Compare direct return values
|
||||
if (!values_equal(mod_opt, mod_noopt)) {
|
||||
push(results.tests, {name: "<return>", status: "failed"})
|
||||
push(results.errors, `return value mismatch: opt=${describe(mod_opt)} noopt=${describe(mod_noopt)}`)
|
||||
results.tests[] = {name: "<return>", status: "failed"}
|
||||
results.errors[] = `return value mismatch: opt=${describe(mod_opt)} noopt=${describe(mod_noopt)}`
|
||||
results.failed = results.failed + 1
|
||||
} else {
|
||||
push(results.tests, {name: "<return>", status: "passed"})
|
||||
results.tests[] = {name: "<return>", status: "passed"}
|
||||
results.passed = results.passed + 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ var run = function() {
|
||||
var operands = null
|
||||
var line_str = null
|
||||
while (j < n - 2) {
|
||||
push(parts, fmt_val(instr[j]))
|
||||
parts[] = fmt_val(instr[j])
|
||||
j = j + 1
|
||||
}
|
||||
operands = text(parts, ", ")
|
||||
|
||||
@@ -206,7 +206,7 @@ var run = function() {
|
||||
parts = []
|
||||
j = 1
|
||||
while (j < n - 2) {
|
||||
push(parts, fmt_val(instr[j]))
|
||||
parts[] = fmt_val(instr[j])
|
||||
j = j + 1
|
||||
}
|
||||
operands = text(parts, ", ")
|
||||
|
||||
2
fd.cm
2
fd.cm
@@ -83,7 +83,7 @@ fd.globfs = function(globs, dir) {
|
||||
}
|
||||
} else {
|
||||
if (!check_neg(item_rel) && check_pos(item_rel)) {
|
||||
push(results, item_rel)
|
||||
results[] = item_rel
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
26
fold.cm
26
fold.cm
@@ -709,26 +709,26 @@ var fold = function(ast) {
|
||||
if (sv != null && sv.nr_uses == 0) {
|
||||
if (is_pure(stmt.right)) stmt.dead = true
|
||||
if (stmt.right != null && stmt.right.kind == "(" && stmt.right.expression != null && stmt.right.expression.name == "use") {
|
||||
push(ast._diagnostics, {
|
||||
ast._diagnostics[] = {
|
||||
severity: "warning",
|
||||
line: stmt.left.from_row + 1,
|
||||
col: stmt.left.from_column + 1,
|
||||
message: `unused import '${name}'`
|
||||
})
|
||||
}
|
||||
} else if (stmt.kind == "def") {
|
||||
push(ast._diagnostics, {
|
||||
ast._diagnostics[] = {
|
||||
severity: "warning",
|
||||
line: stmt.left.from_row + 1,
|
||||
col: stmt.left.from_column + 1,
|
||||
message: `unused constant '${name}'`
|
||||
})
|
||||
}
|
||||
} else {
|
||||
push(ast._diagnostics, {
|
||||
ast._diagnostics[] = {
|
||||
severity: "warning",
|
||||
line: stmt.left.from_row + 1,
|
||||
col: stmt.left.from_column + 1,
|
||||
message: `unused variable '${name}'`
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -742,15 +742,15 @@ var fold = function(ast) {
|
||||
sv = scope_var(fn_nr, stmt.name)
|
||||
if (sv != null && sv.nr_uses == 0) {
|
||||
stmt.dead = true
|
||||
push(ast._diagnostics, {
|
||||
ast._diagnostics[] = {
|
||||
severity: "warning",
|
||||
line: stmt.from_row + 1,
|
||||
col: stmt.from_column + 1,
|
||||
message: `unused function '${stmt.name}'`
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stmt.dead != true) push(out, stmt)
|
||||
if (stmt.dead != true) out[] = stmt
|
||||
i = i + 1
|
||||
}
|
||||
return out
|
||||
@@ -1039,7 +1039,7 @@ var fold = function(ast) {
|
||||
i = 0
|
||||
while (i < length(ast.intrinsics)) {
|
||||
if (used_intrinsics[ast.intrinsics[i]] == true) {
|
||||
push(new_intrinsics, ast.intrinsics[i])
|
||||
new_intrinsics[] = ast.intrinsics[i]
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
@@ -1071,16 +1071,16 @@ var fold = function(ast) {
|
||||
fn_sv = scope_var(0, fn.name)
|
||||
if (fn_sv != null && fn_sv.nr_uses == 0) {
|
||||
fn.dead = true
|
||||
push(ast._diagnostics, {
|
||||
ast._diagnostics[] = {
|
||||
severity: "warning",
|
||||
line: fn.from_row + 1,
|
||||
col: fn.from_column + 1,
|
||||
message: `unused function '${fn.name}'`
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fn.dead != true) {
|
||||
push(live_fns, fn)
|
||||
live_fns[] = fn
|
||||
}
|
||||
fi = fi + 1
|
||||
}
|
||||
|
||||
12
fuzz.ce
12
fuzz.ce
@@ -89,7 +89,7 @@ function run_fuzz(seed_val) {
|
||||
var _parse = function() {
|
||||
ast = analyze(src, name + ".cm")
|
||||
} disruption {
|
||||
push(errors, "parse error")
|
||||
errors[] = "parse error"
|
||||
}
|
||||
_parse()
|
||||
if (length(errors) > 0) return {seed: seed_val, errors: errors, src: src}
|
||||
@@ -112,7 +112,7 @@ function run_fuzz(seed_val) {
|
||||
|
||||
// Check module-level behavior
|
||||
if (opt_err != noopt_err) {
|
||||
push(errors, `module load: opt=${opt_err != null ? opt_err : "ok"} noopt=${noopt_err != null ? noopt_err : "ok"}`)
|
||||
errors[] = `module load: opt=${opt_err != null ? opt_err : "ok"} noopt=${noopt_err != null ? noopt_err : "ok"}`
|
||||
return {seed: seed_val, errors: errors, src: src}
|
||||
}
|
||||
if (opt_err != null) {
|
||||
@@ -137,10 +137,10 @@ function run_fuzz(seed_val) {
|
||||
_run()
|
||||
|
||||
if (is_text(ret)) {
|
||||
push(errors, `self-check ${key}: ${ret}`)
|
||||
errors[] = `self-check ${key}: ${ret}`
|
||||
}
|
||||
if (run_err != null) {
|
||||
push(errors, `self-check ${key}: unexpected disruption`)
|
||||
errors[] = `self-check ${key}: unexpected disruption`
|
||||
}
|
||||
}
|
||||
k = k + 1
|
||||
@@ -174,9 +174,9 @@ function run_fuzz(seed_val) {
|
||||
_run_noopt()
|
||||
|
||||
if (opt_fn_err != noopt_fn_err) {
|
||||
push(errors, `diff ${key2}: opt=${opt_fn_err != null ? opt_fn_err : "ok"} noopt=${noopt_fn_err != null ? noopt_fn_err : "ok"}`)
|
||||
errors[] = `diff ${key2}: opt=${opt_fn_err != null ? opt_fn_err : "ok"} noopt=${noopt_fn_err != null ? noopt_fn_err : "ok"}`
|
||||
} else if (!values_equal(opt_result, noopt_result)) {
|
||||
push(errors, `diff ${key2}: opt=${describe(opt_result)} noopt=${describe(noopt_result)}`)
|
||||
errors[] = `diff ${key2}: opt=${describe(opt_result)} noopt=${describe(noopt_result)}`
|
||||
}
|
||||
}
|
||||
k2 = k2 + 1
|
||||
|
||||
@@ -241,7 +241,7 @@ function gen_array_test() {
|
||||
var v = 0
|
||||
while (i < n) {
|
||||
v = rand_int(-100, 100)
|
||||
push(vals, v)
|
||||
vals[] = v
|
||||
sum = sum + v
|
||||
i = i + 1
|
||||
}
|
||||
@@ -249,7 +249,7 @@ function gen_array_test() {
|
||||
var val_strs = []
|
||||
i = 0
|
||||
while (i < n) {
|
||||
push(val_strs, text(vals[i]))
|
||||
val_strs[] = text(vals[i])
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
|
||||
12
graph.ce
12
graph.ce
@@ -98,7 +98,7 @@ function gather_graph(locator, visited) {
|
||||
arrfor(array(deps), function(alias) {
|
||||
var dep_locator = deps[alias]
|
||||
add_node(dep_locator)
|
||||
push(edges, { from: locator, to: dep_locator, alias: alias })
|
||||
edges[] = { from: locator, to: dep_locator, alias: alias }
|
||||
gather_graph(dep_locator, visited)
|
||||
})
|
||||
}
|
||||
@@ -117,7 +117,7 @@ if (show_world) {
|
||||
packages = shop.list_packages()
|
||||
arrfor(packages, function(p) {
|
||||
if (p != 'core') {
|
||||
push(roots, p)
|
||||
roots[] = p
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -128,7 +128,7 @@ if (show_world) {
|
||||
|
||||
target_locator = shop.resolve_locator(target_locator)
|
||||
|
||||
push(roots, target_locator)
|
||||
roots[] = target_locator
|
||||
}
|
||||
|
||||
arrfor(roots, function(root) {
|
||||
@@ -164,7 +164,7 @@ if (format == 'tree') {
|
||||
children = []
|
||||
arrfor(edges, function(e) {
|
||||
if (e.from == locator) {
|
||||
push(children, e)
|
||||
children[] = e
|
||||
}
|
||||
})
|
||||
|
||||
@@ -180,7 +180,7 @@ if (format == 'tree') {
|
||||
children = []
|
||||
arrfor(edges, function(e) {
|
||||
if (e.from == roots[i]) {
|
||||
push(children, e)
|
||||
children[] = e
|
||||
}
|
||||
})
|
||||
|
||||
@@ -230,7 +230,7 @@ if (format == 'tree') {
|
||||
}
|
||||
|
||||
arrfor(array(nodes), function(id) {
|
||||
push(output.nodes, nodes[id])
|
||||
output.nodes[] = nodes[id]
|
||||
})
|
||||
|
||||
output.edges = edges
|
||||
|
||||
47
http.cm
47
http.cm
@@ -457,7 +457,7 @@ function parse_headers(raw) {
|
||||
}
|
||||
}
|
||||
|
||||
// decode chunked transfer encoding
|
||||
// decode chunked transfer encoding (text version, for async responses)
|
||||
function decode_chunked(body_text) {
|
||||
var result = ""
|
||||
var pos = 0
|
||||
@@ -475,6 +475,37 @@ function decode_chunked(body_text) {
|
||||
return result
|
||||
}
|
||||
|
||||
// decode chunked transfer encoding (blob version, preserves binary data)
|
||||
function decode_chunked_blob(buf, body_start_bytes) {
|
||||
var result = Blob()
|
||||
var pos = body_start_bytes
|
||||
var total_bytes = length(buf) / 8
|
||||
var header_end = null
|
||||
var header_blob = null
|
||||
var header_text = null
|
||||
var crlf_pos = null
|
||||
var chunk_size = null
|
||||
var chunk_data = null
|
||||
while (pos < total_bytes) {
|
||||
header_end = pos + 20
|
||||
if (header_end > total_bytes) header_end = total_bytes
|
||||
header_blob = buf.read_blob(pos * 8, header_end * 8)
|
||||
stone(header_blob)
|
||||
header_text = text(header_blob)
|
||||
crlf_pos = search(header_text, CRLF)
|
||||
if (crlf_pos == null) break
|
||||
chunk_size = number(text(header_text, 0, crlf_pos), 16)
|
||||
if (chunk_size == null || chunk_size == 0) break
|
||||
pos = pos + crlf_pos + 2
|
||||
chunk_data = buf.read_blob(pos * 8, (pos + chunk_size) * 8)
|
||||
stone(chunk_data)
|
||||
result.write_blob(chunk_data)
|
||||
pos = pos + chunk_size + 2
|
||||
}
|
||||
stone(result)
|
||||
return result
|
||||
}
|
||||
|
||||
// receive_response requestor — async incremental receive
|
||||
var receive_response = function(callback, state) {
|
||||
var cancelled = false
|
||||
@@ -650,6 +681,8 @@ var fetch = function(url) {
|
||||
var addrs = null
|
||||
var address = null
|
||||
var ok = true
|
||||
var status_line = null
|
||||
var status_code = null
|
||||
|
||||
if (scheme_end != null) {
|
||||
scheme = lower(text(url, 0, scheme_end))
|
||||
@@ -705,8 +738,16 @@ var fetch = function(url) {
|
||||
hdr_end = search(raw_text, CRLF + CRLF)
|
||||
if (hdr_end == null) return null
|
||||
header_text = text(raw_text, 0, hdr_end)
|
||||
if (search(lower(header_text), "transfer-encoding: chunked") != null)
|
||||
return decode_chunked(text(raw_text, hdr_end + 4))
|
||||
status_line = text(header_text, 0, search(header_text, CRLF) || length(header_text))
|
||||
status_code = number(text(status_line, 9, 12))
|
||||
if (status_code == null || status_code < 200 || status_code >= 300) {
|
||||
log.error("fetch: " + status_line)
|
||||
disrupt
|
||||
}
|
||||
if (search(lower(header_text), "transfer-encoding: chunked") != null) {
|
||||
body = decode_chunked_blob(buf, hdr_end + 4)
|
||||
return body
|
||||
}
|
||||
// Headers are ASCII so char offset = byte offset
|
||||
body_start_bits = (hdr_end + 4) * 8
|
||||
body = buf.read_blob(body_start_bits, length(buf))
|
||||
|
||||
@@ -109,7 +109,7 @@ function trace_imports(file_path, depth) {
|
||||
|
||||
all_packages[imp_pkg] = true
|
||||
|
||||
push(all_imports, {
|
||||
all_imports[] = {
|
||||
from: file_path,
|
||||
from_pkg: file_pkg,
|
||||
module_path: mod_path,
|
||||
@@ -117,7 +117,7 @@ function trace_imports(file_path, depth) {
|
||||
package: imp_pkg,
|
||||
type: imp_type,
|
||||
depth: depth
|
||||
})
|
||||
}
|
||||
|
||||
// Recurse into resolved scripts
|
||||
if (resolved && (ends_with(resolved, '.cm') || ends_with(resolved, '.ce'))) {
|
||||
|
||||
512
internal/enet.c
512
internal/enet.c
@@ -14,31 +14,28 @@ static void js_enet_host_finalizer(JSRuntime *rt, JSValue val)
|
||||
if (host) enet_host_destroy(host);
|
||||
}
|
||||
|
||||
static void js_enet_peer_finalizer(JSRuntime *rt, JSValue val)
|
||||
static JSClassDef enet_host_def = {
|
||||
"ENetHost",
|
||||
.finalizer = js_enet_host_finalizer,
|
||||
};
|
||||
|
||||
static JSClassDef enet_peer_def = {
|
||||
"ENetPeer",
|
||||
};
|
||||
|
||||
/* Helper: create a JS peer wrapper for an ENetPeer pointer.
|
||||
Fresh wrapper each time — no caching in peer->data. */
|
||||
static JSValue peer_wrap(JSContext *ctx, ENetPeer *peer)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(val, enet_peer_class_id);
|
||||
if (peer && peer->data) {
|
||||
free(peer->data);
|
||||
}
|
||||
JSValue obj = JS_NewObjectClass(ctx, enet_peer_class_id);
|
||||
if (JS_IsException(obj)) return obj;
|
||||
JS_SetOpaque(obj, peer);
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Initialize the ENet library. Must be called before using any ENet functionality.
|
||||
static JSValue js_enet_initialize(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
if (enet_initialize() != 0) return JS_RaiseDisrupt(ctx, "Error initializing ENet");
|
||||
return JS_NULL;
|
||||
}
|
||||
/* ── Host functions ─────────────────────────────────────────── */
|
||||
|
||||
// Deinitialize the ENet library, cleaning up all resources.
|
||||
static JSValue js_enet_deinitialize(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
enet_deinitialize();
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Create an ENet host for either a client-like unbound host or a server bound to a specific
|
||||
// address and port.
|
||||
static JSValue js_enet_host_create(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
static JSValue js_enet_create_host(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetHost *host;
|
||||
ENetAddress address;
|
||||
@@ -74,7 +71,7 @@ static JSValue js_enet_host_create(JSContext *ctx, JSValueConst this_val, int ar
|
||||
int err = enet_address_set_host_ip(&address, addr_str);
|
||||
if (err != 0) {
|
||||
JS_FreeCString(ctx, addr_str);
|
||||
return JS_RaiseDisrupt(ctx, "Failed to set host IP from '%s'. Error: %d", addr_str, err);
|
||||
return JS_RaiseDisrupt(ctx, "Failed to set host IP. Error: %d", err);
|
||||
}
|
||||
}
|
||||
address.port = (enet_uint16)port32;
|
||||
@@ -103,97 +100,76 @@ wrap:
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Helper function to get a JSValue for an ENetPeer.
|
||||
static JSValue peer_get_value(JSContext *ctx, ENetPeer *peer)
|
||||
/* service(host, callback [, timeout]) */
|
||||
static JSValue js_enet_service(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
if (!peer->data) {
|
||||
peer->data = malloc(sizeof(JSValue));
|
||||
*(JSValue*)peer->data = JS_NewObjectClass(ctx, enet_peer_class_id);
|
||||
JS_SetOpaque(*(JSValue*)peer->data, peer);
|
||||
}
|
||||
return *(JSValue*)peer->data;
|
||||
}
|
||||
if (argc < 2) return JS_RaiseDisrupt(ctx, "service: expected (host, callback)");
|
||||
|
||||
// Poll for and process any available network events from this host,
|
||||
// calling the provided callback for each event.
|
||||
static JSValue js_enet_host_service(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetHost *host = JS_GetOpaque(this_val, enet_host_id);
|
||||
if (!host) return JS_EXCEPTION;
|
||||
ENetHost *host = JS_GetOpaque(argv[0], enet_host_id);
|
||||
if (!host) return JS_RaiseDisrupt(ctx, "service: invalid host");
|
||||
|
||||
if (argc < 1 || !JS_IsFunction(argv[0]))
|
||||
return JS_RaiseDisrupt(ctx, "Expected a callback function as first argument");
|
||||
if (!JS_IsFunction(argv[1]))
|
||||
return JS_RaiseDisrupt(ctx, "service: expected callback function");
|
||||
|
||||
enet_uint32 timeout_ms = 0;
|
||||
if (argc >= 2 && !JS_IsNull(argv[1])) {
|
||||
if (argc >= 3 && !JS_IsNull(argv[2])) {
|
||||
double secs = 0;
|
||||
JS_ToFloat64(ctx, &secs, argv[1]);
|
||||
JS_ToFloat64(ctx, &secs, argv[2]);
|
||||
if (secs > 0) timeout_ms = (enet_uint32)(secs * 1000.0);
|
||||
}
|
||||
|
||||
JS_FRAME(ctx);
|
||||
JSGCRef event_ref = { .val = JS_NULL, .prev = NULL };
|
||||
JS_PushGCRef(ctx, &event_ref);
|
||||
JS_ROOT(event_obj, JS_NULL);
|
||||
|
||||
ENetEvent event;
|
||||
while (enet_host_service(host, &event, timeout_ms) > 0) {
|
||||
event_ref.val = JS_NewObject(ctx);
|
||||
event_obj.val = JS_NewObject(ctx);
|
||||
|
||||
JSValue peer_val = peer_get_value(ctx, event.peer);
|
||||
JS_SetPropertyStr(ctx, event_ref.val, "peer", peer_val);
|
||||
JSValue peer_val = peer_wrap(ctx, event.peer);
|
||||
JS_SetPropertyStr(ctx, event_obj.val, "peer", peer_val);
|
||||
|
||||
switch (event.type) {
|
||||
case ENET_EVENT_TYPE_CONNECT: {
|
||||
JSValue type_str = JS_NewString(ctx, "connect");
|
||||
JS_SetPropertyStr(ctx, event_ref.val, "type", type_str);
|
||||
case ENET_EVENT_TYPE_CONNECT:
|
||||
JS_SetPropertyStr(ctx, event_obj.val, "type", JS_NewString(ctx, "connect"));
|
||||
break;
|
||||
}
|
||||
case ENET_EVENT_TYPE_RECEIVE: {
|
||||
JSValue type_str = JS_NewString(ctx, "receive");
|
||||
JS_SetPropertyStr(ctx, event_ref.val, "type", type_str);
|
||||
JS_SetPropertyStr(ctx, event_ref.val, "channelID", JS_NewInt32(ctx, event.channelID));
|
||||
case ENET_EVENT_TYPE_RECEIVE:
|
||||
JS_SetPropertyStr(ctx, event_obj.val, "type", JS_NewString(ctx, "receive"));
|
||||
JS_SetPropertyStr(ctx, event_obj.val, "channelID", JS_NewInt32(ctx, event.channelID));
|
||||
if (event.packet->dataLength > 0) {
|
||||
JSValue data_val = js_new_blob_stoned_copy(ctx, event.packet->data, event.packet->dataLength);
|
||||
JS_SetPropertyStr(ctx, event_ref.val, "data", data_val);
|
||||
JS_SetPropertyStr(ctx, event_obj.val, "data", data_val);
|
||||
}
|
||||
enet_packet_destroy(event.packet);
|
||||
break;
|
||||
}
|
||||
case ENET_EVENT_TYPE_DISCONNECT: {
|
||||
JSValue type_str = JS_NewString(ctx, "disconnect");
|
||||
JS_SetPropertyStr(ctx, event_ref.val, "type", type_str);
|
||||
case ENET_EVENT_TYPE_DISCONNECT:
|
||||
JS_SetPropertyStr(ctx, event_obj.val, "type", JS_NewString(ctx, "disconnect"));
|
||||
break;
|
||||
}
|
||||
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT: {
|
||||
JSValue type_str = JS_NewString(ctx, "disconnect_timeout");
|
||||
JS_SetPropertyStr(ctx, event_ref.val, "type", type_str);
|
||||
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT:
|
||||
JS_SetPropertyStr(ctx, event_obj.val, "type", JS_NewString(ctx, "disconnect_timeout"));
|
||||
break;
|
||||
}
|
||||
case ENET_EVENT_TYPE_NONE: {
|
||||
JSValue type_str = JS_NewString(ctx, "none");
|
||||
JS_SetPropertyStr(ctx, event_ref.val, "type", type_str);
|
||||
case ENET_EVENT_TYPE_NONE:
|
||||
JS_SetPropertyStr(ctx, event_obj.val, "type", JS_NewString(ctx, "none"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
JS_Call(ctx, argv[0], JS_NULL, 1, &event_ref.val);
|
||||
JS_Call(ctx, argv[1], JS_NULL, 1, &event_obj.val);
|
||||
}
|
||||
|
||||
JS_RETURN_NULL();
|
||||
}
|
||||
|
||||
// Initiate a connection from this host to a remote server.
|
||||
static JSValue js_enet_host_connect(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
/* connect(host, address, port) → peer */
|
||||
static JSValue js_enet_connect(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetHost *host = JS_GetOpaque(this_val, enet_host_id);
|
||||
if (!host) return JS_EXCEPTION;
|
||||
if (argc < 3) return JS_RaiseDisrupt(ctx, "connect: expected (host, address, port)");
|
||||
|
||||
if (argc < 2) return JS_RaiseDisrupt(ctx, "Expected 2 arguments: hostname, port");
|
||||
ENetHost *host = JS_GetOpaque(argv[0], enet_host_id);
|
||||
if (!host) return JS_RaiseDisrupt(ctx, "connect: invalid host");
|
||||
|
||||
const char *hostname = JS_ToCString(ctx, argv[0]);
|
||||
const char *hostname = JS_ToCString(ctx, argv[1]);
|
||||
if (!hostname) return JS_EXCEPTION;
|
||||
int port;
|
||||
JS_ToInt32(ctx, &port, argv[1]);
|
||||
JS_ToInt32(ctx, &port, argv[2]);
|
||||
|
||||
ENetAddress address;
|
||||
enet_address_set_host(&address, hostname);
|
||||
@@ -201,43 +177,43 @@ static JSValue js_enet_host_connect(JSContext *ctx, JSValueConst this_val, int a
|
||||
address.port = port;
|
||||
|
||||
ENetPeer *peer = enet_host_connect(host, &address, 2, 0);
|
||||
if (!peer) return JS_RaiseDisrupt(ctx, "No available peers for initiating an ENet connection");
|
||||
if (!peer) return JS_RaiseDisrupt(ctx, "No available peers for connection");
|
||||
|
||||
return peer_get_value(ctx, peer);
|
||||
return peer_wrap(ctx, peer);
|
||||
}
|
||||
|
||||
// Flush all pending outgoing packets for this host immediately.
|
||||
static JSValue js_enet_host_flush(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
/* flush(host) */
|
||||
static JSValue js_enet_flush(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetHost *host = JS_GetOpaque(this_val, enet_host_id);
|
||||
if (!host) return JS_EXCEPTION;
|
||||
if (argc < 1) return JS_RaiseDisrupt(ctx, "flush: expected (host)");
|
||||
ENetHost *host = JS_GetOpaque(argv[0], enet_host_id);
|
||||
if (!host) return JS_RaiseDisrupt(ctx, "flush: invalid host");
|
||||
enet_host_flush(host);
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Broadcast a string or blob to all connected peers on channel 0.
|
||||
static JSValue js_enet_host_broadcast(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
/* broadcast(host, data) */
|
||||
static JSValue js_enet_broadcast(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetHost *host = JS_GetOpaque(this_val, enet_host_id);
|
||||
if (!host) return JS_EXCEPTION;
|
||||
|
||||
if (argc < 1) return JS_RaiseDisrupt(ctx, "Expected a string or blob to broadcast");
|
||||
if (argc < 2) return JS_RaiseDisrupt(ctx, "broadcast: expected (host, data)");
|
||||
ENetHost *host = JS_GetOpaque(argv[0], enet_host_id);
|
||||
if (!host) return JS_RaiseDisrupt(ctx, "broadcast: invalid host");
|
||||
|
||||
const char *data_str = NULL;
|
||||
size_t data_len = 0;
|
||||
uint8_t *buf = NULL;
|
||||
|
||||
if (JS_IsText(argv[0])) {
|
||||
data_str = JS_ToCStringLen(ctx, &data_len, argv[0]);
|
||||
if (JS_IsText(argv[1])) {
|
||||
data_str = JS_ToCStringLen(ctx, &data_len, argv[1]);
|
||||
if (!data_str) return JS_EXCEPTION;
|
||||
} else if (js_is_blob(ctx, argv[0])) {
|
||||
buf = js_get_blob_data(ctx, &data_len, argv[0]);
|
||||
} else if (js_is_blob(ctx, argv[1])) {
|
||||
buf = js_get_blob_data(ctx, &data_len, argv[1]);
|
||||
if (!buf) return JS_EXCEPTION;
|
||||
} else {
|
||||
return JS_RaiseDisrupt(ctx, "broadcast() only accepts a string or blob");
|
||||
return JS_RaiseDisrupt(ctx, "broadcast: data must be string or blob");
|
||||
}
|
||||
|
||||
ENetPacket *packet = enet_packet_create(data_str ? (const void*)data_str : (const void*)buf, data_len, ENET_PACKET_FLAG_RELIABLE);
|
||||
ENetPacket *packet = enet_packet_create(data_str ? (const void *)data_str : (const void *)buf, data_len, ENET_PACKET_FLAG_RELIABLE);
|
||||
if (data_str) JS_FreeCString(ctx, data_str);
|
||||
if (!packet) return JS_RaiseDisrupt(ctx, "Failed to create ENet packet");
|
||||
|
||||
@@ -245,55 +221,51 @@ static JSValue js_enet_host_broadcast(JSContext *ctx, JSValueConst this_val, int
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Host property getters
|
||||
static JSValue js_enet_host_get_port(JSContext *js, JSValueConst self)
|
||||
/* host_port(host) → number */
|
||||
static JSValue js_enet_host_port(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetHost *host = JS_GetOpaque(self, enet_host_id);
|
||||
if (!host) return JS_EXCEPTION;
|
||||
return JS_NewInt32(js, host->address.port);
|
||||
if (argc < 1) return JS_RaiseDisrupt(ctx, "host_port: expected (host)");
|
||||
ENetHost *host = JS_GetOpaque(argv[0], enet_host_id);
|
||||
if (!host) return JS_RaiseDisrupt(ctx, "host_port: invalid host");
|
||||
return JS_NewInt32(ctx, host->address.port);
|
||||
}
|
||||
|
||||
static JSValue js_enet_host_get_address(JSContext *js, JSValueConst self)
|
||||
/* host_address(host) → string */
|
||||
static JSValue js_enet_host_address(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetHost *me = JS_GetOpaque(self, enet_host_id);
|
||||
if (!me) return JS_EXCEPTION;
|
||||
if (argc < 1) return JS_RaiseDisrupt(ctx, "host_address: expected (host)");
|
||||
ENetHost *host = JS_GetOpaque(argv[0], enet_host_id);
|
||||
if (!host) return JS_RaiseDisrupt(ctx, "host_address: invalid host");
|
||||
char ip_str[128];
|
||||
if (enet_address_get_host_ip(&me->address, ip_str, sizeof(ip_str)) != 0)
|
||||
if (enet_address_get_host_ip(&host->address, ip_str, sizeof(ip_str)) != 0)
|
||||
return JS_NULL;
|
||||
return JS_NewString(js, ip_str);
|
||||
return JS_NewString(ctx, ip_str);
|
||||
}
|
||||
|
||||
// Peer-level operations
|
||||
static JSValue js_enet_peer_disconnect(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
enet_peer_disconnect(peer, 0);
|
||||
return JS_NULL;
|
||||
}
|
||||
/* ── Peer functions ─────────────────────────────────────────── */
|
||||
|
||||
static JSValue js_enet_peer_send(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
/* send(peer, data) */
|
||||
static JSValue js_enet_send(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
|
||||
if (argc < 1) return JS_RaiseDisrupt(ctx, "Expected a string or blob to send");
|
||||
if (argc < 2) return JS_RaiseDisrupt(ctx, "send: expected (peer, data)");
|
||||
ENetPeer *peer = JS_GetOpaque(argv[0], enet_peer_class_id);
|
||||
if (!peer) return JS_RaiseDisrupt(ctx, "send: invalid peer");
|
||||
|
||||
const char *data_str = NULL;
|
||||
size_t data_len = 0;
|
||||
uint8_t *buf = NULL;
|
||||
|
||||
if (JS_IsText(argv[0])) {
|
||||
data_str = JS_ToCStringLen(ctx, &data_len, argv[0]);
|
||||
if (JS_IsText(argv[1])) {
|
||||
data_str = JS_ToCStringLen(ctx, &data_len, argv[1]);
|
||||
if (!data_str) return JS_EXCEPTION;
|
||||
} else if (js_is_blob(ctx, argv[0])) {
|
||||
buf = js_get_blob_data(ctx, &data_len, argv[0]);
|
||||
} else if (js_is_blob(ctx, argv[1])) {
|
||||
buf = js_get_blob_data(ctx, &data_len, argv[1]);
|
||||
if (!buf) return JS_EXCEPTION;
|
||||
} else {
|
||||
return JS_RaiseDisrupt(ctx, "send() only accepts a string or blob");
|
||||
return JS_RaiseDisrupt(ctx, "send: data must be string or blob");
|
||||
}
|
||||
|
||||
ENetPacket *packet = enet_packet_create(data_str ? (const void*)data_str : (const void*)buf, data_len, ENET_PACKET_FLAG_RELIABLE);
|
||||
ENetPacket *packet = enet_packet_create(data_str ? (const void *)data_str : (const void *)buf, data_len, ENET_PACKET_FLAG_RELIABLE);
|
||||
if (data_str) JS_FreeCString(ctx, data_str);
|
||||
if (!packet) return JS_RaiseDisrupt(ctx, "Failed to create ENet packet");
|
||||
|
||||
@@ -301,225 +273,185 @@ static JSValue js_enet_peer_send(JSContext *ctx, JSValueConst this_val, int argc
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_disconnect_now(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
/* disconnect(peer) */
|
||||
static JSValue js_enet_disconnect(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
if (argc < 1) return JS_RaiseDisrupt(ctx, "disconnect: expected (peer)");
|
||||
ENetPeer *peer = JS_GetOpaque(argv[0], enet_peer_class_id);
|
||||
if (!peer) return JS_RaiseDisrupt(ctx, "disconnect: invalid peer");
|
||||
enet_peer_disconnect(peer, 0);
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
/* disconnect_now(peer) */
|
||||
static JSValue js_enet_disconnect_now(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
if (argc < 1) return JS_RaiseDisrupt(ctx, "disconnect_now: expected (peer)");
|
||||
ENetPeer *peer = JS_GetOpaque(argv[0], enet_peer_class_id);
|
||||
if (!peer) return JS_RaiseDisrupt(ctx, "disconnect_now: invalid peer");
|
||||
enet_peer_disconnect_now(peer, 0);
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_disconnect_later(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
/* disconnect_later(peer) */
|
||||
static JSValue js_enet_disconnect_later(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
if (argc < 1) return JS_RaiseDisrupt(ctx, "disconnect_later: expected (peer)");
|
||||
ENetPeer *peer = JS_GetOpaque(argv[0], enet_peer_class_id);
|
||||
if (!peer) return JS_RaiseDisrupt(ctx, "disconnect_later: invalid peer");
|
||||
enet_peer_disconnect_later(peer, 0);
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_reset(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
/* reset(peer) */
|
||||
static JSValue js_enet_reset(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
if (argc < 1) return JS_RaiseDisrupt(ctx, "reset: expected (peer)");
|
||||
ENetPeer *peer = JS_GetOpaque(argv[0], enet_peer_class_id);
|
||||
if (!peer) return JS_RaiseDisrupt(ctx, "reset: invalid peer");
|
||||
enet_peer_reset(peer);
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_ping(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
/* ping(peer) */
|
||||
static JSValue js_enet_ping(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
if (argc < 1) return JS_RaiseDisrupt(ctx, "ping: expected (peer)");
|
||||
ENetPeer *peer = JS_GetOpaque(argv[0], enet_peer_class_id);
|
||||
if (!peer) return JS_RaiseDisrupt(ctx, "ping: invalid peer");
|
||||
enet_peer_ping(peer);
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_throttle_configure(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
/* throttle_configure(peer, interval, acceleration, deceleration) */
|
||||
static JSValue js_enet_throttle_configure(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
|
||||
if (argc < 4) return JS_RaiseDisrupt(ctx, "throttle_configure: expected (peer, interval, accel, decel)");
|
||||
ENetPeer *peer = JS_GetOpaque(argv[0], enet_peer_class_id);
|
||||
if (!peer) return JS_RaiseDisrupt(ctx, "throttle_configure: invalid peer");
|
||||
int interval, acceleration, deceleration;
|
||||
if (argc < 3 || JS_ToInt32(ctx, &interval, argv[0]) || JS_ToInt32(ctx, &acceleration, argv[1]) || JS_ToInt32(ctx, &deceleration, argv[2]))
|
||||
return JS_RaiseDisrupt(ctx, "Expected 3 int arguments: interval, acceleration, deceleration");
|
||||
|
||||
if (JS_ToInt32(ctx, &interval, argv[1]) || JS_ToInt32(ctx, &acceleration, argv[2]) || JS_ToInt32(ctx, &deceleration, argv[3]))
|
||||
return JS_RaiseDisrupt(ctx, "throttle_configure: expected integer arguments");
|
||||
enet_peer_throttle_configure(peer, interval, acceleration, deceleration);
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
/* peer_timeout(peer, limit, min, max) */
|
||||
static JSValue js_enet_peer_timeout(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
|
||||
if (argc < 4) return JS_RaiseDisrupt(ctx, "peer_timeout: expected (peer, limit, min, max)");
|
||||
ENetPeer *peer = JS_GetOpaque(argv[0], enet_peer_class_id);
|
||||
if (!peer) return JS_RaiseDisrupt(ctx, "peer_timeout: invalid peer");
|
||||
int timeout_limit, timeout_min, timeout_max;
|
||||
if (argc < 3 || JS_ToInt32(ctx, &timeout_limit, argv[0]) || JS_ToInt32(ctx, &timeout_min, argv[1]) || JS_ToInt32(ctx, &timeout_max, argv[2]))
|
||||
return JS_RaiseDisrupt(ctx, "Expected 3 integer arguments: timeout_limit, timeout_min, timeout_max");
|
||||
|
||||
if (JS_ToInt32(ctx, &timeout_limit, argv[1]) || JS_ToInt32(ctx, &timeout_min, argv[2]) || JS_ToInt32(ctx, &timeout_max, argv[3]))
|
||||
return JS_RaiseDisrupt(ctx, "peer_timeout: expected integer arguments");
|
||||
enet_peer_timeout(peer, timeout_limit, timeout_min, timeout_max);
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Class definitions
|
||||
static JSClassDef enet_host = {
|
||||
"ENetHost",
|
||||
.finalizer = js_enet_host_finalizer,
|
||||
};
|
||||
/* ── Peer property getters ──────────────────────────────────── */
|
||||
|
||||
static JSClassDef enet_peer_class = {
|
||||
"ENetPeer",
|
||||
.finalizer = js_enet_peer_finalizer,
|
||||
};
|
||||
|
||||
static JSValue js_enet_resolve_hostname(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
const char *hostname = JS_ToCString(js, argv[0]);
|
||||
JS_FreeCString(js, hostname);
|
||||
return JS_NULL;
|
||||
#define PEER_GETTER(name, field, convert) \
|
||||
static JSValue js_enet_##name(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { \
|
||||
if (argc < 1) return JS_RaiseDisrupt(ctx, #name ": expected (peer)"); \
|
||||
ENetPeer *peer = JS_GetOpaque(argv[0], enet_peer_class_id); \
|
||||
if (!peer) return JS_RaiseDisrupt(ctx, #name ": invalid peer"); \
|
||||
return convert(ctx, peer->field); \
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_enet_funcs[] = {
|
||||
JS_CFUNC_DEF("initialize", 0, js_enet_initialize),
|
||||
JS_CFUNC_DEF("deinitialize", 0, js_enet_deinitialize),
|
||||
JS_CFUNC_DEF("create_host", 1, js_enet_host_create),
|
||||
JS_CFUNC_DEF("resolve_hostname", 1, js_enet_resolve_hostname),
|
||||
};
|
||||
static inline JSValue _int32(JSContext *ctx, int v) { return JS_NewInt32(ctx, v); }
|
||||
static inline JSValue _uint32(JSContext *ctx, unsigned int v) { return JS_NewUint32(ctx, v); }
|
||||
|
||||
static const JSCFunctionListEntry js_enet_host_funcs[] = {
|
||||
JS_CFUNC_DEF("service", 2, js_enet_host_service),
|
||||
JS_CFUNC_DEF("connect", 2, js_enet_host_connect),
|
||||
JS_CFUNC_DEF("flush", 0, js_enet_host_flush),
|
||||
JS_CFUNC_DEF("broadcast", 1, js_enet_host_broadcast),
|
||||
JS_CFUNC0_DEF("port", js_enet_host_get_port),
|
||||
JS_CFUNC0_DEF("address", js_enet_host_get_address),
|
||||
};
|
||||
PEER_GETTER(peer_rtt, roundTripTime, _int32)
|
||||
PEER_GETTER(peer_rtt_variance, roundTripTimeVariance, _int32)
|
||||
PEER_GETTER(peer_last_send_time, lastSendTime, _int32)
|
||||
PEER_GETTER(peer_last_receive_time, lastReceiveTime, _int32)
|
||||
PEER_GETTER(peer_mtu, mtu, _int32)
|
||||
PEER_GETTER(peer_outgoing_data_total, outgoingDataTotal, _int32)
|
||||
PEER_GETTER(peer_incoming_data_total, incomingDataTotal, _int32)
|
||||
PEER_GETTER(peer_packet_loss, packetLoss, _int32)
|
||||
PEER_GETTER(peer_state, state, _int32)
|
||||
PEER_GETTER(peer_reliable_data_in_transit, reliableDataInTransit, _int32)
|
||||
|
||||
// Peer property getters (zero-arg methods)
|
||||
static JSValue js_enet_peer_get_rtt(JSContext *ctx, JSValueConst this_val)
|
||||
static JSValue js_enet_peer_incoming_bandwidth(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
return JS_NewInt32(ctx, peer->roundTripTime);
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_get_incoming_bandwidth(JSContext *ctx, JSValueConst this_val)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
if (argc < 1) return JS_RaiseDisrupt(ctx, "peer_incoming_bandwidth: expected (peer)");
|
||||
ENetPeer *peer = JS_GetOpaque(argv[0], enet_peer_class_id);
|
||||
if (!peer) return JS_RaiseDisrupt(ctx, "peer_incoming_bandwidth: invalid peer");
|
||||
if (peer->incomingBandwidth == 0) return JS_NewFloat64(ctx, INFINITY);
|
||||
return JS_NewInt32(ctx, peer->incomingBandwidth);
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_get_outgoing_bandwidth(JSContext *ctx, JSValueConst this_val)
|
||||
static JSValue js_enet_peer_outgoing_bandwidth(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
if (argc < 1) return JS_RaiseDisrupt(ctx, "peer_outgoing_bandwidth: expected (peer)");
|
||||
ENetPeer *peer = JS_GetOpaque(argv[0], enet_peer_class_id);
|
||||
if (!peer) return JS_RaiseDisrupt(ctx, "peer_outgoing_bandwidth: invalid peer");
|
||||
if (peer->outgoingBandwidth == 0) return JS_NewFloat64(ctx, INFINITY);
|
||||
return JS_NewInt32(ctx, peer->outgoingBandwidth);
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_get_last_send_time(JSContext *ctx, JSValueConst this_val)
|
||||
static JSValue js_enet_peer_port(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
return JS_NewInt32(ctx, peer->lastSendTime);
|
||||
if (argc < 1) return JS_RaiseDisrupt(ctx, "peer_port: expected (peer)");
|
||||
ENetPeer *peer = JS_GetOpaque(argv[0], enet_peer_class_id);
|
||||
if (!peer) return JS_RaiseDisrupt(ctx, "peer_port: invalid peer");
|
||||
return JS_NewUint32(ctx, peer->address.port);
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_get_last_receive_time(JSContext *ctx, JSValueConst this_val)
|
||||
static JSValue js_enet_peer_address(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
return JS_NewInt32(ctx, peer->lastReceiveTime);
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_get_mtu(JSContext *ctx, JSValueConst this_val)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_NewFloat64(ctx, INFINITY);
|
||||
return JS_NewInt32(ctx, peer->mtu);
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_get_outgoing_data_total(JSContext *ctx, JSValueConst this_val)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_NewFloat64(ctx, INFINITY);
|
||||
return JS_NewInt32(ctx, peer->outgoingDataTotal);
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_get_incoming_data_total(JSContext *ctx, JSValueConst this_val)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_NewFloat64(ctx, INFINITY);
|
||||
return JS_NewInt32(ctx, peer->incomingDataTotal);
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_get_rtt_variance(JSContext *ctx, JSValueConst this_val)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_NewFloat64(ctx, INFINITY);
|
||||
return JS_NewInt32(ctx, peer->roundTripTimeVariance);
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_get_packet_loss(JSContext *ctx, JSValueConst this_val)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_NewFloat64(ctx, INFINITY);
|
||||
return JS_NewInt32(ctx, peer->packetLoss);
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_get_state(JSContext *ctx, JSValueConst this_val)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_NewInt32(ctx, -1);
|
||||
return JS_NewInt32(ctx, peer->state);
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_get_reliable_data_in_transit(JSContext *ctx, JSValueConst this_val)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(this_val, enet_peer_class_id);
|
||||
if (!peer) return JS_NewFloat64(ctx, INFINITY);
|
||||
return JS_NewInt32(ctx, peer->reliableDataInTransit);
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_get_port(JSContext *js, JSValueConst self)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(self, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
return JS_NewUint32(js, peer->address.port);
|
||||
}
|
||||
|
||||
static JSValue js_enet_peer_get_address(JSContext *js, JSValueConst self)
|
||||
{
|
||||
ENetPeer *peer = JS_GetOpaque(self, enet_peer_class_id);
|
||||
if (!peer) return JS_EXCEPTION;
|
||||
if (argc < 1) return JS_RaiseDisrupt(ctx, "peer_address: expected (peer)");
|
||||
ENetPeer *peer = JS_GetOpaque(argv[0], enet_peer_class_id);
|
||||
if (!peer) return JS_RaiseDisrupt(ctx, "peer_address: invalid peer");
|
||||
char ip_str[128];
|
||||
if (enet_address_get_host_ip(&peer->address, ip_str, sizeof(ip_str)) != 0)
|
||||
return JS_NULL;
|
||||
return JS_NewString(js, ip_str);
|
||||
return JS_NewString(ctx, ip_str);
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_enet_peer_funcs[] = {
|
||||
JS_CFUNC_DEF("send", 1, js_enet_peer_send),
|
||||
JS_CFUNC_DEF("disconnect", 0, js_enet_peer_disconnect),
|
||||
JS_CFUNC_DEF("disconnect_now", 0, js_enet_peer_disconnect_now),
|
||||
JS_CFUNC_DEF("disconnect_later", 0, js_enet_peer_disconnect_later),
|
||||
JS_CFUNC_DEF("reset", 0, js_enet_peer_reset),
|
||||
JS_CFUNC_DEF("ping", 0, js_enet_peer_ping),
|
||||
JS_CFUNC_DEF("throttle_configure", 3, js_enet_peer_throttle_configure),
|
||||
JS_CFUNC_DEF("timeout", 3, js_enet_peer_timeout),
|
||||
JS_CFUNC0_DEF("rtt", js_enet_peer_get_rtt),
|
||||
JS_CFUNC0_DEF("incoming_bandwidth", js_enet_peer_get_incoming_bandwidth),
|
||||
JS_CFUNC0_DEF("outgoing_bandwidth", js_enet_peer_get_outgoing_bandwidth),
|
||||
JS_CFUNC0_DEF("last_send_time", js_enet_peer_get_last_send_time),
|
||||
JS_CFUNC0_DEF("last_receive_time", js_enet_peer_get_last_receive_time),
|
||||
JS_CFUNC0_DEF("mtu", js_enet_peer_get_mtu),
|
||||
JS_CFUNC0_DEF("outgoing_data_total", js_enet_peer_get_outgoing_data_total),
|
||||
JS_CFUNC0_DEF("incoming_data_total", js_enet_peer_get_incoming_data_total),
|
||||
JS_CFUNC0_DEF("rtt_variance", js_enet_peer_get_rtt_variance),
|
||||
JS_CFUNC0_DEF("packet_loss", js_enet_peer_get_packet_loss),
|
||||
JS_CFUNC0_DEF("state", js_enet_peer_get_state),
|
||||
JS_CFUNC0_DEF("reliable_data_in_transit", js_enet_peer_get_reliable_data_in_transit),
|
||||
JS_CFUNC0_DEF("port", js_enet_peer_get_port),
|
||||
JS_CFUNC0_DEF("address", js_enet_peer_get_address),
|
||||
static JSValue js_enet_resolve_hostname(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
const char *hostname = JS_ToCString(ctx, argv[0]);
|
||||
JS_FreeCString(ctx, hostname);
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
/* ── Module export ──────────────────────────────────────────── */
|
||||
|
||||
static const JSCFunctionListEntry js_enet_funcs[] = {
|
||||
/* host */
|
||||
JS_CFUNC_DEF("create_host", 1, js_enet_create_host),
|
||||
JS_CFUNC_DEF("service", 2, js_enet_service),
|
||||
JS_CFUNC_DEF("connect", 3, js_enet_connect),
|
||||
JS_CFUNC_DEF("flush", 1, js_enet_flush),
|
||||
JS_CFUNC_DEF("broadcast", 2, js_enet_broadcast),
|
||||
JS_CFUNC_DEF("host_port", 1, js_enet_host_port),
|
||||
JS_CFUNC_DEF("host_address", 1, js_enet_host_address),
|
||||
/* peer */
|
||||
JS_CFUNC_DEF("send", 2, js_enet_send),
|
||||
JS_CFUNC_DEF("disconnect", 1, js_enet_disconnect),
|
||||
JS_CFUNC_DEF("disconnect_now", 1, js_enet_disconnect_now),
|
||||
JS_CFUNC_DEF("disconnect_later", 1, js_enet_disconnect_later),
|
||||
JS_CFUNC_DEF("reset", 1, js_enet_reset),
|
||||
JS_CFUNC_DEF("ping", 1, js_enet_ping),
|
||||
JS_CFUNC_DEF("throttle_configure", 4, js_enet_throttle_configure),
|
||||
JS_CFUNC_DEF("peer_timeout", 4, js_enet_peer_timeout),
|
||||
JS_CFUNC_DEF("peer_address", 1, js_enet_peer_address),
|
||||
JS_CFUNC_DEF("peer_port", 1, js_enet_peer_port),
|
||||
JS_CFUNC_DEF("peer_rtt", 1, js_enet_peer_rtt),
|
||||
JS_CFUNC_DEF("peer_rtt_variance", 1, js_enet_peer_rtt_variance),
|
||||
JS_CFUNC_DEF("peer_incoming_bandwidth", 1, js_enet_peer_incoming_bandwidth),
|
||||
JS_CFUNC_DEF("peer_outgoing_bandwidth", 1, js_enet_peer_outgoing_bandwidth),
|
||||
JS_CFUNC_DEF("peer_last_send_time", 1, js_enet_peer_last_send_time),
|
||||
JS_CFUNC_DEF("peer_last_receive_time", 1, js_enet_peer_last_receive_time),
|
||||
JS_CFUNC_DEF("peer_mtu", 1, js_enet_peer_mtu),
|
||||
JS_CFUNC_DEF("peer_outgoing_data_total", 1, js_enet_peer_outgoing_data_total),
|
||||
JS_CFUNC_DEF("peer_incoming_data_total", 1, js_enet_peer_incoming_data_total),
|
||||
JS_CFUNC_DEF("peer_packet_loss", 1, js_enet_peer_packet_loss),
|
||||
JS_CFUNC_DEF("peer_state", 1, js_enet_peer_state),
|
||||
JS_CFUNC_DEF("peer_reliable_data_in_transit", 1, js_enet_peer_reliable_data_in_transit),
|
||||
JS_CFUNC_DEF("resolve_hostname", 1, js_enet_resolve_hostname),
|
||||
};
|
||||
|
||||
JSValue js_core_internal_enet_use(JSContext *ctx)
|
||||
@@ -529,16 +461,10 @@ JSValue js_core_internal_enet_use(JSContext *ctx)
|
||||
JS_FRAME(ctx);
|
||||
|
||||
JS_NewClassID(&enet_host_id);
|
||||
JS_NewClass(ctx, enet_host_id, &enet_host);
|
||||
JS_ROOT(host_proto, JS_NewObject(ctx));
|
||||
JS_SetPropertyFunctionList(ctx, host_proto.val, js_enet_host_funcs, countof(js_enet_host_funcs));
|
||||
JS_SetClassProto(ctx, enet_host_id, host_proto.val);
|
||||
JS_NewClass(ctx, enet_host_id, &enet_host_def);
|
||||
|
||||
JS_NewClassID(&enet_peer_class_id);
|
||||
JS_NewClass(ctx, enet_peer_class_id, &enet_peer_class);
|
||||
JS_ROOT(peer_proto, JS_NewObject(ctx));
|
||||
JS_SetPropertyFunctionList(ctx, peer_proto.val, js_enet_peer_funcs, countof(js_enet_peer_funcs));
|
||||
JS_SetClassProto(ctx, enet_peer_class_id, peer_proto.val);
|
||||
JS_NewClass(ctx, enet_peer_class_id, &enet_peer_def);
|
||||
|
||||
JS_ROOT(export_obj, JS_NewObject(ctx));
|
||||
JS_SetPropertyFunctionList(ctx, export_obj.val, js_enet_funcs, countof(js_enet_funcs));
|
||||
|
||||
@@ -5,6 +5,10 @@ var native_mode = false
|
||||
var _no_warn = (init != null && init.no_warn) ? true : false
|
||||
var SYSYM = '__SYSTEM__'
|
||||
|
||||
var log = function(name, args) {
|
||||
|
||||
}
|
||||
|
||||
var _cell = {}
|
||||
var need_stop = false
|
||||
|
||||
@@ -539,7 +543,7 @@ if (_init != null && _init.native_mode)
|
||||
if (args != null && (_init == null || !_init.program)) {
|
||||
_program = args[0]
|
||||
while (_j < length(args)) {
|
||||
push(_user_args, args[_j])
|
||||
_user_args[] = args[_j]
|
||||
_j = _j + 1
|
||||
}
|
||||
if (_init == null) {
|
||||
@@ -908,6 +912,7 @@ $_.delay = function delay(fn, seconds) {
|
||||
send_messages()
|
||||
}
|
||||
var id = actor_mod.delay(delay_turn, _seconds)
|
||||
log.connection(`$delay: registered timer id=${text(id)} seconds=${text(_seconds)}`)
|
||||
return function() { actor_mod.removetimer(id) }
|
||||
}
|
||||
|
||||
@@ -940,7 +945,7 @@ $_.start = function start(cb, program) {
|
||||
no_warn: _no_warn,
|
||||
}
|
||||
greeters[id] = cb
|
||||
push(message_queue, { startup })
|
||||
message_queue[] = { startup }
|
||||
}
|
||||
|
||||
$_.receiver = function receiver(fn) {
|
||||
@@ -959,20 +964,34 @@ $_.couple = function couple(actor) {
|
||||
}
|
||||
|
||||
$_.contact = function(callback, record) {
|
||||
send(create_actor(record), record, callback)
|
||||
log.connection(`contact: creating actor for ${record.address}:${text(record.port)}`)
|
||||
var a = create_actor(record)
|
||||
log.connection(`contact: actor created, sending contact`)
|
||||
send(a, record, function(reply) {
|
||||
var server = null
|
||||
if (reply && reply.actor_id) {
|
||||
server = create_actor({id: reply.actor_id, address: record.address, port: record.port})
|
||||
log.connection(`contact: connected, server id=${reply.actor_id}`)
|
||||
callback(server)
|
||||
} else {
|
||||
log.connection(`contact: connection failed or no reply`)
|
||||
callback(null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
$_.portal = function(fn, port) {
|
||||
if (portal) {
|
||||
log.error(`Already started a portal listening on ${portal.port()}`)
|
||||
log.error(`Already started a portal listening on ${enet.host_port(portal)}`)
|
||||
disrupt
|
||||
}
|
||||
if (!port) {
|
||||
log.error("Requires a valid port.")
|
||||
disrupt
|
||||
}
|
||||
log.system(`starting a portal on port ${port}`)
|
||||
log.connection(`portal: starting on port ${text(port)}`)
|
||||
portal = enet.create_host({address: "any", port})
|
||||
log.connection(`portal: created host=${portal}`)
|
||||
portal_fn = fn
|
||||
enet_check()
|
||||
}
|
||||
@@ -1362,59 +1381,74 @@ function guid(bits)
|
||||
}
|
||||
|
||||
enet = use_core('internal/enet')
|
||||
enet = use_core('enet')
|
||||
|
||||
function peer_connection(peer) {
|
||||
return {
|
||||
latency: peer.rtt(),
|
||||
latency: enet.peer_rtt(peer),
|
||||
bandwidth: {
|
||||
incoming: peer.incoming_bandwidth(),
|
||||
outgoing: peer.outgoing_bandwidth()
|
||||
incoming: enet.peer_incoming_bandwidth(peer),
|
||||
outgoing: enet.peer_outgoing_bandwidth(peer)
|
||||
},
|
||||
activity: {
|
||||
last_sent: peer.last_send_time(),
|
||||
last_received: peer.last_receive_time()
|
||||
last_sent: enet.peer_last_send_time(peer),
|
||||
last_received: enet.peer_last_receive_time(peer)
|
||||
},
|
||||
mtu: peer.mtu(),
|
||||
mtu: enet.peer_mtu(peer),
|
||||
data: {
|
||||
incoming_total: peer.incoming_data_total(),
|
||||
outgoing_total: peer.outgoing_data_total(),
|
||||
reliable_in_transit: peer.reliable_data_in_transit()
|
||||
incoming_total: enet.peer_incoming_data_total(peer),
|
||||
outgoing_total: enet.peer_outgoing_data_total(peer),
|
||||
reliable_in_transit: enet.peer_reliable_data_in_transit(peer)
|
||||
},
|
||||
latency_variance: peer.rtt_variance(),
|
||||
packet_loss: peer.packet_loss(),
|
||||
state: peer.state()
|
||||
latency_variance: enet.peer_rtt_variance(peer),
|
||||
packet_loss: enet.peer_packet_loss(peer),
|
||||
state: enet.peer_state(peer)
|
||||
}
|
||||
}
|
||||
|
||||
// Strip ::ffff: prefix from IPv6-mapped IPv4 addresses
|
||||
function normalize_addr(addr) {
|
||||
if (starts_with(addr, "::ffff:"))
|
||||
return text(addr, 7)
|
||||
return addr
|
||||
}
|
||||
|
||||
function handle_host(e) {
|
||||
var queue = null
|
||||
var data = null
|
||||
var addr = null
|
||||
var port = null
|
||||
var pkey = null
|
||||
|
||||
log.connection(`handle_host: event type=${e.type}`)
|
||||
if (e.type == "connect") {
|
||||
addr = e.peer.address()
|
||||
port = e.peer.port()
|
||||
log.system(`connected a new peer: ${addr}:${port}`)
|
||||
peers[`${addr}:${port}`] = e.peer
|
||||
queue = peer_queue[e.peer]
|
||||
addr = normalize_addr(enet.peer_address(e.peer))
|
||||
port = enet.peer_port(e.peer)
|
||||
pkey = addr + ":" + text(port)
|
||||
log.connection(`handle_host: peer connected ${pkey}`)
|
||||
peers[pkey] = e.peer
|
||||
queue = peer_queue[pkey]
|
||||
if (queue) {
|
||||
arrfor(queue, (msg, index) => e.peer.send(nota.encode(msg)))
|
||||
log.system(`sent queue out of queue`)
|
||||
delete peer_queue[e.peer]
|
||||
log.connection(`handle_host: flushing ${text(length(queue))} queued messages to ${pkey}`)
|
||||
arrfor(queue, (msg, index) => enet.send(e.peer, nota.encode(msg)))
|
||||
delete peer_queue[pkey]
|
||||
} else {
|
||||
log.connection(`handle_host: no queued messages for ${pkey}`)
|
||||
}
|
||||
} else if (e.type == "disconnect") {
|
||||
delete peer_queue[e.peer]
|
||||
arrfor(array(peers), function(id, index) {
|
||||
if (peers[id] == e.peer) delete peers[id]
|
||||
})
|
||||
log.system('portal got disconnect from ' + e.peer.address() + ":" + e.peer.port())
|
||||
addr = normalize_addr(enet.peer_address(e.peer))
|
||||
port = enet.peer_port(e.peer)
|
||||
pkey = addr + ":" + text(port)
|
||||
log.connection(`handle_host: peer disconnected ${pkey}`)
|
||||
delete peer_queue[pkey]
|
||||
delete peers[pkey]
|
||||
} else if (e.type == "receive") {
|
||||
data = nota.decode(e.data)
|
||||
if (data.replycc && !data.replycc.address) {
|
||||
data.replycc[ACTORDATA].address = e.peer.address()
|
||||
data.replycc[ACTORDATA].port = e.peer.port()
|
||||
log.connection(`handle_host: received data type=${data.type}`)
|
||||
if (data.replycc_id && !data.replycc) {
|
||||
data.replycc = create_actor({id: data.replycc_id, address: normalize_addr(enet.peer_address(e.peer)), port: enet.peer_port(e.peer)})
|
||||
} else if (data.replycc && !data.replycc.address) {
|
||||
data.replycc[ACTORDATA].address = normalize_addr(enet.peer_address(e.peer))
|
||||
data.replycc[ACTORDATA].port = enet.peer_port(e.peer)
|
||||
}
|
||||
if (data.data) populate_actor_addresses(data.data, e)
|
||||
handle_message(data)
|
||||
@@ -1425,8 +1459,8 @@ function handle_host(e) {
|
||||
function populate_actor_addresses(obj, e) {
|
||||
if (!is_object(obj)) return
|
||||
if (obj[ACTORDATA] && !obj[ACTORDATA].address) {
|
||||
obj[ACTORDATA].address = e.peer.address()
|
||||
obj[ACTORDATA].port = e.peer.port()
|
||||
obj[ACTORDATA].address = normalize_addr(enet.peer_address(e.peer))
|
||||
obj[ACTORDATA].port = enet.peer_port(e.peer)
|
||||
}
|
||||
arrfor(array(obj), function(key, index) {
|
||||
if (key in obj)
|
||||
@@ -1436,7 +1470,7 @@ function populate_actor_addresses(obj, e) {
|
||||
|
||||
|
||||
function actor_prep(actor, send) {
|
||||
push(message_queue, {actor,send});
|
||||
message_queue[] = {actor,send};
|
||||
}
|
||||
|
||||
// Send a message immediately without queuing
|
||||
@@ -1447,6 +1481,7 @@ function actor_send_immediate(actor, send) {
|
||||
function actor_send(actor, message) {
|
||||
var wota_blob = null
|
||||
var peer = null
|
||||
var pkey = null
|
||||
|
||||
if (actor[HEADER] && !actor[HEADER].replycc) // attempting to respond to a message but sender is not expecting; silently drop
|
||||
return
|
||||
@@ -1463,12 +1498,14 @@ function actor_send(actor, message) {
|
||||
|
||||
// message to self
|
||||
if (actor[ACTORDATA].id == _cell.id) {
|
||||
log.connection(`actor_send: message to self, type=${message.type}`)
|
||||
if (receive_fn) receive_fn(message.data)
|
||||
return
|
||||
}
|
||||
|
||||
// message to actor in same flock
|
||||
if (actor[ACTORDATA].id && actor_mod.mailbox_exist(actor[ACTORDATA].id)) {
|
||||
log.connection(`actor_send: local mailbox for ${text(actor[ACTORDATA].id, 0, 8)}`)
|
||||
wota_blob = wota.encode(message)
|
||||
actor_mod.mailbox_push(actor[ACTORDATA].id, wota_blob)
|
||||
return
|
||||
@@ -1480,23 +1517,27 @@ function actor_send(actor, message) {
|
||||
else
|
||||
message.type = "contact"
|
||||
|
||||
peer = peers[actor[ACTORDATA].address + ":" + actor[ACTORDATA].port]
|
||||
pkey = actor[ACTORDATA].address + ":" + text(actor[ACTORDATA].port)
|
||||
log.connection(`actor_send: remote ${pkey} msg.type=${message.type}`)
|
||||
peer = peers[pkey]
|
||||
if (!peer) {
|
||||
if (!portal) {
|
||||
log.system(`creating a contactor ...`)
|
||||
log.connection(`actor_send: no portal, creating contactor`)
|
||||
portal = enet.create_host({address:"any"})
|
||||
log.system(`allowing contact to port ${portal.port()}`)
|
||||
log.connection(`actor_send: contactor on port ${text(enet.host_port(portal))}`)
|
||||
enet_check()
|
||||
}
|
||||
log.system(`no peer! connecting to ${actor[ACTORDATA].address}:${actor[ACTORDATA].port}`)
|
||||
peer = portal.connect(actor[ACTORDATA].address, actor[ACTORDATA].port)
|
||||
peer_queue.set(peer, [message])
|
||||
log.connection(`actor_send: no peer for ${pkey}, connecting...`)
|
||||
peer = enet.connect(portal, actor[ACTORDATA].address, actor[ACTORDATA].port)
|
||||
log.connection(`actor_send: connect initiated, peer=${peer}, queuing message`)
|
||||
peer_queue[pkey] = [message]
|
||||
} else {
|
||||
peer.send(nota.encode(message))
|
||||
log.connection(`actor_send: have peer for ${pkey}, sending directly`)
|
||||
enet.send(peer, nota.encode(message))
|
||||
}
|
||||
return
|
||||
}
|
||||
log.system(`Unable to send message to actor ${actor[ACTORDATA].id}`)
|
||||
log.connection(`actor_send: no route for actor id=${actor[ACTORDATA].id} (no address, not local)`)
|
||||
}
|
||||
|
||||
function send_messages() {
|
||||
@@ -1509,6 +1550,8 @@ function send_messages() {
|
||||
|
||||
var _qi = 0
|
||||
var _qm = null
|
||||
if (length(message_queue) > 0)
|
||||
log.connection(`send_messages: processing ${text(length(message_queue))} queued messages`)
|
||||
while (_qi < length(message_queue)) {
|
||||
_qm = message_queue[_qi]
|
||||
if (_qm.startup) {
|
||||
@@ -1667,13 +1710,40 @@ function handle_sysym(msg)
|
||||
function handle_message(msg) {
|
||||
var letter = null
|
||||
var fn = null
|
||||
var conn = null
|
||||
var pkey = null
|
||||
var peer = null
|
||||
var reply_msg = null
|
||||
|
||||
log.connection(`handle_message: type=${msg.type}`)
|
||||
|
||||
if (msg[SYSYM]) {
|
||||
handle_sysym(msg[SYSYM])
|
||||
return
|
||||
}
|
||||
|
||||
if (msg.type == "user") {
|
||||
if (msg.type == "contact") {
|
||||
// Remote $contact arrived — create a connection actor for the caller.
|
||||
// msg.replycc was constructed by handle_host with id + address + port.
|
||||
conn = msg.replycc
|
||||
log.connection(`handle_message: contact from ${conn ? conn[ACTORDATA].id : "unknown"}`)
|
||||
|
||||
// Reply directly over enet so the client's $contact callback fires
|
||||
if (conn && msg.reply) {
|
||||
pkey = conn[ACTORDATA].address + ":" + text(conn[ACTORDATA].port)
|
||||
peer = peers[pkey]
|
||||
if (peer) {
|
||||
reply_msg = {type: "user", data: {type: "connected", actor_id: _cell.id}, return: msg.reply}
|
||||
log.connection(`handle_message: sending contact reply to ${pkey}`)
|
||||
enet.send(peer, nota.encode(reply_msg))
|
||||
}
|
||||
}
|
||||
|
||||
if (portal_fn) {
|
||||
log.connection(`handle_message: calling portal_fn`)
|
||||
portal_fn(conn)
|
||||
}
|
||||
} else if (msg.type == "user") {
|
||||
letter = msg.data // what the sender really sent
|
||||
if (msg.replycc_id) {
|
||||
msg.replycc = create_actor({id: msg.replycc_id})
|
||||
@@ -1683,11 +1753,13 @@ function handle_message(msg) {
|
||||
|
||||
if (msg.return) {
|
||||
fn = replies[msg.return]
|
||||
log.connection(`handle_message: reply callback ${msg.return} fn=${fn ? "yes" : "no"}`)
|
||||
if (fn) fn(letter)
|
||||
delete replies[msg.return]
|
||||
return
|
||||
}
|
||||
|
||||
log.connection(`handle_message: dispatching to receive_fn=${receive_fn ? "yes" : "no"}`)
|
||||
if (receive_fn) receive_fn(letter)
|
||||
} else if (msg.type == "stopped") {
|
||||
handle_actor_disconnect(msg.id)
|
||||
@@ -1696,8 +1768,12 @@ function handle_message(msg) {
|
||||
|
||||
function enet_check()
|
||||
{
|
||||
if (portal) portal.service(handle_host)
|
||||
|
||||
if (portal) {
|
||||
log.connection(`enet_check: servicing portal`)
|
||||
enet.service(portal, handle_host)
|
||||
} else {
|
||||
log.connection(`enet_check: no portal`)
|
||||
}
|
||||
$_.delay(enet_check, ENETSERVICE);
|
||||
}
|
||||
|
||||
|
||||
@@ -1021,19 +1021,41 @@ function ensure_package_dylibs(pkg) {
|
||||
var build_mod = use_cache['core/build']
|
||||
var target = null
|
||||
var c_files = null
|
||||
var _all_ok = true
|
||||
var _ri = 0
|
||||
|
||||
if (build_mod) {
|
||||
target = detect_host_target()
|
||||
if (!target) return null
|
||||
|
||||
c_files = pkg_tools.get_c_files(_pkg, target, true)
|
||||
if (!c_files || length(c_files) == 0) {
|
||||
package_dylibs[_pkg] = []
|
||||
return []
|
||||
// Fast path: if manifest exists and all dylibs are present, skip build_dynamic
|
||||
results = read_dylib_manifest(_pkg)
|
||||
if (results != null) {
|
||||
_all_ok = true
|
||||
_ri = 0
|
||||
while (_ri < length(results)) {
|
||||
if (results[_ri].dylib && !fd.is_file(results[_ri].dylib)) {
|
||||
_all_ok = false
|
||||
break
|
||||
}
|
||||
_ri = _ri + 1
|
||||
}
|
||||
if (_all_ok) {
|
||||
log.shop('manifest ok for ' + _pkg + ' (' + text(length(results)) + ' modules)')
|
||||
} else {
|
||||
results = null
|
||||
}
|
||||
}
|
||||
if (results == null) {
|
||||
target = detect_host_target()
|
||||
if (!target) return null
|
||||
|
||||
log.shop('ensuring C modules for ' + _pkg)
|
||||
results = build_mod.build_dynamic(_pkg, target, 'release', {})
|
||||
c_files = pkg_tools.get_c_files(_pkg, target, true)
|
||||
if (!c_files || length(c_files) == 0) {
|
||||
package_dylibs[_pkg] = []
|
||||
return []
|
||||
}
|
||||
|
||||
log.shop('ensuring C modules for ' + _pkg)
|
||||
results = build_mod.build_dynamic(_pkg, target, 'release', {})
|
||||
}
|
||||
} else {
|
||||
// No build module at runtime — read manifest from cell build
|
||||
results = read_dylib_manifest(_pkg)
|
||||
@@ -1477,18 +1499,18 @@ Shop.use = function use(path, _pkg_ctx) {
|
||||
if (use_cache[info.cache_key])
|
||||
return use_cache[info.cache_key]
|
||||
|
||||
push(use_stack, _use_entry)
|
||||
use_stack[] = _use_entry
|
||||
var _use_result = null
|
||||
var _use_ok = false
|
||||
var _load = function() {
|
||||
_use_result = execute_module(info)
|
||||
_use_ok = true
|
||||
} disruption {
|
||||
pop(use_stack)
|
||||
use_stack[]
|
||||
disrupt
|
||||
}
|
||||
_load()
|
||||
pop(use_stack)
|
||||
use_stack[]
|
||||
use_cache[info.cache_key] = _use_result
|
||||
return _use_result
|
||||
}
|
||||
@@ -1622,12 +1644,16 @@ function download_zip(pkg, commit_hash) {
|
||||
return _download()
|
||||
}
|
||||
|
||||
// Get zip from cache, returns null if not cached
|
||||
// Get zip from cache, returns null if not cached or empty
|
||||
function get_cached_zip(pkg, commit_hash) {
|
||||
var cache_path = get_cache_path(pkg, commit_hash)
|
||||
if (fd.is_file(cache_path))
|
||||
return fd.slurp(cache_path)
|
||||
|
||||
var data = null
|
||||
if (fd.is_file(cache_path)) {
|
||||
data = fd.slurp(cache_path)
|
||||
stone(data)
|
||||
if (length(data) > 0) return data
|
||||
fd.remove(cache_path)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -1883,7 +1909,7 @@ Shop.sync_with_deps = function(pkg, opts) {
|
||||
if (visited[current]) continue
|
||||
visited[current] = true
|
||||
|
||||
log.console(' Fetching ' + current + '...')
|
||||
log.build(' Fetching ' + current + '...')
|
||||
Shop.sync(current, opts)
|
||||
|
||||
_read_deps = function() {
|
||||
@@ -1897,7 +1923,7 @@ Shop.sync_with_deps = function(pkg, opts) {
|
||||
arrfor(array(deps), function(alias) {
|
||||
dep_locator = deps[alias]
|
||||
if (!visited[dep_locator])
|
||||
push(queue, dep_locator)
|
||||
queue[] = dep_locator
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -2036,7 +2062,7 @@ function get_package_scripts(package)
|
||||
for (i = 0; i < length(files); i++) {
|
||||
file = files[i]
|
||||
if (ends_with(file, '.cm') || ends_with(file, '.ce')) {
|
||||
push(scripts, file)
|
||||
scripts[] = file
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2058,7 +2084,7 @@ function extract_use_calls(source) {
|
||||
if (end == null) end = search(text(source, start), '"')
|
||||
if (end != null) {
|
||||
arg = text(source, start, start + end)
|
||||
push(uses, arg)
|
||||
uses[] = arg
|
||||
}
|
||||
idx = search(text(source, idx + 4), "use(")
|
||||
if (idx != null) idx = idx + (source.length - (source.length - idx))
|
||||
@@ -2081,16 +2107,16 @@ Shop.build_package_scripts = function(package)
|
||||
resolve_mod_fn(pkg_dir + '/' + script, package)
|
||||
ok = ok + 1
|
||||
} disruption {
|
||||
push(errors, script)
|
||||
log.console(" compile error: " + package + '/' + script)
|
||||
errors[] = script
|
||||
log.build(" compile error: " + package + '/' + script)
|
||||
}
|
||||
_try()
|
||||
})
|
||||
|
||||
if (length(errors) > 0) {
|
||||
log.console(' Compiling scripts (' + text(ok) + ' ok, ' + text(length(errors)) + ' errors)')
|
||||
log.build(' Compiling scripts (' + text(ok) + ' ok, ' + text(length(errors)) + ' errors)')
|
||||
} else if (ok > 0) {
|
||||
log.console(' Compiling scripts (' + text(ok) + ' ok)')
|
||||
log.build(' Compiling scripts (' + text(ok) + ' ok)')
|
||||
}
|
||||
|
||||
return {ok: ok, errors: errors, total: length(scripts)}
|
||||
@@ -2134,14 +2160,14 @@ Shop.audit_use_resolution = function(package) {
|
||||
end = search(rest, quote)
|
||||
if (end == null) continue
|
||||
arg = text(rest, 0, end)
|
||||
if (length(arg) > 0) push(uses, arg)
|
||||
if (length(arg) > 0) uses[] = arg
|
||||
rest = text(rest, end + 1)
|
||||
}
|
||||
|
||||
arrfor(uses, function(mod) {
|
||||
var _resolve = function() {
|
||||
info = resolve_module_info(mod, package)
|
||||
if (!info) push(unresolved, {script: script, module: mod})
|
||||
if (!info) unresolved[] = {script: script, module: mod}
|
||||
} disruption {}
|
||||
_resolve()
|
||||
})
|
||||
@@ -2392,7 +2418,7 @@ Shop.audit_packages = function() {
|
||||
if (package == 'core') return
|
||||
if (fd.is_dir(package)) return
|
||||
if (fetch_remote_hash(package)) return
|
||||
push(bad, package)
|
||||
bad[] = package
|
||||
})
|
||||
|
||||
return bad
|
||||
|
||||
6
link.cm
6
link.cm
@@ -208,11 +208,11 @@ Link.sync_all = function(shop) {
|
||||
// Validate target exists
|
||||
var link_target = resolve_link_target(target)
|
||||
if (!fd.is_dir(link_target)) {
|
||||
push(errors, canonical + ': target ' + link_target + ' does not exist')
|
||||
errors[] = canonical + ': target ' + link_target + ' does not exist'
|
||||
return
|
||||
}
|
||||
if (!fd.is_file(link_target + '/cell.toml')) {
|
||||
push(errors, canonical + ': target ' + link_target + ' is not a valid package')
|
||||
errors[] = canonical + ': target ' + link_target + ' is not a valid package'
|
||||
return
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ Link.sync_all = function(shop) {
|
||||
|
||||
count = count + 1
|
||||
} disruption {
|
||||
push(errors, canonical + ': sync failed')
|
||||
errors[] = canonical + ': sync failed'
|
||||
}
|
||||
_sync()
|
||||
})
|
||||
|
||||
14
list.ce
14
list.ce
@@ -89,16 +89,16 @@ var run = function() {
|
||||
// Add status indicators
|
||||
status = []
|
||||
if (link_target) {
|
||||
push(status, "linked -> " + link_target)
|
||||
status[] = "linked -> " + link_target
|
||||
}
|
||||
if (lock_entry && lock_entry.commit) {
|
||||
push(status, "@" + text(lock_entry.commit, 0, 8))
|
||||
status[] = "@" + text(lock_entry.commit, 0, 8)
|
||||
}
|
||||
if (lock_entry && lock_entry.type == 'local') {
|
||||
push(status, "local")
|
||||
status[] = "local"
|
||||
}
|
||||
if (!lock_entry) {
|
||||
push(status, "not installed")
|
||||
status[] = "not installed"
|
||||
}
|
||||
|
||||
if (length(status) > 0) {
|
||||
@@ -136,11 +136,11 @@ if (mode == 'local') {
|
||||
var link_target = links[p]
|
||||
|
||||
if (link_target) {
|
||||
push(linked_pkgs, p)
|
||||
linked_pkgs[] = p
|
||||
} else if (lock_entry && lock_entry.type == 'local') {
|
||||
push(local_pkgs, p)
|
||||
local_pkgs[] = p
|
||||
} else {
|
||||
push(remote_pkgs, p)
|
||||
remote_pkgs[] = p
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
10
log.ce
10
log.ce
@@ -371,6 +371,7 @@ function do_enable() {
|
||||
var sink = null
|
||||
var i = 0
|
||||
var already = false
|
||||
var new_exclude = []
|
||||
if (length(args) < 2) {
|
||||
log.error("Usage: cell log enable <channel>")
|
||||
return
|
||||
@@ -388,9 +389,9 @@ function do_enable() {
|
||||
}
|
||||
if (is_array(sink.channels) && length(sink.channels) == 1 && sink.channels[0] == "*") {
|
||||
if (is_array(sink.exclude)) {
|
||||
var new_exclude = []
|
||||
new_exclude = []
|
||||
arrfor(sink.exclude, function(ex) {
|
||||
if (ex != channel) push(new_exclude, ex)
|
||||
if (ex != channel) new_exclude[] = ex
|
||||
})
|
||||
sink.exclude = new_exclude
|
||||
}
|
||||
@@ -411,6 +412,7 @@ function do_disable() {
|
||||
var sink = null
|
||||
var i = 0
|
||||
var new_channels = []
|
||||
var already_excluded = false
|
||||
if (length(args) < 2) {
|
||||
log.error("Usage: cell log disable <channel>")
|
||||
return
|
||||
@@ -428,7 +430,7 @@ function do_disable() {
|
||||
}
|
||||
if (is_array(sink.channels) && length(sink.channels) == 1 && sink.channels[0] == "*") {
|
||||
if (!is_array(sink.exclude)) sink.exclude = []
|
||||
var already_excluded = false
|
||||
already_excluded = false
|
||||
arrfor(sink.exclude, function(ex) {
|
||||
if (ex == channel) already_excluded = true
|
||||
})
|
||||
@@ -436,7 +438,7 @@ function do_disable() {
|
||||
} else {
|
||||
if (is_array(sink.channels)) {
|
||||
arrfor(sink.channels, function(ch) {
|
||||
if (ch != channel) push(new_channels, ch)
|
||||
if (ch != channel) new_channels[] = ch
|
||||
})
|
||||
sink.channels = new_channels
|
||||
}
|
||||
|
||||
2
mcode.ce
2
mcode.ce
@@ -85,7 +85,7 @@ var dump_function = function(func, name) {
|
||||
parts = []
|
||||
j = 1
|
||||
while (j < n - 2) {
|
||||
push(parts, fmt_val(instr[j]))
|
||||
parts[] = fmt_val(instr[j])
|
||||
j = j + 1
|
||||
}
|
||||
operands = text(parts, ", ")
|
||||
|
||||
55
mcode.cm
55
mcode.cm
@@ -166,7 +166,7 @@ var mcode = function(ast) {
|
||||
|
||||
// Variable tracking
|
||||
var add_var = function(name, slot, is_const) {
|
||||
push(s_vars, {name: name, slot: slot, is_const: is_const, is_closure: false})
|
||||
s_vars[] = {name: name, slot: slot, is_const: is_const, is_closure: false}
|
||||
}
|
||||
|
||||
var find_var = function(name) {
|
||||
@@ -228,13 +228,13 @@ var mcode = function(ast) {
|
||||
|
||||
// Instruction emission
|
||||
var add_instr = function(instr) {
|
||||
push(instr, s_cur_line)
|
||||
push(instr, s_cur_col)
|
||||
push(s_instructions, instr)
|
||||
instr[] = s_cur_line
|
||||
instr[] = s_cur_col
|
||||
s_instructions[] = instr
|
||||
}
|
||||
|
||||
var emit_label = function(label) {
|
||||
push(s_instructions, label)
|
||||
s_instructions[] = label
|
||||
}
|
||||
|
||||
var emit_0 = function(op) {
|
||||
@@ -743,7 +743,7 @@ var mcode = function(ast) {
|
||||
slot = alloc_slot()
|
||||
lit = {kind: "name", name: name, make: "intrinsic"}
|
||||
add_instr(["access", slot, lit])
|
||||
push(s_intrinsic_cache, {name: name, slot: slot})
|
||||
s_intrinsic_cache[] = {name: name, slot: slot}
|
||||
_i = _i + 1
|
||||
}
|
||||
}
|
||||
@@ -1974,7 +1974,7 @@ var mcode = function(ast) {
|
||||
expr_slots = []
|
||||
_i = 0
|
||||
while (_i < nexpr) {
|
||||
push(expr_slots, gen_expr(list[_i], -1))
|
||||
expr_slots[] = gen_expr(list[_i], -1)
|
||||
_i = _i + 1
|
||||
}
|
||||
// Create array from expression results
|
||||
@@ -2083,6 +2083,23 @@ var mcode = function(ast) {
|
||||
if (kind == "[") {
|
||||
obj = expr.left
|
||||
idx = expr.right
|
||||
if (idx == null) {
|
||||
// arr[] pop expression
|
||||
obj_slot = gen_expr(obj, -1)
|
||||
guard_t = alloc_slot()
|
||||
guard_err = gen_label("pop_err")
|
||||
guard_done = gen_label("pop_done")
|
||||
emit_2("is_array", guard_t, obj_slot)
|
||||
emit_jump_cond("jump_false", guard_t, guard_err)
|
||||
slot = target >= 0 ? target : alloc_slot()
|
||||
emit_2("pop", slot, obj_slot)
|
||||
emit_jump(guard_done)
|
||||
emit_label(guard_err)
|
||||
emit_log_error("cannot pop: target must be an array")
|
||||
emit_0("disrupt")
|
||||
emit_label(guard_done)
|
||||
return slot
|
||||
}
|
||||
obj_slot = gen_expr(obj, -1)
|
||||
idx_slot = gen_expr(idx, -1)
|
||||
slot = alloc_slot()
|
||||
@@ -2264,7 +2281,7 @@ var mcode = function(ast) {
|
||||
_i = 0
|
||||
nargs = args_list != null ? length(args_list) : 0
|
||||
while (_i < nargs) {
|
||||
push(arg_slots, gen_expr(args_list[_i], -1))
|
||||
arg_slots[] = gen_expr(args_list[_i], -1)
|
||||
_i = _i + 1
|
||||
}
|
||||
dest = alloc_slot()
|
||||
@@ -2432,7 +2449,7 @@ var mcode = function(ast) {
|
||||
elem_slots = []
|
||||
_i = 0
|
||||
while (_i < count) {
|
||||
push(elem_slots, gen_expr(list[_i], -1))
|
||||
elem_slots[] = gen_expr(list[_i], -1)
|
||||
_i = _i + 1
|
||||
}
|
||||
dest = alloc_slot()
|
||||
@@ -2449,7 +2466,7 @@ var mcode = function(ast) {
|
||||
if (kind == "record") {
|
||||
list = expr.list
|
||||
dest = alloc_slot()
|
||||
push(s_instructions, ["record", dest, length(list)])
|
||||
s_instructions[] = ["record", dest, length(list)]
|
||||
_i = 0
|
||||
while (_i < length(list)) {
|
||||
pair = list[_i]
|
||||
@@ -2479,7 +2496,7 @@ var mcode = function(ast) {
|
||||
func = gen_function(expr)
|
||||
func_id = s_func_counter
|
||||
s_func_counter = s_func_counter + 1
|
||||
push(s_functions, func)
|
||||
s_functions[] = func
|
||||
dest = alloc_slot()
|
||||
emit_2("function", dest, func_id)
|
||||
return dest
|
||||
@@ -2797,7 +2814,7 @@ var mcode = function(ast) {
|
||||
_i = 0
|
||||
nargs = args_list != null ? length(args_list) : 0
|
||||
while (_i < nargs) {
|
||||
push(arg_slots, gen_expr(args_list[_i], -1))
|
||||
arg_slots[] = gen_expr(args_list[_i], -1)
|
||||
_i = _i + 1
|
||||
}
|
||||
callee_kind = callee.kind
|
||||
@@ -2852,7 +2869,7 @@ var mcode = function(ast) {
|
||||
case_kind = case_node.kind
|
||||
if (case_kind == "default") {
|
||||
default_label = gen_label("switch_default")
|
||||
push(case_labels, default_label)
|
||||
case_labels[] = default_label
|
||||
} else {
|
||||
case_label = gen_label("switch_case")
|
||||
case_expr = case_node.expression
|
||||
@@ -2862,7 +2879,7 @@ var mcode = function(ast) {
|
||||
_bp_rn = case_expr
|
||||
emit_binop("eq", cmp_slot, switch_val, case_val)
|
||||
emit_jump_cond("jump_true", cmp_slot, case_label)
|
||||
push(case_labels, case_label)
|
||||
case_labels[] = case_label
|
||||
}
|
||||
_i = _i + 1
|
||||
}
|
||||
@@ -2894,7 +2911,7 @@ var mcode = function(ast) {
|
||||
func = gen_function(stmt)
|
||||
func_id = s_func_counter
|
||||
s_func_counter = s_func_counter + 1
|
||||
push(s_functions, func)
|
||||
s_functions[] = func
|
||||
local_slot = find_var(name)
|
||||
dest = alloc_slot()
|
||||
emit_2("function", dest, func_id)
|
||||
@@ -2948,7 +2965,7 @@ var mcode = function(ast) {
|
||||
var saved_func = 0
|
||||
var captured_this = 0
|
||||
|
||||
push(parent_states, saved)
|
||||
parent_states[] = saved
|
||||
|
||||
s_instructions = []
|
||||
s_vars = []
|
||||
@@ -3039,7 +3056,7 @@ var mcode = function(ast) {
|
||||
compiled = gen_function(fn)
|
||||
func_id = s_func_counter
|
||||
s_func_counter = s_func_counter + 1
|
||||
push(s_functions, compiled)
|
||||
s_functions[] = compiled
|
||||
local_slot = find_var(fname)
|
||||
dest = alloc_slot()
|
||||
emit_2("function", dest, func_id)
|
||||
@@ -3112,7 +3129,7 @@ var mcode = function(ast) {
|
||||
saved_func = s_func_counter
|
||||
|
||||
// Pop parent state
|
||||
pop(parent_states)
|
||||
parent_states[]
|
||||
restore_state(saved)
|
||||
s_label_counter = saved_label
|
||||
s_func_counter = saved_func
|
||||
@@ -3179,7 +3196,7 @@ var mcode = function(ast) {
|
||||
compiled = gen_function(fn)
|
||||
func_id = s_func_counter
|
||||
s_func_counter = s_func_counter + 1
|
||||
push(s_functions, compiled)
|
||||
s_functions[] = compiled
|
||||
local_slot = find_var(name)
|
||||
dest = alloc_slot()
|
||||
emit_2("function", dest, func_id)
|
||||
|
||||
6
pack.ce
6
pack.ce
@@ -88,9 +88,9 @@ var packages = ['core']
|
||||
var deps = pkg_tools.gather_dependencies(target_package)
|
||||
|
||||
for (i = 0; i < length(deps); i++) {
|
||||
push(packages, deps[i])
|
||||
packages[] = deps[i]
|
||||
}
|
||||
push(packages, target_package)
|
||||
packages[] = target_package
|
||||
|
||||
// Remove duplicates
|
||||
var unique_packages = []
|
||||
@@ -98,7 +98,7 @@ var seen = {}
|
||||
for (i = 0; i < length(packages); i++) {
|
||||
if (!seen[packages[i]]) {
|
||||
seen[packages[i]] = true
|
||||
push(unique_packages, packages[i])
|
||||
unique_packages[] = packages[i]
|
||||
}
|
||||
}
|
||||
packages = unique_packages
|
||||
|
||||
12
package.cm
12
package.cm
@@ -198,7 +198,7 @@ package.find_packages = function(dir) {
|
||||
var list = fd.readdir(dir)
|
||||
if (!list) return found
|
||||
if (fd.is_file(dir + '/cell.toml'))
|
||||
push(found, dir)
|
||||
found[] = dir
|
||||
arrfor(list, function(item) {
|
||||
if (item == '.' || item == '..' || item == '.cell' || item == '.git') return
|
||||
var full = dir + '/' + item
|
||||
@@ -207,7 +207,7 @@ package.find_packages = function(dir) {
|
||||
if (st && st.isDirectory) {
|
||||
sub = package.find_packages(full)
|
||||
arrfor(sub, function(p) {
|
||||
push(found, p)
|
||||
found[] = p
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -227,14 +227,14 @@ package.list_modules = function(name) {
|
||||
var stem = null
|
||||
for (i = 0; i < length(files); i++) {
|
||||
if (ends_with(files[i], '.cm')) {
|
||||
push(modules, text(files[i], 0, -3))
|
||||
modules[] = text(files[i], 0, -3)
|
||||
}
|
||||
}
|
||||
var c_files = package.get_c_files(name, null, true)
|
||||
for (i = 0; i < length(c_files); i++) {
|
||||
stem = ends_with(c_files[i], '.cpp') ? text(c_files[i], 0, -4) : text(c_files[i], 0, -2)
|
||||
if (find(modules, function(m) { return m == stem }) == null)
|
||||
push(modules, stem)
|
||||
modules[] = stem
|
||||
}
|
||||
return modules
|
||||
}
|
||||
@@ -245,7 +245,7 @@ package.list_programs = function(name) {
|
||||
var i = 0
|
||||
for (i = 0; i < length(files); i++) {
|
||||
if (ends_with(files[i], '.ce')) {
|
||||
push(programs, text(files[i], 0, -3))
|
||||
programs[] = text(files[i], 0, -3)
|
||||
}
|
||||
}
|
||||
return programs
|
||||
@@ -360,7 +360,7 @@ package.get_c_files = function(name, target, exclude_main) {
|
||||
basename = fd.basename(selected)
|
||||
if (basename == 'main.c' || starts_with(basename, 'main_')) return
|
||||
}
|
||||
push(result, selected)
|
||||
result[] = selected
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
98
parse.cm
98
parse.cm
@@ -90,12 +90,12 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
var parse_error = function(token, msg) {
|
||||
if (error_count >= 5) return null
|
||||
error_count = error_count + 1
|
||||
push(errors, {
|
||||
errors[] = {
|
||||
message: msg,
|
||||
line: token.from_row + 1,
|
||||
column: token.from_column + 1,
|
||||
offset: token.at
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var _keywords = {
|
||||
@@ -230,8 +230,8 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
if (tv[tvi] == "\\" && tvi + 1 < tvlen) {
|
||||
esc_ch = tv[tvi + 1]
|
||||
esc_val = template_escape_map[esc_ch]
|
||||
if (esc_val != null) { push(fmt_parts, esc_val) }
|
||||
else { push(fmt_parts, esc_ch) }
|
||||
if (esc_val != null) { fmt_parts[] = esc_val }
|
||||
else { fmt_parts[] = esc_ch }
|
||||
tvi = tvi + 2
|
||||
} else if (tv[tvi] == "$" && tvi + 1 < tvlen && tv[tvi + 1] == "{") {
|
||||
tvi = tvi + 2
|
||||
@@ -239,27 +239,27 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
expr_parts = []
|
||||
while (tvi < tvlen && depth > 0) {
|
||||
tc = tv[tvi]
|
||||
if (tc == "{") { depth = depth + 1; push(expr_parts, tc); tvi = tvi + 1 }
|
||||
if (tc == "{") { depth = depth + 1; expr_parts[] = tc; tvi = tvi + 1 }
|
||||
else if (tc == "}") {
|
||||
depth = depth - 1
|
||||
if (depth > 0) { push(expr_parts, tc) }
|
||||
if (depth > 0) { expr_parts[] = tc }
|
||||
tvi = tvi + 1
|
||||
}
|
||||
else if (tc == "'" || tc == "\"" || tc == "`") {
|
||||
tq = tc
|
||||
push(expr_parts, tc)
|
||||
expr_parts[] = tc
|
||||
tvi = tvi + 1
|
||||
while (tvi < tvlen && tv[tvi] != tq) {
|
||||
if (tv[tvi] == "\\" && tvi + 1 < tvlen) {
|
||||
push(expr_parts, tv[tvi])
|
||||
expr_parts[] = tv[tvi]
|
||||
tvi = tvi + 1
|
||||
}
|
||||
push(expr_parts, tv[tvi])
|
||||
expr_parts[] = tv[tvi]
|
||||
tvi = tvi + 1
|
||||
}
|
||||
if (tvi < tvlen) { push(expr_parts, tv[tvi]); tvi = tvi + 1 }
|
||||
if (tvi < tvlen) { expr_parts[] = tv[tvi]; tvi = tvi + 1 }
|
||||
} else {
|
||||
push(expr_parts, tc)
|
||||
expr_parts[] = tc
|
||||
tvi = tvi + 1
|
||||
}
|
||||
}
|
||||
@@ -274,14 +274,14 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
} else {
|
||||
sub_expr = sub_stmt
|
||||
}
|
||||
push(tpl_list, sub_expr)
|
||||
tpl_list[] = sub_expr
|
||||
}
|
||||
push(fmt_parts, "{")
|
||||
push(fmt_parts, text(idx))
|
||||
push(fmt_parts, "}")
|
||||
fmt_parts[] = "{"
|
||||
fmt_parts[] = text(idx)
|
||||
fmt_parts[] = "}"
|
||||
idx = idx + 1
|
||||
} else {
|
||||
push(fmt_parts, tv[tvi])
|
||||
fmt_parts[] = tv[tvi]
|
||||
tvi = tvi + 1
|
||||
}
|
||||
}
|
||||
@@ -332,7 +332,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
advance()
|
||||
while (tok.kind != "]" && tok.kind != "eof") {
|
||||
elem = parse_assign_expr()
|
||||
if (elem != null) push(list, elem)
|
||||
if (elem != null) list[] = elem
|
||||
if (tok.kind == ",") advance()
|
||||
else break
|
||||
}
|
||||
@@ -395,7 +395,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
advance()
|
||||
param.expression = parse_assign_expr()
|
||||
}
|
||||
push(params, param)
|
||||
params[] = param
|
||||
} else {
|
||||
parse_error(tok, "expected parameter name")
|
||||
break
|
||||
@@ -436,7 +436,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
} else {
|
||||
parse_error(tok, "expected ':' after property name")
|
||||
}
|
||||
push(list, pair)
|
||||
list[] = pair
|
||||
if (tok.kind == ",") advance()
|
||||
else if (tok.kind == "{") {
|
||||
if (right && right.kind == "(") {
|
||||
@@ -473,17 +473,17 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
flags_parts = []
|
||||
while (rpos < _src_len && src[rpos] != "/") {
|
||||
if (src[rpos] == "\\" && rpos + 1 < _src_len) {
|
||||
push(pattern_parts, src[rpos])
|
||||
push(pattern_parts, src[rpos + 1])
|
||||
pattern_parts[] = src[rpos]
|
||||
pattern_parts[] = src[rpos + 1]
|
||||
rpos = rpos + 2
|
||||
} else {
|
||||
push(pattern_parts, src[rpos])
|
||||
pattern_parts[] = src[rpos]
|
||||
rpos = rpos + 1
|
||||
}
|
||||
}
|
||||
if (rpos < _src_len) rpos = rpos + 1
|
||||
while (rpos < _src_len && is_letter(src[rpos])) {
|
||||
push(flags_parts, src[rpos])
|
||||
flags_parts[] = src[rpos]
|
||||
rpos = rpos + 1
|
||||
}
|
||||
node.pattern = text(pattern_parts)
|
||||
@@ -557,7 +557,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
new_node.list = args_list
|
||||
while (tok.kind != ")" && tok.kind != "eof") {
|
||||
arg = parse_assign_expr()
|
||||
if (arg != null) push(args_list, arg)
|
||||
if (arg != null) args_list[] = arg
|
||||
if (tok.kind == ",") advance()
|
||||
else break
|
||||
}
|
||||
@@ -830,7 +830,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
before = cursor
|
||||
stmt = parse_statement()
|
||||
if (stmt != null) {
|
||||
push(stmts, stmt)
|
||||
stmts[] = stmt
|
||||
} else if (cursor == before) {
|
||||
sync_to_statement()
|
||||
}
|
||||
@@ -872,14 +872,14 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
param.name = tok.value
|
||||
pname = tok.value
|
||||
if (find(prev_names, pname) != null) parse_error(tok, "duplicate parameter name '" + pname + "'")
|
||||
push(prev_names, pname)
|
||||
prev_names[] = pname
|
||||
advance()
|
||||
ast_node_end(param)
|
||||
if (tok.kind == "=" || tok.kind == "|") {
|
||||
advance()
|
||||
param.expression = parse_assign_expr()
|
||||
}
|
||||
push(params, param)
|
||||
params[] = param
|
||||
} else {
|
||||
parse_error(tok, "expected parameter name")
|
||||
break
|
||||
@@ -959,7 +959,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
param.name = tok.value
|
||||
advance()
|
||||
ast_node_end(param)
|
||||
push(params, param)
|
||||
params[] = param
|
||||
} else if (tok.kind == "(") {
|
||||
advance()
|
||||
prev_names = []
|
||||
@@ -969,14 +969,14 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
param.name = tok.value
|
||||
pname = tok.value
|
||||
if (find(prev_names, pname) != null) parse_error(tok, "duplicate parameter name '" + pname + "'")
|
||||
push(prev_names, pname)
|
||||
prev_names[] = pname
|
||||
advance()
|
||||
ast_node_end(param)
|
||||
if (tok.kind == "=" || tok.kind == "|") {
|
||||
advance()
|
||||
param.expression = parse_assign_expr()
|
||||
}
|
||||
push(params, param)
|
||||
params[] = param
|
||||
} else {
|
||||
parse_error(tok, "expected parameter name")
|
||||
break
|
||||
@@ -1010,7 +1010,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
expr = parse_assign_expr()
|
||||
ret.expression = expr
|
||||
ast_node_end(ret)
|
||||
push(stmts, ret)
|
||||
stmts[] = ret
|
||||
node.statements = stmts
|
||||
}
|
||||
|
||||
@@ -1110,7 +1110,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
parse_error(start, "'var' declarations must be initialized; use 'var " + var_name + " = null' if no value is needed")
|
||||
}
|
||||
ast_node_end(node)
|
||||
push(decls, node)
|
||||
decls[] = node
|
||||
decl_count = decl_count + 1
|
||||
if (tok.kind == ",") advance()
|
||||
else break
|
||||
@@ -1142,7 +1142,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
_control_depth = _control_depth + 1
|
||||
_expecting_body = true
|
||||
body = parse_statement()
|
||||
if (body != null) push(then_stmts, body)
|
||||
if (body != null) then_stmts[] = body
|
||||
else_ifs = []
|
||||
node.list = else_ifs
|
||||
if (tok.kind == "else") {
|
||||
@@ -1151,7 +1151,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
_control_depth = saved_cd
|
||||
_control_type = saved_ct
|
||||
elif = parse_statement()
|
||||
if (elif != null) push(else_ifs, elif)
|
||||
if (elif != null) else_ifs[] = elif
|
||||
ast_node_end(node)
|
||||
return node
|
||||
} else {
|
||||
@@ -1159,7 +1159,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
node.else = else_stmts
|
||||
_expecting_body = true
|
||||
body = parse_statement()
|
||||
if (body != null) push(else_stmts, body)
|
||||
if (body != null) else_stmts[] = body
|
||||
}
|
||||
}
|
||||
_control_depth = saved_cd
|
||||
@@ -1185,7 +1185,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
_control_depth = _control_depth + 1
|
||||
_expecting_body = true
|
||||
body = parse_statement()
|
||||
if (body != null) push(stmts, body)
|
||||
if (body != null) stmts[] = body
|
||||
_control_depth = saved_cd
|
||||
_control_type = saved_ct
|
||||
ast_node_end(node)
|
||||
@@ -1203,7 +1203,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
_control_depth = _control_depth + 1
|
||||
_expecting_body = true
|
||||
body = parse_statement()
|
||||
if (body != null) push(stmts, body)
|
||||
if (body != null) stmts[] = body
|
||||
_control_depth = saved_cd
|
||||
_control_type = saved_ct
|
||||
if (tok.kind == "while") advance()
|
||||
@@ -1256,7 +1256,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
_control_depth = _control_depth + 1
|
||||
_expecting_body = true
|
||||
body = parse_statement()
|
||||
if (body != null) push(stmts, body)
|
||||
if (body != null) stmts[] = body
|
||||
_control_depth = saved_cd
|
||||
_control_type = saved_ct
|
||||
ast_node_end(node)
|
||||
@@ -1402,9 +1402,9 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
stmt = parse_statement()
|
||||
if (stmt != null) {
|
||||
if (stmt.kind == "function") {
|
||||
push(functions, stmt)
|
||||
functions[] = stmt
|
||||
} else {
|
||||
push(statements, stmt)
|
||||
statements[] = stmt
|
||||
}
|
||||
} else if (cursor == before) {
|
||||
sync_to_statement()
|
||||
@@ -1426,7 +1426,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
var err = {message: msg}
|
||||
if (node.from_row != null) err.line = node.from_row + 1
|
||||
if (node.from_column != null) err.column = node.from_column + 1
|
||||
push(sem_errors, err)
|
||||
sem_errors[] = err
|
||||
}
|
||||
|
||||
var make_scope = function(parent, fn_nr, opts) {
|
||||
@@ -1452,7 +1452,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
}
|
||||
if (make_opts.reached == false) entry.reached = false
|
||||
if (make_opts.decl_line != null) entry.decl_line = make_opts.decl_line
|
||||
push(scope.vars, entry)
|
||||
scope.vars[] = entry
|
||||
}
|
||||
|
||||
var sem_lookup_var = function(scope, name) {
|
||||
@@ -1503,7 +1503,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
}
|
||||
|
||||
var sem_add_intrinsic = function(name) {
|
||||
if (find(intrinsics, name) == null) push(intrinsics, name)
|
||||
if (find(intrinsics, name) == null) intrinsics[] = name
|
||||
}
|
||||
|
||||
var functino_names = {
|
||||
@@ -1828,7 +1828,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
}
|
||||
}
|
||||
sr = sem_build_scope_record(fn_scope)
|
||||
push(scopes_array, sr.rec)
|
||||
scopes_array[] = sr.rec
|
||||
expr.nr_slots = sr.nr_slots
|
||||
expr.nr_close_slots = sr.nr_close
|
||||
return null
|
||||
@@ -1858,9 +1858,9 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
r.v.nr_uses = r.v.nr_uses + 1
|
||||
if (r.level > 0) r.v.closure = 1
|
||||
if (r.v.reached == false && r.v.decl_line != null && expr.from_row != null && expr.from_row + 1 < r.v.decl_line) {
|
||||
push(hoisted_fn_refs, {name: name, line: expr.from_row + 1,
|
||||
hoisted_fn_refs[] = {name: name, line: expr.from_row + 1,
|
||||
col: expr.from_column != null ? expr.from_column + 1 : null,
|
||||
decl_line: r.v.decl_line})
|
||||
decl_line: r.v.decl_line}
|
||||
}
|
||||
} else {
|
||||
expr.level = -1
|
||||
@@ -2110,7 +2110,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
}
|
||||
}
|
||||
sr = sem_build_scope_record(fn_scope)
|
||||
push(scopes_array, sr.rec)
|
||||
scopes_array[] = sr.rec
|
||||
stmt.nr_slots = sr.nr_slots
|
||||
stmt.nr_close_slots = sr.nr_close
|
||||
return null
|
||||
@@ -2153,7 +2153,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
new_scopes = [sr.rec]
|
||||
i = 0
|
||||
while (i < length(scopes_array)) {
|
||||
push(new_scopes, scopes_array[i])
|
||||
new_scopes[] = scopes_array[i]
|
||||
i = i + 1
|
||||
}
|
||||
scopes_array = new_scopes
|
||||
@@ -2183,7 +2183,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
if (ast.errors != null) {
|
||||
_mi = 0
|
||||
while (_mi < length(errors)) {
|
||||
push(ast.errors, errors[_mi])
|
||||
ast.errors[] = errors[_mi]
|
||||
_mi = _mi + 1
|
||||
}
|
||||
} else {
|
||||
|
||||
14
qbe_emit.cm
14
qbe_emit.cm
@@ -948,7 +948,7 @@ var qbe_emit = function(ir, qbe, export_name) {
|
||||
// ============================================================
|
||||
|
||||
var emit = function(s) {
|
||||
push(out, s)
|
||||
out[] = s
|
||||
}
|
||||
|
||||
var fresh = function() {
|
||||
@@ -982,9 +982,9 @@ var qbe_emit = function(ir, qbe, export_name) {
|
||||
escaped = replace(escaped, "\r", "\\r")
|
||||
escaped = replace(escaped, "\t", "\\t")
|
||||
var line = "data " + label + ' = ' + '{ b "' + escaped + '", b 0 }'
|
||||
push(data_out, line)
|
||||
data_out[] = line
|
||||
var entry = { label: label, idx: length(str_entries) }
|
||||
push(str_entries, entry)
|
||||
str_entries[] = entry
|
||||
str_table[val] = entry
|
||||
return entry
|
||||
}
|
||||
@@ -2909,16 +2909,16 @@ var qbe_emit = function(ir, qbe, export_name) {
|
||||
|
||||
// Export nr_slots for main function so the module loader can use right-sized frames
|
||||
var main_name = export_name ? sanitize(export_name) : "cell_main"
|
||||
push(data_out, "export data $" + main_name + "_nr_slots = { w " + text(ir.main.nr_slots) + " }")
|
||||
push(data_out, "export data $cell_lit_count = { w " + text(length(str_entries)) + " }")
|
||||
data_out[] = "export data $" + main_name + "_nr_slots = { w " + text(ir.main.nr_slots) + " }"
|
||||
data_out[] = "export data $cell_lit_count = { w " + text(length(str_entries)) + " }"
|
||||
if (length(str_entries) > 0) {
|
||||
lit_data = []
|
||||
si = 0
|
||||
while (si < length(str_entries)) {
|
||||
push(lit_data, `l ${str_entries[si].label}`)
|
||||
lit_data[] = `l ${str_entries[si].label}`
|
||||
si = si + 1
|
||||
}
|
||||
push(data_out, "export data $cell_lit_table = { " + text(lit_data, ", ") + " }")
|
||||
data_out[] = "export data $cell_lit_table = { " + text(lit_data, ", ") + " }"
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -149,7 +149,7 @@ if (!is_array(args) || length(args) < 1) {
|
||||
}
|
||||
|
||||
for (; i < length(args) - 1; i++) {
|
||||
push(sources, args[i])
|
||||
sources[] = args[i]
|
||||
}
|
||||
archive = args[length(args) - 1]
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ var run = function() {
|
||||
arrfor(all_packages, function(p) {
|
||||
if (p == 'core') return
|
||||
if (!needed[p] && find(packages_to_remove, p) == null) {
|
||||
push(packages_to_remove, p)
|
||||
packages_to_remove[] = p
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
10
resolve.ce
10
resolve.ce
@@ -165,11 +165,11 @@ for (i = 0; i < length(sorted); i++) {
|
||||
|
||||
// Format output
|
||||
status_parts = []
|
||||
if (is_linked) push(status_parts, "linked")
|
||||
if (is_local) push(status_parts, "local")
|
||||
if (!is_in_lock) push(status_parts, "not in lock")
|
||||
if (!is_fetched) push(status_parts, "not fetched")
|
||||
if (has_c_files) push(status_parts, "has C modules")
|
||||
if (is_linked) status_parts[] = "linked"
|
||||
if (is_local) status_parts[] = "local"
|
||||
if (!is_in_lock) status_parts[] = "not in lock"
|
||||
if (!is_fetched) status_parts[] = "not fetched"
|
||||
if (has_c_files) status_parts[] = "has C modules"
|
||||
|
||||
commit_str = ""
|
||||
if (lock_entry && lock_entry.commit) {
|
||||
|
||||
@@ -21,7 +21,7 @@ var packages = shop.list_packages()
|
||||
arrfor(packages, function(package_name) {
|
||||
// Check if package name matches
|
||||
if (search(package_name, query) != null) {
|
||||
push(found_packages, package_name)
|
||||
found_packages[] = package_name
|
||||
}
|
||||
|
||||
// Search modules and actors within the package
|
||||
@@ -29,14 +29,14 @@ arrfor(packages, function(package_name) {
|
||||
var modules = pkg.list_modules(package_name)
|
||||
arrfor(modules, function(mod) {
|
||||
if (search(mod, query) != null) {
|
||||
push(found_modules, package_name + ':' + mod)
|
||||
found_modules[] = package_name + ':' + mod
|
||||
}
|
||||
})
|
||||
|
||||
var actors = pkg.list_programs(package_name)
|
||||
arrfor(actors, function(actor) {
|
||||
if (search(actor, query) != null) {
|
||||
push(found_actors, package_name + ':' + actor)
|
||||
found_actors[] = package_name + ':' + actor
|
||||
}
|
||||
})
|
||||
} disruption {
|
||||
|
||||
6
slots.ce
6
slots.ce
@@ -179,7 +179,7 @@ var run = function() {
|
||||
first_def[slot_num] = pc
|
||||
first_def_op[slot_num] = op
|
||||
}
|
||||
push(events, {kind: "DEF", slot: operand_val, pc: pc, instr: instr})
|
||||
events[] = {kind: "DEF", slot: operand_val, pc: pc, instr: instr}
|
||||
}
|
||||
di = di + 1
|
||||
}
|
||||
@@ -191,7 +191,7 @@ var run = function() {
|
||||
slot_num = text(operand_val)
|
||||
if (!uses[slot_num]) uses[slot_num] = 0
|
||||
uses[slot_num] = uses[slot_num] + 1
|
||||
push(events, {kind: "USE", slot: operand_val, pc: pc, instr: instr})
|
||||
events[] = {kind: "USE", slot: operand_val, pc: pc, instr: instr}
|
||||
}
|
||||
ui = ui + 1
|
||||
}
|
||||
@@ -219,7 +219,7 @@ var run = function() {
|
||||
parts = []
|
||||
j = 1
|
||||
while (j < n - 2) {
|
||||
push(parts, fmt_val(evt.instr[j]))
|
||||
parts[] = fmt_val(evt.instr[j])
|
||||
j = j + 1
|
||||
}
|
||||
operands = text(parts, ", ")
|
||||
|
||||
@@ -313,6 +313,26 @@ void actor_disrupt(JSContext *ctx)
|
||||
JSValue js_core_internal_os_use(JSContext *js);
|
||||
JSValue js_core_json_use(JSContext *js);
|
||||
|
||||
/* Engine-env log proxy: routes log("channel", [msg]) through JS_Log.
|
||||
Before set_log is called, JS_Log falls back to stderr.
|
||||
After set_log, JS_Log forwards to the engine's JS log function.
|
||||
This exists so mcode-generated type-check error paths (which always
|
||||
access 'log' as an intrinsic) work inside engine.cm itself. */
|
||||
static JSValue js_engine_log(JSContext *js, JSValue self,
|
||||
int argc, JSValue *argv) {
|
||||
if (argc < 2) return JS_NULL;
|
||||
const char *channel = JS_ToCString(js, argv[0]);
|
||||
if (!channel) return JS_NULL;
|
||||
JSValue msg_val = JS_GetPropertyNumber(js, argv[1], 0);
|
||||
const char *msg = JS_ToCString(js, msg_val);
|
||||
if (msg) {
|
||||
JS_Log(js, channel, "%s", msg);
|
||||
JS_FreeCString(js, msg);
|
||||
}
|
||||
JS_FreeCString(js, channel);
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
void script_startup(JSContext *js)
|
||||
{
|
||||
if (!g_runtime) {
|
||||
@@ -414,6 +434,8 @@ void script_startup(JSContext *js)
|
||||
}
|
||||
tmp = shop_path ? JS_NewString(js, shop_path) : JS_NULL;
|
||||
JS_SetPropertyStr(js, env_ref.val, "shop_path", tmp);
|
||||
tmp = JS_NewCFunction(js, js_engine_log, "log", 2);
|
||||
JS_SetPropertyStr(js, env_ref.val, "log", tmp);
|
||||
|
||||
// Stone the environment
|
||||
JSValue hidden_env = JS_Stone(js, env_ref.val);
|
||||
@@ -761,6 +783,8 @@ int cell_init(int argc, char **argv)
|
||||
}
|
||||
JS_SetPropertyStr(ctx, env_ref.val, "args", args_ref.val);
|
||||
JS_DeleteGCRef(ctx, &args_ref);
|
||||
tmp = JS_NewCFunction(ctx, js_engine_log, "log", 2);
|
||||
JS_SetPropertyStr(ctx, env_ref.val, "log", tmp);
|
||||
JSValue hidden_env = JS_Stone(ctx, env_ref.val);
|
||||
|
||||
g_crash_ctx = ctx;
|
||||
|
||||
@@ -876,7 +876,7 @@ typedef struct {
|
||||
#define ACTOR_SLOW 5
|
||||
#define ACTOR_REFRESHED 6
|
||||
|
||||
#define ACTOR_FAST_TIMER_NS (10ULL * 1000000)
|
||||
#define ACTOR_FAST_TIMER_NS (1000ULL * 1000000)
|
||||
#define ACTOR_SLOW_TIMER_NS (60000ULL * 1000000)
|
||||
#define ACTOR_SLOW_STRIKES_MAX 3
|
||||
#define ACTOR_MEMORY_LIMIT (1024ULL * 1024 * 1024)
|
||||
|
||||
@@ -1915,12 +1915,13 @@ int ctx_gc (JSContext *ctx, int allow_grow, size_t alloc_size) {
|
||||
if (ctx->trace_hook && (ctx->trace_type & JS_HOOK_GC))
|
||||
ctx->trace_hook(ctx, JS_HOOK_GC, NULL, ctx->trace_data);
|
||||
|
||||
/* Check memory limit — kill actor if heap exceeds cap */
|
||||
/* Check memory limit — kill actor if heap exceeds cap.
|
||||
Use JS_Log "memory" channel which always fprintf's (safe during GC). */
|
||||
if (ctx->heap_memory_limit > 0 && ctx->current_block_size > ctx->heap_memory_limit) {
|
||||
#ifdef ACTOR_TRACE
|
||||
fprintf(stderr, "[ACTOR_TRACE] heap %zu > limit %zu, OOM\n",
|
||||
ctx->current_block_size, ctx->heap_memory_limit);
|
||||
#endif
|
||||
JS_Log(ctx, "memory", "%s: heap %zuKB exceeds limit %zuMB, killing",
|
||||
ctx->name ? ctx->name : ctx->id,
|
||||
ctx->current_block_size / 1024,
|
||||
ctx->heap_memory_limit / (1024 * 1024));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -3283,19 +3284,18 @@ JS_RaiseDisrupt (JSContext *ctx, const char *fmt, ...) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
/* Log to "memory" channel + disrupt. Skips JS callback (can't allocate). */
|
||||
/* Log to "memory" channel + disrupt. Skips JS callback (can't allocate).
|
||||
Uses fprintf directly — safe even during OOM. */
|
||||
JSValue JS_RaiseOOM (JSContext *ctx) {
|
||||
size_t used = (size_t)((uint8_t *)ctx->heap_free - (uint8_t *)ctx->heap_base);
|
||||
size_t block = ctx->current_block_size;
|
||||
size_t limit = ctx->heap_memory_limit;
|
||||
const char *name = ctx->name ? ctx->name : ctx->id;
|
||||
const char *label = ctx->actor_label;
|
||||
if (limit > 0) {
|
||||
fprintf(stderr, "out of memory: heap %zuKB / %zuKB block, limit %zuMB",
|
||||
used / 1024, block / 1024, limit / (1024 * 1024));
|
||||
} else {
|
||||
fprintf(stderr, "out of memory: heap %zuKB / %zuKB block, no limit",
|
||||
used / 1024, block / 1024);
|
||||
}
|
||||
fprintf(stderr, "[memory] %s: out of memory — heap %zuKB / %zuKB block",
|
||||
name ? name : "?", used / 1024, block / 1024);
|
||||
if (limit > 0)
|
||||
fprintf(stderr, ", limit %zuMB", limit / (1024 * 1024));
|
||||
if (label)
|
||||
fprintf(stderr, " [%s]", label);
|
||||
fprintf(stderr, "\n");
|
||||
@@ -12009,7 +12009,7 @@ void JS_CrashPrintStack(JSContext *ctx) {
|
||||
if (!ctx) return;
|
||||
if (JS_IsNull(ctx->reg_current_frame)) return;
|
||||
|
||||
static const char hdr[] = "\n--- JS Stack at crash ---\n";
|
||||
static const char hdr[] = "\n--- JS Stack ---\n";
|
||||
write(STDERR_FILENO, hdr, sizeof(hdr) - 1);
|
||||
|
||||
JSFrameRegister *frame = (JSFrameRegister *)JS_VALUE_GET_PTR(ctx->reg_current_frame);
|
||||
|
||||
@@ -293,9 +293,15 @@ void *timer_thread_func(void *arg) {
|
||||
/* Only fire if turn_gen still matches (stale timers are ignored) */
|
||||
uint32_t cur = atomic_load_explicit(&t.actor->turn_gen, memory_order_relaxed);
|
||||
if (cur == t.turn_gen) {
|
||||
/* Can't call JS_Log from timer thread — use fprintf */
|
||||
const char *name = t.actor->name ? t.actor->name : t.actor->id;
|
||||
if (t.type == TIMER_PAUSE) {
|
||||
fprintf(stderr, "[slow] %s: pausing (turn exceeded %llums)\n",
|
||||
name, (unsigned long long)(ACTOR_FAST_TIMER_NS / 1000000));
|
||||
JS_SetPauseFlag(t.actor, 1);
|
||||
} else {
|
||||
fprintf(stderr, "[slow] %s: kill timer fired (turn exceeded %llus)\n",
|
||||
name, (unsigned long long)(ACTOR_SLOW_TIMER_NS / 1000000000));
|
||||
t.actor->disrupt = 1;
|
||||
JS_SetPauseFlag(t.actor, 2);
|
||||
}
|
||||
@@ -577,17 +583,11 @@ int actor_exists(const char *id)
|
||||
void set_actor_state(JSContext *actor)
|
||||
{
|
||||
if (actor->disrupt) {
|
||||
#ifdef SCHEDULER_DEBUG
|
||||
fprintf(stderr, "set_actor_state: %s disrupted, freeing\n", actor->name ? actor->name : actor->id);
|
||||
#endif
|
||||
actor_free(actor);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_lock(actor->msg_mutex);
|
||||
|
||||
#ifdef SCHEDULER_DEBUG
|
||||
fprintf(stderr, "set_actor_state: %s state=%d letters=%ld\n", actor->name ? actor->name : actor->id, actor->state, (long)arrlen(actor->letters));
|
||||
#endif
|
||||
switch(actor->state) {
|
||||
case ACTOR_RUNNING:
|
||||
case ACTOR_READY:
|
||||
@@ -601,9 +601,6 @@ void set_actor_state(JSContext *actor)
|
||||
actor->is_quiescent = 0;
|
||||
atomic_fetch_sub(&engine.quiescent_count, 1);
|
||||
}
|
||||
#ifdef SCHEDULER_DEBUG
|
||||
fprintf(stderr, "set_actor_state: %s IDLE->READY, enqueueing (main=%d)\n", actor->name ? actor->name : actor->id, actor->main_thread_only);
|
||||
#endif
|
||||
actor->state = ACTOR_READY;
|
||||
actor->ar = 0;
|
||||
enqueue_actor_priority(actor);
|
||||
@@ -846,6 +843,8 @@ void actor_turn(JSContext *actor)
|
||||
|
||||
if (JS_IsSuspended(result)) {
|
||||
/* Still suspended after kill timer — shouldn't happen, kill it */
|
||||
fprintf(stderr, "[slow] %s: still suspended after resume, killing\n",
|
||||
actor->name ? actor->name : actor->id);
|
||||
actor->disrupt = 1;
|
||||
goto ENDTURN;
|
||||
}
|
||||
@@ -854,16 +853,12 @@ void actor_turn(JSContext *actor)
|
||||
actor->disrupt = 1;
|
||||
}
|
||||
actor->slow_strikes++;
|
||||
#ifdef ACTOR_TRACE
|
||||
fprintf(stderr, "[ACTOR_TRACE] %s: slow strike %d/%d\n",
|
||||
actor->name ? actor->name : actor->id,
|
||||
actor->slow_strikes, ACTOR_SLOW_STRIKES_MAX);
|
||||
#endif
|
||||
JS_Log(actor, "slow", "%s: slow strike %d/%d",
|
||||
actor->name ? actor->name : actor->id,
|
||||
actor->slow_strikes, ACTOR_SLOW_STRIKES_MAX);
|
||||
if (actor->slow_strikes >= ACTOR_SLOW_STRIKES_MAX) {
|
||||
#ifdef ACTOR_TRACE
|
||||
fprintf(stderr, "[ACTOR_TRACE] %s: %d slow strikes, killing\n",
|
||||
actor->name ? actor->name : actor->id, actor->slow_strikes);
|
||||
#endif
|
||||
JS_Log(actor, "slow", "%s: killed after %d consecutive slow turns",
|
||||
actor->name ? actor->name : actor->id, actor->slow_strikes);
|
||||
actor->disrupt = 1;
|
||||
}
|
||||
goto ENDTURN;
|
||||
@@ -876,10 +871,6 @@ void actor_turn(JSContext *actor)
|
||||
pthread_mutex_unlock(actor->msg_mutex);
|
||||
goto ENDTURN;
|
||||
}
|
||||
#ifdef SCHEDULER_DEBUG
|
||||
fprintf(stderr, "actor_turn: %s has %d letters, type=%d\n",
|
||||
actor->name ? actor->name : actor->id, pending, actor->letters[0].type);
|
||||
#endif
|
||||
letter l = actor->letters[0];
|
||||
arrdel(actor->letters, 0);
|
||||
pthread_mutex_unlock(actor->msg_mutex);
|
||||
@@ -937,29 +928,22 @@ ENDTURN:
|
||||
actor->actor_trace_hook(actor, CELL_HOOK_EXIT);
|
||||
|
||||
if (actor->disrupt) {
|
||||
#ifdef SCHEDULER_DEBUG
|
||||
fprintf(stderr, "actor_turn ENDTURN: %s disrupted, freeing\n",
|
||||
actor->name ? actor->name : actor->id);
|
||||
#endif
|
||||
pthread_mutex_unlock(actor->mutex);
|
||||
actor_free(actor);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SCHEDULER_DEBUG
|
||||
fprintf(stderr, "actor_turn ENDTURN: %s has %ld letters, calling set_actor_state\n",
|
||||
actor->name ? actor->name : actor->id, (long)arrlen(actor->letters));
|
||||
#endif
|
||||
set_actor_state(actor);
|
||||
pthread_mutex_unlock(actor->mutex);
|
||||
return;
|
||||
|
||||
ENDTURN_SLOW:
|
||||
g_crash_ctx = NULL;
|
||||
#ifdef ACTOR_TRACE
|
||||
fprintf(stderr, "[ACTOR_TRACE] %s: suspended mid-turn -> SLOW\n",
|
||||
actor->name ? actor->name : actor->id);
|
||||
#endif
|
||||
/* VM suspended mid-turn — can't call JS_Log, use fprintf.
|
||||
Print stack trace while frames are still intact. */
|
||||
fprintf(stderr, "[slow] %s: suspended mid-turn, entering slow queue (strike %d/%d)\n",
|
||||
actor->name ? actor->name : actor->id,
|
||||
actor->slow_strikes + 1, ACTOR_SLOW_STRIKES_MAX);
|
||||
if (actor->actor_trace_hook)
|
||||
actor->actor_trace_hook(actor, CELL_HOOK_EXIT);
|
||||
enqueue_actor_priority(actor);
|
||||
|
||||
@@ -243,7 +243,7 @@ var type_annotation = function(slot_types, instr) {
|
||||
if (is_number(v)) {
|
||||
t = slot_types[text(v)]
|
||||
if (t != null && t != T_UNKNOWN) {
|
||||
push(parts, `s${text(v)}:${t}`)
|
||||
parts[] = `s${text(v)}:${t}`
|
||||
}
|
||||
}
|
||||
j = j + 1
|
||||
@@ -290,7 +290,7 @@ var dump_function_typed = function(func, name) {
|
||||
operand_parts = []
|
||||
j = 1
|
||||
while (j < n - 2) {
|
||||
push(operand_parts, fmt_val(instr[j]))
|
||||
operand_parts[] = fmt_val(instr[j])
|
||||
j = j + 1
|
||||
}
|
||||
operands = text(operand_parts, ", ")
|
||||
|
||||
40
test.ce
40
test.ce
@@ -62,7 +62,7 @@ function parse_args() {
|
||||
} else if (_args[i] == '--diff') {
|
||||
diff_mode = true
|
||||
} else {
|
||||
push(cleaned_args, _args[i])
|
||||
cleaned_args[] = _args[i]
|
||||
}
|
||||
}
|
||||
_args = cleaned_args
|
||||
@@ -247,11 +247,11 @@ function collect_actor_tests(package_name, specific_test) {
|
||||
if (test_base != match_base) continue
|
||||
}
|
||||
|
||||
push(actor_tests, {
|
||||
actor_tests[] = {
|
||||
package: package_name || "local",
|
||||
file: f,
|
||||
path: prefix + '/' + f
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return actor_tests
|
||||
@@ -296,16 +296,16 @@ function spawn_actor_test(test_info) {
|
||||
entry.error = { message: event.reason || "Actor disrupted" }
|
||||
log.console(` FAIL ${test_name}: ${entry.error.message}`)
|
||||
}
|
||||
push(actor_test_results, entry)
|
||||
actor_test_results[] = entry
|
||||
if (gc_after_each_test) dbg.gc()
|
||||
check_completion()
|
||||
}, actor_path)
|
||||
push(pending_actor_tests, entry)
|
||||
pending_actor_tests[] = entry
|
||||
} disruption {
|
||||
entry.status = "failed"
|
||||
entry.error = { message: "Failed to spawn actor" }
|
||||
entry.duration_ns = 0
|
||||
push(actor_test_results, entry)
|
||||
actor_test_results[] = entry
|
||||
log.console(` FAIL ${test_name}: Failed to spawn`)
|
||||
}
|
||||
_spawn()
|
||||
@@ -347,7 +347,7 @@ function run_tests(package_name, specific_test) {
|
||||
match_base = ends_with(match_name, '.cm') ? text(match_name, 0, -3) : match_name
|
||||
if (test_name != match_base) continue
|
||||
}
|
||||
push(test_files, f)
|
||||
test_files[] = f
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,14 +408,14 @@ function run_tests(package_name, specific_test) {
|
||||
var first_null_key = null
|
||||
var first_other_key = null
|
||||
if (is_function(test_mod)) {
|
||||
push(tests, {name: 'main', fn: test_mod})
|
||||
tests[] = {name: 'main', fn: test_mod}
|
||||
} else if (is_object(test_mod)) {
|
||||
all_keys = array(test_mod)
|
||||
log.console(` Found ${length(all_keys)} test entries`)
|
||||
arrfor(all_keys, function(k) {
|
||||
if (is_function(test_mod[k])) {
|
||||
fn_count = fn_count + 1
|
||||
push(tests, {name: k, fn: test_mod[k]})
|
||||
tests[] = {name: k, fn: test_mod[k]}
|
||||
} else if (is_null(test_mod[k])) {
|
||||
null_count = null_count + 1
|
||||
if (!first_null_key) first_null_key = k
|
||||
@@ -494,7 +494,7 @@ function run_tests(package_name, specific_test) {
|
||||
file_result.failed = file_result.failed + 1
|
||||
}
|
||||
|
||||
push(file_result.tests, test_entry)
|
||||
file_result.tests[] = test_entry
|
||||
pkg_result.total = pkg_result.total + 1
|
||||
if (gc_after_each_test) {
|
||||
dbg.gc()
|
||||
@@ -512,7 +512,7 @@ function run_tests(package_name, specific_test) {
|
||||
file_result.failed = file_result.failed + 1
|
||||
pkg_result.total = pkg_result.total + 1
|
||||
}
|
||||
push(pkg_result.files, file_result)
|
||||
pkg_result.files[] = file_result
|
||||
}
|
||||
return pkg_result
|
||||
}
|
||||
@@ -525,18 +525,18 @@ var i = 0
|
||||
if (all_pkgs) {
|
||||
// Run local first if we're in a valid package
|
||||
if (is_valid_package('.')) {
|
||||
push(all_results, run_tests(null, null))
|
||||
all_results[] = run_tests(null, null)
|
||||
all_actor_tests = array(all_actor_tests, collect_actor_tests(null, null))
|
||||
}
|
||||
|
||||
// Then all packages in lock
|
||||
packages = shop.list_packages()
|
||||
for (i = 0; i < length(packages); i++) {
|
||||
push(all_results, run_tests(packages[i], null))
|
||||
all_results[] = run_tests(packages[i], null)
|
||||
all_actor_tests = array(all_actor_tests, collect_actor_tests(packages[i], null))
|
||||
}
|
||||
} else {
|
||||
push(all_results, run_tests(target_pkg, target_test))
|
||||
all_results[] = run_tests(target_pkg, target_test)
|
||||
all_actor_tests = array(all_actor_tests, collect_actor_tests(target_pkg, target_test))
|
||||
}
|
||||
|
||||
@@ -561,7 +561,7 @@ function check_timeouts() {
|
||||
entry = pending_actor_tests[i]
|
||||
elapsed_ms = (now - entry.start_time) * 1000
|
||||
if (elapsed_ms > ACTOR_TEST_TIMEOUT) {
|
||||
push(timed_out, i)
|
||||
timed_out[] = i
|
||||
}
|
||||
}
|
||||
|
||||
@@ -573,7 +573,7 @@ function check_timeouts() {
|
||||
entry.status = "failed"
|
||||
entry.error = { message: "Test timed out" }
|
||||
entry.duration_ns = ACTOR_TEST_TIMEOUT * 1000000
|
||||
push(actor_test_results, entry)
|
||||
actor_test_results[] = entry
|
||||
log.console(` TIMEOUT ${entry.test}`)
|
||||
}
|
||||
|
||||
@@ -612,7 +612,7 @@ function finalize_results() {
|
||||
}
|
||||
if (!pkg_result) {
|
||||
pkg_result = { package: r.package, files: [], total: 0, passed: 0, failed: 0 }
|
||||
push(all_results, pkg_result)
|
||||
all_results[] = pkg_result
|
||||
}
|
||||
|
||||
file_result = null
|
||||
@@ -624,10 +624,10 @@ function finalize_results() {
|
||||
}
|
||||
if (!file_result) {
|
||||
file_result = { name: r.file, tests: [], passed: 0, failed: 0 }
|
||||
push(pkg_result.files, file_result)
|
||||
pkg_result.files[] = file_result
|
||||
}
|
||||
|
||||
push(file_result.tests, r)
|
||||
file_result.tests[] = r
|
||||
pkg_result.total = pkg_result.total + 1
|
||||
if (r.status == "passed") {
|
||||
pkg_result.passed = pkg_result.passed + 1
|
||||
@@ -760,7 +760,7 @@ Total: ${totals.total}, Passed: ${totals.passed}, Failed: ${totals.failed}
|
||||
for (j = 0; j < length(pkg_res.files); j++) {
|
||||
f = pkg_res.files[j]
|
||||
for (k = 0; k < length(f.tests); k++) {
|
||||
push(pkg_tests, f.tests[k])
|
||||
pkg_tests[] = f.tests[k]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ var testarr = []
|
||||
var i = 0
|
||||
var t = null
|
||||
for (i = 0; i < 500; i++) {
|
||||
push(testarr, 1)
|
||||
testarr[] = 1
|
||||
}
|
||||
|
||||
var testCases = [
|
||||
|
||||
@@ -2918,7 +2918,7 @@ return {
|
||||
test_arrfor_with_index: function() {
|
||||
var arr = ["a", "b", "c"]
|
||||
var indices = []
|
||||
arrfor(arr, (x, i) => { push(indices, i) })
|
||||
arrfor(arr, (x, i) => { indices[] = i })
|
||||
if (indices[0] != 0 || indices[2] != 2) return "arrfor with index failed"
|
||||
},
|
||||
|
||||
@@ -2931,7 +2931,7 @@ return {
|
||||
test_arrfor_mutation: function() {
|
||||
var arr = [1, 2, 3]
|
||||
var results = []
|
||||
arrfor(arr, x => { push(results, x * 2) })
|
||||
arrfor(arr, x => { results[] = x * 2 })
|
||||
if (results[0] != 2 || results[1] != 4 || results[2] != 6) return "arrfor mutation failed"
|
||||
},
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ var testarr = []
|
||||
var i = 0
|
||||
var t = null
|
||||
var name = null
|
||||
for (i = 0; i < 500; i++) { push(testarr, 1) }
|
||||
for (i = 0; i < 500; i++) { testarr[] = 1 }
|
||||
|
||||
var testCases = [
|
||||
{ name: 'zero', input: 0 },
|
||||
|
||||
60
tokenize.cm
60
tokenize.cm
@@ -103,26 +103,26 @@ var tokenize = function(src, filename) {
|
||||
run_start = pos
|
||||
while (pos < len && pk() != quote) {
|
||||
if (pk() == "\\") {
|
||||
if (pos > run_start) push(parts, text(src, run_start, pos))
|
||||
if (pos > run_start) parts[] = text(src, run_start, pos)
|
||||
adv()
|
||||
esc = adv()
|
||||
esc_val = escape_map[esc]
|
||||
if (esc_val != null) { push(parts, esc_val) }
|
||||
else if (esc == "u") { push(parts, read_unicode_escape()) }
|
||||
else { push(parts, esc) }
|
||||
if (esc_val != null) { parts[] = esc_val }
|
||||
else if (esc == "u") { parts[] = read_unicode_escape() }
|
||||
else { parts[] = esc }
|
||||
run_start = pos
|
||||
} else {
|
||||
adv()
|
||||
}
|
||||
}
|
||||
if (pos > run_start) push(parts, text(src, run_start, pos))
|
||||
if (pos > run_start) parts[] = text(src, run_start, pos)
|
||||
if (pos < len) adv() // skip closing quote
|
||||
push(tokens, {
|
||||
tokens[] = {
|
||||
kind: "text", at: start,
|
||||
from_row: start_row, from_column: start_col,
|
||||
to_row: row, to_column: col,
|
||||
value: text(parts)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var read_template = function() {
|
||||
@@ -139,12 +139,12 @@ var tokenize = function(src, filename) {
|
||||
run_start = pos
|
||||
while (pos < len && pk() != "`") {
|
||||
if (pk() == "\\" && pos + 1 < len) {
|
||||
if (pos > run_start) push(parts, text(src, run_start, pos))
|
||||
push(parts, text(src, pos, pos + 2))
|
||||
if (pos > run_start) parts[] = text(src, run_start, pos)
|
||||
parts[] = text(src, pos, pos + 2)
|
||||
adv(); adv()
|
||||
run_start = pos
|
||||
} else if (pk() == "$" && pos + 1 < len && pk_at(1) == "{") {
|
||||
if (pos > run_start) push(parts, text(src, run_start, pos))
|
||||
if (pos > run_start) parts[] = text(src, run_start, pos)
|
||||
interp_start = pos
|
||||
adv(); adv() // $ {
|
||||
depth = 1
|
||||
@@ -164,20 +164,20 @@ var tokenize = function(src, filename) {
|
||||
if (pos < len) adv()
|
||||
} else { adv() }
|
||||
}
|
||||
push(parts, text(src, interp_start, pos))
|
||||
parts[] = text(src, interp_start, pos)
|
||||
run_start = pos
|
||||
} else {
|
||||
adv()
|
||||
}
|
||||
}
|
||||
if (pos > run_start) push(parts, text(src, run_start, pos))
|
||||
if (pos > run_start) parts[] = text(src, run_start, pos)
|
||||
if (pos < len) adv() // skip closing backtick
|
||||
push(tokens, {
|
||||
tokens[] = {
|
||||
kind: "text", at: start,
|
||||
from_row: start_row, from_column: start_col,
|
||||
to_row: row, to_column: col,
|
||||
value: text(parts)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var read_number = function() {
|
||||
@@ -207,12 +207,12 @@ var tokenize = function(src, filename) {
|
||||
}
|
||||
}
|
||||
raw = substr(start, pos)
|
||||
push(tokens, {
|
||||
tokens[] = {
|
||||
kind: "number", at: start,
|
||||
from_row: start_row, from_column: start_col,
|
||||
to_row: row, to_column: col,
|
||||
value: raw, number: number(raw)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var read_name = function() {
|
||||
@@ -225,18 +225,18 @@ var tokenize = function(src, filename) {
|
||||
name = substr(start, pos)
|
||||
kw = keywords[name]
|
||||
if (kw != null) {
|
||||
push(tokens, {
|
||||
tokens[] = {
|
||||
kind: kw, at: start,
|
||||
from_row: start_row, from_column: start_col,
|
||||
to_row: row, to_column: col
|
||||
})
|
||||
}
|
||||
} else {
|
||||
push(tokens, {
|
||||
tokens[] = {
|
||||
kind: "name", at: start,
|
||||
from_row: start_row, from_column: start_col,
|
||||
to_row: row, to_column: col,
|
||||
value: name
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,12 +258,12 @@ var tokenize = function(src, filename) {
|
||||
}
|
||||
}
|
||||
raw = substr(start, pos)
|
||||
push(tokens, {
|
||||
tokens[] = {
|
||||
kind: "comment", at: start,
|
||||
from_row: start_row, from_column: start_col,
|
||||
to_row: row, to_column: col,
|
||||
value: raw
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var emit_op = function(kind, count) {
|
||||
@@ -272,11 +272,11 @@ var tokenize = function(src, filename) {
|
||||
var start_col = col
|
||||
var i = 0
|
||||
while (i < count) { adv(); i = i + 1 }
|
||||
push(tokens, {
|
||||
tokens[] = {
|
||||
kind: kind, at: start,
|
||||
from_row: start_row, from_column: start_col,
|
||||
to_row: row, to_column: col
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var emit_ident = function(count) {
|
||||
@@ -285,12 +285,12 @@ var tokenize = function(src, filename) {
|
||||
var start_col = col
|
||||
var i = 0
|
||||
while (i < count) { adv(); i = i + 1 }
|
||||
push(tokens, {
|
||||
tokens[] = {
|
||||
kind: "name", at: start,
|
||||
from_row: start_row, from_column: start_col,
|
||||
to_row: row, to_column: col,
|
||||
value: text(src, start, pos)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var tokenize_one = function() {
|
||||
@@ -304,21 +304,21 @@ var tokenize = function(src, filename) {
|
||||
if (c == "\n") {
|
||||
start = pos; start_row = row; start_col = col
|
||||
adv()
|
||||
push(tokens, { kind: "newline", at: start, from_row: start_row, from_column: start_col, to_row: row, to_column: col, value: "\n" })
|
||||
tokens[] = { kind: "newline", at: start, from_row: start_row, from_column: start_col, to_row: row, to_column: col, value: "\n" }
|
||||
return true
|
||||
}
|
||||
if (c == "\r") {
|
||||
start = pos; start_row = row; start_col = col
|
||||
adv()
|
||||
if (pos < len && pk() == "\n") adv()
|
||||
push(tokens, { kind: "newline", at: start, from_row: start_row, from_column: start_col, to_row: row, to_column: col, value: "\n" })
|
||||
tokens[] = { kind: "newline", at: start, from_row: start_row, from_column: start_col, to_row: row, to_column: col, value: "\n" }
|
||||
return true
|
||||
}
|
||||
if (c == " " || c == "\t") {
|
||||
start = pos; start_row = row; start_col = col
|
||||
while (pos < len && (pk() == " " || pk() == "\t")) adv()
|
||||
raw = substr(start, pos)
|
||||
push(tokens, { kind: "space", at: start, from_row: start_row, from_column: start_col, to_row: row, to_column: col, value: raw })
|
||||
tokens[] = { kind: "space", at: start, from_row: start_row, from_column: start_col, to_row: row, to_column: col, value: raw }
|
||||
return true
|
||||
}
|
||||
if (c == "'" || c == "\"") { read_string(c); return true }
|
||||
@@ -446,7 +446,7 @@ var tokenize = function(src, filename) {
|
||||
}
|
||||
|
||||
// EOF token
|
||||
push(tokens, { kind: "eof", at: pos, from_row: row, from_column: col, to_row: row, to_column: col })
|
||||
tokens[] = { kind: "eof", at: pos, from_row: row, from_column: col, to_row: row, to_column: col }
|
||||
|
||||
return {filename: filename, tokens: tokens}
|
||||
}
|
||||
|
||||
16
toml.cm
16
toml.cm
@@ -127,7 +127,7 @@ function parse_key_path(str) {
|
||||
} else if (c == '.' && !in_quote) {
|
||||
piece = trim(current)
|
||||
if (piece == null) piece = trim(current)
|
||||
push(parts, parse_key(piece))
|
||||
parts[] = parse_key(piece)
|
||||
current = ''
|
||||
continue
|
||||
}
|
||||
@@ -136,7 +136,7 @@ function parse_key_path(str) {
|
||||
|
||||
var tail = trim(current)
|
||||
if (tail == null) tail = trim(current)
|
||||
if (length(tail) > 0) push(parts, parse_key(tail))
|
||||
if (length(tail) > 0) parts[] = parse_key(tail)
|
||||
|
||||
return parts
|
||||
}
|
||||
@@ -165,7 +165,7 @@ function parse_array(str) {
|
||||
} else if (ch == ',' && !in_quotes) {
|
||||
piece = trim(current)
|
||||
if (piece == null) piece = trim(current)
|
||||
push(items, parse_value(piece))
|
||||
items[] = parse_value(piece)
|
||||
current = ''
|
||||
} else {
|
||||
current = current + ch
|
||||
@@ -174,7 +174,7 @@ function parse_array(str) {
|
||||
|
||||
var last = trim(current)
|
||||
if (last == null) last = trim(current)
|
||||
if (last) push(items, parse_value(last))
|
||||
if (last) items[] = parse_value(last)
|
||||
|
||||
return items
|
||||
}
|
||||
@@ -204,7 +204,7 @@ function encode_toml(obj) {
|
||||
if (is_number(value)) return text(value)
|
||||
if (is_array(value)) {
|
||||
items = []
|
||||
for (i = 0; i < length(value); i++) push(items, encode_value(value[i]))
|
||||
for (i = 0; i < length(value); i++) items[] = encode_value(value[i])
|
||||
return '[' + text(items, ', ') + ']'
|
||||
}
|
||||
return text(value)
|
||||
@@ -230,7 +230,7 @@ function encode_toml(obj) {
|
||||
for (i = 0; i < length(keys); i++) {
|
||||
key = keys[i]
|
||||
value = obj[key]
|
||||
if (!is_object(value)) push(result, quote_key(key) + ' = ' + encode_value(value))
|
||||
if (!is_object(value)) result[] = quote_key(key) + ' = ' + encode_value(value)
|
||||
}
|
||||
|
||||
// Second pass: encode nested objects
|
||||
@@ -252,14 +252,14 @@ function encode_toml(obj) {
|
||||
if (is_object(value)) {
|
||||
quoted = quote_key(key)
|
||||
section_path = path ? path + '.' + quoted : quoted
|
||||
push(result, '[' + section_path + ']')
|
||||
result[] = '[' + section_path + ']'
|
||||
|
||||
// Direct properties
|
||||
section_keys = array(value)
|
||||
for (j = 0; j < length(section_keys); j++) {
|
||||
sk = section_keys[j]
|
||||
sv = value[sk]
|
||||
if (!is_object(sv)) push(result, quote_key(sk) + ' = ' + encode_value(sv))
|
||||
if (!is_object(sv)) result[] = quote_key(sk) + ' = ' + encode_value(sv)
|
||||
}
|
||||
|
||||
// Nested sections
|
||||
|
||||
85
update.ce
85
update.ce
@@ -20,7 +20,6 @@ var target_triple = null
|
||||
var follow_links = false
|
||||
var git_pull = false
|
||||
var i = 0
|
||||
var updated = 0
|
||||
var packages = null
|
||||
|
||||
var run = function() {
|
||||
@@ -54,7 +53,14 @@ var run = function() {
|
||||
if (target_pkg)
|
||||
target_pkg = shop.resolve_locator(target_pkg)
|
||||
|
||||
function update_one(pkg) {
|
||||
if (target_pkg) {
|
||||
update_single(target_pkg)
|
||||
} else {
|
||||
update_all()
|
||||
}
|
||||
}
|
||||
|
||||
function check_one(pkg) {
|
||||
var effective_pkg = pkg
|
||||
var link_target = null
|
||||
var lock = shop.load_lock()
|
||||
@@ -62,59 +68,84 @@ function update_one(pkg) {
|
||||
var old_commit = old_entry ? old_entry.commit : null
|
||||
var info = shop.resolve_package_info(pkg)
|
||||
var new_entry = null
|
||||
var old_str = null
|
||||
|
||||
if (follow_links) {
|
||||
link_target = link.get_target(pkg)
|
||||
if (link_target) {
|
||||
effective_pkg = link_target
|
||||
log.console(" Following link: " + pkg + " -> " + effective_pkg)
|
||||
}
|
||||
}
|
||||
|
||||
// For local packages with --git, pull first
|
||||
if (git_pull && info == 'local' && fd.is_dir(effective_pkg + '/.git')) {
|
||||
log.console(" " + effective_pkg + " (git pull)")
|
||||
log.build(" " + effective_pkg + " (git pull)")
|
||||
os.system('git -C "' + effective_pkg + '" pull')
|
||||
}
|
||||
|
||||
// Check for update (sets lock entry if changed)
|
||||
new_entry = shop.update(effective_pkg)
|
||||
|
||||
if (new_entry && new_entry.commit) {
|
||||
old_str = old_commit ? text(old_commit, 0, 8) : "(new)"
|
||||
log.console(" " + effective_pkg + " " + old_str + " -> " + text(new_entry.commit, 0, 8))
|
||||
return {
|
||||
pkg: pkg,
|
||||
effective: effective_pkg,
|
||||
old_commit: old_commit,
|
||||
new_entry: new_entry,
|
||||
changed: new_entry != null && new_entry.commit != null
|
||||
}
|
||||
|
||||
// Sync: fetch, extract, build
|
||||
shop.sync(effective_pkg, {target: target_triple})
|
||||
|
||||
return new_entry
|
||||
}
|
||||
|
||||
if (target_pkg) {
|
||||
if (update_one(target_pkg)) {
|
||||
log.console("Updated " + target_pkg + ".")
|
||||
function sync_one(effective_pkg) {
|
||||
shop.sync(effective_pkg, {target: target_triple})
|
||||
}
|
||||
|
||||
function update_single(pkg) {
|
||||
var result = check_one(pkg)
|
||||
var old_str = null
|
||||
if (result.changed) {
|
||||
old_str = result.old_commit ? text(result.old_commit, 0, 8) : "(new)"
|
||||
log.console("==> Upgrading " + result.effective)
|
||||
log.console(" " + old_str + " -> " + text(result.new_entry.commit, 0, 8))
|
||||
log.console("==> Syncing " + result.effective)
|
||||
sync_one(result.effective)
|
||||
log.console("Updated " + result.effective + ".")
|
||||
} else {
|
||||
log.console(target_pkg + " is up to date.")
|
||||
log.console(pkg + " is up to date.")
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
function update_all() {
|
||||
var results = []
|
||||
var changed = []
|
||||
var result = null
|
||||
|
||||
packages = shop.list_packages()
|
||||
log.console("Checking for updates (" + text(length(packages)) + " packages)...")
|
||||
log.console("Checking for updates...")
|
||||
|
||||
arrfor(packages, function(pkg) {
|
||||
if (pkg == 'core') return
|
||||
if (update_one(pkg))
|
||||
updated = updated + 1
|
||||
result = check_one(pkg)
|
||||
results[] = result
|
||||
if (result.changed)
|
||||
changed[] = result
|
||||
})
|
||||
|
||||
if (updated > 0) {
|
||||
log.console("Updated " + text(updated) + " package(s).")
|
||||
} else {
|
||||
if (length(changed) == 0) {
|
||||
log.console("All packages are up to date.")
|
||||
return
|
||||
}
|
||||
|
||||
log.console("==> Upgrading " + text(length(changed)) + " outdated package" + (length(changed) != 1 ? "s" : "") + ":")
|
||||
arrfor(changed, function(r) {
|
||||
var old_str = r.old_commit ? text(r.old_commit, 0, 8) : "(new)"
|
||||
log.console(" " + r.effective + " " + old_str + " -> " + text(r.new_entry.commit, 0, 8))
|
||||
})
|
||||
|
||||
arrfor(changed, function(r) {
|
||||
log.console("==> Syncing " + r.effective)
|
||||
sync_one(r.effective)
|
||||
})
|
||||
|
||||
log.console("Updated " + text(length(changed)) + " package(s).")
|
||||
}
|
||||
}
|
||||
|
||||
run()
|
||||
|
||||
$stop()
|
||||
|
||||
10
verify.ce
10
verify.ce
@@ -67,11 +67,11 @@ var warnings = []
|
||||
var checked = 0
|
||||
|
||||
function add_error(msg) {
|
||||
push(errors, msg)
|
||||
errors[] = msg
|
||||
}
|
||||
|
||||
function add_warning(msg) {
|
||||
push(warnings, msg)
|
||||
warnings[] = msg
|
||||
}
|
||||
|
||||
// Verify a single package
|
||||
@@ -211,12 +211,12 @@ if (scope == 'shop') {
|
||||
if (deep) {
|
||||
// Gather all dependencies
|
||||
all_deps = pkg.gather_dependencies(locator)
|
||||
push(packages_to_verify, locator)
|
||||
packages_to_verify[] = locator
|
||||
arrfor(all_deps, function(dep) {
|
||||
push(packages_to_verify, dep)
|
||||
packages_to_verify[] = dep
|
||||
})
|
||||
} else {
|
||||
push(packages_to_verify, locator)
|
||||
packages_to_verify[] = locator
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
28
verify_ir.cm
28
verify_ir.cm
@@ -172,7 +172,7 @@ var check_slot_bounds = function(func) {
|
||||
if (pos < length(instr) - 2) {
|
||||
val = instr[pos]
|
||||
if (is_number(val) && (val < 0 || val >= nr_slots)) {
|
||||
push(errors, `slot_bounds: instr ${text(i)} op=${op} slot[${text(positions[j])}]=${text(val)} out of range 0..${text(nr_slots - 1)}`)
|
||||
errors[] = `slot_bounds: instr ${text(i)} op=${op} slot[${text(positions[j])}]=${text(val)} out of range 0..${text(nr_slots - 1)}`
|
||||
}
|
||||
}
|
||||
j = j + 1
|
||||
@@ -217,7 +217,7 @@ var check_jump_targets = function(func) {
|
||||
if (label_pos != null) {
|
||||
target = instr[label_pos + 1]
|
||||
if (is_text(target) && labels[target] != true) {
|
||||
push(errors, `jump_targets: instr ${text(i)} op=${op} target label "${target}" not found`)
|
||||
errors[] = `jump_targets: instr ${text(i)} op=${op} target label "${target}" not found`
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -301,46 +301,46 @@ var check_type_consistency = function(func) {
|
||||
s2 = text(instr[2])
|
||||
t2 = slot_types[s2]
|
||||
if (t2 != null && t2 != T_INT && t2 != "unknown") {
|
||||
push(errors, `type_consistency: instr ${text(i)} op=${op} src1 slot ${s2} has type ${t2}, expected int`)
|
||||
errors[] = `type_consistency: instr ${text(i)} op=${op} src1 slot ${s2} has type ${t2}, expected int`
|
||||
}
|
||||
if (length(instr) >= 6) {
|
||||
s3 = text(instr[3])
|
||||
t3 = slot_types[s3]
|
||||
if (t3 != null && t3 != T_INT && t3 != "unknown") {
|
||||
push(errors, `type_consistency: instr ${text(i)} op=${op} src2 slot ${s3} has type ${t3}, expected int`)
|
||||
errors[] = `type_consistency: instr ${text(i)} op=${op} src2 slot ${s3} has type ${t3}, expected int`
|
||||
}
|
||||
}
|
||||
} else if (float_ops[op] == true && length(instr) >= 5) {
|
||||
s2 = text(instr[2])
|
||||
t2 = slot_types[s2]
|
||||
if (t2 != null && t2 != T_FLOAT && t2 != "unknown") {
|
||||
push(errors, `type_consistency: instr ${text(i)} op=${op} src1 slot ${s2} has type ${t2}, expected float`)
|
||||
errors[] = `type_consistency: instr ${text(i)} op=${op} src1 slot ${s2} has type ${t2}, expected float`
|
||||
}
|
||||
if (length(instr) >= 6) {
|
||||
s3 = text(instr[3])
|
||||
t3 = slot_types[s3]
|
||||
if (t3 != null && t3 != T_FLOAT && t3 != "unknown") {
|
||||
push(errors, `type_consistency: instr ${text(i)} op=${op} src2 slot ${s3} has type ${t3}, expected float`)
|
||||
errors[] = `type_consistency: instr ${text(i)} op=${op} src2 slot ${s3} has type ${t3}, expected float`
|
||||
}
|
||||
}
|
||||
} else if (text_ops[op] == true && length(instr) >= 5) {
|
||||
s2 = text(instr[2])
|
||||
t2 = slot_types[s2]
|
||||
if (t2 != null && t2 != T_TEXT && t2 != "unknown") {
|
||||
push(errors, `type_consistency: instr ${text(i)} op=${op} src1 slot ${s2} has type ${t2}, expected text`)
|
||||
errors[] = `type_consistency: instr ${text(i)} op=${op} src1 slot ${s2} has type ${t2}, expected text`
|
||||
}
|
||||
if (length(instr) >= 6) {
|
||||
s3 = text(instr[3])
|
||||
t3 = slot_types[s3]
|
||||
if (t3 != null && t3 != T_TEXT && t3 != "unknown") {
|
||||
push(errors, `type_consistency: instr ${text(i)} op=${op} src2 slot ${s3} has type ${t3}, expected text`)
|
||||
errors[] = `type_consistency: instr ${text(i)} op=${op} src2 slot ${s3} has type ${t3}, expected text`
|
||||
}
|
||||
}
|
||||
} else if (bool_ops[op] == true && length(instr) >= 5) {
|
||||
s2 = text(instr[2])
|
||||
t2 = slot_types[s2]
|
||||
if (t2 != null && t2 != T_BOOL && t2 != "unknown") {
|
||||
push(errors, `type_consistency: instr ${text(i)} op=${op} src1 slot ${s2} has type ${t2}, expected bool`)
|
||||
errors[] = `type_consistency: instr ${text(i)} op=${op} src1 slot ${s2} has type ${t2}, expected bool`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,7 +394,7 @@ var check_nop_consistency = function(func) {
|
||||
if (label_pos != null) {
|
||||
target = instr[label_pos + 1]
|
||||
if (is_text(target) && nops[target] == true) {
|
||||
push(errors, `nop_consistency: instr ${text(i)} op=${op} jumps to nop marker "${target}"`)
|
||||
errors[] = `nop_consistency: instr ${text(i)} op=${op} jumps to nop marker "${target}"`
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -415,28 +415,28 @@ var verify_all = function(func, pass_name) {
|
||||
check_errors = check_slot_bounds(func)
|
||||
i = 0
|
||||
while (i < length(check_errors)) {
|
||||
push(all_errors, `${prefix}${fn_name}: ${check_errors[i]}`)
|
||||
all_errors[] = `${prefix}${fn_name}: ${check_errors[i]}`
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
check_errors = check_jump_targets(func)
|
||||
i = 0
|
||||
while (i < length(check_errors)) {
|
||||
push(all_errors, `${prefix}${fn_name}: ${check_errors[i]}`)
|
||||
all_errors[] = `${prefix}${fn_name}: ${check_errors[i]}`
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
check_errors = check_type_consistency(func)
|
||||
i = 0
|
||||
while (i < length(check_errors)) {
|
||||
push(all_errors, `${prefix}${fn_name}: ${check_errors[i]}`)
|
||||
all_errors[] = `${prefix}${fn_name}: ${check_errors[i]}`
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
check_errors = check_nop_consistency(func)
|
||||
i = 0
|
||||
while (i < length(check_errors)) {
|
||||
push(all_errors, `${prefix}${fn_name}: ${check_errors[i]}`)
|
||||
all_errors[] = `${prefix}${fn_name}: ${check_errors[i]}`
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
|
||||
4
xref.ce
4
xref.ce
@@ -93,11 +93,11 @@ var run = function() {
|
||||
if (!creates[text(parent_idx)]) {
|
||||
creates[text(parent_idx)] = []
|
||||
}
|
||||
push(creates[text(parent_idx)], {child: child_idx, line: instr_line})
|
||||
creates[text(parent_idx)][] = {child: child_idx, line: instr_line}
|
||||
if (!created_by[text(child_idx)]) {
|
||||
created_by[text(child_idx)] = []
|
||||
}
|
||||
push(created_by[text(child_idx)], {parent: parent_idx, line: instr_line})
|
||||
created_by[text(child_idx)][] = {parent: parent_idx, line: instr_line}
|
||||
}
|
||||
j = j + 1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user