format code

This commit is contained in:
nganhkhoa 2021-05-19 17:26:50 +07:00
parent 236c3aeb68
commit 3011542376
6 changed files with 170 additions and 243 deletions

View File

@ -1,16 +1,16 @@
mod visitor; mod visitor;
use std::fs;
use full_moon::parse; use full_moon::parse;
use std::fs;
use visitor::Visitor;
use visitor::ConstantFolder; use visitor::ConstantFolder;
use visitor::Visitor;
fn main() { fn main() {
// let contents = fs::read_to_string("main_android_org.lua") // let contents = fs::read_to_string("main_android_org.lua")
// let contents = fs::read_to_string("small.lua") // let contents = fs::read_to_string("small.lua")
let contents = fs::read_to_string("very_small.lua") let contents =
.expect("Something went wrong reading the file"); fs::read_to_string("very_small.lua").expect("Something went wrong reading the file");
let tree = parse(&contents).expect("Parsing lua gone wrong"); let tree = parse(&contents).expect("Parsing lua gone wrong");

View File

@ -1,5 +1,5 @@
mod visitor;
mod constant_folder; mod constant_folder;
mod visitor;
pub use visitor::*;
pub use constant_folder::*; pub use constant_folder::*;
pub use visitor::*;

View File

@ -5,31 +5,26 @@ use full_moon::ast::*;
use crate::visitor::Visitor; use crate::visitor::Visitor;
pub struct ConstantFolder { pub struct ConstantFolder {
locals: Box<Vec<expression_reducer::Variable>> locals: Box<Vec<expression_reducer::Variable>>,
} }
impl ConstantFolder { impl ConstantFolder {
pub fn new() -> Self { pub fn new() -> Self {
ConstantFolder{ ConstantFolder {
locals: Box::new(vec![]) locals: Box::new(vec![]),
} }
} }
fn register_local(&mut self, name: String, value: Option<Expression>) { fn register_local(&mut self, name: String, value: Option<Expression>) {
let locals = &*self.locals; let locals = &*self.locals;
let var = expression_reducer::Variable::with_value( let var = expression_reducer::Variable::with_value(name, value, locals);
name, value, locals
);
self.locals.push(var); self.locals.push(var);
} }
fn assign(&mut self, name: String, value: Option<Expression>) { fn assign(&mut self, name: String, value: Option<Expression>) {
let locals = &*self.locals; let locals = &*self.locals;
let var = expression_reducer::Variable::with_value( let var = expression_reducer::Variable::with_value(name, value, locals);
name, value, locals
);
{ {
let mut iter = self.locals.iter_mut(); let mut iter = self.locals.iter_mut();
let it = iter.find(|it| it.name() == var.name()); let it = iter.find(|it| it.name() == var.name());
@ -48,7 +43,7 @@ impl Visitor for ConstantFolder {
panic!("assignment Var::Expression is not supported") panic!("assignment Var::Expression is not supported")
} }
Var::Name(n) => n.token().to_string(), Var::Name(n) => n.token().to_string(),
_ => unreachable!() _ => unreachable!(),
}); });
let expr = expressions.next().map(|x| x.clone() /* reduced */); let expr = expressions.next().map(|x| x.clone() /* reduced */);
match name { match name {
@ -68,7 +63,10 @@ impl Visitor for ConstantFolder {
fn visit_function_call<'a>(&mut self, function_call: &FunctionCall<'a>) { fn visit_function_call<'a>(&mut self, function_call: &FunctionCall<'a>) {
println!("visit function_call {}", function_call); println!("visit function_call {}", function_call);
let reduced = expression_reducer::reduce_expression_value_function_call(function_call.clone(), &*self.locals); let reduced = expression_reducer::reduce_expression_value_function_call(
function_call.clone(),
&*self.locals,
);
println!("{:?}", reduced); println!("{:?}", reduced);
} }
@ -124,5 +122,4 @@ impl Visitor for ConstantFolder {
fn visit_label<'a>(&mut self, label: &lua52::Label<'a>) { fn visit_label<'a>(&mut self, label: &lua52::Label<'a>) {
println!("visit label {}", label); println!("visit label {}", label);
} }
} }

View File

@ -61,17 +61,14 @@ use full_moon::ast;
#[derive(Debug)] #[derive(Debug)]
pub struct Variable { pub struct Variable {
n: String, n: String,
v: Expression v: Expression,
} }
impl Variable { impl Variable {
pub fn with_value(name: String, expr: Option<ast::Expression>, locals: &Vec<Variable>) -> Self { pub fn with_value(name: String, expr: Option<ast::Expression>, locals: &Vec<Variable>) -> Self {
let v = Expression::reduce(expr, locals); let v = Expression::reduce(expr, locals);
println!("variable_with {} = {:?}", name, v); println!("variable_with {} = {:?}", name, v);
Self { Self { n: name, v: v }
n: name,
v: v,
}
} }
pub fn name(&self) -> String { pub fn name(&self) -> String {
@ -121,7 +118,7 @@ impl BinOp {
ast::BinOp::TildeEqual(_) => BinOp::TildeEqual, ast::BinOp::TildeEqual(_) => BinOp::TildeEqual,
ast::BinOp::TwoDots(_) => BinOp::TwoDots, ast::BinOp::TwoDots(_) => BinOp::TwoDots,
ast::BinOp::TwoEqual(_) => BinOp::TwoEqual, ast::BinOp::TwoEqual(_) => BinOp::TwoEqual,
_ => unreachable!() _ => unreachable!(),
} }
} }
} }
@ -139,7 +136,7 @@ impl UnOp {
ast::UnOp::Minus(_) => UnOp::Minus, ast::UnOp::Minus(_) => UnOp::Minus,
ast::UnOp::Not(_) => UnOp::Not, ast::UnOp::Not(_) => UnOp::Not,
ast::UnOp::Hash(_) => UnOp::Hash, ast::UnOp::Hash(_) => UnOp::Hash,
_ => unreachable!() _ => unreachable!(),
} }
} }
} }
@ -166,7 +163,7 @@ pub struct Expression {
impl Expression { impl Expression {
pub fn reduce(expr: Option<ast::Expression>, locals: &Vec<Variable>) -> Self { pub fn reduce(expr: Option<ast::Expression>, locals: &Vec<Variable>) -> Self {
if expr.is_none() { if expr.is_none() {
Expression{ Expression {
t: ExpressionType::Nil, t: ExpressionType::Nil,
} }
} else { } else {
@ -199,34 +196,18 @@ impl Expression {
fn reduce_expression(expr: ast::Expression, locals: &Vec<Variable>) -> Expression { fn reduce_expression(expr: ast::Expression, locals: &Vec<Variable>) -> Expression {
match expr { match expr {
ast::Expression::BinaryOperator { ast::Expression::BinaryOperator { lhs, rhs, binop } => {
lhs,
rhs,
binop
} => {
let lhs_ = reduce_expression(*lhs, locals); let lhs_ = reduce_expression(*lhs, locals);
let rhs_ = reduce_expression(*rhs, locals); let rhs_ = reduce_expression(*rhs, locals);
apply_binary_operator(lhs_, rhs_, binop) apply_binary_operator(lhs_, rhs_, binop)
} }
ast::Expression::Parentheses { ast::Expression::Parentheses { expression, .. } => reduce_expression(*expression, locals),
expression, ast::Expression::UnaryOperator { unop, expression } => {
..
} => {
reduce_expression(*expression, locals)
}
ast::Expression::UnaryOperator {
unop,
expression,
} => {
let expression_ = reduce_expression(*expression, locals); let expression_ = reduce_expression(*expression, locals);
apply_unary_operator(expression_, unop) apply_unary_operator(expression_, unop)
} }
ast::Expression::Value { ast::Expression::Value { value } => reduce_expression_value(*value, locals),
value _ => unreachable!(),
} => {
reduce_expression_value(*value, locals)
}
_ => unreachable!()
} }
} }
@ -243,36 +224,32 @@ fn reduce_expression_value(value: ast::Value, locals: &Vec<Variable>) -> Express
} }
ast::Value::Number(number) => { ast::Value::Number(number) => {
let num = number.token().to_string(); let num = number.token().to_string();
Expression{ Expression {
t: ExpressionType::Number(num.parse::<f64>().unwrap()), t: ExpressionType::Number(num.parse::<f64>().unwrap()),
} }
} }
ast::Value::ParenthesesExpression(parentheses_expression) => { ast::Value::ParenthesesExpression(parentheses_expression) => {
reduce_expression(parentheses_expression, locals) reduce_expression(parentheses_expression, locals)
} }
ast::Value::String(string) => { ast::Value::String(string) => Expression {
Expression{
t: ExpressionType::String(string.token().to_string()), t: ExpressionType::String(string.token().to_string()),
} },
}
ast::Value::Symbol(symbol) => { ast::Value::Symbol(symbol) => {
let s = symbol.token().to_string(); let s = symbol.token().to_string();
if s == "true" { if s == "true" {
Expression{ Expression {
t: ExpressionType::Boolean(true), t: ExpressionType::Boolean(true),
} }
} else if s == "false" { } else if s == "false" {
Expression{ Expression {
t: ExpressionType::Boolean(false), t: ExpressionType::Boolean(false),
} }
} else { } else {
panic!("reduce Expression::Symbol is not true/false"); panic!("reduce Expression::Symbol is not true/false");
} }
} }
ast::Value::Var(var) => { ast::Value::Var(var) => reduce_expression_value_var(var, locals),
reduce_expression_value_var(var, locals) _ => unreachable!(),
}
_ => unreachable!()
} }
} }
@ -282,105 +259,90 @@ fn reduce_expression_value_var(var: ast::Var, locals: &Vec<Variable>) -> Express
let prefix = { let prefix = {
match expr.prefix() { match expr.prefix() {
ast::Prefix::Name(name) => name.token().to_string(), ast::Prefix::Name(name) => name.token().to_string(),
_ => panic!("Var::Expression prefix expression is unsupported") _ => panic!("Var::Expression prefix expression is unsupported"),
} }
}; };
let suffixes = expr.suffixes().map(|suf| { let suffixes = expr
match suf { .suffixes()
ast::Suffix::Index(ast::Index::Dot{ .map(|suf| match suf {
name, ast::Suffix::Index(ast::Index::Dot { name, .. }) => name.token().to_string(),
.. _ => panic!("Var::Expression Call not supported"),
}) => { })
name.token().to_string() .collect::<Vec<String>>();
}
_ => panic!("Var::Expression Call not supported")
}
}).collect::<Vec<String>>();
let local_var = locals.iter().find(|it| it.name() == prefix); let local_var = locals.iter().find(|it| it.name() == prefix);
match local_var { match local_var {
None => { None => Expression {
Expression { t: ExpressionType::Module(prefix, suffixes),
t: ExpressionType::Module(prefix, suffixes) },
} Some(var) => match var.v.clone().t {
} ExpressionType::Module(n, _) => Expression {
Some(var) => { t: ExpressionType::Module(n, suffixes),
match var.v.clone().t { },
ExpressionType::Module(n, _) => { _ => Expression {
Expression { t: ExpressionType::Module(var.name(), suffixes),
t: ExpressionType::Module(n, suffixes) },
} },
}
_ => {
Expression {
t: ExpressionType::Module(var.name(), suffixes)
}
}
}
}
} }
} }
ast::Var::Name(name) => { ast::Var::Name(name) => {
fn is_standard_library(name: &String) -> bool { fn is_standard_library(name: &String) -> bool {
let standard_library_names: Vec<&str> = vec![ let standard_library_names: Vec<&str> = vec!["math", "string", "table", "bit"];
"math", "string", "table", "bit"
];
standard_library_names.contains(&name.as_str()) standard_library_names.contains(&name.as_str())
} }
let name_str = name.token().to_string(); let name_str = name.token().to_string();
if is_standard_library(&name_str) { if is_standard_library(&name_str) {
return Expression { return Expression {
t: ExpressionType::Module(name_str, vec![]) t: ExpressionType::Module(name_str, vec![]),
}; };
} }
let local_var = locals.iter().find(|it| it.name() == name_str); let local_var = locals.iter().find(|it| it.name() == name_str);
match local_var { match local_var {
None => { None => Expression {
Expression { t: ExpressionType::Var(name_str),
t: ExpressionType::Var(name_str) },
Some(v) => v.v.clone(),
} }
} }
Some(v) => { _ => unreachable!(),
v.v.clone()
}
}
}
_ => unreachable!()
} }
} }
pub fn reduce_expression_value_function_call(function_call: ast::FunctionCall, locals: &Vec<Variable>) -> Expression { pub fn reduce_expression_value_function_call(
function_call: ast::FunctionCall,
locals: &Vec<Variable>,
) -> Expression {
let function_name = match function_call.prefix() { let function_name = match function_call.prefix() {
ast::Prefix::Name(name) => name.token().to_string(), ast::Prefix::Name(name) => name.token().to_string(),
_ => panic!("Function name as expression is unsupported") _ => panic!("Function name as expression is unsupported"),
}; };
let args = { let args = {
let suf = function_call.suffixes().next().unwrap(); let suf = function_call.suffixes().next().unwrap();
match suf { match suf {
ast::Suffix::Call(ast::Call::AnonymousCall(ast::FunctionArgs::Parentheses{ ast::Suffix::Call(ast::Call::AnonymousCall(ast::FunctionArgs::Parentheses {
arguments, arguments,
.. ..
})) => { })) => arguments
arguments.iter().map(|x| reduce_expression(x.clone(), locals)).collect::<Vec<_>>() .iter()
} .map(|x| reduce_expression(x.clone(), locals))
_ => panic!("Index not supported") .collect::<Vec<_>>(),
_ => panic!("Index not supported"),
} }
}; };
Expression { Expression {
t: ExpressionType::FunctionCall(function_name, args) t: ExpressionType::FunctionCall(function_name, args),
} }
} }
fn apply_binary_operator(lhs: Expression, rhs: Expression, binop: ast::BinOp) -> Expression { fn apply_binary_operator(lhs: Expression, rhs: Expression, binop: ast::BinOp) -> Expression {
match (&lhs.t, &rhs.t) { match (&lhs.t, &rhs.t) {
(&ExpressionType::Number(lhs_), &ExpressionType::Number(rhs_)) => { (&ExpressionType::Number(lhs_), &ExpressionType::Number(rhs_)) => match binop {
match binop {
ast::BinOp::GreaterThan(_) => { ast::BinOp::GreaterThan(_) => {
return Expression { return Expression {
t: ExpressionType::Boolean(lhs_ > rhs_), t: ExpressionType::Boolean(lhs_ > rhs_),
} }
}, }
ast::BinOp::GreaterThanEqual(_) => { ast::BinOp::GreaterThanEqual(_) => {
return Expression { return Expression {
t: ExpressionType::Boolean(lhs_ >= rhs_), t: ExpressionType::Boolean(lhs_ >= rhs_),
@ -437,14 +399,12 @@ fn apply_binary_operator(lhs: Expression, rhs: Expression, binop: ast::BinOp) ->
} }
} }
_ => {} _ => {}
} },
}
_ => {} _ => {}
}; };
match (&lhs.t, &rhs.t) { match (&lhs.t, &rhs.t) {
(&ExpressionType::Boolean(lhs_), &ExpressionType::Boolean(rhs_)) => { (&ExpressionType::Boolean(lhs_), &ExpressionType::Boolean(rhs_)) => match binop {
match binop {
ast::BinOp::And(_) => { ast::BinOp::And(_) => {
return Expression { return Expression {
t: ExpressionType::Boolean(lhs_ & rhs_), t: ExpressionType::Boolean(lhs_ & rhs_),
@ -456,22 +416,19 @@ fn apply_binary_operator(lhs: Expression, rhs: Expression, binop: ast::BinOp) ->
} }
} }
_ => {} _ => {}
} },
}
_ => {} _ => {}
} }
match (&lhs.t, &rhs.t) { match (&lhs.t, &rhs.t) {
(&ExpressionType::String(ref lhs_), &ExpressionType::String(ref rhs_)) => { (&ExpressionType::String(ref lhs_), &ExpressionType::String(ref rhs_)) => match binop {
match binop {
ast::BinOp::TwoDots(_) => { ast::BinOp::TwoDots(_) => {
return Expression { return Expression {
t: ExpressionType::String(lhs_.clone() + &rhs_), t: ExpressionType::String(lhs_.clone() + &rhs_),
} }
} }
_ => {} _ => {}
} },
}
_ => {} _ => {}
} }
@ -486,20 +443,20 @@ fn apply_unary_operator(expr: Expression, unop: ast::UnOp) -> Expression {
if let ExpressionType::Boolean(e) = expr.t { if let ExpressionType::Boolean(e) = expr.t {
return Expression { return Expression {
t: ExpressionType::Boolean(!e), t: ExpressionType::Boolean(!e),
} };
} }
} }
ast::UnOp::Minus(_) => { ast::UnOp::Minus(_) => {
if let ExpressionType::Number(e) = expr.t { if let ExpressionType::Number(e) = expr.t {
return Expression { return Expression {
t: ExpressionType::Number(-e), t: ExpressionType::Number(-e),
} };
} }
} }
ast::UnOp::Hash(_) => { ast::UnOp::Hash(_) => {
panic!("Unary Hash unimplemented") panic!("Unary Hash unimplemented")
} }
_ => unreachable!() _ => unreachable!(),
} }
Expression { Expression {

View File

@ -8,9 +8,7 @@ pub struct Scope {
impl Scope { impl Scope {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self { scope: vec![] }
scope: vec![],
}
} }
fn frame(&self) -> Option<&Local> { fn frame(&self) -> Option<&Local> {
@ -30,11 +28,8 @@ impl Scope {
} }
pub fn find_name(&self, name: String) -> Option<&Variable> { pub fn find_name(&self, name: String) -> Option<&Variable> {
self.frame().map_or(None, |frame| { self.frame()
frame .map_or(None, |frame| frame.iter().find(|var| var.name() == name))
.iter()
.find(|var| var.name() == name)
})
} }
pub fn set_var(&mut self, value: Variable) { pub fn set_var(&mut self, value: Variable) {

View File

@ -10,39 +10,21 @@ pub trait Visitor {
fn visit_statement<'a>(&mut self, stmt: &Stmt<'a>) { fn visit_statement<'a>(&mut self, stmt: &Stmt<'a>) {
match stmt { match stmt {
Stmt::Assignment(assignment) => { Stmt::Assignment(assignment) => self.visit_assignment(assignment),
self.visit_assignment(assignment) Stmt::Do(do_) => self.visit_do(do_),
} Stmt::FunctionCall(function_call) => self.visit_function_call(function_call),
Stmt::Do(do_) => {
self.visit_do(do_)
}
Stmt::FunctionCall(function_call) => {
self.visit_function_call(function_call)
}
Stmt::FunctionDeclaration(function_declaration) => { Stmt::FunctionDeclaration(function_declaration) => {
self.visit_function_declaration(function_declaration) self.visit_function_declaration(function_declaration)
} }
Stmt::GenericFor(generic_for) => { Stmt::GenericFor(generic_for) => self.visit_generic_for(generic_for),
self.visit_generic_for(generic_for) Stmt::If(if_) => self.visit_if(if_),
}
Stmt::If(if_) => {
self.visit_if(if_)
}
Stmt::LocalAssignment(local_assignment) => { Stmt::LocalAssignment(local_assignment) => {
self.visit_local_assignment(local_assignment) self.visit_local_assignment(local_assignment)
} }
Stmt::LocalFunction(local_function) => { Stmt::LocalFunction(local_function) => self.visit_local_function(local_function),
self.visit_local_function(local_function) Stmt::NumericFor(numeric_for) => self.visit_numeric_for(numeric_for),
} Stmt::Repeat(repeat) => self.visit_repeat(repeat),
Stmt::NumericFor(numeric_for) => { Stmt::While(while_) => self.visit_while(while_),
self.visit_numeric_for(numeric_for)
}
Stmt::Repeat(repeat) => {
self.visit_repeat(repeat)
}
Stmt::While(while_) => {
self.visit_while(while_)
}
// Stmt::CompoundAssignment(compound_assignment) => { // Stmt::CompoundAssignment(compound_assignment) => {
// self.visit_compound_assignment(compound_assignment) // self.visit_compound_assignment(compound_assignment)
// } // }
@ -52,12 +34,8 @@ pub trait Visitor {
// Stmt::TypeDeclaration(type_declaration) => { // Stmt::TypeDeclaration(type_declaration) => {
// self.visit_type_declaration(type_declaration) // self.visit_type_declaration(type_declaration)
// } // }
Stmt::Goto(goto) => { Stmt::Goto(goto) => self.visit_goto(goto),
self.visit_goto(goto) Stmt::Label(label) => self.visit_label(label),
}
Stmt::Label(label) => {
self.visit_label(label)
}
_ => {} _ => {}
}; };
} }