🚚 Re-structure code

main
Shad Amethyst 1 year ago
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 compile;
pub mod config;
pub mod cursor;
pub mod optimize;
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,7 +1,8 @@
use basic_to_mindustry::{
common::Config,
compile::{optimize_constant, optimize_jump_always, optimize_jump_op, translate_ast, Namer},
optimize::{optimize_constant, optimize_jump_always, optimize_jump_op},
parse::{build_ast, tokenize},
prelude::*,
translate::{translate_ast, Namer},
};
fn main() {

@ -1,4 +1,7 @@
use regex::Regex;
use super::*;
use crate::prelude::*;
/// Optimizes away unnecessary `sets`
pub fn optimize_constant(program: MindustryProgram) -> MindustryProgram {

@ -1,4 +1,8 @@
use regex::Regex;
use std::collections::HashSet;
use super::*;
use crate::prelude::*;
pub(crate) fn optimize_dead_code(program: MindustryProgram) -> MindustryProgram {
let tmp_regex = Regex::new(r"__tmp_[0-9]+$").unwrap();

@ -1,4 +1,7 @@
use regex::Regex;
use super::*;
use crate::prelude::*;
/// Tries to merge the condition in an `op` into the `jump` itself
pub fn optimize_jump_op(program: MindustryProgram) -> MindustryProgram {

@ -1,6 +1,5 @@
//! Lookaround helpers for quickly implementing optimizations
use super::*;
use crate::prelude::*;
pub(crate) enum Lookaround<T> {
Stop(T),

@ -1,7 +1,3 @@
use std::collections::HashSet;
use super::*;
mod constant;
pub use constant::*;

@ -1,4 +1,4 @@
use super::*;
use crate::prelude::*;
pub(crate) fn replace_if<F>(program: MindustryProgram, callback: F) -> MindustryProgram
where

@ -1,46 +1,7 @@
use super::*;
use crate::common::*;
use crate::cursor::Cursor;
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(),
}
}
}
pub fn build_ast(tokens: &[BasicToken], config: &Config) -> Result<BasicAstBlock, ParseError> {
enum Context {
Main,

@ -1,7 +1,5 @@
use crate::common::*;
use crate::cursor::Cursor;
use super::*;
use crate::prelude::*;
#[test]
fn test_tokenize_basic() {

@ -1,5 +1,5 @@
use super::ParseError;
use crate::common::*;
use crate::prelude::*;
use regex::Regex;
#[derive(PartialEq, Clone, Debug)]

@ -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;

@ -1,5 +1,3 @@
use std::collections::HashMap;
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Operator {
Add,
@ -98,37 +96,3 @@ pub(crate) fn format_unary_operator(operator: UnaryOperator) -> &'static str {
UnaryOperator::Sqrt => "sqrt",
}
}
#[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,120 +1,6 @@
use regex::Regex;
use crate::common::*;
use crate::parse::{BasicAstBlock, BasicAstExpression};
mod optimize;
pub use optimize::*;
#[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 {
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([]),
}
}
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![],
}
}
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)
}
}
use crate::prelude::*;
pub struct Namer {
var_index: usize,
@ -205,7 +91,7 @@ pub fn translate_ast(
namer: &mut Namer,
config: &Config,
) -> MindustryProgram {
use crate::parse::BasicAstInstruction as Instr;
use crate::repr::basic::BasicAstInstruction as Instr;
let mut res = MindustryProgram::new();
for instruction in basic_ast.instructions.iter() {

@ -2,11 +2,10 @@
use std::path::{Path, PathBuf};
use basic_to_mindustry::common::Config;
use basic_to_mindustry::compile::{
optimize_constant, optimize_jump_always, optimize_jump_op, translate_ast,
};
use basic_to_mindustry::optimize::{optimize_constant, optimize_jump_always, optimize_jump_op};
use basic_to_mindustry::parse::{build_ast, tokenize};
use basic_to_mindustry::prelude::*;
use basic_to_mindustry::translate::translate_ast;
fn read_basic_examples() -> impl Iterator<Item = (String, String)> {
Path::new("./examples/")

Loading…
Cancel
Save