mirror of
https://github.com/exoticorn/curlywas.git
synced 2026-01-20 11:46:43 +01:00
implement type checking and constand folding for simple example
This commit is contained in:
77
src/constfold.rs
Normal file
77
src/constfold.rs
Normal file
@@ -0,0 +1,77 @@
|
||||
use crate::ast;
|
||||
|
||||
pub fn fold_script(script: &mut ast::Script) {
|
||||
for func in &mut script.functions {
|
||||
fold_block(&mut func.body);
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_block(block: &mut ast::Block) {
|
||||
for stmt in &mut block.statements {
|
||||
match stmt {
|
||||
ast::Statement::LocalVariable(lv) => {
|
||||
if let Some(ref mut expr) = lv.value {
|
||||
fold_expr(expr);
|
||||
}
|
||||
}
|
||||
ast::Statement::Expression(expr) => fold_expr(expr),
|
||||
ast::Statement::Poke {
|
||||
mem_location,
|
||||
value,
|
||||
..
|
||||
} => {
|
||||
fold_mem_location(mem_location);
|
||||
fold_expr(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(ref mut expr) = block.final_expression {
|
||||
fold_expr(expr);
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_mem_location(mem_location: &mut ast::MemoryLocation) {
|
||||
fold_expr(&mut mem_location.left);
|
||||
fold_expr(&mut mem_location.right);
|
||||
}
|
||||
|
||||
fn fold_expr(expr: &mut ast::Expression) {
|
||||
use ast::BinOp::*;
|
||||
match expr.expr {
|
||||
ast::Expr::BinOp {
|
||||
ref mut left, op, ref mut right, ..
|
||||
} => {
|
||||
fold_expr(left);
|
||||
fold_expr(right);
|
||||
dbg!(&left.expr, &right.expr);
|
||||
match (&left.expr, &right.expr) {
|
||||
(&ast::Expr::I32Const(left), &ast::Expr::I32Const(right)) => {
|
||||
let result = match op {
|
||||
Add => left.wrapping_add(right),
|
||||
Sub => left.wrapping_sub(right),
|
||||
Mul => left.wrapping_mul(right),
|
||||
Div => left / right, // TODO: protect agains division by zero
|
||||
Rem => left % right, // TODO: check correct behavior with negative operands
|
||||
And => left & right,
|
||||
Or => left | right,
|
||||
Xor => left ^ right,
|
||||
Eq => (left == right) as i32,
|
||||
Ne => (left != right) as i32,
|
||||
Lt => (left < right) as i32,
|
||||
Le => (left <= right) as i32,
|
||||
Gt => (left > right) as i32,
|
||||
Ge => (left >= right) as i32,
|
||||
};
|
||||
expr.expr = ast::Expr::I32Const(result);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
ast::Expr::I32Const(_) | ast::Expr::Variable { .. } => (),
|
||||
ast::Expr::LocalTee { ref mut value, .. } => fold_expr(value),
|
||||
ast::Expr::Loop { ref mut block, .. } => fold_block(block),
|
||||
ast::Expr::BranchIf {
|
||||
ref mut condition, ..
|
||||
} => fold_expr(condition),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user