1- class AsmWriter :
1+ from asm_reader import AsmReader
2+
3+ class AsmStringBackend :
24
35 def __init__ (self ):
46 self .output = ''
57 self .indent = 0
6- self .sub = False
7- self ._setup = []
8- self .after_sub = []
98
10- # TODO unused
11- def write_statement (self , stmt ):
12- type , * args = stmt
13- if type == 'constant' :
14- self .write_constant (* args )
15- elif type == 'subroutine' :
16- self .write_subroutine (* args )
17- elif type == 'instruction' :
18- self .write_instruction (* args )
19- elif type == 'local_subroutine' :
20- self .write_local_sub (* args )
21- elif type == 'directive' :
22- self .write_directive (* args )
9+ def get_output (self ):
10+ return self .output
2311
2412 def write_constant (self , name , value ):
2513 self .write_line ('.%s %s' % (name , value ))
@@ -30,48 +18,168 @@ def write_directive(self, name, value):
3018 def write_entity_local (self , name ):
3119 self .write_line ('@%s' % name )
3220
21+ def write_local_label (self , label ):
22+ self .write_line ('_%s:' % label )
23+
24+ def write_label (self , label ):
25+ self .indent = 0
26+ self .write_line ('%s:' % label )
27+ self .indent = 4
28+
29+ def write_instruction (self , insn , operands , comment = None ):
30+ line = '%s%s' % (insn , (' ' + ', ' .join (operands )) if operands else '' )
31+ line = line .replace ('\n ' , '\\ n' )
32+ if comment :
33+ line += ' ; ' + comment
34+ self .write_line (line )
35+
36+ def write_raw_asm (self , asm ):
37+ self .write_line (asm )
38+
39+ def inject (self , block ):
40+ self .output += block
41+
42+ def write_line (self , line ):
43+ self .output += (' ' * self .indent ) + line + '\n '
44+
45+ def ref_literal (self , number ):
46+ return '#%d' % number
47+
48+ def ref_address (self , number ):
49+ return '%d' % number
50+
51+ def ref_string (self , string ):
52+ return '"%s"' % string .replace ('\\ ' , '\\ \\ ' ).replace ('"' , '\\ "' )
53+
54+ def ref_symbol (self , symbol ):
55+ return str (symbol )
56+
57+ def ref_raw (self , text ):
58+ return str (text )
59+
60+ class AsmTokenBackend :
61+
62+ def __init__ (self ):
63+ self .tokens = []
64+ self .asm_reader = AsmReader ()
65+
66+ def get_output (self ):
67+ return self .tokens
68+
69+ def add (self , key , value ):
70+ self .tokens .append ((key , value ))
71+
72+ def write_constant (self , name , value ):
73+ self .add ('const' , (name , value ))
74+
75+ def write_directive (self , name , value ):
76+ self .add ('directive' , (name , value ))
77+
78+ def write_entity_local (self , name ):
79+ self .add ('entity_local' , name )
80+
81+ def write_local_label (self , label ):
82+ self .add ('local_label' , label )
83+
84+ def write_label (self , label ):
85+ self .add ('label' , label )
86+
87+ def write_instruction (self , insn , operands , comment = None ):
88+ self .add ('instruction' , (insn , operands ))
89+
90+ def write_raw_asm (self , asm ):
91+ self .asm_reader .feed (asm )
92+ for token in self .asm_reader :
93+ self .tokens .append (token )
94+
95+ def inject (self , block ):
96+ self .tokens .extend (block )
97+
98+ def ref_literal (self , number ):
99+ return ('literal' , number )
100+
101+ def ref_address (self , number ):
102+ return ('address' , number )
103+
104+ def ref_string (self , string ):
105+ return ('string' , string )
106+
107+ def ref_symbol (self , symbol ):
108+ return ('symbol' , symbol )
109+
110+ def ref_raw (self , text ):
111+ return str (text )
112+
113+ class AsmWriter :
114+
115+ def __init__ (self , backend = 'string' ):
116+ self .backend = {
117+ 'string' : AsmStringBackend ,
118+ 'token' : AsmTokenBackend
119+ }[backend ]()
120+ self .backend_type = backend
121+ self .sub = False
122+ self ._setup = []
123+ self .after_sub = []
124+
125+ def fork (self ):
126+ return AsmWriter (self .backend_type )
127+
128+ def ref_literal (self , number ):
129+ return self .backend .ref_literal (number )
130+
131+ def ref_address (self , number ):
132+ return self .backend .ref_address (number )
133+
134+ def ref_string (self , string ):
135+ return self .backend .ref_string (string )
136+
137+ def ref_symbol (self , symbol ):
138+ return self .backend .ref_symbol (symbol )
139+
140+ def ref_raw (self , text ):
141+ return self .backend .ref_raw (text )
142+
143+ def write_constant (self , name , value ):
144+ self .backend .write_constant (name , value )
145+
146+ def write_directive (self , name , value ):
147+ self .backend .write_directive (name , value )
148+
149+ def write_entity_local (self , name ):
150+ self .backend .write_entity_local (name )
151+
33152 def write_subroutine (self , name ):
34153 if name == '__setup__' :
35154 return
36- self .write_line ('%s:' % name )
37- self .indent = 4
38155 self .sub = True
156+ self .backend .write_label (name )
39157
40158 def end_subroutine (self ):
41- self .indent = 0
42- self .write_line ('' )
43159 self .sub = False
44160 for after in self .after_sub :
45- self .output += after
161+ self .backend . inject ( after )
46162 self .after_sub = []
47163
48164 def write_after_subroutine (self , block ):
49165 self .after_sub .append (block )
50166
51- def write_instruction (self , insn , * args , comment = None , raw = False ):
52- if raw :
53- line = '%s%s' % (insn , '' . join ( args ) )
167+ def write_instruction (self , insn , * args , comment = None ):
168+ if self . sub :
169+ self . backend . write_instruction (insn , args , comment )
54170 else :
55- line = '%s%s' % (insn , (' ' + ', ' .join (args )) if args else '' )
56- line = line .replace ('\n ' , '\\ n' )
57- if comment :
58- line += ' ; ' + comment
59- if not self .sub :
60- self ._setup .append (line )
61- else :
62- self .write_line (line )
171+ self ._setup .append ((insn , args , comment ))
63172
64173 def write_local_sub (self , label ):
65- self .write_line ( '_%s:' % label )
174+ self .backend . write_local_label ( label )
66175
67- def write_line (self , line ):
68- self .output += ( ' ' * self . indent ) + line + ' \n '
176+ def write_raw_asm (self , asm ):
177+ self .backend . write_raw_asm ( asm )
69178
70179 def get_output (self ):
71180 assert not self .sub
72- setup = ''
73181 if self ._setup :
74- setup = '__setup__: \n '
75- setup += ' \n ' . join ( self ._setup )
76- setup += ' \n \n '
77- return self .output + setup
182+ self . backend . write_label ( '__setup__' )
183+ for ( insn , args , comment ) in self ._setup :
184+ self . backend . write_instruction ( insn , args , comment )
185+ return self .backend . get_output ()
0 commit comments