aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--asm/atk16.py4
-rw-r--r--asm/test_py_src.atk16266
-rw-r--r--asm/test_py_src.atk16_optimized161
-rw-r--r--asm/test_py_src.py20
-rw-r--r--digital/atk16_mem.dig421
-rw-r--r--src/ast_compiler.py289
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))