parent
91f2eed15a
commit
4576609b1e
@ -0,0 +1,35 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Config {
|
||||||
|
pub builtin_functions: HashMap<String, (String, bool, usize)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
macro_rules! builtin_function {
|
||||||
|
( $name:expr, $target_name:expr, $mutating:expr, $n_args:expr ) => {
|
||||||
|
(
|
||||||
|
String::from($name),
|
||||||
|
(String::from($target_name), $mutating, $n_args),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
builtin_functions: HashMap::from([
|
||||||
|
builtin_function!("print_flush", "printflush", false, 1),
|
||||||
|
// TODO: write a special case for message
|
||||||
|
builtin_function!("print_message_mission", "message mission", false, 0),
|
||||||
|
builtin_function!("read", "read", true, 3),
|
||||||
|
// TODO: don't use a generic operation here
|
||||||
|
builtin_function!("write", "write", false, 3),
|
||||||
|
builtin_function!("wait", "wait", false, 1),
|
||||||
|
// TODO: don't use a generic operation here either
|
||||||
|
builtin_function!("set_flag", "setflag", false, 2),
|
||||||
|
builtin_function!("get_flag", "getflag", true, 2),
|
||||||
|
// TODO: same thing
|
||||||
|
builtin_function!("spawn", "spawn", false, 6),
|
||||||
|
]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,14 @@
|
|||||||
pub mod common;
|
pub mod config;
|
||||||
pub mod compile;
|
|
||||||
pub mod cursor;
|
pub mod cursor;
|
||||||
|
pub mod optimize;
|
||||||
pub mod parse;
|
pub mod parse;
|
||||||
|
pub mod repr;
|
||||||
|
pub mod translate;
|
||||||
|
|
||||||
|
pub mod prelude {
|
||||||
|
pub use crate::config::Config;
|
||||||
|
pub use crate::cursor::Cursor;
|
||||||
|
pub use crate::repr::basic::*;
|
||||||
|
pub use crate::repr::mlog::*;
|
||||||
|
pub use crate::repr::operator::*;
|
||||||
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
use regex::Regex;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
/// Optimizes away unnecessary `sets`
|
/// Optimizes away unnecessary `sets`
|
||||||
pub fn optimize_constant(program: MindustryProgram) -> MindustryProgram {
|
pub fn optimize_constant(program: MindustryProgram) -> MindustryProgram {
|
@ -1,4 +1,8 @@
|
|||||||
|
use regex::Regex;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub(crate) fn optimize_dead_code(program: MindustryProgram) -> MindustryProgram {
|
pub(crate) fn optimize_dead_code(program: MindustryProgram) -> MindustryProgram {
|
||||||
let tmp_regex = Regex::new(r"__tmp_[0-9]+$").unwrap();
|
let tmp_regex = Regex::new(r"__tmp_[0-9]+$").unwrap();
|
@ -1,4 +1,7 @@
|
|||||||
|
use regex::Regex;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
/// Tries to merge the condition in an `op` into the `jump` itself
|
/// Tries to merge the condition in an `op` into the `jump` itself
|
||||||
pub fn optimize_jump_op(program: MindustryProgram) -> MindustryProgram {
|
pub fn optimize_jump_op(program: MindustryProgram) -> MindustryProgram {
|
@ -1,6 +1,5 @@
|
|||||||
//! Lookaround helpers for quickly implementing optimizations
|
//! Lookaround helpers for quickly implementing optimizations
|
||||||
|
use crate::prelude::*;
|
||||||
use super::*;
|
|
||||||
|
|
||||||
pub(crate) enum Lookaround<T> {
|
pub(crate) enum Lookaround<T> {
|
||||||
Stop(T),
|
Stop(T),
|
@ -1,7 +1,3 @@
|
|||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
mod constant;
|
mod constant;
|
||||||
pub use constant::*;
|
pub use constant::*;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
use super::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub(crate) fn replace_if<F>(program: MindustryProgram, callback: F) -> MindustryProgram
|
pub(crate) fn replace_if<F>(program: MindustryProgram, callback: F) -> MindustryProgram
|
||||||
where
|
where
|
@ -0,0 +1,41 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum BasicAstExpression {
|
||||||
|
Integer(i64),
|
||||||
|
Float(f64),
|
||||||
|
Variable(String),
|
||||||
|
String(String),
|
||||||
|
Binary(Operator, Box<BasicAstExpression>, Box<BasicAstExpression>),
|
||||||
|
Unary(UnaryOperator, Box<BasicAstExpression>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum BasicAstInstruction {
|
||||||
|
JumpLabel(String),
|
||||||
|
Assign(String, BasicAstExpression),
|
||||||
|
Jump(String),
|
||||||
|
IfThenElse(BasicAstExpression, BasicAstBlock, BasicAstBlock),
|
||||||
|
Print(Vec<(BasicAstExpression, bool)>),
|
||||||
|
CallBuiltin(String, Vec<BasicAstExpression>),
|
||||||
|
For {
|
||||||
|
variable: String,
|
||||||
|
start: BasicAstExpression,
|
||||||
|
end: BasicAstExpression,
|
||||||
|
step: BasicAstExpression,
|
||||||
|
instructions: BasicAstBlock,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Default)]
|
||||||
|
pub struct BasicAstBlock {
|
||||||
|
pub instructions: Vec<BasicAstInstruction>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BasicAstBlock {
|
||||||
|
pub fn new(instructions: impl IntoIterator<Item = BasicAstInstruction>) -> Self {
|
||||||
|
Self {
|
||||||
|
instructions: instructions.into_iter().collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,111 @@
|
|||||||
|
use super::operator::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Operand {
|
||||||
|
Variable(String),
|
||||||
|
String(String),
|
||||||
|
Integer(i64),
|
||||||
|
Float(f64),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Operand {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Operand::Variable(name) => write!(f, "{}", name),
|
||||||
|
Operand::String(string) => {
|
||||||
|
let escaped = string.replace('\\', r"\\").replace('"', r#"\""#);
|
||||||
|
write!(f, "\"{}\"", escaped)
|
||||||
|
}
|
||||||
|
Operand::Integer(int) => write!(f, "{}", int),
|
||||||
|
Operand::Float(float) => write!(f, "{}", float),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum MindustryOperation {
|
||||||
|
JumpLabel(String),
|
||||||
|
Jump(String),
|
||||||
|
JumpIf(String, Operator, Operand, Operand),
|
||||||
|
Operator(String, Operator, Operand, Operand),
|
||||||
|
UnaryOperator(String, UnaryOperator, Operand),
|
||||||
|
// TODO: add RandOperator
|
||||||
|
Set(String, Operand),
|
||||||
|
/// A generic operation, with the following invariants:
|
||||||
|
/// - all of the operands are read-only
|
||||||
|
/// - there is no external dependency to other variables
|
||||||
|
/// - no external variable is modified
|
||||||
|
Generic(String, Vec<Operand>),
|
||||||
|
/// A generic, mutating operation `(name, out_name, operands)`, with the following invariants:
|
||||||
|
/// - all of the operands are read-only
|
||||||
|
/// - there is no external dependency to other variables, except `out_name`
|
||||||
|
/// - only `out_name` is modified
|
||||||
|
GenericMut(String, String, Vec<Operand>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MindustryOperation {
|
||||||
|
pub(crate) fn operands(&self) -> Box<[&Operand]> {
|
||||||
|
match self {
|
||||||
|
Self::JumpIf(_label, _operator, lhs, rhs) => Box::new([lhs, rhs]),
|
||||||
|
Self::Operator(_target, _operator, lhs, rhs) => Box::new([lhs, rhs]),
|
||||||
|
Self::UnaryOperator(_target, _operator, value) => Box::new([value]),
|
||||||
|
Self::Set(_target, value) => Box::new([value]),
|
||||||
|
Self::Generic(_name, operands) => {
|
||||||
|
operands.iter().collect::<Vec<_>>().into_boxed_slice()
|
||||||
|
}
|
||||||
|
Self::GenericMut(_name, _out_name, operands) => {
|
||||||
|
operands.iter().collect::<Vec<_>>().into_boxed_slice()
|
||||||
|
}
|
||||||
|
_ => Box::new([]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn operands_mut(&mut self) -> Vec<&mut Operand> {
|
||||||
|
match self {
|
||||||
|
Self::JumpIf(_label, _operator, lhs, rhs) => vec![lhs, rhs],
|
||||||
|
Self::Operator(_target, _operator, lhs, rhs) => vec![lhs, rhs],
|
||||||
|
Self::UnaryOperator(_target, _operator, value) => vec![value],
|
||||||
|
Self::Set(_target, value) => vec![value],
|
||||||
|
Self::Generic(_name, operands) => operands.iter_mut().collect::<Vec<_>>(),
|
||||||
|
Self::GenericMut(_name, _out_name, operands) => operands.iter_mut().collect::<Vec<_>>(),
|
||||||
|
_ => vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn mutates(&self, var_name: &str) -> bool {
|
||||||
|
match self {
|
||||||
|
MindustryOperation::JumpLabel(_)
|
||||||
|
| MindustryOperation::Jump(_)
|
||||||
|
| MindustryOperation::JumpIf(_, _, _, _)
|
||||||
|
| MindustryOperation::Generic(_, _) => false,
|
||||||
|
|
||||||
|
MindustryOperation::Operator(out_name, _, _, _)
|
||||||
|
| MindustryOperation::UnaryOperator(out_name, _, _)
|
||||||
|
| MindustryOperation::Set(out_name, _)
|
||||||
|
| MindustryOperation::GenericMut(_, out_name, _) => out_name == var_name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct MindustryProgram(pub Vec<MindustryOperation>);
|
||||||
|
|
||||||
|
impl MindustryProgram {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(Vec::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, operation: MindustryOperation) {
|
||||||
|
self.0.push(operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append(&mut self, other: &mut Self) {
|
||||||
|
self.0.append(&mut other.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec<MindustryOperation>> for MindustryProgram {
|
||||||
|
fn from(value: Vec<MindustryOperation>) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
pub mod basic;
|
||||||
|
pub mod mlog;
|
||||||
|
pub mod operator;
|
Loading…
Reference in new issue