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()?;
stream.expect(Token::Keyword(Keyword::End))?;
Ok(Self::If(cond, then))
} else if peeked == Some(Token::Keyword(Keyword::Local)) {
stream.next();
} else if let Some(Token::Keyword(Keyword::Local | Keyword::Global)) = peeked {
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()?;
stream.expect(Token::Symbol('='))?;
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
&& stream.peek2() == Some(Token::Symbol('='))
{
@ -263,7 +267,7 @@ impl Parse for Statement {
}
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AccessModifier {
Local,
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 compile;
mod token_stream;
mod vm;
static TEST: &str = include_str!("../examples/test.lua");
@ -23,7 +25,8 @@ fn main() {
let chunk = stream.parse::<Block>().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,
End,
Local,
Global,
Return,
If,
Then,
@ -23,6 +24,7 @@ impl Keyword {
"function" => Keyword::Function,
"end" => Keyword::End,
"local" => Keyword::Local,
"global" => Keyword::Global,
"return" => Keyword::Return,
"if" => Keyword::If,
"then" => Keyword::Then,
@ -37,6 +39,7 @@ impl ToString for Keyword {
Keyword::Function => "function",
Keyword::End => "end",
Keyword::Local => "local",
Keyword::Global => "global",
Keyword::Return => "return",
Keyword::If => "if",
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(),
}
}
}