1+ use unwrap_none:: UnwrapNone ;
12use crate :: ast:: { Atom , Expression , Function , Lines , Statement } ;
23use crate :: script:: CallError ;
34use crate :: tokenizer:: Op ;
4- use crate :: { ScriptIter , ScriptType } ;
5+ use crate :: { ScriptIter , ScriptType , ScriptObject , Variant } ;
56use core:: convert:: TryInto ;
67use core:: fmt:: { self , Debug , Formatter } ;
78use rustc_hash:: FxHashMap ;
@@ -18,14 +19,15 @@ pub(crate) enum Instruction {
1819 Call ( Box < ( u16 , CallArgs ) > ) ,
1920 CallSelf ( Box < CallArgs > ) ,
2021 CallGlobal ( Box < CallArgs > ) ,
21- //Iter(Box<dyn Iterator<Item = Rc<dyn ScriptType> >>),
22+ //Iter(Box<dyn Iterator<Item = ScriptObject >>),
2223 //Jmp(u32),
2324 //JmpIf(u16, u32),
2425 RetSome ,
2526 RetNone ,
2627
2728 IterConst ( Box < ( u16 , u32 , Box < dyn ScriptIter > ) > ) ,
2829 IterJmp ( u16 , u32 ) ,
30+ IterInt ( u16 , isize ) ,
2931
3032 /*
3133 AndJmp(u16, u16, u32),
@@ -61,7 +63,7 @@ pub(crate) struct ByteCode {
6163 code : Vec < Instruction > ,
6264 param_count : u16 ,
6365 var_count : u16 ,
64- consts : Vec < Rc < dyn ScriptType > > ,
66+ consts : Vec < Variant > ,
6567}
6668
6769#[ derive( Debug ) ]
@@ -73,14 +75,15 @@ pub enum RunError {
7375 UndefinedFunction ,
7476 CallError ( Box < CallError > ) ,
7577 IncorrectArgumentCount ,
78+ IncompatibleType ,
7679}
7780
7881pub struct Environment {
7982 functions : FxHashMap < Box < str > , EnvironmentFunction > ,
8083}
8184
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 > ;
8487
8588#[ derive( Debug ) ]
8689pub enum EnvironmentError {
@@ -141,7 +144,7 @@ impl ByteCode {
141144 conv ( a) ;
142145 conv ( b) ;
143146 }
144- IterConst ( _) | IterJmp ( _, _) | RetSome | RetNone => ( ) ,
147+ IterConst ( _) | IterInt ( _ , _ ) | IterJmp ( _, _) | RetSome | RetNone => ( ) ,
145148 }
146149 }
147150 }
@@ -160,7 +163,7 @@ impl ByteCode {
160163 locals : & FxHashMap < Box < str > , u16 > ,
161164 instr : & mut Vec < Instruction > ,
162165 vars : & mut FxHashMap < & ' a str , u16 > ,
163- consts : & mut Vec < Rc < dyn ScriptType > > ,
166+ consts : & mut Vec < Variant > ,
164167 curr_var_count : & mut u16 ,
165168 mut min_var_count : u16 ,
166169 ) -> Result < u16 , ByteCodeError > {
@@ -182,10 +185,10 @@ impl ByteCode {
182185 args. push ( match a {
183186 Expression :: Atom ( a) => match a {
184187 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 ( ) ) ) )
186189 }
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) ) ,
189192 Atom :: Name ( a) => todo ! ( "call {:?}" , a) ,
190193 } ,
191194 Expression :: Function {
@@ -201,11 +204,11 @@ impl ByteCode {
201204 match a {
202205 Expression :: Atom ( a) => {
203206 args. push ( match a {
204- Atom :: String ( a) => add_const ( Rc :: new (
207+ Atom :: String ( a) => add_const ( Variant :: Object ( Rc :: new (
205208 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) ) ,
209212 Atom :: Name ( a) => todo ! ( "call {:?}" , a) ,
210213 } ) ;
211214 }
@@ -250,9 +253,7 @@ impl ByteCode {
250253 u32:: MAX ,
251254 Box :: new ( a. to_string ( ) . into_boxed_str ( ) ) ,
252255 ) ) ) ,
253- Atom :: Integer ( a) => {
254- Instruction :: IterConst ( Box :: new ( ( reg, u32:: MAX , Box :: new ( * a) ) ) )
255- }
256+ Atom :: Integer ( a) => Instruction :: IterInt ( reg, * a) ,
256257 //Atom::Real(a) => Instruction::IterConst(Box::new(a)),
257258 Atom :: Real ( a) => todo ! ( "for Real({})" , a) ,
258259 Atom :: Name ( a) => todo ! ( "for {:?}" , a) ,
@@ -274,10 +275,10 @@ impl ByteCode {
274275 ) ?;
275276 instr. push ( Instruction :: IterJmp ( reg, ip) ) ;
276277 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 ! ( ) ,
281282 }
282283 }
283284 Statement :: Return { expr } => {
@@ -429,8 +430,8 @@ impl ByteCode {
429430 pub ( crate ) fn run (
430431 & self ,
431432 functions : & FxHashMap < Box < str > , Self > ,
432- locals : & mut [ Rc < dyn ScriptType > ] ,
433- args : & [ Rc < dyn ScriptType > ] ,
433+ locals : & mut [ Variant ] ,
434+ args : & [ Variant ] ,
434435 env : & Environment ,
435436 ) -> CallResult < RunError > {
436437 if args. len ( ) != self . param_count as usize {
@@ -440,9 +441,7 @@ impl ByteCode {
440441 for a in args. iter ( ) {
441442 vars. push ( a. clone ( ) ) ;
442443 }
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 ( ) ) ;
446445 vars. extend ( self . consts . iter ( ) . cloned ( ) ) ;
447446 let mut ip = 0 ;
448447 let mut iterators = Vec :: new ( ) ;
@@ -467,7 +466,7 @@ impl ByteCode {
467466 for & a in args. iter ( ) {
468467 call_args. push ( vars. get ( a as usize ) . ok_or ( err_roob ( ) ) ?. clone ( ) ) ;
469468 }
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 ( ) ) ?;
471470 let r = obj. call ( func, & call_args[ ..] ) . map_err ( err_call) ?;
472471 call_args. clear ( ) ;
473472 if let Some ( reg) = store_in {
@@ -505,7 +504,7 @@ impl ByteCode {
505504 }
506505 }
507506 RetSome => break Ok ( vars. first ( ) . ok_or ( err_roob ( ) ) ?. clone ( ) ) ,
508- RetNone => break Ok ( Rc :: new ( ( ) ) ) ,
507+ RetNone => break Ok ( Variant :: None ) ,
509508 IterConst ( box ( reg, jmp_ip, iter) ) => {
510509 let mut iter = iter. iter ( ) ;
511510 if let Some ( e) = iter. next ( ) {
@@ -515,6 +514,15 @@ impl ByteCode {
515514 ip = * jmp_ip;
516515 }
517516 }
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+ }
518526 IterJmp ( reg, jmp_ip) => {
519527 if let Some ( iter) = iterators. last_mut ( ) {
520528 if let Some ( e) = iter. next ( ) {
@@ -528,13 +536,45 @@ impl ByteCode {
528536 Mul ( r, a, b) => {
529537 let a = vars. get ( * a as usize ) . ok_or ( err_roob ( ) ) ?;
530538 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+ } ;
532556 * vars. get_mut ( * r as usize ) . ok_or ( err_roob ( ) ) ? = e;
533557 }
534558 Add ( r, a, b) => {
535559 let a = vars. get ( * a as usize ) . ok_or ( err_roob ( ) ) ?;
536560 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+ } ;
538578 * vars. get_mut ( * r as usize ) . ok_or ( err_roob ( ) ) ? = e;
539579 }
540580 _ => todo ! ( "{:?}" , instr) ,
@@ -567,7 +607,7 @@ impl Environment {
567607 }
568608 }
569609
570- pub fn call ( & self , func : & str , args : & [ Rc < dyn ScriptType > ] ) -> CallResult < EnvironmentError > {
610+ pub fn call ( & self , func : & str , args : & [ Variant ] ) -> CallResult < EnvironmentError > {
571611 Ok ( self
572612 . functions
573613 . get ( func)
@@ -588,6 +628,7 @@ impl Debug for Instruction {
588628 RetSome => write ! ( f, "ret 0" ) ,
589629 RetNone => write ! ( f, "ret none" ) ,
590630 IterConst ( box ( r, p, i) ) => write ! ( f, "iter {}, {}, {:?}" , r, p, i) ,
631+ IterInt ( r, i) => write ! ( f, "iter {}, {}" , r, i) ,
591632 IterJmp ( r, p) => write ! ( f, "iterjmp {}, {}" , r, p) ,
592633 Add ( r, a, b) => write ! ( f, "add {}, {}, {}" , r, a, b) ,
593634 Mul ( r, a, b) => write ! ( f, "mul {}, {}, {}" , r, a, b) ,
0 commit comments