1
+ use unwrap_none:: UnwrapNone ;
1
2
use crate :: ast:: { Atom , Expression , Function , Lines , Statement } ;
2
3
use crate :: script:: CallError ;
3
4
use crate :: tokenizer:: Op ;
4
- use crate :: { ScriptIter , ScriptType } ;
5
+ use crate :: { ScriptIter , ScriptType , ScriptObject , Variant } ;
5
6
use core:: convert:: TryInto ;
6
7
use core:: fmt:: { self , Debug , Formatter } ;
7
8
use rustc_hash:: FxHashMap ;
@@ -18,14 +19,15 @@ pub(crate) enum Instruction {
18
19
Call ( Box < ( u16 , CallArgs ) > ) ,
19
20
CallSelf ( Box < CallArgs > ) ,
20
21
CallGlobal ( Box < CallArgs > ) ,
21
- //Iter(Box<dyn Iterator<Item = Rc<dyn ScriptType> >>),
22
+ //Iter(Box<dyn Iterator<Item = ScriptObject >>),
22
23
//Jmp(u32),
23
24
//JmpIf(u16, u32),
24
25
RetSome ,
25
26
RetNone ,
26
27
27
28
IterConst ( Box < ( u16 , u32 , Box < dyn ScriptIter > ) > ) ,
28
29
IterJmp ( u16 , u32 ) ,
30
+ IterInt ( u16 , isize ) ,
29
31
30
32
/*
31
33
AndJmp(u16, u16, u32),
@@ -61,7 +63,7 @@ pub(crate) struct ByteCode {
61
63
code : Vec < Instruction > ,
62
64
param_count : u16 ,
63
65
var_count : u16 ,
64
- consts : Vec < Rc < dyn ScriptType > > ,
66
+ consts : Vec < Variant > ,
65
67
}
66
68
67
69
#[ derive( Debug ) ]
@@ -73,14 +75,15 @@ pub enum RunError {
73
75
UndefinedFunction ,
74
76
CallError ( Box < CallError > ) ,
75
77
IncorrectArgumentCount ,
78
+ IncompatibleType ,
76
79
}
77
80
78
81
pub struct Environment {
79
82
functions : FxHashMap < Box < str > , EnvironmentFunction > ,
80
83
}
81
84
82
- pub type EnvironmentFunction = Box < dyn Fn ( & [ Rc < dyn ScriptType > ] ) -> CallResult < RunError > > ;
83
- pub type CallResult < E > = Result < Rc < dyn ScriptType > , E > ;
85
+ pub type EnvironmentFunction = Box < dyn Fn ( & [ Variant ] ) -> CallResult < RunError > > ;
86
+ pub type CallResult < E > = Result < Variant , E > ;
84
87
85
88
#[ derive( Debug ) ]
86
89
pub enum EnvironmentError {
@@ -141,7 +144,7 @@ impl ByteCode {
141
144
conv ( a) ;
142
145
conv ( b) ;
143
146
}
144
- IterConst ( _) | IterJmp ( _, _) | RetSome | RetNone => ( ) ,
147
+ IterConst ( _) | IterInt ( _ , _ ) | IterJmp ( _, _) | RetSome | RetNone => ( ) ,
145
148
}
146
149
}
147
150
}
@@ -160,7 +163,7 @@ impl ByteCode {
160
163
locals : & FxHashMap < Box < str > , u16 > ,
161
164
instr : & mut Vec < Instruction > ,
162
165
vars : & mut FxHashMap < & ' a str , u16 > ,
163
- consts : & mut Vec < Rc < dyn ScriptType > > ,
166
+ consts : & mut Vec < Variant > ,
164
167
curr_var_count : & mut u16 ,
165
168
mut min_var_count : u16 ,
166
169
) -> Result < u16 , ByteCodeError > {
@@ -182,10 +185,10 @@ impl ByteCode {
182
185
args. push ( match a {
183
186
Expression :: Atom ( a) => match a {
184
187
Atom :: String ( a) => {
185
- add_const ( Rc :: new ( a. to_string ( ) . into_boxed_str ( ) ) )
188
+ add_const ( Variant :: Object ( Rc :: new ( a. to_string ( ) . into_boxed_str ( ) ) ) )
186
189
}
187
- Atom :: Integer ( a) => add_const ( Rc :: new ( * a) ) ,
188
- Atom :: Real ( a) => add_const ( Rc :: new ( * a) ) ,
190
+ Atom :: Integer ( a) => add_const ( Variant :: Integer ( * a) ) ,
191
+ Atom :: Real ( a) => add_const ( Variant :: Real ( * a) ) ,
189
192
Atom :: Name ( a) => todo ! ( "call {:?}" , a) ,
190
193
} ,
191
194
Expression :: Function {
@@ -201,11 +204,11 @@ impl ByteCode {
201
204
match a {
202
205
Expression :: Atom ( a) => {
203
206
args. push ( match a {
204
- Atom :: String ( a) => add_const ( Rc :: new (
207
+ Atom :: String ( a) => add_const ( Variant :: Object ( Rc :: new (
205
208
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) ) ,
209
+ ) ) ) ,
210
+ Atom :: Integer ( a) => add_const ( Variant :: Integer ( * a) ) ,
211
+ Atom :: Real ( a) => add_const ( Variant :: Real ( * a) ) ,
209
212
Atom :: Name ( a) => todo ! ( "call {:?}" , a) ,
210
213
} ) ;
211
214
}
@@ -250,9 +253,7 @@ impl ByteCode {
250
253
u32:: MAX ,
251
254
Box :: new ( a. to_string ( ) . into_boxed_str ( ) ) ,
252
255
) ) ) ,
253
- Atom :: Integer ( a) => {
254
- Instruction :: IterConst ( Box :: new ( ( reg, u32:: MAX , Box :: new ( * a) ) ) )
255
- }
256
+ Atom :: Integer ( a) => Instruction :: IterInt ( reg, * a) ,
256
257
//Atom::Real(a) => Instruction::IterConst(Box::new(a)),
257
258
Atom :: Real ( a) => todo ! ( "for Real({})" , a) ,
258
259
Atom :: Name ( a) => todo ! ( "for {:?}" , a) ,
@@ -274,10 +275,10 @@ impl ByteCode {
274
275
) ?;
275
276
instr. push ( Instruction :: IterJmp ( reg, ip) ) ;
276
277
let ip = instr. len ( ) as u32 ;
277
- if let Some ( Instruction :: IterConst ( ic ) ) = instr. get_mut ( ic) {
278
- ic . 1 = ip;
279
- } else {
280
- unreachable ! ( ) ;
278
+ match instr. get_mut ( ic) {
279
+ Some ( Instruction :: IterConst ( ic ) ) => ic . 1 = ip,
280
+ Some ( Instruction :: IterInt ( .. ) ) => ( ) ,
281
+ _ => unreachable ! ( ) ,
281
282
}
282
283
}
283
284
Statement :: Return { expr } => {
@@ -429,8 +430,8 @@ impl ByteCode {
429
430
pub ( crate ) fn run (
430
431
& self ,
431
432
functions : & FxHashMap < Box < str > , Self > ,
432
- locals : & mut [ Rc < dyn ScriptType > ] ,
433
- args : & [ Rc < dyn ScriptType > ] ,
433
+ locals : & mut [ Variant ] ,
434
+ args : & [ Variant ] ,
434
435
env : & Environment ,
435
436
) -> CallResult < RunError > {
436
437
if args. len ( ) != self . param_count as usize {
@@ -440,9 +441,7 @@ impl ByteCode {
440
441
for a in args. iter ( ) {
441
442
vars. push ( a. clone ( ) ) ;
442
443
}
443
- vars. resize_with ( self . var_count as usize , || {
444
- Rc :: new ( ( ) ) as Rc < dyn ScriptType >
445
- } ) ;
444
+ vars. resize ( self . var_count as usize , Variant :: default ( ) ) ;
446
445
vars. extend ( self . consts . iter ( ) . cloned ( ) ) ;
447
446
let mut ip = 0 ;
448
447
let mut iterators = Vec :: new ( ) ;
@@ -467,7 +466,7 @@ impl ByteCode {
467
466
for & a in args. iter ( ) {
468
467
call_args. push ( vars. get ( a as usize ) . ok_or ( err_roob ( ) ) ?. clone ( ) ) ;
469
468
}
470
- let obj = vars. get ( * reg as usize ) . ok_or ( err_roob ( ) ) ?. as_ref ( ) ;
469
+ let obj = vars. get ( * reg as usize ) . ok_or ( err_roob ( ) ) ?;
471
470
let r = obj. call ( func, & call_args[ ..] ) . map_err ( err_call) ?;
472
471
call_args. clear ( ) ;
473
472
if let Some ( reg) = store_in {
@@ -505,7 +504,7 @@ impl ByteCode {
505
504
}
506
505
}
507
506
RetSome => break Ok ( vars. first ( ) . ok_or ( err_roob ( ) ) ?. clone ( ) ) ,
508
- RetNone => break Ok ( Rc :: new ( ( ) ) ) ,
507
+ RetNone => break Ok ( Variant :: None ) ,
509
508
IterConst ( box ( reg, jmp_ip, iter) ) => {
510
509
let mut iter = iter. iter ( ) ;
511
510
if let Some ( e) = iter. next ( ) {
@@ -515,6 +514,15 @@ impl ByteCode {
515
514
ip = * jmp_ip;
516
515
}
517
516
}
517
+ IterInt ( reg, i) => {
518
+ let mut iter = if * i < 0 {
519
+ Box :: new ( ( ( 1 - i) ..=0 ) . rev ( ) . map ( Variant :: Integer ) ) as Box < dyn Iterator < Item = Variant > >
520
+ } else {
521
+ Box :: new ( ( 0 ..* i) . map ( Variant :: Integer ) ) as Box < dyn Iterator < Item = Variant > >
522
+ } ;
523
+ * vars. get_mut ( * reg as usize ) . ok_or ( err_roob ( ) ) ? = iter. next ( ) . unwrap ( ) ;
524
+ iterators. push ( iter) ;
525
+ }
518
526
IterJmp ( reg, jmp_ip) => {
519
527
if let Some ( iter) = iterators. last_mut ( ) {
520
528
if let Some ( e) = iter. next ( ) {
@@ -528,13 +536,45 @@ impl ByteCode {
528
536
Mul ( r, a, b) => {
529
537
let a = vars. get ( * a as usize ) . ok_or ( err_roob ( ) ) ?;
530
538
let b = vars. get ( * b as usize ) . ok_or ( err_roob ( ) ) ?;
531
- let e = a. mul ( b) . map_err ( err_call) ?;
539
+ let err = || Err ( RunError :: IncompatibleType ) ;
540
+ let e = match a {
541
+ Variant :: None => return err ( ) ,
542
+ Variant :: Real ( a) => match b {
543
+ Variant :: None => return err ( ) ,
544
+ Variant :: Real ( b) => Variant :: Real ( a * b) ,
545
+ & Variant :: Integer ( b) => Variant :: Real ( a * b as f64 ) ,
546
+ Variant :: Object ( _) => return err ( ) ,
547
+ }
548
+ & Variant :: Integer ( a) => match b {
549
+ Variant :: None => return err ( ) ,
550
+ Variant :: Real ( b) => Variant :: Real ( a as f64 * b) ,
551
+ Variant :: Integer ( b) => Variant :: Integer ( a * b) ,
552
+ Variant :: Object ( _) => return err ( ) ,
553
+ }
554
+ Variant :: Object ( _) => return err ( ) ,
555
+ } ;
532
556
* vars. get_mut ( * r as usize ) . ok_or ( err_roob ( ) ) ? = e;
533
557
}
534
558
Add ( r, a, b) => {
535
559
let a = vars. get ( * a as usize ) . ok_or ( err_roob ( ) ) ?;
536
560
let b = vars. get ( * b as usize ) . ok_or ( err_roob ( ) ) ?;
537
- let e = a. add ( b) . map_err ( err_call) ?;
561
+ let err = || Err ( RunError :: IncompatibleType ) ;
562
+ let e = match a {
563
+ Variant :: None => return err ( ) ,
564
+ Variant :: Real ( a) => match b {
565
+ Variant :: None => return err ( ) ,
566
+ Variant :: Real ( b) => Variant :: Real ( a + b) ,
567
+ & Variant :: Integer ( b) => Variant :: Real ( a + b as f64 ) ,
568
+ Variant :: Object ( _) => return err ( ) ,
569
+ }
570
+ & Variant :: Integer ( a) => match b {
571
+ Variant :: None => return err ( ) ,
572
+ Variant :: Real ( b) => Variant :: Real ( a as f64 + b) ,
573
+ Variant :: Integer ( b) => Variant :: Integer ( a + b) ,
574
+ Variant :: Object ( _) => return err ( ) ,
575
+ }
576
+ Variant :: Object ( _) => return err ( ) ,
577
+ } ;
538
578
* vars. get_mut ( * r as usize ) . ok_or ( err_roob ( ) ) ? = e;
539
579
}
540
580
_ => todo ! ( "{:?}" , instr) ,
@@ -567,7 +607,7 @@ impl Environment {
567
607
}
568
608
}
569
609
570
- pub fn call ( & self , func : & str , args : & [ Rc < dyn ScriptType > ] ) -> CallResult < EnvironmentError > {
610
+ pub fn call ( & self , func : & str , args : & [ Variant ] ) -> CallResult < EnvironmentError > {
571
611
Ok ( self
572
612
. functions
573
613
. get ( func)
@@ -588,6 +628,7 @@ impl Debug for Instruction {
588
628
RetSome => write ! ( f, "ret 0" ) ,
589
629
RetNone => write ! ( f, "ret none" ) ,
590
630
IterConst ( box ( r, p, i) ) => write ! ( f, "iter {}, {}, {:?}" , r, p, i) ,
631
+ IterInt ( r, i) => write ! ( f, "iter {}, {}" , r, i) ,
591
632
IterJmp ( r, p) => write ! ( f, "iterjmp {}, {}" , r, p) ,
592
633
Add ( r, a, b) => write ! ( f, "add {}, {}, {}" , r, a, b) ,
593
634
Mul ( r, a, b) => write ! ( f, "mul {}, {}, {}" , r, a, b) ,
0 commit comments