@@ -3,55 +3,50 @@ use crate::script::CallError;
3
3
use crate :: tokenizer:: Op ;
4
4
use crate :: { ScriptIter , ScriptType } ;
5
5
use core:: convert:: TryInto ;
6
+ use core:: fmt:: { self , Debug , Formatter } ;
6
7
use rustc_hash:: FxHashMap ;
7
8
use std:: collections:: hash_map:: Entry ;
8
9
use std:: rc:: Rc ;
9
10
10
- #[ derive( Debug ) ]
11
11
pub ( crate ) struct CallArgs {
12
12
store_in : Option < u16 > ,
13
13
func : Box < str > ,
14
14
args : Box < [ u16 ] > ,
15
15
}
16
16
17
- #[ derive( Debug ) ]
18
17
pub ( crate ) enum Instruction {
19
18
Call ( Box < ( u16 , CallArgs ) > ) ,
20
19
CallSelf ( Box < CallArgs > ) ,
21
20
CallGlobal ( Box < CallArgs > ) ,
22
21
//Iter(Box<dyn Iterator<Item = Rc<dyn ScriptType>>>),
23
22
//Jmp(u32),
24
23
//JmpIf(u16, u32),
25
-
26
24
RetSome ,
27
25
RetNone ,
28
26
29
27
IterConst ( Box < ( u16 , u32 , Box < dyn ScriptIter > ) > ) ,
30
28
IterJmp ( u16 , u32 ) ,
31
29
32
- /*
30
+ /*
33
31
AndJmp(u16, u16, u32),
34
32
OrJmp(u16, u16, u32),
35
33
Xor(u16, u16, u32),
36
34
Eq,
37
35
Neq,
38
- */
39
-
36
+ */
40
37
Add ( u16 , u16 , u16 ) ,
41
38
//Sub(u16, u16, u16),
42
39
Mul ( u16 , u16 , u16 ) ,
43
40
//Div(u16, u16, u16),
44
41
//Rem(u16, u16, u16),
45
-
46
42
Move ( u16 , u16 ) ,
47
-
48
- /*
43
+ /*
49
44
AddConst,
50
45
SubConst,
51
46
MulConst,
52
47
DivConst,
53
48
RemConst,
54
- */
49
+ */
55
50
}
56
51
57
52
#[ derive( Debug ) ]
@@ -66,7 +61,7 @@ pub(crate) struct ByteCode {
66
61
code : Vec < Instruction > ,
67
62
param_count : u16 ,
68
63
var_count : u16 ,
69
- consts : Vec < Rc < dyn ScriptType > > ,
64
+ consts : Vec < Rc < dyn ScriptType > > ,
70
65
}
71
66
72
67
#[ derive( Debug ) ]
@@ -97,12 +92,12 @@ pub enum EnvironmentError {
97
92
impl ByteCode {
98
93
pub ( crate ) fn parse (
99
94
function : Function ,
100
- methods : & FxHashMap < & str , ( ) > ,
95
+ methods : & FxHashMap < & str , ( ) > ,
101
96
locals : & FxHashMap < Box < str > , u16 > ,
102
97
) -> Result < Self , ByteCodeError > {
103
98
let mut instr = Vec :: new ( ) ;
104
99
let mut vars = FxHashMap :: with_hasher ( Default :: default ( ) ) ;
105
- let mut consts = Vec :: new ( ) ;
100
+ let mut consts = Vec :: new ( ) ;
106
101
let param_count = function. parameters . len ( ) as u16 ;
107
102
for p in function. parameters {
108
103
if vars. insert ( p, vars. len ( ) as u16 ) . is_some ( ) {
@@ -112,11 +107,11 @@ impl ByteCode {
112
107
let mut var_count = vars. len ( ) as u16 ;
113
108
let vars = Self :: parse_block (
114
109
& function. lines ,
115
- methods,
110
+ methods,
116
111
locals,
117
112
& mut instr,
118
113
& mut vars,
119
- & mut consts,
114
+ & mut consts,
120
115
& mut var_count,
121
116
0 ,
122
117
) ?;
@@ -125,43 +120,47 @@ impl ByteCode {
125
120
_ => instr. push ( Instruction :: RetNone ) ,
126
121
}
127
122
128
- if consts. len ( ) > 0 {
129
- // All consts are using the upper-most registers, move them downwards
130
- let offset = ( u16:: MAX - consts. len ( ) as u16 ) . wrapping_add ( 1 ) ;
131
- for i in instr. iter_mut ( ) {
132
- use Instruction :: * ;
133
- let conv = |c : & mut u16 | if * c >= offset { * c = u16:: MAX - * c + vars } ;
134
- match i {
135
- Call ( box ( _, ca) ) | CallSelf ( box ca) | CallGlobal ( box ca) => {
136
- for a in ca. args . iter_mut ( ) {
137
- conv ( a) ;
138
- }
139
- }
140
- Move ( _, a) => conv ( a) ,
141
- Add ( _, a, b) | Mul ( _, a, b) => {
142
- conv ( a) ;
143
- conv ( b) ;
144
- }
145
- IterConst ( _) | IterJmp ( _, _) | RetSome | RetNone => ( ) ,
146
- }
147
- }
148
- }
123
+ if consts. len ( ) > 0 {
124
+ // All consts are using the upper-most registers, move them downwards
125
+ let offset = ( u16:: MAX - consts. len ( ) as u16 ) . wrapping_add ( 1 ) ;
126
+ for i in instr. iter_mut ( ) {
127
+ use Instruction :: * ;
128
+ let conv = |c : & mut u16 | {
129
+ if * c >= offset {
130
+ * c = u16:: MAX - * c + vars
131
+ }
132
+ } ;
133
+ match i {
134
+ Call ( box ( _, ca) ) | CallSelf ( box ca) | CallGlobal ( box ca) => {
135
+ for a in ca. args . iter_mut ( ) {
136
+ conv ( a) ;
137
+ }
138
+ }
139
+ Move ( _, a) => conv ( a) ,
140
+ Add ( _, a, b) | Mul ( _, a, b) => {
141
+ conv ( a) ;
142
+ conv ( b) ;
143
+ }
144
+ IterConst ( _) | IterJmp ( _, _) | RetSome | RetNone => ( ) ,
145
+ }
146
+ }
147
+ }
149
148
150
149
Ok ( Self {
151
150
code : instr,
152
151
var_count : vars,
153
152
param_count,
154
- consts,
153
+ consts,
155
154
} )
156
155
}
157
156
158
157
fn parse_block < ' a > (
159
158
lines : & Lines < ' a > ,
160
- methods : & FxHashMap < & str , ( ) > ,
159
+ methods : & FxHashMap < & str , ( ) > ,
161
160
locals : & FxHashMap < Box < str > , u16 > ,
162
161
instr : & mut Vec < Instruction > ,
163
162
vars : & mut FxHashMap < & ' a str , u16 > ,
164
- consts : & mut Vec < Rc < dyn ScriptType > > ,
163
+ consts : & mut Vec < Rc < dyn ScriptType > > ,
165
164
curr_var_count : & mut u16 ,
166
165
mut min_var_count : u16 ,
167
166
) -> Result < u16 , ByteCodeError > {
@@ -176,13 +175,15 @@ impl ByteCode {
176
175
let mut args = Vec :: with_capacity ( arguments. len ( ) ) ;
177
176
// TODO move this to `parse_expression`
178
177
for a in arguments {
179
- let mut add_const = |v| {
180
- consts. push ( v) ;
181
- u16:: MAX - consts. len ( ) as u16 + 1
182
- } ;
178
+ let mut add_const = |v| {
179
+ consts. push ( v) ;
180
+ u16:: MAX - consts. len ( ) as u16 + 1
181
+ } ;
183
182
args. push ( match a {
184
183
Expression :: Atom ( a) => match a {
185
- Atom :: String ( a) => add_const ( Rc :: new ( a. to_string ( ) . into_boxed_str ( ) ) ) ,
184
+ Atom :: String ( a) => {
185
+ add_const ( Rc :: new ( a. to_string ( ) . into_boxed_str ( ) ) )
186
+ }
186
187
Atom :: Integer ( a) => add_const ( Rc :: new ( * a) ) ,
187
188
Atom :: Real ( a) => add_const ( Rc :: new ( * a) ) ,
188
189
Atom :: Name ( a) => todo ! ( "call {:?}" , a) ,
@@ -200,9 +201,11 @@ impl ByteCode {
200
201
match a {
201
202
Expression :: Atom ( a) => {
202
203
args. push ( match a {
203
- Atom :: String ( a) => add_const ( Rc :: new ( a. to_string ( ) . into_boxed_str ( ) ) ) ,
204
- Atom :: Integer ( a) => add_const ( Rc :: new ( * a) ) ,
205
- Atom :: Real ( a) => add_const ( Rc :: new ( * a) ) ,
204
+ Atom :: String ( a) => add_const ( Rc :: new (
205
+ a. to_string ( ) . into_boxed_str ( ) ,
206
+ ) ) ,
207
+ Atom :: Integer ( a) => add_const ( Rc :: new ( * a) ) ,
208
+ Atom :: Real ( a) => add_const ( Rc :: new ( * a) ) ,
206
209
Atom :: Name ( a) => todo ! ( "call {:?}" , a) ,
207
210
} ) ;
208
211
}
@@ -229,11 +232,11 @@ impl ByteCode {
229
232
func : ( * func) . into ( ) ,
230
233
args : args. into_boxed_slice ( ) ,
231
234
} ) ;
232
- instr. push ( if methods. contains_key ( func) {
233
- Instruction :: CallSelf ( args)
234
- } else {
235
- Instruction :: CallGlobal ( args)
236
- } ) ;
235
+ instr. push ( if methods. contains_key ( func) {
236
+ Instruction :: CallSelf ( args)
237
+ } else {
238
+ Instruction :: CallGlobal ( args)
239
+ } ) ;
237
240
}
238
241
Statement :: For { var, expr, lines } => {
239
242
let reg = vars. len ( ) . try_into ( ) . expect ( "Too many variables" ) ;
@@ -261,11 +264,11 @@ impl ByteCode {
261
264
let ip = instr. len ( ) as u32 ;
262
265
min_var_count = Self :: parse_block (
263
266
lines,
264
- methods,
267
+ methods,
265
268
locals,
266
269
instr,
267
270
vars,
268
- consts,
271
+ consts,
269
272
curr_var_count,
270
273
min_var_count,
271
274
) ?;
@@ -440,10 +443,10 @@ impl ByteCode {
440
443
vars. resize_with ( self . var_count as usize , || {
441
444
Rc :: new ( ( ) ) as Rc < dyn ScriptType >
442
445
} ) ;
443
- vars. extend ( self . consts . iter ( ) . cloned ( ) ) ;
446
+ vars. extend ( self . consts . iter ( ) . cloned ( ) ) ;
444
447
let mut ip = 0 ;
445
448
let mut iterators = Vec :: new ( ) ;
446
- let mut call_args = Vec :: new ( ) ;
449
+ let mut call_args = Vec :: new ( ) ;
447
450
loop {
448
451
let err_roob = || RunError :: RegisterOutOfBounds ;
449
452
let err_uf = || RunError :: UndefinedFunction ;
@@ -461,12 +464,12 @@ impl ByteCode {
461
464
args,
462
465
} ,
463
466
) ) => {
464
- for & a in args. iter ( ) {
465
- call_args. push ( vars. get ( a as usize ) . ok_or ( err_roob ( ) ) ?. clone ( ) ) ;
466
- }
467
- let obj = vars. get ( * reg as usize ) . ok_or ( err_roob ( ) ) ?. as_ref ( ) ;
468
- let r = obj. call ( func, & call_args[ ..] ) . map_err ( err_call) ?;
469
- call_args. clear ( ) ;
467
+ for & a in args. iter ( ) {
468
+ call_args. push ( vars. get ( a as usize ) . ok_or ( err_roob ( ) ) ?. clone ( ) ) ;
469
+ }
470
+ let obj = vars. get ( * reg as usize ) . ok_or ( err_roob ( ) ) ?. as_ref ( ) ;
471
+ let r = obj. call ( func, & call_args[ ..] ) . map_err ( err_call) ?;
472
+ call_args. clear ( ) ;
470
473
if let Some ( reg) = store_in {
471
474
* vars. get_mut ( * reg as usize ) . ok_or ( err_roob ( ) ) ? = r;
472
475
}
@@ -476,11 +479,11 @@ impl ByteCode {
476
479
func,
477
480
args,
478
481
} ) => {
479
- for & a in args. iter ( ) {
480
- call_args. push ( vars. get ( a as usize ) . ok_or ( err_roob ( ) ) ?. clone ( ) ) ;
481
- }
482
- let r = env. call ( func, & call_args[ ..] ) . map_err ( err_env) ?;
483
- call_args. clear ( ) ;
482
+ for & a in args. iter ( ) {
483
+ call_args. push ( vars. get ( a as usize ) . ok_or ( err_roob ( ) ) ?. clone ( ) ) ;
484
+ }
485
+ let r = env. call ( func, & call_args[ ..] ) . map_err ( err_env) ?;
486
+ call_args. clear ( ) ;
484
487
if let Some ( reg) = store_in {
485
488
* vars. get_mut ( * reg as usize ) . ok_or ( err_roob ( ) ) ? = r;
486
489
}
@@ -490,18 +493,20 @@ impl ByteCode {
490
493
func,
491
494
args,
492
495
} ) => {
493
- for & a in args. iter ( ) {
494
- call_args. push ( vars. get ( a as usize ) . ok_or ( err_roob ( ) ) ?. clone ( ) ) ;
495
- }
496
- let r = functions. get ( func) . ok_or ( RunError :: UndefinedFunction ) ?;
497
- let r = r. run ( functions, locals, & call_args[ ..] , env) ?;
498
- call_args. clear ( ) ;
499
- // SAFETY: ditto
496
+ for & a in args. iter ( ) {
497
+ call_args. push ( vars. get ( a as usize ) . ok_or ( err_roob ( ) ) ?. clone ( ) ) ;
498
+ }
499
+ let r = functions. get ( func) . ok_or ( RunError :: UndefinedFunction ) ?;
500
+ let r = r. run ( functions, locals, & call_args[ ..] , env) ?;
501
+ call_args. clear ( ) ;
502
+ // SAFETY: ditto
500
503
if let Some ( reg) = store_in {
501
504
* vars. get_mut ( * reg as usize ) . ok_or ( err_roob ( ) ) ? = r;
502
505
}
503
506
}
504
- RetSome => break Ok ( vars. first ( ) . ok_or ( RunError :: RegisterOutOfBounds ) ?. clone ( ) ) ,
507
+ RetSome => {
508
+ break Ok ( vars. first ( ) . ok_or ( RunError :: RegisterOutOfBounds ) ?. clone ( ) )
509
+ }
505
510
RetNone => break Ok ( Rc :: new ( ( ) ) ) ,
506
511
IterConst ( box ( reg, jmp_ip, iter) ) => {
507
512
let mut iter = iter. iter ( ) ;
@@ -542,11 +547,11 @@ impl ByteCode {
542
547
. get_mut ( * r as usize )
543
548
. ok_or ( RunError :: RegisterOutOfBounds ) ? = e;
544
549
}
545
- /*
550
+ /*
546
551
DupConst(r, c) => {
547
552
*vars.get_mut(*r as usize).ok_or(err_roob())? = c.clone();
548
553
}
549
- */
554
+ */
550
555
_ => todo ! ( "{:?}" , instr) ,
551
556
}
552
557
} else {
@@ -585,3 +590,32 @@ impl Environment {
585
590
. unwrap ( ) )
586
591
}
587
592
}
593
+
594
+ /// This returns each instruction on oneline instead of 5+ with the default Debug
595
+ impl Debug for Instruction {
596
+ fn fmt ( & self , f : & mut Formatter ) -> fmt:: Result {
597
+ use Instruction :: * ;
598
+ match self {
599
+ Call ( box ( r, a) ) => write ! ( f, "call {}, {:?}" , r, a) ,
600
+ CallSelf ( a) => write ! ( f, "call self, {:?}" , a) ,
601
+ CallGlobal ( a) => write ! ( f, "call env, {:?}" , a) ,
602
+ Move ( a, b) => write ! ( f, "move {:?}, {:?}" , a, b) ,
603
+ RetSome => write ! ( f, "ret 0" ) ,
604
+ RetNone => write ! ( f, "ret none" ) ,
605
+ IterConst ( box ( r, p, i) ) => write ! ( f, "iter {}, {}, {:?}" , r, p, i) ,
606
+ IterJmp ( r, p) => write ! ( f, "iterjmp {}, {}" , r, p) ,
607
+ Add ( r, a, b) => write ! ( f, "add {}, {}, {}" , r, a, b) ,
608
+ Mul ( r, a, b) => write ! ( f, "mul {}, {}, {}" , r, a, b) ,
609
+ }
610
+ }
611
+ }
612
+
613
+ impl Debug for CallArgs {
614
+ fn fmt ( & self , f : & mut Formatter ) -> fmt:: Result {
615
+ if let Some ( n) = self . store_in {
616
+ write ! ( f, "{}, \" {}\" , {:?}" , n, self . func, self . args)
617
+ } else {
618
+ write ! ( f, "none, \" {}\" , {:?}" , self . func, self . args)
619
+ }
620
+ }
621
+ }
0 commit comments