mirascript 0.0.6__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.
mirascript/emit.py ADDED
@@ -0,0 +1,1182 @@
1
+ import logging
2
+ import struct
3
+ import json
4
+ import base64
5
+ import traceback
6
+ from typing import Any, Union, List, Tuple, Optional, Dict
7
+ import ast
8
+ import sys
9
+
10
+ from mirascript.vm.operations import ToString_, is_decimal_number
11
+ from .vm.helpers import GlobalFallback
12
+ from .vm.env import vm_globals
13
+ from .deep_nonlocal_fix import deep_nonlocal_fix
14
+
15
+ class OpCodes:
16
+ """MiraScript 操作码"""
17
+
18
+ def __init__(self) -> None:
19
+ from .mirascript import op_codes
20
+ self.__dict__.update(op_codes())
21
+
22
+ def __getattr__(self, name: str) -> int:
23
+ if name in self.__dict__:
24
+ return self.__dict__[name]
25
+ raise AttributeError(f"No such OpCode: {name}")
26
+
27
+ def __setattr__(self, name: str, value) -> None:
28
+ raise AttributeError("OpCodes is immutable, cannot set attributes.")
29
+
30
+ def __delattr__(self, name: str) -> None:
31
+ raise AttributeError("OpCodes is immutable, cannot delete attributes.")
32
+
33
+ OpCode = OpCodes()
34
+ """MiraScript 操作码"""
35
+
36
+ # 类型定义
37
+ VmPrimitive = Union[None, bool, int, float, str]
38
+ VmConst = Union[VmPrimitive, dict, list]
39
+ ScriptInput = Union[str, bytes]
40
+
41
+ class TranspileOptions:
42
+ """转译选项"""
43
+ def __init__(self, pretty: bool = False, source_map: bool = False,
44
+ file_name: Optional[str] = None, input_mode: str = 'Script'):
45
+ self.pretty = pretty
46
+ self.source_map = source_map
47
+ self.file_name = file_name
48
+ self.input_mode = input_mode
49
+
50
+ ORIGIN = "mira://MiraScript"
51
+ source_id = 1
52
+
53
+ def read_const(data: bytes, offset: int) -> Tuple[VmPrimitive, int]:
54
+ """解析常量"""
55
+
56
+ type_byte = data[offset]
57
+
58
+ if type_byte == 0:
59
+ return None, 1
60
+ elif type_byte == 1:
61
+ return True, 1
62
+ elif type_byte == 2:
63
+ return False, 1
64
+ elif type_byte == 3:
65
+ ordinal = struct.unpack('<i', data[offset + 1:offset + 5])[0]
66
+ return ordinal, 5
67
+ elif type_byte == 4:
68
+ num = struct.unpack('<d', data[offset + 1:offset + 9])[0]
69
+
70
+ return num, 9
71
+ elif type_byte == 5:
72
+ length = struct.unpack('<I', data[offset + 1:offset + 5])[0]
73
+ str_bytes = data[offset + 5:offset + 5 + length]
74
+ text = str_bytes.decode('utf-8')
75
+ return text, 5 + length
76
+ else:
77
+ raise ValueError(f"Unknown constant type: {type_byte}")
78
+
79
+ def to_python(value: VmConst) -> Any:
80
+ """将值转为 Python"""
81
+
82
+ if value is None:
83
+ return None
84
+ if isinstance(value, (dict, list,str,bool)):
85
+ return value
86
+ if isinstance(value, (int, float)):
87
+ return float(value)
88
+ return value
89
+
90
+ def get_opcode_name(opcode: int) -> str:
91
+ """获取操作码名称"""
92
+ for attr_name in dir(OpCode):
93
+ if not attr_name.startswith('_') and getattr(OpCode, attr_name, None) == opcode:
94
+ return attr_name
95
+ return str(opcode)
96
+
97
+ def ast_call(func_id: str, call_args: List[Any]) -> ast.Call:
98
+ """生成 call"""
99
+ return ast.Call(
100
+ func=ast.Name(id=func_id, ctx=ast.Load()),
101
+ args=call_args,
102
+ keywords=[],lineno=0)
103
+
104
+ def assign_call(target_id: str, func_id: str, call_args: List[Any]) -> ast.Assign:
105
+ """生成 assign call"""
106
+ return ast.Assign(
107
+ targets=[
108
+ ast.Name(id=target_id, ctx=ast.Store())],
109
+ value=ast_call(func_id=func_id, call_args=call_args), lineno=0)
110
+
111
+ def create_Element(argsValue:List[str],fun_id='Element') -> ast.Call:
112
+ return ast.Call(func=ast.Name(id=fun_id, ctx=ast.Load()),
113
+ args=[ast.Name(id=a, ctx=ast.Load()) for a in argsValue],
114
+ keywords=[])
115
+
116
+ def cp(id):
117
+ """生成 Cp 调用"""
118
+ return ast.Expr(
119
+ value=ast.Call(
120
+ func=ast.Name(id=id, ctx=ast.Load()),
121
+ args=[],
122
+ keywords=[]))
123
+
124
+ def create_parameter(name):
125
+ """生成参数"""
126
+ if name =='None':
127
+ return ast.Constant(value=None, lineno=0)
128
+ return ast.Name(id=name, ctx=ast.Load(), lineno=0)
129
+
130
+ def create_if(name: str, negate) -> ast.If:
131
+ return ast.If(test=
132
+ ast.Compare(
133
+ left=ast.Call(
134
+ func=ast.Name(id='ToBoolean_', ctx=ast.Load()),
135
+ args=[
136
+ ast.Name(id=name, ctx=ast.Load())],
137
+ keywords=[]),
138
+ ops=[
139
+ ast.NotEq()],
140
+ comparators=[
141
+ ast.Constant(value=negate)]),
142
+ body=[],
143
+ orelse=[])
144
+
145
+
146
+ def create_range_loop(index,start,end,exclusive=False):
147
+
148
+ s=ast.Assign(
149
+ targets=[
150
+ ast.Name(id='start', ctx=ast.Store())],
151
+ value=ast.Call(
152
+ func=ast.Name(id='ToNumber_', ctx=ast.Load()),
153
+ args=[
154
+ ast.Name(id=start, ctx=ast.Load())],
155
+ keywords=[]))
156
+ e= ast.Assign(
157
+ targets=[
158
+ ast.Name(id='end', ctx=ast.Store())],
159
+ value=ast.Call(
160
+ func=ast.Name(id='ToNumber_', ctx=ast.Load()),
161
+ args=[
162
+ ast.Name(id=end, ctx=ast.Load())],
163
+ keywords=[]))
164
+ i =ast.Assign(
165
+ targets=[
166
+ ast.Name(id=index, ctx=ast.Store())],
167
+ value=ast.Name(id='start', ctx=ast.Load()))
168
+ w=ast.While(
169
+ test=ast.Compare(
170
+ left=ast.Name(id=index, ctx=ast.Load()),
171
+ ops=[
172
+ ast.LtE() if not exclusive else ast.Lt()],
173
+ comparators=[
174
+ ast.Name(id='end', ctx=ast.Load())]),
175
+ body=[],
176
+ orelse=[])
177
+ return s,e,i,w
178
+
179
+ # def RangeExclusive_(start,end):
180
+ # pass
181
+ # s = ToNumber_(start)
182
+ # e = ToNumber_(end)
183
+ # if math.isnan(s) or math.isnan(e):
184
+ # return []
185
+ # # return list(range(int(s),int(e)))
186
+ # result=[]
187
+ # while s<e:
188
+ # result.append(s)
189
+ # s+=1
190
+ # return result
191
+ class Emitter:
192
+ """代码生成"""
193
+
194
+ def __init__(self, chunk: bytes):
195
+ self.chunk = chunk
196
+ # 解析 chunk 头部
197
+ self.chunk_size = struct.unpack('<I', chunk[0:4])[0]
198
+ self.code_size = struct.unpack('<I', chunk[4:8])[0]
199
+ self.const_size = struct.unpack('<I', chunk[8 + self.code_size:12 + self.code_size])[0]
200
+
201
+ # 设置数据视图
202
+ self.code_data = chunk[8:8 + self.code_size]
203
+ self.const_data = chunk[12 + self.code_size:12 + self.code_size + self.const_size]
204
+
205
+ # 初始化状态
206
+ self.constants: List[Any] = []
207
+ self.code_lines: List[str] = []
208
+
209
+ self.func_script=None
210
+ self.code_offset = 0
211
+ self.closure_counter = 0
212
+ self.ident_counter = 0
213
+ self.current_blocks_body=None
214
+ self.pre_blocks=None
215
+ self.fun_name_counter=0
216
+ def read_consts(self) -> None:
217
+ """读取常量表"""
218
+ i = 0
219
+ while i < self.const_size:
220
+ constant, size = read_const(self.const_data, i)
221
+ self.constants.append(to_python(constant))
222
+ i += size
223
+
224
+ def ident(self, length: int = 0) -> str:
225
+ """制造缩进"""
226
+ return ' ' * (self.ident_counter + length)
227
+
228
+ def rv(self, i: int, level: int = 0) -> str:
229
+ """Read variable"""
230
+ if not i:
231
+ return 'None'
232
+ c = self.closure_counter - level
233
+ return f'var_{c}_{i}'
234
+
235
+ def wv(self, i: int, level: int = 0) -> str:
236
+ """Write variable"""
237
+ if not i:
238
+ return '_'
239
+ return self.rv(i, level)
240
+
241
+ def fun_name(self) -> str:
242
+ """函数名称"""
243
+ self.fun_name_counter += 1
244
+ return f'fun_{self.fun_name_counter}'
245
+
246
+ def create_regs_array(self,nreg,start_index=0):
247
+ target= ast.Tuple(
248
+ elts=[
249
+ ],
250
+ ctx=ast.Store())
251
+ regsValue = ast.Tuple(elts=[], ctx=ast.Load())
252
+ regs = ast.Assign(
253
+ targets=[target],
254
+ value=regsValue, lineno=0)
255
+
256
+ for i in range(nreg + 1):
257
+ if i:
258
+ target.elts.append(ast.Name(id=self.wv(i+start_index , -1), ctx=ast.Store()))
259
+ regsValue.elts.append(ast.Name(id='Uninitialized', ctx=ast.Load()))
260
+ else:
261
+ target.elts.append(ast.Name(id=self.wv(0 ,-1), ctx=ast.Store()))
262
+ regsValue.elts.append(ast.Name(id='Uninitialized', ctx=ast.Load()))
263
+
264
+ return regs
265
+
266
+ def create_function(self,func_name,regs):
267
+
268
+ args = ast.arguments(
269
+ posonlyargs=[],
270
+ args=[],
271
+ vararg=None,
272
+ kwonlyargs=[],
273
+ kw_defaults=[],
274
+ kwarg=None,
275
+ defaults=[]
276
+ )
277
+
278
+ code = ast.FunctionDef(func_name,args=args,body=[],decorator_list=[],lineno=0)
279
+
280
+ try_code=ast.Try(body=[cp('CpEnter'),regs],handlers=[],finalbody=[ast.Expr(
281
+ value=ast.Call(
282
+ func=ast.Name(id='CpExit', ctx=ast.Load()),
283
+ args=[],
284
+ keywords=[]))],orelse=[])
285
+ code.body.append(try_code)
286
+
287
+ return [code,try_code]
288
+
289
+ def create_loop(self,nreg,code,increment:Optional[ast.AugAssign]=None):
290
+
291
+
292
+ func_name = self.fun_name()
293
+ [loop_func_code,try_code] =self.create_function(func_name, self.create_regs_array(nreg-1,2))
294
+ code.body.append(loop_func_code)
295
+ loop_func_code.body.append(ast.Return(value=ast.Name(id='LoopContinue', ctx=ast.Load())))
296
+
297
+
298
+ code.body.append(
299
+ ast.Assign(
300
+ targets=[
301
+ ast.Name(id=f'inner{func_name}Result', ctx=ast.Store())],
302
+ value=ast_call('Call_', [ast.Name(id=func_name, ctx=ast.Load())]), lineno=0))
303
+ code.body.append(increment) if increment else None
304
+ code.body.append(
305
+ ast.If(
306
+ test=ast.Compare(
307
+ left=ast.Name(id=f'inner{func_name}Result', ctx=ast.Load()),
308
+ ops=[
309
+ ast.Is()],
310
+ comparators=[
311
+ ast.Name(id='LoopContinue', ctx=ast.Load())]),
312
+ body=[
313
+ ast.Continue()],
314
+ orelse=[
315
+ ast.If(
316
+ test=ast.Compare(
317
+ left=ast.Name(id=f'inner{func_name}Result', ctx=ast.Load()),
318
+ ops=[
319
+ ast.Is()],
320
+ comparators=[
321
+ ast.Name(id='LoopBreak', ctx=ast.Load())]),
322
+ body=[
323
+ ast.Break()],
324
+ orelse=[
325
+ ast.Return(
326
+ value=ast.Name(id=f'inner{func_name}Result', ctx=ast.Load()))])])
327
+ )
328
+
329
+ return try_code
330
+
331
+
332
+
333
+ def read_param(self, wide: bool) -> int:
334
+ """读取 code param"""
335
+ if wide:
336
+ value = struct.unpack('<I', self.code_data[self.code_offset:self.code_offset + 4])[0]
337
+ self.code_offset += 4
338
+ else:
339
+ value = self.code_data[self.code_offset]
340
+ self.code_offset += 1
341
+ return value
342
+
343
+ def read_index(self, wide: bool) -> int:
344
+ """读取 code index"""
345
+ if wide:
346
+ value = struct.unpack('<i', self.code_data[self.code_offset:self.code_offset + 4])[0]
347
+ self.code_offset += 4
348
+ else:
349
+
350
+ value = struct.unpack('<b', self.code_data[self.code_offset:self.code_offset + 1])[0]
351
+ self.code_offset += 1
352
+ return value
353
+
354
+ def read_closure(self,current_blocks_body:List[ast.stmt]) -> None:
355
+ """读取闭包"""
356
+ self.closure_counter += 1
357
+ self.ident_counter += 1
358
+
359
+ while self.code_offset < self.code_size:
360
+ opcode_raw = self.code_data[self.code_offset]
361
+ opcode = opcode_raw & 0x7f
362
+
363
+ if opcode != OpCode.FuncEnd:
364
+ self.read_code(current_blocks_body)
365
+ continue
366
+ self.code_offset += 1
367
+ self.closure_counter -= 1
368
+ self.ident_counter -= 1
369
+ break
370
+
371
+ def read_block_end(self, end_opcode: int,current_blocks_body:List[ast.stmt]) -> None:
372
+ """读取块结束"""
373
+ while self.code_offset < self.code_size:
374
+ opcode_raw = self.code_data[self.code_offset]
375
+ opcode = opcode_raw & 0x7f
376
+
377
+ if opcode != end_opcode:
378
+ self.read_code(current_blocks_body)
379
+ continue
380
+
381
+ self.code_offset += 1
382
+ self.ident_counter -= 1
383
+
384
+ if end_opcode == OpCode.LoopEnd:
385
+ self.closure_counter -= 1
386
+
387
+ # body = self.ident() + "};"
388
+ # self.code_lines.append(body)
389
+ break
390
+
391
+ def read_if_else(self,block:ast.If) -> None:
392
+ """读取 if else 或 if 结束"""
393
+ self.ident_counter += 1
394
+ body = block.body
395
+ while self.code_offset < self.code_size:
396
+ opcode_raw = self.code_data[self.code_offset]
397
+ opcode = opcode_raw & 0x7f
398
+
399
+ if opcode == OpCode.IfEnd:
400
+ return self.read_block_end(OpCode.IfEnd,body)
401
+ elif opcode == OpCode.Else:
402
+ self.code_offset += 1
403
+ body=block.orelse
404
+ break
405
+
406
+ elif opcode == OpCode.ElIf:
407
+ self.code_offset += 1
408
+ # body = self.ident(-1) + "} else "
409
+ # self.code_lines.append(body)
410
+ raise ValueError("ElIf not supported in Python emitter")
411
+
412
+
413
+ # return self.read_code()
414
+
415
+ self.read_code(block.body)
416
+
417
+ return self.read_block_end(OpCode.IfEnd,body)
418
+
419
+ def read_record(self,obj, block: ast.Dict) -> None:
420
+ """读取 record"""
421
+ self.ident_counter += 1
422
+
423
+ while self.code_offset < self.code_size:
424
+ opcode_raw = self.code_data[self.code_offset]
425
+ self.code_offset += 1
426
+ opcode = opcode_raw & 0x7f
427
+ wide = opcode_raw >= 0x80
428
+
429
+ def read():
430
+ return self.read_param(wide)
431
+
432
+ def add_Element(argsValue:list,fun_id='ElementOpt',key=None) -> None:
433
+ block.keys.append(key)
434
+ block.values.append(ast.Call(
435
+ func=ast.Name(id=fun_id, ctx=ast.Load()),
436
+ args=[ast.Name(id=a, ctx=ast.Load()) if not isinstance(a,ast.expr) else a for a in argsValue],
437
+ keywords=[]))
438
+ if opcode in (OpCode.FieldOpt, OpCode.Field):
439
+ field = read()
440
+ field_name = self.constants[field]
441
+ if field_name is None:
442
+ raise ValueError(f"Unknown field {field},{self.constants}")
443
+ value = read()
444
+ opt = opcode == OpCode.FieldOpt
445
+ if opt:
446
+
447
+ add_Element([ast.Constant(value=f"{field_name}"), self.rv(value)])
448
+
449
+ else:
450
+ add_Element([self.rv(value)],fun_id='Element',key=ast.Constant(value=field_name))
451
+ elif opcode in (OpCode.FieldOptDyn, OpCode.FieldDyn):
452
+ field = read()
453
+ value = read()
454
+ opt = opcode == OpCode.FieldOptDyn
455
+ if opt:
456
+ add_Element([self.rv(field), self.rv(value)])
457
+ else:
458
+ add_Element([self.rv(value)],fun_id='Element',key=ast.Name(id=self.rv(field), ctx=ast.Load()))
459
+ elif opcode in (OpCode.FieldOptIndex, OpCode.FieldIndex):
460
+ field = self.read_index(wide)
461
+ value = read()
462
+ opt = opcode == OpCode.FieldOptIndex
463
+ if opt:
464
+ add_Element([ast.Constant(value=ToString_(field)), self.rv(value)])
465
+ else:
466
+ add_Element([self.rv(value)],fun_id='Element',key=ast.Constant(value=str(field)))
467
+ elif opcode == OpCode.Spread:
468
+ value = read()
469
+ add_Element([ self.rv(value)],"RecordSpread_")
470
+
471
+
472
+
473
+
474
+ ident = self.ident()
475
+ # self.code_lines.append(ident + code)
476
+
477
+ if opcode == OpCode.Freeze:
478
+ return
479
+
480
+ def read_array(self, arr: int,block:ast.List) -> None:
481
+ """读取 array"""
482
+ self.ident_counter += 1
483
+
484
+ while self.code_offset < self.code_size:
485
+ opcode_raw = self.code_data[self.code_offset]
486
+ self.code_offset += 1
487
+ opcode = opcode_raw & 0x7f
488
+ wide = opcode_raw >= 0x80
489
+
490
+ def read():
491
+ return self.read_param(wide)
492
+
493
+
494
+
495
+ if opcode == OpCode.Item:
496
+ value = read()
497
+ block.elts.append(create_Element([self.rv(value)]))
498
+
499
+ elif opcode == OpCode.ItemRange:
500
+ start = read()
501
+ end = read()
502
+ # code = f"...ArrayRange({start}, {end}),"
503
+ block.elts.append(ast.Starred(value=create_Element([self.rv(start), self.rv(end)],fun_id="ArrayRange"), ctx=ast.Load()))
504
+ elif opcode == OpCode.ItemRangeDyn:
505
+ start = read()
506
+ end = read()
507
+ # code = f"...ArrayRange({self.rv(start)}, {self.rv(end)}),"
508
+ block.elts.append(ast.Starred(value=create_Element([self.rv(start), self.rv(end)],fun_id="ArrayRange"), ctx=ast.Load()))
509
+ elif opcode == OpCode.ItemRangeExclusiveDyn:
510
+ start = read()
511
+ end = read()
512
+ # code = f"...ArrayRangeExclusive({self.rv(start)}, {self.rv(end)}),"
513
+ block.elts.append(ast.Starred(value=create_Element([self.rv(start), self.rv(end)],fun_id="ArrayRangeExclusive"), ctx=ast.Load()))
514
+ elif opcode == OpCode.Spread:
515
+ value = read()
516
+ # code = f"...$ArraySpread({self.rv(value)}),"
517
+ block.elts.append(ast.Starred(value=create_Element([self.rv(value)],fun_id="ArraySpread_"), ctx=ast.Load()))
518
+ elif opcode == OpCode.Freeze:
519
+ pass
520
+ # self.ident_counter -= 1
521
+ # code = "]);"
522
+ else:
523
+ opcode_name = get_opcode_name(opcode)
524
+ code = f"// ?{opcode_name}"
525
+
526
+ ident = self.ident()
527
+ # self.code_lines.append(ident + code)
528
+
529
+ if opcode == OpCode.Freeze:
530
+ return
531
+
532
+ def read_code(self,current_blocks_body:Union[List[ast.stmt],None]=None) -> None:
533
+ """读取代码"""
534
+ opcode_raw = self.code_data[self.code_offset]
535
+ self.code_offset += 1
536
+ opcode = opcode_raw & 0x7f
537
+ wide = opcode_raw >= 0x80
538
+
539
+ def read():
540
+ return self.read_param(wide)
541
+
542
+ def read_index():
543
+ return self.read_index(wide)
544
+
545
+ ident = self.ident()
546
+ code=ast.Pass()
547
+ reg = 0
548
+ func_name=None
549
+ loop_node=None
550
+ # 处理各种操作码
551
+ if opcode in (OpCode.FuncVarg, OpCode.Func):
552
+ script = self.code_offset == 1
553
+ reg = read()
554
+ varg = opcode == OpCode.FuncVarg
555
+ argn = read()
556
+ regn = read()
557
+ args = ast.arguments(
558
+ posonlyargs=[],
559
+ args=[],
560
+ vararg=ast.arg(arg='args'),
561
+ kwonlyargs=[],
562
+ kw_defaults=[],
563
+ kwarg=ast.arg(arg='kwargs'),
564
+ defaults=[]
565
+ )
566
+ for i in range(argn):
567
+ wv = self.wv(i + 1, -1)
568
+ if varg and i == argn - 1:
569
+ # 最后一个参数为可变参数
570
+ args.vararg=ast.arg(arg='vargs')
571
+ else:
572
+ args.args.append(ast.arg(f"{wv}"))
573
+ args.defaults.append(ast.Constant(value=None, lineno=0))
574
+
575
+ target= ast.Tuple(
576
+ elts=[
577
+ ],
578
+ ctx=ast.Store())
579
+ regsValue = ast.Tuple(elts=[], ctx=ast.Load())
580
+ regs = ast.Assign(
581
+ targets=[target],
582
+ value=regsValue, lineno=0)
583
+ for i in range(regn - argn + 1):
584
+ if i:
585
+ target.elts.append(ast.Name(id=self.wv(i + argn, -1), ctx=ast.Store()))
586
+ regsValue.elts.append(ast.Name(id='Uninitialized',ctx=ast.Load()))
587
+ else:
588
+ target.elts.append(ast.Name(id=self.wv(0 ,-1), ctx=ast.Store()))
589
+ regsValue.elts.append(ast.Name(id='Uninitialized',ctx=ast.Load()))
590
+
591
+ if script:
592
+ args.args.insert(0, ast.arg(arg='context'))
593
+ args.defaults.insert(0, ast.Call(
594
+ func=ast.Name(id='GlobalFallback', ctx=ast.Load()),
595
+ args=[],
596
+ keywords=[]))
597
+ code = ast.FunctionDef("script",args=args,body=[],decorator_list=[],lineno=0)
598
+
599
+ self.func_script=code
600
+
601
+ try_code=ast.Try(body=[cp('CpEnter'),regs],handlers=[],finalbody=[ast.Expr(
602
+ value=ast.Call(
603
+ func=ast.Name(id='CpExit', ctx=ast.Load()),
604
+ args=[],
605
+ keywords=[]))],orelse=[])
606
+ code.body.append(try_code)
607
+
608
+ else:
609
+ func_name = self.wv(reg)
610
+ code = ast.FunctionDef(func_name,args=args,body=[],decorator_list=[],lineno=0)
611
+ try_code=ast.Try(body=[cp('CpEnter'),regs],handlers=[],finalbody=[cp('CpExit')],orelse=[])
612
+
613
+ code.body.append(try_code)
614
+
615
+ if varg:
616
+ try_code.body.append(ast.Assign(
617
+ targets=[ast.Name(id=self.wv(argn,-1), ctx=ast.Store())],
618
+ value=ast.Call(
619
+ func=ast.Name(id='Vargs', ctx=ast.Load()),
620
+ args=[
621
+ ast.Name(id='vargs', ctx=ast.Load())],
622
+ keywords=[]), lineno=0))
623
+
624
+ elif opcode == OpCode.Constant:
625
+ reg = read()
626
+ i = read()
627
+ c = self.constants[i]
628
+ code = ast.Assign(
629
+ targets=[
630
+ ast.Name(id=self.wv(reg), ctx=ast.Store())],
631
+ value=ast.Constant(value=c),lineno=0)
632
+
633
+ elif opcode == OpCode.Uninit:
634
+ reg = read()
635
+ # code = f"{self.wv(reg)} = undefined;"
636
+ code = ast.Assign(
637
+ targets=[ast.Name(id=self.wv(reg), ctx=ast.Store())],
638
+ value=ast.Name(id='Uninitialized',ctx=ast.Load()),lineno=0)
639
+
640
+ elif opcode == OpCode.Return:
641
+ reg = read()
642
+ # code = f"return {self.rv(reg)};"
643
+ code =ast.Return(value=create_parameter(self.rv(reg)))
644
+
645
+ elif opcode == OpCode.Format:
646
+ reg = read()
647
+ leftValue = read()
648
+ fmtValue = read_index()
649
+
650
+ code =ast.Assign(
651
+ targets=[
652
+ ast.Name(id=self.wv(reg), ctx=ast.Store())],
653
+ value=ast.Call(
654
+ func=ast.Name(id='Format_', ctx=ast.Load()),
655
+ args=[
656
+ ast.Name(id=self.rv(leftValue), ctx=ast.Load()),
657
+ ast.Constant(value=self.constants[fmtValue])],
658
+ keywords=[]),lineno=0)
659
+
660
+ elif opcode in (OpCode.Add, OpCode.Sub, OpCode.Mul, OpCode.Div, OpCode.Mod, OpCode.Pow,
661
+ OpCode.Gt, OpCode.Gte, OpCode.Lt, OpCode.Lte, OpCode.Eq, OpCode.Neq,
662
+ OpCode.Aeq, OpCode.Naeq, OpCode.Same, OpCode.Nsame, OpCode.In, OpCode.And, OpCode.Or):
663
+ reg = read()
664
+ left = read()
665
+ right = read()
666
+ opcode_name = get_opcode_name(opcode)
667
+ opArgs=[]
668
+ leftValue=self.rv(left)
669
+ rightValue=self.rv(right)
670
+
671
+ if leftValue=='None':
672
+ opArgs.append(ast.Constant(value=None))
673
+ else:
674
+ opArgs.append(ast.Name(id=leftValue, ctx=ast.Load()))
675
+ if rightValue=='None':
676
+ opArgs.append(ast.Constant(value=None))
677
+ else:
678
+ opArgs.append(ast.Name(id=rightValue, ctx=ast.Load()))
679
+ code =ast.Assign(
680
+ targets=[
681
+ ast.Name(id=self.wv(reg), ctx=ast.Store())],
682
+ value=ast.Call(
683
+ func=ast.Name(id=f"{opcode_name}_", ctx=ast.Load()),
684
+ args=opArgs,
685
+ keywords=[]),lineno=0)
686
+
687
+ elif opcode == OpCode.InGlobal:
688
+ reg = read()
689
+ left = read()
690
+ code = ast.Assign(
691
+ targets=[
692
+ ast.Name(id=self.wv(reg), ctx=ast.Store())],
693
+ value=ast.Call(
694
+ func=ast.Attribute(
695
+ value=ast.Name(id='context', ctx=ast.Load()),
696
+ attr='has',
697
+ ctx=ast.Load()),
698
+ args=[
699
+ ast.Call(
700
+ func=ast.Name(id='ToString_', ctx=ast.Load()),
701
+ args=[
702
+ ast.Name(id=self.rv(left), ctx=ast.Load())],
703
+ keywords=[])
704
+ ],
705
+ keywords=[]),lineno=0)
706
+
707
+
708
+ elif opcode == OpCode.Concat:
709
+ reg = read()
710
+ n = read()
711
+ args = [self.rv(read()) for _ in range(n)]
712
+ opcode_name = get_opcode_name(opcode)
713
+ code = assign_call(self.wv(reg), f"{opcode_name}_", [ast.Name(id=a, ctx=ast.Load()) for a in args])
714
+
715
+ elif opcode in (OpCode.Omit, OpCode.Pick):
716
+ reg = read()
717
+ value = read()
718
+ n = read()
719
+ args = [self.constants[read()] for _ in range(n)]
720
+ opcode_name = get_opcode_name(opcode)
721
+
722
+ call_args = ast.List(elts=[ast.Constant(value=a) for a in args], ctx=ast.Load())
723
+ code = assign_call(self.wv(reg), f"{opcode_name}_", [ ast.Name(id=self.rv(value), ctx=ast.Load()), call_args])
724
+
725
+ #
726
+ # code = f"{self.wv(reg)} = ${opcode_name}({self.rv(value)}, [{', '.join(args)}]);"
727
+
728
+ elif opcode in (OpCode.Call, OpCode.CallDyn):
729
+ reg = read()
730
+ func = read()
731
+ n = read()
732
+ args = [read() for _ in range(n)]
733
+ ns = read()
734
+ spreads = [read() for _ in range(ns)]
735
+
736
+ if opcode == OpCode.Call:
737
+ # Compatibility: ast.Index was removed in Python 3.9.
738
+ # Use ast.Index for older Pythons, and plain expr (ast.Constant) for 3.9+.
739
+ if sys.version_info >= (3, 9):
740
+ slice_node = ast.Constant(value=self.constants[func])
741
+ else:
742
+ slice_node = ast.Index(value=ast.Constant(value=self.constants[func]))
743
+
744
+ call_target = ast.Subscript(
745
+ value=ast.Name(id='context', ctx=ast.Load()),
746
+ slice=slice_node,
747
+ ctx=ast.Load())
748
+ else:
749
+ call_target = ast.Name(id=self.rv(func), ctx=ast.Load())
750
+
751
+
752
+ call_args = ast.Tuple(elts=[], ctx=ast.Load())
753
+ for i, a in enumerate(args):
754
+ if i in spreads:
755
+ # call_args.append(f"...$ArraySpread({self.rv(a)})")
756
+ call_args.elts.append(ast.Starred(create_Element([self.rv(a)],fun_id="ArraySpread_"), ctx=ast.Load()))
757
+ else:
758
+ # call_args.append(self.rv(a))
759
+ call_args.elts.append(ast.Name(id=self.rv(a), ctx=ast.Load(),lineno=0))
760
+
761
+
762
+ fun_args:list=[call_target]
763
+
764
+ if len(call_args.elts)>0:
765
+ fun_args.append(ast.Starred(value=call_args, ctx=ast.Load()))
766
+ code = assign_call(self.wv(reg), 'Call_', fun_args)
767
+
768
+
769
+
770
+ elif opcode == OpCode.Assign:
771
+ reg = read()
772
+ value = read()
773
+ if not value:
774
+ val = ast.Constant(value=None)
775
+ else:
776
+ val = ast.Name(id=self.rv(value), ctx=ast.Load())
777
+ code =ast.Assign(
778
+ targets=[
779
+ ast.Name(id=self.wv(reg), ctx=ast.Store())],
780
+ value=val,lineno=0)
781
+
782
+ elif opcode in (OpCode.Pos, OpCode.Neg, OpCode.Not, OpCode.Type, OpCode.ToBoolean,
783
+ OpCode.ToNumber, OpCode.ToString, OpCode.IsBoolean, OpCode.IsNumber,
784
+ OpCode.IsString, OpCode.IsRecord, OpCode.IsArray, OpCode.Length):
785
+ reg = read()
786
+ value = read()
787
+ opcode_name = get_opcode_name(opcode)
788
+ code = assign_call(self.wv(reg), f"{opcode_name}_", [ast.Name(id=self.rv(value), ctx=ast.Load())])
789
+ # code = f"{self.wv(reg)} = ${opcode_name}({self.rv(value)});"
790
+
791
+ elif opcode in (OpCode.AssertInit, OpCode.AssertNonNil):
792
+ reg = read()
793
+ opcode_name = get_opcode_name(opcode)
794
+ # code =ast.Expr( value=ast_call(f"{opcode_name}_", [ast.Constant(value=None)]))
795
+ if reg==0:
796
+ code =ast.Expr( value=ast_call(f"{opcode_name}_", [ast.Constant(value=None)]))
797
+ else:
798
+ code = assign_call('', f"{opcode_name}_", [ast.Name(id=self.rv(reg), ctx=ast.Load())])
799
+ # code = f"${opcode_name}({self.rv(reg)})"
800
+
801
+ # # 处理属性访问相关操作
802
+ elif opcode == OpCode.Get:
803
+ reg = read()
804
+ obj = read()
805
+ prop = self.constants[read()]
806
+ code = assign_call(self.wv(reg), 'Get_', [ast.Name(id=self.rv(obj), ctx=ast.Load()),ast.Constant(value=prop)])
807
+
808
+ elif opcode == OpCode.GetIndex:
809
+ reg = read()
810
+ obj = read()
811
+ index = read_index()
812
+ code = assign_call(self.wv(reg), 'Get_', [ast.Name(id=self.rv(obj), ctx=ast.Load()), ast.Constant(value=index)])
813
+ # code = f"{self.wv(reg)} = $Get({self.rv(obj)}, {index});"
814
+
815
+ elif opcode == OpCode.GetDyn:
816
+ reg = read()
817
+ obj = read()
818
+ index = read()
819
+ code = assign_call(self.wv(reg), 'Get_', [ast.Name(id=self.rv(obj), ctx=ast.Load()), ast.Name(id=self.rv(index), ctx=ast.Load())])
820
+ # code = f"{self.wv(reg)} = $Get({self.rv(obj)}, {self.rv(index)});"
821
+
822
+ elif opcode == OpCode.Has:
823
+ reg = read()
824
+ obj = read()
825
+ prop = self.constants[read()]
826
+ code = assign_call(self.wv(reg), 'Has_', [ast.Name(id=self.rv(obj), ctx=ast.Load()), ast.Constant(value=prop)])
827
+ # code = f"{self.wv(reg)} = $Has({self.rv(obj)}, {prop});"
828
+
829
+ elif opcode == OpCode.HasIndex:
830
+ reg = read()
831
+ obj = read()
832
+ index = read_index()
833
+ code = assign_call(self.wv(reg), 'Has_', [ast.Name(id=self.rv(obj), ctx=ast.Load()), ast.Constant(value=index)])
834
+ # code = f"{self.wv(reg)} = $Has({self.rv(obj)}, {index});"
835
+
836
+ elif opcode == OpCode.HasDyn:
837
+ reg = read()
838
+ obj = read()
839
+ index = read()
840
+ code = assign_call(self.wv(reg), 'Has_', [ast.Name(id=self.rv(obj), ctx=ast.Load()), ast.Name(id=self.rv(index), ctx=ast.Load())])
841
+ # code = f"{self.wv(reg)} = $Has({self.rv(obj)}, {self.rv(index)});"
842
+
843
+ elif opcode == OpCode.Set:
844
+ reg = read()
845
+ obj = read()
846
+ prop = self.constants[read()]
847
+ code = assign_call(self.wv(reg), 'Set_', [ast.Name(id=self.rv(obj), ctx=ast.Load()), ast.Constant(value=prop), ast.Name(id=self.rv(reg), ctx=ast.Load())])
848
+ # code = f"$Set({self.rv(obj)}, {prop}, {self.rv(reg)});"
849
+
850
+ elif opcode == OpCode.SetIndex:
851
+ reg = read()
852
+ obj = read()
853
+ index = read_index()
854
+ code = assign_call(self.wv(reg), 'Set_', [ast.Name(id=self.rv(obj), ctx=ast.Load()), ast.Constant(value=index), ast.Name(id=self.rv(reg), ctx=ast.Load())])
855
+ # code = f"$Set({self.rv(obj)}, {index}, {self.rv(reg)});"
856
+
857
+ elif opcode == OpCode.SetDyn:
858
+ reg = read()
859
+ obj = read()
860
+ index = read()
861
+ code = assign_call(self.wv(reg), 'Set_', [ast.Name(id=self.rv(obj), ctx=ast.Load()), ast.Name(id=self.rv(index), ctx=ast.Load()), ast.Name(id=self.rv(reg), ctx=ast.Load())])
862
+ # code = f"$Set({self.rv(obj)}, {self.rv(index)}, {self.rv(reg)});"
863
+
864
+ # 处理全局变量访问
865
+ elif opcode == OpCode.GetGlobal:
866
+ reg = read()
867
+ i = read()
868
+ c = self.constants[i]
869
+ code = assign_call(self.wv(reg), 'GetGlobal_', [ast.Name(id='context', ctx=ast.Load()), ast.Constant(value=c)])
870
+
871
+ elif opcode == OpCode.GetGlobalDyn:
872
+ reg = read()
873
+ name = read()
874
+ code = assign_call(self.wv(reg), 'GetGlobal_', [ast.Name(id='context', ctx=ast.Load()), ast.Name(id=self.rv(name), ctx=ast.Load())])
875
+ # code = f"{self.wv(reg)} = global[{self.rv(name)}] ?? null;"
876
+
877
+ # # 处理闭包变量
878
+ elif opcode == OpCode.GetUpvalue:
879
+ reg = read()
880
+ level = read()
881
+ up = read()
882
+ code = assign_call(self.wv(reg), 'Upvalue', [ast.Name(id=self.rv(up, level), ctx=ast.Load())])
883
+
884
+
885
+ elif opcode == OpCode.SetUpvalue:
886
+ reg = read()
887
+ level = read()
888
+ up = read()
889
+ if not current_blocks_body:
890
+ raise ValueError("No current block to set upvalue")
891
+
892
+ current_blocks_body.insert(0,ast.Nonlocal(
893
+ names=[self.rv(up, level)]))
894
+ code = ast.Assign(
895
+ targets=[
896
+ ast.Name(id=self.rv(up, level), ctx=ast.Store())],
897
+ value=ast.Name(id=self.rv(reg), ctx=ast.Load()),lineno=0)
898
+
899
+ # # 处理数组切片
900
+ elif opcode == OpCode.Slice:
901
+ reg = read()
902
+ obj = read()
903
+ start = read_index()
904
+ end = read_index()
905
+ code = assign_call(self.wv(reg), 'Slice_', [ast.Name(id=self.rv(obj), ctx=ast.Load()), ast.Constant(value=start), ast.Constant(value=end)])
906
+ # code = f"{self.wv(reg)} = $Slice({self.rv(obj)}, {start}, {end});"
907
+
908
+ elif opcode == OpCode.SliceStart:
909
+ reg = read()
910
+ obj = read()
911
+ end = read_index()
912
+ code = assign_call(self.wv(reg), 'Slice_', [ast.Name(id=self.rv(obj), ctx=ast.Load()), ast.Constant(value=None), ast.Constant(value=end)])
913
+ # code = f"{self.wv(reg)} = $Slice({self.rv(obj)}, null, {end});"
914
+
915
+ elif opcode == OpCode.SliceEnd:
916
+ reg = read()
917
+ obj = read()
918
+ start = read_index()
919
+ code = assign_call(self.wv(reg), 'Slice_', [ast.Name(id=self.rv(obj), ctx=ast.Load()), ast.Constant(value=start), ast.Constant(value=None)])
920
+ # code = f"{self.wv(reg)} = $Slice({self.rv(obj)}, {start}, null);"
921
+
922
+ elif opcode == OpCode.SliceDyn:
923
+ reg = read()
924
+ obj = read()
925
+ start = read()
926
+ end = read()
927
+ code = assign_call(self.wv(reg), 'Slice_', [create_parameter(self.rv(obj)), create_parameter(self.rv(start)), create_parameter(self.rv(end))])
928
+ # code = f"{self.wv(reg)} = $Slice({self.rv(obj)}, {self.rv(start)}, {self.rv(end)});"
929
+
930
+ elif opcode == OpCode.SliceExclusiveDyn:
931
+ reg = read()
932
+ obj = read()
933
+ start = read()
934
+ end = read()
935
+
936
+
937
+ code = assign_call(self.wv(reg), 'SliceExclusive_', [create_parameter(self.rv(obj)), create_parameter(self.rv(start)), create_parameter(self.rv(end))])
938
+ # code = f"{self.wv(reg)} = $SliceExclusive({self.rv(obj)}, {self.rv(start)}, {self.rv(end)});"
939
+
940
+ # # 处理数据结构初始化
941
+ elif opcode == OpCode.Record:
942
+ reg = read()
943
+ # code = f"{self.wv(reg)} = ({{"
944
+ code = ast.Assign(targets=[
945
+ ast.Name(id=self.wv(reg), ctx=ast.Store())],
946
+ value=ast.Dict(
947
+ keys=[],
948
+ values=[]),lineno=0)
949
+
950
+ elif opcode == OpCode.Array:
951
+ reg = read()
952
+ code =ast.Assign(targets=[
953
+ ast.Name(id=self.wv(reg), ctx=ast.Store())],
954
+ value=ast.List(
955
+ elts=[],
956
+ ctx=ast.Load()),lineno=0)
957
+ # code = f"{self.wv(reg)} = (["
958
+
959
+ # # 处理条件语句
960
+ elif opcode == OpCode.If:
961
+ cond = read()
962
+ code = create_if(self.rv(cond), False)
963
+ # code = f"if ($ToBoolean({self.rv(cond)})) {{"
964
+
965
+ elif opcode == OpCode.IfNot:
966
+ cond = read()
967
+ code = create_if(self.rv(cond), True)
968
+ # code = f"if (!$ToBoolean({self.rv(cond)})) {{"
969
+
970
+ elif opcode == OpCode.IfInit:
971
+ cond = read()
972
+ code = ast.If(test=ast.Compare(
973
+ left=ast.Name(id=self.rv(cond), ctx=ast.Load()),
974
+ ops=[
975
+ ast.IsNot()],
976
+ comparators=[
977
+ ast.Name(id='Uninitialized', ctx=ast.Load())]),
978
+ body=[],
979
+ orelse=[])
980
+
981
+ # code = f"if ({self.rv(cond)} !== undefined) {{"
982
+
983
+ elif opcode == OpCode.IfNotInit:
984
+ cond = read()
985
+ code = ast.If(test=ast.Compare(
986
+ left=ast.Name(id=self.rv(cond), ctx=ast.Load()),
987
+ ops=[
988
+ ast.Is()],
989
+ comparators=[
990
+ ast. Name(id='Uninitialized', ctx=ast.Load())]),
991
+ body=[],
992
+ orelse=[])
993
+ # code = f"if ({self.rv(cond)} === undefined) {{"
994
+
995
+ elif opcode == OpCode.IfNil:
996
+ cond = read()
997
+ code = ast.If(test=ast.Compare(
998
+ left=ast.Name(id=self.rv(cond), ctx=ast.Load()),
999
+ ops=[
1000
+ ast.Is()],
1001
+ comparators=[
1002
+ ast.Constant(value=None)]),
1003
+ body=[],
1004
+ orelse=[])
1005
+ # code = f"if ({self.rv(cond)} === null) {{"
1006
+
1007
+ elif opcode == OpCode.IfNotNil:
1008
+ cond = read()
1009
+ code = ast.If(test=ast.Compare(
1010
+ left=ast.Name(id=self.rv(cond), ctx=ast.Load()),
1011
+ ops=[
1012
+ ast.IsNot()],
1013
+ comparators=[
1014
+ ast.Constant(value=None)]),
1015
+ body=[],
1016
+ orelse=[])
1017
+
1018
+ # code = f"if ({self.rv(cond)} !== null) {{"
1019
+
1020
+ # # 处理循环语句
1021
+ elif opcode == OpCode.LoopFor:
1022
+ nreg = read()
1023
+ iterable = read()
1024
+ regs = [self.wv(i + 2, -1) for i in range(nreg - 1)]
1025
+ # code = f"for (let {self.wv(1, -1)} of $Iterable({self.rv(iterable)})) {{ Cp(); let _, {', '.join(regs)};"
1026
+
1027
+ code = ast.For(
1028
+ target=ast.Name(id=self.wv(1, -1), ctx=ast.Store()),
1029
+ iter=ast_call('Iterable_', [ast.Name(id=self.rv(iterable), ctx=ast.Load())]),
1030
+ body=[],
1031
+ orelse=[],lineno=0)
1032
+
1033
+ loop_node=self.create_loop(nreg,code)
1034
+
1035
+ elif opcode in (OpCode.LoopRange, OpCode.LoopRangeExclusive):
1036
+ nreg = read()
1037
+ start = read()
1038
+ end = read()
1039
+ exclusive = opcode == OpCode.LoopRangeExclusive
1040
+
1041
+ s,e,i,code= create_range_loop(self.wv(1, -1), self.rv(start), self.rv(end), exclusive)
1042
+ # code = ast.For(
1043
+ # target=ast.Name(id=self.wv(1, -1), ctx=ast.Store()),
1044
+ # iter=ast_call('Range_' if not exclusive else 'RangeExclusive_', [ast.Name(id=self.rv(start), ctx=ast.Load()), ast.Name(id=self.rv(end), ctx=ast.Load())]),
1045
+ # body=[],
1046
+ # orelse=[],lineno=0)
1047
+
1048
+ current_blocks_body.append(s)
1049
+ current_blocks_body.append(e)
1050
+ current_blocks_body.append(i)
1051
+ loop_node=self.create_loop(nreg,code,ast.AugAssign(
1052
+ target=ast.Name(id=self.wv(1, -1), ctx=ast.Store()),
1053
+ op=ast.Add(),
1054
+ value=ast.Constant(value=1)))
1055
+ elif opcode == OpCode.Loop:
1056
+ nreg = read()
1057
+
1058
+
1059
+ code = ast.While(test=ast.Constant(value=True), body=[ast.Expr(
1060
+ value=ast.Call(
1061
+ func=ast.Name(id='Cp', ctx=ast.Load()),
1062
+ args=[],
1063
+ keywords=[]))], orelse=[])
1064
+
1065
+ loop_node=self.create_loop(nreg,code)
1066
+
1067
+ elif opcode == OpCode.Break:
1068
+ # code = ast.Break()
1069
+ code = ast.Return(value=ast.Name(id='LoopBreak', ctx=ast.Load()))
1070
+
1071
+ elif opcode == OpCode.Continue:
1072
+ # code = "continue;"
1073
+ # code = ast.Continue()
1074
+ code = ast.Return(value=ast.Name(id='LoopContinue', ctx=ast.Load()))
1075
+
1076
+ else:
1077
+ # 默认处理未知 opcode
1078
+ opcode_name = get_opcode_name(opcode)
1079
+ logging.debug(f"Unknown opcode: {opcode_name} ({opcode}) at offset {self.code_offset - 1}")
1080
+
1081
+ if current_blocks_body is None :
1082
+ if not isinstance(code,ast.FunctionDef):
1083
+ raise ValueError("current_blocks_body is None, please set it before calling read_code")
1084
+ try_code= code.body[0]
1085
+ if not isinstance(try_code,ast.Try):
1086
+ raise ValueError(f"Expected Try node, got {type(try_code)}")
1087
+ current_blocks_body= try_code.body
1088
+
1089
+ else:
1090
+ current_blocks_body.append(code)
1091
+
1092
+
1093
+
1094
+ # 处理特殊的 opcode 后续逻辑
1095
+ if opcode in (OpCode.FuncVarg, OpCode.Func):
1096
+ if not isinstance(code,ast.FunctionDef):
1097
+ raise ValueError("current_blocks_body is None, please set it before calling read_code")
1098
+ try_code= code.body[0]
1099
+ if not isinstance(try_code,ast.Try):
1100
+ raise ValueError(f"Expected Try node, got {type(try_code)}")
1101
+ self.read_closure(try_code.body)
1102
+ self.ident_counter += 2
1103
+ pass
1104
+ elif opcode in (OpCode.If, OpCode.IfNot, OpCode.IfNil, OpCode.IfNotNil, OpCode.IfInit, OpCode.IfNotInit):
1105
+ if not isinstance(code, ast.If):
1106
+ raise ValueError(f"Expected If node, got {type(code)}")
1107
+ self.read_if_else(code)
1108
+ if len(code.body)<1:
1109
+ code.body.append(ast.Pass())
1110
+
1111
+ elif opcode in (OpCode.Loop, OpCode.LoopFor, OpCode.LoopRange, OpCode.LoopRangeExclusive):
1112
+ self.ident_counter += 1
1113
+ self.closure_counter += 1
1114
+ if loop_node is None:
1115
+ raise ValueError("while_node is None, please set it before calling read_code")
1116
+ self.read_block_end(OpCode.LoopEnd,loop_node.body)
1117
+ elif opcode == OpCode.Record:
1118
+ if not isinstance(code, ast.Assign):
1119
+ raise ValueError(f"Expected Assign node for Record, got {type(code)}")
1120
+ if not isinstance(code.value, ast.Dict):
1121
+ raise ValueError(f"Expected Dict value for Record, got {type(code.value)}")
1122
+ self.read_record(reg,code.value)
1123
+ elif opcode == OpCode.Array:
1124
+ if not isinstance(code, ast.Assign):
1125
+ raise ValueError(f"Expected Assign node for Record, got {type(code)}")
1126
+ if not isinstance(code.value, ast.List):
1127
+ raise ValueError(f"Expected Dict value for Record, got {type(code.value)}")
1128
+ self.read_array(reg,code.value)
1129
+
1130
+ def read(self) -> None:
1131
+ """读取 chunk"""
1132
+ self.read_consts()
1133
+ self.read_code()
1134
+
1135
+ def set_ast_positions(node, lineno=1, col_offset=0):
1136
+ """为AST节点设置行号和列偏移量"""
1137
+ for field, value in ast.iter_fields(node):
1138
+ if isinstance(value, list):
1139
+ for item in value:
1140
+ if isinstance(item, ast.AST):
1141
+ set_ast_positions(item, lineno, col_offset)
1142
+ elif isinstance(value, ast.AST):
1143
+ set_ast_positions(value, lineno, col_offset)
1144
+
1145
+ # 设置当前节点的位置信息
1146
+ if not hasattr(node, 'lineno'):
1147
+ node.lineno = lineno
1148
+ if not hasattr(node, 'col_offset'):
1149
+ node.col_offset = col_offset
1150
+ if not hasattr(node, 'annotation '):
1151
+ node.annotation = None
1152
+
1153
+ ## 将所有 nonlocal 声明提升到函数体顶部,有些情况下nonlocal声明可能在条件语句或循环内
1154
+ # ...existing code...
1155
+
1156
+
1157
+ def emit( chunk: bytes) :
1158
+ """生成代码"""
1159
+ try:
1160
+ try:
1161
+ import astor
1162
+ except ImportError:
1163
+ astor =None
1164
+
1165
+ gen = Emitter( chunk)
1166
+ gen.read()
1167
+ code=None
1168
+ if gen.func_script is not None:
1169
+ script =deep_nonlocal_fix(gen.func_script)
1170
+ set_ast_positions(script)
1171
+ module = ast.Module(body=[script], type_ignores=[])
1172
+ code=compile(module, "<string>", "exec")
1173
+ if code is not None:
1174
+ exec(code, vm_globals,)
1175
+ return vm_globals.get('script', None)
1176
+
1177
+ except Exception as e:
1178
+ traceback.print_exc()
1179
+
1180
+ return None
1181
+
1182
+