We have SSA

This commit is contained in:
2026-07-07 13:47:45 -05:00
parent e57e319dec
commit 4aa9341bf3
5 changed files with 273 additions and 11 deletions
+122
View File
@@ -0,0 +1,122 @@
use crate::lex::{ TeaValue, Operator };
use crate::parse::{ ASTNode, Value };
use std::collections::HashMap;
#[derive(Debug)]
enum VarType {
Const(TeaValue),
//Mut,
}
#[derive(Debug)]
pub struct InterpreterError {
description: String,
}
impl InterpreterError {
pub fn new(e: &str) -> Self {
Self {
description: e.to_owned(),
}
}
}
macro_rules! some_or_error {
($matchee:expr, $ret:expr) => {
match $matchee {
Some(s) => s,
_ => return Err($ret),
}
}
}
fn get_value(v: Value, scope: &HashMap<String, VarType>) -> Result<TeaValue, InterpreterError> {
match v {
Value::Lit(t) => Ok(t),
Value::Id(s) => match scope.get(&s) {
None => Err(InterpreterError::new("undefined variable")),
Some(VarType::Const(t)) => Ok(t.clone()),
},
}
}
macro_rules! apply_op {
($a:ident, $b:ident, $op:tt) => {
match ($a, $b) {
(TeaValue::Float(aa), TeaValue::Float(bb)) => {
TeaValue::Float(aa $op bb)
},
(TeaValue::Int(aa), TeaValue::Int(bb)) => {
TeaValue::Int(aa $op bb)
},
//(TeaValue::Uint(aa), TeaValue::Uint(bb)) => {
// TeaValue::Uint(aa $op bb)
//},
_ => panic!("Invalid types"),
}
}
}
pub fn interpret(ast: Vec<ASTNode>) -> Result<Vec<Value>, InterpreterError> {
let mut ast = ast.clone();
ast.reverse();
let mut stack = vec![];
let mut global_scope: HashMap<String, VarType> = HashMap::new();
loop {
match ast.pop() {
None => return Ok(stack),
Some(ASTNode::Val(v)) => stack.push(v),
Some(ASTNode::BinOp(op)) => {
let b = some_or_error!(stack.pop(), InterpreterError::new("right value needed"));
let a = some_or_error!(stack.pop(), InterpreterError::new("left value needed"));
let b: TeaValue = get_value(b, &global_scope)?;
let a: TeaValue = get_value(a, &global_scope)?;
stack.push(Value::Lit(match op {
Operator::Plus => {
apply_op!(a, b, +)
},
Operator::Minus => {
apply_op!(a, b, -)
},
Operator::Star => {
apply_op!(a, b, *)
},
Operator::Slash => {
apply_op!(a, b, /)
},
}));
},
Some(ASTNode::UnaryMinus) => {
let x = some_or_error!(stack.pop(), InterpreterError::new("value needed"));
let x: TeaValue = get_value(x, &global_scope)?;
stack.push(Value::Lit(match x {
TeaValue::Float(f) => TeaValue::Float(-f),
TeaValue::Int(i) => TeaValue::Int(-i),
TeaValue::Uint(u) => TeaValue::Int(-(u as i32)),
TeaValue::String(_) => return Err(InterpreterError::new("cannot invert string")),
}));
},
Some(ASTNode::ConstDecl) => {
let rhs = some_or_error!(stack.pop(), InterpreterError::new("rhs value needed"));
let lhs = some_or_error!(stack.pop(), InterpreterError::new("lhs value needed"));
let rhs: TeaValue = get_value(rhs, &global_scope)?;
match lhs {
Value::Lit(_) => return Err(InterpreterError::new("invalid left hand side")),
Value::Id(s) => {
if global_scope.contains_key(&s) {
return Err(InterpreterError::new("already defined constant"));
} else {
global_scope.insert(s, VarType::Const(rhs));
}
}
}
},
Some(ASTNode::StatementEnd) => {
if !stack.is_empty() {
return Err(InterpreterError::new("stack not empty"));
}
}
}
}
}