Find constants
This commit is contained in:
parent
12e2fab066
commit
d74a887c4e
@ -1 +1 @@
|
|||||||
c = max(5, 7)
|
global c = max(5, 7)
|
||||||
12
src/ast.rs
12
src/ast.rs
@ -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
74
src/compile.rs
Normal 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 ¶ms.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
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
23
src/vm.rs
Normal 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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user