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/__init__.py +11 -0
- mirascript/deep_nonlocal_fix.py +136 -0
- mirascript/diagnostics.py +82 -0
- mirascript/emit.py +1182 -0
- mirascript/main.py +26 -0
- mirascript/subtle.py +5 -0
- mirascript/vm/VmWrapper.py +50 -0
- mirascript/vm/__init__.py +15 -0
- mirascript/vm/env.py +13 -0
- mirascript/vm/error.py +19 -0
- mirascript/vm/helpers.py +124 -0
- mirascript/vm/operations.py +592 -0
- mirascript/vm/types/__init__.py +21 -0
- mirascript/vm/types/checker.py +107 -0
- mirascript/vm/types/const.py +39 -0
- mirascript/vm/types/context.py +130 -0
- mirascript/vm/types/extern.py +123 -0
- mirascript/vm/types/function.py +28 -0
- mirascript/vm/types/module.py +33 -0
- mirascript/vm/types/script.py +17 -0
- mirascript/vm/types/types.py +143 -0
- mirascript/vm/types/wrapper.py +56 -0
- mirascript-0.0.6.dist-info/METADATA +17 -0
- mirascript-0.0.6.dist-info/RECORD +26 -0
- mirascript-0.0.6.dist-info/WHEEL +5 -0
- mirascript-0.0.6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,592 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
from mirascript.helpers.convert.to_boolean import toBoolean
|
|
5
|
+
from mirascript.helpers.convert.to_format import toFormat
|
|
6
|
+
from mirascript.helpers.convert.to_number import toNumber
|
|
7
|
+
from mirascript.helpers.convert.to_string import toString
|
|
8
|
+
from mirascript.vm.error import VmError
|
|
9
|
+
|
|
10
|
+
from mirascript.vm.types.checker import is_vm_primitive
|
|
11
|
+
from mirascript.vm.types.module import VmModule
|
|
12
|
+
from mirascript.vm.types.wrapper import VmWrapper,isVmWrapper
|
|
13
|
+
|
|
14
|
+
from ..vm.types.checker import is_vm_const, is_vm_record
|
|
15
|
+
|
|
16
|
+
from .types.extern import VmExtern, is_vm_extern
|
|
17
|
+
from mirascript.vm.types.const import Uninitialized, getVmFunctionInfo
|
|
18
|
+
import unicodedata
|
|
19
|
+
## 标记当前值未返回的值
|
|
20
|
+
LoopContinue = type("LoopContinue", (), {})()
|
|
21
|
+
## 标记当前值为Break
|
|
22
|
+
LoopBreak = type("LoopBreak", (), {})()
|
|
23
|
+
|
|
24
|
+
def is_decimal_number(num):
|
|
25
|
+
"""判断数字是否为小数(不是整数)"""
|
|
26
|
+
|
|
27
|
+
if isinstance(num, (int, float)):
|
|
28
|
+
return isinstance(num, float) and not num.is_integer()
|
|
29
|
+
return False
|
|
30
|
+
def is_safe_integer(n):
|
|
31
|
+
"""
|
|
32
|
+
检查是否为安全整数(在 64 位浮点数精确表示范围内)
|
|
33
|
+
类似于 JavaScript 的 Number.isSafeInteger()
|
|
34
|
+
"""
|
|
35
|
+
if is_decimal_number(n):
|
|
36
|
+
return False
|
|
37
|
+
|
|
38
|
+
# 64 位浮点数能精确表示的最大整数范围
|
|
39
|
+
MIN_SAFE_INTEGER = -2**53 + 1
|
|
40
|
+
MAX_SAFE_INTEGER = 2**53 - 1
|
|
41
|
+
|
|
42
|
+
return MIN_SAFE_INTEGER <= n <= MAX_SAFE_INTEGER
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def IsNumber_(a):
|
|
48
|
+
if isinstance(a, bool):
|
|
49
|
+
return False
|
|
50
|
+
return isinstance(a, (int, float))
|
|
51
|
+
|
|
52
|
+
def isSame(a,b):
|
|
53
|
+
if(IsNumber_(a) and IsNumber_(b)):
|
|
54
|
+
return a ==b or (math.isnan(a) and math.isnan(b))
|
|
55
|
+
if a==b and type(a) is type(b):
|
|
56
|
+
return True
|
|
57
|
+
if isinstance(a,VmWrapper):
|
|
58
|
+
return a.same(b)
|
|
59
|
+
if isinstance(b,VmWrapper):
|
|
60
|
+
return b.same(a)
|
|
61
|
+
return False
|
|
62
|
+
def AssertInit_(val):
|
|
63
|
+
if val is Uninitialized:
|
|
64
|
+
raise VmError("Uninitialized value`",None)
|
|
65
|
+
|
|
66
|
+
def ToBoolean_(value):
|
|
67
|
+
AssertInit_(value)
|
|
68
|
+
return toBoolean(value)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def isVmArray(value):
|
|
72
|
+
|
|
73
|
+
if type(value) is list:
|
|
74
|
+
return True
|
|
75
|
+
return False
|
|
76
|
+
|
|
77
|
+
def ToNumber_(value):
|
|
78
|
+
"""
|
|
79
|
+
将输入值转换为数字
|
|
80
|
+
|
|
81
|
+
参数:
|
|
82
|
+
value: 要转换的值
|
|
83
|
+
default: 转换失败时返回的默认值
|
|
84
|
+
prefer_float: 是否优先转换为浮点数
|
|
85
|
+
|
|
86
|
+
返回:
|
|
87
|
+
转换后的数字,如果无法转换则返回默认值
|
|
88
|
+
"""
|
|
89
|
+
AssertInit_(value)
|
|
90
|
+
return toNumber(value)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def ToString_(val):
|
|
97
|
+
AssertInit_(val)
|
|
98
|
+
if val is None:
|
|
99
|
+
return ""
|
|
100
|
+
return toString(val,Uninitialized,False)
|
|
101
|
+
|
|
102
|
+
def overloadNumberString_(a,b):
|
|
103
|
+
|
|
104
|
+
if IsNumber_(a) or IsNumber_(b):
|
|
105
|
+
return True
|
|
106
|
+
if isinstance(a,str) or isinstance(b,str):
|
|
107
|
+
return False
|
|
108
|
+
return True
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def Add_(a,b):
|
|
113
|
+
return ToNumber_(a)+ToNumber_(b)
|
|
114
|
+
|
|
115
|
+
def Sub_(a,b):
|
|
116
|
+
return ToNumber_(a)-ToNumber_(b)
|
|
117
|
+
|
|
118
|
+
def Mul_(a,b):
|
|
119
|
+
return ToNumber_(a)*ToNumber_(b)
|
|
120
|
+
|
|
121
|
+
def Div_(a,b):
|
|
122
|
+
a = ToNumber_(a)
|
|
123
|
+
b = ToNumber_(b)
|
|
124
|
+
if b!=0:
|
|
125
|
+
return a / b
|
|
126
|
+
|
|
127
|
+
if a ==0:
|
|
128
|
+
return math.nan
|
|
129
|
+
return math.copysign(1,a)*math.copysign(1,b)*math.inf
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def Mod_(a,b):
|
|
133
|
+
|
|
134
|
+
x = ToNumber_(a)
|
|
135
|
+
y = ToNumber_(b)
|
|
136
|
+
"""
|
|
137
|
+
IEEE 754 标准的取余运算 (remainder operation)
|
|
138
|
+
对应 ECMAScript 的 % 运算符
|
|
139
|
+
|
|
140
|
+
规范定义:
|
|
141
|
+
1. If either operand is NaN, the result is NaN.
|
|
142
|
+
2. If x is ±Infinity, the result is NaN.
|
|
143
|
+
3. If y is ±Infinity and x is finite, the result is x.
|
|
144
|
+
4. If y is ±0, the result is NaN.
|
|
145
|
+
5. If x is ±0 and y is nonzero and finite, the result is x.
|
|
146
|
+
6. Otherwise, the result has the same sign as x and magnitude:
|
|
147
|
+
abs(x) - floor(abs(x) / abs(y)) × abs(y)
|
|
148
|
+
"""
|
|
149
|
+
# 1. If either operand is NaN, return NaN
|
|
150
|
+
if math.isnan(x) or math.isnan(y):
|
|
151
|
+
return math.nan
|
|
152
|
+
|
|
153
|
+
# 2. If x is ±Infinity, return NaN
|
|
154
|
+
if math.isinf(x):
|
|
155
|
+
return math.nan
|
|
156
|
+
|
|
157
|
+
# 3. If y is ±Infinity and x is finite, return x
|
|
158
|
+
if math.isinf(y):
|
|
159
|
+
return x
|
|
160
|
+
|
|
161
|
+
# 4. If y is ±0, return NaN
|
|
162
|
+
if y == 0:
|
|
163
|
+
return math.nan
|
|
164
|
+
|
|
165
|
+
# 5. If x is ±0 and y is nonzero and finite, return x (保留符号)
|
|
166
|
+
if x == 0:
|
|
167
|
+
return x # 保留 +0 或 -0 的符号
|
|
168
|
+
|
|
169
|
+
# 6. 计算取余:结果符号与 x 相同
|
|
170
|
+
# Python 的 % 运算符结果符号与除数相同,不符合 IEEE 754
|
|
171
|
+
# 需要使用 math.fmod,它的结果符号与被除数相同
|
|
172
|
+
return math.fmod(x, y)
|
|
173
|
+
|
|
174
|
+
def Pow_(a,b):
|
|
175
|
+
try:
|
|
176
|
+
return math.pow(ToNumber_(a),ToNumber_(b))
|
|
177
|
+
except ValueError as e:
|
|
178
|
+
return math.nan
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def And_(a,b):
|
|
182
|
+
return ToBoolean_(a) and ToBoolean_(b)
|
|
183
|
+
|
|
184
|
+
def Or_(a,b):
|
|
185
|
+
return ToBoolean_(a) or ToBoolean_(b)
|
|
186
|
+
|
|
187
|
+
def Gt_(a,b):
|
|
188
|
+
if overloadNumberString_(a,b):
|
|
189
|
+
return ToNumber_(a) > ToNumber_(b)
|
|
190
|
+
else:
|
|
191
|
+
return str(a) >str(b)
|
|
192
|
+
|
|
193
|
+
def Gte_(a,b):
|
|
194
|
+
if overloadNumberString_(a,b):
|
|
195
|
+
return ToNumber_(a) >= ToNumber_(b)
|
|
196
|
+
else:
|
|
197
|
+
return str(a) >= str(b)
|
|
198
|
+
|
|
199
|
+
def Lt_(a,b):
|
|
200
|
+
if overloadNumberString_(a,b):
|
|
201
|
+
return ToNumber_(a) < ToNumber_(b)
|
|
202
|
+
else:
|
|
203
|
+
return str(a) < str(b)
|
|
204
|
+
|
|
205
|
+
def Lte_(a,b):
|
|
206
|
+
if overloadNumberString_(a,b):
|
|
207
|
+
return ToNumber_(a) <= ToNumber_(b)
|
|
208
|
+
else:
|
|
209
|
+
return str(a) <= str(b)
|
|
210
|
+
|
|
211
|
+
def Eq_(a,b):
|
|
212
|
+
|
|
213
|
+
AssertInit_(a)
|
|
214
|
+
AssertInit_(b)
|
|
215
|
+
|
|
216
|
+
if isinstance(a, (int, float)) and isinstance(b, (int, float)):
|
|
217
|
+
return a==b
|
|
218
|
+
|
|
219
|
+
return isSame(a,b)
|
|
220
|
+
|
|
221
|
+
def Neq_(a,b):
|
|
222
|
+
return not Eq_(a,b)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
## 高级相等比较
|
|
226
|
+
def Aeq_(a,b):
|
|
227
|
+
|
|
228
|
+
if overloadNumberString_(a,b):
|
|
229
|
+
an = ToNumber_(a)
|
|
230
|
+
bn = ToNumber_(b)
|
|
231
|
+
EPS = 1e-15
|
|
232
|
+
if math.isnan(an) or math.isnan(bn):
|
|
233
|
+
return False
|
|
234
|
+
if an == bn:
|
|
235
|
+
return True
|
|
236
|
+
absoluteDifference = abs(an - bn)
|
|
237
|
+
if absoluteDifference < EPS:
|
|
238
|
+
return True
|
|
239
|
+
base = min(abs(an) , abs(bn))
|
|
240
|
+
return absoluteDifference < base * EPS
|
|
241
|
+
else:
|
|
242
|
+
as_str = ToString_(a)
|
|
243
|
+
bs_str = ToString_(b)
|
|
244
|
+
|
|
245
|
+
if as_str == bs_str:
|
|
246
|
+
return True
|
|
247
|
+
|
|
248
|
+
ai = unicodedata.normalize('NFC',as_str.lower())
|
|
249
|
+
bi = unicodedata.normalize('NFC',bs_str.lower())
|
|
250
|
+
return ai == bi
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def Naeq_(a,b):
|
|
254
|
+
return not Aeq_(a,b)
|
|
255
|
+
|
|
256
|
+
def Same_(a,b):
|
|
257
|
+
AssertInit_(a)
|
|
258
|
+
AssertInit_(b)
|
|
259
|
+
return isSame(a,b)
|
|
260
|
+
|
|
261
|
+
def Nsame_(a,b):
|
|
262
|
+
return not Same_(a,b)
|
|
263
|
+
|
|
264
|
+
def In_(a,b):
|
|
265
|
+
AssertInit_(a)
|
|
266
|
+
AssertInit_(b)
|
|
267
|
+
if b is None:
|
|
268
|
+
return False
|
|
269
|
+
if isVmArray(b):
|
|
270
|
+
if a is None:
|
|
271
|
+
return a in b
|
|
272
|
+
|
|
273
|
+
if is_vm_primitive(a):
|
|
274
|
+
return a in b
|
|
275
|
+
|
|
276
|
+
for item in b:
|
|
277
|
+
if isSame(a,item):
|
|
278
|
+
return True
|
|
279
|
+
return False
|
|
280
|
+
pk = ToString_(a)
|
|
281
|
+
if isinstance(b , dict):
|
|
282
|
+
|
|
283
|
+
return pk in b
|
|
284
|
+
if isVmWrapper(b):
|
|
285
|
+
return b.has(pk)
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
return False
|
|
289
|
+
|
|
290
|
+
def Concat_(*args):
|
|
291
|
+
result = ""
|
|
292
|
+
for a in args:
|
|
293
|
+
AssertInit_(a)
|
|
294
|
+
result += toFormat(a,None)
|
|
295
|
+
return result
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def Pos_(a):
|
|
299
|
+
# TO DO: implement Pos_
|
|
300
|
+
return ToNumber_(a)
|
|
301
|
+
pass
|
|
302
|
+
|
|
303
|
+
def Neg_(a):
|
|
304
|
+
return -ToNumber_(a)
|
|
305
|
+
|
|
306
|
+
def Not_(a):
|
|
307
|
+
return not ToBoolean_(a)
|
|
308
|
+
|
|
309
|
+
def Length_(a):
|
|
310
|
+
AssertInit_(a)
|
|
311
|
+
if isVmArray(a):
|
|
312
|
+
return len(a)
|
|
313
|
+
if isinstance(a, str):
|
|
314
|
+
return len(a)
|
|
315
|
+
if isinstance(a, dict):
|
|
316
|
+
return len(a)
|
|
317
|
+
if isinstance(a, VmWrapper) and hasattr(a,'length'):
|
|
318
|
+
return a.length()
|
|
319
|
+
raise TypeError(f"`Expected array, string or record, got {Type_(a)}")
|
|
320
|
+
|
|
321
|
+
def Omit_(a,b):
|
|
322
|
+
AssertInit_(a)
|
|
323
|
+
if a is None or not is_vm_record(a):
|
|
324
|
+
return {}
|
|
325
|
+
result = {}
|
|
326
|
+
|
|
327
|
+
valueKeys = a.keys()
|
|
328
|
+
omittedSet = set([ToString_(x) for x in b ])
|
|
329
|
+
for key in valueKeys:
|
|
330
|
+
if key not in omittedSet:
|
|
331
|
+
result[key] = a[key]
|
|
332
|
+
return result
|
|
333
|
+
|
|
334
|
+
def Pick_(a,b):
|
|
335
|
+
AssertInit_(a)
|
|
336
|
+
if a is None or not is_vm_record(a):
|
|
337
|
+
return {}
|
|
338
|
+
result = {}
|
|
339
|
+
for key in b:
|
|
340
|
+
k = ToString_(key)
|
|
341
|
+
if k in a:
|
|
342
|
+
result[k] = a[k]
|
|
343
|
+
|
|
344
|
+
return result
|
|
345
|
+
|
|
346
|
+
def sliceCore(a,start,end,exclusive):
|
|
347
|
+
length = len(a)
|
|
348
|
+
|
|
349
|
+
if math.isnan(start):
|
|
350
|
+
start = 0
|
|
351
|
+
elif start<0:
|
|
352
|
+
start = length+start
|
|
353
|
+
if math.isnan(end):
|
|
354
|
+
end = length
|
|
355
|
+
elif end<0:
|
|
356
|
+
end = length+end
|
|
357
|
+
if not math.isinf(start):
|
|
358
|
+
start =math.ceil(start)
|
|
359
|
+
else:
|
|
360
|
+
if start>0:
|
|
361
|
+
start = length
|
|
362
|
+
else:
|
|
363
|
+
start = 0
|
|
364
|
+
# --- DEBUG ---
|
|
365
|
+
|
|
366
|
+
if math.isinf(end) :
|
|
367
|
+
if end>0:
|
|
368
|
+
end = length
|
|
369
|
+
else:
|
|
370
|
+
end = 0
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
elif exclusive or not is_safe_integer(end):
|
|
374
|
+
end = math.ceil(end)
|
|
375
|
+
else:
|
|
376
|
+
end = int(end + 1)
|
|
377
|
+
return a[start:end]
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def Slice_(a,start,end):
|
|
381
|
+
AssertInit_(a)
|
|
382
|
+
if not isVmArray(a):
|
|
383
|
+
raise VmError(f"`Expected array, got {Type_(a)}",[])
|
|
384
|
+
s = ToNumber_(start) if start is not None else 0
|
|
385
|
+
e = ToNumber_(end) if end is not None else len(a)-1
|
|
386
|
+
return sliceCore(a,s,e,False)
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
def SliceExclusive_(a,start,end):
|
|
390
|
+
AssertInit_(a)
|
|
391
|
+
if not isVmArray(a):
|
|
392
|
+
raise VmError(f"`Expected array, got {Type_(a)}",[])
|
|
393
|
+
s = ToNumber_(start) if start is not None else 0
|
|
394
|
+
e = ToNumber_(end) if end is not None else len(a)
|
|
395
|
+
return sliceCore(a,s,e,True)
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def Call_(func,*args):
|
|
400
|
+
for a in args:
|
|
401
|
+
AssertInit_(a)
|
|
402
|
+
if isinstance(func,VmExtern) and hasattr(func,'callable'):
|
|
403
|
+
return func.call(args)
|
|
404
|
+
if callable(func):
|
|
405
|
+
|
|
406
|
+
if len(args)==0:
|
|
407
|
+
return func()
|
|
408
|
+
return func(*args)
|
|
409
|
+
raise VmError(f"{type(func)}, {func} object is not callable",None)
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
def Type_(val):
|
|
413
|
+
if val is Uninitialized or val is None:
|
|
414
|
+
return "nil"
|
|
415
|
+
if isinstance(val, bool):
|
|
416
|
+
return "boolean"
|
|
417
|
+
if isinstance(val, (int, float)):
|
|
418
|
+
return "number"
|
|
419
|
+
if isinstance(val, str):
|
|
420
|
+
return "string"
|
|
421
|
+
if isVmArray(val):
|
|
422
|
+
return "array"
|
|
423
|
+
if is_vm_record(val):
|
|
424
|
+
return "record"
|
|
425
|
+
if isinstance(val, VmExtern):
|
|
426
|
+
return "extern"
|
|
427
|
+
if isinstance(val, VmModule):
|
|
428
|
+
return "module"
|
|
429
|
+
if callable(val):
|
|
430
|
+
return "function"
|
|
431
|
+
return type(val).__name__
|
|
432
|
+
|
|
433
|
+
def IsBoolean_(val):
|
|
434
|
+
AssertInit_(val)
|
|
435
|
+
return isinstance(val, bool)
|
|
436
|
+
|
|
437
|
+
def IsString_(val):
|
|
438
|
+
AssertInit_(val)
|
|
439
|
+
return isinstance(val, str)
|
|
440
|
+
|
|
441
|
+
def IsRecord_(val):
|
|
442
|
+
AssertInit_(val)
|
|
443
|
+
return is_vm_record(val)
|
|
444
|
+
|
|
445
|
+
def IsArray_(val):
|
|
446
|
+
AssertInit_(val)
|
|
447
|
+
return isVmArray(val)
|
|
448
|
+
|
|
449
|
+
def AssertNonNil_(val):
|
|
450
|
+
AssertInit_(val)
|
|
451
|
+
if val is not None:
|
|
452
|
+
return
|
|
453
|
+
raise VmError("Expected non-nil value",None)
|
|
454
|
+
|
|
455
|
+
def Has_(obj,key):
|
|
456
|
+
AssertInit_(obj)
|
|
457
|
+
pk = ToString_(key)
|
|
458
|
+
if obj is None:
|
|
459
|
+
return False
|
|
460
|
+
|
|
461
|
+
if isinstance(obj,VmWrapper):
|
|
462
|
+
return obj.has(pk)
|
|
463
|
+
if isinstance(obj,dict):
|
|
464
|
+
return pk in obj
|
|
465
|
+
if isinstance(obj,(list,tuple)) :
|
|
466
|
+
try:
|
|
467
|
+
idx = int(float(key))
|
|
468
|
+
return 0<= idx < len(obj)
|
|
469
|
+
except:
|
|
470
|
+
return False
|
|
471
|
+
if hasattr(obj,pk):
|
|
472
|
+
return True
|
|
473
|
+
return False
|
|
474
|
+
|
|
475
|
+
def Get_(obj,key):
|
|
476
|
+
AssertInit_(obj)
|
|
477
|
+
pk = ToString_(key)
|
|
478
|
+
if obj is None:
|
|
479
|
+
return None
|
|
480
|
+
|
|
481
|
+
if isinstance(obj,VmWrapper):
|
|
482
|
+
return obj.get(pk)
|
|
483
|
+
if isinstance(obj,dict):
|
|
484
|
+
return obj.get(pk,None)
|
|
485
|
+
if isinstance(obj,(list,tuple)) :
|
|
486
|
+
|
|
487
|
+
try:
|
|
488
|
+
idx = int(float(key))
|
|
489
|
+
return obj[idx]
|
|
490
|
+
except:
|
|
491
|
+
return None
|
|
492
|
+
if hasattr(obj,pk):
|
|
493
|
+
return getattr(obj,pk)
|
|
494
|
+
return None
|
|
495
|
+
|
|
496
|
+
def GetGlobal_(obj,key):
|
|
497
|
+
|
|
498
|
+
r= Get_(obj,key)
|
|
499
|
+
return r
|
|
500
|
+
pass
|
|
501
|
+
|
|
502
|
+
def Set_(obj,key,val):
|
|
503
|
+
AssertInit_(obj)
|
|
504
|
+
AssertInit_(val)
|
|
505
|
+
pk = ToString_(key)
|
|
506
|
+
if obj is None:
|
|
507
|
+
return
|
|
508
|
+
if not is_vm_extern(obj):
|
|
509
|
+
raise VmError(f"`Expected extern object, got {Type_(obj)}",None)
|
|
510
|
+
|
|
511
|
+
obj.set(pk,val)
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
def Iterable_(val):
|
|
516
|
+
AssertInit_(val)
|
|
517
|
+
if isVmWrapper(val):
|
|
518
|
+
if hasattr(val,'keys'):
|
|
519
|
+
return val.keys()
|
|
520
|
+
if isinstance(val, (list,tuple)):
|
|
521
|
+
return val
|
|
522
|
+
if isinstance(val, dict):
|
|
523
|
+
return val.keys()
|
|
524
|
+
raise VmError(f"`Value is not iterable {Type_(val)}",None)
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
def RecordSpread_(val):
|
|
528
|
+
AssertInit_(val)
|
|
529
|
+
if val is None:
|
|
530
|
+
return {}
|
|
531
|
+
if isVmArray(val):
|
|
532
|
+
result = {}
|
|
533
|
+
for i in range(len(val)):
|
|
534
|
+
result[str(i)] = val[i]
|
|
535
|
+
return result
|
|
536
|
+
if isinstance(val,dict):
|
|
537
|
+
return val
|
|
538
|
+
if is_vm_extern(val):
|
|
539
|
+
result = {}
|
|
540
|
+
for key in val.keys():
|
|
541
|
+
value = val.get(key)
|
|
542
|
+
if is_vm_primitive(value):
|
|
543
|
+
result[key] = value
|
|
544
|
+
return result
|
|
545
|
+
|
|
546
|
+
if isinstance(val,VmWrapper) and hasattr(val,'to_dict'):
|
|
547
|
+
return val.to_dict()
|
|
548
|
+
|
|
549
|
+
raise VmError(f"`Expected record, extern or nil, got {Type_(val)}",None)
|
|
550
|
+
|
|
551
|
+
def ArraySpread_(val):
|
|
552
|
+
AssertInit_(val)
|
|
553
|
+
if val is None:
|
|
554
|
+
return []
|
|
555
|
+
if isVmArray(val):
|
|
556
|
+
return val
|
|
557
|
+
|
|
558
|
+
raise VmError(f"`Expected array, iterable extern or nil, got {Type_(val)}",None)
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
def Format_(val, fmt=None):
|
|
563
|
+
AssertInit_(val)
|
|
564
|
+
|
|
565
|
+
return toFormat(val,fmt)
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
def Range_(start,end):
|
|
570
|
+
s = ToNumber_(start)
|
|
571
|
+
e = ToNumber_(end)
|
|
572
|
+
if math.isnan(s) or math.isnan(e):
|
|
573
|
+
return []
|
|
574
|
+
result=[]
|
|
575
|
+
while s<=e:
|
|
576
|
+
result.append(s)
|
|
577
|
+
s+=1
|
|
578
|
+
return result
|
|
579
|
+
|
|
580
|
+
def RangeExclusive_(start,end):
|
|
581
|
+
pass
|
|
582
|
+
s = ToNumber_(start)
|
|
583
|
+
e = ToNumber_(end)
|
|
584
|
+
if math.isnan(s) or math.isnan(e):
|
|
585
|
+
return []
|
|
586
|
+
# return list(range(int(s),int(e)))
|
|
587
|
+
result=[]
|
|
588
|
+
while s<e:
|
|
589
|
+
result.append(s)
|
|
590
|
+
s+=1
|
|
591
|
+
return result
|
|
592
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from typing import Tuple, Union
|
|
3
|
+
from .const import VmAny, VmPrimitive, VmRecord, VmArray,VmValue,VmUninitialized
|
|
4
|
+
from .extern import VmExtern, wrap_to_vm_value, unwrap_from_vm_value
|
|
5
|
+
from .function import VmFunction
|
|
6
|
+
from .module import VmModule
|
|
7
|
+
from .wrapper import VmWrapper
|
|
8
|
+
from .context import VmContext, create_vm_context, DefaultVmContext
|
|
9
|
+
from .script import VmScript, is_vm_script
|
|
10
|
+
from .checker import is_vm_any, is_vm_const, is_vm_immutable, is_vm_value
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
'VmExtern', 'wrap_to_vm_value', 'unwrap_from_vm_value',
|
|
15
|
+
'VmFunction',
|
|
16
|
+
'VmModule', 'VmWrapper', 'VmContext',
|
|
17
|
+
'create_vm_context', 'DefaultVmContext', 'VmScript', 'is_vm_script',
|
|
18
|
+
'is_vm_any', 'is_vm_const', 'is_vm_immutable', 'is_vm_value',
|
|
19
|
+
'VmPrimitive', 'VmRecord', 'VmArray','VmValue', 'VmAny','VmUninitialized'
|
|
20
|
+
]
|
|
21
|
+
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import math
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from mirascript.vm.types.extern import is_vm_extern
|
|
6
|
+
|
|
7
|
+
from .wrapper import VmWrapper
|
|
8
|
+
from .module import VmModule
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
MAX_DEPTH = 100
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def is_vm_primitive(value) -> bool:
|
|
17
|
+
return isinstance(value, (str, int, float, bool)) or value is None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def is_vm_array(value):
|
|
21
|
+
# VmArray 应为普通数组
|
|
22
|
+
if not isinstance(value, list):
|
|
23
|
+
return False
|
|
24
|
+
return True
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def is_vm_record(value):
|
|
28
|
+
# VmRecord 应为普通对象或空原型对象
|
|
29
|
+
if not isinstance(value, dict):
|
|
30
|
+
return False
|
|
31
|
+
return True
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def is_vm_const_inner(value, depth):
|
|
35
|
+
if depth >= MAX_DEPTH:
|
|
36
|
+
return False
|
|
37
|
+
depth += 1
|
|
38
|
+
if isinstance(value, (str, int, float, bool)) or value is None:
|
|
39
|
+
return True
|
|
40
|
+
if isinstance(value, VmWrapper):
|
|
41
|
+
return False
|
|
42
|
+
if isinstance(value, list):
|
|
43
|
+
return is_vm_array(value)
|
|
44
|
+
if isinstance(value, dict):
|
|
45
|
+
return is_vm_record(value)
|
|
46
|
+
return False
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def is_vm_const(value, check_deep=False):
|
|
50
|
+
if isinstance(value, (str, int, float, bool)):
|
|
51
|
+
return True
|
|
52
|
+
if value is None:
|
|
53
|
+
return True
|
|
54
|
+
if isinstance(value, VmWrapper):
|
|
55
|
+
return False
|
|
56
|
+
if not check_deep:
|
|
57
|
+
if isinstance(value, list):
|
|
58
|
+
return is_vm_array(value)
|
|
59
|
+
if isinstance(value, dict):
|
|
60
|
+
return is_vm_record(value)
|
|
61
|
+
return False
|
|
62
|
+
else:
|
|
63
|
+
return is_vm_const_inner(value, 1)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def is_vm_immutable(value, check_deep=False):
|
|
67
|
+
# VmModule 需补充
|
|
68
|
+
return False #
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def is_vm_value(value, check_deep=False):
|
|
72
|
+
if value is None:
|
|
73
|
+
return False
|
|
74
|
+
return is_vm_any(value, check_deep)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def is_vm_any(value, check_deep=False):
|
|
78
|
+
if isinstance(value, (str, int, float, bool)) or value is None:
|
|
79
|
+
return True
|
|
80
|
+
if isinstance(value, VmWrapper):
|
|
81
|
+
return True
|
|
82
|
+
if isinstance(value, list) or isinstance(value, dict):
|
|
83
|
+
return is_vm_const(value, check_deep)
|
|
84
|
+
if callable(value):
|
|
85
|
+
return True
|
|
86
|
+
return False
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def is_vm_module(value) -> bool:
|
|
90
|
+
# VmModule 需补充
|
|
91
|
+
return isinstance(value, VmModule)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
## 判断正负零
|
|
95
|
+
def is_positive_zero(value: Any) -> bool:
|
|
96
|
+
return math.copysign(1.0, value) > 0 and value == 0.0
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def is_negative_zero(value: Any) -> bool:
|
|
100
|
+
return math.copysign(1.0, value) < 0 and value == 0.0
|
|
101
|
+
|
|
102
|
+
def is_vm_callable(value) -> bool:
|
|
103
|
+
if callable(value):
|
|
104
|
+
return True
|
|
105
|
+
if is_vm_extern(value) and callable(value.value):
|
|
106
|
+
return True
|
|
107
|
+
return False
|