diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2023-11-11 23:13:43 +0200 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2023-11-12 00:40:00 +0200 |
| commit | 6f68c0febdbfd6138fa95f77bc09785bde8a8371 (patch) | |
| tree | 8f622e64ddbfa132e9fa991bb3e5961b72f826bb | |
| parent | f7dd9705d44b9cee5103b267797c0449d42319df (diff) | |
Add function defs & calls
| -rw-r--r-- | asm/atk16.py | 4 | ||||
| -rw-r--r-- | asm/test_py_src.atk16 | 266 | ||||
| -rw-r--r-- | asm/test_py_src.atk16_optimized | 161 | ||||
| -rw-r--r-- | asm/test_py_src.py | 20 | ||||
| -rw-r--r-- | digital/atk16_mem.dig | 421 | ||||
| -rw-r--r-- | src/ast_compiler.py | 289 |
6 files changed, 821 insertions, 340 deletions
diff --git a/asm/atk16.py b/asm/atk16.py index 6d9bc10..9a5921c 100644 --- a/asm/atk16.py +++ b/asm/atk16.py @@ -20,3 +20,7 @@ def call_inline(expr: T) -> T: def asm(asm: str): """Inject ATK16 assembly `asm` into the compiled output.""" return NotImplemented + +def ord(char: Char) -> int: + """Convert char to int""" + return NotImplemented diff --git a/asm/test_py_src.atk16 b/asm/test_py_src.atk16 index ca44267..02752ec 100644 --- a/asm/test_py_src.atk16 +++ b/asm/test_py_src.atk16 @@ -73,50 +73,256 @@ ;; END BOOTSTRAP +@label text_mode + 1 +@label graphics_mode_addr_p + 23 +@label text_mem_addr_p + 25 +@label int_1 + 104 +@label int_2 + 105 - -; <ast.FunctionDef object at 0x100c7b310> +; <ast.FunctionDef object at 0x1032fef50> @label func -; stack frame: ['arg1', 'arg2', 'a'] +; stack frame names: ['return_address_0', 'arg1', 'arg2', 'a'] addi SP 1 SP -; <ast.Name object at 0x100c7aef0> (arg1) - ldi ${SP - 3} RA +; <ast.Assign object at 0x1032fee30> +; assigning a to stack segment + offset 7 +; <ast.Name object at 0x1032fedd0> (arg1) + ldi vt_stack_addr RC + ldr RC RC + ldi 5 RD + add RC RD RC + ldr RC RC + spu RC + ldi vt_stack_addr RA + ldr RA RA + ldi 7 RB + add RA RB RA + spo RB + str RB RA +; <ast.Return object at 0x1032feda0> + ldi vt_stack_addr RA + ldr RA RA + ldi 4 RB + add RA RB RA +; <ast.Add object at 0x10301ab60> +; BinOp lhs <ast.BinOp object at 0x1032fed70> +; <ast.Name object at 0x1032fed40> (a) + ldi vt_stack_addr RC + ldr RC RC + ldi 7 RD + add RC RD RC + ldr RC RC + spu RC +; BinOp rhs <ast.BinOp object at 0x1032fed70> +; <ast.Name object at 0x1032fed10> (a) + ldi vt_stack_addr RC + ldr RC RC + ldi 7 RD + add RC RD RC + ldr RC RC + spu RC + spo RD + spo RC + add RC RD RC + spu RC + spo RB + mov RA SP + ldr RA RA + spu RB +; return from function + jpr RA + +@label main +; stack frame names: ['i', 'graphics_mode_addr', 'text_mem_addr', 'b'] + addi SP 4 SP +; <ast.Assign object at 0x103067b80> +; assigning graphics_mode_addr to stack segment + offset 1 +; <ast.Call object at 0x1030677f0> +; Builtin call load [<ast.Name object at 0x103067fa0>] +; <ast.Name object at 0x103067fa0> (GRAPHICS_MODE_ADDR_P) + ldi graphics_mode_addr_p RC + ldr RC RC + spu RC + spo RC + ldr RC RC + spu RC + ldi vt_stack_addr RA + ldr RA RA + ldi 1 RB + add RA RB RA + spo RB + str RB RA +; <ast.Assign object at 0x103067790> +; assigning text_mem_addr to stack segment + offset 2 +; <ast.Call object at 0x103067220> +; Builtin call load [<ast.Name object at 0x103067f40>] +; <ast.Name object at 0x103067f40> (TEXT_MEM_ADDR_P) + ldi text_mem_addr_p RC + ldr RC RC + spu RC + spo RC + ldr RC RC + spu RC + ldi vt_stack_addr RA + ldr RA RA + ldi 2 RB + add RA RB RA + spo RB + str RB RA +; <ast.Call object at 0x1030673d0> +; Builtin call store [<ast.Name object at 0x1032fefb0>, <ast.Name object at 0x1032fef80>] +; <ast.Name object at 0x1032fefb0> (graphics_mode_addr) + ldi vt_stack_addr RA + ldr RA RA + ldi 1 RB + add RA RB RA ldr RA RA spu RA +; <ast.Name object at 0x1032fef80> (TEXT_MODE) + ldi text_mode RA + ldr RA RA + spu RA + spo RB spo RA - ldi ${SP - 1} RB - str RA RB -; <ast.Return object at 0x100c7b0a0> -; <ast.BinOp object at 0x100c7b370> -; BinOp lhs <ast.BinOp object at 0x100c7b370> -; <ast.Name object at 0x100c7b3a0> (a) - ldi ${SP - 1} RA + str RB RA +; <ast.Assign object at 0x1032fecb0> +; assigning b to stack segment + offset 3 +; <ast.Call object at 0x1032fec50> +; Call function func + ldi 0 RC + spu RC +; <ast.Constant object at 0x1032febf0> + ldi 1 RC + spu RC +; <ast.Constant object at 0x1032febc0> + ldi 3 RC + spu RC +; set up return address and jump to subroutine + subi SP 3 RC + lpc RD + addi RD 3 RD + str RD RC + jpi func + ldi vt_stack_addr RA + ldr RA RA + ldi 3 RB + add RA RB RA + spo RB + str RB RA +; <ast.Assign object at 0x1032feb90> +; assigning i to stack segment + offset 0 +; <ast.Constant object at 0x1032feb30> + ldi 0 RC + spu RC + ldi vt_stack_addr RA + ldr RA RA + ldi 0 RB + add RA RB RA + spo RB + str RB RA +; <ast.Call object at 0x1032fead0> +; Builtin call store [<ast.BinOp object at 0x1032fea40>, <ast.Call object at 0x1032fe9b0>] +; <ast.Add object at 0x10301ab60> +; BinOp lhs <ast.BinOp object at 0x1032fea40> +; <ast.Name object at 0x1032fea10> (text_mem_addr) + ldi vt_stack_addr RA + ldr RA RA + ldi 2 RB + add RA RB RA ldr RA RA spu RA -; BinOp rhs <ast.BinOp object at 0x100c7b370> -; <ast.Name object at 0x100c7b3d0> (a) - ldi ${SP - 1} RA +; BinOp rhs <ast.BinOp object at 0x1032fea40> +; <ast.Name object at 0x1032fe9e0> (i) + ldi vt_stack_addr RA + ldr RA RA + ldi 0 RB + add RA RB RA ldr RA RA spu RA spo RB spo RA add RA RB RA spu RA - subi SP 1 SP - rsr - -@label main -; stack frame: ['b'] - addi SP 1 SP -; <ast.Call object at 0x100c7b520> -; <ast.Constant object at 0x100c7b580> - ldi 1 RA +; <ast.Call object at 0x1032fe9b0> +; Builtin call ord [<ast.Constant object at 0x1032fe920>] +; <ast.Constant object at 0x1032fe920> + ldi int_1 RA + ldr RA RA + spu RA + spo RB + spo RA + str RB RA +; <ast.Assign object at 0x1032fe8f0> +; assigning i to stack segment + offset 0 +; <ast.Add object at 0x10301ab60> +; BinOp lhs <ast.BinOp object at 0x1032fe890> +; <ast.Name object at 0x1032fe860> (i) + ldi vt_stack_addr RC + ldr RC RC + ldi 0 RD + add RC RD RC + ldr RC RC + spu RC +; BinOp rhs <ast.BinOp object at 0x1032fe890> +; <ast.Constant object at 0x1032fe830> + ldi 1 RC + spu RC + spo RD + spo RC + add RC RD RC + spu RC + ldi vt_stack_addr RA + ldr RA RA + ldi 0 RB + add RA RB RA + spo RB + str RB RA +; <ast.Call object at 0x1032fe7d0> +; Builtin call store [<ast.BinOp object at 0x1032fe740>, <ast.Call object at 0x1032fe6b0>] +; <ast.Add object at 0x10301ab60> +; BinOp lhs <ast.BinOp object at 0x1032fe740> +; <ast.Name object at 0x1032fe710> (text_mem_addr) + ldi vt_stack_addr RA + ldr RA RA + ldi 2 RB + add RA RB RA + ldr RA RA + spu RA +; BinOp rhs <ast.BinOp object at 0x1032fe740> +; <ast.Name object at 0x1032fe6e0> (i) + ldi vt_stack_addr RA + ldr RA RA + ldi 0 RB + add RA RB RA + ldr RA RA spu RA -; <ast.Constant object at 0x100c7b5b0> - ldi 3 RA + spo RB + spo RA + add RA RB RA + spu RA +; <ast.Call object at 0x1032fe6b0> +; Builtin call ord [<ast.Constant object at 0x1032fe620>] +; <ast.Constant object at 0x1032fe620> + ldi int_2 RA + ldr RA RA spu RA - csi func + spo RB spo RA - ldi ${SP - 1} RB - str RA RB - subi SP 1 SP + str RB RA +; <ast.While object at 0x1032fe5f0> +@label while_test_3 +; <ast.Constant object at 0x1032fe5c0> + ldi 1 RB + spu RB + spo RA + addi RA 0 RA + bri zero While_else_4 +; <ast.Pass object at 0x1032fe590> + jpi While_test_3 +@label while_else_4 +@label while_end_5 + subi SP 4 SP diff --git a/asm/test_py_src.atk16_optimized b/asm/test_py_src.atk16_optimized index 4a65ec4..601dfad 100644 --- a/asm/test_py_src.atk16_optimized +++ b/asm/test_py_src.atk16_optimized @@ -58,28 +58,157 @@ ldi gr_disabled_mode RB str RB RA jpi main +@label text_mode + 1 +@label graphics_mode_addr_p + 23 +@label text_mem_addr_p + 25 +@label int_1 + 104 +@label int_2 + 105 @label func addi SP 1 SP - ldi ${SP - 3} RA + ldi vt_stack_addr RC + ldr RC RC + ldi 5 RD + add RC RD RC + ldr RC RC + spu RC + ldi vt_stack_addr RA ldr RA RA - ldi ${SP - 1} RB - str RA RB - ldi ${SP - 1} RA + ldi 7 RB + add RA RB RA + spo RB + str RB RA + ldi vt_stack_addr RA ldr RA RA - ldi ${SP - 1} RB - ldr RB RB + ldi 4 RB add RA RB RA - spu RA - subi SP 1 SP - rsr + ldi vt_stack_addr RC + ldr RC RC + ldi 7 RD + add RC RD RC + ldr RC RC + spu RC + ldi vt_stack_addr RC + ldr RC RC + ldi 7 RD + add RC RD RC + ldr RC RD + spo RC + add RC RD RB + mov RA SP + ldr RA RA + spu RB + jpr RA @label main - addi SP 1 SP - ldi 1 RA + addi SP 4 SP + ldi graphics_mode_addr_p RC + ldr RC RC + ldr RC RC + spu RC + ldi vt_stack_addr RA + ldr RA RA + ldi 1 RB + add RA RB RA + spo RB + str RB RA + ldi text_mem_addr_p RC + ldr RC RC + ldr RC RC + spu RC + ldi vt_stack_addr RA + ldr RA RA + ldi 2 RB + add RA RB RA + spo RB + str RB RA + ldi vt_stack_addr RA + ldr RA RA + ldi 1 RB + add RA RB RA + ldr RA RA + ldi text_mode RB + ldr RB RB + str RB RA + ldi 0 RC + spu RC + ldi 1 RC + spu RC + ldi 3 RC + spu RC + subi SP 3 RC + lpc RD + addi RD 3 RD + str RD RC + jpi func + ldi vt_stack_addr RA + ldr RA RA + ldi 3 RB + add RA RB RA + spo RB + str RB RA + ldi 0 RC + spu RC + ldi vt_stack_addr RA + ldr RA RA + ldi 0 RB + add RA RB RA + spo RB + str RB RA + ldi vt_stack_addr RA + ldr RA RA + ldi 2 RB + add RA RB RA + ldr RA RA spu RA - ldi 3 RA + ldi vt_stack_addr RA + ldr RA RA + ldi 0 RB + add RA RB RA + ldr RA RB + spo RA + add RA RB RA + ldi int_1 RB + ldr RB RB + str RB RA + ldi vt_stack_addr RC + ldr RC RC + ldi 0 RD + add RC RD RC + ldr RC RC + ldi 1 RD + add RC RD RC + spu RC + ldi vt_stack_addr RA + ldr RA RA + ldi 0 RB + add RA RB RA + spo RB + str RB RA + ldi vt_stack_addr RA + ldr RA RA + ldi 2 RB + add RA RB RA + ldr RA RA spu RA - csi func + ldi vt_stack_addr RA + ldr RA RA + ldi 0 RB + add RA RB RA + ldr RA RB spo RA - ldi ${SP - 1} RB - str RA RB - subi SP 1 SP
\ No newline at end of file + add RA RB RA + ldi int_2 RB + ldr RB RB + str RB RA +@label while_test_3 + ldi 1 RA + addi RA 0 RA + bri zero While_else_4 + jpi While_test_3 +@label while_else_4 +@label while_end_5 + subi SP 4 SP
\ No newline at end of file diff --git a/asm/test_py_src.py b/asm/test_py_src.py index 9af944e..ca816de 100644 --- a/asm/test_py_src.py +++ b/asm/test_py_src.py @@ -1,11 +1,31 @@ import atk16 +TEXT_MODE: atk16.ConstInt = 1 +GRAPHICS_MODE_ADDR_P: atk16.ConstInt = 0x17 +graphics_mode_addr = atk16.load(GRAPHICS_MODE_ADDR_P) + +TEXT_MEM_ADDR_P: atk16.ConstInt = 0x19 +text_mem_addr = atk16.load(TEXT_MEM_ADDR_P) + +atk16.store(graphics_mode_addr, TEXT_MODE) + def func(arg1: int, arg2: int) -> int: a = arg1 return a + a b = func(1, 3) +i = 0 +atk16.store(text_mem_addr + i, atk16.ord("h")) +i = i + 1 +atk16.store(text_mem_addr + i, atk16.ord("i")) + +while True: + pass + +# atk16.asm("@label keepalive") +# atk16.asm(" jpi keepalive") + # TEXT_MODE: atk16.ConstInt = 1 # GRAPHICS_MODE_ADDR: atk16.ConstInt = 0x17 diff --git a/digital/atk16_mem.dig b/digital/atk16_mem.dig index 356500f..d09244e 100644 --- a/digital/atk16_mem.dig +++ b/digital/atk16_mem.dig @@ -1,11 +1,10 @@ -<?xml version="1.0" encoding="utf-8"?> <circuit> <version>2</version> <attributes> <entry> <string>romContent</string> <romList> - <roms/> + <roms /> </romList> </entry> <entry> @@ -35,56 +34,40 @@ </entry> <entry> <string>Data</string> - <data>4014,2c00,6029,13*8000,1c,1a,1a,1a,8000,e000,e001,e002,e800,f800 -,4855,f000,3180,1d88,3188,1d88,4016,2000,2000,4215,2240,3040,1800 -,3188,1d88,3180,1d88,e000,4017,2000,4200,3008,6017,0,0,f800,48 -,f801,45,f802,4c,f803,f804,4f,0,3008,1d89,2f80,51c0,4017,2000 -,4201,3008,1d89,2f80,51c0,4000,3180,1d88,4041,3180,1d88,1d89,2180 -,9e00,1fe0,31b8,1d88,5000,1d89,2180,4000,3180,1d88,403d,3180,1d88 -,4033,2000,3180,1d88,4034,2000,3180,1d88,1d89,2380,1d89,2180,1d89 -,2580,9e00,1fe0,31b8,1d88,5080,1d89,2180,4000,3180,1d88,403d,3180 -,1d88,4035,2000,3180,1d88,4036,2000,3180,1d88,1d89,2380,1d89,2180 -,1d89,2580,9e00,1fe0,31b8,1d88,5080,1d89,2180,4000,3180,1d88,403d -,3180,1d88,4037,2000,3180,1d88,4038,2000,3180,1d88,1d89,2380,1d89 -,2180,1d89,2580,9e00,1fe0,31b8,1d88,5080,1d89,2180,4000,3180,1d88 -,403d,3180,1d88,4039,2000,3180,1d88,4038,2000,3180,1d88,1d89,2380 -,1d89,2180,1d89,2580,9e00,1fe0,31b8,1d88,5080,1d89,2180,4000,3180 -,1d88,403d,3180,1d88,403a,2000,3180,1d88,403b,2000,3180,1d88,1d89 -,2380,1d89,2180,1d89,2580,9e00,1fe0,31b8,1d88,5080,1d89,2180,403c -,2000,3180,1d88,61ff</data> + <data>4014,2c00,6028,8000,8000,8000,8000,8000,8000,8000,8000,8000,8000,8000,8000,8000,001c,001a,001a,001a,8000,e000,e001,e002,e800,f800,4855,f000,3180,1d88,3188,1d88,4016,2000,2000,4215,2240,3040,1d89,2380,1d89,2180,e000,4017,2000,4200,3008,602c,0001,0017,0019,0068,0069,1d88,4414,2480,4605,0498,2480,3190,1d88,4014,2000,4207,0008,1d89,2380,3008,4014,2000,4204,0008,4414,2480,4607,0498,2480,3190,1d88,4414,2480,4607,0498,2680,1d89,2580,0298,1c00,2000,3188,1d88,5000,1da0,4431,2480,2480,3190,1d88,4014,2000,4201,0008,1d89,2380,3008,4432,2480,2480,3190,1d88,4014,2000,4202,0008,1d89,2380,3008,4014,2000,4201,0008,2000,4230,2240,3008,4400,3190,1d88,4401,3190,1d88,4403,3190,1d88,1599,9600,16d8,3098,61aa,4014,2000,4203,0008,1d89,2380,3008,4400,3190,1d88,4014,2000,4200,0008,1d89,2380,3008,4014,2000,4202,0008,2000,3180,1d88,4014,2000,4200,0008,2200,1d89,2180,0008,4233,2240,3008,4414,2480,4600,0498,2480,4601,0498,3190,1d88,4014,2000,4200,0008,1d89,2380,3008,4014,2000,4202,0008,2000,3180,1d88,4014,2000,4200,0008,2200,1d89,2180,0008,4234,2240,3008,4001,1000,8401,61fc,1da1</data> </entry> </elementAttributes> - <pos x="740" y="100"/> + <pos x="740" y="100" /> </visualElement> <visualElement> <elementName>Ground</elementName> <elementAttributes> <entry> <string>rotation</string> - <rotation rotation="1"/> + <rotation rotation="1" /> </entry> </elementAttributes> - <pos x="720" y="160"/> + <pos x="720" y="160" /> </visualElement> <visualElement> <elementName>VDD</elementName> <elementAttributes> <entry> <string>rotation</string> - <rotation rotation="1"/> + <rotation rotation="1" /> </entry> </elementAttributes> - <pos x="720" y="120"/> + <pos x="720" y="120" /> </visualElement> <visualElement> <elementName>VDD</elementName> <elementAttributes> <entry> <string>rotation</string> - <rotation reference="../../../../visualElement[3]/elementAttributes/entry/rotation"/> + <rotation reference="../../../../visualElement[3]/elementAttributes/entry/rotation" /> </entry> </elementAttributes> - <pos x="720" y="180"/> + <pos x="720" y="180" /> </visualElement> <visualElement> <elementName>In</elementName> @@ -102,7 +85,7 @@ <int>16</int> </entry> </elementAttributes> - <pos x="160" y="140"/> + <pos x="160" y="140" /> </visualElement> <visualElement> <elementName>Splitter</elementName> @@ -116,12 +99,12 @@ <string>13,1,1,1</string> </entry> </elementAttributes> - <pos x="220" y="140"/> + <pos x="220" y="140" /> </visualElement> <visualElement> <elementName>atk16_mem_mux.dig</elementName> - <elementAttributes/> - <pos x="320" y="160"/> + <elementAttributes /> + <pos x="320" y="160" /> </visualElement> <visualElement> <elementName>Splitter</elementName> @@ -135,7 +118,7 @@ <string>15</string> </entry> </elementAttributes> - <pos x="320" y="80"/> + <pos x="320" y="80" /> </visualElement> <visualElement> <elementName>Splitter</elementName> @@ -149,7 +132,7 @@ <string>2</string> </entry> </elementAttributes> - <pos x="400" y="160"/> + <pos x="400" y="160" /> </visualElement> <visualElement> <elementName>Demultiplexer</elementName> @@ -163,7 +146,7 @@ <int>15</int> </entry> </elementAttributes> - <pos x="420" y="60"/> + <pos x="420" y="60" /> </visualElement> <visualElement> <elementName>Probe</elementName> @@ -173,7 +156,7 @@ <string>ROM_OUT</string> </entry> </elementAttributes> - <pos x="840" y="100"/> + <pos x="840" y="100" /> </visualElement> <visualElement> <elementName>Driver</elementName> @@ -187,7 +170,7 @@ <boolean>true</boolean> </entry> </elementAttributes> - <pos x="880" y="140"/> + <pos x="880" y="140" /> </visualElement> <visualElement> <elementName>Demultiplexer</elementName> @@ -201,7 +184,7 @@ <boolean>true</boolean> </entry> </elementAttributes> - <pos x="420" y="300"/> + <pos x="420" y="300" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -211,7 +194,7 @@ <string>RAM_IE</string> </entry> </elementAttributes> - <pos x="480" y="320"/> + <pos x="480" y="320" /> </visualElement> <visualElement> <elementName>In</elementName> @@ -233,7 +216,7 @@ <boolean>true</boolean> </entry> </elementAttributes> - <pos x="260" y="500"/> + <pos x="260" y="500" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -243,7 +226,7 @@ <string>CLK</string> </entry> </elementAttributes> - <pos x="180" y="280"/> + <pos x="180" y="280" /> </visualElement> <visualElement> <elementName>RAMDualPort</elementName> @@ -261,59 +244,59 @@ <int>16</int> </entry> </elementAttributes> - <pos x="660" y="280"/> + <pos x="660" y="280" /> </visualElement> <visualElement> <elementName>VDD</elementName> <elementAttributes> <entry> <string>rotation</string> - <rotation rotation="1"/> + <rotation rotation="1" /> </entry> </elementAttributes> - <pos x="640" y="360"/> + <pos x="640" y="360" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> <elementAttributes> <entry> <string>rotation</string> - <rotation rotation="2"/> + <rotation rotation="2" /> </entry> <entry> <string>NetName</string> <string>CLK</string> </entry> </elementAttributes> - <pos x="640" y="340"/> + <pos x="640" y="340" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> <elementAttributes> <entry> <string>rotation</string> - <rotation rotation="2"/> + <rotation rotation="2" /> </entry> <entry> <string>NetName</string> <string>RAM_IE</string> </entry> </elementAttributes> - <pos x="640" y="320"/> + <pos x="640" y="320" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> <elementAttributes> <entry> <string>rotation</string> - <rotation rotation="2"/> + <rotation rotation="2" /> </entry> <entry> <string>NetName</string> <string>DBUS</string> </entry> </elementAttributes> - <pos x="640" y="300"/> + <pos x="640" y="300" /> </visualElement> <visualElement> <elementName>Probe</elementName> @@ -323,7 +306,7 @@ <string>RAM_OUT</string> </entry> </elementAttributes> - <pos x="760" y="280"/> + <pos x="760" y="280" /> </visualElement> <visualElement> <elementName>Driver</elementName> @@ -333,7 +316,7 @@ <int>16</int> </entry> </elementAttributes> - <pos x="860" y="320"/> + <pos x="860" y="320" /> </visualElement> <visualElement> <elementName>In</elementName> @@ -347,7 +330,7 @@ <string>CLK</string> </entry> </elementAttributes> - <pos x="160" y="280"/> + <pos x="160" y="280" /> </visualElement> <visualElement> <elementName>Out</elementName> @@ -361,7 +344,7 @@ <string>MMIO_IE</string> </entry> </elementAttributes> - <pos x="880" y="540"/> + <pos x="880" y="540" /> </visualElement> <visualElement> <elementName>Out</elementName> @@ -375,7 +358,7 @@ <string>MMIO_OE</string> </entry> </elementAttributes> - <pos x="880" y="600"/> + <pos x="880" y="600" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -385,7 +368,7 @@ <string>MMIO_S</string> </entry> </elementAttributes> - <pos x="260" y="40"/> + <pos x="260" y="40" /> </visualElement> <visualElement> <elementName>Testcase</elementName> @@ -411,7 +394,7 @@ C 0x8000 0 1 Z 0xAA </testData> </entry> </elementAttributes> - <pos x="540" y="480"/> + <pos x="540" y="480" /> </visualElement> <visualElement> <elementName>In</elementName> @@ -425,7 +408,7 @@ C 0x8000 0 1 Z 0xAA <string>MEM_IE</string> </entry> </elementAttributes> - <pos x="160" y="340"/> + <pos x="160" y="340" /> </visualElement> <visualElement> <elementName>In</elementName> @@ -439,17 +422,17 @@ C 0x8000 0 1 Z 0xAA <string>MEM_OE</string> </entry> </elementAttributes> - <pos x="260" y="560"/> + <pos x="260" y="560" /> </visualElement> <visualElement> <elementName>And</elementName> <elementAttributes> <entry> <string>rotation</string> - <rotation rotation="2"/> + <rotation rotation="2" /> </entry> </elementAttributes> - <pos x="960" y="280"/> + <pos x="960" y="280" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -459,7 +442,7 @@ C 0x8000 0 1 Z 0xAA <string>RAM_OE</string> </entry> </elementAttributes> - <pos x="960" y="280"/> + <pos x="960" y="280" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -469,7 +452,7 @@ C 0x8000 0 1 Z 0xAA <string>MEM_OE</string> </entry> </elementAttributes> - <pos x="280" y="560"/> + <pos x="280" y="560" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -479,7 +462,7 @@ C 0x8000 0 1 Z 0xAA <string>MEM_OE</string> </entry> </elementAttributes> - <pos x="960" y="240"/> + <pos x="960" y="240" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -489,17 +472,17 @@ C 0x8000 0 1 Z 0xAA <string>DBUS</string> </entry> </elementAttributes> - <pos x="900" y="320"/> + <pos x="900" y="320" /> </visualElement> <visualElement> <elementName>And</elementName> <elementAttributes> <entry> <string>rotation</string> - <rotation rotation="2"/> + <rotation rotation="2" /> </entry> </elementAttributes> - <pos x="960" y="200"/> + <pos x="960" y="200" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -509,7 +492,7 @@ C 0x8000 0 1 Z 0xAA <string>ROM_OE</string> </entry> </elementAttributes> - <pos x="960" y="200"/> + <pos x="960" y="200" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -519,7 +502,7 @@ C 0x8000 0 1 Z 0xAA <string>MEM_OE</string> </entry> </elementAttributes> - <pos x="960" y="160"/> + <pos x="960" y="160" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -529,7 +512,7 @@ C 0x8000 0 1 Z 0xAA <string>DBUS</string> </entry> </elementAttributes> - <pos x="920" y="120"/> + <pos x="920" y="120" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -539,7 +522,7 @@ C 0x8000 0 1 Z 0xAA <string>DBUS</string> </entry> </elementAttributes> - <pos x="280" y="500"/> + <pos x="280" y="500" /> </visualElement> <visualElement> <elementName>Decoder</elementName> @@ -553,7 +536,7 @@ C 0x8000 0 1 Z 0xAA <boolean>true</boolean> </entry> </elementAttributes> - <pos x="460" y="180"/> + <pos x="460" y="180" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -563,7 +546,7 @@ C 0x8000 0 1 Z 0xAA <string>ROM_OE</string> </entry> </elementAttributes> - <pos x="500" y="180"/> + <pos x="500" y="180" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -573,7 +556,7 @@ C 0x8000 0 1 Z 0xAA <string>RAM_OE</string> </entry> </elementAttributes> - <pos x="500" y="200"/> + <pos x="500" y="200" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -583,7 +566,7 @@ C 0x8000 0 1 Z 0xAA <string>MMIO_OE</string> </entry> </elementAttributes> - <pos x="500" y="220"/> + <pos x="500" y="220" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -593,73 +576,73 @@ C 0x8000 0 1 Z 0xAA <string>MMIO_IE</string> </entry> </elementAttributes> - <pos x="480" y="340"/> + <pos x="480" y="340" /> </visualElement> <visualElement> <elementName>And</elementName> - <elementAttributes/> - <pos x="780" y="580"/> + <elementAttributes /> + <pos x="780" y="580" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> <elementAttributes> <entry> <string>rotation</string> - <rotation rotation="2"/> + <rotation rotation="2" /> </entry> <entry> <string>NetName</string> <string>MEM_OE</string> </entry> </elementAttributes> - <pos x="780" y="620"/> + <pos x="780" y="620" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> <elementAttributes> <entry> <string>rotation</string> - <rotation rotation="2"/> + <rotation rotation="2" /> </entry> <entry> <string>NetName</string> <string>MMIO_OE</string> </entry> </elementAttributes> - <pos x="780" y="580"/> + <pos x="780" y="580" /> </visualElement> <visualElement> <elementName>And</elementName> - <elementAttributes/> - <pos x="780" y="500"/> + <elementAttributes /> + <pos x="780" y="500" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> <elementAttributes> <entry> <string>rotation</string> - <rotation rotation="2"/> + <rotation rotation="2" /> </entry> <entry> <string>NetName</string> <string>MEM_IE</string> </entry> </elementAttributes> - <pos x="780" y="540"/> + <pos x="780" y="540" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> <elementAttributes> <entry> <string>rotation</string> - <rotation rotation="2"/> + <rotation rotation="2" /> </entry> <entry> <string>NetName</string> <string>MMIO_IE</string> </entry> </elementAttributes> - <pos x="780" y="500"/> + <pos x="780" y="500" /> </visualElement> <visualElement> <elementName>Out</elementName> @@ -677,21 +660,21 @@ C 0x8000 0 1 Z 0xAA <int>13</int> </entry> </elementAttributes> - <pos x="880" y="460"/> + <pos x="880" y="460" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> <elementAttributes> <entry> <string>rotation</string> - <rotation rotation="2"/> + <rotation rotation="2" /> </entry> <entry> <string>NetName</string> <string>MMIO_S</string> </entry> </elementAttributes> - <pos x="860" y="460"/> + <pos x="860" y="460" /> </visualElement> <visualElement> <elementName>Tunnel</elementName> @@ -701,266 +684,266 @@ C 0x8000 0 1 Z 0xAA <string>MEM_IE</string> </entry> </elementAttributes> - <pos x="300" y="360"/> + <pos x="300" y="360" /> </visualElement> </visualElements> <wires> <wire> - <p1 x="720" y="160"/> - <p2 x="740" y="160"/> + <p1 x="720" y="160" /> + <p2 x="740" y="160" /> </wire> <wire> - <p1 x="240" y="160"/> - <p2 x="260" y="160"/> + <p1 x="240" y="160" /> + <p2 x="260" y="160" /> </wire> <wire> - <p1 x="380" y="160"/> - <p2 x="400" y="160"/> + <p1 x="380" y="160" /> + <p2 x="400" y="160" /> </wire> <wire> - <p1 x="420" y="160"/> - <p2 x="440" y="160"/> + <p1 x="420" y="160" /> + <p2 x="440" y="160" /> </wire> <wire> - <p1 x="260" y="160"/> - <p2 x="320" y="160"/> + <p1 x="260" y="160" /> + <p2 x="320" y="160" /> </wire> <wire> - <p1 x="440" y="160"/> - <p2 x="480" y="160"/> + <p1 x="440" y="160" /> + <p2 x="480" y="160" /> </wire> <wire> - <p1 x="460" y="320"/> - <p2 x="480" y="320"/> + <p1 x="460" y="320" /> + <p2 x="480" y="320" /> </wire> <wire> - <p1 x="640" y="320"/> - <p2 x="660" y="320"/> + <p1 x="640" y="320" /> + <p2 x="660" y="320" /> </wire> <wire> - <p1 x="720" y="320"/> - <p2 x="760" y="320"/> + <p1 x="720" y="320" /> + <p2 x="760" y="320" /> </wire> <wire> - <p1 x="880" y="320"/> - <p2 x="900" y="320"/> + <p1 x="880" y="320" /> + <p2 x="900" y="320" /> </wire> <wire> - <p1 x="760" y="320"/> - <p2 x="840" y="320"/> + <p1 x="760" y="320" /> + <p2 x="840" y="320" /> </wire> <wire> - <p1 x="620" y="100"/> - <p2 x="740" y="100"/> + <p1 x="620" y="100" /> + <p2 x="740" y="100" /> </wire> <wire> - <p1 x="260" y="100"/> - <p2 x="320" y="100"/> + <p1 x="260" y="100" /> + <p2 x="320" y="100" /> </wire> <wire> - <p1 x="380" y="100"/> - <p2 x="420" y="100"/> + <p1 x="380" y="100" /> + <p2 x="420" y="100" /> </wire> <wire> - <p1 x="860" y="260"/> - <p2 x="900" y="260"/> + <p1 x="860" y="260" /> + <p2 x="900" y="260" /> </wire> <wire> - <p1 x="240" y="200"/> - <p2 x="320" y="200"/> + <p1 x="240" y="200" /> + <p2 x="320" y="200" /> </wire> <wire> - <p1 x="640" y="360"/> - <p2 x="660" y="360"/> + <p1 x="640" y="360" /> + <p2 x="660" y="360" /> </wire> <wire> - <p1 x="280" y="360"/> - <p2 x="300" y="360"/> + <p1 x="280" y="360" /> + <p2 x="300" y="360" /> </wire> <wire> - <p1 x="240" y="40"/> - <p2 x="260" y="40"/> + <p1 x="240" y="40" /> + <p2 x="260" y="40" /> </wire> <wire> - <p1 x="840" y="520"/> - <p2 x="860" y="520"/> + <p1 x="840" y="520" /> + <p2 x="860" y="520" /> </wire> <wire> - <p1 x="640" y="300"/> - <p2 x="660" y="300"/> + <p1 x="640" y="300" /> + <p2 x="660" y="300" /> </wire> <wire> - <p1 x="800" y="140"/> - <p2 x="840" y="140"/> + <p1 x="800" y="140" /> + <p2 x="840" y="140" /> </wire> <wire> - <p1 x="160" y="140"/> - <p2 x="220" y="140"/> + <p1 x="160" y="140" /> + <p2 x="220" y="140" /> </wire> <wire> - <p1 x="840" y="140"/> - <p2 x="860" y="140"/> + <p1 x="840" y="140" /> + <p2 x="860" y="140" /> </wire> <wire> - <p1 x="860" y="460"/> - <p2 x="880" y="460"/> + <p1 x="860" y="460" /> + <p2 x="880" y="460" /> </wire> <wire> - <p1 x="240" y="80"/> - <p2 x="320" y="80"/> + <p1 x="240" y="80" /> + <p2 x="320" y="80" /> </wire> <wire> - <p1 x="340" y="80"/> - <p2 x="380" y="80"/> + <p1 x="340" y="80" /> + <p2 x="380" y="80" /> </wire> <wire> - <p1 x="460" y="80"/> - <p2 x="600" y="80"/> + <p1 x="460" y="80" /> + <p2 x="600" y="80" /> </wire> <wire> - <p1 x="260" y="560"/> - <p2 x="280" y="560"/> + <p1 x="260" y="560" /> + <p2 x="280" y="560" /> </wire> <wire> - <p1 x="720" y="180"/> - <p2 x="740" y="180"/> + <p1 x="720" y="180" /> + <p2 x="740" y="180" /> </wire> <wire> - <p1 x="240" y="180"/> - <p2 x="280" y="180"/> + <p1 x="240" y="180" /> + <p2 x="280" y="180" /> </wire> <wire> - <p1 x="380" y="180"/> - <p2 x="400" y="180"/> + <p1 x="380" y="180" /> + <p2 x="400" y="180" /> </wire> <wire> - <p1 x="880" y="180"/> - <p2 x="900" y="180"/> + <p1 x="880" y="180" /> + <p2 x="900" y="180" /> </wire> <wire> - <p1 x="280" y="180"/> - <p2 x="320" y="180"/> + <p1 x="280" y="180" /> + <p2 x="320" y="180" /> </wire> <wire> - <p1 x="640" y="340"/> - <p2 x="660" y="340"/> + <p1 x="640" y="340" /> + <p2 x="660" y="340" /> </wire> <wire> - <p1 x="160" y="340"/> - <p2 x="280" y="340"/> + <p1 x="160" y="340" /> + <p2 x="280" y="340" /> </wire> <wire> - <p1 x="460" y="340"/> - <p2 x="480" y="340"/> + <p1 x="460" y="340" /> + <p2 x="480" y="340" /> </wire> <wire> - <p1 x="280" y="340"/> - <p2 x="420" y="340"/> + <p1 x="280" y="340" /> + <p2 x="420" y="340" /> </wire> <wire> - <p1 x="260" y="500"/> - <p2 x="280" y="500"/> + <p1 x="260" y="500" /> + <p2 x="280" y="500" /> </wire> <wire> - <p1 x="160" y="280"/> - <p2 x="180" y="280"/> + <p1 x="160" y="280" /> + <p2 x="180" y="280" /> </wire> <wire> - <p1 x="600" y="280"/> - <p2 x="660" y="280"/> + <p1 x="600" y="280" /> + <p2 x="660" y="280" /> </wire> <wire> - <p1 x="720" y="120"/> - <p2 x="740" y="120"/> + <p1 x="720" y="120" /> + <p2 x="740" y="120" /> </wire> <wire> - <p1 x="280" y="120"/> - <p2 x="320" y="120"/> + <p1 x="280" y="120" /> + <p2 x="320" y="120" /> </wire> <wire> - <p1 x="900" y="120"/> - <p2 x="920" y="120"/> + <p1 x="900" y="120" /> + <p2 x="920" y="120" /> </wire> <wire> - <p1 x="840" y="600"/> - <p2 x="880" y="600"/> + <p1 x="840" y="600" /> + <p2 x="880" y="600" /> </wire> <wire> - <p1 x="460" y="60"/> - <p2 x="620" y="60"/> + <p1 x="460" y="60" /> + <p2 x="620" y="60" /> </wire> <wire> - <p1 x="860" y="540"/> - <p2 x="880" y="540"/> + <p1 x="860" y="540" /> + <p2 x="880" y="540" /> </wire> <wire> - <p1 x="480" y="160"/> - <p2 x="480" y="180"/> + <p1 x="480" y="160" /> + <p2 x="480" y="180" /> </wire> <wire> - <p1 x="260" y="100"/> - <p2 x="260" y="160"/> + <p1 x="260" y="100" /> + <p2 x="260" y="160" /> </wire> <wire> - <p1 x="900" y="120"/> - <p2 x="900" y="140"/> + <p1 x="900" y="120" /> + <p2 x="900" y="140" /> </wire> <wire> - <p1 x="840" y="100"/> - <p2 x="840" y="140"/> + <p1 x="840" y="100" /> + <p2 x="840" y="140" /> </wire> <wire> - <p1 x="620" y="60"/> - <p2 x="620" y="100"/> + <p1 x="620" y="60" /> + <p2 x="620" y="100" /> </wire> <wire> - <p1 x="240" y="40"/> - <p2 x="240" y="80"/> + <p1 x="240" y="40" /> + <p2 x="240" y="80" /> </wire> <wire> - <p1 x="240" y="80"/> - <p2 x="240" y="140"/> + <p1 x="240" y="80" /> + <p2 x="240" y="140" /> </wire> <wire> - <p1 x="880" y="160"/> - <p2 x="880" y="180"/> + <p1 x="880" y="160" /> + <p2 x="880" y="180" /> </wire> <wire> - <p1 x="280" y="120"/> - <p2 x="280" y="180"/> + <p1 x="280" y="120" /> + <p2 x="280" y="180" /> </wire> <wire> - <p1 x="280" y="340"/> - <p2 x="280" y="360"/> + <p1 x="280" y="340" /> + <p2 x="280" y="360" /> </wire> <wire> - <p1 x="440" y="140"/> - <p2 x="440" y="160"/> + <p1 x="440" y="140" /> + <p2 x="440" y="160" /> </wire> <wire> - <p1 x="440" y="160"/> - <p2 x="440" y="300"/> + <p1 x="440" y="160" /> + <p2 x="440" y="300" /> </wire> <wire> - <p1 x="600" y="80"/> - <p2 x="600" y="280"/> + <p1 x="600" y="80" /> + <p2 x="600" y="280" /> </wire> <wire> - <p1 x="760" y="280"/> - <p2 x="760" y="320"/> + <p1 x="760" y="280" /> + <p2 x="760" y="320" /> </wire> <wire> - <p1 x="380" y="80"/> - <p2 x="380" y="100"/> + <p1 x="380" y="80" /> + <p2 x="380" y="100" /> </wire> <wire> - <p1 x="860" y="520"/> - <p2 x="860" y="540"/> + <p1 x="860" y="520" /> + <p2 x="860" y="540" /> </wire> <wire> - <p1 x="860" y="260"/> - <p2 x="860" y="300"/> + <p1 x="860" y="260" /> + <p2 x="860" y="300" /> </wire> </wires> - <measurementOrdering/> + <measurementOrdering /> </circuit>
\ No newline at end of file diff --git a/src/ast_compiler.py b/src/ast_compiler.py index 929b979..e6e78bf 100644 --- a/src/ast_compiler.py +++ b/src/ast_compiler.py @@ -5,7 +5,7 @@ import sys import ast from dataclasses import dataclass -from typing import Literal, Set, cast, Any, TypeAlias +from typing import Literal, Set, cast, Any, TypeAlias, TypeVar from collections import OrderedDict from tokenizer import tokenize @@ -16,8 +16,8 @@ if len(sys.argv) != 3: infile_path = sys.argv[1] outfile_path = sys.argv[2] -Addr = int Label = str +StackOffset = int RegChar = Literal["A", "B", "C", "D", "E", "F", "G", "H"] @dataclass @@ -42,6 +42,38 @@ def format_asm_row(asm: str) -> str: else: return asm +@dataclass +class Frame: + names: list[str] + bindings: dict[str, Label | StackOffset] + + def size(self) -> int: + return len(self.names) + +class FrameStack: + def __init__(self, stack: list[Frame] = []): + self.stack: list[Frame] = stack + + def push(self, frame: Frame): + self.stack.append(frame) + + def pop(self) -> Frame | None: + if len(self.stack) == 0: return None + return self.stack.pop() + + def peek(self) -> Frame: + return self.stack[self.size() - 1] + + def size(self) -> int: + return len(self.stack) + + def total_offset(self) -> int: + total: int = 0 + for frame in self.stack: + total += frame.size() + + return total + class Compiler(ast.NodeVisitor): def __init__(self): self.const_asm: list[str] = [] @@ -50,9 +82,9 @@ class Compiler(ast.NodeVisitor): ] self.function_def_asms: list[str] = [] self.currently_emitting_asm_list = self.program_asm - self.stack_pointer_offset: int | None = None - self.bindings: dict[str, Label] = {} - self.call_depth: int = 0 + + self.frame_stack = FrameStack() + self.unique_name_counter = 0 self.latest_break_target: Label | None = None @@ -64,9 +96,16 @@ class Compiler(ast.NodeVisitor): return ret def assign_const(self, name: str, value: int): - self.const_asm.append(f"@label {name}") - self.const_asm.append(f" {value}") - self.bindings[name] = name + prev_currently_emitting_asm_list = self.currently_emitting_asm_list + self.currently_emitting_asm_list = self.const_asm + + self.emit_label(name) + self.emit(f"{value}") + + frame = self.frame_stack.peek() + frame.bindings[name] = name + + self.currently_emitting_asm_list = prev_currently_emitting_asm_list def emit(self, asm: str): asm = asm.strip() @@ -74,6 +113,10 @@ class Compiler(ast.NodeVisitor): self.currently_emitting_asm_list.append(asm) + def emit_label(self, label_name: str): + label_name = label_name.lower() + self.emit(f"@label {label_name}") + def alloc_reg(self) -> Reg: for reg in GENERIC_REGS: if not reg in self.reserved_regs: @@ -89,7 +132,7 @@ class Compiler(ast.NodeVisitor): def __init__(self, compiler): self.compiler = compiler - def __enter__(self): + def __enter__(self) -> Reg: self.reg = self.compiler.alloc_reg() return self.reg @@ -126,6 +169,7 @@ class Compiler(ast.NodeVisitor): self.emit(value) case other: raise Exception(f"asm: invalid args: {other}") + case "store": if len(args) != 2: raise Exception("Invalid number of arguments to store: " + str(len(args))) @@ -139,6 +183,26 @@ class Compiler(ast.NodeVisitor): self.emit(f"spo {arg1}") self.emit(f"str {arg2} {arg1}") + case "load": + if len(args) != 1: + raise Exception("Invalid number of arguments to load: " + str(len(args))) + + self.visit(args[0]) + + with self.allocated_reg() as arg: + self.emit(f"spo {arg}") + self.emit(f"ldr {arg} {arg}") + self.emit(f"spu {arg}") + + case "ord": + if len(args) != 1: + raise Exception("Invalid number of arguments to ord: " + str(len(args))) + + self.visit(args[0]) + + case other: + raise Exception(f"Unknown builtin: {other}") + def eval_int_constant_and_spu(self, value: int): with self.allocated_reg() as reg: if value >= 0 and value < 8: @@ -153,36 +217,41 @@ class Compiler(ast.NodeVisitor): def visit_Module(self, node: ast.Module): stmts = node.body - stack_frame = self.collect_local_variables(stmts) + frame_names = self.collect_local_variables(stmts) - self.emit(f"; stack frame: {stack_frame}") + self.emit(f"; stack frame names: {frame_names}") # Move stack pointer to accommodate local variables - self.stack_pointer_offset = len(stack_frame) - self.emit(f"addi SP {self.stack_pointer_offset} SP") + # TODO instead of self.stack_frame_size, use a proper stack for frames. + # That way, we can restore the top-level stack frame when returning - prev_bindings = self.bindings - self.bindings: dict[str, Label] = prev_bindings.copy() - for idx, name in enumerate(stack_frame): - offset = len(stack_frame) - idx - offset_label = f"${{SP - {offset}}}" - self.bindings[name] = offset_label + frame_bindings: dict[str, Label | StackOffset] = {} + for idx, name in enumerate(frame_names): + offset = self.frame_stack.total_offset() + idx + frame_bindings[name] = offset + + frame = Frame( + names = frame_names, + bindings = frame_bindings, + ) + self.frame_stack.push(frame) + self.emit(f"addi SP {len(frame.names)} SP") for stmt in stmts: self.visit(stmt) - self.bindings = prev_bindings - self.emit(f"subi SP {self.stack_pointer_offset} SP") + self.frame_stack.pop() + self.emit(f"subi SP {len(frame.names)} SP") def visit_Expr(self, expr: ast.Expr): - # if self.call_depth == 0 and type(expr.value) != ast.Call: - # self.emit("; NOP top-level expression") - # return + if self.frame_stack.size == 1 and type(expr.value) != ast.Call: + self.emit("; NOP top-level expression") + return self.visit(expr.value) def visit_UnaryOp(self, node: ast.UnaryOp): - self.emit(f"; {node}") + self.emit(f"; {node.op}") self.visit(node.operand) match node.op: case ast.Not(): @@ -228,7 +297,7 @@ class Compiler(ast.NodeVisitor): self.emit(f"addi {reg} 0 {reg}") self.emit(f"bri zero {label_short_circuit}") - self.emit(f"@label {label_short_circuit}") + self.emit_label(label_short_circuit) self.emit(f"spu {reg}") case ast.Or(): @@ -243,14 +312,14 @@ class Compiler(ast.NodeVisitor): self.emit(f"subi {reg1} 1 {reg2}") self.emit(f"bri carry {label_short_circuit}") - self.emit(f"@label {label_short_circuit}") + self.emit_label(label_short_circuit) self.emit(f"spu {reg1}") case other: raise NotImplementedError(f"Unhandled BoolOp: {other}") def visit_BinOp(self, node: ast.BinOp): - self.emit(f"; {node}") + self.emit(f"; {node.op}") self.emit(f"; BinOp lhs {node}") self.visit(node.left) @@ -315,12 +384,12 @@ class Compiler(ast.NodeVisitor): self.visit(true_branch_stmt) self.emit(f"jpi {label_end}") - self.emit(f"@label {label_false}") + self.emit_label(label_false) for false_branch_stmt in node.orelse: self.visit(false_branch_stmt) - self.emit(f"@label {label_end}") + self.emit_label(label_end) def visit_While(self, node: ast.While): self.emit(f"; {node}") @@ -333,7 +402,7 @@ class Compiler(ast.NodeVisitor): self.latest_break_target = label_end with self.allocated_reg() as reg: - self.emit(f"@label {label_test}") + self.emit_label(label_test) self.visit(node.test) self.emit(f"spo {reg}") self.emit(f"addi {reg} 0 {reg}") @@ -344,15 +413,19 @@ class Compiler(ast.NodeVisitor): self.emit(f"jpi {label_test}") - self.emit(f"@label {label_else}") + self.emit_label(label_else) for else_stmt in node.orelse: self.visit(else_stmt) - self.emit(f"@label {label_end}") + self.emit_label(label_end) self.latest_break_target = prev_break_target + def visit_Pass(self, node: ast.Pass): + self.emit(f"; {node}") + pass + def visit_Break(self, node: ast.Break): self.emit(f"; {node}") @@ -386,6 +459,7 @@ class Compiler(ast.NodeVisitor): return list(set(symbols)) def visit_FunctionDef(self, node: ast.FunctionDef): + prev_currently_emitting_asm_list = self.currently_emitting_asm_list self.currently_emitting_asm_list = self.function_def_asms self.emit(f"; {node}") @@ -393,50 +467,69 @@ class Compiler(ast.NodeVisitor): fn_params = [str(param.arg) for param in node.args.args] fn_stmts = node.body - # Add a "return None" to the end to make sure there the function returns + # Add a "return None" to the end to make sure the function returns if len(fn_stmts) == 0 or type(fn_stmts[len(fn_stmts) - 1]) != ast.Return: fn_stmts.append(ast.Return(value=None)) if len(node.args.kwonlyargs) > 0 or len(node.args.posonlyargs) > 0 or len(node.args.kw_defaults) > 0 or len(node.args.defaults) > 0: raise Exception("Only simple positional args are supported for now in function definitions.") - self.emit(f"@label {fn_name}") - stack_frame = fn_params + self.collect_local_variables(fn_stmts) - self.emit(f"; stack frame: {stack_frame}") + self.emit_label(fn_name) + return_address_name = self.get_unique_name("return_address") + local_var_names = self.collect_local_variables(fn_stmts) + frame_names = [return_address_name] + fn_params + local_var_names + self.emit(f"; stack frame names: {frame_names}") + # Move stack pointer to accommodate local variables - self.stack_pointer_offset = len(stack_frame) - len(fn_params) + self.emit(f"addi SP {len(local_var_names)} SP") - self.emit(f"addi SP {self.stack_pointer_offset} SP") + frame_bindings: dict[str, Label | StackOffset] = {} + for idx, name in enumerate(frame_names): + offset = self.frame_stack.total_offset() + idx + frame_bindings[name] = offset - prev_bindings = self.bindings - self.bindings: dict[str, Label] = prev_bindings.copy() - for idx, name in enumerate(stack_frame): - offset = len(stack_frame) - idx - offset_label = f"${{SP - {offset}}}" - self.bindings[name] = offset_label + frame = Frame( + names = frame_names, + bindings = frame_bindings + ) + self.frame_stack.push(frame) for stmt in fn_stmts: self.visit(stmt) - self.bindings = prev_bindings - self.currently_emitting_asm_list = self.program_asm + self.frame_stack.pop() + self.currently_emitting_asm_list = prev_currently_emitting_asm_list def visit_Return(self, node: ast.Return): self.emit(f"; {node}") - if self.stack_pointer_offset is None: - raise Exception("Encountered Return outside a function def context") + + if self.frame_stack.size() <= 1: + raise Exception("Encountered return in the top level stack frame") + + frame = self.frame_stack.peek() ret = node.value - if ret is not None: - self.visit(ret) - else: - with self.allocated_reg() as reg: - self.emit(f"ldi 0 {reg}") - self.emit(f"spu {reg}") + with self.allocated_reg() as reg1, self.allocated_reg() as reg2: + print(frame.names) + ret_addr_offset = self.frame_stack.total_offset() - frame.size() + self.emit(f"ldi vt_stack_addr {reg1}") # vector table address of stack segment address + self.emit(f"ldr {reg1} {reg1}") # stack segment address + self.emit(f"ldi {ret_addr_offset} {reg2}") # stack offset + self.emit(f"add {reg1} {reg2} {reg1}") # stack address of return address = stack segment start + stack offset + + if ret is not None: + self.visit(ret) + self.emit(f"spo {reg2}") + else: + self.emit(f"ldi 0 {reg2}") + + self.emit(f"mov {reg1} SP") # reset stack pointer to return address position (i.e. start of stack frame) + self.emit(f"ldr {reg1} {reg1}") # return address - self.emit(f"subi SP {self.stack_pointer_offset} SP") - self.emit("rsr") + self.emit(f"spu {reg2}") + self.emit(f"; return from function") + self.emit(f"jpr {reg1}") def visit_Call(self, node: ast.Call): self.emit(f"; {node}") @@ -445,42 +538,88 @@ class Compiler(ast.NodeVisitor): case ast.Attribute(ast.Name(id="atk16"), attr): self.emit_builtin_call(attr, node.args) case ast.Name(name): - # Evaluate args before call + self.emit(f"; Call function {name}") + + # Reserve a stack slot for the return address + with self.allocated_reg() as reg: + self.emit(f"ldi 0 {reg}") + self.emit(f"spu {reg}") + + # Evaluate args before call, pushing them to stack for arg in node.args: self.visit(arg) - self.emit(f"csi {name}") + with self.allocated_reg() as reg1, self.allocated_reg() as reg2: + self.emit("; set up return address and jump to subroutine") + self.emit(f"subi SP {len(node.args) + 1} {reg1}") + self.emit(f"lpc {reg2}") + self.emit(f"addi {reg2} 3 {reg2}") + self.emit(f"str {reg2} {reg1}") + self.emit(f"jpi {name}") + case other: raise NotImplementedError(f"Unhandled Call: {other}") + def resolve_name(self, name: str) -> Label | StackOffset: + frames = FrameStack(self.frame_stack.stack.copy()) + + while frames.size() > 0: + frame = cast(Frame, frames.pop()) + + if name in frame.bindings: + addr = frame.bindings[name] + match addr: + case Label(value): + return value + case StackOffset(value): + return value + + raise Exception(f"{name} is unbound") + def visit_Name(self, node: ast.Name): self.emit(f"; {node} ({node.id})") - name = node.id - if name not in self.bindings: - raise Exception(f"{name} is unbound") + name = node.id.lower() + addr = self.resolve_name(name) - addr = self.bindings[name] - with self.allocated_reg() as reg: - self.emit(f"ldi {addr} {reg}") - self.emit(f"ldr {reg} {reg}") - self.emit(f"spu {reg}") + with self.allocated_reg() as reg1, self.allocated_reg() as reg2: + match addr: + case Label(label): + self.emit(f"ldi {label} {reg1}") + case StackOffset(offset): + self.emit(f"ldi vt_stack_addr {reg1}") + self.emit(f"ldr {reg1} {reg1}") + self.emit(f"ldi {offset} {reg2}") + self.emit(f"add {reg1} {reg2} {reg1}") + case other: + raise Exception(f"Unsupported addr value: {other}") + + self.emit(f"ldr {reg1} {reg1}") + self.emit(f"spu {reg1}") def visit_Assign(self, node: ast.Assign): + self.emit(f"; {node}") + targets = node.targets value = node.value match targets: case [ast.Name(name)]: - if name not in self.bindings: - raise Exception(f"{name} is not in bindings. Bindings:\n{self.bindings}") + offset = self.resolve_name(name) - self.visit(value) - addr = self.bindings[name] + if type(offset) != StackOffset: + raise Exception(f"Invalid address {offset} for name {name}. Can only assign to stack offsets.") + + self.emit(f"; assigning {name} to stack segment + offset {offset}") with self.allocated_reg() as reg1, self.allocated_reg() as reg2: - self.emit(f"spo {reg1}") - self.emit(f"ldi {addr} {reg2}") - self.emit(f"str {reg1} {reg2}") + self.visit(value) + self.emit(f"ldi vt_stack_addr {reg1}") + self.emit(f"ldr {reg1} {reg1}") + self.emit(f"ldi {offset} {reg2}") + self.emit(f"add {reg1} {reg2} {reg1}") # address + self.emit(f"spo {reg2}") # value + self.emit(f"str {reg2} {reg1}") + case other: raise Exception(f"Unsupported assign targets: {other}") @@ -501,7 +640,7 @@ class Compiler(ast.NodeVisitor): value=ast.Constant(value) # TODO: constant folding ): if type(value) == int: - self.assign_const(name, value) + self.assign_const(name.lower(), value) return raise NotImplementedError("Unhandled AnnAssign:\n" + ast.dump(node, indent=4)) |
