mirror of
https://github.com/imjasonh/nescript
synced 2026-07-09 01:16:12 +00:00
M2: Add call graph analysis, recursion detection, and optimizer
Analyzer extensions: - Call graph construction from function bodies and state handlers - DFS-based recursion detection (direct and mutual) with E0402 errors - Max call depth computation per entry point with E0401 enforcement - Function declarations registered as symbols (E0503 for undefined calls) - Collects calls from all statement/expression types recursively Optimizer (new module): - Constant folding: evaluate known-constant arithmetic at compile time - Dead code elimination: remove ops with unused destination temps - Both operate per-basic-block in a single pass 171 tests total (22 new: 6 analyzer + 11 IR lowering + 5 optimizer) https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
This commit is contained in:
parent
664ccc05db
commit
192d9c5c3d
9 changed files with 914 additions and 23 deletions
|
|
@ -42,7 +42,11 @@ fn lower_var_assignment() {
|
|||
start Main
|
||||
"#,
|
||||
);
|
||||
let frame_fn = ir.functions.iter().find(|f| f.name.contains("frame")).unwrap();
|
||||
let frame_fn = ir
|
||||
.functions
|
||||
.iter()
|
||||
.find(|f| f.name.contains("frame"))
|
||||
.unwrap();
|
||||
// Should have a StoreVar op
|
||||
let has_store = frame_fn
|
||||
.blocks
|
||||
|
|
@ -62,7 +66,11 @@ fn lower_plus_assign() {
|
|||
start Main
|
||||
"#,
|
||||
);
|
||||
let frame_fn = ir.functions.iter().find(|f| f.name.contains("frame")).unwrap();
|
||||
let frame_fn = ir
|
||||
.functions
|
||||
.iter()
|
||||
.find(|f| f.name.contains("frame"))
|
||||
.unwrap();
|
||||
let has_add = frame_fn
|
||||
.blocks
|
||||
.iter()
|
||||
|
|
@ -83,12 +91,19 @@ fn lower_if_creates_branch() {
|
|||
start Main
|
||||
"#,
|
||||
);
|
||||
let frame_fn = ir.functions.iter().find(|f| f.name.contains("frame")).unwrap();
|
||||
let frame_fn = ir
|
||||
.functions
|
||||
.iter()
|
||||
.find(|f| f.name.contains("frame"))
|
||||
.unwrap();
|
||||
let has_branch = frame_fn
|
||||
.blocks
|
||||
.iter()
|
||||
.any(|b| matches!(&b.terminator, IrTerminator::Branch(..)));
|
||||
assert!(has_branch, "if statement should produce a Branch terminator");
|
||||
assert!(
|
||||
has_branch,
|
||||
"if statement should produce a Branch terminator"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -103,7 +118,11 @@ fn lower_while_creates_loop() {
|
|||
start Main
|
||||
"#,
|
||||
);
|
||||
let frame_fn = ir.functions.iter().find(|f| f.name.contains("frame")).unwrap();
|
||||
let frame_fn = ir
|
||||
.functions
|
||||
.iter()
|
||||
.find(|f| f.name.contains("frame"))
|
||||
.unwrap();
|
||||
// A while loop needs at least 3 blocks: condition check, body, and exit
|
||||
assert!(
|
||||
frame_fn.blocks.len() >= 3,
|
||||
|
|
@ -124,7 +143,11 @@ fn lower_button_read() {
|
|||
start Main
|
||||
"#,
|
||||
);
|
||||
let frame_fn = ir.functions.iter().find(|f| f.name.contains("frame")).unwrap();
|
||||
let frame_fn = ir
|
||||
.functions
|
||||
.iter()
|
||||
.find(|f| f.name.contains("frame"))
|
||||
.unwrap();
|
||||
let has_input = frame_fn
|
||||
.blocks
|
||||
.iter()
|
||||
|
|
@ -144,7 +167,11 @@ fn lower_draw_sprite() {
|
|||
start Main
|
||||
"#,
|
||||
);
|
||||
let frame_fn = ir.functions.iter().find(|f| f.name.contains("frame")).unwrap();
|
||||
let frame_fn = ir
|
||||
.functions
|
||||
.iter()
|
||||
.find(|f| f.name.contains("frame"))
|
||||
.unwrap();
|
||||
let has_draw = frame_fn
|
||||
.blocks
|
||||
.iter()
|
||||
|
|
@ -164,7 +191,11 @@ fn lower_constants_become_immediates() {
|
|||
start Main
|
||||
"#,
|
||||
);
|
||||
let frame_fn = ir.functions.iter().find(|f| f.name.contains("frame")).unwrap();
|
||||
let frame_fn = ir
|
||||
.functions
|
||||
.iter()
|
||||
.find(|f| f.name.contains("frame"))
|
||||
.unwrap();
|
||||
// SPEED should be lowered to LoadImm(_, 3)
|
||||
let has_imm3 = frame_fn
|
||||
.blocks
|
||||
|
|
@ -232,7 +263,11 @@ fn lower_wait_frame() {
|
|||
start Main
|
||||
"#,
|
||||
);
|
||||
let frame_fn = ir.functions.iter().find(|f| f.name.contains("frame")).unwrap();
|
||||
let frame_fn = ir
|
||||
.functions
|
||||
.iter()
|
||||
.find(|f| f.name.contains("frame"))
|
||||
.unwrap();
|
||||
let has_wait = frame_fn
|
||||
.blocks
|
||||
.iter()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue