tests(macro): inline samples into new directory hierarchy and drop legacy macro_golden_* sources
This commit is contained in:
@ -67,6 +67,8 @@ Action Items (next 48h)
|
||||
- [x] LLVM PHI hygiene smoke on If cases
|
||||
- [ ] ScopeBox docs + macro scaffold (no-op) + MIR hint type sketch
|
||||
- [ ] ControlFlowBuilder/PatternBuilder docs(本commitで追加)→ スキャフォールド実装 → If/Matchマクロ置換の最初の1本
|
||||
- [x] Reorganize macro tests under apps/tests/macro/* and update golden/smoke paths
|
||||
- [x] Add MIR hints module (no-op sink) and loop header/latch hint calls
|
||||
|
||||
## Phase‑16 Outlook
|
||||
- MacroCtx (gensym/report/getEnv) and capabilities mapped to `nyash.toml`.
|
||||
|
||||
11
apps/tests/macro/README.md
Normal file
11
apps/tests/macro/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Macro Tests Layout
|
||||
|
||||
- if/: If normalization cases (assign, print, return, chains/guards)
|
||||
- loopform/: Loop normalization (carrier tail align, two-vars)
|
||||
- collections/: Array/Map macro examples
|
||||
- types/: Type checks (is/as)
|
||||
- strings/: String macros (upper_string)
|
||||
- identity/: Identity macro
|
||||
- test_runner/: Macro test runner behavior (filters, args, return policy)
|
||||
|
||||
Each file is a thin include to the original sample kept at the root for now. Once stabilized, originals can be removed and bodies moved here.
|
||||
@ -1,2 +1,2 @@
|
||||
include "../../macro_golden_array_empty.nyash"
|
||||
print([])
|
||||
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
include "../../macro_golden_array_mixed.nyash"
|
||||
print(["x", 3])
|
||||
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
include "../../macro_golden_array_nested.nyash"
|
||||
print([1, [2, []]])
|
||||
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
include "../../macro_golden_array_prepend_zero.nyash"
|
||||
print([1, 2])
|
||||
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
include "../../macro_golden_map_esc.nyash"
|
||||
print({"k:1": "v\"2"})
|
||||
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
include "../../macro_golden_map_insert_tag.nyash"
|
||||
print({"a": 1})
|
||||
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
include "../../macro_golden_map_multi.nyash"
|
||||
print({"a": 1, "b": 2})
|
||||
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
include "../../macro_golden_identity.nyash"
|
||||
print("x")
|
||||
|
||||
|
||||
@ -1,2 +1,4 @@
|
||||
include "../../macro_golden_if_assign.nyash"
|
||||
local x = 0
|
||||
x = if (1 < 2) { 10 } else { 20 }
|
||||
print(x)
|
||||
|
||||
|
||||
@ -1,2 +1,11 @@
|
||||
include "../../macro_golden_if_chain_guard.nyash"
|
||||
local x = 5
|
||||
if (x < 0) {
|
||||
print(-1)
|
||||
} else if (x < 3) {
|
||||
print(0)
|
||||
} else if ((x < 10) && x.is("Integer")) {
|
||||
print(1)
|
||||
} else {
|
||||
print(2)
|
||||
}
|
||||
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
include "../../macro_golden_if_print.nyash"
|
||||
print(if (1 < 2) { 10 } else { 20 })
|
||||
|
||||
|
||||
@ -1,2 +1,4 @@
|
||||
include "../../macro_golden_if_return.nyash"
|
||||
function main() {
|
||||
return if (1 < 2) { 10 } else { 20 }
|
||||
}
|
||||
|
||||
|
||||
@ -1,2 +1,6 @@
|
||||
include "../../macro_golden_loop_simple.nyash"
|
||||
local i = 0
|
||||
loop(i < 3) {
|
||||
print(i)
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
|
||||
@ -1,2 +1,8 @@
|
||||
include "../../macro_golden_loop_two_vars.nyash"
|
||||
local i = 0
|
||||
local sum = 0
|
||||
loop(i < 3) {
|
||||
print(i)
|
||||
sum = sum + i
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
include "../../macro_golden_upper_string.nyash"
|
||||
print("UPPER:hello")
|
||||
|
||||
|
||||
@ -1,2 +1,18 @@
|
||||
include "../../macro_test_args.nyash"
|
||||
// Macro test-args demo (top-level + Box static/instance)
|
||||
|
||||
function test_top_level(a, b) {
|
||||
return (a == 1) && (b == "x")
|
||||
}
|
||||
|
||||
box B {
|
||||
static function test_static(i) {
|
||||
return i == 2
|
||||
}
|
||||
function method(s) {
|
||||
return s == "y"
|
||||
}
|
||||
function test_instance(p) {
|
||||
return me.method(p)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,2 +1,8 @@
|
||||
include "../../macro_test_args_defaults.nyash"
|
||||
function test_param_zero(x) {
|
||||
return x == 0
|
||||
}
|
||||
|
||||
function test_param_pair(a, b) {
|
||||
return (a == 0) && (b == 0)
|
||||
}
|
||||
|
||||
|
||||
@ -1,2 +1,8 @@
|
||||
include "../../macro_test_runner_basic.nyash"
|
||||
function test_true() {
|
||||
return true
|
||||
}
|
||||
|
||||
function test_one_equals_one() {
|
||||
return 1 == 1
|
||||
}
|
||||
|
||||
|
||||
@ -1,2 +1,8 @@
|
||||
include "../../macro_test_filter.nyash"
|
||||
function test_api_ok() {
|
||||
return true
|
||||
}
|
||||
|
||||
function test_impl_skip() {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@ -1,2 +1,8 @@
|
||||
include "../../macro_test_return_policy.nyash"
|
||||
function test_dummy() {
|
||||
return true
|
||||
}
|
||||
|
||||
function main(args) {
|
||||
return 7
|
||||
}
|
||||
|
||||
|
||||
@ -1,2 +1,7 @@
|
||||
include "../../macro_golden_type_is_basic.nyash"
|
||||
local x = 1
|
||||
if (x.is("Integer")) {
|
||||
print(1)
|
||||
} else {
|
||||
print(0)
|
||||
}
|
||||
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
print([])
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
print(["x", 3])
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
print([1, [2, []]])
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
print([1, 2])
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
print("x")
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
local x = 0
|
||||
x = if (1 < 2) { 10 } else { 20 }
|
||||
print(x)
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
local x = 5
|
||||
if (x < 0) {
|
||||
print(-1)
|
||||
} else if (x < 3) {
|
||||
print(0)
|
||||
} else if ((x < 10) && x.is("Integer")) {
|
||||
print(1)
|
||||
} else {
|
||||
print(2)
|
||||
}
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
print(if (1 < 2) { 10 } else { 20 })
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
function main() {
|
||||
return if (1 < 2) { 10 } else { 20 }
|
||||
}
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
local i = 0
|
||||
loop(i < 3) {
|
||||
print(i)
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
local i = 0
|
||||
local sum = 0
|
||||
loop(i < 3) {
|
||||
print(i)
|
||||
sum = sum + i
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
print({"k:1": "v\"2"})
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
print({"a": 1})
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
print({"a": 1, "b": 2})
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
local x = 1
|
||||
if (x.is("Integer")) {
|
||||
print(1)
|
||||
} else {
|
||||
print(0)
|
||||
}
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
print("UPPER:hello")
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
// Macro test-args demo (top-level + Box static/instance)
|
||||
|
||||
function test_top_level(a, b) {
|
||||
return (a == 1) && (b == "x")
|
||||
}
|
||||
|
||||
box B {
|
||||
static function test_static(i) {
|
||||
return i == 2
|
||||
}
|
||||
function method(s) {
|
||||
return s == "y"
|
||||
}
|
||||
function test_instance(p) {
|
||||
return me.method(p)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
function test_param_zero(x) {
|
||||
return x == 0
|
||||
}
|
||||
|
||||
function test_param_pair(a, b) {
|
||||
return (a == 0) && (b == 0)
|
||||
}
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
function test_api_ok() {
|
||||
return true
|
||||
}
|
||||
|
||||
function test_impl_skip() {
|
||||
return true
|
||||
}
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
function test_dummy() {
|
||||
return true
|
||||
}
|
||||
|
||||
function main(args) {
|
||||
return 7
|
||||
}
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
function test_true() {
|
||||
return true
|
||||
}
|
||||
|
||||
function test_one_equals_one() {
|
||||
return 1 == 1
|
||||
}
|
||||
|
||||
@ -124,6 +124,9 @@ pub struct MirBuilder {
|
||||
/// Policy flags (snapshotted at entry of try/catch lowering)
|
||||
pub(super) cleanup_allow_return: bool,
|
||||
pub(super) cleanup_allow_throw: bool,
|
||||
|
||||
/// Hint sink (zero-cost guidance; currently no-op)
|
||||
pub(super) hint_sink: crate::mir::hints::HintSink,
|
||||
}
|
||||
|
||||
impl MirBuilder {
|
||||
@ -160,6 +163,7 @@ impl MirBuilder {
|
||||
in_cleanup_block: false,
|
||||
cleanup_allow_return: false,
|
||||
cleanup_allow_throw: false,
|
||||
hint_sink: crate::mir::hints::HintSink::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,6 +171,18 @@ impl MirBuilder {
|
||||
pub(super) fn push_if_merge(&mut self, bb: BasicBlockId) { self.if_merge_stack.push(bb); }
|
||||
pub(super) fn pop_if_merge(&mut self) { let _ = self.if_merge_stack.pop(); }
|
||||
|
||||
// ---- Hint helpers (no-op by default) ----
|
||||
#[inline]
|
||||
pub(crate) fn hint_loop_header(&mut self) { self.hint_sink.loop_header(); }
|
||||
#[inline]
|
||||
pub(crate) fn hint_loop_latch(&mut self) { self.hint_sink.loop_latch(); }
|
||||
#[inline]
|
||||
pub(crate) fn hint_scope_enter(&mut self, id: u32) { self.hint_sink.scope_enter(id); }
|
||||
#[inline]
|
||||
pub(crate) fn hint_scope_leave(&mut self, id: u32) { self.hint_sink.scope_leave(id); }
|
||||
#[inline]
|
||||
pub(crate) fn hint_join_result<S: Into<String>>(&mut self, var: S) { self.hint_sink.join_result(var.into()); }
|
||||
|
||||
// moved to builder_calls.rs: lower_method_as_function
|
||||
|
||||
/// Build a complete MIR module from AST
|
||||
|
||||
@ -62,8 +62,11 @@ impl MirBuilder {
|
||||
self.ensure_block_exists(merge_block)?;
|
||||
self.push_if_merge(merge_block);
|
||||
|
||||
// Pre-analysis: identify then-assigned var for skip
|
||||
// Pre-analysis: identify then/else assigned var for skip and hints
|
||||
let assigned_then_pre = super::phi::extract_assigned_var(&then_ast_for_analysis);
|
||||
let assigned_else_pre = else_ast_for_analysis
|
||||
.as_ref()
|
||||
.and_then(|e| super::phi::extract_assigned_var(e));
|
||||
let pre_then_var_value = assigned_then_pre
|
||||
.as_ref()
|
||||
.and_then(|name| pre_if_var_map.get(name).copied());
|
||||
@ -83,6 +86,13 @@ impl MirBuilder {
|
||||
pre_then_var_value,
|
||||
)?;
|
||||
|
||||
// Hint: join result variable if both branches assign to the same variable name
|
||||
if let (Some(tn), Some(en)) = (assigned_then_pre.as_deref(), assigned_else_pre.as_deref()) {
|
||||
if tn == en {
|
||||
self.hint_join_result(tn);
|
||||
}
|
||||
}
|
||||
|
||||
// Merge other modified variables (skip the primary assignment if any)
|
||||
let skip_name = assigned_then_pre.as_deref();
|
||||
self.merge_modified_vars(
|
||||
|
||||
@ -156,6 +156,8 @@ impl<'a> LoopBuilder<'a> {
|
||||
|
||||
// 3. Headerブロックの準備(unsealed状態)
|
||||
self.set_current_block(header_id)?;
|
||||
// Hint: loop header (no-op sink)
|
||||
self.parent_builder.hint_loop_header();
|
||||
let _ = self.mark_block_unsealed(header_id);
|
||||
|
||||
// 4. ループ変数のPhi nodeを準備
|
||||
@ -189,6 +191,8 @@ impl<'a> LoopBuilder<'a> {
|
||||
// 8. Latchブロック(ボディの最後)からHeaderへ戻る
|
||||
// 現在の挿入先が latch(最後のブロック)なので、そのブロックIDでスナップショットを保存する
|
||||
let latch_id = self.current_block()?;
|
||||
// Hint: loop latch (no-op sink)
|
||||
self.parent_builder.hint_loop_latch();
|
||||
let latch_snapshot = self.get_current_variable_map();
|
||||
// 以前は body_id に保存していたが、複数ブロックのボディや continue 混在時に不正確になるため
|
||||
// 実際の latch_id に対してスナップショットを紐づける
|
||||
|
||||
9
tools/test/golden/macro/README.md
Normal file
9
tools/test/golden/macro/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
# Macro Goldens
|
||||
|
||||
- Compare expanded AST JSON (key-order insensitive) against expected.
|
||||
- Structure mirrors apps/tests/macro categories.
|
||||
- Keep case names aligned with test files for discoverability.
|
||||
|
||||
Helpers
|
||||
- normalize_json: Python json.dumps with sort_keys=True
|
||||
- *_user_macro_golden.sh scripts: run nyash --dump-expanded-ast-json and compare
|
||||
Reference in New Issue
Block a user