codecin 5.4.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. codecin/__init__.py +27 -0
  2. codecin/aot.py +229 -0
  3. codecin/assembler.py +548 -0
  4. codecin/cache.py +71 -0
  5. codecin/cin.py +2558 -0
  6. codecin/cli.py +282 -0
  7. codecin/config.py +58 -0
  8. codecin/console.py +183 -0
  9. codecin/cpu.py +1654 -0
  10. codecin/crom.py +222 -0
  11. codecin/debugger.py +659 -0
  12. codecin/disasm.py +86 -0
  13. codecin/errors.py +58 -0
  14. codecin/isa.py +457 -0
  15. codecin/jit.py +270 -0
  16. codecin/libcodecin_native.so +0 -0
  17. codecin/logger.py +145 -0
  18. codecin/memory.py +348 -0
  19. codecin/native/aot/aot.go +70 -0
  20. codecin/native/aot/build.go +219 -0
  21. codecin/native/aot/stub_main.go.txt +22 -0
  22. codecin/native/build.ps1 +33 -0
  23. codecin/native/build.sh +48 -0
  24. codecin/native/cmd/codecin/main.go +287 -0
  25. codecin/native/compiler/codegen.go +1938 -0
  26. codecin/native/compiler/compile_test.go +164 -0
  27. codecin/native/compiler/parser.go +1071 -0
  28. codecin/native/compiler/syscalls.go +86 -0
  29. codecin/native/compiler/tokenizer.go +336 -0
  30. codecin/native/compiler/types.go +213 -0
  31. codecin/native/engine/audio.go +152 -0
  32. codecin/native/engine/audio_other.go +46 -0
  33. codecin/native/engine/audio_windows.go +43 -0
  34. codecin/native/engine/canvas.go +271 -0
  35. codecin/native/engine/crom.go +86 -0
  36. codecin/native/engine/encode.go +93 -0
  37. codecin/native/engine/engine_test.go +198 -0
  38. codecin/native/engine/isa_gen.go +445 -0
  39. codecin/native/engine/system.go +190 -0
  40. codecin/native/engine/termux.go +113 -0
  41. codecin/native/engine/version_gen.go +7 -0
  42. codecin/native/engine/vm.go +1157 -0
  43. codecin/native/go.mod +3 -0
  44. codecin/native/ir/ir.go +48 -0
  45. codecin/native/main.go +225 -0
  46. codecin/native.py +336 -0
  47. codecin/registers.py +130 -0
  48. codecin/stats.py +235 -0
  49. codecin-5.4.2.dist-info/METADATA +985 -0
  50. codecin-5.4.2.dist-info/RECORD +54 -0
  51. codecin-5.4.2.dist-info/WHEEL +5 -0
  52. codecin-5.4.2.dist-info/entry_points.txt +2 -0
  53. codecin-5.4.2.dist-info/licenses/LICENSE +7 -0
  54. codecin-5.4.2.dist-info/top_level.txt +1 -0
codecin/cin.py ADDED
@@ -0,0 +1,2558 @@
1
+ """CIN 高级语言编译器。
2
+
3
+ 将 CIN 源码 (类 C 语法: 函数/struct/多维数组/字符串/浮点/控制流)
4
+ 编译为 Code CIN 字节码 IR。
5
+
6
+ 语法扩展 (2026):
7
+ - 语句: break/continue, do-while, switch/case/default (case 常量表达式)
8
+ - 表达式: ?: 三目 (短路), ++/-- 前缀与后缀, 复合赋值 += -= *= /= %=
9
+ - 字面量/类型: 0x/0b/0o 进制与 u/L/f 后缀、数字下划线、字符字面量 'a';
10
+ char/short/long/unsigned 类型别名 (64 位槽模型, 与 int 同宽)
11
+ - 内建: int_to_str/itoa, float_to_str/ftoa, bool_to_str
12
+
13
+ 运行时约定:
14
+ - 所有值均为 64 位槽: int 为有符号整数; float 为 float64 位模式;
15
+ bool 为 0/1; string/struct/数组为内存指针。
16
+ - 浮点运算经 SYS 宿主调用 (FADD/FSUB/...), 数学函数同理。
17
+ - 栈帧: [参数...][返回地址][局部变量/数组...] , SP 指向帧内最低地址。
18
+ - struct 采用浅拷贝语义 (变量保存对象指针, 堆分配, 不回收)。
19
+ - 定长数组就地存放 (数据段/栈帧); int[][] 为指向行指针数组的指针。
20
+ """
21
+
22
+ import os
23
+ import re
24
+ import struct
25
+ from dataclasses import dataclass, field
26
+ from typing import Any, Dict, List, Optional, Tuple
27
+
28
+ from .console import Console
29
+ from .errors import CompilerError
30
+ from .isa import Syscall
31
+
32
+ # ---------------- 类型表示 ----------------
33
+ # 'int' / 'float' / 'bool' / 'string' / 'void'
34
+ # ('struct', Name)
35
+ # ('array', elem_type, size) 定长数组 (多维: elem 仍为 array)
36
+ # ('ptrarray', elem_type) 动态/参数数组 (int[] / int[][])
37
+
38
+ SCALARS = {'int', 'float', 'bool', 'string', 'void'}
39
+
40
+ Operand = Tuple[Any, ...]
41
+ Instruction = Tuple[str, List[Operand]]
42
+
43
+
44
+ def _is_scalar(t) -> bool:
45
+ return isinstance(t, str)
46
+
47
+
48
+ def _is_struct(t) -> bool:
49
+ return isinstance(t, tuple) and t[0] == 'struct'
50
+
51
+
52
+ def _is_fixed_array(t) -> bool:
53
+ return isinstance(t, tuple) and t[0] == 'array'
54
+
55
+
56
+ def _is_ptr_array(t) -> bool:
57
+ return isinstance(t, tuple) and t[0] == 'ptrarray'
58
+
59
+
60
+ def _array_elem(t):
61
+ return t[1]
62
+
63
+
64
+ def _type_slots(t) -> int:
65
+ """类型占据的 qword 槽数。"""
66
+ if _is_fixed_array(t):
67
+ elem, size = t[1], t[2]
68
+ return size * _type_slots(elem)
69
+ return 1 # 标量/struct指针/ptrarray 均为 1 槽
70
+
71
+
72
+ # ==================== 词法分析 ====================
73
+
74
+ _KEYWORDS = {
75
+ 'struct', 'function', 'return', 'if', 'else', 'while', 'for', 'do',
76
+ 'switch', 'case', 'default', 'break', 'continue', 'true', 'false',
77
+ 'int', 'float', 'bool', 'string', 'void', 'char', 'short', 'long',
78
+ 'unsigned',
79
+ 'set', 'add', 'subtract', 'multiply', 'divide', 'increment', 'decrement',
80
+ }
81
+
82
+ # 声明起始的标量类型词 (含新支持的类型别名, 均映射到 64 位槽 int 模型)
83
+ BASE_TYPE_WORDS = ('int', 'float', 'bool', 'string', 'char', 'short', 'long',
84
+ 'unsigned')
85
+
86
+ # 复合赋值: 词法 token -> C 风格运算符
87
+ _COMPOUND_ASSIGN = {
88
+ 'PLUSEQ': '+=', 'MINUSEQ': '-=', 'STAREQ': '*=',
89
+ 'SLASHEQ': '/=', 'PERCENTEQ': '%=',
90
+ 'ANDEQ': '&=', 'OREQ': '|=', 'XOREQ': '^=',
91
+ 'SHLEQ': '<<=', 'SHREQ': '>>=',
92
+ }
93
+
94
+ _SINGLE_OPS = {
95
+ '{': 'LBRACE', '}': 'RBRACE', '(': 'LPAREN', ')': 'RPAREN',
96
+ '[': 'LBRACKET', ']': 'RBRACKET', ',': 'COMMA', ';': 'SEMI',
97
+ '+': 'PLUS', '-': 'MINUS', '*': 'STAR', '/': 'SLASH', '%': 'PERCENT',
98
+ '=': 'ASSIGN', '<': 'LT', '>': 'GT', '!': 'BANG', '.': 'DOT',
99
+ '?': 'QUESTION', ':': 'COLON',
100
+ '&': 'AMP', '|': 'PIPE', '^': 'CARET', '~': 'TILDE',
101
+ }
102
+
103
+ # 复合赋值运算符 -> 底层运算符
104
+ _COMPOUND_TO_BASE = {
105
+ '+=': '+', '-=': '-', '*=': '*', '/=': '/', '%=': '%',
106
+ '&=': '&', '|=': '|', '^=': '^', '<<=': '<<', '>>=': '>>',
107
+ }
108
+
109
+ # 宿主能力内建 (表驱动): 名称 -> (SYS 功能号, 参数个数, 返回类型)。
110
+ # 全部由 Go 原生引擎实现; 解释器 (--no-native) 下会给出明确错误。
111
+ HOST_BUILTINS = {
112
+ # 联网音频
113
+ 'audio_play': (Syscall.AUDIOPLAY, 1, 'int'),
114
+ 'audio_stop': (Syscall.AUDIOSTOP, 0, 'void'),
115
+ 'audio_volume': (Syscall.AUDIOVOL, 1, 'void'),
116
+ 'audio_wait': (Syscall.AUDIOWAIT, 0, 'void'),
117
+ # 2D 绘图画布
118
+ 'canvas': (Syscall.CANVASNEW, 2, 'void'),
119
+ 'set_color': (Syscall.CANVASSET, 1, 'void'),
120
+ 'fill_rect': (Syscall.CANVASRECT, 4, 'void'),
121
+ 'fill_circle': (Syscall.CANVASCIRC, 3, 'void'),
122
+ 'draw_line': (Syscall.CANVASLINE, 4, 'void'),
123
+ 'draw_text': (Syscall.CANVASTEXT, 3, 'void'),
124
+ 'save_png': (Syscall.CANVASSAVE, 1, 'int'),
125
+ 'show_canvas': (Syscall.CANVASSHOW, 0, 'int'),
126
+ # 系统原生交互 (跨平台)
127
+ 'file_read': (Syscall.FILEREAD, 1, 'string'),
128
+ 'file_write': (Syscall.FILEWRITE, 2, 'int'),
129
+ 'file_append': (Syscall.FILEAPPEND, 2, 'int'),
130
+ 'file_exists': (Syscall.FILEEXISTS, 1, 'int'),
131
+ 'file_delete': (Syscall.FILEDELETE, 1, 'int'),
132
+ 'file_size': (Syscall.FILESIZE, 1, 'int'),
133
+ 'mkdir': (Syscall.MKDIR, 1, 'int'),
134
+ 'dir_list': (Syscall.DIRLIST, 1, 'string'),
135
+ 'exec': (Syscall.EXEC, 1, 'int'),
136
+ 'exec_output': (Syscall.EXECOUTPUT, 1, 'string'),
137
+ 'getenv': (Syscall.GETENV, 1, 'string'),
138
+ 'setenv': (Syscall.SETENV, 2, 'int'),
139
+ 'os_name': (Syscall.OSNAME, 0, 'string'),
140
+ 'hostname': (Syscall.HOSTNAME, 0, 'string'),
141
+ 'username': (Syscall.USERNAME, 0, 'string'),
142
+ 'cwd': (Syscall.CWD, 0, 'string'),
143
+ 'home_dir': (Syscall.HOMEDIR, 0, 'string'),
144
+ # Termux API
145
+ 'termux_available': (Syscall.TERMUXAVAIL, 0, 'int'),
146
+ 'termux_notify': (Syscall.TERMUXNOTIFY, 2, 'int'),
147
+ 'termux_toast': (Syscall.TERMUXTOAST, 1, 'int'),
148
+ 'termux_clipboard_get': (Syscall.TERMUXCLIPGET, 0, 'string'),
149
+ 'termux_clipboard_set': (Syscall.TERMUXCLIPSET, 1, 'int'),
150
+ 'termux_battery': (Syscall.TERMUXBATTERY, 0, 'string'),
151
+ 'termux_vibrate': (Syscall.TERMUXVIBRATE, 1, 'int'),
152
+ 'termux_tts': (Syscall.TERMUXTTS, 1, 'int'),
153
+ 'termux_location': (Syscall.TERMUXLOCATION, 0, 'string'),
154
+ 'termux_wifi_info': (Syscall.TERMUXWIFI, 0, 'string'),
155
+ 'termux_dialog': (Syscall.TERMUXDIALOG, 1, 'string'),
156
+ 'termux_sms_send': (Syscall.TERMUXSMS, 2, 'int'),
157
+ }
158
+
159
+ # 内建函数最少参数个数 (按各分支实际索引的最大下标 + 1 得出)。
160
+ # 缺失参数旧代码会直接 IndexError 崩溃 (如 sqrt()、substr("a",1)),
161
+ # 现在统一报 CompilerError。必须与 Go 侧 compiler.builtinMinArgs 保持一致。
162
+ BUILTIN_MIN_ARGS = {
163
+ 'println': 0, 'print': 0,
164
+ 'sqrt': 1, 'sin': 1, 'cos': 1, 'tan': 1,
165
+ 'floor': 1, 'ceil': 1, 'round': 1,
166
+ 'min': 2, 'max': 2,
167
+ 'idiv': 2, 'pow': 2,
168
+ 'abs': 1, 'strlen': 1, 'strcmp': 2, 'strcpy': 1,
169
+ 'rand': 0, 'srand': 1,
170
+ 'int_to_str': 1, 'itoa': 1,
171
+ 'float_to_str': 1, 'ftoa': 1,
172
+ 'bool_to_str': 1,
173
+ 'substr': 3, 'indexof': 2,
174
+ 'upper': 1, 'lower': 1,
175
+ 'trim': 1, 'ltrim': 1, 'rtrim': 1, 'atoi': 1,
176
+ 'time': 0, 'input': 0,
177
+ }
178
+ BUILTIN_MIN_ARGS.update({k: v[1] for k, v in HOST_BUILTINS.items()})
179
+
180
+
181
+ @dataclass
182
+ class Token:
183
+ kind: str
184
+ value: Any
185
+ line: int
186
+ filename: Optional[str] = None
187
+
188
+
189
+ def tokenize(source: str,
190
+ origin: Optional[List[Optional[Tuple[str, int]]]] = None
191
+ ) -> List[Token]:
192
+ tokens: List[Token] = []
193
+ i, line, n = 0, 1, len(source)
194
+
195
+ def at_loc(ln: int) -> str:
196
+ if origin and 0 < ln < len(origin):
197
+ ent = origin[ln]
198
+ if ent is not None:
199
+ f, lineno = ent
200
+ return f"{f}:{lineno}"
201
+ return f"line {ln}"
202
+
203
+ def skip_comment_block():
204
+ nonlocal i, line
205
+ i += 2
206
+ while i < n - 1 and not (source[i] == '*' and source[i + 1] == '/'):
207
+ if source[i] == '\n':
208
+ line += 1
209
+ i += 1
210
+ i += 2
211
+
212
+ while i < n:
213
+ c = source[i]
214
+ if c == '\n':
215
+ tokens.append(Token('NL', '\n', line))
216
+ line += 1
217
+ i += 1
218
+ elif c in ' \t\r\ufeff':
219
+ i += 1
220
+ elif c == '/' and i + 1 < n and source[i + 1] == '/':
221
+ while i < n and source[i] != '\n':
222
+ i += 1
223
+ elif c == '/' and i + 1 < n and source[i + 1] == '*':
224
+ skip_comment_block()
225
+ elif c == '"':
226
+ start_line = line
227
+ i += 1
228
+ buf = []
229
+ while i < n and source[i] != '"':
230
+ if source[i] == '\\' and i + 1 < n:
231
+ esc = source[i + 1]
232
+ buf.append({'n': '\n', 't': '\t', 'r': '\r',
233
+ '"': '"', '\\': '\\', '0': '\0'}.get(esc, esc))
234
+ i += 2
235
+ else:
236
+ if source[i] == '\n':
237
+ line += 1
238
+ buf.append(source[i])
239
+ i += 1
240
+ i += 1
241
+ tokens.append(Token('STRING', ''.join(buf), start_line))
242
+ elif c.isdigit() or (c == '.' and i + 1 < n and source[i + 1].isdigit()):
243
+ start = i
244
+ is_float = False
245
+ if c == '0' and i + 1 < n and source[i + 1] in 'xXbBoO':
246
+ # 进制前缀: 0x/0X 16, 0b/0B 2, 0o/0O 8
247
+ base = {'x': 16, 'X': 16, 'b': 2, 'B': 2,
248
+ 'o': 8, 'O': 8}[source[i + 1]]
249
+ i += 2
250
+ dstart = i
251
+ allowed = ('0123456789abcdefABCDEF_' if base == 16 else
252
+ ('01_' if base == 2 else '01234567_'))
253
+ while i < n and source[i] in allowed:
254
+ i += 1
255
+ if i == dstart or not any(ch != '_' for ch in
256
+ source[dstart:i]):
257
+ raise CompilerError(f"Malformed numeric literal at "
258
+ f"{at_loc(line)}")
259
+ dend = i
260
+ # 后缀 (u/U/l/L, f/F): 64 位槽模型忽略宽度差异。
261
+ # 注意: 数值文本必须在吃后缀"之前"截取, 否则 0xFFu 会整段
262
+ # 交给 int() 而抛裸 ValueError。
263
+ while i < n and source[i] in 'uUlL':
264
+ i += 1
265
+ if i < n and source[i] in 'fF':
266
+ is_float = True
267
+ i += 1
268
+ text = source[start:dend]
269
+ norm = '0' + text[1].lower() + text[2:]
270
+ try:
271
+ value = int(norm.replace('_', ''), 0)
272
+ except ValueError:
273
+ raise CompilerError(f"Malformed numeric literal at "
274
+ f"{at_loc(line)}") from None
275
+ if value > 0xFFFFFFFFFFFFFFFF:
276
+ raise CompilerError(
277
+ f"Numeric literal out of 64-bit range at "
278
+ f"{at_loc(line)}")
279
+ else:
280
+ while i < n and (source[i].isdigit() or source[i] == '.'
281
+ or source[i] == '_'):
282
+ if source[i] == '.':
283
+ is_float = True
284
+ i += 1
285
+ if i < n and source[i] in 'eE':
286
+ is_float = True
287
+ i += 1
288
+ if i < n and source[i] in '+-':
289
+ i += 1
290
+ while i < n and (source[i].isdigit() or source[i] == '_'):
291
+ i += 1
292
+ dend = i
293
+ # 同上: 先截取数值文本, 再吃后缀
294
+ while i < n and source[i] in 'uUlL':
295
+ i += 1
296
+ if i < n and source[i] in 'fF':
297
+ is_float = True
298
+ i += 1
299
+ text = source[start:dend].replace('_', '')
300
+ try:
301
+ value = float(text) if is_float else int(text)
302
+ except ValueError:
303
+ raise CompilerError(f"Malformed numeric literal at "
304
+ f"{at_loc(line)}") from None
305
+ if not is_float and value > 0x7FFFFFFFFFFFFFFF:
306
+ raise CompilerError(
307
+ f"Numeric literal out of 64-bit range at "
308
+ f"{at_loc(line)}")
309
+ tokens.append(Token('FLOAT', float(value), line) if is_float
310
+ else Token('NUMBER', int(value), line))
311
+ elif c.isalpha() or c == '_':
312
+ start = i
313
+ while i < n and (source[i].isalnum() or source[i] == '_'):
314
+ i += 1
315
+ word = source[start:i]
316
+ tokens.append(Token('IDENT', word, line))
317
+ elif c == '-' and i + 1 < n and source[i + 1] == '>':
318
+ tokens.append(Token('ARROW', '->', line))
319
+ i += 2
320
+ elif c == "'": # 字符字面量: 'a' '\n' '\'' ...
321
+ start_line = line
322
+ i += 1
323
+ if i >= n:
324
+ raise CompilerError(f"Unterminated char literal at "
325
+ f"{at_loc(start_line)}")
326
+ if source[i] == '\\' and i + 1 < n:
327
+ esc = source[i + 1]
328
+ val = {'n': 10, 't': 9, 'r': 13, '0': 0, 'a': 7, 'b': 8,
329
+ 'f': 12, 'v': 11, "'": 39, '"': 34,
330
+ '\\': 92}.get(esc, ord(esc))
331
+ i += 2
332
+ else:
333
+ val = ord(source[i])
334
+ i += 1
335
+ if i >= n or source[i] != "'":
336
+ raise CompilerError(f"Unterminated char literal at "
337
+ f"{at_loc(start_line)}")
338
+ i += 1
339
+ tokens.append(Token('NUMBER', val, line))
340
+ elif c in ('+', '-', '*', '/', '%') and i + 1 < n and source[i + 1] == '=':
341
+ kind = {'+': 'PLUSEQ', '-': 'MINUSEQ', '*': 'STAREQ',
342
+ '/': 'SLASHEQ', '%': 'PERCENTEQ'}[c]
343
+ tokens.append(Token(kind, c + '=', line))
344
+ i += 2
345
+ elif c in ('&', '|', '^') and i + 1 < n and source[i + 1] == '=':
346
+ kind = {'&': 'ANDEQ', '|': 'OREQ', '^': 'XOREQ'}[c]
347
+ tokens.append(Token(kind, c + '=', line))
348
+ i += 2
349
+ elif c in ('<', '>') and i + 2 < n and source[i + 1] == c \
350
+ and source[i + 2] == '=':
351
+ tokens.append(Token('SHLEQ' if c == '<' else 'SHREQ',
352
+ c + c + '=', line))
353
+ i += 3
354
+ elif c in ('<', '>') and i + 1 < n and source[i + 1] == c:
355
+ tokens.append(Token('SHL' if c == '<' else 'SHR', c + c, line))
356
+ i += 2
357
+ elif c == '+' and i + 1 < n and source[i + 1] == '+':
358
+ tokens.append(Token('INC', '++', line))
359
+ i += 2
360
+ elif c == '-' and i + 1 < n and source[i + 1] == '-':
361
+ tokens.append(Token('DEC', '--', line))
362
+ i += 2
363
+ elif c == '=' and i + 1 < n and source[i + 1] == '=':
364
+ tokens.append(Token('EQ', '==', line))
365
+ i += 2
366
+ elif c == '!' and i + 1 < n and source[i + 1] == '=':
367
+ tokens.append(Token('NEQ', '!=', line))
368
+ i += 2
369
+ elif c == '<' and i + 1 < n and source[i + 1] == '=':
370
+ tokens.append(Token('LE', '<=', line))
371
+ i += 2
372
+ elif c == '>' and i + 1 < n and source[i + 1] == '=':
373
+ tokens.append(Token('GE', '>=', line))
374
+ i += 2
375
+ elif c == '&' and i + 1 < n and source[i + 1] == '&':
376
+ tokens.append(Token('AND', '&&', line))
377
+ i += 2
378
+ elif c == '|' and i + 1 < n and source[i + 1] == '|':
379
+ tokens.append(Token('OR', '||', line))
380
+ i += 2
381
+ elif c in _SINGLE_OPS:
382
+ tokens.append(Token(_SINGLE_OPS[c], c, line))
383
+ i += 1
384
+ else:
385
+ raise CompilerError(f"Unexpected character {c!r} at {at_loc(line)}")
386
+
387
+ # 行连接: 圆/方括号深度内或行尾为运算符时 NL 无效;
388
+ # 花括号 {} 块内的 NL 必须保留 (语句以换行终止)
389
+ filtered: List[Token] = []
390
+ depth = 0
391
+ open_kw = {'LPAREN', 'LBRACKET'}
392
+ close_kw = {'RPAREN', 'RBRACKET'}
393
+ continue_ops = {'PLUS', 'MINUS', 'STAR', 'SLASH', 'PERCENT', 'ASSIGN',
394
+ 'LT', 'GT', 'LE', 'GE', 'EQ', 'NEQ', 'AND', 'OR', 'COMMA',
395
+ 'ARROW', 'DOT', 'PLUSEQ', 'MINUSEQ', 'STAREQ', 'SLASHEQ',
396
+ 'PERCENTEQ', 'INC', 'DEC',
397
+ 'AMP', 'PIPE', 'CARET', 'TILDE', 'SHL', 'SHR',
398
+ 'ANDEQ', 'OREQ', 'XOREQ', 'SHLEQ', 'SHREQ'}
399
+ for tok in tokens:
400
+ if tok.kind in open_kw:
401
+ depth += 1
402
+ elif tok.kind in close_kw:
403
+ depth = max(0, depth - 1)
404
+ if tok.kind == 'NL':
405
+ if depth > 0:
406
+ continue
407
+ prev = filtered[-1] if filtered else None
408
+ if prev is not None and prev.kind in continue_ops:
409
+ continue
410
+ if filtered and filtered[-1].kind == 'NL':
411
+ continue
412
+ filtered.append(tok)
413
+ filtered.append(Token('EOF', None, line))
414
+ return filtered
415
+
416
+
417
+ # ==================== import 预处理 (B2) ====================
418
+ # import "path.cin" 仅在文件顶部/列首识别; 相对源文件目录或仓库 lib/ 目录解析;
419
+ # 同一文件每个编译仅包含一次, 循环引用报错。
420
+
421
+ _IMPORT_RE = re.compile(r'^import\s+["\']([^"\']+)["\']\s*;?\s*$')
422
+
423
+ _CODECIN_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
424
+
425
+
426
+ def _resolve_import(name: str, source_dir: str, lib_dir: str) -> str:
427
+ candidates = [os.path.join(source_dir, name),
428
+ os.path.join(lib_dir, name) if lib_dir else '',
429
+ os.path.join(_CODECIN_ROOT, name)]
430
+ for cand in candidates:
431
+ if cand and os.path.isfile(cand):
432
+ return cand
433
+ raise CompilerError(f"Import file not found: {name!r} (searched "
434
+ f"{source_dir}, {lib_dir}, {_CODECIN_ROOT})")
435
+
436
+
437
+ def _collect_module_lines(path: str, loaded: set, active: set,
438
+ out: List[Tuple[str, str]]) -> None:
439
+ """深度优先收集 (源文件, 文本行) 序列 (import 处内联展开)。
440
+
441
+ 防重复: 每个 realpath 每编译一次仅包含一次; 循环引用报错。
442
+ """
443
+ real = os.path.realpath(os.path.abspath(path))
444
+ if real in active:
445
+ raise CompilerError(f"Circular import: {path} ({real})")
446
+ if real in loaded:
447
+ return
448
+ active.add(real)
449
+ with open(real, encoding='utf-8-sig') as f:
450
+ # utf-8-sig: 容忍 Windows 编辑器写出的 BOM, 否则首行 `import ...`
451
+ # 匹配不上 _IMPORT_RE, 会报一个与真实原因无关的解析错误
452
+ lines = f.read().split('\n')
453
+ for line in lines:
454
+ m = _IMPORT_RE.match(line)
455
+ if m:
456
+ target = _resolve_import(
457
+ m.group(1), os.path.dirname(real),
458
+ os.path.join(_CODECIN_ROOT, 'lib'))
459
+ _collect_module_lines(target, loaded, active, out)
460
+ continue
461
+ out.append((real, line))
462
+ active.discard(real)
463
+ loaded.add(real)
464
+
465
+
466
+ def load_program_source_mapped(path: str) -> Tuple[str, List[Optional[Tuple[str, int]]]]:
467
+ """读取 CIN 并展开 import, 返回 (文本, 行来源表)。
468
+
469
+ origin[merged_line] = (源文件 realpath, 源文件内行号); origin[0] = None。
470
+ """
471
+ real = os.path.realpath(os.path.abspath(path))
472
+ out: List[Tuple[str, str]] = []
473
+ _collect_module_lines(real, set(), set(), out)
474
+ counters: Dict[str, int] = {}
475
+ origin: List[Optional[Tuple[str, int]]] = [None]
476
+ for fname, _line in out:
477
+ counters[fname] = counters.get(fname, 0) + 1
478
+ origin.append((fname, counters[fname]))
479
+ text = '\n'.join(line for _f, line in out)
480
+ return text, origin
481
+
482
+
483
+ def load_program_source(path: str) -> str:
484
+ """读取 CIN 文件并展开 import (返回可直接 tokenize 的源码文本)。"""
485
+ text, _origin = load_program_source_mapped(path)
486
+ return text
487
+
488
+
489
+ def _remap_tokens(tokens: List[Token], origin: List[Optional[Tuple[str, int]]]
490
+ ) -> None:
491
+ """把拼合文本中的 token 行号重定位到源文件 (file, line)。"""
492
+ for tok in tokens:
493
+ if 0 < tok.line < len(origin):
494
+ ent = origin[tok.line]
495
+ if ent is not None:
496
+ tok.filename, tok.line = ent[0], ent[1]
497
+
498
+
499
+ # ==================== 语法分析 ====================
500
+
501
+ @dataclass
502
+ class StructDef:
503
+ name: str
504
+ fields: List[Tuple[str, Any]] = field(default_factory=list) # (name, type)
505
+ offsets: Dict[str, int] = field(default_factory=dict) # qword 偏移
506
+ size_slots: int = 0
507
+
508
+
509
+ @dataclass
510
+ class FuncDef:
511
+ name: str
512
+ params: List[Tuple[str, Any]]
513
+ ret_type: Any
514
+ body: list
515
+ line: int
516
+
517
+
518
+ @dataclass
519
+ class GlobalVar:
520
+ name: str
521
+ vtype: Any
522
+ addr: int
523
+ init: Optional[list] = None # AST 表达式
524
+ array_lit: Optional[list] = None # 数组字面量行
525
+
526
+
527
+ class Parser:
528
+ def __init__(self, tokens: List[Token]):
529
+ self.toks = tokens
530
+ self.pos = 0
531
+
532
+ def peek(self, k: int = 0) -> Token:
533
+ return self.toks[min(self.pos + k, len(self.toks) - 1)]
534
+
535
+ def next(self) -> Token:
536
+ t = self.toks[self.pos]
537
+ self.pos += 1
538
+ return t
539
+
540
+ def accept(self, kind: str) -> Optional[Token]:
541
+ if self.peek().kind == kind:
542
+ return self.next()
543
+ return None
544
+
545
+ def expect(self, kind: str) -> Token:
546
+ t = self.peek()
547
+ if t.kind != kind:
548
+ raise CompilerError(f"Expected {kind} but got {t.kind} ({t.value!r}) "
549
+ f"at {self._loc(t)}")
550
+ return self.next()
551
+
552
+ def skip_nl(self) -> None:
553
+ while self.accept('NL'):
554
+ pass
555
+
556
+ def _loc(self, tok: Optional[Token] = None) -> str:
557
+ """token 的 'file:line' 定位 (import 展开后为真实源文件)。"""
558
+ t = tok if tok is not None else self.peek()
559
+ return f"{t.filename or '<cin>'}:{t.line}"
560
+
561
+ # ---------------- 类型 ----------------
562
+
563
+ def parse_type(self) -> Any:
564
+ t = self.expect('IDENT')
565
+ base = t.value
566
+ if base == 'unsigned':
567
+ # unsigned [char|short|int|long]; 缺省为 int
568
+ nxt = self.peek()
569
+ if nxt.kind == 'IDENT' and nxt.value in ('char', 'short', 'int', 'long'):
570
+ self.next()
571
+ vtype = 'int'
572
+ elif base in ('int', 'float', 'bool', 'string', 'void', 'char', 'short',
573
+ 'long'):
574
+ # char/short/long 为整数别名 (64 位槽模型, 与 int 同宽)
575
+ vtype = 'int' if base in ('char', 'short', 'long') else base
576
+ else:
577
+ vtype = ('struct', base)
578
+ # int[] / int[][] 形式 (后缀在类型名上)
579
+ while self.peek().kind == 'LBRACKET' and self.peek(1).kind == 'RBRACKET':
580
+ self.next()
581
+ self.next()
582
+ vtype = ('ptrarray', vtype)
583
+ return vtype
584
+
585
+ def _is_decl_start(self) -> bool:
586
+ """当前是否处于类型声明起始 (基础类型 / unsigned / struct 类型名)。"""
587
+ t = self.peek()
588
+ if t.kind != 'IDENT':
589
+ return False
590
+ v = t.value
591
+ if v in BASE_TYPE_WORDS:
592
+ return True
593
+ # struct 类型名 (裸标识符) 后跟另一个标识符 = 声明
594
+ return v not in _KEYWORDS and self.peek(1).kind == 'IDENT'
595
+
596
+ def parse_dims(self) -> List[int]:
597
+ dims = []
598
+ while self.peek().kind == 'LBRACKET':
599
+ self.next()
600
+ num = self.accept('NUMBER')
601
+ self.expect('RBRACKET')
602
+ dims.append(num.value if num else 0)
603
+ return dims
604
+
605
+ # ---------------- 程序 ----------------
606
+
607
+ def parse_program(self):
608
+ structs: Dict[str, StructDef] = {}
609
+ globals_: List[GlobalVar] = []
610
+ functions: Dict[str, FuncDef] = {}
611
+
612
+ self.skip_nl()
613
+ while self.peek().kind != 'EOF':
614
+ if self.peek().kind == 'IDENT' and self.peek().value == 'struct':
615
+ self._parse_struct(structs)
616
+ elif self.peek().kind == 'IDENT' and self.peek().value == 'function':
617
+ f = self._parse_function()
618
+ functions[f.name] = f
619
+ else:
620
+ self._parse_global(globals_)
621
+ self.skip_nl()
622
+ return structs, globals_, functions
623
+
624
+ def _parse_struct(self, structs: Dict[str, StructDef]) -> None:
625
+ self.next() # struct
626
+ name = self.expect('IDENT').value
627
+ self.expect('LBRACE')
628
+ self.skip_nl()
629
+ sd = StructDef(name=name)
630
+ off = 0
631
+ while self.peek().kind != 'RBRACE':
632
+ ftype = self.parse_type()
633
+ fname = self.expect('IDENT').value
634
+ dims = self.parse_dims()
635
+ t = ftype
636
+ for d in reversed(dims):
637
+ t = ('array', t, d) if d else ('ptrarray', t)
638
+ sd.fields.append((fname, t))
639
+ sd.offsets[fname] = off
640
+ off += _type_slots(t)
641
+ self.accept('SEMI')
642
+ self.skip_nl()
643
+ self.expect('RBRACE')
644
+ sd.size_slots = off
645
+ structs[name] = sd
646
+ self.accept('SEMI')
647
+
648
+ def _parse_function(self) -> FuncDef:
649
+ line = self.next().line # function
650
+ name = self.expect('IDENT').value
651
+ self.expect('LPAREN')
652
+ params: List[Tuple[str, Any]] = []
653
+ while self.peek().kind != 'RPAREN':
654
+ ptype = self.parse_type()
655
+ pname = self.expect('IDENT').value
656
+ dims = self.parse_dims()
657
+ for d in reversed(dims):
658
+ ptype = ('array', ptype, d) if d else ('ptrarray', ptype)
659
+ params.append((pname, ptype))
660
+ if not self.accept('COMMA'):
661
+ break
662
+ self.expect('RPAREN')
663
+ ret_type: Any = 'void'
664
+ if self.accept('ARROW'):
665
+ ret_type = self.parse_type()
666
+ self.expect('LBRACE')
667
+ body = self.parse_block_body(RBRACE_TOKENS)
668
+ self.expect('RBRACE')
669
+ return FuncDef(name, params, ret_type, body, line)
670
+
671
+ def _parse_global(self, globals_: List[GlobalVar]) -> None:
672
+ vtype = self.parse_type()
673
+ while True:
674
+ name = self.expect('IDENT').value
675
+ dims = self.parse_dims()
676
+ t = vtype
677
+ for d in reversed(dims):
678
+ t = ('array', t, d) if d else ('ptrarray', t)
679
+ gv = GlobalVar(name=name, vtype=t, addr=0)
680
+ if self.accept('ASSIGN'):
681
+ if self.peek().kind == 'LBRACE':
682
+ gv.array_lit = self.parse_array_literal()
683
+ else:
684
+ gv.init = self.parse_expr()
685
+ globals_.append(gv)
686
+ if not self.accept('COMMA'):
687
+ break
688
+ self.accept('SEMI')
689
+
690
+ def parse_array_literal(self) -> list:
691
+ self.expect('LBRACE')
692
+ rows: list = []
693
+ current: list = []
694
+ while self.peek().kind != 'RBRACE':
695
+ if self.accept('LBRACE'):
696
+ inner = []
697
+ while self.peek().kind != 'RBRACE':
698
+ inner.append(self.parse_expr())
699
+ if not self.accept('COMMA'):
700
+ break
701
+ self.expect('RBRACE')
702
+ rows.append(inner)
703
+ else:
704
+ current.append(self.parse_expr())
705
+ if not self.accept('COMMA'):
706
+ break
707
+ self.expect('RBRACE')
708
+ return rows if rows else current
709
+
710
+ # ---------------- 语句 ----------------
711
+
712
+ def parse_block_body(self, _unused=None) -> list:
713
+ stmts = []
714
+ self.skip_nl()
715
+ while self.peek().kind not in ('RBRACE', 'EOF'):
716
+ stmts.append(self.parse_stmt())
717
+ self.skip_nl()
718
+ return stmts
719
+
720
+ def parse_stmt(self):
721
+ t = self.peek()
722
+ if t.kind == 'LBRACE':
723
+ self.next()
724
+ body = self.parse_block_body()
725
+ self.expect('RBRACE')
726
+ return ('block', body)
727
+ if t.kind == 'IDENT' and t.value == 'assert':
728
+ return self.parse_assert()
729
+ if t.kind == 'IDENT' and t.value == 'return':
730
+ self.next()
731
+ expr = None if self.peek().kind in ('NL', 'SEMI', 'RBRACE') else self.parse_expr()
732
+ self.accept('SEMI')
733
+ return ('return', expr)
734
+ if t.kind == 'IDENT' and t.value == 'if':
735
+ return self.parse_if()
736
+ if t.kind == 'IDENT' and t.value == 'while':
737
+ self.next()
738
+ cond = self.parse_paren_expr()
739
+ body = self.parse_stmt()
740
+ return ('while', cond, body)
741
+ if t.kind == 'IDENT' and t.value == 'for':
742
+ return self.parse_for()
743
+ if t.kind == 'IDENT' and t.value == 'do':
744
+ return self.parse_do()
745
+ if t.kind == 'IDENT' and t.value == 'switch':
746
+ return self.parse_switch()
747
+ if t.kind == 'IDENT' and t.value == 'break':
748
+ self.next()
749
+ self.accept('SEMI')
750
+ return ('break',)
751
+ if t.kind == 'IDENT' and t.value == 'continue':
752
+ self.next()
753
+ self.accept('SEMI')
754
+ return ('continue',)
755
+ if self._is_decl_start():
756
+ return self.parse_decl()
757
+ if t.kind == 'IDENT' and t.value in ('set', 'add', 'subtract', 'multiply',
758
+ 'divide', 'increment', 'decrement'):
759
+ return self.parse_cpu_stmt()
760
+ # 表达式语句 / 赋值
761
+ expr = self.parse_assign()
762
+ self.accept('SEMI')
763
+ return ('expr', expr)
764
+
765
+ def parse_assign(self):
766
+ target = self.parse_expr()
767
+ t = self.peek().kind
768
+ if t == 'ASSIGN':
769
+ self.next()
770
+ value = self.parse_assign()
771
+ return ('binop', '=', target, value)
772
+ if t in _COMPOUND_ASSIGN:
773
+ self.next()
774
+ value = self.parse_assign()
775
+ return ('binop', _COMPOUND_ASSIGN[t], target, value)
776
+ return target
777
+
778
+ def parse_do(self):
779
+ self.next() # do
780
+ body = self.parse_stmt()
781
+ self.skip_nl()
782
+ if not (self.peek().kind == 'IDENT' and self.peek().value == 'while'):
783
+ raise CompilerError("Expected 'while' after do body at "
784
+ f"{self._loc()}")
785
+ self.next()
786
+ cond = self.parse_paren_expr()
787
+ self.accept('SEMI')
788
+ return ('dowhile', body, cond)
789
+
790
+ def parse_switch(self):
791
+ self.next() # switch
792
+ cond = self.parse_paren_expr()
793
+ self.expect('LBRACE')
794
+ self.skip_nl()
795
+ # branches: [('case', const_expr|None, [stmt,...])] (None = default)
796
+ branches = []
797
+ cur: Optional[Tuple[Any, list]] = None
798
+ while self.peek().kind not in ('RBRACE', 'EOF'):
799
+ self.skip_nl()
800
+ t = self.peek()
801
+ if t.kind == 'IDENT' and t.value == 'case':
802
+ if cur is not None:
803
+ branches.append(cur)
804
+ self.next()
805
+ const = self.parse_expr()
806
+ self.expect('COLON')
807
+ cur = ('case', const, [])
808
+ elif t.kind == 'IDENT' and t.value == 'default':
809
+ if cur is not None:
810
+ branches.append(cur)
811
+ self.next()
812
+ self.expect('COLON')
813
+ cur = ('case', None, [])
814
+ else:
815
+ if cur is None:
816
+ raise CompilerError(
817
+ "Statement before first case in switch at "
818
+ f"{self._loc(t)}")
819
+ cur[2].append(self.parse_stmt())
820
+ self.skip_nl()
821
+ if cur is not None:
822
+ branches.append(cur)
823
+ self.expect('RBRACE')
824
+ if not branches:
825
+ raise CompilerError(f"Empty switch at {self._loc()}")
826
+ return ('switch', cond, branches)
827
+
828
+ def parse_assert(self):
829
+ tok = self.peek()
830
+ self.next() # assert
831
+ self.expect('LPAREN')
832
+ cond = self.parse_expr()
833
+ msg = None
834
+ if self.accept('COMMA'):
835
+ msg = self.parse_expr()
836
+ self.expect('RPAREN')
837
+ self.accept('SEMI')
838
+ return ('assert', cond, msg, tok.line, tok.filename)
839
+
840
+ def parse_if(self):
841
+ self.next()
842
+ cond = self.parse_paren_expr()
843
+ then_body = self.parse_stmt()
844
+ else_body = None
845
+ self.skip_nl()
846
+ if self.peek().kind == 'IDENT' and self.peek().value == 'else':
847
+ self.next()
848
+ self.skip_nl()
849
+ else_body = self.parse_stmt()
850
+ return ('if', cond, then_body, else_body)
851
+
852
+ def parse_for(self):
853
+ self.next() # for
854
+ self.expect('LPAREN')
855
+ # init
856
+ init = None
857
+ if self.peek().kind != 'SEMI':
858
+ if self._is_decl_start():
859
+ init = self.parse_decl(no_semi=True)
860
+ else:
861
+ init = ('expr', self.parse_expr())
862
+ self.expect('SEMI')
863
+ cond = None
864
+ if self.peek().kind != 'SEMI':
865
+ cond = self.parse_expr()
866
+ self.expect('SEMI')
867
+ update = None
868
+ if self.peek().kind != 'RPAREN':
869
+ update = ('expr', self.parse_assign())
870
+ self.expect('RPAREN')
871
+ body = self.parse_stmt()
872
+ return ('for', init, cond, update, body)
873
+
874
+ def parse_decl(self, no_semi: bool = False):
875
+ vtype = self.parse_type()
876
+ decls = []
877
+ while True:
878
+ name = self.expect('IDENT').value
879
+ dims = self.parse_dims()
880
+ t = vtype
881
+ for d in reversed(dims):
882
+ t = ('array', t, d) if d else ('ptrarray', t)
883
+ init = None
884
+ array_lit = None
885
+ if self.accept('ASSIGN'):
886
+ if self.peek().kind == 'LBRACE':
887
+ array_lit = self.parse_array_literal()
888
+ else:
889
+ init = self.parse_expr()
890
+ decls.append((name, t, init, array_lit))
891
+ if not self.accept('COMMA'):
892
+ break
893
+ if not no_semi:
894
+ self.accept('SEMI')
895
+ return ('decl', decls)
896
+
897
+ def parse_cpu_stmt(self):
898
+ op = self.next().value
899
+ operands = []
900
+ while self.peek().kind not in ('NL', 'SEMI', 'EOF'):
901
+ tok = self.next()
902
+ operands.append((tok.kind, tok.value))
903
+ self.accept('SEMI')
904
+ return ('cpu', op, operands)
905
+
906
+ def parse_paren_expr(self):
907
+ self.expect('LPAREN')
908
+ e = self.parse_expr()
909
+ self.expect('RPAREN')
910
+ return e
911
+
912
+ # ---------------- 表达式 ----------------
913
+
914
+ def parse_expr(self):
915
+ e = self.parse_or()
916
+ if self.accept('QUESTION'):
917
+ a = self.parse_assign()
918
+ self.expect('COLON')
919
+ b = self.parse_assign()
920
+ return ('cond', e, a, b)
921
+ return e
922
+
923
+ def parse_or(self):
924
+ left = self.parse_and()
925
+ while self.peek().kind == 'OR':
926
+ self.next()
927
+ right = self.parse_and()
928
+ left = ('binop', '||', left, right)
929
+ return left
930
+
931
+ def parse_and(self):
932
+ left = self.parse_bit_or()
933
+ while self.peek().kind == 'AND':
934
+ self.next()
935
+ right = self.parse_bit_or()
936
+ left = ('binop', '&&', left, right)
937
+ return left
938
+
939
+ def parse_bit_or(self):
940
+ left = self.parse_bit_xor()
941
+ while self.peek().kind == 'PIPE':
942
+ self.next()
943
+ right = self.parse_bit_xor()
944
+ left = ('binop', '|', left, right)
945
+ return left
946
+
947
+ def parse_bit_xor(self):
948
+ left = self.parse_bit_and()
949
+ while self.peek().kind == 'CARET':
950
+ self.next()
951
+ right = self.parse_bit_and()
952
+ left = ('binop', '^', left, right)
953
+ return left
954
+
955
+ def parse_bit_and(self):
956
+ left = self.parse_equality()
957
+ while self.peek().kind == 'AMP':
958
+ self.next()
959
+ right = self.parse_equality()
960
+ left = ('binop', '&', left, right)
961
+ return left
962
+
963
+ def parse_equality(self):
964
+ left = self.parse_relational()
965
+ while self.peek().kind in ('EQ', 'NEQ'):
966
+ op = '==' if self.next().kind == 'EQ' else '!='
967
+ right = self.parse_relational()
968
+ left = ('binop', op, left, right)
969
+ return left
970
+
971
+ def parse_relational(self):
972
+ left = self.parse_shift()
973
+ while self.peek().kind in ('LT', 'GT', 'LE', 'GE'):
974
+ tok = self.next()
975
+ op = {'LT': '<', 'GT': '>', 'LE': '<=', 'GE': '>='}[tok.kind]
976
+ right = self.parse_shift()
977
+ left = ('binop', op, left, right)
978
+ return left
979
+
980
+ def parse_shift(self):
981
+ left = self.parse_additive()
982
+ while self.peek().kind in ('SHL', 'SHR'):
983
+ op = '<<' if self.next().kind == 'SHL' else '>>'
984
+ right = self.parse_additive()
985
+ left = ('binop', op, left, right)
986
+ return left
987
+
988
+ def parse_additive(self):
989
+ left = self.parse_multiplicative()
990
+ while self.peek().kind in ('PLUS', 'MINUS'):
991
+ op = '+' if self.next().kind == 'PLUS' else '-'
992
+ right = self.parse_multiplicative()
993
+ left = ('binop', op, left, right)
994
+ return left
995
+
996
+ def parse_multiplicative(self):
997
+ left = self.parse_unary()
998
+ while self.peek().kind in ('STAR', 'SLASH', 'PERCENT'):
999
+ tok = self.next()
1000
+ op = {'STAR': '*', 'SLASH': '/', 'PERCENT': '%'}[tok.kind]
1001
+ right = self.parse_unary()
1002
+ left = ('binop', op, left, right)
1003
+ return left
1004
+
1005
+ def parse_unary(self):
1006
+ if self.peek().kind == 'BANG':
1007
+ self.next()
1008
+ return ('not', self.parse_unary())
1009
+ if self.peek().kind == 'TILDE':
1010
+ self.next()
1011
+ return ('bitnot', self.parse_unary())
1012
+ if self.peek().kind == 'MINUS':
1013
+ self.next()
1014
+ return ('neg', self.parse_unary())
1015
+ if self.peek().kind == 'INC':
1016
+ self.next()
1017
+ return ('preinc', self.parse_unary())
1018
+ if self.peek().kind == 'DEC':
1019
+ self.next()
1020
+ return ('predec', self.parse_unary())
1021
+ return self.parse_postfix()
1022
+
1023
+ def parse_postfix(self):
1024
+ e = self.parse_primary()
1025
+ while True:
1026
+ if self.peek().kind == 'LBRACKET':
1027
+ self.next()
1028
+ idx = self.parse_expr()
1029
+ self.expect('RBRACKET')
1030
+ e = ('index', e, idx)
1031
+ elif self.peek().kind == 'DOT':
1032
+ self.next()
1033
+ name = self.expect('IDENT').value
1034
+ e = ('member', e, name)
1035
+ elif self.peek().kind == 'INC':
1036
+ self.next()
1037
+ e = ('postinc', e)
1038
+ elif self.peek().kind == 'DEC':
1039
+ self.next()
1040
+ e = ('postdec', e)
1041
+ else:
1042
+ break
1043
+ return e
1044
+
1045
+ def parse_primary(self):
1046
+ t = self.peek()
1047
+ if t.kind == 'NUMBER':
1048
+ self.next()
1049
+ return ('num', t.value, False)
1050
+ if t.kind == 'FLOAT':
1051
+ self.next()
1052
+ return ('num', t.value, True)
1053
+ if t.kind == 'STRING':
1054
+ self.next()
1055
+ return ('str', t.value)
1056
+ if t.kind == 'IDENT' and t.value == 'true':
1057
+ self.next()
1058
+ return ('bool', True)
1059
+ if t.kind == 'IDENT' and t.value == 'false':
1060
+ self.next()
1061
+ return ('bool', False)
1062
+ if t.kind == 'LPAREN':
1063
+ return self.parse_paren_expr()
1064
+ if t.kind == 'IDENT':
1065
+ name = self.next().value
1066
+ if self.peek().kind == 'LPAREN':
1067
+ self.next()
1068
+ args = []
1069
+ while self.peek().kind != 'RPAREN':
1070
+ args.append(self.parse_expr())
1071
+ if not self.accept('COMMA'):
1072
+ break
1073
+ self.expect('RPAREN')
1074
+ return ('call', name, args)
1075
+ return ('var', name)
1076
+ raise CompilerError(f"Unexpected token {t.kind} ({t.value!r}) "
1077
+ f"at {self._loc(t)}")
1078
+
1079
+
1080
+ RBRACE_TOKENS = None
1081
+
1082
+
1083
+ # ==================== 代码生成 ====================
1084
+
1085
+ class CompileResult:
1086
+ def __init__(self):
1087
+ self.instructions: List[Instruction] = []
1088
+ self.labels: Dict[str, int] = {}
1089
+ self.data_labels: Dict[str, int] = {}
1090
+ self.data_writes: List[Tuple[int, bytes]] = []
1091
+
1092
+
1093
+ class CINCompiler:
1094
+ def __init__(self, console: Optional[Console] = None, logger=None):
1095
+ self.console = console or Console()
1096
+ self.logger = logger
1097
+
1098
+ def compile(self, filename: str, bounds_check: bool = False) -> CompileResult:
1099
+ source, origin = load_program_source_mapped(filename)
1100
+ return self.compile_source(source, filename,
1101
+ bounds_check=bounds_check, origin=origin)
1102
+
1103
+ def compile_source(self, source: str, filename: str = '<cin>',
1104
+ bounds_check: bool = False,
1105
+ origin: Optional[List[Optional[Tuple[str, int]]]] = None
1106
+ ) -> CompileResult:
1107
+ dbg = self.logger.debug if (self.logger and self.logger.is_debug) \
1108
+ else (lambda msg: None)
1109
+ tokens = tokenize(source, origin)
1110
+ if origin:
1111
+ _remap_tokens(tokens, origin)
1112
+ dbg(f"CIN tokenize: {len(tokens)} tokens")
1113
+ parser = Parser(tokens)
1114
+ structs, globals_, functions = parser.parse_program()
1115
+ dbg(f"CIN parse: {len(structs)} structs, {len(globals_)} globals, "
1116
+ f"{len(functions)} functions "
1117
+ f"({', '.join(list(functions)[:8])}"
1118
+ f"{', ...' if len(functions) > 8 else ''})")
1119
+ for name, fn in functions.items():
1120
+ dbg(f"CIN function {name}: {len(fn.params)} params")
1121
+
1122
+ gen = CodeGen(structs, functions, filename=filename,
1123
+ bounds_check=bounds_check)
1124
+ gen.layout_globals(globals_)
1125
+ for name, (typ, addr, block) in gen.globals.items():
1126
+ dbg(f"CIN global '{name}': type={typ} addr=0x{addr:x} block={block}")
1127
+ result = gen.generate(globals_, functions)
1128
+ for name in functions:
1129
+ dbg(f"CIN codegen function '{name}' done")
1130
+ dbg(f"CIN codegen total: {len(result.instructions)} instructions, "
1131
+ f"{sum(len(d) for _, d in result.data_writes)} data bytes, "
1132
+ f"{len(result.labels)} labels, {len(result.data_writes)} data writes")
1133
+ return result
1134
+
1135
+
1136
+ class CodeGen:
1137
+ def __init__(self, structs: Dict[str, StructDef],
1138
+ functions: Dict[str, FuncDef], filename: str = '<cin>',
1139
+ bounds_check: bool = False):
1140
+ self.structs = structs
1141
+ self.functions = functions
1142
+ self.res = CompileResult()
1143
+ self._filename = filename
1144
+ self._bounds = bounds_check
1145
+
1146
+ self.data_ptr = 0
1147
+ self.heap_strings: Dict[str, int] = {}
1148
+
1149
+ # 函数生成上下文
1150
+ self.func: Optional[FuncDef] = None
1151
+ self.locals: Dict[str, Tuple[Any, int, bool]] = {} # name -> (type, off, is_block)
1152
+ self.frame_bytes = 0
1153
+ self.break_labels: List[str] = []
1154
+ self.continue_labels: List[str] = []
1155
+ self.label_counter = 0
1156
+
1157
+ self.globals: Dict[str, Tuple[Any, int, bool]] = {} # name -> (type, addr, is_block)
1158
+
1159
+ # ---------------- 发射辅助 ----------------
1160
+
1161
+ def emit(self, op: str, *args: Operand) -> int:
1162
+ self.res.instructions.append((op, list(args)))
1163
+ return len(self.res.instructions) - 1
1164
+
1165
+ def label(self, name: str) -> None:
1166
+ self.res.labels[name] = len(self.res.instructions)
1167
+
1168
+ def new_label(self, hint: str) -> str:
1169
+ self.label_counter += 1
1170
+ return f"_{hint}_{self.label_counter}"
1171
+
1172
+ @staticmethod
1173
+ def reg(n: int) -> Operand:
1174
+ return ('reg', n)
1175
+
1176
+ @staticmethod
1177
+ def imm(v: int) -> Operand:
1178
+ return ('imm', v & 0xFFFFFFFFFFFFFFFF)
1179
+
1180
+ def lab(self, name: str) -> Operand:
1181
+ return ('label', name)
1182
+
1183
+ # ---------------- 数据段 ----------------
1184
+
1185
+ def _alloc_data(self, nbytes: int, align: int = 8) -> int:
1186
+ if align > 1:
1187
+ self.data_ptr = (self.data_ptr + align - 1) & ~(align - 1)
1188
+ addr = self.data_ptr
1189
+ self.data_ptr += nbytes
1190
+ return addr
1191
+
1192
+ def _data_string(self, text: str) -> int:
1193
+ if text in self.heap_strings:
1194
+ return self.heap_strings[text]
1195
+ data = text.encode('utf-8') + b'\x00'
1196
+ addr = self._alloc_data(len(data), align=1)
1197
+ self.res.data_writes.append((addr, data))
1198
+ self.res.data_labels[f'str_{addr:x}'] = addr
1199
+ self.heap_strings[text] = addr
1200
+ return addr
1201
+
1202
+ def _data_qword(self, value: int) -> int:
1203
+ addr = self._alloc_data(8)
1204
+ self.res.data_writes.append((addr, struct.pack('<Q', value & 0xFFFFFFFFFFFFFFFF)))
1205
+ return addr
1206
+
1207
+ def layout_globals(self, globals_: List[GlobalVar]) -> None:
1208
+ for gv in globals_:
1209
+ t = gv.vtype
1210
+ if _is_fixed_array(t):
1211
+ addr = self._alloc_data(_type_slots(t) * 8)
1212
+ self.globals[gv.name] = (t, addr, True)
1213
+ gv.addr = addr
1214
+ else:
1215
+ addr = self._alloc_data(8)
1216
+ self.globals[gv.name] = (t, addr, False)
1217
+ gv.addr = addr
1218
+ if _is_struct(t):
1219
+ sd = self.structs[t[1]]
1220
+ block = self._alloc_data(sd.size_slots * 8)
1221
+ self.res.data_writes.append(
1222
+ (addr, struct.pack('<Q', block)))
1223
+
1224
+ # ---------------- 初始化数据 ----------------
1225
+
1226
+ def _const_value(self, node) -> Tuple[Any, int]:
1227
+ """编译期常量 (全局初始化用): 返回 (type, raw_bits/addr)。"""
1228
+ kind = node[0]
1229
+ if kind == 'num':
1230
+ if node[2]:
1231
+ return 'float', struct.unpack('<Q', struct.pack('<d', node[1]))[0]
1232
+ return 'int', node[1] & 0xFFFFFFFFFFFFFFFF
1233
+ if kind == 'bool':
1234
+ return 'bool', 1 if node[1] else 0
1235
+ if kind == 'str':
1236
+ return 'string', self._data_string(node[1])
1237
+ if kind == 'neg' and node[1][0] == 'num':
1238
+ inner = node[1]
1239
+ if inner[2]:
1240
+ return 'float', struct.unpack('<Q', struct.pack('<d', -inner[1]))[0]
1241
+ return 'int', (-inner[1]) & 0xFFFFFFFFFFFFFFFF
1242
+ if kind == 'bitnot':
1243
+ ctype, raw = self._const_value(node[1])
1244
+ if ctype not in ('int', 'bool'):
1245
+ raise CompilerError(f"Bitwise NOT requires integer, got: {ctype}")
1246
+ return 'int', (~raw) & 0xFFFFFFFFFFFFFFFF
1247
+ raise CompilerError(f"Non-constant global initializer: {kind}")
1248
+
1249
+ def emit_globals_init(self, globals_: List[GlobalVar]) -> None:
1250
+ for gv in globals_:
1251
+ t, addr, is_block = self.globals[gv.name]
1252
+ if gv.init is not None:
1253
+ ctype, raw = self._const_value(gv.init)
1254
+ self.res.data_writes.append((addr, struct.pack('<Q', raw)))
1255
+ elif gv.array_lit is not None:
1256
+ rows = gv.array_lit
1257
+ if rows and isinstance(rows[0], list):
1258
+ # 2D 字面量: 仅 ptrarray 有意义 (int[][] mat1 = ...)
1259
+ # 全局 2D 定长数组按行写入
1260
+ for i, row in enumerate(rows):
1261
+ for j, elem in enumerate(row):
1262
+ _, raw = self._const_value(elem)
1263
+ self.res.data_writes.append(
1264
+ (addr + (i * len(row) + j) * 8, struct.pack('<Q', raw)))
1265
+ else:
1266
+ for i, elem in enumerate(rows):
1267
+ _, raw = self._const_value(elem)
1268
+ self.res.data_writes.append((addr + i * 8, struct.pack('<Q', raw)))
1269
+
1270
+ # ---------------- 主生成 ----------------
1271
+
1272
+ def generate(self, globals_: List[GlobalVar],
1273
+ functions: Dict[str, FuncDef]) -> CompileResult:
1274
+ self.emit_globals_init(globals_)
1275
+
1276
+ # 入口: CALL main; HALT
1277
+ self.emit('CALL', self.lab('main'))
1278
+ self.emit('HALT')
1279
+
1280
+ for _fname, fdef in functions.items():
1281
+ self.gen_function(fdef)
1282
+
1283
+ return self.res
1284
+
1285
+ # ---------------- 栈帧 ----------------
1286
+
1287
+ def _prescan_locals(self, body: list) -> List[Tuple[str, Any, int]]:
1288
+ """收集函数内所有局部声明 (含 for 初始化), 返回 (name,type,slots)。"""
1289
+ found: List[Tuple[str, Any, int]] = []
1290
+ seen = set()
1291
+
1292
+ def walk(stmts):
1293
+ for s in stmts:
1294
+ kind = s[0]
1295
+ if kind == 'decl':
1296
+ for name, t, _init, _al in s[1]:
1297
+ if name in seen:
1298
+ continue
1299
+ seen.add(name)
1300
+ found.append((name, t, _type_slots(t)))
1301
+ elif kind == 'block':
1302
+ walk(s[1])
1303
+ elif kind == 'if':
1304
+ walk([s[2]])
1305
+ if s[3]:
1306
+ walk([s[3]])
1307
+ elif kind == 'while':
1308
+ walk([s[2]])
1309
+ elif kind == 'dowhile':
1310
+ walk([s[1]])
1311
+ elif kind == 'switch':
1312
+ for _bk, _const, stmts in s[2]:
1313
+ walk(stmts)
1314
+ elif kind == 'for':
1315
+ if s[1] is not None and s[1][0] == 'decl':
1316
+ for name, t, _i, _a in s[1][1]:
1317
+ if name not in seen:
1318
+ seen.add(name)
1319
+ found.append((name, t, _type_slots(t)))
1320
+ walk([s[4]])
1321
+ walk(body)
1322
+ return found
1323
+
1324
+ def gen_function(self, f: FuncDef) -> None:
1325
+ self.func = f
1326
+ self.locals = {}
1327
+ self.break_labels = []
1328
+ self.continue_labels = []
1329
+
1330
+ # 局部变量布局 (自 FP 向下分配):
1331
+ # 标量槽地址 = fp-(8+off); 数组块基址 = fp-(off+slots*8)
1332
+ # (元素从基址向高地址生长, 不与后续变量冲突)
1333
+ locals_info = self._prescan_locals(f.body)
1334
+ off = 0
1335
+ for name, t, slots in locals_info:
1336
+ self.locals[name] = (t, -(off + slots * 8), _is_fixed_array(t))
1337
+ off += slots * 8
1338
+ self.frame_bytes = off
1339
+
1340
+ # 参数位置 (相对 FP): fp+16 为第一个压栈参数 (最左)
1341
+ # 帧布局: [参数...][返回地址(fp+8)][保存的FP(fp)][局部...]
1342
+ nargs = len(f.params)
1343
+ for k, (pname, ptype) in enumerate(f.params):
1344
+ poff = 16 + (nargs - 1 - k) * 8
1345
+ self.locals[pname] = (ptype, poff, False)
1346
+
1347
+ self.label(f.name)
1348
+ # prologue: 保存调用方 FP, 建立帧指针, 分配局部空间
1349
+ self.emit('PUSH', self.reg(29))
1350
+ self.emit('MOV', self.reg(29), self.reg(32)) # FP = SP
1351
+ if self.frame_bytes:
1352
+ self.emit('ADDI', self.reg(0), self.reg(32), self.imm(-self.frame_bytes))
1353
+ self.emit('MOV', self.reg(32), self.reg(0))
1354
+
1355
+ # struct 局部变量: 堆分配对象
1356
+ for _name, (t, loff, _is_block) in list(self.locals.items()):
1357
+ if _is_struct(t) and loff < 0:
1358
+ sd = self.structs[t[1]]
1359
+ self.emit('MOV', self.reg(0), self.imm(sd.size_slots * 8))
1360
+ self.emit('SYS', self.imm(Syscall.MALLOC))
1361
+ self.emit('MOV', self.reg(2), self.reg(0)) # 对象指针
1362
+ self._addr_local(loff) # x0 = &slot
1363
+ self.emit('SD', self.reg(2), ('mem', 0, 0))
1364
+
1365
+ self.gen_stmts(f.body)
1366
+
1367
+ # epilogue
1368
+ self._epilogue()
1369
+
1370
+ def _epilogue(self) -> None:
1371
+ # 不得破坏 x0 (返回值)
1372
+ self.emit('MOV', self.reg(6), self.reg(29)) # SP = FP
1373
+ self.emit('MOV', self.reg(32), self.reg(6))
1374
+ self.emit('POP', self.reg(29)) # 恢复调用方 FP
1375
+ self.emit('RET')
1376
+
1377
+ def _addr_local(self, off: int) -> None:
1378
+ """x0 = FP + off (局部 off 为负, 参数 off 为正)。"""
1379
+ if off == 0:
1380
+ self.emit('MOV', self.reg(0), self.reg(29))
1381
+ else:
1382
+ self.emit('ADDI', self.reg(0), self.reg(29), self.imm(off))
1383
+
1384
+ def _addr_var(self, name: str) -> None:
1385
+ """x0 = 变量槽地址。"""
1386
+ if name in self.locals:
1387
+ _t, off, _is_block = self.locals[name]
1388
+ self._addr_local(off)
1389
+ elif name in self.globals:
1390
+ _t, addr, _is_block = self.globals[name]
1391
+ self.emit('MOV', self.reg(0), self.imm(addr))
1392
+ else:
1393
+ raise CompilerError(f"Undefined variable: {name}")
1394
+
1395
+ def _var_type(self, name: str):
1396
+ if name in self.locals:
1397
+ return self.locals[name][0]
1398
+ if name in self.globals:
1399
+ return self.globals[name][0]
1400
+ return None
1401
+
1402
+ # ---------------- 语句 ----------------
1403
+
1404
+ def gen_stmts(self, stmts: list) -> None:
1405
+ for s in stmts:
1406
+ self.gen_stmt(s)
1407
+
1408
+ def gen_stmt(self, s) -> None:
1409
+ kind = s[0]
1410
+ if kind == 'block':
1411
+ self.gen_stmts(s[1])
1412
+ elif kind == 'return':
1413
+ if s[1] is not None:
1414
+ t = self.gen_value(s[1])
1415
+ self._convert(t, self.func.ret_type)
1416
+ self._epilogue()
1417
+ elif kind == 'if':
1418
+ self.gen_if(s[1], s[2], s[3])
1419
+ elif kind == 'while':
1420
+ self.gen_while(s[1], s[2])
1421
+ elif kind == 'for':
1422
+ self.gen_for(s[1], s[2], s[3], s[4])
1423
+ elif kind == 'dowhile':
1424
+ self.gen_dowhile(s[1], s[2])
1425
+ elif kind == 'switch':
1426
+ self.gen_switch(s[1], s[2])
1427
+ elif kind == 'break':
1428
+ if not self.break_labels:
1429
+ raise CompilerError("break outside loop")
1430
+ self.emit('JMP', self.lab(self.break_labels[-1]))
1431
+ elif kind == 'continue':
1432
+ if not self.continue_labels:
1433
+ raise CompilerError("continue outside loop")
1434
+ self.emit('JMP', self.lab(self.continue_labels[-1]))
1435
+ elif kind == 'decl':
1436
+ self.gen_decl(s[1])
1437
+ elif kind == 'cpu':
1438
+ self.gen_cpu_stmt(s[1], s[2])
1439
+ elif kind == 'assert':
1440
+ self.gen_assert(s[1], s[2], s[3],
1441
+ s[4] if len(s) > 4 else self._filename)
1442
+ elif kind == 'expr':
1443
+ self.gen_expr_stmt(s[1])
1444
+
1445
+ def gen_if(self, cond, then_body, else_body) -> None:
1446
+ l_else = self.new_label('else')
1447
+ l_end = self.new_label('endif')
1448
+ target = l_else if else_body is not None else l_end
1449
+ self.gen_cond_jump_false(cond, target)
1450
+ self.gen_stmt(then_body)
1451
+ if else_body is not None:
1452
+ self.emit('JMP', self.lab(l_end))
1453
+ self.label(l_else)
1454
+ self.gen_stmt(else_body)
1455
+ self.label(l_end)
1456
+
1457
+ def gen_while(self, cond, body) -> None:
1458
+ l_start = self.new_label('while')
1459
+ l_end = self.new_label('wend')
1460
+ self.label(l_start)
1461
+ self.gen_cond_jump_false(cond, l_end)
1462
+ self.break_labels.append(l_end)
1463
+ self.continue_labels.append(l_start)
1464
+ self.gen_stmt(body)
1465
+ self.emit('JMP', self.lab(l_start))
1466
+ self.break_labels.pop()
1467
+ self.continue_labels.pop()
1468
+ self.label(l_end)
1469
+
1470
+ def gen_for(self, init, cond, update, body) -> None:
1471
+ if init is not None:
1472
+ self.gen_stmt(init)
1473
+ l_cond = self.new_label('forc')
1474
+ l_update = self.new_label('foru')
1475
+ l_end = self.new_label('fore')
1476
+ self.label(l_cond)
1477
+ if cond is not None:
1478
+ self.gen_cond_jump_false(cond, l_end)
1479
+ self.break_labels.append(l_end)
1480
+ self.continue_labels.append(l_update)
1481
+ self.gen_stmt(body)
1482
+ self.label(l_update)
1483
+ if update is not None:
1484
+ self.gen_stmt(update)
1485
+ self.emit('JMP', self.lab(l_cond))
1486
+ self.break_labels.pop()
1487
+ self.continue_labels.pop()
1488
+ self.label(l_end)
1489
+
1490
+ def gen_dowhile(self, body, cond) -> None:
1491
+ l_body = self.new_label('dbody')
1492
+ l_cond = self.new_label('dcond')
1493
+ l_end = self.new_label('dend')
1494
+ self.label(l_body)
1495
+ self.break_labels.append(l_end)
1496
+ self.continue_labels.append(l_cond)
1497
+ self.gen_stmt(body)
1498
+ self.label(l_cond)
1499
+ self.gen_cond_jump_false(cond, l_end)
1500
+ self.emit('JMP', self.lab(l_body))
1501
+ self.break_labels.pop()
1502
+ self.continue_labels.pop()
1503
+ self.label(l_end)
1504
+
1505
+ def gen_switch(self, cond, branches) -> None:
1506
+ """switch: 选择器压栈, CMP 链分派, case 体按文字顺序内联 (C 贯穿语义)。"""
1507
+ sel_t = self._expr_type(cond)
1508
+ if sel_t not in ('int', 'bool'):
1509
+ raise CompilerError(
1510
+ f"Switch expression must be integer, got: {sel_t}")
1511
+ l_end = self.new_label('swend')
1512
+ self.break_labels.append(l_end)
1513
+ # continue 必须先把选择器弹出再跳, 否则每轮迭代泄漏 8 字节栈直至撞堆。
1514
+ # 只有在循环内 (存在外层 continue 目标) 才接管 continue, 否则保持
1515
+ # "continue outside loop" 报错语义。
1516
+ outer_cont = self.continue_labels[-1] if self.continue_labels else None
1517
+ l_cont = None
1518
+ if outer_cont is not None:
1519
+ l_cont = self.new_label('swcont')
1520
+ self.continue_labels.append(l_cont)
1521
+ self.gen_value(cond)
1522
+ self.emit('PUSH', self.reg(0)) # [SP] = selector
1523
+
1524
+ labels: List[Tuple[Optional[int], str]] = []
1525
+ default_lbl: Optional[str] = None
1526
+ for _kind, const, _stmts in branches:
1527
+ if const is None:
1528
+ lbl = self.new_label('swdef')
1529
+ default_lbl = lbl
1530
+ labels.append((None, lbl))
1531
+ continue
1532
+ try:
1533
+ ctype, raw = self._const_value(const)
1534
+ except CompilerError:
1535
+ raise CompilerError(
1536
+ "case value must be an integer constant") from None
1537
+ if ctype not in ('int', 'bool'):
1538
+ raise CompilerError(
1539
+ f"case value must be an integer constant, got: {ctype}")
1540
+ labels.append((raw & 0xFFFFFFFFFFFFFFFF, self.new_label('swcase')))
1541
+
1542
+ # 分派比较链
1543
+ for raw, lbl in labels:
1544
+ if raw is None:
1545
+ continue
1546
+ self.emit('LD', self.reg(0), ('mem', 32, 0))
1547
+ self.emit('MOV', self.reg(1), self.imm(raw))
1548
+ self.emit('CMP', self.reg(0), self.reg(1))
1549
+ self.emit('B', self.lab(lbl), ('cond', 'EQ'))
1550
+ self.emit('JMP', self.lab(default_lbl if default_lbl is not None
1551
+ else l_end))
1552
+
1553
+ # case/default 体 (inline, 贯穿)
1554
+ for idx, (_kind, _const, stmts) in enumerate(branches):
1555
+ self.label(labels[idx][1])
1556
+ self.gen_stmts(stmts)
1557
+
1558
+ # 贯穿到末尾与 break 都必须走弹出选择器的路径
1559
+ self.emit('JMP', self.lab(l_end))
1560
+ if l_cont is not None:
1561
+ self.label(l_cont)
1562
+ self.emit('ADDI', self.reg(32), self.reg(32), self.imm(8))
1563
+ self.emit('JMP', self.lab(outer_cont))
1564
+ self.continue_labels.pop()
1565
+ self.label(l_end)
1566
+ self.break_labels.pop()
1567
+ self.emit('ADDI', self.reg(32), self.reg(32), self.imm(8)) # 丢 selector
1568
+
1569
+ def gen_decl(self, decls) -> None:
1570
+ for name, t, init, array_lit in decls:
1571
+ if array_lit is not None:
1572
+ if array_lit and isinstance(array_lit[0], list):
1573
+ self.gen_init_2d_literal(name, t, array_lit)
1574
+ else:
1575
+ self.gen_init_1d_literal(name, t, array_lit)
1576
+ continue
1577
+ if init is not None:
1578
+ vt = self.gen_value(init)
1579
+ self._convert(vt, t)
1580
+ # x0 = value; 存到变量槽
1581
+ self.emit('MOV', self.reg(2), self.reg(0))
1582
+ self._addr_var(name)
1583
+ self.emit('SD', self.reg(2), ('mem', 0, 0))
1584
+ elif _is_ptr_array(t) and _is_ptr_array(_array_elem(t)):
1585
+ # int[][] result (无尺寸): 预分配 64 个行指针
1586
+ self.emit('MOV', self.reg(0), self.imm(64 * 8))
1587
+ self.emit('SYS', self.imm(Syscall.MALLOC))
1588
+ self.emit('MOV', self.reg(2), self.reg(0))
1589
+ self._addr_var(name)
1590
+ self.emit('SD', self.reg(2), ('mem', 0, 0))
1591
+
1592
+ def gen_init_1d_literal(self, name: str, t, elems: list) -> None:
1593
+ # 定长 1D 数组: 就地写入 (每轮重新取基址, 避免地址累加)
1594
+ elem_t = _array_elem(t) if _is_fixed_array(t) else 'int'
1595
+ for i, elem in enumerate(elems):
1596
+ vt = self.gen_value(elem)
1597
+ self._convert(vt, elem_t)
1598
+ self.emit('MOV', self.reg(2), self.reg(0)) # value
1599
+ self._addr_var(name) # x0 = base
1600
+ if i:
1601
+ self.emit('ADDI', self.reg(0), self.reg(0), self.imm(i * 8))
1602
+ self.emit('SD', self.reg(2), ('mem', 0, 0))
1603
+
1604
+ def gen_init_2d_literal(self, name: str, t, rows: list) -> None:
1605
+ # int[][] mat1 = {{...},{...}}: 堆分配行指针数组 + 每行
1606
+ nrows = len(rows)
1607
+ ncols = max(len(r) for r in rows)
1608
+ # 外层: nrows 个指针
1609
+ self.emit('MOV', self.reg(0), self.imm(nrows * 8))
1610
+ self.emit('SYS', self.imm(Syscall.MALLOC))
1611
+ self.emit('MOV', self.reg(4), self.reg(0)) # outer
1612
+ for i, row in enumerate(rows):
1613
+ self.emit('MOV', self.reg(0), self.imm(max(ncols, 1) * 8))
1614
+ self.emit('SYS', self.imm(Syscall.MALLOC))
1615
+ self.emit('MOV', self.reg(5), self.reg(0)) # row ptr
1616
+ # outer[i] = row ptr
1617
+ self.emit('MOV', self.reg(0), self.reg(4))
1618
+ self.emit('ADDI', self.reg(0), self.reg(0), self.imm(i * 8))
1619
+ self.emit('SD', self.reg(5), ('mem', 0, 0))
1620
+ for j, elem in enumerate(row):
1621
+ vt = self.gen_value(elem)
1622
+ self._convert(vt, 'int')
1623
+ self.emit('MOV', self.reg(2), self.reg(0))
1624
+ self.emit('MOV', self.reg(0), self.reg(5))
1625
+ if j:
1626
+ self.emit('ADDI', self.reg(0), self.reg(0), self.imm(j * 8))
1627
+ self.emit('SD', self.reg(2), ('mem', 0, 0))
1628
+ # 保存 outer 到变量槽
1629
+ self.emit('MOV', self.reg(2), self.reg(4))
1630
+ self._addr_var(name)
1631
+ self.emit('SD', self.reg(2), ('mem', 0, 0))
1632
+
1633
+ def gen_cpu_stmt(self, op: str, operands: list) -> None:
1634
+ def operand_value(operand):
1635
+ kind, val = operand
1636
+ if kind == 'NUMBER':
1637
+ return val
1638
+ if kind == 'IDENT':
1639
+ return ('var', val)
1640
+ raise CompilerError(f"Bad CPU-style operand: {operand}")
1641
+
1642
+ if op in ('increment', 'decrement'):
1643
+ varname = operands[0][1]
1644
+ self._addr_var(varname)
1645
+ self.emit('LD', self.reg(0), ('mem', 0, 0))
1646
+ self.emit('INC' if op == 'increment' else 'DEC', self.reg(0))
1647
+ self.emit('MOV', self.reg(2), self.reg(0))
1648
+ self._addr_var(varname)
1649
+ self.emit('SD', self.reg(2), ('mem', 0, 0))
1650
+ return
1651
+
1652
+ varname = operands[0][1]
1653
+ rhs = operand_value(operands[1]) if len(operands) > 1 else None
1654
+
1655
+ if op == 'set':
1656
+ if isinstance(rhs, tuple):
1657
+ self.gen_value(rhs)
1658
+ else:
1659
+ self.emit('MOV', self.reg(0), self.imm(int(rhs)))
1660
+ else:
1661
+ # add/subtract/multiply/divide: var = var op rhs (整数)
1662
+ self._addr_var(varname)
1663
+ self.emit('LD', self.reg(0), ('mem', 0, 0))
1664
+ if isinstance(rhs, tuple):
1665
+ self.emit('MOV', self.reg(2), self.reg(0))
1666
+ self.gen_value(rhs)
1667
+ self.emit('MOV', self.reg(1), self.reg(0))
1668
+ self.emit('MOV', self.reg(0), self.reg(2))
1669
+ else:
1670
+ self.emit('MOV', self.reg(1), self.imm(int(rhs)))
1671
+ op_map = {'add': 'ADD', 'subtract': 'SUB',
1672
+ 'multiply': 'MUL', 'divide': 'DIV'}
1673
+ self.emit(op_map[op], self.reg(0), self.reg(1))
1674
+ self.emit('MOV', self.reg(2), self.reg(0))
1675
+ self._addr_var(varname)
1676
+ self.emit('SD', self.reg(2), ('mem', 0, 0))
1677
+
1678
+ def gen_expr_stmt(self, node) -> None:
1679
+ # 赋值
1680
+ if node[0] == 'binop' and node[1] == '=':
1681
+ pass
1682
+ # parse 不产生 '=' binop; 赋值在 parse 层未处理, 这里检测 call/var 链
1683
+ self.gen_value(node)
1684
+
1685
+ # ---------------- 运行时断言 / 中止 (A1) ----------------
1686
+
1687
+ def _runtime_abort(self, text: str) -> None:
1688
+ """SYS ABORT: 加载静态消息指针并抛出运行时错误。"""
1689
+ addr = self._data_string(text)
1690
+ self.emit('MOV', self.reg(0), self.imm(addr))
1691
+ self.emit('SYS', self.imm(Syscall.ABORT))
1692
+
1693
+ def gen_assert(self, cond, msg, line: int,
1694
+ filename: Optional[str] = None) -> None:
1695
+ """assert(cond [, msg]) → 条件不成立时运行时中止 (定位: filename:line)。"""
1696
+ l_ok = self.new_label('assertok')
1697
+ self.gen_cond_jump_true(cond, l_ok)
1698
+ if msg is None:
1699
+ self._runtime_abort(
1700
+ f"{(filename or self._filename)}:{line}: assertion failed")
1701
+ else:
1702
+ # [prefix] + 消息 (消息支持任意表达式, 自动字符串化)
1703
+ prefix = self._data_string(
1704
+ f"[assert {(filename or self._filename)}:{line}] ")
1705
+ self.emit('MOV', self.reg(0), self.imm(prefix))
1706
+ self.emit('PUSH', self.reg(0))
1707
+ self._gen_string_value(msg)
1708
+ self.emit('MOV', self.reg(1), self.reg(0))
1709
+ self.emit('POP', self.reg(0))
1710
+ self.emit('SYS', self.imm(Syscall.STR_CONCAT))
1711
+ self.emit('SYS', self.imm(Syscall.ABORT))
1712
+ self.label(l_ok)
1713
+
1714
+ # ---------------- 类型转换 ----------------
1715
+
1716
+ def _convert(self, from_type, to_type) -> None:
1717
+ """将 x0 从 from_type 转换为 to_type (原地)。"""
1718
+ if to_type is None or from_type is None:
1719
+ return
1720
+ if from_type == to_type:
1721
+ return
1722
+ if from_type == 'int' and to_type == 'float':
1723
+ self.emit('SYS', self.imm(Syscall.ITOF))
1724
+ elif from_type == 'float' and to_type == 'int':
1725
+ self.emit('SYS', self.imm(Syscall.FTOI))
1726
+ elif from_type == 'bool' and to_type in ('int', 'float'):
1727
+ if to_type == 'float':
1728
+ self.emit('SYS', self.imm(Syscall.ITOF))
1729
+ elif from_type == 'int' and to_type == 'bool':
1730
+ pass
1731
+ # string/struct/array 指针无需转换
1732
+
1733
+ # ---------------- 表达式 ----------------
1734
+
1735
+ def gen_value(self, node) -> Any:
1736
+ """求值表达式到 x0, 返回 CIN 类型。"""
1737
+ kind = node[0]
1738
+ if kind == 'num':
1739
+ if node[2]:
1740
+ bits = struct.unpack('<Q', struct.pack('<d', float(node[1])))[0]
1741
+ self.emit('MOV', self.reg(0), self.imm(bits))
1742
+ return 'float'
1743
+ self.emit('MOV', self.reg(0), self.imm(int(node[1])))
1744
+ return 'int'
1745
+ if kind == 'bool':
1746
+ self.emit('MOV', self.reg(0), self.imm(1 if node[1] else 0))
1747
+ return 'bool'
1748
+ if kind == 'str':
1749
+ self.emit('MOV', self.reg(0), self.imm(self._data_string(node[1])))
1750
+ return 'string'
1751
+ if kind == 'var':
1752
+ return self._gen_var_value(node[1])
1753
+ if kind == 'member':
1754
+ return self._gen_member(node[1], node[2], lvalue=False)
1755
+ if kind == 'index':
1756
+ return self._gen_index(node[1], node[2], lvalue=False)
1757
+ if kind == 'call':
1758
+ return self._gen_call(node[1], node[2])
1759
+ if kind == 'neg':
1760
+ t = self.gen_value(node[1])
1761
+ self.emit('MOV', self.reg(1), self.reg(0))
1762
+ if t == 'float':
1763
+ # 浮点: 0.0 - x (x1 为 float64 位模式)
1764
+ self.emit('MOV', self.reg(0), self.imm(0))
1765
+ self.emit('SYS', self.imm(Syscall.ITOF))
1766
+ self.emit('SYS', self.imm(Syscall.FSUB))
1767
+ else:
1768
+ self.emit('MOV', self.reg(0), self.imm(0))
1769
+ self.emit('SUB', self.reg(0), self.reg(1))
1770
+ return t
1771
+ if kind == 'not':
1772
+ t = self.gen_value(node[1])
1773
+ self.emit('XORI', self.reg(0), self.reg(0), self.imm(1))
1774
+ return 'bool'
1775
+ if kind == 'bitnot':
1776
+ t = self.gen_value(node[1])
1777
+ if t in ('float', 'string'):
1778
+ raise CompilerError("Bitwise NOT '~' requires an integer operand")
1779
+ self.emit('MVN', self.reg(0), self.reg(0))
1780
+ return 'int'
1781
+ if kind in ('preinc', 'predec', 'postinc', 'postdec'):
1782
+ return self._gen_incdec(kind, node[1])
1783
+ if kind == 'cond':
1784
+ return self._gen_ternary(node[1], node[2], node[3])
1785
+ if kind == 'binop':
1786
+ return self._gen_binop(node[1], node[2], node[3])
1787
+ raise CompilerError(f"Cannot generate code for expression: {kind}")
1788
+
1789
+ def _gen_var_value(self, name: str) -> Any:
1790
+ t = self._var_type(name)
1791
+ if t is None:
1792
+ raise CompilerError(f"Undefined variable: {name}")
1793
+ is_block = False
1794
+ if name in self.locals:
1795
+ is_block = self.locals[name][2]
1796
+ elif name in self.globals:
1797
+ is_block = self.globals[name][2]
1798
+ if is_block:
1799
+ # 定长数组: 值 = 块地址
1800
+ self._addr_var(name)
1801
+ return t
1802
+ self._addr_var(name)
1803
+ self.emit('LD', self.reg(0), ('mem', 0, 0))
1804
+ return t
1805
+
1806
+ def _gen_lvalue_addr(self, node) -> None:
1807
+ """求值左值地址到 x0。"""
1808
+ kind = node[0]
1809
+ if kind == 'var':
1810
+ self._addr_var(node[1])
1811
+ return
1812
+ if kind == 'member':
1813
+ self._gen_member(node[1], node[2], lvalue=True)
1814
+ return
1815
+ if kind == 'index':
1816
+ self._gen_index(node[1], node[2], lvalue=True)
1817
+ return
1818
+ raise CompilerError(f"Invalid assignment target: {kind}")
1819
+
1820
+ def _struct_field(self, struct_type, fname: str) -> Tuple[Any, int]:
1821
+ sd = self.structs[struct_type[1]]
1822
+ if fname not in sd.offsets:
1823
+ raise CompilerError(f"Struct {struct_type[1]} has no field {fname}")
1824
+ ftype = dict(sd.fields)[fname]
1825
+ return ftype, sd.offsets[fname]
1826
+
1827
+ def _gen_member(self, obj_node, fname: str, lvalue: bool):
1828
+ obj_t = self.gen_value(obj_node) # x0 = struct 指针
1829
+ if not _is_struct(obj_t):
1830
+ raise CompilerError(f"Member access on non-struct type: {obj_t}")
1831
+ ftype, foff = self._struct_field(obj_t, fname)
1832
+ if lvalue:
1833
+ if foff:
1834
+ self.emit('ADDI', self.reg(0), self.reg(0), self.imm(foff * 8))
1835
+ return None
1836
+ # 值
1837
+ if _is_fixed_array(ftype):
1838
+ # 内联数组: 值 = 字段地址, 类型退化为指针视图
1839
+ if foff:
1840
+ self.emit('ADDI', self.reg(0), self.reg(0), self.imm(foff * 8))
1841
+ return self._decay(ftype)
1842
+ self.emit('MOV', self.reg(1), self.reg(0))
1843
+ if foff:
1844
+ self.emit('ADDI', self.reg(1), self.reg(1), self.imm(foff * 8))
1845
+ self.emit('LD', self.reg(0), ('mem', 1, 0))
1846
+ return ftype
1847
+
1848
+ @staticmethod
1849
+ def _decay(t):
1850
+ """定长数组作为指针值时的类型视图。"""
1851
+ if _is_fixed_array(t):
1852
+ elem = t[1]
1853
+ if _is_fixed_array(elem):
1854
+ return ('array', elem, t[2]) # 多维: 子数组仍定长
1855
+ return ('ptrarray', elem)
1856
+ return t
1857
+
1858
+ def _gen_index(self, base_node, idx_node, lvalue: bool):
1859
+ base_t = self.gen_value(base_node) # 定长数组=块地址; ptrarray=指针; string=ptr
1860
+ if base_t == 'string':
1861
+ if lvalue:
1862
+ raise CompilerError(
1863
+ "Cannot assign to string element (strings are immutable)")
1864
+ self.emit('MOV', self.reg(3), self.reg(0)) # x3 = 字符串基址
1865
+ self.gen_value(idx_node) # x0 = index
1866
+ self.emit('ADD', self.reg(0), self.reg(3)) # x0 = base + i (字节偏移)
1867
+ self.emit('LB', self.reg(0), ('mem', 0, 0)) # 读 1 字节 (符号扩展)
1868
+ self.emit('ANDI', self.reg(0), self.reg(0), self.imm(0xFF)) # 0..255
1869
+ return 'int'
1870
+ if _is_fixed_array(base_t) or _is_ptr_array(base_t):
1871
+ elem_t = _array_elem(base_t)
1872
+ else:
1873
+ raise CompilerError(f"Indexing non-array type: {base_t}")
1874
+
1875
+ # x0 = base pointer; 计算 elem 地址
1876
+ self.emit('MOV', self.reg(3), self.reg(0)) # x3 = base
1877
+ self.gen_value(idx_node) # x0 = index
1878
+
1879
+ # A1 --bounds-check: 定长数组索引 0 <= i < size
1880
+ if self._bounds and _is_fixed_array(base_t):
1881
+ size = base_t[2]
1882
+ l_ge = self.new_label('bndok')
1883
+ self.emit('CMP', self.reg(0), self.imm(0))
1884
+ self.emit('B', self.lab(l_ge), ('cond', 'GE'))
1885
+ self._runtime_abort("bounds-check: negative array index")
1886
+ self.label(l_ge)
1887
+ l_lt = self.new_label('bndok')
1888
+ self.emit('CMP', self.reg(0), self.imm(size))
1889
+ self.emit('B', self.lab(l_lt), ('cond', 'LT'))
1890
+ self._runtime_abort(f"bounds-check: index >= length ({size})")
1891
+ self.label(l_lt)
1892
+
1893
+ scale = _type_slots(elem_t) * 8
1894
+ self.emit('MOV', self.reg(1), self.imm(scale))
1895
+ self.emit('MUL', self.reg(0), self.reg(1)) # x0 = index * scale
1896
+ self.emit('ADD', self.reg(0), self.reg(3)) # x0 = elem 地址
1897
+
1898
+ if lvalue:
1899
+ return None
1900
+
1901
+ if _is_fixed_array(elem_t):
1902
+ return elem_t # 子数组: 值 = 地址
1903
+ if _is_ptr_array(elem_t):
1904
+ # 行指针 (int[][] 的 a[i]): 若为空则延迟分配 64 元素行
1905
+ self.emit('MOV', self.reg(5), self.reg(0)) # x5 = elem 地址
1906
+ self.emit('LD', self.reg(1), ('mem', 5, 0)) # x1 = 行指针
1907
+ l_done = self.new_label('rowdone')
1908
+ self.emit('CMP', self.reg(1), self.imm(0))
1909
+ self.emit('B', self.lab(l_done), ('cond', 'NE'))
1910
+ self.emit('MOV', self.reg(0), self.imm(64 * 8))
1911
+ self.emit('SYS', self.imm(Syscall.MALLOC))
1912
+ self.emit('MOV', self.reg(1), self.reg(0)) # x1 = 新行指针
1913
+ self.emit('SD', self.reg(1), ('mem', 5, 0)) # 写回 elem 槽
1914
+ self.label(l_done)
1915
+ self.emit('MOV', self.reg(0), self.reg(1))
1916
+ return elem_t
1917
+ # 标量元素
1918
+ self.emit('LD', self.reg(0), ('mem', 0, 0))
1919
+ return elem_t
1920
+
1921
+ # ---------------- 赋值 (在 gen_value 中拦截 binop '=') ----------------
1922
+
1923
+ def _gen_assign(self, target, value_node):
1924
+ vt = self.gen_value(value_node)
1925
+ # 目标类型
1926
+ tt = self._expr_type(target)
1927
+ self._convert(vt, tt)
1928
+ self.emit('MOV', self.reg(2), self.reg(0)) # value
1929
+ self._gen_lvalue_addr(target) # x0 = addr
1930
+ self.emit('SD', self.reg(2), ('mem', 0, 0))
1931
+ return tt
1932
+
1933
+ def _expr_type(self, node):
1934
+ kind = node[0]
1935
+ if kind == 'var':
1936
+ return self._var_type(node[1])
1937
+ if kind == 'member':
1938
+ obj_t = self._expr_type(node[1])
1939
+ if _is_struct(obj_t):
1940
+ ftype, _ = self._struct_field(obj_t, node[2])
1941
+ return ftype
1942
+ if kind == 'index':
1943
+ base_t = self._expr_type(node[1])
1944
+ if base_t == 'string':
1945
+ return 'int'
1946
+ elem = _array_elem(base_t) if _is_fixed_array(base_t) or _is_ptr_array(base_t) else None
1947
+ if _is_fixed_array(elem):
1948
+ return elem
1949
+ return elem
1950
+ if kind == 'call':
1951
+ f = self.functions.get(node[1])
1952
+ if f:
1953
+ return f.ret_type
1954
+ if node[1] in ('min', 'max'):
1955
+ at = self._expr_type(node[2][0])
1956
+ bt = self._expr_type(node[2][1])
1957
+ return 'float' if (at == 'float' or bt == 'float') else 'int'
1958
+ return self._builtin_ret_type(node[1])
1959
+ if kind == 'num':
1960
+ return 'float' if node[2] else 'int'
1961
+ if kind == 'bool':
1962
+ return 'bool'
1963
+ if kind == 'str':
1964
+ return 'string'
1965
+ if kind == 'binop':
1966
+ if node[1] in ('+=', '-=', '*=', '/=', '%=',
1967
+ '&=', '|=', '^=', '<<=', '>>='):
1968
+ return self._expr_type(node[2])
1969
+ if node[1] in ('&', '|', '^', '<<', '>>'):
1970
+ return 'int'
1971
+ if node[1] in ('+', '-', '*', '%'):
1972
+ lt = self._expr_type(node[2])
1973
+ rt = self._expr_type(node[3])
1974
+ if lt == 'string' or rt == 'string':
1975
+ return 'string'
1976
+ return 'float' if lt == 'float' or rt == 'float' else 'int'
1977
+ if node[1] == '/':
1978
+ return 'float'
1979
+ if node[1] in ('==', '!=', '<', '>', '<=', '>=', '&&', '||'):
1980
+ return 'bool'
1981
+ if kind == 'cond':
1982
+ lt = self._expr_type(node[2])
1983
+ rt = self._expr_type(node[3])
1984
+ if (lt == 'string') != (rt == 'string'):
1985
+ return 'int'
1986
+ return 'string' if lt == 'string' else \
1987
+ ('float' if lt == 'float' or rt == 'float' else 'int')
1988
+ if kind in ('preinc', 'predec', 'postinc', 'postdec'):
1989
+ return self._expr_type(node[1])
1990
+ if kind == 'neg':
1991
+ it = self._expr_type(node[1])
1992
+ return 'float' if it == 'float' else 'int'
1993
+ if kind == 'not':
1994
+ return 'bool'
1995
+ if kind == 'bitnot':
1996
+ return 'int'
1997
+ return None
1998
+
1999
+ # ---------------- 二元运算 ----------------
2000
+
2001
+ def _gen_binop(self, op, left, right):
2002
+ if op == '=':
2003
+ return self._gen_assign(left, right)
2004
+ if op in _COMPOUND_TO_BASE:
2005
+ return self._gen_compound(left, _COMPOUND_TO_BASE[op], right)
2006
+ if op == '&&' or op == '||':
2007
+ return self._gen_logical(op, left, right)
2008
+ if op in ('&', '|', '^', '<<', '>>'):
2009
+ return self._gen_bitwise(op, left, right)
2010
+ if op in ('==', '!=', '<', '>', '<=', '>='):
2011
+ # 比较作为值表达式: 条件成立得 1, 否则 0
2012
+ l_false = self.new_label('cmpf')
2013
+ l_end = self.new_label('cmpe')
2014
+ self.gen_cond_jump_false(('binop', op, left, right), l_false)
2015
+ self.emit('MOV', self.reg(0), self.imm(1))
2016
+ self.emit('JMP', self.lab(l_end))
2017
+ self.label(l_false)
2018
+ self.emit('MOV', self.reg(0), self.imm(0))
2019
+ self.label(l_end)
2020
+ return 'bool'
2021
+
2022
+ lt = self._expr_type(left)
2023
+ rt = self._expr_type(right)
2024
+ if op == '+' and (lt == 'string' or rt == 'string'):
2025
+ self._gen_string_value(left)
2026
+ self.emit('PUSH', self.reg(0))
2027
+ self._gen_string_value(right)
2028
+ self.emit('MOV', self.reg(1), self.reg(0))
2029
+ self.emit('POP', self.reg(0))
2030
+ self.emit('SYS', self.imm(Syscall.STR_CONCAT))
2031
+ return 'string'
2032
+
2033
+ float_mode = (lt == 'float' or rt == 'float') or op == '/'
2034
+ # 左操作数
2035
+ self.gen_value(left)
2036
+ if float_mode and lt == 'int':
2037
+ self.emit('SYS', self.imm(Syscall.ITOF))
2038
+ if float_mode and lt == 'bool':
2039
+ self.emit('SYS', self.imm(Syscall.ITOF))
2040
+ self.emit('PUSH', self.reg(0))
2041
+ # 右操作数
2042
+ self.gen_value(right)
2043
+ if float_mode and rt in ('int', 'bool'):
2044
+ self.emit('SYS', self.imm(Syscall.ITOF))
2045
+ self.emit('MOV', self.reg(1), self.reg(0))
2046
+ self.emit('POP', self.reg(0))
2047
+
2048
+ if float_mode:
2049
+ sys_map = {'+': Syscall.FADD, '-': Syscall.FSUB,
2050
+ '*': Syscall.FMUL, '/': Syscall.FDIV}
2051
+ if op == '%':
2052
+ raise CompilerError("Float modulo not supported")
2053
+ self.emit('SYS', self.imm(sys_map[op]))
2054
+ return 'float'
2055
+
2056
+ if op == '%':
2057
+ # x0 = a - (a/b)*b
2058
+ self.emit('MOV', self.reg(2), self.reg(1)) # b
2059
+ self.emit('PUSH', self.reg(0)) # a
2060
+ self.emit('DIV', self.reg(0), self.reg(2)) # a/b
2061
+ self.emit('MUL', self.reg(0), self.reg(2)) # (a/b)*b
2062
+ self.emit('MOV', self.reg(1), self.reg(0))
2063
+ self.emit('POP', self.reg(0))
2064
+ self.emit('SUB', self.reg(0), self.reg(1))
2065
+ return 'int'
2066
+
2067
+ op_map = {'+': 'ADD', '-': 'SUB', '*': 'MUL'}
2068
+ if op not in op_map:
2069
+ raise CompilerError(f"Unsupported int operator: {op}")
2070
+ self.emit(op_map[op], self.reg(0), self.reg(1))
2071
+ return 'int'
2072
+
2073
+ def _gen_logical(self, op, left, right):
2074
+ l_true = self.new_label('lt')
2075
+ l_false = self.new_label('lf')
2076
+ l_end = self.new_label('le')
2077
+ if op == '&&':
2078
+ self.gen_cond_jump_false(left, l_false)
2079
+ self.gen_cond_jump_false(right, l_false)
2080
+ else: # ||
2081
+ self.gen_cond_jump_true(left, l_true)
2082
+ self.gen_cond_jump_true(right, l_true)
2083
+ self.emit('JMP', self.lab(l_false))
2084
+ self.label(l_true)
2085
+ self.emit('MOV', self.reg(0), self.imm(1))
2086
+ self.emit('JMP', self.lab(l_end))
2087
+ self.label(l_false)
2088
+ self.emit('MOV', self.reg(0), self.imm(0))
2089
+ self.label(l_end)
2090
+ return 'bool'
2091
+
2092
+ def _gen_bitwise(self, op, left, right) -> Any:
2093
+ """位运算 & | ^ << >> (整数); >> 为算术右移 (保留符号)。"""
2094
+ lt = self._expr_type(left)
2095
+ rt = self._expr_type(right)
2096
+ if lt in ('float', 'string') or rt in ('float', 'string'):
2097
+ raise CompilerError(
2098
+ f"Bitwise operator '{op}' requires integer operands "
2099
+ f"(got {lt} and {rt})")
2100
+ self.gen_value(left)
2101
+ self.emit('PUSH', self.reg(0))
2102
+ self.gen_value(right)
2103
+ self.emit('MOV', self.reg(1), self.reg(0))
2104
+ self.emit('POP', self.reg(0))
2105
+ if op == '&':
2106
+ self.emit('AND', self.reg(0), self.reg(1))
2107
+ elif op == '|':
2108
+ self.emit('OR', self.reg(0), self.reg(1))
2109
+ elif op == '^':
2110
+ self.emit('XOR', self.reg(0), self.reg(1))
2111
+ elif op == '<<':
2112
+ self.emit('SHL', self.reg(0), self.reg(1))
2113
+ else: # '>>'
2114
+ self.emit('ASR', self.reg(0), self.reg(0), self.reg(1))
2115
+ return 'int'
2116
+
2117
+ # ---------------- 复合赋值 / 自增自减 / 三目 ----------------
2118
+
2119
+ def _gen_compound(self, target, op: str, value_node) -> Any:
2120
+ """target op= value (op ∈ + - * / % & | ^ << >>); 左值地址只求值一次。"""
2121
+ tt = self._expr_type(target)
2122
+ if tt not in ('int', 'bool', 'float'):
2123
+ raise CompilerError(f"Cannot apply '{op}=' to type: {tt}")
2124
+ if tt == 'float' and op not in ('+', '-', '*', '/'):
2125
+ raise CompilerError(f"Cannot apply '{op}=' to float")
2126
+ float_mode = tt == 'float'
2127
+
2128
+ self._gen_lvalue_addr(target)
2129
+ self.emit('PUSH', self.reg(0)) # [SP] = addr
2130
+ vt = self.gen_value(value_node) # x0 = rhs
2131
+ self._convert(vt, tt)
2132
+ self.emit('MOV', self.reg(1), self.reg(0)) # b = rhs
2133
+ self.emit('LD', self.reg(2), ('mem', 32, 0)) # x2 = addr
2134
+ self.emit('LD', self.reg(0), ('mem', 2, 0)) # a = old
2135
+
2136
+ if float_mode:
2137
+ fmap = {'+': Syscall.FADD, '-': Syscall.FSUB,
2138
+ '*': Syscall.FMUL, '/': Syscall.FDIV}
2139
+ self.emit('SYS', self.imm(fmap[op]))
2140
+ elif op == '+':
2141
+ self.emit('ADD', self.reg(0), self.reg(1))
2142
+ elif op == '-':
2143
+ self.emit('SUB', self.reg(0), self.reg(1))
2144
+ elif op == '*':
2145
+ self.emit('MUL', self.reg(0), self.reg(1))
2146
+ elif op == '/':
2147
+ self.emit('DIV', self.reg(0), self.reg(1))
2148
+ elif op == '%':
2149
+ self.emit('MOV', self.reg(3), self.reg(1)) # 除数备份
2150
+ self.emit('PUSH', self.reg(0))
2151
+ self.emit('DIV', self.reg(0), self.reg(3))
2152
+ self.emit('MUL', self.reg(0), self.reg(3))
2153
+ self.emit('MOV', self.reg(1), self.reg(0))
2154
+ self.emit('POP', self.reg(0))
2155
+ self.emit('SUB', self.reg(0), self.reg(1))
2156
+ elif op == '&':
2157
+ self.emit('AND', self.reg(0), self.reg(1))
2158
+ elif op == '|':
2159
+ self.emit('OR', self.reg(0), self.reg(1))
2160
+ elif op == '^':
2161
+ self.emit('XOR', self.reg(0), self.reg(1))
2162
+ elif op == '<<':
2163
+ self.emit('SHL', self.reg(0), self.reg(1))
2164
+ elif op == '>>':
2165
+ self.emit('ASR', self.reg(0), self.reg(0), self.reg(1))
2166
+ else:
2167
+ raise CompilerError(f"Unsupported compound operator: {op}=")
2168
+
2169
+ self.emit('SD', self.reg(0), ('mem', 2, 0))
2170
+ self.emit('ADDI', self.reg(32), self.reg(32), self.imm(8))
2171
+ return tt
2172
+
2173
+ def _gen_incdec(self, kind: str, target) -> Any:
2174
+ """++/-- (前缀与后缀); 后缀返回旧值, 前缀返回新值。"""
2175
+ tt = self._expr_type(target)
2176
+ if tt not in ('int', 'bool', 'float'):
2177
+ raise CompilerError(f"Cannot {kind} value of type: {tt}")
2178
+ op = '+' if 'inc' in kind else '-'
2179
+ postfix = kind.startswith('post')
2180
+ float_mode = tt == 'float'
2181
+
2182
+ self._gen_lvalue_addr(target)
2183
+ self.emit('PUSH', self.reg(0)) # [SP] = addr
2184
+ self.emit('LD', self.reg(2), ('mem', 32, 0)) # x2 = addr
2185
+ self.emit('LD', self.reg(0), ('mem', 2, 0)) # a = old
2186
+ if postfix:
2187
+ self.emit('MOV', self.reg(5), self.reg(0)) # 保存旧值
2188
+ if float_mode:
2189
+ self.emit('MOV', self.reg(0), self.imm(1))
2190
+ self.emit('SYS', self.imm(Syscall.ITOF)) # b = 1.0
2191
+ self.emit('MOV', self.reg(1), self.reg(0))
2192
+ self.emit('LD', self.reg(0), ('mem', 2, 0)) # a 回填
2193
+ self.emit('SYS', self.imm(Syscall.FADD if op == '+'
2194
+ else Syscall.FSUB))
2195
+ else:
2196
+ self.emit('MOV', self.reg(1), self.imm(1))
2197
+ self.emit('ADD' if op == '+' else 'SUB',
2198
+ self.reg(0), self.reg(1))
2199
+ self.emit('SD', self.reg(0), ('mem', 2, 0))
2200
+ self.emit('ADDI', self.reg(32), self.reg(32), self.imm(8))
2201
+ if postfix:
2202
+ self.emit('MOV', self.reg(0), self.reg(5))
2203
+ return tt
2204
+
2205
+ def _gen_minmax(self, name: str, args) -> Any:
2206
+ """min/max(a, b): int/float 数值最值 (bool 视作 int)。"""
2207
+ at = self._expr_type(args[0])
2208
+ bt = self._expr_type(args[1])
2209
+ if at == 'string' or bt == 'string':
2210
+ raise CompilerError(f"{name} does not accept string operands")
2211
+ tt = 'float' if (at == 'float' or bt == 'float') else 'int'
2212
+
2213
+ self.gen_value(args[0])
2214
+ if tt == 'float' and at in ('int', 'bool'):
2215
+ self.emit('SYS', self.imm(Syscall.ITOF))
2216
+ self.emit('PUSH', self.reg(0)) # [SP] = a
2217
+ self.gen_value(args[1])
2218
+ if tt == 'float' and bt in ('int', 'bool'):
2219
+ self.emit('SYS', self.imm(Syscall.ITOF))
2220
+ self.emit('MOV', self.reg(1), self.reg(0)) # x1 = b
2221
+ self.emit('POP', self.reg(0)) # x0 = a
2222
+
2223
+ # min: a<=b 取 a; max: a>=b 取 a
2224
+ cond = 'LE' if name == 'min' else 'GE'
2225
+ if tt == 'float':
2226
+ self.emit('MOV', self.reg(2), self.reg(0)) # 备份 a
2227
+ self.emit('MOV', self.reg(3), self.reg(1)) # 备份 b
2228
+ self.emit('SYS', self.imm(Syscall.FCMP)) # x0 = cmp(a,b) ∈ {-1,0,1}
2229
+ self.emit('CMP', self.reg(0), self.imm(0))
2230
+ l_keep = self.new_label('mmkeep')
2231
+ l_done = self.new_label('mmdone')
2232
+ self.emit('B', self.lab(l_keep), ('cond', cond))
2233
+ self.emit('MOV', self.reg(0), self.reg(3)) # result = b
2234
+ self.emit('JMP', self.lab(l_done))
2235
+ self.label(l_keep)
2236
+ self.emit('MOV', self.reg(0), self.reg(2)) # result = a
2237
+ self.label(l_done)
2238
+ else:
2239
+ self.emit('CMP', self.reg(0), self.reg(1))
2240
+ l_keep = self.new_label('mmkeep')
2241
+ self.emit('B', self.lab(l_keep), ('cond', cond))
2242
+ self.emit('MOV', self.reg(0), self.reg(1)) # result = b
2243
+ self.label(l_keep)
2244
+ return tt
2245
+
2246
+ def _gen_ternary(self, cond, a, b) -> Any:
2247
+ lt = self._expr_type(a)
2248
+ rt = self._expr_type(b)
2249
+ if (lt == 'string') != (rt == 'string'):
2250
+ raise CompilerError("Cannot mix string and numeric in '?:'")
2251
+ tt = 'string' if lt == 'string' else \
2252
+ ('float' if (lt == 'float' or rt == 'float') else 'int')
2253
+ l_false = self.new_label('cndf')
2254
+ l_end = self.new_label('cnde')
2255
+ self.gen_cond_jump_false(cond, l_false)
2256
+ t1 = self.gen_value(a)
2257
+ self._convert(t1, tt)
2258
+ self.emit('MOV', self.reg(6), self.reg(0))
2259
+ self.emit('JMP', self.lab(l_end))
2260
+ self.label(l_false)
2261
+ t2 = self.gen_value(b)
2262
+ self._convert(t2, tt)
2263
+ self.emit('MOV', self.reg(6), self.reg(0))
2264
+ self.label(l_end)
2265
+ self.emit('MOV', self.reg(0), self.reg(6))
2266
+ return tt
2267
+
2268
+ # ---------------- 字符串化 (print/concat) ----------------
2269
+
2270
+ def _gen_string_value(self, node) -> None:
2271
+ """求值表达式并将 x0 转为字符串指针。"""
2272
+ t = self.gen_value(node)
2273
+ if t == 'string':
2274
+ return
2275
+ if t == 'float':
2276
+ self.emit('SYS', self.imm(Syscall.FTOA))
2277
+ elif t == 'bool':
2278
+ self.emit('SYS', self.imm(Syscall.BOOL_STR))
2279
+ else:
2280
+ self.emit('SYS', self.imm(Syscall.ITOA))
2281
+
2282
+ def gen_print(self, node, newline: bool) -> None:
2283
+ t = self.gen_value(node)
2284
+ if t == 'string':
2285
+ pass
2286
+ elif t == 'float':
2287
+ self.emit('SYS', self.imm(Syscall.FTOA))
2288
+ elif t == 'bool':
2289
+ self.emit('SYS', self.imm(Syscall.BOOL_STR))
2290
+ else:
2291
+ self.emit('SYS', self.imm(Syscall.ITOA))
2292
+ self.emit('SYS', self.imm(Syscall.PRINT_STR))
2293
+ if newline:
2294
+ self.emit('OUT', self.imm(10))
2295
+
2296
+ # ---------------- 函数调用 ----------------
2297
+
2298
+ def _builtin_ret_type(self, name: str):
2299
+ host = HOST_BUILTINS.get(name)
2300
+ if host is not None:
2301
+ return None if host[2] == 'void' else host[2]
2302
+ if name in ('sin', 'cos', 'tan', 'sqrt', 'pow', 'floor', 'ceil', 'round'):
2303
+ return 'float'
2304
+ if name in ('strlen', 'strcmp', 'rand', 'time', 'abs', 'input',
2305
+ 'idiv', 'atoi'):
2306
+ return 'int'
2307
+ if name in ('strcpy', 'int_to_str', 'itoa', 'float_to_str', 'ftoa',
2308
+ 'bool_to_str', 'substr', 'upper', 'lower',
2309
+ 'trim', 'ltrim', 'rtrim'):
2310
+ return 'string'
2311
+ return None
2312
+
2313
+ def _gen_host_sys(self, sys_id: int, args: list) -> None:
2314
+ """求值 args (左到右) 并放入 x0..x(n-1), 发射 SYS sys_id。"""
2315
+ for a in args:
2316
+ self.gen_value(a)
2317
+ self.emit('PUSH', self.reg(0))
2318
+ for i in range(len(args) - 1, -1, -1):
2319
+ self.emit('POP', self.reg(i))
2320
+ self.emit('SYS', self.imm(sys_id))
2321
+
2322
+ def _gen_call(self, name: str, args: list):
2323
+ min_args = BUILTIN_MIN_ARGS.get(name)
2324
+ if min_args is not None and len(args) < min_args:
2325
+ raise CompilerError(
2326
+ f"{name}() expects at least {min_args} argument(s), "
2327
+ f"got {len(args)}")
2328
+ if name in ('println', 'print'):
2329
+ # 单参数 (拼接由表达式完成)
2330
+ if args:
2331
+ self.gen_print(args[0], newline=(name == 'println'))
2332
+ else:
2333
+ self.emit('OUT', self.imm(10))
2334
+ return 'void'
2335
+
2336
+ math_unary = {'sqrt': Syscall.SQRT, 'sin': Syscall.SIN,
2337
+ 'cos': Syscall.COS, 'tan': Syscall.TAN}
2338
+ if name in math_unary:
2339
+ at = self.gen_value(args[0])
2340
+ if at == 'int':
2341
+ self.emit('SYS', self.imm(Syscall.ITOF))
2342
+ self.emit('SYS', self.imm(math_unary[name]))
2343
+ return 'float'
2344
+
2345
+ round_unary = {'floor': Syscall.FLOOR, 'ceil': Syscall.CEIL,
2346
+ 'round': Syscall.ROUND}
2347
+ if name in round_unary:
2348
+ at = self.gen_value(args[0])
2349
+ if at in ('int', 'bool'):
2350
+ self.emit('SYS', self.imm(Syscall.ITOF))
2351
+ self.emit('SYS', self.imm(round_unary[name]))
2352
+ return 'float'
2353
+
2354
+ if name in ('min', 'max'):
2355
+ return self._gen_minmax(name, args)
2356
+
2357
+ if name == 'idiv':
2358
+ at = self._expr_type(args[0])
2359
+ bt = self._expr_type(args[1])
2360
+ if at in ('float', 'string') or bt in ('float', 'string'):
2361
+ raise CompilerError("idiv requires integer operands")
2362
+ self.gen_value(args[0])
2363
+ self.emit('PUSH', self.reg(0))
2364
+ self.gen_value(args[1])
2365
+ self.emit('MOV', self.reg(1), self.reg(0))
2366
+ self.emit('POP', self.reg(0))
2367
+ self.emit('DIV', self.reg(0), self.reg(1))
2368
+ return 'int'
2369
+
2370
+ if name == 'pow':
2371
+ self._arg_float(args[0])
2372
+ self.emit('PUSH', self.reg(0))
2373
+ self._arg_float(args[1])
2374
+ self.emit('MOV', self.reg(1), self.reg(0))
2375
+ self.emit('POP', self.reg(0))
2376
+ self.emit('SYS', self.imm(Syscall.POW))
2377
+ return 'float'
2378
+ if name == 'abs':
2379
+ self.gen_value(args[0])
2380
+ self.emit('SYS', self.imm(Syscall.ABS))
2381
+ return 'int'
2382
+ if name == 'strlen':
2383
+ self.gen_value(args[0])
2384
+ self.emit('SYS', self.imm(Syscall.STRLEN))
2385
+ return 'int'
2386
+ if name == 'strcmp':
2387
+ self.gen_value(args[0])
2388
+ self.emit('PUSH', self.reg(0))
2389
+ self.gen_value(args[1])
2390
+ self.emit('MOV', self.reg(1), self.reg(0))
2391
+ self.emit('POP', self.reg(0))
2392
+ self.emit('SYS', self.imm(Syscall.STRCMP))
2393
+ return 'int'
2394
+ if name == 'strcpy':
2395
+ self.gen_value(args[0])
2396
+ self.emit('PUSH', self.reg(0))
2397
+ self.emit('MOV', self.reg(0), self.imm(self._data_string("")))
2398
+ self.emit('MOV', self.reg(1), self.reg(0))
2399
+ self.emit('POP', self.reg(0))
2400
+ self.emit('SYS', self.imm(Syscall.STR_CONCAT))
2401
+ return 'string'
2402
+ if name == 'rand':
2403
+ self.emit('SYS', self.imm(Syscall.RAND))
2404
+ return 'int'
2405
+ if name == 'srand':
2406
+ self.gen_value(args[0])
2407
+ self.emit('SYS', self.imm(Syscall.SRAND))
2408
+ return 'void'
2409
+ if name in ('int_to_str', 'itoa'):
2410
+ self.gen_value(args[0])
2411
+ self.emit('SYS', self.imm(Syscall.ITOA))
2412
+ return 'string'
2413
+ if name in ('float_to_str', 'ftoa'):
2414
+ t = self.gen_value(args[0])
2415
+ if t in ('int', 'bool'):
2416
+ self.emit('SYS', self.imm(Syscall.ITOF))
2417
+ self.emit('SYS', self.imm(Syscall.FTOA))
2418
+ return 'string'
2419
+ if name in ('bool_to_str',):
2420
+ self.gen_value(args[0])
2421
+ self.emit('SYS', self.imm(Syscall.BOOL_STR))
2422
+ return 'string'
2423
+ if name == 'substr':
2424
+ self._gen_string_value(args[0])
2425
+ self.emit('PUSH', self.reg(0))
2426
+ self.gen_value(args[1])
2427
+ self.emit('PUSH', self.reg(0))
2428
+ self.gen_value(args[2])
2429
+ self.emit('MOV', self.reg(2), self.reg(0))
2430
+ self.emit('POP', self.reg(1))
2431
+ self.emit('POP', self.reg(0))
2432
+ self.emit('SYS', self.imm(Syscall.SUBSTR))
2433
+ return 'string'
2434
+ if name == 'indexof':
2435
+ self._gen_string_value(args[0])
2436
+ self.emit('PUSH', self.reg(0))
2437
+ self._gen_string_value(args[1])
2438
+ self.emit('MOV', self.reg(1), self.reg(0))
2439
+ self.emit('POP', self.reg(0))
2440
+ self.emit('SYS', self.imm(Syscall.INDEXOF))
2441
+ return 'int'
2442
+ if name in ('upper', 'lower'):
2443
+ self._gen_string_value(args[0])
2444
+ self.emit('SYS', self.imm(Syscall.TOUPPER if name == 'upper'
2445
+ else Syscall.TOLOWER))
2446
+ return 'string'
2447
+ if name in ('trim', 'ltrim', 'rtrim'):
2448
+ self._gen_string_value(args[0])
2449
+ sys_id = {'trim': Syscall.TRIM, 'ltrim': Syscall.LTRIM,
2450
+ 'rtrim': Syscall.RTRIM}[name]
2451
+ self.emit('SYS', self.imm(sys_id))
2452
+ return 'string'
2453
+ if name == 'atoi':
2454
+ self.gen_value(args[0])
2455
+ self.emit('SYS', self.imm(Syscall.ATOI))
2456
+ return 'int'
2457
+ # ---- 宿主能力 (表驱动): 音频 / 画布 / 系统交互 / Termux API ----
2458
+ host = HOST_BUILTINS.get(name)
2459
+ if host is not None:
2460
+ sys_id, nargs, ret = host
2461
+ self._gen_host_sys(sys_id, args[:nargs])
2462
+ return ret
2463
+ if name == 'time':
2464
+ self.emit('SYS', self.imm(Syscall.TIME))
2465
+ return 'int'
2466
+ if name == 'input':
2467
+ self.emit('MOV', self.reg(0), self.imm(0))
2468
+ return 'int'
2469
+
2470
+ # 用户函数
2471
+ fdef = self.functions.get(name)
2472
+ if fdef is None:
2473
+ raise CompilerError(f"Unknown function: {name}")
2474
+ for k, arg in enumerate(args):
2475
+ at = self.gen_value(arg)
2476
+ ptype = fdef.params[k][1] if k < len(fdef.params) else None
2477
+ self._convert(at, self._param_promote(ptype))
2478
+ self.emit('PUSH', self.reg(0))
2479
+ self.emit('CALL', self.lab(name))
2480
+ # 调用方清理参数 (不得使用 x0, 它持有返回值)
2481
+ nargs = len(args)
2482
+ if nargs:
2483
+ self.emit('ADDI', self.reg(6), self.reg(32), self.imm(nargs * 8))
2484
+ self.emit('MOV', self.reg(32), self.reg(6))
2485
+ return fdef.ret_type
2486
+
2487
+ @staticmethod
2488
+ def _param_promote(ptype):
2489
+ # 数组参数衰减
2490
+ if _is_fixed_array(ptype):
2491
+ return ('ptrarray', _array_elem(ptype))
2492
+ return ptype
2493
+
2494
+ def _arg_float(self, node) -> None:
2495
+ t = self.gen_value(node)
2496
+ if t == 'int' or t == 'bool':
2497
+ self.emit('SYS', self.imm(Syscall.ITOF))
2498
+
2499
+ # ---------------- 条件跳转 ----------------
2500
+
2501
+ _COND_FALSE_JUMP = {
2502
+ '==': 'NE', '!=': 'EQ',
2503
+ '<': 'GE', '>': 'LE',
2504
+ '<=': 'GT', '>=': 'LT',
2505
+ }
2506
+
2507
+ def gen_cond_jump_false(self, node, label_false: str) -> None:
2508
+ kind = node[0]
2509
+ if kind == 'bool':
2510
+ if not node[1]:
2511
+ self.emit('JMP', self.lab(label_false))
2512
+ return
2513
+ if kind == 'binop' and node[1] == '&&':
2514
+ self.gen_cond_jump_false(node[2], label_false)
2515
+ self.gen_cond_jump_false(node[3], label_false)
2516
+ return
2517
+ if kind == 'binop' and node[1] == '||':
2518
+ l_true = self.new_label('ortrue')
2519
+ self.gen_cond_jump_true(node[2], l_true)
2520
+ self.gen_cond_jump_true(node[3], l_true)
2521
+ self.emit('JMP', self.lab(label_false))
2522
+ self.label(l_true)
2523
+ return
2524
+ if kind == 'not':
2525
+ self.gen_cond_jump_true(node[1], label_false)
2526
+ return
2527
+ if kind == 'binop' and node[1] in self._COND_FALSE_JUMP:
2528
+ op = node[1]
2529
+ lt = self._expr_type(node[2])
2530
+ rt = self._expr_type(node[3])
2531
+ float_mode = lt == 'float' or rt == 'float'
2532
+ self.gen_value(node[2])
2533
+ if float_mode and lt in ('int', 'bool'):
2534
+ self.emit('SYS', self.imm(Syscall.ITOF))
2535
+ self.emit('PUSH', self.reg(0))
2536
+ self.gen_value(node[3])
2537
+ if float_mode and rt in ('int', 'bool'):
2538
+ self.emit('SYS', self.imm(Syscall.ITOF))
2539
+ self.emit('MOV', self.reg(1), self.reg(0))
2540
+ self.emit('POP', self.reg(0))
2541
+ if float_mode:
2542
+ self.emit('SYS', self.imm(Syscall.FCMP))
2543
+ self.emit('CMP', self.reg(0), self.imm(0))
2544
+ else:
2545
+ self.emit('CMP', self.reg(0), self.reg(1))
2546
+ self.emit('B', self.lab(label_false),
2547
+ ('cond', self._COND_FALSE_JUMP[op]))
2548
+ return
2549
+ # 普通布尔值
2550
+ self.gen_value(node)
2551
+ self.emit('CMP', self.reg(0), self.imm(0))
2552
+ self.emit('JZ', self.lab(label_false))
2553
+
2554
+ def gen_cond_jump_true(self, node, label_true: str) -> None:
2555
+ l_false = self.new_label('cf')
2556
+ self.gen_cond_jump_false(node, l_false)
2557
+ self.emit('JMP', self.lab(label_true))
2558
+ self.label(l_false)