Add arithmeticexpression
This commit is contained in:
parent
ec32e55357
commit
00619f09fd
@ -1,2 +1,3 @@
|
|||||||
let gotus = "Hello, world!";
|
let number = 2 + 5 * 2 + 5 + 1 * 10 + 1;
|
||||||
print(gotus);
|
let text = "" + number;
|
||||||
|
print(text);
|
@ -3,23 +3,42 @@ use std::collections::HashMap;
|
|||||||
use std::num::ParseIntError;
|
use std::num::ParseIntError;
|
||||||
|
|
||||||
use super::errors::CompilerError;
|
use super::errors::CompilerError;
|
||||||
use super::parser::{Expression, LiteralPattern, ParsedReid, Pattern, Statement};
|
use super::parser::{
|
||||||
|
ArithmeticExpression, Expression, LiteralPattern, ParsedReid, Pattern, Statement,
|
||||||
|
};
|
||||||
|
use super::vm::VariableType::*;
|
||||||
use super::vm::{Command, CompiledReid, FuncID, FunctionSignature, HeapID, Position, VariableType};
|
use super::vm::{Command, CompiledReid, FuncID, FunctionSignature, HeapID, Position, VariableType};
|
||||||
|
|
||||||
pub type Variable = (HeapID, VariableType);
|
pub type Variable = (HeapID, VariableType);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum ArithmeticOp {
|
||||||
|
Add(VariableType, VariableType, VariableType),
|
||||||
|
Subtract(VariableType, VariableType, VariableType),
|
||||||
|
Mult(VariableType, VariableType, VariableType),
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Compiler {
|
pub struct Compiler {
|
||||||
parsed: ParsedReid,
|
parsed: ParsedReid,
|
||||||
root_scope: Scope,
|
root_scope: Scope,
|
||||||
list: Vec<Command>,
|
list: Vec<Command>,
|
||||||
|
possible_arit_possib: Vec<ArithmeticOp>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Compiler {
|
impl Compiler {
|
||||||
pub fn from(parsed: ParsedReid) -> Compiler {
|
pub fn from(parsed: ParsedReid) -> Compiler {
|
||||||
|
let list = vec![
|
||||||
|
ArithmeticOp::Add(TypeI32, TypeI32, TypeI32),
|
||||||
|
ArithmeticOp::Subtract(TypeI32, TypeI32, TypeI32),
|
||||||
|
ArithmeticOp::Mult(TypeI32, TypeI32, TypeI32),
|
||||||
|
ArithmeticOp::Add(TypeString, TypeI32, TypeString),
|
||||||
|
ArithmeticOp::Add(TypeString, TypeString, TypeString),
|
||||||
|
];
|
||||||
Compiler {
|
Compiler {
|
||||||
parsed,
|
parsed,
|
||||||
root_scope: Scope::default(),
|
root_scope: Scope::default(),
|
||||||
list: Vec::new(),
|
list: Vec::new(),
|
||||||
|
possible_arit_possib: list,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +95,9 @@ impl Compiler {
|
|||||||
Err(CompilerError::FunctionNotFound(pos, name, arguments))
|
Err(CompilerError::FunctionNotFound(pos, name, arguments))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Expression::ArithmeticExpression(pos, val) => {
|
||||||
|
self.handle_arithmetic_expression(pos, *val)
|
||||||
|
}
|
||||||
Expression::ValueRef(_, val) => match val {
|
Expression::ValueRef(_, val) => match val {
|
||||||
Pattern::IdentPattern(pos, ident) => {
|
Pattern::IdentPattern(pos, ident) => {
|
||||||
if let Some(var) = self.root_scope.get(ident.clone()) {
|
if let Some(var) = self.root_scope.get(ident.clone()) {
|
||||||
@ -94,6 +116,77 @@ impl Compiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_arithmetic_expression(
|
||||||
|
&mut self,
|
||||||
|
pos: Position,
|
||||||
|
exp: ArithmeticExpression,
|
||||||
|
) -> Result<Option<VariableType>, CompilerError> {
|
||||||
|
let (exp1, exp2) = match exp.clone() {
|
||||||
|
ArithmeticExpression::Add(e1, e2) => (e1, e2),
|
||||||
|
ArithmeticExpression::Subtract(e1, e2) => (e1, e2),
|
||||||
|
ArithmeticExpression::Mult(e1, e2) => (e1, e2),
|
||||||
|
};
|
||||||
|
let type1 = self.handle_expression(exp1)?;
|
||||||
|
let type2 = self.handle_expression(exp2)?;
|
||||||
|
if let (Some(type1), Some(type2)) = (type1, type2) {
|
||||||
|
let mut return_type = None;
|
||||||
|
for op in &self.possible_arit_possib {
|
||||||
|
match op {
|
||||||
|
ArithmeticOp::Add(t1, t2, t3) => {
|
||||||
|
if let ArithmeticExpression::Add(..) = exp {
|
||||||
|
if (t1 == &type1 && t2 == &type2) || (t2 == &type1 && t1 == &type2) {
|
||||||
|
return_type = Some(t3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ArithmeticOp::Subtract(t1, t2, t3) => {
|
||||||
|
if let ArithmeticExpression::Subtract(..) = exp {
|
||||||
|
if (t1 == &type1 && t2 == &type2) || (t2 == &type1 && t1 == &type2) {
|
||||||
|
return_type = Some(t3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ArithmeticOp::Mult(t1, t2, t3) => {
|
||||||
|
if let ArithmeticExpression::Mult(..) = exp {
|
||||||
|
if (t1 == &type1 && t2 == &type2) || (t2 == &type1 && t1 == &type2) {
|
||||||
|
return_type = Some(t3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let (command, error) = match exp {
|
||||||
|
ArithmeticExpression::Add(..) => {
|
||||||
|
(Command::Add, ArithmeticOp::Add(type1, type2, TypeI32))
|
||||||
|
}
|
||||||
|
ArithmeticExpression::Subtract(..) => (
|
||||||
|
Command::Subtract,
|
||||||
|
ArithmeticOp::Subtract(type1, type2, TypeI32),
|
||||||
|
),
|
||||||
|
ArithmeticExpression::Mult(..) => {
|
||||||
|
(Command::Mult, ArithmeticOp::Subtract(type1, type2, TypeI32))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Some(t) = return_type {
|
||||||
|
self.list.push(command);
|
||||||
|
Ok(Some(*t))
|
||||||
|
} else {
|
||||||
|
Err(CompilerError::ArithmeticExpressionFailed(
|
||||||
|
pos,
|
||||||
|
Box::new(CompilerError::InvalidArithmeticOperation(error)),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(CompilerError::ArithmeticExpressionFailed(
|
||||||
|
pos,
|
||||||
|
Box::new(CompilerError::CanNotAssignVoidType),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_statement(
|
fn handle_statement(
|
||||||
&mut self,
|
&mut self,
|
||||||
statement: Statement,
|
statement: Statement,
|
||||||
|
@ -5,6 +5,9 @@ use std::io;
|
|||||||
#[cfg(feature = "compiler")]
|
#[cfg(feature = "compiler")]
|
||||||
use std::num::ParseIntError;
|
use std::num::ParseIntError;
|
||||||
|
|
||||||
|
#[cfg(feature = "compiler")]
|
||||||
|
use super::compiler::ArithmeticOp;
|
||||||
|
|
||||||
#[cfg(feature = "compiler")]
|
#[cfg(feature = "compiler")]
|
||||||
use super::vm::Position;
|
use super::vm::Position;
|
||||||
use super::vm::VariableType;
|
use super::vm::VariableType;
|
||||||
@ -113,6 +116,8 @@ pub enum CompilerError {
|
|||||||
CanNotAssignVoidType,
|
CanNotAssignVoidType,
|
||||||
FunctionNotFound(Position, String, Vec<VariableType>),
|
FunctionNotFound(Position, String, Vec<VariableType>),
|
||||||
ParseIntError(ParseIntError),
|
ParseIntError(ParseIntError),
|
||||||
|
ArithmeticExpressionFailed(Position, Box<CompilerError>),
|
||||||
|
InvalidArithmeticOperation(ArithmeticOp),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "compiler")]
|
#[cfg(feature = "compiler")]
|
||||||
@ -140,6 +145,23 @@ impl Display for CompilerError {
|
|||||||
pos
|
pos
|
||||||
),
|
),
|
||||||
CompilerError::ParseIntError(err) => format!("Failed to parse integer value: {}", err),
|
CompilerError::ParseIntError(err) => format!("Failed to parse integer value: {}", err),
|
||||||
|
CompilerError::ArithmeticExpressionFailed(pos, err) => {
|
||||||
|
format!("Arithmetic expression failed at {}:\n {}", pos, err)
|
||||||
|
}
|
||||||
|
CompilerError::InvalidArithmeticOperation(op) => {
|
||||||
|
let text = match op {
|
||||||
|
ArithmeticOp::Add(t1, t2, _) => {
|
||||||
|
format!("{} + {}", t1.to_string(), t2.to_string())
|
||||||
|
}
|
||||||
|
ArithmeticOp::Subtract(t1, t2, _) => {
|
||||||
|
format!("{} - {}", t1.to_string(), t2.to_string())
|
||||||
|
}
|
||||||
|
ArithmeticOp::Mult(t1, t2, _) => {
|
||||||
|
format!("{} * {}", t1.to_string(), t2.to_string())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
format!("Invalid arithmetic operation: {}", text)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
write!(f, "{}", text)
|
write!(f, "{}", text)
|
||||||
}
|
}
|
||||||
@ -175,4 +197,5 @@ pub enum RuntimePanic {
|
|||||||
ValueNotInitialized,
|
ValueNotInitialized,
|
||||||
InvalidTypeAssign,
|
InvalidTypeAssign,
|
||||||
InvalidFuncAddress,
|
InvalidFuncAddress,
|
||||||
|
AttemptedInvalidArithmeticOperation,
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,9 @@ impl Command {
|
|||||||
Command::StringLit(..) => 7,
|
Command::StringLit(..) => 7,
|
||||||
Command::I32Lit(..) => 8,
|
Command::I32Lit(..) => 8,
|
||||||
Command::FunctionCall(..) => 9,
|
Command::FunctionCall(..) => 9,
|
||||||
|
Command::Add => 10,
|
||||||
|
Command::Subtract => 11,
|
||||||
|
Command::Mult => 12,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +131,9 @@ impl Command {
|
|||||||
let funcid = u16::from_be_bytes([*iter.next()?, *iter.next()?]);
|
let funcid = u16::from_be_bytes([*iter.next()?, *iter.next()?]);
|
||||||
Some(Command::FunctionCall(funcid))
|
Some(Command::FunctionCall(funcid))
|
||||||
}
|
}
|
||||||
|
10 => Some(Command::Add),
|
||||||
|
11 => Some(Command::Subtract),
|
||||||
|
12 => Some(Command::Mult),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,6 +173,9 @@ impl Command {
|
|||||||
let funcid = funcid.to_be_bytes();
|
let funcid = funcid.to_be_bytes();
|
||||||
list.append(&mut vec![funcid[0], funcid[1]]);
|
list.append(&mut vec![funcid[0], funcid[1]]);
|
||||||
}
|
}
|
||||||
|
Command::Add => (),
|
||||||
|
Command::Subtract => (),
|
||||||
|
Command::Mult => (),
|
||||||
}
|
}
|
||||||
list
|
list
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ impl Statement {
|
|||||||
parser
|
parser
|
||||||
.expect_static("=")
|
.expect_static("=")
|
||||||
.get_or(SyntaxError::ExpectedToken(pos, '='))?;
|
.get_or(SyntaxError::ExpectedToken(pos, '='))?;
|
||||||
match Expression::parse(parser) {
|
match Expression::parse(parser, true) {
|
||||||
Ok(expr) => {
|
Ok(expr) => {
|
||||||
parser
|
parser
|
||||||
.expect_static(";")
|
.expect_static(";")
|
||||||
@ -32,7 +32,7 @@ impl Statement {
|
|||||||
Err(err) => Err(SyntaxError::ExpectedExpression(pos, Some(Box::new(err)))),
|
Err(err) => Err(SyntaxError::ExpectedExpression(pos, Some(Box::new(err)))),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match Expression::parse(parser) {
|
match Expression::parse(parser, true) {
|
||||||
Ok(expr) => {
|
Ok(expr) => {
|
||||||
let statement = Statement::ExprStatement(pos, expr);
|
let statement = Statement::ExprStatement(pos, expr);
|
||||||
parser
|
parser
|
||||||
@ -50,14 +50,15 @@ impl Statement {
|
|||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
BlockExpr(Position, Vec<Statement>),
|
BlockExpr(Position, Vec<Statement>),
|
||||||
FunctionCall(Position, Ident, Vec<Expression>),
|
FunctionCall(Position, Ident, Vec<Expression>),
|
||||||
|
ArithmeticExpression(Position, Box<ArithmeticExpression>),
|
||||||
ValueRef(Position, Pattern),
|
ValueRef(Position, Pattern),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
pub fn parse(parser: &mut Parser) -> Result<Expression, SyntaxError> {
|
pub fn parse(parser: &mut Parser, allow_arithmetic: bool) -> Result<Expression, SyntaxError> {
|
||||||
let begin_pos = parser.pos();
|
let begin_pos = parser.pos();
|
||||||
|
|
||||||
if parser.expect_static("{").get().is_some() {
|
let first = if parser.expect_static("{").get().is_some() {
|
||||||
let mut statement_list = Vec::new();
|
let mut statement_list = Vec::new();
|
||||||
while {
|
while {
|
||||||
match Statement::parse(parser) {
|
match Statement::parse(parser) {
|
||||||
@ -78,7 +79,7 @@ impl Expression {
|
|||||||
let name = texts.get(0).unwrap();
|
let name = texts.get(0).unwrap();
|
||||||
let mut arg_list = Vec::new();
|
let mut arg_list = Vec::new();
|
||||||
while {
|
while {
|
||||||
match Expression::parse(parser) {
|
match Expression::parse(parser, true) {
|
||||||
Ok(exp) => {
|
Ok(exp) => {
|
||||||
arg_list.push(exp);
|
arg_list.push(exp);
|
||||||
parser.expect_static(",").get().is_some()
|
parser.expect_static(",").get().is_some()
|
||||||
@ -100,7 +101,100 @@ impl Expression {
|
|||||||
Ok(Expression::ValueRef(begin_pos, pattern))
|
Ok(Expression::ValueRef(begin_pos, pattern))
|
||||||
} else {
|
} else {
|
||||||
Err(SyntaxError::ExpectedExpression(begin_pos, None))
|
Err(SyntaxError::ExpectedExpression(begin_pos, None))
|
||||||
|
}?;
|
||||||
|
|
||||||
|
if allow_arithmetic {
|
||||||
|
if let Ok(exp) = ArithmeticExpression::parse(first.clone(), parser) {
|
||||||
|
Ok(Expression::ArithmeticExpression(begin_pos, Box::new(exp)))
|
||||||
|
} else {
|
||||||
|
Ok(first)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Ok(first)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum ArithmeticExpression {
|
||||||
|
Add(Expression, Expression),
|
||||||
|
Subtract(Expression, Expression),
|
||||||
|
Mult(Expression, Expression),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArithmeticExpression {
|
||||||
|
fn parse(
|
||||||
|
first_exp: Expression,
|
||||||
|
parser: &mut Parser,
|
||||||
|
) -> Result<ArithmeticExpression, SyntaxError> {
|
||||||
|
let mut list = Vec::new();
|
||||||
|
let mut exp = first_exp;
|
||||||
|
while {
|
||||||
|
let sign = parser
|
||||||
|
.expect_static("+")
|
||||||
|
.get()
|
||||||
|
.or_else(|| parser.expect_static("-").get())
|
||||||
|
.or_else(|| parser.expect_static("*").get());
|
||||||
|
if sign.is_some() {
|
||||||
|
list.push((exp, sign.clone()));
|
||||||
|
exp = Expression::parse(parser, false)?;
|
||||||
|
}
|
||||||
|
sign.is_some()
|
||||||
|
} {}
|
||||||
|
list.push((exp, None));
|
||||||
|
if list.len() == 1 {
|
||||||
|
return Err(SyntaxError::Fatal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace all (expr, "*"), (expr, any) => ((mult_expr, any)
|
||||||
|
let clone = list.clone();
|
||||||
|
let iter = clone.iter().enumerate().rev();
|
||||||
|
let mut previous: Option<(Expression, Option<String>)> = None;
|
||||||
|
for (idx, (exp, sign)) in iter {
|
||||||
|
if let Some(sign) = sign {
|
||||||
|
if sign == "*" {
|
||||||
|
if let Some((exp2, sign2)) = previous {
|
||||||
|
list.remove(idx + 1);
|
||||||
|
list.remove(idx);
|
||||||
|
let expr = Expression::ArithmeticExpression(
|
||||||
|
parser.pos(),
|
||||||
|
Box::new(ArithmeticExpression::Mult(exp.clone(), exp2.clone())),
|
||||||
|
);
|
||||||
|
list.insert(idx, (expr, sign2.clone()));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previous = Some((exp.clone(), sign.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut ret = Err(SyntaxError::Fatal);
|
||||||
|
while list.len() > 1 {
|
||||||
|
let (exp2, sign2) = list.remove(1);
|
||||||
|
let (exp1, sign1) = list.remove(0);
|
||||||
|
let expr = if let Some(sign1) = sign1 {
|
||||||
|
match &*sign1 {
|
||||||
|
"+" => Some(Box::new(ArithmeticExpression::Add(exp1, exp2))),
|
||||||
|
"-" => Some(Box::new(ArithmeticExpression::Subtract(exp1, exp2))),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(SyntaxError::ExpectedExpression(parser.pos(), None));
|
||||||
|
};
|
||||||
|
if let Some(expr) = expr {
|
||||||
|
list.insert(
|
||||||
|
0,
|
||||||
|
(Expression::ArithmeticExpression(parser.pos(), expr), sign2),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(first) = list.get(0) {
|
||||||
|
if let Expression::ArithmeticExpression(_, expr) = &first.0 {
|
||||||
|
ret = Ok(*expr.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use std::ops::{Add, Sub};
|
||||||
|
|
||||||
pub type FuncID = u16;
|
pub type FuncID = u16;
|
||||||
pub type HeapID = u16;
|
pub type HeapID = u16;
|
||||||
pub type RegID = u8;
|
pub type RegID = u8;
|
||||||
@ -17,6 +19,9 @@ pub enum Command {
|
|||||||
StringLit(String), // Bring String Literal to Stack
|
StringLit(String), // Bring String Literal to Stack
|
||||||
I32Lit(i32), // Bring i32 Literal to Stack
|
I32Lit(i32), // Bring i32 Literal to Stack
|
||||||
FunctionCall(FuncID), // Call Function at FuncID
|
FunctionCall(FuncID), // Call Function at FuncID
|
||||||
|
Add, // Add last two items on stack
|
||||||
|
Subtract, // Subtract last two items on stack
|
||||||
|
Mult, // Subtract last two items on stack
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -37,6 +42,39 @@ impl Value {
|
|||||||
Value::I32Val(_) => VariableType::TypeI32,
|
Value::I32Val(_) => VariableType::TypeI32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add(self, other: Value) -> Option<Value> {
|
||||||
|
match self {
|
||||||
|
Value::StringVal(string) => match other {
|
||||||
|
Value::StringVal(string2) => Some(Value::StringVal(string + &string2)),
|
||||||
|
Value::I32Val(val) => Some(Value::StringVal(string + &val.to_string())),
|
||||||
|
},
|
||||||
|
Value::I32Val(val) => match other {
|
||||||
|
Value::StringVal(string) => Some(Value::StringVal(val.to_string() + &string)),
|
||||||
|
Value::I32Val(val2) => Some(Value::I32Val(val + val2)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sub(self, other: Value) -> Option<Value> {
|
||||||
|
match self {
|
||||||
|
Value::StringVal(_) => None,
|
||||||
|
Value::I32Val(val) => match other {
|
||||||
|
Value::I32Val(val2) => Some(Value::I32Val(val - val2)),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mul(self, other: Value) -> Option<Value> {
|
||||||
|
match self {
|
||||||
|
Value::StringVal(_) => None,
|
||||||
|
Value::I32Val(val) => match other {
|
||||||
|
Value::I32Val(val2) => Some(Value::I32Val(val * val2)),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
@ -73,38 +73,29 @@ impl VirtualMachine {
|
|||||||
match command {
|
match command {
|
||||||
Command::InitializeVariable(heapid, vtype) => {
|
Command::InitializeVariable(heapid, vtype) => {
|
||||||
self.heap.insert(heapid, AllocatedVar(vtype, None));
|
self.heap.insert(heapid, AllocatedVar(vtype, None));
|
||||||
//dbg!("Initialized new variable to heap", &self.heap);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Command::BeginScope => {
|
Command::BeginScope => {
|
||||||
self.registry_stack.push(self.registry.clone());
|
self.registry_stack.push(self.registry.clone());
|
||||||
self.registry = Default::default();
|
self.registry = Default::default();
|
||||||
//dbg!("Begun new scope");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Command::EndScope => {
|
Command::EndScope => {
|
||||||
if let Some(reg) = self.registry_stack.pop() {
|
if let Some(reg) = self.registry_stack.pop() {
|
||||||
self.registry = reg;
|
self.registry = reg;
|
||||||
//dbg!("Scope ended");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimePanic::ScopeStackUnderflow)
|
Err(RuntimePanic::ScopeStackUnderflow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::Pop(regid) => {
|
Command::Pop(regid) => {
|
||||||
if let Some(val) = self.stack.pop() {
|
self.registry[regid as usize] = Some(self.pop_stack()?);
|
||||||
self.registry[regid as usize] = Some(val);
|
|
||||||
//dbg!("Registry popped", regid, &self.stack, &self.registry);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
|
||||||
Err(RuntimePanic::StackUnderflow)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Command::Push(regid) => {
|
Command::Push(regid) => {
|
||||||
if let Some(reg) = &self.registry[regid as usize] {
|
if let Some(reg) = &self.registry[regid as usize] {
|
||||||
if self.stack.len() < usize::MAX {
|
if self.stack.len() < usize::MAX {
|
||||||
self.stack.push(reg.clone());
|
self.stack.push(reg.clone());
|
||||||
//dbg!("Registry pushed", regid, &self.stack);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimePanic::StackOverflow)
|
Err(RuntimePanic::StackOverflow)
|
||||||
@ -117,7 +108,6 @@ impl VirtualMachine {
|
|||||||
if let Some(reg) = &self.registry[regid as usize] {
|
if let Some(reg) = &self.registry[regid as usize] {
|
||||||
if let Some(var) = self.heap.get_mut(&heapid) {
|
if let Some(var) = self.heap.get_mut(&heapid) {
|
||||||
var.try_set(Some(reg.clone()))?;
|
var.try_set(Some(reg.clone()))?;
|
||||||
//dbg!("Variable assigned", heapid, regid, &self.heap);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimePanic::InvalidHeapAddress)
|
Err(RuntimePanic::InvalidHeapAddress)
|
||||||
@ -130,7 +120,6 @@ impl VirtualMachine {
|
|||||||
if let Some(var) = self.heap.get(&heapid) {
|
if let Some(var) = self.heap.get(&heapid) {
|
||||||
if let Some(val) = &var.1 {
|
if let Some(val) = &var.1 {
|
||||||
self.registry[regid as usize] = Some(val.clone());
|
self.registry[regid as usize] = Some(val.clone());
|
||||||
//dbg!("Variable pushed to registry", heapid, regid, &self.registry);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimePanic::ValueNotInitialized)
|
Err(RuntimePanic::ValueNotInitialized)
|
||||||
@ -139,23 +128,8 @@ impl VirtualMachine {
|
|||||||
Err(RuntimePanic::InvalidHeapAddress)
|
Err(RuntimePanic::InvalidHeapAddress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::StringLit(string) => {
|
Command::StringLit(string) => self.push_stack(Value::StringVal(string)),
|
||||||
if self.stack.len() < usize::MAX {
|
Command::I32Lit(val) => self.push_stack(Value::I32Val(val)),
|
||||||
self.stack.push(Value::StringVal(string));
|
|
||||||
//dbg!("String literal added to stack", string, &self.stack);
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(RuntimePanic::StackOverflow)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Command::I32Lit(val) => {
|
|
||||||
if self.stack.len() < usize::MAX {
|
|
||||||
self.stack.push(Value::I32Val(val));
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(RuntimePanic::StackOverflow)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Command::FunctionCall(funcid) => {
|
Command::FunctionCall(funcid) => {
|
||||||
if self.functions.len() <= funcid as usize {
|
if self.functions.len() <= funcid as usize {
|
||||||
Err(RuntimePanic::InvalidFuncAddress)
|
Err(RuntimePanic::InvalidFuncAddress)
|
||||||
@ -176,6 +150,56 @@ impl VirtualMachine {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Command::Add => {
|
||||||
|
let val1 = self.pop_stack()?;
|
||||||
|
let val2 = self.pop_stack()?;
|
||||||
|
let res = val2.add(val1);
|
||||||
|
if let Some(res) = res {
|
||||||
|
self.push_stack(res);
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(RuntimePanic::AttemptedInvalidArithmeticOperation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command::Subtract => {
|
||||||
|
let val1 = self.pop_stack()?;
|
||||||
|
let val2 = self.pop_stack()?;
|
||||||
|
let res = val2.sub(val1);
|
||||||
|
if let Some(res) = res {
|
||||||
|
self.push_stack(res);
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(RuntimePanic::AttemptedInvalidArithmeticOperation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command::Mult => {
|
||||||
|
let val1 = self.pop_stack()?;
|
||||||
|
let val2 = self.pop_stack()?;
|
||||||
|
let res = val2.mul(val1);
|
||||||
|
if let Some(res) = res {
|
||||||
|
self.push_stack(res);
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(RuntimePanic::AttemptedInvalidArithmeticOperation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pop_stack(&mut self) -> Result<Value, RuntimePanic> {
|
||||||
|
if let Some(val) = self.stack.pop() {
|
||||||
|
Ok(val)
|
||||||
|
} else {
|
||||||
|
Err(RuntimePanic::StackUnderflow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_stack(&mut self, val: Value) -> Result<(), RuntimePanic> {
|
||||||
|
if self.stack.len() < usize::MAX {
|
||||||
|
self.stack.push(val);
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(RuntimePanic::StackOverflow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user