26-fn2-pattern.M1pp (1801B)
1 # %fn2 / %stl / %ldl — the intended P1pp-side ergonomic pattern built 2 # on %struct + %frame + %endframe + %local. 3 # 4 # %fn2(name, locals, body) synthesizes <name>_FRAME from `locals`, 5 # emits the function label, opens %scope+%frame around the body, and 6 # brackets it with %enter sized from <name>_FRAME.SIZE plus %eret. 7 # 8 # %stl(reg, local) / %ldl(reg, local) store/load a named local via 9 # %local(name), which resolves against the currently active frame. 10 # 11 # A nested %scope inside the body affects ::label resolution but does 12 # NOT affect %local — locals stay bound to the function's frame. 13 # 14 # %enter, %eret, %st, %ld, %b, %beqz are stubbed as plain text-emitting 15 # macros so the test isolates the macro-composition behavior rather 16 # than depending on real P1 encodings. 17 18 %macro enter(size) 19 ENTER size 20 %endm 21 22 %macro eret() 23 ERET 24 %endm 25 26 %macro st(rs, base, off) 27 ST rs base off 28 %endm 29 30 %macro ld(rd, base, off) 31 LD rd base off 32 %endm 33 34 %macro b(target) 35 B target 36 %endm 37 38 %macro beqz(rs, target) 39 BEQZ rs target 40 %endm 41 42 %macro fn2(name, locals, body) 43 %struct name ## _FRAME { locals } 44 LABEL name 45 %scope name 46 %frame name 47 %enter(% ## name ## _FRAME.SIZE) 48 body 49 %eret 50 %endframe 51 %endscope 52 %endm 53 54 %macro stl(reg, local) 55 %st(reg, sp, %local(local)) 56 %endm 57 58 %macro ldl(reg, local) 59 %ld(reg, sp, %local(local)) 60 %endm 61 62 # A function with three named locals. Demonstrates: 63 # - %enter sized from the synthesized print_FRAME.SIZE = 24 64 # - %stl/%ldl resolving names a/b/c to offsets 0/8/16 65 # - a nested %scope (loop) for ::label resolution coexisting with the 66 # outer %frame, so %ldl(s0, a) inside the loop still hits offset 0 67 # (print_FRAME.a) rather than anything tied to the loop scope. 68 %fn2(print, {a b c}, { 69 %stl(s0, a) 70 %stl(s1, b) 71 %stl(s2, c) 72 %scope loop 73 ::top 74 %ldl(s0, a) 75 %beqz(s0, &::top) 76 %endscope 77 }) 78 79 END