-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathfunction.mdtlbl
More file actions
161 lines (150 loc) · 4.25 KB
/
function.mdtlbl
File metadata and controls
161 lines (150 loc) · 4.25 KB
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
#**
* 虽然直接展开代码可以无性能损耗, 但是如果行数过多,
* 我们就需要考虑原生逻辑中常用的封装方法: 函数 了
* 函数虽然相对来说限制很多, 只能传普通值, 速度慢等
* 但是节省代码行数很有效
*
* 如果要使用可以直接将这部分复制粘贴到你的代码中, 非常方便
*#
Builtin.BindSep! '.';
Builtin.MissesMatch! 1;
const Function = (const match @ => *@ F {
take B = $;
take DeclStat = null;
take I=0;
inline 0@ {
take*I=I+1;
match @ {
[@declare] @ { take DeclStat = @declare; }
[@define] B @ { take*I=I+1; take DeclStat = @define; }
@ { take*I=I- 1; Builtin.StopRepeat!; }
}
}
Builtin.SliceArgs! I *Builtin.ArgsLen[];
match DeclStat { [null @declare] {} [@define] {
B.define_line = @counter + 1;
} }
match DeclStat { [@declare] {} [null @define] {
goto :end;
} }
{
const B.Return = (const match @ {
{
@counter = ...ret_counter;
}
F {
F! ..->ret_counter;
}
});
const B.DefaultReturn = B->Return;
const B.Body = F;
const B.Expander = (
...Body! @;
...DefaultReturn!;
);
const B.RawCall = (match @ {
{
...Goto!;
setres ...result;
}
});
inline@ Arg {
take Handle = Builtin.BindHandle2[`B` Arg];
const B.Expander = ([Handle &E:B->Expander](
setres E[Handle @];
));
const B.RawCall = ([Handle &C:B->RawCall](match @ {
@ Fst {
match Fst { [Handle] {} _ { Handle = Fst; } }
setres C[@];
}
}));
}
take*B.ArgC = Builtin.ArgsLen[];
const B.RawCall = ([ArgC:B.ArgC &C:B->RawCall](
match Builtin.ArgsLen[] {
[ArgC] {
setres C[@];
}
N {
Builtin.ExpandStack!;
Builtin.Err! *Builtin.Concat[
"Unexpected argc "
*Builtin.Concat[
*Builtin.Stringify[N]
*Builtin.Concat[
", expected: "
*Builtin.Stringify[ArgC]
]
]
];
inline@ Arg {
Builtin.Err! Arg;
}
Builtin.Exit! 3;
}
}
));
const B.Call = (match @ => @ {
setres ...RawCall[@];
});
const B.Goto = ([B DeclStat](
setres B.result;
B.ret_counter = @counter + 1;
match DeclStat {
[null] { goto :start; }
[@declare @define] { @counter = B.define_line; }
}
));
match DeclStat { [@declare @define] {} [null] {
:start
const B.Goto = ([| :start]B->Goto);
} }
match DeclStat { [@declare] {} [null @define] {
B.Expander!;
} }
}
:end
});
# 允许将声明定义分开, 可以进行一些灵活的操作,
# 但是依旧需要在调用前运行定义, 不然跳转行号是未知的
const Add = Function[@declare a b ()]->Call;
const Foo = Function[(
...result = Add[1 2];
)]->Call;
Function! @define Add->.. a b (
...result = _0 + _1;
);
print Add[1 2]", "Add[3 4]"\n";
print "foo: "Foo[];
printflush message1;
#* >>>
jump 7 always 0 0
set __6.b 2
set __6.a 1
op add __6.ret_counter @counter 1
set @counter __6.define_line
set __31.result __6.result
set @counter __31.ret_counter
op add __6.define_line @counter 1
jump 11 always 0 0
op add __6.result __6.a __6.b
set @counter __6.ret_counter
set __6.b 2
set __6.a 1
op add __6.ret_counter @counter 1
set @counter __6.define_line
print __6.result
print ", "
set __6.b 4
set __6.a 3
op add __6.ret_counter @counter 1
set @counter __6.define_line
print __6.result
print "\n"
print "foo: "
op add __31.ret_counter @counter 1
jump 1 always 0 0
print __31.result
printflush message1
*#