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.
@@ -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