-
Notifications
You must be signed in to change notification settings - Fork 0
/
instructions.go
3824 lines (3390 loc) · 90.6 KB
/
instructions.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Copyright 2022 of chainx.zh@gmail.com, All rights reserved.
// Use of this source code is governed by a MIT license.
// Package inst 脚本基础指令集的实现。
package inst
import (
"bytes"
crand "crypto/rand"
"crypto/sha256"
"crypto/sha512"
"encoding/base32"
"encoding/base64"
"encoding/binary"
"errors"
"fmt"
"math"
"math/big"
"math/rand"
"regexp"
"strconv"
"strings"
"time"
"unicode/utf8"
"github.com/cxio/cbase"
"github.com/cxio/cbase/base58"
"github.com/cxio/cbase/chash"
"github.com/cxio/cbase/paddr"
"github.com/cxio/locale"
"github.com/cxio/script/ibase"
"github.com/cxio/script/icode"
"github.com/cxio/script/inst/expr"
"github.com/cxio/script/inst/instex"
"github.com/cxio/script/inst/ipriv"
"github.com/cxio/script/inst/model"
"github.com/cxio/script/inst/mox"
"github.com/cxio/script/instor"
"github.com/cxio/script/xpool"
"golang.org/x/crypto/blake2b"
"golang.org/x/crypto/sha3"
)
var _T = locale.GetText // 本地化文本获取。
// 执行器引用。
type Actuator = ibase.Actuator
// 指令配置器引用。
type Instx = ibase.Instx
// 调用器引用
type Wrapper = ibase.Wrapper
// 指令信息包引用。
type Insted = instor.Insted
// 公钥类型引用。
type PubKey = ibase.PubKey
// 出错提示信息。
var (
neverToHere = ibase.ErrToHere
inputEmpty = _T("输入缓存区为空,无法继续")
errConvInt = _T("转换到整数时出错")
errConvByte = _T("转换到字节时出错")
errConvRune = _T("转换到单个字符时出错")
errConvBigInt = _T("转换到大整数时出错")
errConvFloat = _T("转换到浮点数时出错")
errConvDate = _T("转换到时间时出错")
bytesLenFail = _T("字节长度出错")
accessError = _T("执行流抵达不可访问的占位指令")
errMChkSig = _T("多重签名的公钥和签名数量不相等")
)
// 基本错误值。
var (
// 通关检查失败。
NotPass = errors.New(_T("通关验证没有通过"))
// 模式取值失败。
ErrModel = errors.New(_T("目标脚本的模式匹配失败"))
)
/*
* 基本类型。
******************************************************************************
*/
// 布尔类型
type Bool = instor.Bool
// 通用整数
type Int = instor.Int
// 字节类型
type Byte = instor.Byte
// 字符类型
type Rune = instor.Rune
// 通用浮点数
type Float = instor.Float
// 大整数
type BigInt = instor.BigInt
// 文本串
type String = instor.String
// 字节序列
type Bytes = instor.Bytes
// 字符序列
type Runes = instor.Runes
// 时间类型
type Time = instor.Time
// 脚本类型
type Script = instor.Script
// 正则表达式
type RegExp = instor.RegExp
// 数值类型约束
type Number = instor.Number
// 整数类型约束
type Integer = instor.Integer
// 切片成员类型约束
type Itemer = instor.Itemer
// 字典类型。
// 注:与切片类型一起被归类为集合。
type Dict map[string]any
// 退出类型:
// - RETURN 函数内返回,结束函数执行。
// - EXIT 脚本结束(视为验证通过)。
// 说明:
// 与 cease 类似,由内层panic()抛出,但携带数据用于表达返回值。
type Leave struct {
Kind int // RETURN or EXIT
Data any // 返回值
}
// 停止类型:
// - _CONTINUE_ EACH{} 内进入下一迭代(结束当前循环)。
// - _BREAK_ 退出当前 CASE 或中断 EACH 迭代。
// 说明:
// 该类型的值通过panic()抛出,上级调用者捕获后判断执行相应逻辑。
type cease int
// 停止类型定义
const (
_CONTINUE_ cease = iota // 默认下一轮
_BREAK_
)
// 退出类型定义
const (
RETURN int = iota
EXIT
)
// 脚本源码片段标识
// 仅针对当前块,包含子块但无法包含父块。
const (
SOURCE_ALL = 0 // 全部
SOURCE_PAST = -1 // 已执行过(含当前)
SOURCE_PASTX = -2 // 已执行过(NULL=>当前)
SOURCE_NEXT = 1 // 后阶部分
SOURCE_XALL = 2 // NULL=>末尾
)
// 环境值提取器配置。
// 用于提取不直接存在于env集合内的值。
var __envGetter = map[int]func(*Actuator) any{
// 跳转计数
instor.EnvGotos: func(a *Actuator) any { return a.Gotos() },
// 嵌入计数
instor.EnvJumps: func(a *Actuator) any { return a.Jumps() },
//... 待定
}
// 映射指令集。
// - 键:目标指令索引。
// - 值:目标指令配置对象。
// 适用:
// 由附参直接定义目标指令的扩展类指令,
// 如 FN_X, EX_FN 和具体的某个模块如 MO_RE 等。
type mapInst = map[int]Instx
// 直接扩展类指令清单配置。
// - 键:指令码。
// - 值:映射指令集。
// 注:
// 不含自由扩展类 MO_X、EX_INST 和 EX_PRIV。
var __extenList = map[int]mapInst{
icode.FN_X: __fnxSet,
icode.EX_FN: __exfnSet,
icode.MO_RE: __moSetRE,
icode.MO_TIME: __moSetTime,
// ...
}
// 指令配置集。
// 下标位置对应指令的值,该位置存放相应指令的封装器和参数数量定义。
// 注:
// FN_X 及之后为扩展部分,并不在此设置。
var __InstSet [icode.FN_X]Instx
/*
* 值指令
* 多字节整数采用变长正整数存储。
* 其它多字节长度定义采用大端/网络字节序(BigEndian)。
******************************************************************************
*/
// 指令:NIL
// 返回:nil
func _NIL(a *Actuator, _ []any, _ any, _ ...any) []any {
a.Revert()
return []any{nil}
}
// 指令:TRUE
// 返回:Bool
func _TRUE(a *Actuator, _ []any, _ any, _ ...any) []any {
a.Revert()
return []any{true}
}
// 指令:FALSE
// 返回:Bool
func _FALSE(a *Actuator, _ []any, _ any, _ ...any) []any {
a.Revert()
return []any{false}
}
// 指令:{}(1-x) 整数指令
// 附参:1-x bytes,即整数值本身。x为变长字节。
// 返回:Int
func _Int(a *Actuator, _ []any, data any, _ ...any) []any {
a.Revert()
return []any{data.(Int)}
}
// 指令:{}(1) 字节类型 byte
// 附参:1 byte,单字节值。
// 返回:Byte
func _Byte(a *Actuator, _ []any, data any, _ ...any) []any {
a.Revert()
return []any{data.(Byte)}
}
// 指令:{}(4) 字符类型 rune
// 附参:4 byte,单字符值。
// 返回:Rune
func _Rune(a *Actuator, _ []any, data any, _ ...any) []any {
a.Revert()
return []any{data.(Rune)}
}
// 指令:{}(4-8) 浮点数
// 附参:4-8 bytes,浮点数值
// 返回:Float
func _Float(a *Actuator, _ []any, data any, _ ...any) []any {
a.Revert()
return []any{data.(Float)}
}
// 指令:DATE{}(~) 时间对象
// 附参:不定长度,变长正整数毫秒数。
// 返回:Time
func _DATE(a *Actuator, _ []any, data any, _ ...any) []any {
a.Revert()
return []any{data.(Time)}
}
// 指令:{}(1)+N 大整数
// 附参:1 byte,值占用的字节数(长度)
// 返回:一个实例指针。
func _BigInt(a *Actuator, _ []any, data any, _ ...any) []any {
a.Revert()
return []any{data.(*BigInt)}
}
// 指令:DATA{}(1-2) 短字节序列
// 附参:1-2 bytes,字节序列长度
// 返回:Bytes
func _DATA(a *Actuator, _ []any, data any, _ ...any) []any {
a.Revert()
return []any{data.(Bytes)}
}
// 指令:TEXT{}(1-2) 文本串
// 附参:1-2 bytes,文本串长度
// 返回:String
func _TEXT(a *Actuator, _ []any, data any, _ ...any) []any {
a.Revert()
return []any{data.(String)}
}
// 指令:/.../(1) 正则表达式
// 附参:1 byte,表达式长度(<256)
// 返回:一个实例指针。
func _RegExp(a *Actuator, _ []any, data any, _ ...any) []any {
a.Revert()
return []any{data.(*RegExp)}
}
// 指令:CODE{}(1) 指令代码序列
// 附参:1 byte,序列长度(<256)
// 返回:*Script
func _CODE(a *Actuator, _ []any, data any, _ ...any) []any {
a.Revert()
return []any{data.(*Script)}
}
/*
* 取值指令
* 返回值:无。
******************************************************************************
*/
// 指令:@ 实参捕获
// 仅需设置一个标志指明返回值去向即可。
// .fromStack确定为假,强制 ~ 指令只能跟随在后。
func _Capture(a *Actuator, _ []any, _ any, _ ...any) []any {
a.BackTo = ibase.ArgsFlag
a.FromStack = false
a.Change()
return nil
}
// 指令:~ 实参直取
// 可能跟随在 @ 和 $ 之后,标记跟随指令的实参渠道。
func _Bring(a *Actuator, _ []any, _ any, _ ...any) []any {
a.FromStack = true
a.Change()
return nil
}
// 指令:$ 局域存值
// .fromStack确定为假,强制 ~ 指令只能跟随在后。
func _ScopeAdd(a *Actuator, _ []any, _ any, _ ...any) []any {
a.BackTo = ibase.ScopeFlag
a.FromStack = false
a.Change()
return nil
}
// 指令:$(1) 局域取值
// 附参:1 byte,指示取值下标,int8
// 注:
// 普通状态下取值直接进入实参区。
// 在表达式内时直接返回参与计算。
func _ScopeVal(a *Actuator, aux []any, _ any, _ ...any) []any {
a.Revert()
v := a.ScopeItem(aux[0].(int))
// 表达式内时
if a.InExpr() {
return []any{v}
}
a.PutArgs(v)
return nil
}
// 指令:${}(1) 循环域取值
// 附参:1 byte,目标值位置下标 [0-3]。
// 注:
// 同上取值自动进入实参区,但表达式内例外。
func _LoopVal(a *Actuator, aux []any, _ any, _ ...any) []any {
a.Revert()
i := aux[0].(int)
// 表达式内时
if a.InExpr() {
return []any{a.LoopItem(i)}
}
a.PutArgs(a.LoopItem(i))
return nil
}
/*
* 栈操作指令
******************************************************************************
*/
// 指令:NOP 无操作
// 返回:无。
// 外部会根据实参数量配置(-1)自动提取实参,
// 因此简单忽略传入的实参即可。
func _NOP(a *Actuator, _ []any, _ any, _ ...any) []any {
a.Revert()
return nil
}
// 指令:PUSH 数据入栈
// 返回:无。
func _PUSH(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
if len(vs) > 0 {
a.StackPush(vs...)
}
return nil
}
// 指令:SHIFT(1) 提取栈顶条目
// 附参:1 byte,取栈条目数,uint8
// 返回:多值自动展开。
func _SHIFT(a *Actuator, aux []any, _ any, _ ...any) []any {
a.Revert()
return a.StackPops(aux[0].(int))
}
// 指令:CLONE(1) 栈顶项克隆
// 附参:1 byte,栈顶项数,uint8
// 返回:多值自动展开。
func _CLONE(a *Actuator, aux []any, _ any, _ ...any) []any {
a.Revert()
return a.StackTops(aux[0].(int))
}
// 指令:POP 弹出栈顶项
// 返回:any
func _POP(a *Actuator, _ []any, _ any, _ ...any) []any {
a.Revert()
return []any{a.StackPop()}
}
// 指令:POPS(1) 弹出栈顶多项
// 附参:1 byte,弹出条目数,uint8,0表示全部。
// 返回:[]any
func _POPS(a *Actuator, aux []any, _ any, _ ...any) []any {
a.Revert()
n := aux[0].(int)
if n == 0 {
n = a.StackSize()
}
return []any{a.StackPops(n)}
}
// 指令:TOP 引用栈顶项
// 返回:any
func _TOP(a *Actuator, _ []any, _ any, _ ...any) []any {
a.Revert()
return []any{a.StackTop()}
}
// 指令:TOPS(1) 引用栈顶多项
// 附参:1 byte,引用条目数,uint8
// 返回:[]any
func _TOPS(a *Actuator, aux []any, _ any, _ ...any) []any {
a.Revert()
n := aux[0].(int)
if n == 0 {
return []any{} // 空集
}
return []any{a.StackTops(n)}
}
// 指令:PEEK 引用栈内任意条目
// 实参:目标条目下标,支持负数从栈顶倒算。
// 返回:any
func _PEEK(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
i := vs[0].(Int) // 错误即失败
return []any{a.StackItem(int(i))}
}
// 指令:PEEKS(1) 引用栈内任意位置段条目
// 附参:1 byte,引用条目数,uint8
// 实参:起始位置下标,支持负数从栈顶算起。
// 返回:[]any
// 下标位置超出边界或数量超出实际存在都视为异常(失败)。
// 注记:
// 位置实参不计在内。实际上该值已经由上级调用者取出(如果实参区为空)。
func _PEEKS(a *Actuator, aux []any, _ any, vs ...any) []any {
a.Revert()
n := aux[0].(int)
i := vs[0].(Int)
return []any{a.StackItems(int(i), n)}
}
/*
* 集合指令
* 集合包含两种类型:切片 和 字典。
* 这里只提供集合的一些基础性操作,更多的功能在其各自所属的模块内。
******************************************************************************
* 注记:
* 这里仅支持会由脚本指令产生的切片类型:
* - Bytes 由值指令直接创建。
* - Runes 逻辑上必要,也由本指令和转换指令RUNES创建。
* - []any 由数据栈部分操作指令(POPS、TOPS、PEEKS)等创建。
* - []Int 由 RANGE 指令创建。
* - []Float 由 RANGE 指令创建。
* - []String 由正则匹配指令 MATCH 创建。
* 其它值类型的切片不会产生,因此不作支持。
*/
// 指令: SLICE 局部切片
// 实参1:目标切片。
// 实参2:起始下标,支持负数从末尾算起。
// 实参3:结束下标(不含),同上支持负数。nil值表示末尾之后。
// 返回: 一个新切片。
func _SLICE(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
i := int(vs[1].(Int))
switch x := vs[0].(type) {
case Bytes:
return []any{slice(x, i, vs[2])}
case Runes:
return []any{slice(x, i, vs[2])}
case []any:
return []any{slice(x, i, vs[2])}
case []Int:
return []any{slice(x, i, vs[2])}
case []Float:
return []any{slice(x, i, vs[2])}
case []String:
return []any{slice(x, i, vs[2])}
}
panic(neverToHere)
}
// 指令:REVERSE 序列反转
// 实参:目标切片。
// 返回:一个新的反转后的切片。
// 提示:
// 如果需要反转字符串,应当先将字符串转为 Runes 后反转,
// 然后再转回字符串。
func _REVERSE(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
switch x := vs[0].(type) {
case Bytes:
return []any{reverse(x)}
case Runes:
return []any{reverse(x)}
case []any:
return []any{reverse(x)}
case []Int:
return []any{reverse(x)}
case []Float:
return []any{reverse(x)}
case []String:
return []any{reverse(x)}
}
panic(neverToHere)
}
// 指令:MERGE 分片合并
// 实参:1+不定数量子切片,首个实参必须存在。
// 返回:一个新的合并后的切片。
// 注意:各切片的成员类型应当相同。
func _MERGE(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
switch vs[0].(type) {
case Bytes:
return []any{merge[byte](vs)}
case Runes:
return []any{merge[rune](vs)}
case []any:
return []any{merge[any](vs)}
case []Int:
return []any{merge[Int](vs)}
case []Float:
return []any{merge[Float](vs)}
case []String:
return []any{merge[String](vs)}
}
panic(neverToHere)
}
// 指令:EXPAND 集合扩充
// 实参:1+不定数量的成员值,首个实参为目标切片。
// 返回:一个新的扩充后的切片。
func _EXPAND(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
switch buf := vs[0].(type) {
case Bytes:
return []any{expand(buf, vs[1:])}
case Runes:
return []any{expand(buf, vs[1:])}
case []any:
return []any{expand(buf, vs[1:])}
case []Int:
return []any{expand(buf, vs[1:])}
case []Float:
return []any{expand(buf, vs[1:])}
case []String:
return []any{expand(buf, vs[1:])}
}
panic(neverToHere)
}
// 指令:GLUE 成员粘合
// 切片成员间无缝连接。仅支持 Bytes, Runes, []any, []String 类型。
// 其中 []any 成员支持 byte、rune、Bytes、String。
// 实参:一个切片。
// 返回:一个新的字节序列。
// 注意:
// 不支持 []Int, []Float 切片类型,它们的粘合缺乏直接意义。
// 若确实需要,可以先将它们转为字节序列或字符串,然后再粘合。
func _GLUE(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
var buf bytes.Buffer
switch x := vs[0].(type) {
case Bytes:
return []any{newCopy(x, 0)}
case Runes:
for _, v := range x {
buf.WriteRune(v)
}
case []any:
glueAny(&buf, x)
case []String:
for _, v := range x {
buf.WriteString(v)
}
default:
panic(neverToHere)
}
return []any{buf.Bytes()}
}
// 指令:SPREAD 序列展开
// 实参:一个切片。需明确的切片类型。
// 返回:Any切片自动展开。
func _SPREAD(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
switch x := vs[0].(type) {
case Runes:
return cbase.ToAnys(x)
case Bytes:
return cbase.ToAnys(x)
case []any:
return x
case []Int:
return cbase.ToAnys(x)
case []Float:
return cbase.ToAnys(x)
case []String:
return cbase.ToAnys(x)
}
panic(neverToHere)
}
// 指令:ITEM 成员条目获取
// 实参1:目标集。切片或字典。
// 实参2:下标或键名(Int|String)或其集合。
// 返回:一个值或一个切片。
// 注意:
// 从字典中取值时,条目不存在会取到一个默认零值。
// 切片下标支持负数从末尾算起。
func _ITEM(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
switch k := vs[1].(type) {
case Int:
return []any{sliceItemX(vs[0], int(k))}
case []Int:
return []any{sliceItemsX(vs[0], k)}
case String:
return []any{vs[0].(Dict)[k]}
case []String:
return []any{dictItems(vs[0].(Dict), k)}
}
panic(neverToHere)
}
// 指令:SET 设置集合成员
// 实参1:目标字典。
// 实参2:键名或键名集。
// 实参3:成员数据值或值集。
// 返回:原目标引用。
// 注:
// 如果键为一个集合,值集成员需要与之一一对应。
func _SET(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
d := vs[0].(Dict)
switch kx := vs[1].(type) {
case String:
d[kx] = vs[2]
case []String:
for i, k := range kx {
d[k] = sliceItemX(vs[2], i)
}
default:
panic(neverToHere)
}
return []any{vs[0]}
}
// 指令:SIZE 获取成员大小
// 实参:目标集。切片或字典。
// 返回:Int
func _SIZE(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
switch x := vs[0].(type) {
case Bytes:
return []any{Int(len(x))}
case Runes:
return []any{Int(len(x))}
case []any:
return []any{Int(len(x))}
case []Int:
return []any{Int(len(x))}
case []Float:
return []any{Int(len(x))}
case []String:
return []any{Int(len(x))}
case Dict:
return []any{Int(len(x))}
}
panic(neverToHere)
}
// 指令:MAP{}(1) 迭代映射。
// 附参:1 byte,子语句块长度。
// 实参:1+不定数量。首个实参为目标集(切片或字典),后续为私有数据栈初始成员。
// 针对目标集,迭代每一个成员执行子语句块。
// 返回:
// 一个切片。由每次迭代中的返回值构成,但 nil 会被忽略。
// 环境:
// 子语句块被构造为一个私有环境,数据栈和实参区独立出来。
// 各个迭代之间共享这个私有环境。
func _MAP(a *Actuator, _ []any, data any, vs ...any) []any {
a.Revert()
code := data.([]byte)
a2 := a.ScopeNew(code)
// 数据栈初始条目
a2.StackPush(vs[1:]...)
switch x := vs[0].(type) {
case Bytes:
return []any{mapSlice(a2, x, code)}
case Runes:
return []any{mapSlice(a2, x, code)}
case []any:
return []any{mapSlice(a2, x, code)}
case []Int:
return []any{mapSlice(a2, x, code)}
case []Float:
return []any{mapSlice(a2, x, code)}
case []String:
return []any{mapSlice(a2, x, code)}
case Dict:
return []any{mapDict(a2, x, code)}
}
panic(neverToHere)
}
// 指令:FILTER{}(1) 集合过滤。
// 附参:1 byte,子语句块长度。
// 实参:1+不定数量。首个实参为目标集(切片或字典),后续为私有数据栈初始成员。
// 针对目标集,迭代每一个成员执行子语句块。
// 子语句块中返回 true 的当前条目留下,返回 false 的条目被移除。
// 返回:
// 一个切片或字典,与原数据相同类型。
// 环境:
// 与上面 MAP 指令相同说明。
func _FILTER(a *Actuator, _ []any, data any, vs ...any) []any {
a.Revert()
code := data.([]byte)
a2 := a.ScopeNew(code)
// 数据栈初始条目
a2.StackPush(vs[1:]...)
switch x := vs[0].(type) {
case Bytes:
return []any{filterSlice(a2, x, code)}
case Runes:
return []any{filterSlice(a2, x, code)}
case []any:
return []any{filterSlice(a2, x, code)}
case []Int:
return []any{filterSlice(a2, x, code)}
case []Float:
return []any{filterSlice(a2, x, code)}
case []String:
return []any{filterSlice(a2, x, code)}
case Dict:
return []any{filterDict(a2, x, code)}
}
panic(neverToHere)
}
/*
* 交互指令
******************************************************************************
*/
// 指令:INPUT(1) 导入缓存区的数据
// 附参:1 byte,读取的条目数,0值表示全部。
// 实参:无。
// 返回:提取的数据,上级自动展开。
// 说明:
// 如果脚本中包含导入缓存数据逻辑,用户就必须预先灌入数据,
// 否则缓存区无数据或数据不足,将视为失败。
func _INPUT(a *Actuator, aux []any, _ any, _ ...any) []any {
a.Revert()
if a.InputNil() {
panic(inputEmpty)
}
return a.BufinPick(aux[0].(int))
}
// 指令:OUTPUT 导出数据到缓存区
// 实参:不定数量。
// 返回:无。
// 注记:
// 依然为串行逻辑,因为简单地向内存写数据不会阻塞。
func _OUTPUT(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
if len(vs) > 0 {
a.BufoutPush(vs...)
}
return nil
}
// 指令:BUFDUMP 导出区数据转出
// 附参:1 byte,序位标识。可随机,但在同一脚本内应唯一。
// 返回:无。
// 转出全部数据(清空),同时传递脚本id、序位标识和脚本副本。
func _BUFDUMP(a *Actuator, aux []any, _ any, _ ...any) []any {
a.Revert()
n := aux[0].(int)
if !a.OutputNil() {
// 即时取出&构造
x := ibase.Middler{
ID: a.ID,
N: n,
Code: newCopy(a.Source(), 0),
Data: a.BufoutTake(),
}
go func() { a.Ch <- x }()
}
return nil
}
// 指令:PRINT 打印消息
// 实参:不定数量。
// 返回:无。
// 实际上就是调用 fmt.Println(),格式默认。
func _PRINT(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
if len(vs) > 0 {
fmt.Println(vs...)
}
return nil
}
/*
* 结果指令
******************************************************************************
*/
// 指令:PASS 通关检查通过
// 实参:布尔值,真值通过,假值失败。
// 返回:无。
func _PASS(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
if !vs[0].(Bool) {
panic(NotPass)
}
return nil
}
// 指令:FAIL 通关检查失败
// 实参:布尔值,真值失败,假值通过。
// 返回:无。
func _FAIL(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
if vs[0].(Bool) {
panic(NotPass)
}
return nil
}
// 指令:GOTO(4,4,2) 执行流跳转
// 附参1:区块高度。
// 附参2:交易序位。
// 附参3:脚本偏移。
// 实参:不定数量,作为目标脚本数据栈初始内容。
// 返回:无。
func _GOTO(a *Actuator, aux []any, _ any, vs ...any) []any {
a.Revert()
a.IncrGoto()
h := aux[0].(int)
n := aux[1].(int)
i := aux[2].(int)
code := xpool.Get(h, n, i)
a2 := a.ScriptNew(cbase.KeyID(h, n, i), code)
if len(vs) > 0 {
// 新数据栈初始内容
a2.StackPush(vs...)
}
a2.GotoIn()
runEmbed(a2)
return nil
}
// 指令:JUMP(4,4,2) 跳转脚本嵌入
// 附参1:区块高度。
// 附参2:交易序位。
// 附参3:脚本偏移。
// 实参:无。
// 返回:无。
func _JUMP(a *Actuator, aux []any, _ any, vs ...any) []any {
a.Revert()
a.IncrJump()
h := aux[0].(int)
n := aux[1].(int)
i := aux[2].(int)
code := xpool.Get(h, n, i)
a2 := a.EmbedNew(cbase.KeyID(h, n, i), code)
a2.JumpIn()
runEmbed(a2)
return nil
}
// 指令:EXIT 结束脚本
// 实参:不定数量。
// 返回:即实参,多个实参会打包为一个切片。
func _EXIT(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
if len(vs) == 1 {
panic(Leave{EXIT, vs[0]})
}
if len(vs) > 1 {
panic(Leave{EXIT, vs})
}
return nil
}
// 指令:RETURN 返回一个值
// 实参:任意类型,单值。
// 返回:即实参值。
// 仅用于函数类指令块内(MAP 和 FILTER)。
func _RETURN(a *Actuator, _ []any, _ any, vs ...any) []any {
a.Revert()
panic(Leave{RETURN, vs[0]})
}
/*
* 流程指令
******************************************************************************
*/
// 指令:IF{}(1) 真值执行块
// 附参:1 byte,子语句块长度,uint8
// 实参:布尔值,执行判断依据
// 返回:无。
func _IF(a *Actuator, _ []any, code any, vs ...any) []any {
a.Revert()
*a.Ifs = vs[0].(Bool)
if *a.Ifs {
codeRun(a.BlockNew(code.([]byte)))
}
return nil
}
// 指令:ELSE{}(1) IF不满足时执行
// 附参:1 byte,子块长度。
// 实参:无。
// 返回:无。