Skip to content
Snippets Groups Projects
Commit 7889b2b2 authored by MarvelousAnything's avatar MarvelousAnything
Browse files

Did some work. I am committing to push to github.

parent 81a13dd1
No related branches found
No related tags found
No related merge requests found
use std::fmt::Debug; use std::fmt::Debug;
use crate::function::Function; use crate::function::Function;
use crate::native::NativeFunction; use crate::native::NativeFunction;
use crate::stack::StackHolder;
use crate::tvm::Tvm; use crate::tvm::Tvm;
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum Callable { pub enum Callable {
Function(Function), Function(Function),
NativeFunction(NativeFunction), Native(NativeFunction),
}
impl Callable {
pub fn get_callable(id: i32) -> Self {
match id {
n if n < -111 => panic!("Invalid callable id: {}", n),
n @ -111..=-101 => Callable::Native(NativeFunction::get_native(n)),
n if n >= 0 => Callable::Function(Function::get_function(n as usize)),
_ => unreachable!(),
}
}
pub fn get_id(&self) -> i32 {
match self {
Callable::Function(function) => function.id as i32,
Callable::Native(native) => native.get_id(),
}
}
} }
pub trait Caller: Debug + Clone { pub trait Caller: Debug + Clone {
fn call(callable: Callable); fn do_call(&mut self, callable: Callable);
} }
impl Caller for Tvm { impl Caller for Tvm {
fn call(callable: Callable) { fn do_call(&mut self, callable: Callable) {
match callable { match callable {
Callable::Function(function) => { Callable::Function(function) => {
println!("Calling function: {:?}", function); println!("Calling function: {:?}", function);
self.push(0);
},
Callable::Native(native_function) => {
match native_function {
NativeFunction::IPrint { .. } => {
let value = self.pop();
println!("stdout: {}", value);
self.push(0);
}, },
Callable::NativeFunction(native_function) => { NativeFunction::Alloc { .. } => {
println!("Calling native function: {:?}", native_function); let size = self.pop();
self.push(self.heap_size as i32);
self.heap_size += size as usize;
println!("Allocating {} bytes", size);
},
_ => println!("Calling native function: {:?}", native_function),
}
}, },
} }
} }
......
use crate::callable::Callable; use crate::callable::Callable;
use crate::instruction::Instruction; use crate::instruction::Instruction;
use crate::state::{Stateful, StateResult};
use crate::state::StateResult::Continue;
use crate::tvm::Tvm; use crate::tvm::Tvm;
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
...@@ -8,6 +10,14 @@ pub struct Frame { ...@@ -8,6 +10,14 @@ pub struct Frame {
pub name: String, pub name: String,
pub data: Vec<FrameData>, pub data: Vec<FrameData>,
pub pc: usize, pub pc: usize,
pub previous_frame: Option<Box<Frame>>,
pub result: Option<StateResult>,
}
impl Frame {
pub fn builder() -> FrameBuilder {
FrameBuilder::new()
}
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
...@@ -18,12 +28,80 @@ pub enum FrameData { ...@@ -18,12 +28,80 @@ pub enum FrameData {
Primitive(i32), Primitive(i32),
} }
impl FrameData {
pub fn get_id(&self) -> i32 {
match self {
FrameData::Frame(frame) => frame.id as i32,
FrameData::Callable(callable, _) => callable.get_id(),
FrameData::Instruction(instruction, _) => instruction.get_op() as i32,
FrameData::Primitive(value) => *value,
}
}
}
pub trait FrameEvaluator { pub trait FrameEvaluator {
fn eval_frame(&mut self, frame: Frame); fn do_frame_eval(&mut self, frame: &Frame);
} }
impl FrameEvaluator for Tvm { impl FrameEvaluator for Tvm {
fn eval_frame(&mut self, frame: Frame) { fn do_frame_eval(&mut self, frame: &Frame) {
println!("Evaluating frame: {:?}", frame); println!("Evaluating frame: {:?}", frame);
if self.should_continue() {
self.eval(frame.clone());
}
}
}
#[derive(Default)]
pub struct FrameBuilder {
id: usize,
name: String,
data: Vec<FrameData>,
}
impl FrameBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn id(mut self, id: usize) -> Self {
self.id = id;
self
}
pub fn name(mut self, name: String) -> Self {
self.name = name;
self
}
pub fn frame(mut self, frame: Frame) -> Self {
self.data.push(FrameData::Frame(frame));
self
}
pub fn callable(mut self, callable: i32, args: Vec<i32>) -> Self {
self.data.push(FrameData::Callable(Callable::get_callable(callable), args));
self
}
pub fn instruction(mut self, instruction: Instruction, args: Vec<i32>) -> Self {
self.data.push(FrameData::Instruction(instruction, args));
self
}
pub fn primitive(mut self, primitive: i32) -> Self {
self.data.push(FrameData::Primitive(primitive));
self
}
pub fn build(self) -> Frame {
Frame {
id: self.id,
name: self.name,
data: self.data,
pc: 0,
previous_frame: None,
result: None
}
} }
} }
\ No newline at end of file
...@@ -8,3 +8,22 @@ pub struct Function { ...@@ -8,3 +8,22 @@ pub struct Function {
pub locals: usize, pub locals: usize,
pub frame: Frame, pub frame: Frame,
} }
impl Function {
pub(crate) fn get_function(id: usize) -> Function {
Function {
id,
name: "test-function".to_string(),
args: 0,
locals: 0,
frame: Frame {
id: 0,
name: "test-frame".to_string(),
data: vec![],
pc: 0,
previous_frame: None,
result: None,
}
}
}
}
\ No newline at end of file
use std::cell::RefCell;
use std::fmt::Debug; use std::fmt::Debug;
use std::rc::Rc;
use crate::callable::Callable;
use crate::frame::{Frame, FrameData};
use crate::stack::StackHolder;
use crate::state::{Stateful, StateResult};
use crate::state::StateResult::Exit;
use crate::tvm::Tvm; use crate::tvm::Tvm;
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
...@@ -33,12 +40,250 @@ pub enum Instruction { ...@@ -33,12 +40,250 @@ pub enum Instruction {
Unknown(u32), Unknown(u32),
} }
impl Instruction {
pub fn get_instruction(op_code: u32) -> Instruction {
match op_code {
1 => Instruction::Push {
op: 1,
name: "push".to_string(),
num_operands: 0
},
2 => Instruction::Fetch {
op: 2,
name: "fetch".to_string(),
num_operands: 0
},
3 => Instruction::Store {
op: 3,
name: "store".to_string(),
num_operands: 0
},
4 => Instruction::IF {
op: 4,
name: "if".to_string(),
num_operands: 0
},
5 => Instruction::Loop {
op: 5,
name: "loop".to_string(),
num_operands: 0
},
6 => Instruction::Break {
op: 6,
name: "break".to_string(),
num_operands: 0
},
7 => Instruction::Return {
op: 7,
name: "return".to_string(),
num_operands: 0
},
8 => Instruction::Call {
op: 8,
name: "call".to_string(),
num_operands: 0
},
9 => Instruction::FPPlus {
op: 9,
name: "fp+".to_string(),
num_operands: 0
},
10 => Instruction::Add {
op: 10,
name: "+".to_string(),
num_operands: 0
},
11 => Instruction::Sub {
op: 11,
name: "-".to_string(),
num_operands: 0
},
12 => Instruction::Mul {
op: 12,
name: "*".to_string(),
num_operands: 0
},
13 => Instruction::Div {
op: 13,
name: "/".to_string(),
num_operands: 0
},
14 => Instruction::Mod {
op: 14,
name: "%".to_string(),
num_operands: 0
},
15 => Instruction::Not {
op: 15,
name: "!".to_string(),
num_operands: 0
},
16 => Instruction::And {
op: 16,
name: "&".to_string(),
num_operands: 0
},
17 => Instruction::OR {
op: 17,
name: "|".to_string(),
num_operands: 0
},
18 => Instruction::Xor {
op: 18,
name: "^".to_string(),
num_operands: 0
},
19 => Instruction::EQ {
op: 19,
name: "==".to_string(),
num_operands: 0
},
20 => Instruction::Neq {
op: 20,
name: "!=".to_string(),
num_operands: 0
},
21 => Instruction::LT {
op: 21,
name: "<".to_string(),
num_operands: 0
},
22 => Instruction::Leq {
op: 22,
name: "<=".to_string(),
num_operands: 0
},
23 => Instruction::GT {
op: 23,
name: ">".to_string(),
num_operands: 0
},
24 => Instruction::Geq {
op: 24,
name: ">=".to_string(),
num_operands: 0
},
25 => Instruction::Pop {
op: 25,
name: "pop".to_string(),
num_operands: 0
},
26 => Instruction::LShift {
op: 26,
name: "<<".to_string(),
num_operands: 0
},
27 => Instruction::RShift {
op: 27,
name: ">>".to_string(),
num_operands: 0
},
_ => Instruction::Unknown(op_code),
}
}
pub fn get_op(&self) -> u32 {
match self {
Instruction::Push { op, .. } => *op,
Instruction::Fetch { op, .. } => *op,
Instruction::Store { op, .. } => *op,
Instruction::IF { op, .. } => *op,
Instruction::Loop { op, .. } => *op,
Instruction::Break { op, .. } => *op,
Instruction::Return { op, .. } => *op,
Instruction::Call { op, .. } => *op,
Instruction::FPPlus { op, .. } => *op,
Instruction::Add { op, .. } => *op,
Instruction::Sub { op, .. } => *op,
Instruction::Mul { op, .. } => *op,
Instruction::Div { op, .. } => *op,
Instruction::Mod { op, .. } => *op,
Instruction::Not { op, .. } => *op,
Instruction::And { op, .. } => *op,
Instruction::OR { op, .. } => *op,
Instruction::Xor { op, .. } => *op,
Instruction::EQ { op, .. } => *op,
Instruction::Neq { op, .. } => *op,
Instruction::LT { op, .. } => *op,
Instruction::Leq { op, .. } => *op,
Instruction::GT { op, .. } => *op,
Instruction::Geq { op, .. } => *op,
Instruction::Pop { op, .. } => *op,
Instruction::LShift { op, .. } => *op,
Instruction::RShift { op, .. } => *op,
Instruction::Unknown(op) => *op,
}
}
}
pub trait Evaluator: Debug + Clone { pub trait Evaluator: Debug + Clone {
fn eval(&mut self, instruction: Instruction); fn do_eval(&mut self, frame: &mut Frame);
} }
impl Evaluator for Tvm { impl Evaluator for Tvm {
fn eval(&mut self, instruction: Instruction) { fn do_eval(&mut self, frame: &mut Frame) {
if frame.pc >= frame.data.len() {
self.last_result = Some(Exit);
return;
}
let data = &frame.data.get(frame.pc).unwrap();
frame.pc += 1;
match data {
FrameData::Frame(frame) => {
self.frame_eval(frame.clone())
},
FrameData::Instruction(instruction, ..) => {
println!("Evaluating instruction: {:?}", instruction); println!("Evaluating instruction: {:?}", instruction);
match instruction {
Instruction::Push { .. } => {
let x = &frame.data[frame.pc].get_id();
self.push(*x);
frame.pc += 1;
}
Instruction::Fetch { .. } => {
let index = self.pop();
self.push(self.memory[index as usize]);
}
Instruction::Store { .. } => {}
Instruction::IF { .. } => {}
Instruction::Loop { .. } => {}
Instruction::Break { .. } => {}
Instruction::Return { .. } => {}
Instruction::Call { .. } => {
let id = &frame.data[frame.pc].get_id();
let callable = Callable::get_callable(*id);
self.call(callable);
frame.pc += 1;
}
Instruction::FPPlus { .. } => {}
Instruction::Add { .. } => {}
Instruction::Sub { .. } => {}
Instruction::Mul { .. } => {}
Instruction::Div { .. } => {}
Instruction::Mod { .. } => {}
Instruction::Not { .. } => {}
Instruction::And { .. } => {}
Instruction::OR { .. } => {}
Instruction::Xor { .. } => {}
Instruction::EQ { .. } => {}
Instruction::Neq { .. } => {}
Instruction::LT { .. } => {}
Instruction::Leq { .. } => {}
Instruction::GT { .. } => {}
Instruction::Geq { .. } => {}
Instruction::Pop { .. } => {}
Instruction::LShift { .. } => {}
Instruction::RShift { .. } => {}
Instruction::Unknown(_) => {}
}
},
FrameData::Callable(callable, ..) => {
println!("Evaluating callable: {:?}", callable);
self.call(callable.clone())
},
FrameData::Primitive(primitive) => {
println!("Primitive: {:?}", primitive);
}
}
} }
} }
\ No newline at end of file
use crate::state::Stateful;
use crate::tvm::Tvm; use crate::tvm::Tvm;
mod tvm; mod tvm;
...@@ -12,6 +13,16 @@ mod function; ...@@ -12,6 +13,16 @@ mod function;
mod instruction; mod instruction;
fn main() { fn main() {
let tvm = Tvm::default(); use std::io::{ stdin ,stdout, Write};
println!("{:?}", tvm); let mut s = String::new();
let _ = stdout().flush();
let mut tvm = Tvm::default();
tvm.start();
loop {
stdin().read_line(&mut s).expect("Did not enter a correct string");
if !s.is_empty() {
print!("Tick {}:\t\t", tvm.ticks);
tvm.tick();
}
}
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct NativeFunction { pub enum NativeFunction {
pub id: i32, IPrint { id: i32, name: String, args: u32 },
pub name: String, SPrint { id: i32, name: String, args: u32 },
pub args: usize, IRead { id: i32, name: String, args: u32 },
SRead { id: i32, name: String, args: u32 },
NL { id: i32, name: String, args: u32 },
Random { id: i32, name: String, args: u32 },
Timer { id: i32, name: String, args: u32 },
StopTimer { id: i32, name: String, args: u32 },
Alloc { id: i32, name: String, args: u32 },
Free { id: i32, name: String, args: u32 },
I2S { id: i32, name: String, args: u32 },
Unknown(i32),
}
impl NativeFunction {
pub fn get_native(id: i32) -> Self {
match id {
-101 => NativeFunction::IPrint {
id,
name: "iprint".to_string(),
args: 1,
},
-102 => NativeFunction::SPrint {
id,
name: "sprint".to_string(),
args: 1,
},
-103 => NativeFunction::IRead {
id,
name: "iread".to_string(),
args: 1,
},
-104 => NativeFunction::SRead {
id,
name: "sread".to_string(),
args: 2,
},
-105 => NativeFunction::NL {
id,
name: "nl".to_string(),
args: 0,
},
-106 => NativeFunction::Random {
id,
name: "random".to_string(),
args: 1,
},
-107 => NativeFunction::Timer {
id,
name: "timer".to_string(),
args: 2,
},
-108 => NativeFunction::StopTimer {
id,
name: "stoptimer".to_string(),
args: 1,
},
-109 => NativeFunction::Alloc {
id,
name: "alloc".to_string(),
args: 1,
},
-110 => NativeFunction::Free {
id,
name: "free".to_string(),
args: 1,
},
-111 => NativeFunction::I2S {
id,
name: "i2s".to_string(),
args: 1,
},
n => NativeFunction::Unknown(n),
}
}
pub fn get_id(&self) -> i32 {
match self {
NativeFunction::IPrint { id, .. } => *id,
NativeFunction::SPrint { id, .. } => *id,
NativeFunction::IRead { id, .. } => *id,
NativeFunction::SRead { id, .. } => *id,
NativeFunction::NL { id, .. } => *id,
NativeFunction::Random { id, .. } => *id,
NativeFunction::Timer { id, .. } => *id,
NativeFunction::StopTimer { id, .. } => *id,
NativeFunction::Alloc { id, .. } => *id,
NativeFunction::Free { id, .. } => *id,
NativeFunction::I2S { id, .. } => *id,
NativeFunction::Unknown(n) => *n,
}
}
} }
\ No newline at end of file
...@@ -23,11 +23,13 @@ impl StackHolder for Tvm { ...@@ -23,11 +23,13 @@ impl StackHolder for Tvm {
} }
fn pop(&mut self) -> i32 { fn pop(&mut self) -> i32 {
println!("Popping from stack");
self.stack_pointer += 1; self.stack_pointer += 1;
self.memory[self.stack_pointer] self.memory[self.stack_pointer]
} }
fn push(&mut self, value: i32) { fn push(&mut self, value: i32) {
println!("Pushing {} to stack", value);
self.memory[self.stack_pointer] = value; self.memory[self.stack_pointer] = value;
self.stack_pointer -= 1; self.stack_pointer -= 1;
} }
......
use std::fmt::Debug; use std::fmt::Debug;
use std::rc::Rc;
use crate::callable::Callable; use crate::callable::Callable;
use crate::frame::Frame; use crate::frame::Frame;
use crate::tvm::Tvm; use crate::tvm::Tvm;
...@@ -12,6 +13,7 @@ pub enum StateResult { ...@@ -12,6 +13,7 @@ pub enum StateResult {
Return(i32), Return(i32),
Break, Break,
Continue, Continue,
Exit,
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
...@@ -19,7 +21,7 @@ pub enum TvmState { ...@@ -19,7 +21,7 @@ pub enum TvmState {
Waiting, Waiting,
Paused, Paused,
Call(Callable), Call(Callable),
Eval(Frame, usize), Eval(Frame),
FrameEval(Frame), FrameEval(Frame),
Halted, Halted,
} }
...@@ -30,7 +32,7 @@ impl TvmState { ...@@ -30,7 +32,7 @@ impl TvmState {
TvmState::Waiting => Box::new(states::Waiting), TvmState::Waiting => Box::new(states::Waiting),
TvmState::Paused => Box::new(states::Paused), TvmState::Paused => Box::new(states::Paused),
TvmState::Call(callable) => Box::new(states::Call { callable: callable.clone() }), TvmState::Call(callable) => Box::new(states::Call { callable: callable.clone() }),
TvmState::Eval(frame, pc) => Box::new(states::Eval { frame: frame.clone(), pc: *pc }), TvmState::Eval(frame) => Box::new(states::Eval { frame: frame.clone(), pc: 0 }),
TvmState::FrameEval(frame) => Box::new(states::FrameEval { frame: frame.clone() }), TvmState::FrameEval(frame) => Box::new(states::FrameEval { frame: frame.clone() }),
TvmState::Halted => Box::new(states::Halted), TvmState::Halted => Box::new(states::Halted),
} }
...@@ -49,7 +51,7 @@ impl TvmState { ...@@ -49,7 +51,7 @@ impl TvmState {
} }
pub fn is_eval(&self) -> bool { pub fn is_eval(&self) -> bool {
matches!(self, TvmState::Eval(_, _)) matches!(self, TvmState::Eval(_))
} }
pub fn is_frame_eval(&self) -> bool { pub fn is_frame_eval(&self) -> bool {
...@@ -73,6 +75,25 @@ pub trait Stateful : Debug { ...@@ -73,6 +75,25 @@ pub trait Stateful : Debug {
fn get_last_result(&self) -> Option<StateResult>; fn get_last_result(&self) -> Option<StateResult>;
fn is_paused(&self) -> bool; fn is_paused(&self) -> bool;
fn handle_result(&mut self, result: StateResult); fn handle_result(&mut self, result: StateResult);
fn call(&mut self, callable: Callable) {
self.set_state(TvmState::Call(callable));
}
fn eval(&mut self, frame: Frame) {
self.set_state(TvmState::Eval(frame));
}
fn frame_eval(&mut self, frame: Frame) {
self.set_state(TvmState::FrameEval(frame));
}
fn should_continue(&self) -> bool {
!self.get_state().is_halted()
|| matches!(self.get_last_result(), Some(StateResult::Exit))
|| matches!(self.get_last_result(), Some(StateResult::Break))
|| matches!(self.get_last_result(), Some(StateResult::Return(_)))
}
} }
impl Stateful for Tvm { impl Stateful for Tvm {
...@@ -81,6 +102,7 @@ impl Stateful for Tvm { ...@@ -81,6 +102,7 @@ impl Stateful for Tvm {
} }
fn set_state(&mut self, state: TvmState) { fn set_state(&mut self, state: TvmState) {
println!("Setting state to: {:?}", state);
self.previous_state = Some(self.state.clone()); self.previous_state = Some(self.state.clone());
self.state = state; self.state = state;
} }
...@@ -110,15 +132,23 @@ impl Stateful for Tvm { ...@@ -110,15 +132,23 @@ impl Stateful for Tvm {
} }
fn tick(&mut self) { fn tick(&mut self) {
// Do nothing if the tvm is paused
if !self.is_paused() {
self.increment_ticks();
self.state.to_state().tick(self);
let result = self.get_last_result();
self.handle_result(result.unwrap());
}
println!("Tvm state: {:?}", self.state);
} }
fn get_last_result(&self) -> Option<StateResult> { fn get_last_result(&self) -> Option<StateResult> {
todo!() self.last_result.clone()
} }
fn is_paused(&self) -> bool { fn is_paused(&self) -> bool {
self.state == TvmState::Paused matches!(self.state, TvmState::Paused)
} }
fn handle_result(&mut self, result: StateResult) { fn handle_result(&mut self, result: StateResult) {
...@@ -127,6 +157,10 @@ impl Stateful for Tvm { ...@@ -127,6 +157,10 @@ impl Stateful for Tvm {
} }
pub mod states { pub mod states {
use crate::callable::Caller;
use crate::frame::FrameEvaluator;
use crate::instruction::Evaluator;
use crate::state::StateResult::{Continue, Exit};
use super::*; use super::*;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
...@@ -152,40 +186,46 @@ pub mod states { ...@@ -152,40 +186,46 @@ pub mod states {
impl State for Waiting { impl State for Waiting {
// Tick should do nothing. // Tick should do nothing.
fn tick(&mut self, tvm: &mut Tvm) -> StateResult { fn tick(&mut self, tvm: &mut Tvm) -> StateResult {
StateResult::Continue Continue
} }
} }
impl State for Paused { impl State for Paused {
// Tick should do nothing. // Tick should do nothing.
fn tick(&mut self, tvm: &mut Tvm) -> StateResult { fn tick(&mut self, tvm: &mut Tvm) -> StateResult {
StateResult::Continue Continue
} }
} }
impl State for Call { impl State for Call {
fn tick(&mut self, tvm: &mut Tvm) -> StateResult { fn tick(&mut self, tvm: &mut Tvm) -> StateResult {
unimplemented!() tvm.do_call(self.callable.clone());
Continue
} }
} }
impl State for Eval { impl State for Eval {
fn tick(&mut self, tvm: &mut Tvm) -> StateResult { fn tick(&mut self, tvm: &mut Tvm) -> StateResult {
unimplemented!() if tvm.should_continue() {
tvm.do_eval(&mut self.frame);
self.pc = self.frame.pc;
}
Exit
} }
} }
impl State for FrameEval { impl State for FrameEval {
fn tick(&mut self, tvm: &mut Tvm) -> StateResult { fn tick(&mut self, tvm: &mut Tvm) -> StateResult {
unimplemented!() if tvm.should_continue() {
tvm.do_frame_eval(&self.frame);
}
Exit
} }
} }
impl State for Halted { impl State for Halted {
fn tick(&mut self, tvm: &mut Tvm) -> StateResult { fn tick(&mut self, tvm: &mut Tvm) -> StateResult {
unimplemented!() Continue
} }
} }
} }
use crate::frame::Frame; use crate::frame::Frame;
use crate::state::{StateResult, TvmState}; use crate::instruction::Instruction;
use crate::state::{Stateful, StateResult, TvmState};
use crate::state::StateResult::Continue;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Tvm { pub struct Tvm {
...@@ -23,19 +25,33 @@ impl Default for Tvm { ...@@ -23,19 +25,33 @@ impl Default for Tvm {
state: TvmState::Waiting, state: TvmState::Waiting,
ticks: 0, ticks: 0,
previous_state: None, previous_state: None,
last_result: None, last_result: Some(Continue),
} }
} }
} }
impl Tvm { impl Tvm {
pub fn frame_eval(&mut self, frame: Frame) {
self.state = TvmState::FrameEval(frame); pub fn start(&mut self) {
let builder = Frame::builder();
let frame = builder
.id(0)
.name("main".to_string())
.instruction(Instruction::get_instruction(1), vec![])
.primitive(0)
.callable(-101, vec![])
.instruction(Instruction::get_instruction(8), vec![])
.primitive(-109)
.primitive(10)
.build();
self.frame_eval(frame);
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::state::Stateful;
use super::*; use super::*;
#[test] #[test]
...@@ -49,4 +65,23 @@ mod test { ...@@ -49,4 +65,23 @@ mod test {
assert_eq!(tvm.ticks, 0); assert_eq!(tvm.ticks, 0);
assert_eq!(tvm.previous_state, None); assert_eq!(tvm.previous_state, None);
} }
#[test]
fn test_tick_count() {
let mut tvm = Tvm::default();
tvm.tick();
tvm.tick();
tvm.tick();
tvm.tick();
tvm.tick();
tvm.tick();
tvm.tick();
tvm.tick();
tvm.tick();
tvm.tick();
tvm.tick();
tvm.tick();
assert_eq!(tvm.ticks, 12);
}
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment