1
198
//use std::convert::TryFrom;
2
use std::collections::HashMap;
3

            
4
type StackType = i16;
5
type DWType = i32; // double widith type,  used by */ to do more accurate math.
6

            
7
pub enum GasLimit {
8
    Unlimited,
9
    Limited(usize),
10
}
11

            
12
2
#[derive(Debug)]
13
pub enum StackMachineError {
14
    UnkownError,
15
    NumberStackUnderflow,
16
    UnhandledTrap,
17
    RanOutOfGas,
18
}
19

            
20
pub enum TrapHandled {
21
    Handled,
22
    NotHandled,
23
}
24

            
25
// Chain of Command Pattern
26
pub trait HandleTrap {
27
    fn handle_trap(
28
        &mut self,
29
        trap_id: StackType,
30
        st: &mut StackMachineState,
31
    ) -> Result<TrapHandled, StackMachineError>;
32
}
33

            
34
pub struct TrapHandler<'a> {
35
    handled_trap: StackType,
36
    to_run: Box<
37
        dyn Fn(StackType, &mut StackMachineState) -> Result<TrapHandled, StackMachineError> + 'a,
38
    >,
39
}
40

            
41
impl<'a> TrapHandler<'a> {
42
8
    pub fn new<C>(handled_trap: StackType, f: C) -> TrapHandler<'a>
43
    where
44
        C: Fn(StackType, &mut StackMachineState) -> Result<TrapHandled, StackMachineError> + 'a,
45
    {
46
8
        TrapHandler {
47
            handled_trap,
48
8
            to_run: Box::new(f),
49
        }
50
8
    }
51
}
52

            
53
impl<'a> HandleTrap for TrapHandler<'a> {
54
7
    fn handle_trap(
55
        &mut self,
56
        trap_number: StackType,
57
        st: &mut StackMachineState,
58
    ) -> Result<TrapHandled, StackMachineError> {
59
7
        if trap_number == self.handled_trap {
60
6
            return (self.to_run)(self.handled_trap, st);
61
        }
62
1
        Ok(TrapHandled::NotHandled)
63
7
    }
64
}
65

            
66
672
#[derive(Debug, Clone)]
67
pub enum Opcode {
68
    // redirect flow
69
    JMP,
70
    JR,
71
    JRZ,
72
    JRNZ,
73
    CALL,
74

            
75
    // comparison ops
76
    CMPZ,
77
    CMPNZ,
78
    EQ,
79
    LT,
80
    GT,
81

            
82
    // load integer
83
115
    LDI(StackType),
84

            
85
    // stack ops
86
    DROP,
87
    SWAP,
88
    TWODROP,
89
    TWOSWAP,
90
    RET,
91
    DUP,
92
    TWODUP,
93
    QuestionDup,
94
    TRAP,
95
    OVER,
96
    TWOOVER,
97
    TWOROT,
98
    ROT,
99
    ToR,
100
    RFrom,
101
    RFetch,
102
    DEPTH,
103

            
104
    //math ops
105
    ADD,
106
    SUB,
107
    MUL,
108
    DIV,
109
    MOD,
110
    STARSLASH, //  */   does *tiply then /ide using DWType (Double Width Type)
111
    NEGATE,
112
    OnePlus,
113
    OneMinus,
114
    TwoPlus,
115
    TwoMinus,
116
    LShift,
117
    RShift,
118

            
119
    // logic operators
120
    NOT,
121
    AND,
122
    OR,
123
    XOR,
124
    ZeroLess,
125
    ZeroEqual,
126
    ZeroGreater,
127

            
128
    // misc
129
    NOP,
130

            
131
    //variable
132
    // VARIABLE(StackType), // used to put variable +resses on the stack.
133
    BANG,
134
    AT,
135
    // GETCONSTANT(String),
136
    SETCONSTANT(String),
137
    CREATE(String),
138
    ALLOT,
139

            
140
    // io
141
    PRINT,
142
    EMIT,
143
1
    CHAR(char),
144
    KEY,
145
    PRINTTEXT(String),
146
    SPACE,
147
    SPACES,
148
    CR,
149
    QuestionMark,
150
    RightAlign,
151
    //  COUNT,
152
    //  TYPE,
153

            
154
    //chars and strings
155
    //  SDoubleTick(String),
156

            
157
    //random
158
    SETSEED,
159
    RAND,
160
15
    DEBUG(String),
161
}
162

            
163
pub struct StackMachineState {
164
    pub data_stack: Vec<StackType>,
165
    pub return_stack: Vec<StackType>,
166
    pub opcodes: Vec<Opcode>,
167
    pub variable_addresses: HashMap<String, StackType>,
168
    pub variables: Vec<StackType>,
169
    pub constants: HashMap<String, StackType>,
170
    pub text: Vec<String>,
171
    pub memory: Vec<u8>,
172
    // pub loop_stack: Vec<StackType>,
173
    pc: usize,
174
    gas_used: usize,
175
    random_seed: usize,
176
    debug: bool,
177
}
178

            
179
impl Default for StackMachineState {
180
    fn default() -> Self {
181
        Self::new()
182
    }
183
}
184

            
185
impl StackMachineState {
186
100
    pub fn new() -> StackMachineState {
187
100
        let mut s = StackMachineState {
188
100
            data_stack: Vec::new(),
189
100
            return_stack: Vec::new(),
190
100
            opcodes: Vec::new(),
191
100
            variable_addresses: HashMap::new(),
192
100
            variables: Vec::new(),
193
100
            constants: HashMap::new(),
194
100
            text: Vec::new(),
195
100
            memory: Vec::new(),
196
            // loop_stack: Vec::new(),
197
            pc: 0,
198
            gas_used: 0,
199
            random_seed: 7,
200
            debug: false,
201
        };
202
        // these are system defined constants.
203
100
        s.constants.insert("FALSE".to_string(), 0);
204
100
        s.constants.insert("TRUE".to_string(), 1);
205
100
        s.constants.insert("BL".to_string(), 32); // blank ( ie space)
206
        s
207
100
    }
208
}
209

            
210
impl StackMachineState {
211
1
    pub fn gas_used(&self) -> usize {
212
1
        self.gas_used
213
1
    }
214
}
215

            
216
pub struct StackMachine {
217
    pub st: StackMachineState,
218
    pub trap_handlers: Vec<Box<dyn HandleTrap>>,
219
}
220

            
221
impl Default for StackMachine {
222
    fn default() -> Self {
223
        Self::new()
224
    }
225
}
226

            
227
impl StackMachine {
228
100
    pub fn new() -> StackMachine {
229
100
        StackMachine {
230
100
            st: StackMachineState::new(),
231
100
            trap_handlers: Vec::new(),
232
        }
233
100
    }
234

            
235
201
    pub fn execute(
236
        &mut self,
237
        starting_point: usize,
238
        gas_limit: GasLimit,
239
    ) -> Result<String, StackMachineError> {
240
201
        self.st.gas_used = 0;
241
201
        self.st.pc = starting_point;
242

            
243
201
        let mut output: String = String::from("");
244

            
245
        macro_rules! NS_POP {
246
            () => {
247
                self.st
248
                    .data_stack
249
                    .pop()
250
                    .ok_or(StackMachineError::NumberStackUnderflow)?
251
            };
252
        }
253

            
254
201
        if self.st.debug {
255
            println!("{:?}", self.st.opcodes);
256
        }
257
        loop {
258
4063
            if self.st.debug {
259
                println!("{}: opcode:{:?}", self.st.pc, self.st.opcodes[self.st.pc]);
260
            }
261
4063
            let mut pc_reset = false;
262
4063
            match &self.st.opcodes[self.st.pc] {
263
                Opcode::PRINT => {
264
144
                    let x = NS_POP!();
265
143
                    output.push_str(&format!("{} ", x).to_string());
266
                }
267
                Opcode::EMIT => {
268
7
                    let x: StackType = NS_POP!();
269
                    match x {
270
7
                        0..=127 => output.push(x as u8 as char),
271
                        _ => todo!(),
272
                    }
273
                }
274
6
                Opcode::CHAR(c) => match c.is_ascii() {
275
6
                    true => self.st.data_stack.push(*c as u8 as StackType),
276
                    false => todo!(),
277
                },
278
68
                Opcode::PRINTTEXT(s) => {
279
                    //   println!("{}", s);
280
68
                    output.push_str(s);
281
                }
282
                Opcode::SPACE => {
283
1
                    output.push(' ');
284
                }
285
                Opcode::SPACES => {
286
5
                    let x = NS_POP!();
287
22
                    for _i in 0..x {
288
17
                        output.push(' ');
289
                    }
290
                }
291
                Opcode::CR => {
292
97
                    output.push('\n');
293
                }
294
                Opcode::QuestionMark => {
295
1
                    let var_addr = NS_POP!() as usize;
296
1
                    let value = self.st.variables[var_addr];
297
1
                    output.push_str(&format!("{} ", value).to_string());
298
                }
299
                Opcode::RightAlign => {
300
1
                    let width = NS_POP!() as usize;
301
1
                    let value = NS_POP!() as usize;
302
1
                    output.push_str(&format!("{:width$}", value, width = width));
303
                }
304
                /*
305
                Opcode::COUNT => {
306
                    let caddr1 = NS_POP!() as StackType;
307
                    self.st.data_stack.push(caddr1 + 1);
308
                    let len = self.st.memory[caddr1 as usize];
309
                    self.st.data_stack.push(len as StackType);
310
                }
311
                Opcode::TYPE => {
312
                    let caddr = NS_POP!() as usize;
313
                    let len = NS_POP!() as usize;
314
                    for i in 1..len {
315
                        output.push(self.st.memory[caddr + i] as char);
316
                    }
317
                }
318
                Opcode::SDoubleTick(s) => {
319
                    let addr = self.st.memory.len();
320
                    let bytes = s.as_str().as_bytes();
321
                    self.st.memory.push(bytes.len() as u8);
322
                    for mybyte in bytes.iter().take(bytes.len()) {
323
                        self.st.memory.push(*mybyte);
324
                    }
325

            
326
                    self.st.data_stack.push(bytes.len() as StackType);
327
                    self.st.data_stack.push(addr as StackType);
328
                }
329
                */
330
                Opcode::JR => {
331
112
                    let x: StackType = NS_POP!();
332
112
                    self.st.pc = (self.st.pc as StackType + x) as usize;
333
112
                    pc_reset = true;
334
112
                }
335
56
                Opcode::CALL => {
336
56
                    self.st.return_stack.push(self.st.pc as StackType + 1);
337
56
                    self.st.pc = NS_POP!() as usize;
338
56
                    pc_reset = true;
339
                }
340
                Opcode::TWOOVER => {
341
2
                    let x1 = NS_POP!();
342
2
                    let x2 = NS_POP!();
343
2
                    let y1 = NS_POP!();
344
2
                    let y2 = NS_POP!();
345
2
                    self.st.data_stack.push(y2);
346
2
                    self.st.data_stack.push(y1);
347
2
                    self.st.data_stack.push(x2);
348
2
                    self.st.data_stack.push(x1);
349
2
                    self.st.data_stack.push(y2);
350
2
                    self.st.data_stack.push(y1);
351
                }
352
                Opcode::OVER => {
353
5
                    let x = NS_POP!();
354
5
                    let y = NS_POP!();
355
5
                    self.st.data_stack.push(y);
356
5
                    self.st.data_stack.push(x);
357
5
                    self.st.data_stack.push(y);
358
                }
359
                Opcode::ROT => {
360
31
                    let x = NS_POP!();
361
31
                    let y = NS_POP!();
362
31
                    let z = NS_POP!();
363
31
                    self.st.data_stack.push(y);
364
31
                    self.st.data_stack.push(x);
365
31
                    self.st.data_stack.push(z);
366
                }
367
                Opcode::TWOROT => {
368
2
                    let x1 = NS_POP!();
369
2
                    let x2 = NS_POP!();
370
2
                    let y1 = NS_POP!();
371
2
                    let y2 = NS_POP!();
372
2
                    let z1 = NS_POP!();
373
2
                    let z2 = NS_POP!();
374
2
                    self.st.data_stack.push(y2);
375
2
                    self.st.data_stack.push(y1);
376
2
                    self.st.data_stack.push(x2);
377
2
                    self.st.data_stack.push(x1);
378
2
                    self.st.data_stack.push(z2);
379
2
                    self.st.data_stack.push(z1);
380
                }
381
                Opcode::DEPTH => {
382
2
                    self.st
383
                        .data_stack
384
2
                        .push(self.st.data_stack.len() as StackType);
385
                }
386
                Opcode::CMPZ => {
387
2
                    let x = NS_POP!();
388
2
                    if x == 0 {
389
1
                        self.st.data_stack.push(0);
390
                    } else {
391
1
                        self.st.data_stack.push(-1);
392
                    }
393
                }
394
                Opcode::CMPNZ => {
395
2
                    let x = NS_POP!();
396
2
                    if x == 0 {
397
1
                        self.st.data_stack.push(-1);
398
                    } else {
399
1
                        self.st.data_stack.push(0);
400
                    }
401
                }
402
                Opcode::EQ => {
403
2
                    let x = NS_POP!();
404
2
                    let y = NS_POP!();
405
2
                    if x == y {
406
1
                        self.st.data_stack.push(-1);
407
                    } else {
408
1
                        self.st.data_stack.push(0);
409
                    }
410
                }
411
                Opcode::LT => {
412
19
                    let x = NS_POP!();
413
19
                    let y = NS_POP!();
414
19
                    if self.st.debug {
415
                        println!("{} < {} = {}", y, x, y < x);
416
                    }
417
19
                    if y < x {
418
16
                        self.st.data_stack.push(-1);
419
                    } else {
420
3
                        self.st.data_stack.push(0);
421
                    }
422
                }
423
                Opcode::GT => {
424
117
                    let x = NS_POP!();
425
117
                    let y = NS_POP!();
426
117
                    if self.st.debug {
427
                        println!("{} > {} = {}", y, x, y > x);
428
                    }
429
117
                    if y > x {
430
100
                        self.st.data_stack.push(-1);
431
                    } else {
432
17
                        self.st.data_stack.push(0);
433
                    }
434
                }
435
                Opcode::ZeroLess => {
436
2
                    let x = NS_POP!();
437
2
                    self.st.data_stack.push(if x < 0 { 1 } else { 0 });
438
                }
439
                Opcode::ZeroEqual => {
440
5
                    let x = NS_POP!();
441
5
                    self.st.data_stack.push(if x == 0 { 1 } else { 0 });
442
                }
443
                Opcode::ZeroGreater => {
444
2
                    let x = NS_POP!();
445
2
                    self.st.data_stack.push(if x > 0 { 1 } else { 0 });
446
                }
447
                Opcode::JRZ => {
448
166
                    let x = NS_POP!();
449
166
                    let y = NS_POP!();
450
166
                    if y == 0 {
451
45
                        self.st.pc = (self.st.pc as StackType + x) as usize;
452
45
                        pc_reset = true;
453
                    }
454
                }
455
                Opcode::JRNZ => {
456
4
                    let x = NS_POP!();
457
4
                    let y = NS_POP!();
458
4
                    if y != 0 {
459
2
                        self.st.pc = (self.st.pc as StackType + x) as usize;
460
2
                        pc_reset = true;
461
                    }
462
                }
463
                Opcode::JMP => {
464
31
                    let x = NS_POP!();
465
31
                    self.st.pc = (self.st.pc as StackType + x) as usize;
466
31
                    pc_reset = true;
467
31
                }
468
883
                Opcode::LDI(x) => self.st.data_stack.push(*x),
469
                Opcode::DROP => {
470
123
                    let _x = NS_POP!();
471
122
                }
472
                Opcode::TWODROP => {
473
1
                    let _x = NS_POP!();
474
1
                    let _x = NS_POP!();
475
1
                }
476
47
                Opcode::RET => {
477
236
                    match self.st.return_stack.pop() {
478
189
                        None => return Ok(output),
479
47
                        Some(oldpc) => self.st.pc = oldpc as usize,
480
                    };
481
47
                    pc_reset = true;
482
                }
483
                Opcode::NEGATE => {
484
1
                    let x = NS_POP!();
485
1
                    self.st.data_stack.push(-x);
486
                }
487
                Opcode::ADD => {
488
163
                    let x = NS_POP!();
489
163
                    let y = NS_POP!();
490
163
                    self.st.data_stack.push(x + y);
491
                }
492
                Opcode::SUB => {
493
8
                    let x = NS_POP!();
494
8
                    let y = NS_POP!();
495
8
                    self.st.data_stack.push(y - x);
496
                }
497
                Opcode::MUL => {
498
39
                    let x = NS_POP!();
499
39
                    let y = NS_POP!();
500
39
                    self.st.data_stack.push(x * y);
501
                }
502
                Opcode::DIV => {
503
7
                    let x = NS_POP!();
504
7
                    let y = NS_POP!();
505
7
                    self.st.data_stack.push(y / x);
506
                }
507
                Opcode::MOD => {
508
4
                    let x = NS_POP!();
509
4
                    let y = NS_POP!();
510
4
                    self.st.data_stack.push(y % x);
511
                }
512
                Opcode::STARSLASH => {
513
                    // used Double with so that math is more accurate..
514
13
                    let x: DWType = NS_POP!() as DWType;
515
13
                    let y: DWType = NS_POP!() as DWType;
516
13
                    let z: DWType = NS_POP!() as DWType;
517

            
518
13
                    let temp = (z * y / x) as StackType;
519
13
                    self.st.data_stack.push(temp as StackType);
520
                }
521
                Opcode::OnePlus => {
522
1
                    let x = NS_POP!();
523
1
                    self.st.data_stack.push(x + 1);
524
                }
525
                Opcode::OneMinus => {
526
1
                    let x = NS_POP!();
527
1
                    self.st.data_stack.push(x - 1);
528
                }
529
                Opcode::TwoPlus => {
530
1
                    let x = NS_POP!();
531
1
                    self.st.data_stack.push(x + 2);
532
                }
533
                Opcode::TwoMinus => {
534
1
                    let x = NS_POP!();
535
1
                    self.st.data_stack.push(x - 2);
536
                }
537
                Opcode::LShift => {
538
2
                    let x = NS_POP!();
539
2
                    let y = NS_POP!();
540
2
                    self.st.data_stack.push(y << x);
541
                }
542
                Opcode::RShift => {
543
2
                    let x = NS_POP!();
544
2
                    let y = NS_POP!();
545
2
                    self.st.data_stack.push(y >> x);
546
                }
547
                // logical operators
548
                Opcode::NOT => {
549
2
                    let x = NS_POP!();
550
2
                    self.st.data_stack.push(!x);
551
                }
552
                Opcode::AND => {
553
1
                    let x = NS_POP!();
554
1
                    let y = NS_POP!();
555
1
                    self.st.data_stack.push(x & y);
556
                }
557
                Opcode::OR => {
558
1
                    let x = NS_POP!();
559
1
                    let y = NS_POP!();
560
1
                    self.st.data_stack.push(x | y);
561
                }
562
                /*
563
                Opcode::VARIABLE(addr) => {
564
                    self.st.data_stack.push(*addr);
565
                }
566
                */
567
4
                Opcode::CREATE(var) => {
568
7
                    if let std::collections::hash_map::Entry::Vacant(e) =
569
4
                        self.st.variable_addresses.entry(var.to_uppercase())
570
                    {
571
3
                        let addr = self.st.variables.len();
572
3
                        e.insert(addr as StackType);
573
3
                        self.st.variables.push(0); // initialize value to zero.
574
                    } else {
575
                        // output error saying that the variable already exists..
576
                    }
577
4
                }
578
                Opcode::ALLOT => {
579
                    let size = NS_POP!() as usize;
580
                    let addr = NS_POP!() as usize;
581
                    for i in 0..size {
582
                        self.st.memory[addr + i] = 0;
583
                    }
584
                }
585
                Opcode::BANG => {
586
4
                    let var_addr = NS_POP!() as usize;
587
4
                    let value = NS_POP!();
588
4
                    self.st.variables[var_addr] = value;
589
4
                }
590
                Opcode::AT => {
591
4
                    let var_addr = NS_POP!() as usize;
592
4
                    let value = self.st.variables[var_addr];
593
4
                    self.st.data_stack.push(value);
594
                }
595
                /*
596
                Opcode::GETCONSTANT(con) => {
597
                    match self.st.constants.get(con) {
598
                        Some(x) => self.st.data_stack.push(*x),
599
                        None => todo!(), //Err(ForthError::ConstantDoesNotExist(con.to_string())),
600
                    }
601
                }
602
                */
603
3
                Opcode::SETCONSTANT(con) => {
604
3
                    let x = NS_POP!();
605
3
                    self.st.constants.insert(con.to_string(), x);
606
                }
607
                Opcode::XOR => {
608
1
                    let x = NS_POP!();
609
1
                    let y = NS_POP!();
610
1
                    self.st.data_stack.push(x ^ y);
611
                }
612
                Opcode::DUP => {
613
70
                    let x = NS_POP!();
614
70
                    self.st.data_stack.push(x);
615
70
                    self.st.data_stack.push(x);
616
                }
617
                Opcode::TWODUP => {
618
232
                    let x1 = NS_POP!();
619
232
                    let x2 = NS_POP!();
620
232
                    self.st.data_stack.push(x2);
621
232
                    self.st.data_stack.push(x1);
622
232
                    self.st.data_stack.push(x2);
623
232
                    self.st.data_stack.push(x1);
624
                }
625
                Opcode::QuestionDup => {
626
2
                    let x = NS_POP!();
627
2
                    self.st.data_stack.push(x);
628
2
                    if x != 0 {
629
1
                        self.st.data_stack.push(x);
630
                    }
631
                }
632
                Opcode::SWAP => {
633
115
                    let x = NS_POP!();
634
115
                    let y = NS_POP!();
635
115
                    self.st.data_stack.push(x);
636
115
                    self.st.data_stack.push(y);
637
                }
638
                Opcode::TWOSWAP => {
639
1
                    let x1 = NS_POP!();
640
1
                    let x2 = NS_POP!();
641
1
                    let y1 = NS_POP!();
642
1
                    let y2 = NS_POP!();
643
1
                    self.st.data_stack.push(x1);
644
1
                    self.st.data_stack.push(x2);
645
1
                    self.st.data_stack.push(y1);
646
1
                    self.st.data_stack.push(y2);
647
                }
648
                Opcode::TRAP => {
649
                    // We are going to say that TRAPs always have a numeric code on the number stack to define which TRAP is being called
650
7
                    let trap_id = NS_POP!();
651
8
                    for h in self.trap_handlers.iter_mut() {
652
7
                        if let TrapHandled::Handled = h.handle_trap(trap_id, &mut self.st)? {
653
6
                            return Ok("".to_string());
654
                        }
655
                    }
656
1
                    return Err(StackMachineError::UnhandledTrap);
657
                }
658
                Opcode::ToR => {
659
                    //takes a value from the parameter( number) stack and push it on the return stack
660
468
                    let x = NS_POP!();
661
                    // println!("TOR {}", x);
662
468
                    self.st.return_stack.push(x);
663
                    //  println!("{:?}", self.st.return_stack);
664
                }
665
                Opcode::RFrom => {
666
                    // takes a value from the return stack and put it on the parameter stack.
667
468
                    match self.st.return_stack.pop() {
668
468
                        Some(x) => self.st.data_stack.push(x),
669
                        _ => todo!(),
670
                    }
671
                }
672
                Opcode::RFetch => {
673
                    // copies the value from the return stack and puts it on the number stack.
674
1
                    match self.st.return_stack.pop() {
675
1
                        Some(x) => {
676
1
                            self.st.data_stack.push(x);
677
1
                            self.st.return_stack.push(x);
678
                        }
679
                        _ => todo!(),
680
                    }
681
                }
682
                Opcode::NOP => {}
683
                // sets random seed
684
1
                Opcode::SETSEED => {
685
1
                    self.st.random_seed = NS_POP!() as usize;
686
                }
687
                // pushes a random number on the stack.
688
                Opcode::RAND => {
689
4
                    self.st.random_seed ^= self.st.random_seed << 13;
690
4
                    self.st.random_seed ^= self.st.random_seed >> 17;
691
4
                    self.st.random_seed ^= self.st.random_seed << 5;
692
4
                    self.st.data_stack.push(self.st.random_seed as StackType)
693
                }
694
                Opcode::KEY => todo!(), // need to find a way to do this in rust..  (detect keydown, and get value of key in ascii)
695
296
                Opcode::DEBUG(_s) => {} // ignore.. this is for debugging the stack.
696
            }
697
3865
            if !pc_reset {
698
3572
                self.st.pc += 1;
699
            }
700

            
701
3865
            self.st.gas_used += 1;
702

            
703
            //if self.st.debug {
704
            //    println!("after data stack: {:?}", self.st.data_stack);
705
            //    println!("after return stack: {:?}", self.st.return_stack);
706
            //    println!("================");
707
            //}
708

            
709
3865
            if let GasLimit::Limited(x) = gas_limit {
710
3865
                if self.st.gas_used > x {
711
3
                    return Err(StackMachineError::RanOutOfGas);
712
                }
713
            }
714
        }
715
        //Ok(format!("{} ok.", output))
716
201
    }
717
}
718

            
719
#[cfg(test)]
720
mod tests {
721
    use super::*;
722

            
723
    #[test]
724
2
    fn test_char() {
725
1
        let mut sm = StackMachine::new();
726
1
        sm.st
727
            .opcodes
728
            .extend_from_slice(&[Opcode::CHAR('a'), Opcode::RET]);
729

            
730
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
731
1
        assert_eq!(sm.st.data_stack, vec![97]);
732
2
    }
733

            
734
    #[test]
735
2
    fn test_rshift() {
736
1
        let mut sm = StackMachine::new();
737

            
738
1
        sm.st.data_stack.extend_from_slice(&[4, 1]);
739
        // Put the opcodes into the *memory*
740
1
        sm.st
741
            .opcodes
742
            .extend_from_slice(&[Opcode::RShift, Opcode::RET]);
743

            
744
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
745
1
        assert_eq!(sm.st.data_stack, vec![2]);
746

            
747
1
        sm.st.data_stack.clear();
748
1
        sm.st.data_stack.extend_from_slice(&[16, 2]);
749
        // Put the opcodes into the *memory*
750
1
        sm.st
751
            .opcodes
752
            .extend_from_slice(&[Opcode::RShift, Opcode::RET]);
753

            
754
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
755
1
        assert_eq!(sm.st.data_stack, vec![4]);
756
2
    }
757

            
758
    #[test]
759
2
    fn test_lshift() {
760
1
        let mut sm = StackMachine::new();
761

            
762
1
        sm.st.data_stack.extend_from_slice(&[4, 1]);
763
        // Put the opcodes into the *memory*
764
1
        sm.st
765
            .opcodes
766
            .extend_from_slice(&[Opcode::LShift, Opcode::RET]);
767

            
768
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
769
1
        assert_eq!(sm.st.data_stack, vec![8]);
770

            
771
1
        sm.st.data_stack.clear();
772
1
        sm.st.data_stack.extend_from_slice(&[8, 2]);
773
        // Put the opcodes into the *memory*
774
1
        sm.st
775
            .opcodes
776
            .extend_from_slice(&[Opcode::LShift, Opcode::RET]);
777

            
778
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
779
1
        assert_eq!(sm.st.data_stack, vec![32]);
780
2
    }
781

            
782
    #[test]
783
2
    fn test_tor() {
784
1
        let mut sm = StackMachine::new();
785

            
786
        // Populate the number stack
787
1
        sm.st.data_stack.extend_from_slice(&[1]);
788
        //sm.st.return_stack.extend_from_slice(&[0]);
789

            
790
1
        sm.st.opcodes.extend_from_slice(&[Opcode::ToR, Opcode::RET]);
791

            
792
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
793
1
        assert_eq!(sm.st.data_stack.len(), 0);
794
        //  assert_eq!(sm.st.return_stack, vec![1]);    value on return stack is removed with the RET code
795
2
    }
796

            
797
    #[test]
798
2
    fn test_rfrom() {
799
1
        let mut sm = StackMachine::new();
800

            
801
        // Populate the number stack
802
1
        sm.st.return_stack.extend_from_slice(&[1]);
803

            
804
1
        sm.st
805
            .opcodes
806
            .extend_from_slice(&[Opcode::RFrom, Opcode::RET]);
807

            
808
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
809
1
        assert_eq!(sm.st.data_stack, vec![1]);
810
1
        assert!(sm.st.return_stack.is_empty());
811
2
    }
812

            
813
    #[test]
814
2
    fn test_rfetch() {
815
1
        let mut sm = StackMachine::new();
816

            
817
        // Populate the number stack
818
1
        sm.st.return_stack.extend_from_slice(&[1]);
819

            
820
1
        sm.st
821
            .opcodes
822
            .extend_from_slice(&[Opcode::RFetch, Opcode::RET]);
823

            
824
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
825
1
        assert_eq!(sm.st.data_stack, vec![1]);
826
        // assert_eq!(sm.st.return_stack, vec![1]);  // RET will remove the 1 from the return stack
827
2
    }
828

            
829
    #[test]
830
2
    fn test_print() {
831
1
        let mut sm = StackMachine::new();
832

            
833
        // Populate the number stack
834
1
        sm.st.data_stack.extend_from_slice(&[1]);
835
        // Put the opcodes into the *memory*
836
1
        sm.st
837
            .opcodes
838
            .extend_from_slice(&[Opcode::PRINT, Opcode::RET]);
839

            
840
1
        assert_eq!(sm.execute(0, GasLimit::Limited(100)).unwrap(), "1 ");
841
1
        assert_eq!(sm.st.data_stack.len(), 0);
842
2
    }
843

            
844
    #[test]
845
2
    fn test_negate() {
846
1
        let mut sm = StackMachine::new();
847

            
848
        // Populate the number stack
849
1
        sm.st.data_stack.extend_from_slice(&[1]);
850
        // Put the opcodes into the *memory*
851
1
        sm.st
852
            .opcodes
853
            .extend_from_slice(&[Opcode::NEGATE, Opcode::RET]);
854

            
855
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
856
1
        assert_eq!(sm.st.data_stack, vec![-1]);
857
2
    }
858
    #[test]
859
2
    fn test_rot() {
860
1
        let mut sm = StackMachine::new();
861

            
862
        // Populate the number stack
863
1
        sm.st.data_stack.extend_from_slice(&[1, 2, 3]);
864
        // Put the opcodes into the *memory*
865
1
        sm.st.opcodes.extend_from_slice(&[Opcode::ROT, Opcode::RET]);
866

            
867
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
868
1
        assert_eq!(sm.st.data_stack, vec![2, 3, 1]);
869
1
        assert!(sm.st.gas_used() > 0);
870
2
    }
871

            
872
    #[test]
873
2
    fn test_over() {
874
1
        let mut sm = StackMachine::new();
875

            
876
        // Populate the number stack
877
1
        sm.st.data_stack.extend_from_slice(&[1, 2, 3]);
878
        // Put the opcodes into the *memory*
879
1
        sm.st
880
            .opcodes
881
            .extend_from_slice(&[Opcode::OVER, Opcode::RET]);
882

            
883
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
884
1
        assert_eq!(sm.st.data_stack, vec![1, 2, 3, 2]);
885
2
    }
886

            
887
    #[test]
888
2
    fn test_execute_jr_forward() {
889
1
        let mut sm = StackMachine::new();
890

            
891
        // Populate the number stack
892
1
        sm.st.data_stack.extend_from_slice(&[321, 394]);
893
        // Put the opcodes into the *memory*
894
1
        sm.st.opcodes.extend_from_slice(&[
895
            Opcode::LDI(0),
896
            Opcode::LDI(1),
897
            Opcode::LDI(2),
898
            Opcode::LDI(2), // Jump to location 6 with the JR statement, relative jump of 1
899
            Opcode::JR,
900
            Opcode::LDI(3),
901
            Opcode::LDI(4),
902
            Opcode::LDI(5),
903
            Opcode::RET,
904
        ]);
905

            
906
        // Execute the instructions
907
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
908

            
909
1
        assert_eq!(sm.st.data_stack, vec![321, 394, 0, 1, 2, 4, 5]);
910
2
    }
911

            
912
    #[test]
913
2
    fn test_execute_jr_backward() {
914
1
        let mut sm = StackMachine::new();
915

            
916
        // Populate the number stack
917
1
        sm.st.data_stack.extend_from_slice(&[321, 394]);
918
        // Put the opcodes into the *memory*
919
1
        sm.st.opcodes.extend_from_slice(&[
920
            Opcode::LDI(0),
921
            Opcode::LDI(1),
922
            Opcode::RET,
923
            Opcode::LDI(2),
924
            Opcode::LDI(-5), // Jump to the LDI(0)
925
            Opcode::JR,
926
        ]);
927

            
928
        // Execute the instructions
929
1
        sm.execute(3, GasLimit::Limited(100)).unwrap();
930

            
931
1
        assert_eq!(sm.st.data_stack, vec![321, 394, 2, 0, 1]);
932
2
    }
933

            
934
    #[test]
935
2
    fn test_execute_jrz_forward() {
936
1
        let mut sm = StackMachine::new();
937

            
938
        // Populate the number stack
939
1
        sm.st.data_stack.extend_from_slice(&[321, 394]);
940
        // Put the opcodes into the *memory*
941
1
        sm.st.opcodes.extend_from_slice(&[
942
            Opcode::LDI(0),
943
            Opcode::LDI(1),
944
            Opcode::LDI(2),
945
            Opcode::LDI(1), // This won't happen because TOS won't be zero...
946
            Opcode::LDI(2), // TOS for JRZ
947
            Opcode::JRZ,
948
            Opcode::LDI(3),
949
            Opcode::LDI(4),
950
            Opcode::LDI(5),
951
            Opcode::LDI(0),
952
            Opcode::LDI(2), // Relative Jump of 1
953
            Opcode::JRZ,    // Jump over the LDI(6)
954
            Opcode::LDI(6),
955
            Opcode::LDI(7),
956
            Opcode::LDI(8),
957
            Opcode::RET,
958
        ]);
959

            
960
        // Execute the instructions
961
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
962

            
963
1
        assert_eq!(sm.st.data_stack, vec![321, 394, 0, 1, 2, 3, 4, 5, 7, 8]);
964
2
    }
965

            
966
    #[test]
967
2
    fn test_execute_jrz_backward() {
968
1
        let mut sm = StackMachine::new();
969

            
970
        // Populate the number stack
971
1
        sm.st.data_stack.extend_from_slice(&[321, 394]);
972
        // Put the opcodes into the *memory*
973
1
        sm.st.opcodes.extend_from_slice(&[
974
            Opcode::LDI(0),
975
            Opcode::RET,
976
            Opcode::LDI(1),
977
            Opcode::LDI(2),
978
            Opcode::LDI(1),  // This won't happen because TOS won't be zero...
979
            Opcode::LDI(-2), // TOS for JRZ
980
            Opcode::JRZ,
981
            Opcode::LDI(3),
982
            Opcode::LDI(4),
983
            Opcode::LDI(5),
984
            Opcode::LDI(0),
985
            Opcode::LDI(-12), // Relative Jump to start of code
986
            Opcode::JRZ,      // Jump over the LDI(6)
987
            Opcode::LDI(6),
988
            Opcode::LDI(7),
989
            Opcode::LDI(8),
990
            Opcode::RET,
991
        ]);
992

            
993
        // Execute the instructions
994
1
        sm.execute(2, GasLimit::Limited(100)).unwrap();
995

            
996
1
        assert_eq!(sm.st.data_stack, vec![321, 394, 1, 2, 3, 4, 5, 0]);
997
2
    }
998

            
999
    #[test]
2
    fn test_execute_jrnz_forward() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[321, 394]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[
            Opcode::LDI(0),
            Opcode::LDI(1),
            Opcode::LDI(2),
            Opcode::LDI(0), // This won't happen because TOS is zero...
            Opcode::LDI(2), // TOS for JRZ
            Opcode::JRNZ,
            Opcode::LDI(3),
            Opcode::LDI(4),
            Opcode::LDI(5),
            Opcode::LDI(1),
            Opcode::LDI(2), // Relative Jump of 1
            Opcode::JRNZ,   // Jump over the LDI(6)
            Opcode::LDI(6),
            Opcode::LDI(7),
            Opcode::LDI(8),
            Opcode::RET,
        ]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![321, 394, 0, 1, 2, 3, 4, 5, 7, 8]);
2
    }
    #[test]
2
    fn test_execute_jrnz_backward() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[321, 394]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[
            Opcode::LDI(0),
            Opcode::RET,
            Opcode::LDI(1),
            Opcode::LDI(2),
            Opcode::LDI(0),  // This won't happen because TOS is zero...
            Opcode::LDI(-2), // TOS for JRZ
            Opcode::JRNZ,
            Opcode::LDI(3),
            Opcode::LDI(4),
            Opcode::LDI(5),
            Opcode::LDI(1),
            Opcode::LDI(-12), // Relative Jump to start of code
            Opcode::JRNZ,     // Jump over the LDI(6)
            Opcode::LDI(6),
            Opcode::LDI(7),
            Opcode::LDI(8),
            Opcode::RET,
        ]);
        // Execute the instructions
1
        sm.execute(2, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![321, 394, 1, 2, 3, 4, 5, 0]);
2
    }
    #[test]
2
    fn test_execute_cmpz_1() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[123, 321, 0]);
        // Put the opcodes into the *memory*
1
        sm.st
            .opcodes
            .extend_from_slice(&[Opcode::CMPZ, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![123, 321, 0]);
2
    }
    #[test]
2
    fn test_execute_cmpz_2() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[123, 321, 1]);
        // Put the opcodes into the *memory*
1
        sm.st
            .opcodes
            .extend_from_slice(&[Opcode::CMPZ, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![123, 321, -1]);
2
    }
    #[test]
2
    fn test_execute_cmpnz_1() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[123, 321, 0]);
        // Put the opcodes into the *memory*
1
        sm.st
            .opcodes
            .extend_from_slice(&[Opcode::CMPNZ, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![123, 321, -1]);
2
    }
    #[test]
2
    fn test_execute_cmpnz_2() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[123, 321, 1]);
        // Put the opcodes into the *memory*
1
        sm.st
            .opcodes
            .extend_from_slice(&[Opcode::CMPNZ, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![123, 321, 0]);
2
    }
    #[test]
2
    fn test_execute_eq() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[123, 321]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[Opcode::EQ, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![0]);
        // 0 = 0 => true (-1)
1
        sm.st.data_stack.extend_from_slice(&[0]);
1
        sm.st.opcodes.extend_from_slice(&[Opcode::EQ, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![-1]);
2
    }
    #[test]
2
    fn test_execute_lt() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[123, 321]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[Opcode::LT, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![-1]);
        // 0 = 0 => true (-1)
1
        sm.st.data_stack.extend_from_slice(&[-1]);
1
        sm.st.opcodes.extend_from_slice(&[Opcode::EQ, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![0]);
2
    }
    #[test]
2
    fn test_execute_gt() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[123, 321]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[Opcode::GT, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![0]);
        // 0 = 0 => true (-1)
1
        sm.st.data_stack.extend_from_slice(&[-2]);
1
        sm.st.opcodes.extend_from_slice(&[Opcode::EQ, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![-1]);
2
    }
    #[test]
2
    fn test_execute_call() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[321, 394]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[
            Opcode::LDI(0),
            Opcode::LDI(5),
            Opcode::CALL,
            Opcode::LDI(1),
            Opcode::RET,
            Opcode::LDI(2),
            Opcode::LDI(10),
            Opcode::CALL,
            Opcode::LDI(3),
            Opcode::RET,
            Opcode::LDI(4),
            Opcode::LDI(15),
            Opcode::CALL,
            Opcode::LDI(5),
            Opcode::RET,
            Opcode::LDI(6),
            Opcode::LDI(20),
            Opcode::CALL,
            Opcode::LDI(7),
            Opcode::RET,
            Opcode::LDI(8),
            Opcode::LDI(25),
            Opcode::CALL,
            Opcode::LDI(9),
            Opcode::RET,
            Opcode::RET,
        ]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
2
        assert_eq!(
            sm.st.data_stack,
1
            vec![321, 394, 0, 2, 4, 6, 8, 9, 7, 5, 3, 1]
        );
2
    }
    #[test]
2
    fn test_emit() {
1
        let mut sm = StackMachine::new();
1
        sm.st.data_stack.extend_from_slice(&[65, 66]);
        // Put the opcodes into the *memory*
1
        sm.st
            .opcodes
            .extend_from_slice(&[Opcode::EMIT, Opcode::EMIT, Opcode::RET]);
        // AB should be returned by execute
1
        assert_eq!(sm.execute(0, GasLimit::Limited(100)).unwrap(), "BA");
        // now just assume that the output is printed..
        // maybe change how this program caches and displays output?
1
        assert_eq!(sm.st.data_stack, vec![]);
2
    }
    #[test]
2
    fn test_execute_ldi() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[321, 394]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[
            Opcode::LDI(0),
            Opcode::LDI(1),
            Opcode::LDI(2),
            Opcode::RET,
        ]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![321, 394, 0, 1, 2]);
2
    }
    #[test]
2
    fn test_execute_drop() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[321, 394]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[
            Opcode::LDI(0),
            Opcode::LDI(1),
            Opcode::DROP,
            Opcode::LDI(2),
            Opcode::RET,
        ]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![321, 394, 0, 2]);
2
    }
    #[test]
    #[should_panic]
1
    fn test_execute_drop_error() {
        let mut sm = StackMachine::new();
        // Populate the number stack
        sm.st.data_stack.extend_from_slice(&[321, 394]);
        // Put the opcodes into the *memory*
        sm.st.opcodes.extend_from_slice(&[
            Opcode::LDI(0),
            Opcode::LDI(1),
            Opcode::DROP,
            Opcode::DROP,
            Opcode::DROP,
            Opcode::DROP,
            Opcode::DROP,
            Opcode::LDI(2),
            Opcode::RET,
        ]);
        // Execute the instructions
        sm.execute(0, GasLimit::Limited(100)).unwrap();
        assert_eq!(sm.st.data_stack, vec![]);
1
    }
    #[test]
2
    fn test_execute_swap() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[321, 394]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[
            Opcode::LDI(0),
            Opcode::LDI(1),
            Opcode::SWAP,
            Opcode::LDI(2),
            Opcode::RET,
        ]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![321, 394, 1, 0, 2]);
2
    }
    #[test]
2
    fn test_execute_add() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[123, 321]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[Opcode::ADD, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![444]);
        //noather example
1
        sm.st.data_stack.clear();
1
        sm.st.data_stack.extend_from_slice(&[17, 20, 132, 3, 9]);
1
        sm.st.opcodes.clear();
1
        sm.st.opcodes.push(Opcode::ADD);
1
        sm.st.opcodes.push(Opcode::RET);
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![17, 20, 132, 12]);
1
        sm.st.opcodes.clear();
1
        sm.st.opcodes.push(Opcode::ADD);
1
        sm.st.opcodes.push(Opcode::RET);
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![17, 20, 144]);
1
        sm.st.opcodes.clear();
1
        sm.st.opcodes.push(Opcode::ADD);
1
        sm.st.opcodes.push(Opcode::ADD);
1
        sm.st.opcodes.push(Opcode::RET);
1
        println!("{}", sm.execute(0, GasLimit::Limited(100)).unwrap());
1
        assert_eq!(sm.st.data_stack, vec![181]);
2
    }
    #[test]
2
    fn test_execute_sub() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[444, 321]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[Opcode::SUB, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![123]);
2
    }
    #[test]
2
    fn test_execute_mul() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[321, 2]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[Opcode::MUL, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![642]);
2
    }
    #[test]
2
    fn test_execute_div() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[642, 321]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[Opcode::DIV, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![2]);
2
    }
    #[test]
2
    fn test_execute_mod() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[10, 3]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[Opcode::MOD, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![1]);
2
    }
    #[test]
2
    fn test_execute_starslash() {
        //    ie  */
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[2000, 34, 100]);
        // Put the opcodes into the *memory*
1
        sm.st
            .opcodes
            .extend_from_slice(&[Opcode::STARSLASH, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![680]);
2
    }
    #[test]
2
    fn test_execute_not() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[321, 0]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[Opcode::NOT, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![321, -1]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[Opcode::NOT, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![321, 0]);
2
    }
    #[test]
2
    fn test_execute_and() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[15, 1]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[Opcode::AND, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![1]);
2
    }
    #[test]
2
    fn test_execute_or() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[8, 7]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[Opcode::OR, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![15]);
2
    }
    #[test]
2
    fn test_execute_xor() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[16, 17]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[Opcode::XOR, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![1]);
2
    }
    #[test]
2
    fn test_execute_dup() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[123, 394]);
        // Put the opcodes into the *memory*
1
        sm.st.opcodes.extend_from_slice(&[Opcode::DUP, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![123, 394, 394]);
2
    }
    #[test]
    #[should_panic]
1
    fn test_execute_run_out_of_gas() {
        let mut sm = StackMachine::new();
        // Populate the number stack
        sm.st.data_stack.extend_from_slice(&[321, 394]);
        // Put the opcodes into the *memory*
        sm.st.opcodes.extend_from_slice(&[
            Opcode::LDI(0),
            Opcode::LDI(5),
            Opcode::CALL,
            Opcode::LDI(1),
            Opcode::RET,
            Opcode::LDI(2),
            Opcode::LDI(10),
            Opcode::CALL,
            Opcode::LDI(3),
            Opcode::RET,
            Opcode::LDI(4),
            Opcode::LDI(15),
            Opcode::CALL,
            Opcode::LDI(5),
            Opcode::RET,
            Opcode::LDI(6),
            Opcode::LDI(20),
            Opcode::CALL,
            Opcode::LDI(7),
            Opcode::RET,
            Opcode::LDI(8),
            Opcode::LDI(25),
            Opcode::CALL,
            Opcode::LDI(9),
            Opcode::RET,
            Opcode::RET,
        ]);
        // Execute the instructions
        sm.execute(0, GasLimit::Limited(10)).unwrap();
1
    }
    #[test]
2
    fn test_handle_trap_1() {
1
        let mut sm = StackMachine::new();
2
        sm.trap_handlers
2
            .push(Box::from(TrapHandler::new(100, |_trap_id, st| {
1
                st.data_stack
                    .pop()
1
                    .ok_or(StackMachineError::NumberStackUnderflow)?;
1
                st.data_stack.push(200);
1
                Ok(TrapHandled::Handled)
1
            })));
        // Populate the number stack
1
        sm.st.data_stack.extend_from_slice(&[50, 100]);
        // Put the opcodes into the *memory*
1
        sm.st
            .opcodes
            .extend_from_slice(&[Opcode::TRAP, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![200]);
2
    }
    #[test]
2
    fn test_handle_trap_2() {
1
        let mut sm = StackMachine::new();
2
        sm.trap_handlers
1
            .push(Box::from(TrapHandler::new(-100, |_trap_id, st| {
                st.data_stack
                    .pop()
                    .ok_or(StackMachineError::NumberStackUnderflow)?;
                st.data_stack.push(-100);
                Ok(TrapHandled::Handled)
            })));
2
        sm.trap_handlers
2
            .push(Box::from(TrapHandler::new(100, |_trap_id, st| {
1
                st.data_stack
                    .pop()
1
                    .ok_or(StackMachineError::NumberStackUnderflow)?;
1
                st.data_stack.push(200);
1
                Ok(TrapHandled::Handled)
1
            })));
2
        sm.trap_handlers
1
            .push(Box::from(TrapHandler::new(-200, |_trap_id, st| {
                st.data_stack
                    .pop()
                    .ok_or(StackMachineError::NumberStackUnderflow)?;
                st.data_stack.push(-200);
                Ok(TrapHandled::Handled)
            })));
        // Populate the number stack, with a value (50), and the trap number (100)
1
        sm.st.data_stack.extend_from_slice(&[50, 100]);
        // Put the opcodes into the *memory*
1
        sm.st
            .opcodes
            .extend_from_slice(&[Opcode::TRAP, Opcode::RET]);
        // Execute the instructions
1
        sm.execute(0, GasLimit::Limited(100)).unwrap();
1
        assert_eq!(sm.st.data_stack, vec![200]);
2
    }
    #[test]
2
    fn test_unhandled_trap_1() {
1
        let mut sm = StackMachine::new();
        // Populate the number stack, with a value (50), and the trap number (100)
1
        sm.st.data_stack.extend_from_slice(&[50, 100]);
        // Put the opcodes into the *memory*
1
        sm.st
            .opcodes
            .extend_from_slice(&[Opcode::TRAP, Opcode::RET]);
        // Execute the instructions
1
        match sm.execute(0, GasLimit::Limited(100)) {
            Err(StackMachineError::UnhandledTrap) => (),
            r => panic!("Incorrect error type returned {:?}", r),
        }
2
    }
}