aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO.md5
-rw-r--r--tests/conformance/2-types/array_init_bytes_string.zc1
-rw-r--r--tests/conformance/2-types/array_init_string.zc1
-rw-r--r--tests/conformance/4-statements/asm_float_literal.zc2
-rw-r--r--tests/conformance/4-statements/asm_function_name.zc1
-rw-r--r--tests/conformance/4-statements/decl_const_local_typed_float.zc1
-rw-r--r--tests/conformance/4-statements/decl_const_takes_initializer_type.zc1
-rw-r--r--tests/conformance/4-statements/decl_let_array.zc1
-rw-r--r--tests/conformance/4-statements/decl_typed_tag_u_hand_up.zc1
-rw-r--r--tests/conformance/4-statements/memdebug_report.zc4
-rw-r--r--tests/conformance/4-statements/memdebug_report_line.zc2
-rw-r--r--tests/conformance/4-statements/return_frees_owned_locals.zc1
-rw-r--r--tests/conformance/4-statements/switch_break_in_loop_leaves_switch_only.zc3
-rw-r--r--tests/conformance/4-statements/switch_break_leaves_early.zc1
-rw-r--r--tests/conformance/4-statements/switch_case_own_block.zc1
-rw-r--r--tests/conformance/4-statements/switch_case_three.zc1
-rw-r--r--tests/conformance/4-statements/switch_case_underscore.zc1
-rw-r--r--tests/conformance/4-statements/switch_continue_continues_loop.zc1
-rw-r--r--tests/conformance/4-statements/switch_default_first_position_not_matched.zc1
-rw-r--r--tests/conformance/4-statements/switch_default_first_position_taken.zc1
-rw-r--r--tests/conformance/4-statements/switch_default_middle.zc1
-rw-r--r--tests/conformance/4-statements/switch_default_runs.zc1
-rw-r--r--tests/conformance/4-statements/switch_duplicate_labels_first_wins.zc1
-rw-r--r--tests/conformance/4-statements/switch_expression_evaluated_once.zc3
-rw-r--r--tests/conformance/4-statements/switch_label_forms.zc4
-rw-r--r--tests/conformance/4-statements/switch_nested.zc1
-rw-r--r--tests/conformance/4-statements/switch_no_fallthrough_k2.zc1
-rw-r--r--tests/conformance/4-statements/switch_no_match_no_default.zc1
-rw-r--r--tests/conformance/4-statements/switch_return_inside_case.zc1
-rw-r--r--tests/conformance/4-statements/switch_tagged_all_covered_no_warning.zc1
-rw-r--r--tests/conformance/4-statements/switch_tagged_circle.zc1
-rw-r--r--tests/conformance/4-statements/switch_tagged_default_no_warning.zc1
-rw-r--r--tests/conformance/4-statements/switch_tagged_example.zc1
-rw-r--r--tests/conformance/4-statements/switch_tagged_match_by_tag.zc1
-rw-r--r--tests/conformance/4-statements/switch_tagged_uncovered_warning_not_error.zc1
-rw-r--r--tests/conformance/4-statements/unchecked_fn.zc1
-rw-r--r--tests/conformance/4-statements/unchecked_stmt_block.zc1
-rw-r--r--tests/conformance/4-statements/unchecked_toplevel_rest_of_unit.zc1
-rw-r--r--tests/conformance/5-declarations/const_chain.zc6
-rw-r--r--tests/conformance/5-declarations/const_typed.zc6
-rw-r--r--tests/conformance/5-declarations/docs_no_effect.zc10
-rw-r--r--tests/conformance/5-declarations/embed_missing_file.zc7
-rw-r--r--tests/conformance/5-declarations/enhance_wrong_inputs.zc7
-rw-r--r--tests/conformance/5-declarations/enum_member_names_earlier_b2.zc7
-rw-r--r--tests/conformance/5-declarations/fn_13th_param_tagged.zc7
-rw-r--r--tests/conformance/5-declarations/fn_bare_name_not_declaration.zc7
-rw-r--r--tests/conformance/5-declarations/fn_call_before_definition.zc6
-rw-r--r--tests/conformance/5-declarations/fn_falls_off_returns_zero.zc6
-rw-r--r--tests/conformance/5-declarations/fn_main_int_return_ignored.zc5
-rw-r--r--tests/conformance/5-declarations/fn_main_void.zc6
-rw-r--r--tests/conformance/5-declarations/fn_prototype_after_definition_b4.zc8
-rw-r--r--tests/conformance/5-declarations/fn_prototype_mismatch.zc8
-rw-r--r--tests/conformance/5-declarations/fn_prototype_named_params.zc7
-rw-r--r--tests/conformance/5-declarations/fn_prototype_unnamed_params_b13.zc8
-rw-r--r--tests/conformance/5-declarations/fn_redefined_b3.zc8
-rw-r--r--tests/conformance/5-declarations/fn_return_tag_only_u.zc7
-rw-r--r--tests/conformance/5-declarations/fn_struct_param_rejected.zc8
-rw-r--r--tests/conformance/5-declarations/fn_typed_mixed_params.zc6
-rw-r--r--tests/conformance/5-declarations/fn_u_falls_off.zc7
-rw-r--r--tests/conformance/5-declarations/global_call_init_rejected.zc8
-rw-r--r--tests/conformance/5-declarations/global_const_expr_init.zc7
-rw-r--r--tests/conformance/5-declarations/global_float_init_b7.zc7
-rw-r--r--tests/conformance/5-declarations/global_names_global_b8.zc7
-rw-r--r--tests/conformance/5-declarations/global_tagged_rejected.zc7
-rw-r--r--tests/conformance/5-declarations/global_word_string.zc7
-rw-r--r--tests/conformance/5-declarations/global_zero_initialised.zc7
-rw-r--r--tests/conformance/5-declarations/include_in_function_b9.zc6
-rw-r--r--tests/conformance/5-declarations/include_rt_required.zc4
-rw-r--r--tests/conformance/5-declarations/include_twice_compiled_once.zc8
-rw-r--r--tests/conformance/5-declarations/namespace_main_runs.zc7
-rw-r--r--tests/conformance/5-declarations/struct_constant_duplicate.zc7
-rw-r--r--tests/conformance/5-declarations/struct_constant_outside_and_inside.zc7
-rw-r--r--tests/conformance/5-declarations/struct_field_wins_over_method.zc8
-rw-r--r--tests/conformance/5-declarations/struct_method_calls_later.zc7
-rw-r--r--tests/conformance/5-declarations/struct_static_beats_toplevel.zc8
-rw-r--r--tests/conformance/5-declarations/struct_static_call.zc7
-rw-r--r--tests/conformance/5-declarations/struct_static_misspelled.zc7
-rw-r--r--tests/conformance/5-declarations/struct_this_declared.zc7
-rw-r--r--tests/conformance/5-declarations/type_alias.zc8
-rw-r--r--tests/conformance/6-ownership/alias_after_free.zc7
-rw-r--r--tests/conformance/6-ownership/alias_before_free_ok.zc7
-rw-r--r--tests/conformance/6-ownership/array_literal_escape_global.zc7
-rw-r--r--tests/conformance/6-ownership/block_value_m_rejected.zc6
-rw-r--r--tests/conformance/6-ownership/block_value_u.zc6
-rw-r--r--tests/conformance/6-ownership/borrow_to_global.zc8
-rw-r--r--tests/conformance/6-ownership/container_child_freed.zc8
-rw-r--r--tests/conformance/6-ownership/copy_owner_rejected.zc6
-rw-r--r--tests/conformance/6-ownership/d_never_given_away.zc6
-rw-r--r--tests/conformance/6-ownership/d_param_transfers.zc7
-rw-r--r--tests/conformance/6-ownership/free_then_reassign.zc6
-rw-r--r--tests/conformance/6-ownership/fresh_thrown_away.zc6
-rw-r--r--tests/conformance/6-ownership/global_store_needs_recast.zc7
-rw-r--r--tests/conformance/6-ownership/global_store_then_use.zc7
-rw-r--r--tests/conformance/6-ownership/if_join_free_one_branch.zc6
-rw-r--r--tests/conformance/6-ownership/if_join_mismatch.zc6
-rw-r--r--tests/conformance/6-ownership/lend_keeps_owner.zc7
-rw-r--r--tests/conformance/6-ownership/lend_to_global.zc8
-rw-r--r--tests/conformance/6-ownership/lend_to_global_open.zc7
-rw-r--r--tests/conformance/6-ownership/loop_give_away.zc6
-rw-r--r--tests/conformance/6-ownership/loop_give_away_break_ok.zc6
-rw-r--r--tests/conformance/6-ownership/m_freed_at_block_end_report.zc7
-rw-r--r--tests/conformance/6-ownership/never_used.zc6
-rw-r--r--tests/conformance/6-ownership/overwrite_leaks.zc6
-rw-r--r--tests/conformance/6-ownership/recast_back_to_m.zc7
-rw-r--r--tests/conformance/6-ownership/recast_nothing.zc6
-rw-r--r--tests/conformance/6-ownership/return_owned_infers.zc7
-rw-r--r--tests/conformance/6-ownership/temporary_to_reader.zc7
-rw-r--r--tests/conformance/6-ownership/u_must_leave.zc6
-rw-r--r--tests/conformance/6-ownership/unchecked_no_errors.zc6
-rw-r--r--tests/conformance/6-ownership/use_after_free.zc6
-rw-r--r--tests/conformance/7-compile-time/binop_pow.zc10
-rw-r--r--tests/conformance/7-compile-time/evals_prints.zc7
-rw-r--r--tests/conformance/7-compile-time/evals_returns.zc7
-rw-r--r--tests/conformance/7-compile-time/parse_word_five.zc8
-rw-r--r--tests/conformance/7-compile-time/parse_word_reads_nothing.zc8
-rw-r--r--tests/conformance/7-compile-time/quote_count.zc7
-rw-r--r--tests/conformance/7-compile-time/run_requires_include.zc6
-rw-r--r--tests/conformance/7-compile-time/statement_hook_ticks.zc10
-rw-r--r--tests/conformance/7-compile-time/syntax_hi.zc10
-rw-r--r--tests/conformance/8-runtime/div_by_zero_no_trap.zc6
-rw-r--r--tests/conformance/8-runtime/error_line_format.zc8
-rw-r--r--tests/conformance/8-runtime/errors_do_not_run.zc6
-rw-r--r--tests/conformance/8-runtime/get_c_reads_input.zc6
-rw-r--r--tests/conformance/8-runtime/halt_stops.zc5
-rw-r--r--tests/conformance/8-runtime/index_out_of_range.zc6
-rw-r--r--tests/conformance/8-runtime/len_w_eq_w.zc5
-rw-r--r--tests/conformance/8-runtime/new_zeroed.zc6
-rw-r--r--tests/conformance/8-runtime/no_main_runs_nothing.zc6
-rw-r--r--tests/conformance/8-runtime/put_c_low_bits.zc5
-rw-r--r--tests/conformance/8-runtime/put_n_min.zc5
-rw-r--r--tests/conformance/8-runtime/put_s_bstr.zc6
-rw-r--r--tests/conformance/8-runtime/put_s_word_string.zc5
-rw-r--r--tests/conformance/8-runtime/too_many_errors.zc32
-rw-r--r--tests/conformance/9-appendix-b/b1_11_zc0_octal.zc5
-rw-r--r--tests/conformance/9-appendix-b/b1_11_zc0_saturation.zc5
-rw-r--r--tests/conformance/9-appendix-b/b2_05_ternary_int_float.zc7
-rw-r--r--tests/conformance/9-appendix-b/b2_06_bool_normalises.zc6
-rw-r--r--tests/conformance/9-appendix-b/b2_10_recovery_hides_errors.zc6
-rw-r--r--tests/conformance/9-appendix-b/b2_11_unterminated_comment.zc7
-rw-r--r--tests/conformance/9-appendix-b/b2_12_as_int_star.zc6
-rw-r--r--tests/conformance/9-appendix-b/b2_14_len_char_ptr_typecheck_off.zc7
-rw-r--r--tests/conformance/9-appendix-b/b2_15_duplicate_case.zc6
-rw-r--r--tests/conformance/9-appendix-b/b2_16_local_const_in_const_expr.zc6
-rw-r--r--tests/conformance/known.txt71
-rwxr-xr-xtests/conformance/run.sh20
-rwxr-xr-xtests/test.sh4
146 files changed, 864 insertions, 18 deletions
diff --git a/TODO.md b/TODO.md
index 210b4a3..380b0f4 100644
--- a/TODO.md
+++ b/TODO.md
@@ -370,8 +370,7 @@ of the open list.
107, memdebug_report_line line 9, asm_float_literal uses `word w`); real:
`memdebug scrub;` rejected (b.1.1/b.2.1 confirmed), top-level `o3 { }`
rejected (c), `case rect():` with fields possibly rejected (unresolved).
- left: sections 5 to 8, the appendix b confirm/refute list, `known.txt`, the
- `--zc0` runs, final counts, then add the runner to tests/test.sh.
+ resumed on work/spec and finished; see the closed item in the list below.
- record and replay (no code; agent stopped during research). findings: every
syscall goes through `hostcall(op, a, b, c)` (core.c ~264) with three callers
(interpreter ~6324, jit `hook()` ~3617 which the x86-64 helpers also reach,
@@ -459,7 +458,7 @@ items with an architecture note carry the design worked out so far, enough to
brief someone without re-reading the code.
- [ ] remaining zc0 gaps: string literals over 4095 bytes, `embed` of an array type inside a function, `x as T` with more than a single name (`x as int*`), zc0 silently accepting `.u` on a parameter, and integer literals (`010` is 8 in zc0, 10 in the compiler; zc0 saturates on overflow). `docs/history/43-stdlib/notes.md` still says zc0 reserves u/m/d: add a pointer forward rather than rewriting history.
-- [ ] (partly done, see "agent work at the end of the session") verify both compilers against `docs/SPEC.md` with a fresh agent that did not write it: expectations derived from the spec text before running anything, one program per rule under `tests/conformance/<section>/`, a runner `tests/conformance/run.sh`, each failure classified as self-hosted bug, zc0 bug, or spec error, and appendix b confirmed item by item. then add the runner to `tests/test.sh`.
+- [x] verify both compilers against `docs/SPEC.md`: `tests/conformance/<section>/` (sections 1 to 8 plus `9-appendix-b`, 657 programs), runner `tests/conformance/run.sh` (`--zc0`, `--zym`, `--zy`, `-w`), understood failures in `tests/conformance/known.txt` (class a self-hosted bug, b zc0, c spec issue), wired into the interp section of `tests/test.sh`. zy 626 ok, 31 known; zc0 221 ok, 38 known, 398 skipped (outside appendix a). appendix b.2 items 1 to 16 confirmed except b.2.8, which contradicts 5.3.2 and 3.14.2 (the spec documents the address). new class a bugs: `case member():` on a member with fields is rejected (4.7.3); top-level `o3 { }` is rejected (4.10.2, class c). open: `rt.memreport()` reports buddy capacity (`rt.new(2)` is 3 words), whether that is the spec's W; whether top-level `unchecked;` is in the zc0 subset.
- [ ] fix the implementation bugs listed in `docs/SPEC.md` appendix b, once confirmed: `memdebug scrub;` rejected; enum members can't reference earlier members; a plain function redefinition silently shadows the first; a prototype after the definition hides it; `?:` with one int and one float branch gives garbage; `bool` not normalised; float global initializers rejected; a global initializer naming another global uses its address; `include std;` inside a function body; syntax-error recovery hiding later errors; unterminated `/*` and string literals; `x as int * y`; prototypes needing parameter names; `len(char*)` with typecheck off; duplicate `case` labels; local `const` in constant expressions; constant expressions without precedence (`1+2*3` is 9). fix the prose items the appendix lists too.
- [ ] (partly done, see "agent work at the end of the session") a cross-reference report: for every global of the compiler, the functions that write it and the ones that only read it. build it from the language server's references (`textDocument/references` on `build/bin/zclsp`, so scoping is exact) and classify each reference as a write when an assignment operator, `++` or `--` follows it. output under `build/xref/`; a committed baseline and a `--check` mode that fails when a new writer of a global appears, so it can run in ci.
- [ ] optional, low priority: plain enums and `?:` in zc0 (both are small and produce ordinary code), so parity covers more programs. no structs in zc0 (decided).
diff --git a/tests/conformance/2-types/array_init_bytes_string.zc b/tests/conformance/2-types/array_init_bytes_string.zc
index af607f0..531dfe0 100644
--- a/tests/conformance/2-types/array_init_bytes_string.zc
+++ b/tests/conformance/2-types/array_init_bytes_string.zc
@@ -6,3 +6,4 @@ fn main() {
pn(s[0]); pn(s[1]); pn(s[2]); pn(s[3]);
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/2-types/array_init_string.zc b/tests/conformance/2-types/array_init_string.zc
index 33037b9..f57cb67 100644
--- a/tests/conformance/2-types/array_init_string.zc
+++ b/tests/conformance/2-types/array_init_string.zc
@@ -6,3 +6,4 @@ fn main() {
pn(s[0]); pn(s[1]); pn(s[2]); pn(s[3]);
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/asm_float_literal.zc b/tests/conformance/4-statements/asm_float_literal.zc
index dfb1e23..c4090e8 100644
--- a/tests/conformance/4-statements/asm_float_literal.zc
+++ b/tests/conformance/4-statements/asm_float_literal.zc
@@ -3,5 +3,5 @@
include rt;
void pn(int x) { rt.put_n(x); rt.put_c(10); }
fn pf(x) { asm { x @ #1220 } rt.put_c(10); return 0; }
-fn main() { float f = asm { 1.5 }; pf(f); return 0; }
+fn main() { word w = asm { 1.5 }; pf(w); return 0; }
diff --git a/tests/conformance/4-statements/asm_function_name.zc b/tests/conformance/4-statements/asm_function_name.zc
index 56d8bad..209e7d4 100644
--- a/tests/conformance/4-statements/asm_function_name.zc
+++ b/tests/conformance/4-statements/asm_function_name.zc
@@ -4,3 +4,4 @@ include rt;
void pn(int x) { rt.put_n(x); rt.put_c(10); }
int three() { return 3; }
fn main() { fn() g = asm { three }; pn(g()); return 0; }
+// zc0: skip
diff --git a/tests/conformance/4-statements/decl_const_local_typed_float.zc b/tests/conformance/4-statements/decl_const_local_typed_float.zc
index d8470ae..c96cbbc 100644
--- a/tests/conformance/4-statements/decl_const_local_typed_float.zc
+++ b/tests/conformance/4-statements/decl_const_local_typed_float.zc
@@ -4,3 +4,4 @@ include rt;
void pn(int x) { rt.put_n(x); rt.put_c(10); }
fn pf(x) { asm { x @ #1220 } rt.put_c(10); return 0; }
fn main() { const float k = 3; pf(k); return 0; }
+// zc0: skip
diff --git a/tests/conformance/4-statements/decl_const_takes_initializer_type.zc b/tests/conformance/4-statements/decl_const_takes_initializer_type.zc
index cfe2aec..1715148 100644
--- a/tests/conformance/4-statements/decl_const_takes_initializer_type.zc
+++ b/tests/conformance/4-statements/decl_const_takes_initializer_type.zc
@@ -4,3 +4,4 @@ include rt;
void pn(int x) { rt.put_n(x); rt.put_c(10); }
fn pf(x) { asm { x @ #1220 } rt.put_c(10); return 0; }
fn main() { const k = 1.5; pf(k - 1); return 0; }
+// zc0: skip
diff --git a/tests/conformance/4-statements/decl_let_array.zc b/tests/conformance/4-statements/decl_let_array.zc
index 9d8d701..a0d5988 100644
--- a/tests/conformance/4-statements/decl_let_array.zc
+++ b/tests/conformance/4-statements/decl_let_array.zc
@@ -8,3 +8,4 @@ fn main() {
pn(sizeof(a)); pn(a[9]);
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/decl_typed_tag_u_hand_up.zc b/tests/conformance/4-statements/decl_typed_tag_u_hand_up.zc
index 7bbf280..8756d2a 100644
--- a/tests/conformance/4-statements/decl_typed_tag_u_hand_up.zc
+++ b/tests/conformance/4-statements/decl_typed_tag_u_hand_up.zc
@@ -12,3 +12,4 @@ fn main() {
pn(*q);
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/memdebug_report.zc b/tests/conformance/4-statements/memdebug_report.zc
index db81c6d..406662e 100644
--- a/tests/conformance/4-statements/memdebug_report.zc
+++ b/tests/conformance/4-statements/memdebug_report.zc
@@ -1,4 +1,4 @@
-// expect: 1/
+// expect: leak: line 8 3 words/107/
// spec 4.11: rt.memreport() returns the count of live recorded objects
include rt;
void pn(int x) { rt.put_n(x); rt.put_c(10); }
@@ -8,7 +8,7 @@ fn main() {
int* q = rt.new(3);
int* r = rt.new(2);
rt.free(r);
- pn(rt.memreport());
+ pn(rt.memreport() * 100 + 7);
}
return 0;
}
diff --git a/tests/conformance/4-statements/memdebug_report_line.zc b/tests/conformance/4-statements/memdebug_report_line.zc
index 8ab4273..52eecba 100644
--- a/tests/conformance/4-statements/memdebug_report_line.zc
+++ b/tests/conformance/4-statements/memdebug_report_line.zc
@@ -1,4 +1,4 @@
-// expect error: leak: line 8
+// expect: leak: line 9 3 words/
// spec 4.11: leak: line N W words per live recorded object (N is the allocation line)
include rt;
void pn(int x) { rt.put_n(x); rt.put_c(10); }
diff --git a/tests/conformance/4-statements/return_frees_owned_locals.zc b/tests/conformance/4-statements/return_frees_owned_locals.zc
index ccff11c..773eec2 100644
--- a/tests/conformance/4-statements/return_frees_owned_locals.zc
+++ b/tests/conformance/4-statements/return_frees_owned_locals.zc
@@ -9,3 +9,4 @@ int f(int n) {
return 0;
}
fn main() { pn(f(5)); return 0; }
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_break_in_loop_leaves_switch_only.zc b/tests/conformance/4-statements/switch_break_in_loop_leaves_switch_only.zc
index d69b64a..ab55e4d 100644
--- a/tests/conformance/4-statements/switch_break_in_loop_leaves_switch_only.zc
+++ b/tests/conformance/4-statements/switch_break_in_loop_leaves_switch_only.zc
@@ -1,4 +1,4 @@
-// expect: 3/
+// expect: 5/
// spec 4.7.1: break in a switch inside a loop leaves the switch, not the loop
include rt;
void pn(int x) { rt.put_n(x); rt.put_c(10); }
@@ -11,3 +11,4 @@ fn main() {
pn(n);
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_break_leaves_early.zc b/tests/conformance/4-statements/switch_break_leaves_early.zc
index 8adbe64..a9bf11b 100644
--- a/tests/conformance/4-statements/switch_break_leaves_early.zc
+++ b/tests/conformance/4-statements/switch_break_leaves_early.zc
@@ -8,3 +8,4 @@ fn main() {
pn(9);
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_case_own_block.zc b/tests/conformance/4-statements/switch_case_own_block.zc
index 16bc31f..63bdc5f 100644
--- a/tests/conformance/4-statements/switch_case_own_block.zc
+++ b/tests/conformance/4-statements/switch_case_own_block.zc
@@ -9,3 +9,4 @@ void t(int k) {
}
}
fn main() { t(1); t(2); return 0; }
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_case_three.zc b/tests/conformance/4-statements/switch_case_three.zc
index eefaced..f709abb 100644
--- a/tests/conformance/4-statements/switch_case_three.zc
+++ b/tests/conformance/4-statements/switch_case_three.zc
@@ -8,3 +8,4 @@ fn main() {
switch (k) { case 1, 2: ps("one-two"); case 3: ps("three"); break; default: ps("d"); }
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_case_underscore.zc b/tests/conformance/4-statements/switch_case_underscore.zc
index 4d05f8e..969ea7e 100644
--- a/tests/conformance/4-statements/switch_case_underscore.zc
+++ b/tests/conformance/4-statements/switch_case_underscore.zc
@@ -5,3 +5,4 @@ void pn(int x) { rt.put_n(x); rt.put_c(10); }
void ps(char* s) { rt.put_s(s); rt.put_c(10); }
void t(int k) { switch (k) { case 1: ps("one"); case _: ps("d"); } }
fn main() { t(8); t(1); return 0; }
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_continue_continues_loop.zc b/tests/conformance/4-statements/switch_continue_continues_loop.zc
index d408253..c100b0c 100644
--- a/tests/conformance/4-statements/switch_continue_continues_loop.zc
+++ b/tests/conformance/4-statements/switch_continue_continues_loop.zc
@@ -8,3 +8,4 @@ fn main() {
}
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_default_first_position_not_matched.zc b/tests/conformance/4-statements/switch_default_first_position_not_matched.zc
index 4d63ae3..b4f3283 100644
--- a/tests/conformance/4-statements/switch_default_first_position_not_matched.zc
+++ b/tests/conformance/4-statements/switch_default_first_position_not_matched.zc
@@ -8,3 +8,4 @@ fn main() {
switch (k) { default: ps("d"); case 1: ps("one"); case 2: ps("two"); }
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_default_first_position_taken.zc b/tests/conformance/4-statements/switch_default_first_position_taken.zc
index 113795f..a4ab811 100644
--- a/tests/conformance/4-statements/switch_default_first_position_taken.zc
+++ b/tests/conformance/4-statements/switch_default_first_position_taken.zc
@@ -8,3 +8,4 @@ fn main() {
switch (k) { default: ps("d"); case 1: ps("one"); case 2: ps("two"); }
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_default_middle.zc b/tests/conformance/4-statements/switch_default_middle.zc
index a390efe..f96db88 100644
--- a/tests/conformance/4-statements/switch_default_middle.zc
+++ b/tests/conformance/4-statements/switch_default_middle.zc
@@ -5,3 +5,4 @@ void pn(int x) { rt.put_n(x); rt.put_c(10); }
void ps(char* s) { rt.put_s(s); rt.put_c(10); }
void t(int k) { switch (k) { case 1: ps("one"); default: ps("d"); case 2: ps("two"); } }
fn main() { t(5); t(2); return 0; }
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_default_runs.zc b/tests/conformance/4-statements/switch_default_runs.zc
index bc42976..aa9c6a7 100644
--- a/tests/conformance/4-statements/switch_default_runs.zc
+++ b/tests/conformance/4-statements/switch_default_runs.zc
@@ -8,3 +8,4 @@ fn main() {
switch (k) { case 1, 2: ps("one-two"); case 3: ps("three"); break; default: ps("d"); }
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_duplicate_labels_first_wins.zc b/tests/conformance/4-statements/switch_duplicate_labels_first_wins.zc
index e2a2e3b..67a0204 100644
--- a/tests/conformance/4-statements/switch_duplicate_labels_first_wins.zc
+++ b/tests/conformance/4-statements/switch_duplicate_labels_first_wins.zc
@@ -8,3 +8,4 @@ fn main() {
switch (k) { case 4: ps("first"); case 4: ps("second"); }
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_expression_evaluated_once.zc b/tests/conformance/4-statements/switch_expression_evaluated_once.zc
index bf82b99..5b6e822 100644
--- a/tests/conformance/4-statements/switch_expression_evaluated_once.zc
+++ b/tests/conformance/4-statements/switch_expression_evaluated_once.zc
@@ -1,4 +1,4 @@
-// expect: 1/hit/
+// expect: hit1/
// spec 4.7.1
include rt;
void pn(int x) { rt.put_n(x); rt.put_c(10); }
@@ -8,3 +8,4 @@ fn main() {
pn(i);
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_label_forms.zc b/tests/conformance/4-statements/switch_label_forms.zc
index ae131aa..cfe2712 100644
--- a/tests/conformance/4-statements/switch_label_forms.zc
+++ b/tests/conformance/4-statements/switch_label_forms.zc
@@ -1,5 +1,5 @@
// expect: neg/chr/sum/enum/
-// spec 4.7.1 and 3.14: labels are constant expressions
+// spec 4.7.1 and 3.14: labels are constant expressions (no precedence: 1 + 1 * 3 is 6)
include rt;
void pn(int x) { rt.put_n(x); rt.put_c(10); }
enum color { RED, GREEN };
@@ -12,5 +12,5 @@ void t(int k) {
}
rt.put_c(10);
}
-fn main() { t(-1); pn(0); return 0; }
+fn main() { t(-1); t('a'); t(6); t(1); return 0; }
// zc0: skip
diff --git a/tests/conformance/4-statements/switch_nested.zc b/tests/conformance/4-statements/switch_nested.zc
index 7fd9a34..d7f27f5 100644
--- a/tests/conformance/4-statements/switch_nested.zc
+++ b/tests/conformance/4-statements/switch_nested.zc
@@ -12,3 +12,4 @@ fn main() {
}
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_no_fallthrough_k2.zc b/tests/conformance/4-statements/switch_no_fallthrough_k2.zc
index 276ca30..c312236 100644
--- a/tests/conformance/4-statements/switch_no_fallthrough_k2.zc
+++ b/tests/conformance/4-statements/switch_no_fallthrough_k2.zc
@@ -8,3 +8,4 @@ fn main() {
switch (k) { case 1, 2: ps("one-two"); case 3: ps("three"); break; default: ps("d"); }
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_no_match_no_default.zc b/tests/conformance/4-statements/switch_no_match_no_default.zc
index 3021388..54c2016 100644
--- a/tests/conformance/4-statements/switch_no_match_no_default.zc
+++ b/tests/conformance/4-statements/switch_no_match_no_default.zc
@@ -9,3 +9,4 @@ fn main() {
ps("after");
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_return_inside_case.zc b/tests/conformance/4-statements/switch_return_inside_case.zc
index 7375e79..e2a0ee6 100644
--- a/tests/conformance/4-statements/switch_return_inside_case.zc
+++ b/tests/conformance/4-statements/switch_return_inside_case.zc
@@ -4,3 +4,4 @@ include rt;
void pn(int x) { rt.put_n(x); rt.put_c(10); }
int f(int k) { switch (k) { case 1: return 10; case 2: return 20; } return 0; }
fn main() { pn(f(2)); pn(f(1)); return 0; }
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_tagged_all_covered_no_warning.zc b/tests/conformance/4-statements/switch_tagged_all_covered_no_warning.zc
index 45a9846..4a3245f 100644
--- a/tests/conformance/4-statements/switch_tagged_all_covered_no_warning.zc
+++ b/tests/conformance/4-statements/switch_tagged_all_covered_no_warning.zc
@@ -9,3 +9,4 @@ fn main() {
rt.free(s);
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_tagged_circle.zc b/tests/conformance/4-statements/switch_tagged_circle.zc
index b1b1c55..15bc01d 100644
--- a/tests/conformance/4-statements/switch_tagged_circle.zc
+++ b/tests/conformance/4-statements/switch_tagged_circle.zc
@@ -9,3 +9,4 @@ fn main() {
rt.free(s);
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_tagged_default_no_warning.zc b/tests/conformance/4-statements/switch_tagged_default_no_warning.zc
index 0a22a7a..e7078ce 100644
--- a/tests/conformance/4-statements/switch_tagged_default_no_warning.zc
+++ b/tests/conformance/4-statements/switch_tagged_default_no_warning.zc
@@ -9,3 +9,4 @@ fn main() {
rt.free(s);
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_tagged_example.zc b/tests/conformance/4-statements/switch_tagged_example.zc
index 932aefc..0099791 100644
--- a/tests/conformance/4-statements/switch_tagged_example.zc
+++ b/tests/conformance/4-statements/switch_tagged_example.zc
@@ -9,3 +9,4 @@ fn main() {
rt.free(s);
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_tagged_match_by_tag.zc b/tests/conformance/4-statements/switch_tagged_match_by_tag.zc
index 9d2f7a1..3e2895c 100644
--- a/tests/conformance/4-statements/switch_tagged_match_by_tag.zc
+++ b/tests/conformance/4-statements/switch_tagged_match_by_tag.zc
@@ -17,3 +17,4 @@ fn main() {
rt.free(a);
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/switch_tagged_uncovered_warning_not_error.zc b/tests/conformance/4-statements/switch_tagged_uncovered_warning_not_error.zc
index dfacc9c..2207536 100644
--- a/tests/conformance/4-statements/switch_tagged_uncovered_warning_not_error.zc
+++ b/tests/conformance/4-statements/switch_tagged_uncovered_warning_not_error.zc
@@ -9,3 +9,4 @@ fn main() {
rt.free(s);
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/unchecked_fn.zc b/tests/conformance/4-statements/unchecked_fn.zc
index fa2055e..bc8acc5 100644
--- a/tests/conformance/4-statements/unchecked_fn.zc
+++ b/tests/conformance/4-statements/unchecked_fn.zc
@@ -4,3 +4,4 @@ include rt;
void pn(int x) { rt.put_n(x); rt.put_c(10); }
unchecked fn leaky() { int* p = rt.new(int); return 0; }
fn main() { leaky(); pn(1); return 0; }
+// zc0: skip
diff --git a/tests/conformance/4-statements/unchecked_stmt_block.zc b/tests/conformance/4-statements/unchecked_stmt_block.zc
index eca1a38..1aabb03 100644
--- a/tests/conformance/4-statements/unchecked_stmt_block.zc
+++ b/tests/conformance/4-statements/unchecked_stmt_block.zc
@@ -7,3 +7,4 @@ fn main() {
rt.put_s("ok"); rt.put_c(10);
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/4-statements/unchecked_toplevel_rest_of_unit.zc b/tests/conformance/4-statements/unchecked_toplevel_rest_of_unit.zc
index 439eca7..7d70eff 100644
--- a/tests/conformance/4-statements/unchecked_toplevel_rest_of_unit.zc
+++ b/tests/conformance/4-statements/unchecked_toplevel_rest_of_unit.zc
@@ -8,3 +8,4 @@ fn main() {
pn(1);
return 0;
}
+// zc0: skip
diff --git a/tests/conformance/5-declarations/const_chain.zc b/tests/conformance/5-declarations/const_chain.zc
new file mode 100644
index 0000000..96ab822
--- /dev/null
+++ b/tests/conformance/5-declarations/const_chain.zc
@@ -0,0 +1,6 @@
+// expect: 4/
+// spec 5.4
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+const A = 1, B = A + 3;
+fn main() { pn(B); return 0; }
diff --git a/tests/conformance/5-declarations/const_typed.zc b/tests/conformance/5-declarations/const_typed.zc
new file mode 100644
index 0000000..f760da7
--- /dev/null
+++ b/tests/conformance/5-declarations/const_typed.zc
@@ -0,0 +1,6 @@
+// expect: 3/
+// spec 5.4
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+const int A = 3;
+fn main() { pn(A); return 0; }
diff --git a/tests/conformance/5-declarations/docs_no_effect.zc b/tests/conformance/5-declarations/docs_no_effect.zc
new file mode 100644
index 0000000..32cf1eb
--- /dev/null
+++ b/tests/conformance/5-declarations/docs_no_effect.zc
@@ -0,0 +1,10 @@
+// expect: 3/
+// spec 5.14
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+docs on;
+/// three
+int f() { return 3; }
+docs off;
+fn main() { pn(f()); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/embed_missing_file.zc b/tests/conformance/5-declarations/embed_missing_file.zc
new file mode 100644
index 0000000..b83276b
--- /dev/null
+++ b/tests/conformance/5-declarations/embed_missing_file.zc
@@ -0,0 +1,7 @@
+// expect error: can't read the file named by embed
+// spec 5.11
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+embed "no_such_file_xyz.bin" as d;
+fn main() { return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/enhance_wrong_inputs.zc b/tests/conformance/5-declarations/enhance_wrong_inputs.zc
new file mode 100644
index 0000000..2ec23e0
--- /dev/null
+++ b/tests/conformance/5-declarations/enhance_wrong_inputs.zc
@@ -0,0 +1,7 @@
+// expect error: add2: wrong number of inputs
+// spec 5.10
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+enhance add2(a, b) vm { + };
+fn main() { pn(add2(1)); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/enum_member_names_earlier_b2.zc b/tests/conformance/5-declarations/enum_member_names_earlier_b2.zc
new file mode 100644
index 0000000..a0f82e7
--- /dev/null
+++ b/tests/conformance/5-declarations/enum_member_names_earlier_b2.zc
@@ -0,0 +1,7 @@
+// expect: 17/
+// spec 2.8 and appendix b.2.2 (bug: rejected)
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+enum { HI = 16, LO = HI + 1 };
+fn main() { pn(LO); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/fn_13th_param_tagged.zc b/tests/conformance/5-declarations/fn_13th_param_tagged.zc
new file mode 100644
index 0000000..6aee764
--- /dev/null
+++ b/tests/conformance/5-declarations/fn_13th_param_tagged.zc
@@ -0,0 +1,7 @@
+// expect error: only the first 12 parameters can be tagged
+// spec 5.2.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn f(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,.d a13) { return 0; }
+fn main() { return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/fn_bare_name_not_declaration.zc b/tests/conformance/5-declarations/fn_bare_name_not_declaration.zc
new file mode 100644
index 0000000..4da0bed
--- /dev/null
+++ b/tests/conformance/5-declarations/fn_bare_name_not_declaration.zc
@@ -0,0 +1,7 @@
+// expect error: expected a declaration
+// spec 5.2.1
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+f(x) { return x; }
+fn main() { return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/fn_call_before_definition.zc b/tests/conformance/5-declarations/fn_call_before_definition.zc
new file mode 100644
index 0000000..44904da
--- /dev/null
+++ b/tests/conformance/5-declarations/fn_call_before_definition.zc
@@ -0,0 +1,6 @@
+// expect: 7/
+// spec 5.1.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { pn(f()); return 0; }
+int f() { return 7; }
diff --git a/tests/conformance/5-declarations/fn_falls_off_returns_zero.zc b/tests/conformance/5-declarations/fn_falls_off_returns_zero.zc
new file mode 100644
index 0000000..2368c0f
--- /dev/null
+++ b/tests/conformance/5-declarations/fn_falls_off_returns_zero.zc
@@ -0,0 +1,6 @@
+// expect: 0/
+// spec 5.2.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int f() { }
+fn main() { pn(f()); return 0; }
diff --git a/tests/conformance/5-declarations/fn_main_int_return_ignored.zc b/tests/conformance/5-declarations/fn_main_int_return_ignored.zc
new file mode 100644
index 0000000..11cbe9c
--- /dev/null
+++ b/tests/conformance/5-declarations/fn_main_int_return_ignored.zc
@@ -0,0 +1,5 @@
+// expect: ok/
+// spec 5.2.5 and 8.1.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int main() { rt.put_s("ok"); rt.put_c(10); return 5; }
diff --git a/tests/conformance/5-declarations/fn_main_void.zc b/tests/conformance/5-declarations/fn_main_void.zc
new file mode 100644
index 0000000..75ddc79
--- /dev/null
+++ b/tests/conformance/5-declarations/fn_main_void.zc
@@ -0,0 +1,6 @@
+// expect: ok/
+// spec 5.2.5
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+void main() { rt.put_s("ok"); rt.put_c(10); }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/fn_prototype_after_definition_b4.zc b/tests/conformance/5-declarations/fn_prototype_after_definition_b4.zc
new file mode 100644
index 0000000..5b60578
--- /dev/null
+++ b/tests/conformance/5-declarations/fn_prototype_after_definition_b4.zc
@@ -0,0 +1,8 @@
+// expect: 1/
+// spec 5.2.6 and appendix b.2.4 (bug: definition hidden)
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int f() { return 1; }
+int f();
+fn main() { pn(f()); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/fn_prototype_mismatch.zc b/tests/conformance/5-declarations/fn_prototype_mismatch.zc
new file mode 100644
index 0000000..f55c95d
--- /dev/null
+++ b/tests/conformance/5-declarations/fn_prototype_mismatch.zc
@@ -0,0 +1,8 @@
+// expect error: f: doesn't match its earlier declaration
+// spec 5.2.6
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int f(int a);
+int f(int a, int b) { return a; }
+fn main() { return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/fn_prototype_named_params.zc b/tests/conformance/5-declarations/fn_prototype_named_params.zc
new file mode 100644
index 0000000..6c6cbc0
--- /dev/null
+++ b/tests/conformance/5-declarations/fn_prototype_named_params.zc
@@ -0,0 +1,7 @@
+// expect: 9/
+// spec 5.2.1
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int sq(int n);
+fn main() { pn(sq(3)); return 0; }
+int sq(int n) { return n * n; }
diff --git a/tests/conformance/5-declarations/fn_prototype_unnamed_params_b13.zc b/tests/conformance/5-declarations/fn_prototype_unnamed_params_b13.zc
new file mode 100644
index 0000000..34ba270
--- /dev/null
+++ b/tests/conformance/5-declarations/fn_prototype_unnamed_params_b13.zc
@@ -0,0 +1,8 @@
+// expect: 4/
+// spec 5.2.1 and appendix b.2.13 (bug: rejected)
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int dbl(int);
+fn main() { pn(dbl(2)); return 0; }
+int dbl(int n) { return n * 2; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/fn_redefined_b3.zc b/tests/conformance/5-declarations/fn_redefined_b3.zc
new file mode 100644
index 0000000..3f78173
--- /dev/null
+++ b/tests/conformance/5-declarations/fn_redefined_b3.zc
@@ -0,0 +1,8 @@
+// expect error: f: is defined twice
+// spec 5.2.6 and appendix b.2.3 (bug: accepted silently)
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int f() { return 1; }
+int f() { return 2; }
+fn main() { pn(f()); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/fn_return_tag_only_u.zc b/tests/conformance/5-declarations/fn_return_tag_only_u.zc
new file mode 100644
index 0000000..87ec86b
--- /dev/null
+++ b/tests/conformance/5-declarations/fn_return_tag_only_u.zc
@@ -0,0 +1,7 @@
+// expect error: the only return tag is .u
+// spec 5.2.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int*.m f() { return 0; }
+fn main() { return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/fn_struct_param_rejected.zc b/tests/conformance/5-declarations/fn_struct_param_rejected.zc
new file mode 100644
index 0000000..d54f999
--- /dev/null
+++ b/tests/conformance/5-declarations/fn_struct_param_rejected.zc
@@ -0,0 +1,8 @@
+// expect error: structs and arrays are passed by pointer
+// spec 5.2.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+struct p { int x; }
+int f(p v) { return 0; }
+fn main() { return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/fn_typed_mixed_params.zc b/tests/conformance/5-declarations/fn_typed_mixed_params.zc
new file mode 100644
index 0000000..c0658ee
--- /dev/null
+++ b/tests/conformance/5-declarations/fn_typed_mixed_params.zc
@@ -0,0 +1,6 @@
+// expect: 5/
+// spec 5.2.1
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn f(int a, b) { return a + b; }
+fn main() { pn(f(2, 3)); return 0; }
diff --git a/tests/conformance/5-declarations/fn_u_falls_off.zc b/tests/conformance/5-declarations/fn_u_falls_off.zc
new file mode 100644
index 0000000..3ab6194
--- /dev/null
+++ b/tests/conformance/5-declarations/fn_u_falls_off.zc
@@ -0,0 +1,7 @@
+// expect error: a function returning .u has to end with a return
+// spec 5.2.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+.u f(int k) { if (k) return rt.new(2); }
+fn main() { return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/global_call_init_rejected.zc b/tests/conformance/5-declarations/global_call_init_rejected.zc
new file mode 100644
index 0000000..b4b1301
--- /dev/null
+++ b/tests/conformance/5-declarations/global_call_init_rejected.zc
@@ -0,0 +1,8 @@
+// expect error: expected ';', found '('
+// spec 5.3.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int f() { return 1; }
+int a = f();
+fn main() { return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/global_const_expr_init.zc b/tests/conformance/5-declarations/global_const_expr_init.zc
new file mode 100644
index 0000000..8a9d30b
--- /dev/null
+++ b/tests/conformance/5-declarations/global_const_expr_init.zc
@@ -0,0 +1,7 @@
+// expect: 4/
+// spec 5.3.2 and 3.14.1 (left to right: ((1+2)*2)-2)
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int g = 1 + 2 * 2 - 2;
+fn main() { pn(g); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/global_float_init_b7.zc b/tests/conformance/5-declarations/global_float_init_b7.zc
new file mode 100644
index 0000000..14d5204
--- /dev/null
+++ b/tests/conformance/5-declarations/global_float_init_b7.zc
@@ -0,0 +1,7 @@
+// expect: 1/
+// spec 5.3.2 and appendix b.2.7 (bug: rejected)
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+float g = 1.5;
+fn main() { pn(g * 2.0 == 3.0); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/global_names_global_b8.zc b/tests/conformance/5-declarations/global_names_global_b8.zc
new file mode 100644
index 0000000..7d678eb
--- /dev/null
+++ b/tests/conformance/5-declarations/global_names_global_b8.zc
@@ -0,0 +1,7 @@
+// expect: 1/
+// spec 5.3.2 and 3.14.2: a global named in an initializer is its address (appendix b.2.8 calls this a bug)
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int a = 5; int b = a + 1;
+fn main() { pn(b == (int)&a + 1); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/global_tagged_rejected.zc b/tests/conformance/5-declarations/global_tagged_rejected.zc
new file mode 100644
index 0000000..3386ae4
--- /dev/null
+++ b/tests/conformance/5-declarations/global_tagged_rejected.zc
@@ -0,0 +1,7 @@
+// expect error: tags go on locals and parameters, not globals
+// spec 5.3.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int*.m g;
+fn main() { return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/global_word_string.zc b/tests/conformance/5-declarations/global_word_string.zc
new file mode 100644
index 0000000..3a5ba48
--- /dev/null
+++ b/tests/conformance/5-declarations/global_word_string.zc
@@ -0,0 +1,7 @@
+// expect: hi/
+// spec 5.3.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+char* s = "hi";
+fn main() { rt.put_s(s); rt.put_c(10); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/global_zero_initialised.zc b/tests/conformance/5-declarations/global_zero_initialised.zc
new file mode 100644
index 0000000..6f1665d
--- /dev/null
+++ b/tests/conformance/5-declarations/global_zero_initialised.zc
@@ -0,0 +1,7 @@
+// expect: 0/0/
+// spec 5.3.1
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int g; int[4] buf;
+fn main() { pn(g); pn(buf[3]); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/include_in_function_b9.zc b/tests/conformance/5-declarations/include_in_function_b9.zc
new file mode 100644
index 0000000..cccaea5
--- /dev/null
+++ b/tests/conformance/5-declarations/include_in_function_b9.zc
@@ -0,0 +1,6 @@
+// expect error: include
+// spec 5.12.7 and appendix b.2.9: expected an error saying include is top level only
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { include std; return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/include_rt_required.zc b/tests/conformance/5-declarations/include_rt_required.zc
new file mode 100644
index 0000000..e897e97
--- /dev/null
+++ b/tests/conformance/5-declarations/include_rt_required.zc
@@ -0,0 +1,4 @@
+// expect error: module access requires `include rt;`
+// spec 5.12.4 and 8.1.1
+fn main() { rt.put_c(65); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/include_twice_compiled_once.zc b/tests/conformance/5-declarations/include_twice_compiled_once.zc
new file mode 100644
index 0000000..153f66e
--- /dev/null
+++ b/tests/conformance/5-declarations/include_twice_compiled_once.zc
@@ -0,0 +1,8 @@
+// expect: ok/
+// spec 5.12.8
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+include std;
+include std;
+fn main() { rt.put_s("ok"); rt.put_c(10); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/namespace_main_runs.zc b/tests/conformance/5-declarations/namespace_main_runs.zc
new file mode 100644
index 0000000..8a62291
--- /dev/null
+++ b/tests/conformance/5-declarations/namespace_main_runs.zc
@@ -0,0 +1,7 @@
+// expect: 1/
+// spec 8.1.2: main in a namespaced file runs
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+namespace foo;
+fn main() { pn(1); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/struct_constant_duplicate.zc b/tests/conformance/5-declarations/struct_constant_duplicate.zc
new file mode 100644
index 0000000..df14af9
--- /dev/null
+++ b/tests/conformance/5-declarations/struct_constant_duplicate.zc
@@ -0,0 +1,7 @@
+// expect error: MAX: is defined twice in this struct
+// spec 5.5.1
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+struct s { const MAX = 1; const MAX = 2; }
+fn main() { return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/struct_constant_outside_and_inside.zc b/tests/conformance/5-declarations/struct_constant_outside_and_inside.zc
new file mode 100644
index 0000000..79686f8
--- /dev/null
+++ b/tests/conformance/5-declarations/struct_constant_outside_and_inside.zc
@@ -0,0 +1,7 @@
+// expect: 24/25/
+// spec 5.5.1
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+struct s { int x; const MAX = 24; fn m() { return MAX + 1; } }
+fn main() { s* p = rt.new(s); pn(s.MAX); pn(p.m()); rt.free(p); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/struct_field_wins_over_method.zc b/tests/conformance/5-declarations/struct_field_wins_over_method.zc
new file mode 100644
index 0000000..14bf08b
--- /dev/null
+++ b/tests/conformance/5-declarations/struct_field_wins_over_method.zc
@@ -0,0 +1,8 @@
+// expect: 9/
+// spec 5.5.4
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int t9() { return 9; }
+struct s { int x; let m; fn m() { return 1; } }
+fn main() { s* p = rt.new(s); p.m = t9; pn(p.m()); rt.free(p); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/struct_method_calls_later.zc b/tests/conformance/5-declarations/struct_method_calls_later.zc
new file mode 100644
index 0000000..5230f81
--- /dev/null
+++ b/tests/conformance/5-declarations/struct_method_calls_later.zc
@@ -0,0 +1,7 @@
+// expect: 3/
+// spec 5.5.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+struct s { int x; fn a() { return this.b(); } fn b() { return this.x; } }
+fn main() { s* p = rt.new(s); p.x = 3; pn(p.a()); rt.free(p); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/struct_static_beats_toplevel.zc b/tests/conformance/5-declarations/struct_static_beats_toplevel.zc
new file mode 100644
index 0000000..ee63428
--- /dev/null
+++ b/tests/conformance/5-declarations/struct_static_beats_toplevel.zc
@@ -0,0 +1,8 @@
+// expect: 2/
+// spec 5.5.5
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn two() { return 99; }
+struct s { int x; static fn two() { return 2; } static fn get() { return two(); } }
+fn main() { pn(s.get()); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/struct_static_call.zc b/tests/conformance/5-declarations/struct_static_call.zc
new file mode 100644
index 0000000..e2b4fe8
--- /dev/null
+++ b/tests/conformance/5-declarations/struct_static_call.zc
@@ -0,0 +1,7 @@
+// expect: 6/6/
+// spec 5.5.5
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+struct s { int x; static fn two() { return 2; } static fn six() { return two() * 3; } }
+fn main() { pn(s.six()); pn(s.two() * 3); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/struct_static_misspelled.zc b/tests/conformance/5-declarations/struct_static_misspelled.zc
new file mode 100644
index 0000000..9986fde
--- /dev/null
+++ b/tests/conformance/5-declarations/struct_static_misspelled.zc
@@ -0,0 +1,7 @@
+// expect error: MAXX: is not a static function of this struct; did you mean 'MAX'?
+// spec 5.5.6
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+struct s { int x; const MAX = 1; }
+fn main() { pn(s.MAXX); return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/struct_this_declared.zc b/tests/conformance/5-declarations/struct_this_declared.zc
new file mode 100644
index 0000000..88c67e5
--- /dev/null
+++ b/tests/conformance/5-declarations/struct_this_declared.zc
@@ -0,0 +1,7 @@
+// expect error: this is implicit and cannot be declared as a method parameter
+// spec 5.5.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+struct s { int x; fn m(s* this) { return 0; } }
+fn main() { return 0; }
+// zc0: skip
diff --git a/tests/conformance/5-declarations/type_alias.zc b/tests/conformance/5-declarations/type_alias.zc
new file mode 100644
index 0000000..98f7f06
--- /dev/null
+++ b/tests/conformance/5-declarations/type_alias.zc
@@ -0,0 +1,8 @@
+// expect: 5/
+// spec 5.6
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+type num = int;
+num f(num a) { return a + 1; }
+fn main() { pn(f(4)); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/alias_after_free.zc b/tests/conformance/6-ownership/alias_after_free.zc
new file mode 100644
index 0000000..56cc45e
--- /dev/null
+++ b/tests/conformance/6-ownership/alias_after_free.zc
@@ -0,0 +1,7 @@
+// expect error: t: used after it was given away
+// spec 6.6.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+char* tail(char* s) { return s + 1; }
+fn main() { char* b = rt.new(4); b[0] = 97; b[1] = 98; b[2] = 0; char* t = tail(b); rt.free(b); rt.put_s(t); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/alias_before_free_ok.zc b/tests/conformance/6-ownership/alias_before_free_ok.zc
new file mode 100644
index 0000000..cea455e
--- /dev/null
+++ b/tests/conformance/6-ownership/alias_before_free_ok.zc
@@ -0,0 +1,7 @@
+// expect: b/
+// spec 6.6.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+char* tail(char* s) { return s + 1; }
+fn main() { char* b = rt.new(4); b[0] = 97; b[1] = 98; b[2] = 0; char* t = tail(b); rt.put_s(t); rt.put_c(10); rt.free(b); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/array_literal_escape_global.zc b/tests/conformance/6-ownership/array_literal_escape_global.zc
new file mode 100644
index 0000000..b5a9982
--- /dev/null
+++ b/tests/conformance/6-ownership/array_literal_escape_global.zc
@@ -0,0 +1,7 @@
+// expect error: an array literal cannot escape into a global or container
+// spec 6.9.4
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int* g;
+fn main() { g = (int[]){1, 2}; return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/block_value_m_rejected.zc b/tests/conformance/6-ownership/block_value_m_rejected.zc
new file mode 100644
index 0000000..8cd8fe4
--- /dev/null
+++ b/tests/conformance/6-ownership/block_value_m_rejected.zc
@@ -0,0 +1,6 @@
+// expect error: p: has to be u to be handed up as the block's value
+// spec 6.8.4
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int* q = { int* p = rt.new(1); p }; pn(q[0]); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/block_value_u.zc b/tests/conformance/6-ownership/block_value_u.zc
new file mode 100644
index 0000000..9cfd5df
--- /dev/null
+++ b/tests/conformance/6-ownership/block_value_u.zc
@@ -0,0 +1,6 @@
+// expect: 4/
+// spec 6.8.4
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int* q = { int* p = rt.new(1); p[0] = 4; u*p; p }; pn(q[0]); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/borrow_to_global.zc b/tests/conformance/6-ownership/borrow_to_global.zc
new file mode 100644
index 0000000..2616c2d
--- /dev/null
+++ b/tests/conformance/6-ownership/borrow_to_global.zc
@@ -0,0 +1,8 @@
+// expect error: p: is not an owner
+// spec 6.9.1
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int* g;
+void f(int*.m p) { g = p; }
+fn main() { return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/container_child_freed.zc b/tests/conformance/6-ownership/container_child_freed.zc
new file mode 100644
index 0000000..3611617
--- /dev/null
+++ b/tests/conformance/6-ownership/container_child_freed.zc
@@ -0,0 +1,8 @@
+// expect: 0/
+// spec 6.3.5 and 6.5.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+memdebug on;
+struct n { int* c; }
+fn main() { { n* a = rt.new(n); int* c = rt.new(1); c[0] = 1; a.c = c; pn(a.c[0] - 1); } rt.memreport(); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/copy_owner_rejected.zc b/tests/conformance/6-ownership/copy_owner_rejected.zc
new file mode 100644
index 0000000..c102ac9
--- /dev/null
+++ b/tests/conformance/6-ownership/copy_owner_rejected.zc
@@ -0,0 +1,6 @@
+// expect error: p: is an owned object and can't be copied into another variable
+// spec 6.8.5
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int* p = rt.new(1); int* q; q = p; pn(q[0]); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/d_never_given_away.zc b/tests/conformance/6-ownership/d_never_given_away.zc
new file mode 100644
index 0000000..a7167ff
--- /dev/null
+++ b/tests/conformance/6-ownership/d_never_given_away.zc
@@ -0,0 +1,6 @@
+// expect error: p: d object was never given away
+// spec 6.7
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int* p = rt.new(2); p[0] = 1; d*p; return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/d_param_transfers.zc b/tests/conformance/6-ownership/d_param_transfers.zc
new file mode 100644
index 0000000..78cc0e1
--- /dev/null
+++ b/tests/conformance/6-ownership/d_param_transfers.zc
@@ -0,0 +1,7 @@
+// expect error: q: used after it was given away
+// spec 6.4
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+void take(int*.d p) { rt.free(p); }
+fn main() { int* q = rt.new(int); take(q); pn(*q); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/free_then_reassign.zc b/tests/conformance/6-ownership/free_then_reassign.zc
new file mode 100644
index 0000000..5ebc693
--- /dev/null
+++ b/tests/conformance/6-ownership/free_then_reassign.zc
@@ -0,0 +1,6 @@
+// expect: 7/
+// spec 6.8.5
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int* a = rt.new(1); a[0] = 1; int* b = rt.new(1); b[0] = 7; rt.free(a); a = b; pn(a[0]); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/fresh_thrown_away.zc b/tests/conformance/6-ownership/fresh_thrown_away.zc
new file mode 100644
index 0000000..9acec75
--- /dev/null
+++ b/tests/conformance/6-ownership/fresh_thrown_away.zc
@@ -0,0 +1,6 @@
+// expect error: a new object (or a u result) can't be thrown away
+// spec 6.13
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { rt.new(2); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/global_store_needs_recast.zc b/tests/conformance/6-ownership/global_store_needs_recast.zc
new file mode 100644
index 0000000..2b8d09a
--- /dev/null
+++ b/tests/conformance/6-ownership/global_store_needs_recast.zc
@@ -0,0 +1,7 @@
+// expect: 2/
+// spec 6.9.1
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int* g;
+fn main() { int* x = rt.new(1); x[0] = 2; g = d*x; pn(g[0]); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/global_store_then_use.zc b/tests/conformance/6-ownership/global_store_then_use.zc
new file mode 100644
index 0000000..7aebc2c
--- /dev/null
+++ b/tests/conformance/6-ownership/global_store_then_use.zc
@@ -0,0 +1,7 @@
+// expect error: x: used after it was given away
+// spec 6.9.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int* g;
+fn main() { int* x = rt.new(1); x[0] = 2; g = d*x; pn(x[0]); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/if_join_free_one_branch.zc b/tests/conformance/6-ownership/if_join_free_one_branch.zc
new file mode 100644
index 0000000..77ccd23
--- /dev/null
+++ b/tests/conformance/6-ownership/if_join_free_one_branch.zc
@@ -0,0 +1,6 @@
+// expect: 1/
+// spec 6.10.1: dead on one path and m on the other becomes dead, freed on the live path
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int* p = rt.new(1); p[0] = 1; if (p[0]) { pn(p[0]); rt.free(p); } return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/if_join_mismatch.zc b/tests/conformance/6-ownership/if_join_mismatch.zc
new file mode 100644
index 0000000..f5c926f
--- /dev/null
+++ b/tests/conformance/6-ownership/if_join_mismatch.zc
@@ -0,0 +1,6 @@
+// expect error: p: ends the branches of an if in different states
+// spec 6.10.1
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int* p = rt.new(1); p[0] = 1; int k = 1; if (k) { u*p; } else { pn(p[0]); } return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/lend_keeps_owner.zc b/tests/conformance/6-ownership/lend_keeps_owner.zc
new file mode 100644
index 0000000..bb0813c
--- /dev/null
+++ b/tests/conformance/6-ownership/lend_keeps_owner.zc
@@ -0,0 +1,7 @@
+// expect: 3/3/
+// spec 6.6.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+void show(int* p) { pn(*p); }
+fn main() { int* q = rt.new(int); *q = 3; show(q); show(q); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/lend_to_global.zc b/tests/conformance/6-ownership/lend_to_global.zc
new file mode 100644
index 0000000..8cd2b8d
--- /dev/null
+++ b/tests/conformance/6-ownership/lend_to_global.zc
@@ -0,0 +1,8 @@
+// expect: 5/5/
+// spec 6.11
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int* g;
+fn show() { pn(g[0]); return 0; }
+fn main() { int* x = rt.new(1); x[0] = 5; int* saved = g; g = m*x; show(); g = saved; pn(x[0]); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/lend_to_global_open.zc b/tests/conformance/6-ownership/lend_to_global_open.zc
new file mode 100644
index 0000000..7ef3a2b
--- /dev/null
+++ b/tests/conformance/6-ownership/lend_to_global_open.zc
@@ -0,0 +1,7 @@
+// expect error: x: is lent to global g
+// spec 6.11
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int* g;
+fn main() { int* x = rt.new(1); x[0] = 5; g = m*x; return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/loop_give_away.zc b/tests/conformance/6-ownership/loop_give_away.zc
new file mode 100644
index 0000000..6c1d385
--- /dev/null
+++ b/tests/conformance/6-ownership/loop_give_away.zc
@@ -0,0 +1,6 @@
+// expect error: p: is given away inside a loop that comes back around to it
+// spec 6.10.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int* p = rt.new(1); p[0] = 1; for (int i = 0; i < 2; i++) { rt.free(p); } return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/loop_give_away_break_ok.zc b/tests/conformance/6-ownership/loop_give_away_break_ok.zc
new file mode 100644
index 0000000..e0d45ad
--- /dev/null
+++ b/tests/conformance/6-ownership/loop_give_away_break_ok.zc
@@ -0,0 +1,6 @@
+// expect: 1/
+// spec 6.10.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int* p = rt.new(1); p[0] = 1; while (1) { pn(p[0]); rt.free(p); break; } return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/m_freed_at_block_end_report.zc b/tests/conformance/6-ownership/m_freed_at_block_end_report.zc
new file mode 100644
index 0000000..3466e4a
--- /dev/null
+++ b/tests/conformance/6-ownership/m_freed_at_block_end_report.zc
@@ -0,0 +1,7 @@
+// expect: 0/
+// spec 6.5.1
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+memdebug on;
+fn main() { { int* p = rt.new(3); p[0] = 1; pn(p[0] - 1); } rt.memreport(); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/never_used.zc b/tests/conformance/6-ownership/never_used.zc
new file mode 100644
index 0000000..d4434bd
--- /dev/null
+++ b/tests/conformance/6-ownership/never_used.zc
@@ -0,0 +1,6 @@
+// expect error: p: owned object is never used
+// spec 6.5.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int* p = rt.new(3); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/overwrite_leaks.zc b/tests/conformance/6-ownership/overwrite_leaks.zc
new file mode 100644
index 0000000..a9b0138
--- /dev/null
+++ b/tests/conformance/6-ownership/overwrite_leaks.zc
@@ -0,0 +1,6 @@
+// expect error: a: still owns an object; overwriting it would leak it
+// spec 6.8.5
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int* a = rt.new(1); a[0] = 1; a = rt.new(1); pn(a[0]); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/recast_back_to_m.zc b/tests/conformance/6-ownership/recast_back_to_m.zc
new file mode 100644
index 0000000..5784945
--- /dev/null
+++ b/tests/conformance/6-ownership/recast_back_to_m.zc
@@ -0,0 +1,7 @@
+// expect error: p: can't be recast back to m
+// spec 6.7
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int* g;
+fn main() { int* p = rt.new(2); d*p; m*p; g = p; return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/recast_nothing.zc b/tests/conformance/6-ownership/recast_nothing.zc
new file mode 100644
index 0000000..e458a5f
--- /dev/null
+++ b/tests/conformance/6-ownership/recast_nothing.zc
@@ -0,0 +1,6 @@
+// expect error: x: isn't an owned object, so there is no ownership to recast
+// spec 6.7
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int x = 3; int* y = d*x; return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/return_owned_infers.zc b/tests/conformance/6-ownership/return_owned_infers.zc
new file mode 100644
index 0000000..ad40b78
--- /dev/null
+++ b/tests/conformance/6-ownership/return_owned_infers.zc
@@ -0,0 +1,7 @@
+// expect: 5/
+// spec 6.8.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn make() { int* p = rt.new(1); p[0] = 5; return p; }
+fn main() { int* q = make(); pn(q[0]); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/temporary_to_reader.zc b/tests/conformance/6-ownership/temporary_to_reader.zc
new file mode 100644
index 0000000..b45d096
--- /dev/null
+++ b/tests/conformance/6-ownership/temporary_to_reader.zc
@@ -0,0 +1,7 @@
+// expect: abc/
+// spec 6.5.4
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+char* msg() { char* s = rt.new(4); s[0] = 97; s[1] = 98; s[2] = 99; s[3] = 0; return s; }
+fn main() { rt.put_s(msg()); rt.put_c(10); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/u_must_leave.zc b/tests/conformance/6-ownership/u_must_leave.zc
new file mode 100644
index 0000000..147d64f
--- /dev/null
+++ b/tests/conformance/6-ownership/u_must_leave.zc
@@ -0,0 +1,6 @@
+// expect error: p: u object must leave this block
+// spec 6.7
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int* p = rt.new(2); p[0] = 1; u*p; return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/unchecked_no_errors.zc b/tests/conformance/6-ownership/unchecked_no_errors.zc
new file mode 100644
index 0000000..2e4af57
--- /dev/null
+++ b/tests/conformance/6-ownership/unchecked_no_errors.zc
@@ -0,0 +1,6 @@
+// expect: 1/
+// spec 6.12
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+unchecked fn main() { int* p = rt.new(1); p[0] = 1; pn(p[0]); return 0; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/use_after_free.zc b/tests/conformance/6-ownership/use_after_free.zc
new file mode 100644
index 0000000..ff3c113
--- /dev/null
+++ b/tests/conformance/6-ownership/use_after_free.zc
@@ -0,0 +1,6 @@
+// expect error: p: used after it was given away
+// spec 6.5.1
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int* p = rt.new(3); rt.free(p); pn(p[0]); return 0; }
+// zc0: skip
diff --git a/tests/conformance/7-compile-time/binop_pow.zc b/tests/conformance/7-compile-time/binop_pow.zc
new file mode 100644
index 0000000..ea26fb2
--- /dev/null
+++ b/tests/conformance/7-compile-time/binop_pow.zc
@@ -0,0 +1,10 @@
+// expect: 1024/18/
+// spec 7.5
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+include run;
+int ipow(int a, int b) { int r = 1; while (b > 0) { r = r * a; b--; } return r; }
+immediate fn pow_op() { run.next(); run.add_binop("**", 11, "ipow c"); return 0; }
+pow_op
+fn main() { pn(2 ** 10); pn(2 * 3 ** 2); return 0; }
+// zc0: skip
diff --git a/tests/conformance/7-compile-time/evals_prints.zc b/tests/conformance/7-compile-time/evals_prints.zc
new file mode 100644
index 0000000..66e236d
--- /dev/null
+++ b/tests/conformance/7-compile-time/evals_prints.zc
@@ -0,0 +1,7 @@
+// expect: 42/
+// spec 7.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+include run;
+fn main() { run.evals("rt.put_n(40 + 2); rt.put_c(10); return 7;"); return 0; }
+// zc0: skip
diff --git a/tests/conformance/7-compile-time/evals_returns.zc b/tests/conformance/7-compile-time/evals_returns.zc
new file mode 100644
index 0000000..3655612
--- /dev/null
+++ b/tests/conformance/7-compile-time/evals_returns.zc
@@ -0,0 +1,7 @@
+// expect: 42/
+// spec 7.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+include run;
+fn main() { pn(run.evals("return 6 * 7;")); return 0; }
+// zc0: skip
diff --git a/tests/conformance/7-compile-time/parse_word_five.zc b/tests/conformance/7-compile-time/parse_word_five.zc
new file mode 100644
index 0000000..b4da5d9
--- /dev/null
+++ b/tests/conformance/7-compile-time/parse_word_five.zc
@@ -0,0 +1,8 @@
+// expect: 6/
+// spec 7.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+include run;
+immediate fn five() { run.next(); run.lit(5); return 0; }
+fn main() { int x = five + 1; pn(x); return 0; }
+// zc0: skip
diff --git a/tests/conformance/7-compile-time/parse_word_reads_nothing.zc b/tests/conformance/7-compile-time/parse_word_reads_nothing.zc
new file mode 100644
index 0000000..e0f7cc1
--- /dev/null
+++ b/tests/conformance/7-compile-time/parse_word_reads_nothing.zc
@@ -0,0 +1,8 @@
+// expect error: a parse word has to read its own name with next()
+// spec 7.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+include run;
+immediate fn bad() { run.lit(5); return 0; }
+fn main() { int x = bad; return 0; }
+// zc0: skip
diff --git a/tests/conformance/7-compile-time/quote_count.zc b/tests/conformance/7-compile-time/quote_count.zc
new file mode 100644
index 0000000..a6369a8
--- /dev/null
+++ b/tests/conformance/7-compile-time/quote_count.zc
@@ -0,0 +1,7 @@
+// expect: 3/
+// spec 7.4
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+include run;
+fn main() { int* q = quote { a + b }; pn(q[0]); return 0; }
+// zc0: skip
diff --git a/tests/conformance/7-compile-time/run_requires_include.zc b/tests/conformance/7-compile-time/run_requires_include.zc
new file mode 100644
index 0000000..16c6101
--- /dev/null
+++ b/tests/conformance/7-compile-time/run_requires_include.zc
@@ -0,0 +1,6 @@
+// expect error: module access requires `include run;`
+// spec 5.12.4
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { pn(run.evals("return 1;")); return 0; }
+// zc0: skip
diff --git a/tests/conformance/7-compile-time/statement_hook_ticks.zc b/tests/conformance/7-compile-time/statement_hook_ticks.zc
new file mode 100644
index 0000000..7e51085
--- /dev/null
+++ b/tests/conformance/7-compile-time/statement_hook_ticks.zc
@@ -0,0 +1,10 @@
+// expect: 4/
+// spec 7.6
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+include run;
+int ticks;
+int tick() { ticks++; return 0; }
+run.statement_hook(tick);
+fn main() { int a = 1; a = a + 1; a = a + 1; pn(ticks); return 0; }
+// zc0: skip
diff --git a/tests/conformance/7-compile-time/syntax_hi.zc b/tests/conformance/7-compile-time/syntax_hi.zc
new file mode 100644
index 0000000..5cd050b
--- /dev/null
+++ b/tests/conformance/7-compile-time/syntax_hi.zc
@@ -0,0 +1,10 @@
+// expect: HH/
+// spec 7.6
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+include run;
+void kw_hi() { run.next(); run.expect(run.intern(";"));
+ run.lit('H'); run.callname(run.intern("rt.put_c")); run.op(run.O_DROP); return; }
+run.syntax("hi", kw_hi);
+fn main() { hi; hi; rt.put_c(10); return 0; }
+// zc0: skip
diff --git a/tests/conformance/8-runtime/div_by_zero_no_trap.zc b/tests/conformance/8-runtime/div_by_zero_no_trap.zc
new file mode 100644
index 0000000..156bb18
--- /dev/null
+++ b/tests/conformance/8-runtime/div_by_zero_no_trap.zc
@@ -0,0 +1,6 @@
+// expect: ok/
+// spec 8.4 and 3.4.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int z = 0; int x = 7 / z; rt.put_s("ok"); rt.put_c(10); return 0; }
+// zc0: skip
diff --git a/tests/conformance/8-runtime/error_line_format.zc b/tests/conformance/8-runtime/error_line_format.zc
new file mode 100644
index 0000000..0f45306
--- /dev/null
+++ b/tests/conformance/8-runtime/error_line_format.zc
@@ -0,0 +1,8 @@
+// expect error: zc: line 6:
+// spec 8.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() {
+ int x = ;
+ return 0; }
+// zc0: skip
diff --git a/tests/conformance/8-runtime/errors_do_not_run.zc b/tests/conformance/8-runtime/errors_do_not_run.zc
new file mode 100644
index 0000000..1a789a4
--- /dev/null
+++ b/tests/conformance/8-runtime/errors_do_not_run.zc
@@ -0,0 +1,6 @@
+// expect error: zc: 1 error
+// spec 8.1.2 and 8.2: a unit with errors does not run
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { pn(1); int x = ; return 0; }
+// zc0: skip
diff --git a/tests/conformance/8-runtime/get_c_reads_input.zc b/tests/conformance/8-runtime/get_c_reads_input.zc
new file mode 100644
index 0000000..469d564
--- /dev/null
+++ b/tests/conformance/8-runtime/get_c_reads_input.zc
@@ -0,0 +1,6 @@
+// expect: 104/105/-1/
+// spec 8.3: input after the backtick line
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { pn(rt.get_c()); pn(rt.get_c()); rt.get_c(); pn(rt.get_c()); return 0; }
+`hi
diff --git a/tests/conformance/8-runtime/halt_stops.zc b/tests/conformance/8-runtime/halt_stops.zc
new file mode 100644
index 0000000..28ae5e4
--- /dev/null
+++ b/tests/conformance/8-runtime/halt_stops.zc
@@ -0,0 +1,5 @@
+// expect: 1/
+// spec 8.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { pn(1); rt.halt(); pn(2); return 0; }
diff --git a/tests/conformance/8-runtime/index_out_of_range.zc b/tests/conformance/8-runtime/index_out_of_range.zc
new file mode 100644
index 0000000..76938b5
--- /dev/null
+++ b/tests/conformance/8-runtime/index_out_of_range.zc
@@ -0,0 +1,6 @@
+// expect error: zy: index 5 out of range (length 3)
+// spec 8.4
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int[?] a = rt.new(int[?], 3); int i = 5; pn(a[i]); return 0; }
+// zc0: skip
diff --git a/tests/conformance/8-runtime/len_w_eq_w.zc b/tests/conformance/8-runtime/len_w_eq_w.zc
new file mode 100644
index 0000000..78b1876
--- /dev/null
+++ b/tests/conformance/8-runtime/len_w_eq_w.zc
@@ -0,0 +1,5 @@
+// expect: 3/1/
+// spec 8.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { pn(rt.len_w("abc")); pn(rt.eq_w("ab", "ab") != 0); return 0; }
diff --git a/tests/conformance/8-runtime/new_zeroed.zc b/tests/conformance/8-runtime/new_zeroed.zc
new file mode 100644
index 0000000..fbdf407
--- /dev/null
+++ b/tests/conformance/8-runtime/new_zeroed.zc
@@ -0,0 +1,6 @@
+// expect: 0/
+// spec 8.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int* p = rt.new(5); pn(p[4]); return 0; }
+// zc0: skip
diff --git a/tests/conformance/8-runtime/no_main_runs_nothing.zc b/tests/conformance/8-runtime/no_main_runs_nothing.zc
new file mode 100644
index 0000000..91612d0
--- /dev/null
+++ b/tests/conformance/8-runtime/no_main_runs_nothing.zc
@@ -0,0 +1,6 @@
+// expect:
+// spec 8.1.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+int f() { rt.put_c(65); return 0; }
+// zc0: skip
diff --git a/tests/conformance/8-runtime/put_c_low_bits.zc b/tests/conformance/8-runtime/put_c_low_bits.zc
new file mode 100644
index 0000000..dfe226e
--- /dev/null
+++ b/tests/conformance/8-runtime/put_c_low_bits.zc
@@ -0,0 +1,5 @@
+// expect: A/
+// spec 8.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { rt.put_c(321); rt.put_c(10); return 0; }
diff --git a/tests/conformance/8-runtime/put_n_min.zc b/tests/conformance/8-runtime/put_n_min.zc
new file mode 100644
index 0000000..012084e
--- /dev/null
+++ b/tests/conformance/8-runtime/put_n_min.zc
@@ -0,0 +1,5 @@
+// expect: -9223372036854775808/
+// spec 8.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { pn(-9223372036854775807 - 1); return 0; }
diff --git a/tests/conformance/8-runtime/put_s_bstr.zc b/tests/conformance/8-runtime/put_s_bstr.zc
new file mode 100644
index 0000000..141f39c
--- /dev/null
+++ b/tests/conformance/8-runtime/put_s_bstr.zc
@@ -0,0 +1,6 @@
+// expect: bs/
+// spec 8.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { rt.put_s(b"bs"); rt.put_c(10); return 0; }
+// zc0: skip
diff --git a/tests/conformance/8-runtime/put_s_word_string.zc b/tests/conformance/8-runtime/put_s_word_string.zc
new file mode 100644
index 0000000..b8517c2
--- /dev/null
+++ b/tests/conformance/8-runtime/put_s_word_string.zc
@@ -0,0 +1,5 @@
+// expect: hey/
+// spec 8.3
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { rt.put_s("hey"); rt.put_c(10); return 0; }
diff --git a/tests/conformance/8-runtime/too_many_errors.zc b/tests/conformance/8-runtime/too_many_errors.zc
new file mode 100644
index 0000000..4a51501
--- /dev/null
+++ b/tests/conformance/8-runtime/too_many_errors.zc
@@ -0,0 +1,32 @@
+// expect error: zc: too many errors, stopping
+// spec 8.2
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() {
+ undefined_0();
+ undefined_1();
+ undefined_2();
+ undefined_3();
+ undefined_4();
+ undefined_5();
+ undefined_6();
+ undefined_7();
+ undefined_8();
+ undefined_9();
+ undefined_10();
+ undefined_11();
+ undefined_12();
+ undefined_13();
+ undefined_14();
+ undefined_15();
+ undefined_16();
+ undefined_17();
+ undefined_18();
+ undefined_19();
+ undefined_20();
+ undefined_21();
+ undefined_22();
+ undefined_23();
+ undefined_24();
+ return 0; }
+// zc0: skip
diff --git a/tests/conformance/9-appendix-b/b1_11_zc0_octal.zc b/tests/conformance/9-appendix-b/b1_11_zc0_octal.zc
new file mode 100644
index 0000000..747476d
--- /dev/null
+++ b/tests/conformance/9-appendix-b/b1_11_zc0_octal.zc
@@ -0,0 +1,5 @@
+// expect: 10/
+// spec appendix b.1.11: 010 is 10 (the compiler); zc0 reads 8
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { pn(010); return 0; }
diff --git a/tests/conformance/9-appendix-b/b1_11_zc0_saturation.zc b/tests/conformance/9-appendix-b/b1_11_zc0_saturation.zc
new file mode 100644
index 0000000..859761b
--- /dev/null
+++ b/tests/conformance/9-appendix-b/b1_11_zc0_saturation.zc
@@ -0,0 +1,5 @@
+// expect: -1/
+// spec appendix b.1.11: 0xFFFFFFFFFFFFFFFF wraps to -1; zc0 saturates
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { pn(0xFFFFFFFFFFFFFFFF); return 0; }
diff --git a/tests/conformance/9-appendix-b/b2_05_ternary_int_float.zc b/tests/conformance/9-appendix-b/b2_05_ternary_int_float.zc
new file mode 100644
index 0000000..60dd829
--- /dev/null
+++ b/tests/conformance/9-appendix-b/b2_05_ternary_int_float.zc
@@ -0,0 +1,7 @@
+// expect: 1.000000/2.500000/1.000000/2.500000/
+// spec appendix b.2.5: ?: with one int and one float branch
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn pf(float f) { asm { f @ #1220 } rt.put_c(10); return 0; }
+fn main() { pf(1 ? 1 : 2.5); pf(1 ? 2.5 : 1); pf(0 ? 2.5 : 1); pf(0 ? 1 : 2.5); return 0; }
+// zc0: skip
diff --git a/tests/conformance/9-appendix-b/b2_06_bool_normalises.zc b/tests/conformance/9-appendix-b/b2_06_bool_normalises.zc
new file mode 100644
index 0000000..7fe226c
--- /dev/null
+++ b/tests/conformance/9-appendix-b/b2_06_bool_normalises.zc
@@ -0,0 +1,6 @@
+// expect: 1/1/0/
+// spec appendix b.2.6: bool as a 0/1 type
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { bool b = 5; pn(b); pn(b == 1); pn(!b); return 0; }
+// zc0: skip
diff --git a/tests/conformance/9-appendix-b/b2_10_recovery_hides_errors.zc b/tests/conformance/9-appendix-b/b2_10_recovery_hides_errors.zc
new file mode 100644
index 0000000..d770fcd
--- /dev/null
+++ b/tests/conformance/9-appendix-b/b2_10_recovery_hides_errors.zc
@@ -0,0 +1,6 @@
+// expect error: zc: 2 errors
+// spec appendix b.2.10 and 8.2: by design only the first error is reported
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int a = ; int b = 3 +; return 0; }
+// zc0: skip
diff --git a/tests/conformance/9-appendix-b/b2_11_unterminated_comment.zc b/tests/conformance/9-appendix-b/b2_11_unterminated_comment.zc
new file mode 100644
index 0000000..e6e6bbf
--- /dev/null
+++ b/tests/conformance/9-appendix-b/b2_11_unterminated_comment.zc
@@ -0,0 +1,7 @@
+// expect error: unterminated
+// spec appendix b.2.11: an unterminated /* is accepted silently
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { pn(1); return 0; }
+/* never closed
+// zc0: skip
diff --git a/tests/conformance/9-appendix-b/b2_12_as_int_star.zc b/tests/conformance/9-appendix-b/b2_12_as_int_star.zc
new file mode 100644
index 0000000..fc12792
--- /dev/null
+++ b/tests/conformance/9-appendix-b/b2_12_as_int_star.zc
@@ -0,0 +1,6 @@
+// expect: 6/
+// spec appendix b.2.12: x as int * y should multiply
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int x = 2; int y = 3; pn(x as int * y); return 0; }
+// zc0: skip
diff --git a/tests/conformance/9-appendix-b/b2_14_len_char_ptr_typecheck_off.zc b/tests/conformance/9-appendix-b/b2_14_len_char_ptr_typecheck_off.zc
new file mode 100644
index 0000000..b0d0d45
--- /dev/null
+++ b/tests/conformance/9-appendix-b/b2_14_len_char_ptr_typecheck_off.zc
@@ -0,0 +1,7 @@
+// expect: 3/
+// spec appendix b.2.14: len(char*) with typecheck off returns word 0
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+typecheck off;
+fn main() { char* s = "abc"; pn(len(s)); return 0; }
+// zc0: skip
diff --git a/tests/conformance/9-appendix-b/b2_15_duplicate_case.zc b/tests/conformance/9-appendix-b/b2_15_duplicate_case.zc
new file mode 100644
index 0000000..63c30ec
--- /dev/null
+++ b/tests/conformance/9-appendix-b/b2_15_duplicate_case.zc
@@ -0,0 +1,6 @@
+// expect error: duplicate
+// spec appendix b.2.15: duplicate case labels are not diagnosed (4.7.2 says they are allowed)
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { int k = 1; switch (k) { case 1: pn(1); case 1: pn(2); } return 0; }
+// zc0: skip
diff --git a/tests/conformance/9-appendix-b/b2_16_local_const_in_const_expr.zc b/tests/conformance/9-appendix-b/b2_16_local_const_in_const_expr.zc
new file mode 100644
index 0000000..70093c9
--- /dev/null
+++ b/tests/conformance/9-appendix-b/b2_16_local_const_in_const_expr.zc
@@ -0,0 +1,6 @@
+// expect: 5/
+// spec appendix b.2.16 and 3.14.2: a local const is not a constant expression
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+fn main() { const n = 5; int[n] a; pn(5); return 0; }
+// zc0: skip
diff --git a/tests/conformance/known.txt b/tests/conformance/known.txt
new file mode 100644
index 0000000..c26b50e
--- /dev/null
+++ b/tests/conformance/known.txt
@@ -0,0 +1,71 @@
+# understood conformance failures: PATH IMPL CLASS reason
+# class a: self-hosted compiler bug; b: zc0 deviation (appendix a/b); c: spec issue to settle
+1-source/ident_tags_as_variables_glued_star.zc zy a u*d with visible variables u and d is taken as a recast, not a multiplication (spec 1.6.3)
+1-source/lit_bstr_cast_to_int_pointer.zc zy a the bstr flag leaks into an int* local, so p[0] reads a byte
+1-source/lit_char_non_ascii.zc zy a bad character literal in the first statement of a body is swallowed by lookahead
+1-source/lit_char_two_bytes.zc zy a bad character literal in the first statement of a body is swallowed by lookahead
+1-source/lit_char_two_bytes_local_init.zc zy a bad character literal in the first statement of a body is swallowed by lookahead
+1-source/lit_float_bad_exponent.zc zy a bad float literal in the first statement of a body is swallowed by lookahead
+1-source/lit_float_bad_exponent_first_stmt_local.zc zy a bad float literal in the first statement of a body is swallowed by lookahead
+1-source/lit_float_bad_exponent_first_stmt_paren.zc zy a bad float literal in the first statement of a body is swallowed by lookahead
+1-source/lit_float_bad_exponent_in_helper.zc zy a bad float literal in the first statement of a body is swallowed by lookahead
+1-source/lit_float_bad_exponent_sign.zc zy a bad float literal in the first statement of a body is swallowed by lookahead
+2-types/typecheck_off_void_return_value_ok.zc zy a void f() { return 3; } yields 3, not 0 (spec 4.8.3)
+3-expressions/call_24_parameters.zc zy a the parameter limit is 23, not 24 (decl.zc; closures 19)
+3-expressions/call_24_parameters_prototype.zc zy a the parameter limit is 23, not 24 (decl.zc; closures 19)
+4-statements/memdebug_scrub_accepted.zc zy a memdebug scrub; is rejected (appendix b.1.1, b.2.1)
+4-statements/memdebug_scrub_fills.zc zy a memdebug scrub; is rejected (appendix b.1.1, b.2.1)
+4-statements/o3_outside_function_ordinary_block.zc zy c top-level o3 { } is rejected; spec 4.10.2 says it is an ordinary block
+4-statements/switch_tagged_match_by_tag.zc zy a case member(): on a member with fields is rejected (a case binds every field); spec 4.7.3 says it matches by tag
+5-declarations/enum_member_names_earlier_b2.zc zy a appendix b.2.2 confirmed: enum members can't name earlier members
+5-declarations/fn_prototype_after_definition_b4.zc zy a appendix b.2.4 confirmed: a prototype after the definition hides it
+5-declarations/fn_prototype_unnamed_params_b13.zc zy a appendix b.2.13 confirmed (message now: doesn't match its earlier declaration)
+5-declarations/fn_redefined_b3.zc zy a appendix b.2.3 confirmed: a plain redefinition silently shadows the first
+5-declarations/global_float_init_b7.zc zy a appendix b.2.7 confirmed: float global initializer rejected
+5-declarations/include_in_function_b9.zc zy a appendix b.2.9 confirmed: include in a body gives "return outside a function"
+9-appendix-b/b2_05_ternary_int_float.zc zy a appendix b.2.5 confirmed
+9-appendix-b/b2_06_bool_normalises.zc zy a appendix b.2.6 confirmed
+9-appendix-b/b2_10_recovery_hides_errors.zc zy c appendix b.2.10 confirmed; by design per 8.2
+9-appendix-b/b2_11_unterminated_comment.zc zy a appendix b.2.11 confirmed
+9-appendix-b/b2_12_as_int_star.zc zy a appendix b.2.12 confirmed
+9-appendix-b/b2_14_len_char_ptr_typecheck_off.zc zy a appendix b.2.14 confirmed
+9-appendix-b/b2_15_duplicate_case.zc zy c appendix b.2.15 confirmed; 4.7.2 says duplicates are allowed
+9-appendix-b/b2_16_local_const_in_const_expr.zc zy c appendix b.2.16 confirmed; 3.14.2 documents it
+1-source/ident_tags_as_variables_glued_star.zc zc0 b recast u*d emits no code (same misparse as zy)
+1-source/lit_hex.zc zc0 b literals read with strtoll base 0: octal and saturation (appendix b.1.11)
+1-source/lit_hex_wide.zc zc0 b literals read with strtoll base 0: octal and saturation (appendix b.1.11)
+1-source/lit_hex_wraps.zc zc0 b literals read with strtoll base 0: octal and saturation (appendix b.1.11)
+1-source/lit_int_max.zc zc0 b literals read with strtoll base 0: octal and saturation (appendix b.1.11)
+1-source/lit_int_wraps.zc zc0 b literals read with strtoll base 0: octal and saturation (appendix b.1.11)
+1-source/lit_int_zero_and_leading_zeros.zc zc0 b literals read with strtoll base 0: octal and saturation (appendix b.1.11)
+1-source/lit_minus_folded.zc zc0 b literals read with strtoll base 0: octal and saturation (appendix b.1.11)
+2-types/conv_argument_and_return.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+2-types/conv_assignment_to_float.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+2-types/conv_f32_rounds.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+2-types/conv_float_to_int_truncates.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+2-types/conv_int_to_float_initializer.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+2-types/conv_word_keeps_bits.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+2-types/f32_rounds_on_store.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+2-types/float_truthy.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+2-types/int_sized_cut_more.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+2-types/int_sized_cut_store.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+2-types/int_sized_param_return.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+2-types/typecheck_float_to_int_number.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+2-types/typecheck_number_kinds_convert.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+2-types/typecheck_off_void_return_value_ok.zc zc0 b void f() { return 3; } yields 3 (same as zy)
+3-expressions/call_params_converted_to_float.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+3-expressions/call_params_sized_cut.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+3-expressions/cast_as_char_unchanged.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+3-expressions/float_basic_arith.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+3-expressions/float_division_int_stored.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+3-expressions/float_int_ops_on_bits.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+3-expressions/incr_on_float_changes_bits.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+3-expressions/int_min_div_minus1.zc zc0 b INT_MIN / -1 gives 0 and % gives INT_MIN in zc0
+3-expressions/int_min_mod_minus1.zc zc0 b INT_MIN / -1 gives 0 and % gives INT_MIN in zc0
+3-expressions/prec_as_binds_tight.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+4-statements/return_value_converted_float.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+4-statements/return_value_converted_int.zc zc0 b types are read and dropped: no conversion, no sized cut (appendix a)
+9-appendix-b/b1_11_zc0_octal.zc zc0 b literals read with strtoll base 0: octal and saturation (appendix b.1.11)
+9-appendix-b/b1_11_zc0_saturation.zc zc0 b literals read with strtoll base 0: octal and saturation (appendix b.1.11)
+1-source/lit_hex_no_digits_is_zero.zc zc0 b 0x with no digits is rejected (strtoll)
+1-source/lit_int_octal_is_decimal.zc zc0 b 08 is rejected (strtoll base 0 octal)
diff --git a/tests/conformance/run.sh b/tests/conformance/run.sh
index 433b37d..c87b142 100755
--- a/tests/conformance/run.sh
+++ b/tests/conformance/run.sh
@@ -15,7 +15,7 @@
# tests/conformance and IMPL one of zy, zym, zc0. they print as `known` and do not fail the run.
set -u
usage() {
- printf '%s\n' 'usage: tests/conformance/run.sh [--zym] [--zc0] [-q] [-t SECONDS] [FILE.zc | DIR ...]' \
+ printf '%s\n' 'usage: tests/conformance/run.sh [--zym] [--zc0] [--zy BINARY] [-w DIR] [-q] [-t SECONDS] [FILE.zc | DIR ...]' \
'runs the conformance programs under tests/conformance (or the given files and folders) on build/bin/zy.' \
'each program starts with `// expect: TEXT` (output, newlines as /) or `// expect error: TEXT`.' \
'prints ok, FAIL, known or skip per program and implementation, then a summary per section and a total;' \
@@ -23,18 +23,22 @@ usage() {
'options:' \
' --zym also run every program on build/bin/zym' \
' --zc0 also run the programs zc0 accepts through zc0 (build/bin/zc0 and a microcore per program)' \
+ ' --zy BINARY run this core instead of build/bin/zy (tests/test.sh passes its own)' \
+ ' -w DIR keep work files under DIR instead of build/conformance' \
' -q print only FAIL lines and the summary' \
' -t SECONDS time limit for each run (default 20)' \
' --help, -h show this help and exit' \
'work files are under build/conformance/ and build/parity/.'
}
-zym=0; zc0=0; quiet=0; limit=20; args=()
+zym=0; zc0=0; quiet=0; limit=20; args=(); zy=build/bin/zy; W=build/conformance
while [ $# -gt 0 ]; do
case "$1" in
--help|-h) usage; exit 0 ;;
--zym) zym=1; shift ;;
--zc0) zc0=1; shift ;;
-q) quiet=1; shift ;;
+ --zy) [ $# -ge 2 ] || { echo "run.sh: --zy needs a binary" >&2; exit 2; }; zy=$2; shift 2 ;;
+ -w) [ $# -ge 2 ] || { echo "run.sh: -w needs a folder" >&2; exit 2; }; W=$2; shift 2 ;;
-t) [ $# -ge 2 ] || { echo "run.sh: -t needs a number of seconds" >&2; exit 2; }
case "$2" in ''|*[!0-9]*|0) echo "run.sh: -t needs a positive number of seconds" >&2; exit 2 ;; esac
limit=$2; shift 2 ;;
@@ -54,9 +58,11 @@ for a in "${args[@]}"; do
elif [ -f "$a" ]; then files+=("$a")
else echo "run.sh: no such file or folder: $a" >&2; exit 2; fi
done
-[ -x build/bin/zy ] || { echo "run.sh: build/bin/zy is missing; run make first" >&2; exit 2; }
+case $zy in /*) ;; *) zy=$PWD/$zy ;; esac
+case $W in /*) ;; *) W=$PWD/$W ;; esac
+[ -x "$zy" ] || { echo "run.sh: $zy is missing; run make first" >&2; exit 2; }
[ $zym = 0 ] || [ -x build/bin/zym ] || { echo "run.sh: build/bin/zym is missing; run make first" >&2; exit 2; }
-W=build/conformance; mkdir -p "$W"
+mkdir -p "$W"
known=$conf/known.txt
declare -A cnt
@@ -109,15 +115,15 @@ done
run_one() { # file name impl binary
local f=$1 name=$2 impl=$3 bin=$4 d out rc
d=$W/$(echo "${name%.zc}" | tr '/' '_'); mkdir -p "$d"; out=$d/out.$impl
- ( cd "$d" && timeout -k 1 "$limit" "$root/$bin" < "$root/$f" > "$root/$out" 2>&1 ); rc=$?
+ ( cd "$d" && timeout -k 1 "$limit" "$bin" < "$root/$f" > "$out" 2>&1 ); rc=$?
if [ $rc = 124 ]; then emit "$name" "$impl" FAIL "timed out after ${limit}s"; return; fi
if check "$f" "$out"; then emit "$name" "$impl" ok ""; else emit "$name" "$impl" FAIL "$detail"; fi
}
for f in "${files[@]}"; do
case $f in "$conf"/*) name=${f#"$conf"/} ;; *) name=$f ;; esac
head -n1 "$f" | grep -q '^// expect\( error\)\?: ' || continue
- run_one "$f" "$name" zy build/bin/zy
- [ $zym = 0 ] || run_one "$f" "$name" zym build/bin/zym
+ run_one "$f" "$name" zy "$zy"
+ [ $zym = 0 ] || run_one "$f" "$name" zym "$root/build/bin/zym"
done
# zc0 through parity.sh: one call for every program that is meant for it
diff --git a/tests/test.sh b/tests/test.sh
index 22fdf30..4c6d6a9 100755
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -231,6 +231,10 @@ s_interp() {
T=$ROOT/interp
$CC -pthread -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c $GI -o $T/zy
run $T/zy "interp"
+ # docs/SPEC.md conformance programs; failures listed in tests/conformance/known.txt do not count
+ bash tests/conformance/run.sh --zy $T/zy -w $T/conformance -q > $T/conformance.out 2>&1; r=$?
+ grep '^FAIL' $T/conformance.out
+ chk $r 0 "interp conformance suite: $(grep '^ total' $T/conformance.out | sed 's/ */ /g')"
python3 tests/drivers/array_methods_test.py $T/zy > $T/arrays.out 2>&1; r=$?
grep -v '^ok' $T/arrays.out
chk $r 0 "native array receiver, algorithm and ownership contracts"