Find constants

This commit is contained in:
Sofia 2026-03-14 18:31:40 +02:00
parent 12e2fab066
commit d74a887c4e
6 changed files with 114 additions and 7 deletions

View File

@ -1 +1 @@
c = max(5, 7) global c = max(5, 7)

View File

@ -241,12 +241,16 @@ impl Parse for Statement {
let then = stream.parse()?; let then = stream.parse()?;
stream.expect(Token::Keyword(Keyword::End))?; stream.expect(Token::Keyword(Keyword::End))?;
Ok(Self::If(cond, then)) Ok(Self::If(cond, then))
} else if peeked == Some(Token::Keyword(Keyword::Local)) { } else if let Some(Token::Keyword(Keyword::Local | Keyword::Global)) = peeked {
stream.next(); let access_modifier = match stream.next() {
Some(Token::Keyword(Keyword::Local)) => AccessModifier::Local,
Some(Token::Keyword(Keyword::Global)) => AccessModifier::Global,
_ => panic!(),
};
let name = stream.parse()?; let name = stream.parse()?;
stream.expect(Token::Symbol('='))?; stream.expect(Token::Symbol('='))?;
let expr = stream.parse()?; let expr = stream.parse()?;
Ok(Statement::Assignment(AccessModifier::Local, name, expr)) Ok(Statement::Assignment(access_modifier, name, expr))
} else if let Some(Token::Word(_)) = peeked } else if let Some(Token::Word(_)) = peeked
&& stream.peek2() == Some(Token::Symbol('=')) && stream.peek2() == Some(Token::Symbol('='))
{ {
@ -263,7 +267,7 @@ impl Parse for Statement {
} }
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum AccessModifier { pub enum AccessModifier {
Local, Local,
Global, Global,

74
src/compile.rs Normal file
View File

@ -0,0 +1,74 @@
use std::collections::HashSet;
use crate::{
ast::{AccessModifier, Block, Expression, Literal, Statement},
vm::{Constant, VMNumber},
};
struct State {
pub constants: Vec<Constant>,
}
impl Block {
pub fn find_constants(&self) -> HashSet<Constant> {
let mut constants = HashSet::new();
for statement in &self.statements {
constants.extend(statement.kind.find_constants());
}
constants
}
}
impl Statement {
pub fn find_constants(&self) -> HashSet<Constant> {
match self {
Statement::Assignment(access, name, expr) => {
let mut constants = HashSet::new();
if *access == AccessModifier::Global {
constants.insert(Constant::String(name.kind.clone()));
}
constants.extend(expr.kind.find_constants());
constants
}
Statement::Return(expr) => expr.kind.find_constants(),
Statement::If(cond, then) => {
let mut constants = HashSet::new();
constants.extend(cond.kind.find_constants());
constants.extend(then.find_constants());
constants
}
}
}
}
impl Expression {
pub fn find_constants(&self) -> HashSet<Constant> {
match self {
Expression::ValueRef(_) => HashSet::new(),
Expression::BinOp(_, lhs, rhs) => {
let mut constants = HashSet::new();
constants.extend(lhs.kind.find_constants());
constants.extend(rhs.kind.find_constants());
constants
}
Expression::FunctionDefinition(_, block) => block.find_constants(),
Expression::FunctionCall(expr, params) => {
let mut constants = HashSet::new();
constants.extend(expr.kind.find_constants());
for param in &params.kind.0 {
constants.extend(param.kind.find_constants());
}
constants
}
Expression::Literal(literal) => match literal {
Literal::Number(value) => {
let mut constants = HashSet::new();
constants.insert(Constant::Number(value.to_bits()));
constants
}
},
}
}
}

View File

@ -9,7 +9,9 @@ use crate::{
}; };
mod ast; mod ast;
mod compile;
mod token_stream; mod token_stream;
mod vm;
static TEST: &str = include_str!("../examples/test.lua"); static TEST: &str = include_str!("../examples/test.lua");
@ -23,7 +25,8 @@ fn main() {
let chunk = stream.parse::<Block>().unwrap(); let chunk = stream.parse::<Block>().unwrap();
stream.expect(Token::Eof).unwrap(); stream.expect(Token::Eof).unwrap();
dbg!(chunk); dbg!(&chunk);
println!("Hello, world!"); let constants = chunk.find_constants();
dbg!(&constants);
} }

View File

@ -12,6 +12,7 @@ pub enum Keyword {
Function, Function,
End, End,
Local, Local,
Global,
Return, Return,
If, If,
Then, Then,
@ -23,6 +24,7 @@ impl Keyword {
"function" => Keyword::Function, "function" => Keyword::Function,
"end" => Keyword::End, "end" => Keyword::End,
"local" => Keyword::Local, "local" => Keyword::Local,
"global" => Keyword::Global,
"return" => Keyword::Return, "return" => Keyword::Return,
"if" => Keyword::If, "if" => Keyword::If,
"then" => Keyword::Then, "then" => Keyword::Then,
@ -37,6 +39,7 @@ impl ToString for Keyword {
Keyword::Function => "function", Keyword::Function => "function",
Keyword::End => "end", Keyword::End => "end",
Keyword::Local => "local", Keyword::Local => "local",
Keyword::Global => "global",
Keyword::Return => "return", Keyword::Return => "return",
Keyword::If => "if", Keyword::If => "if",
Keyword::Then => "then", Keyword::Then => "then",

23
src/vm.rs Normal file
View File

@ -0,0 +1,23 @@
use std::fmt::Debug;
use crate::ast::LuaNumber;
pub type VMNumber = u64;
#[derive(Clone, Hash, PartialEq, Eq)]
pub enum Constant {
String(String),
Number(VMNumber),
}
impl Debug for Constant {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::String(arg0) => f.debug_tuple("String").field(arg0).finish(),
Self::Number(arg0) => f
.debug_tuple("Number")
.field(&LuaNumber::from_bits(*arg0))
.finish(),
}
}
}