Skip to content

Commit d595907

Browse files
committed
Merge branch 'refactor-nov-2025' into dev
2 parents 002224b + 2c94533 commit d595907

File tree

13 files changed

+270
-464
lines changed

13 files changed

+270
-464
lines changed

compiler/src/backend/bf2d.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use super::common::{
44
};
55
use crate::macros::macros::{r_assert, r_panic};
66

7-
use std::{fmt::Display, hash::Hash};
7+
use std::hash::Hash;
88

99
#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
1010
pub struct TapeCell2D(pub i32, pub i32);
@@ -102,7 +102,7 @@ impl BrainfuckProgram for Vec<Opcode2D> {
102102
}
103103
}
104104

105-
impl Display for TapeCell2D {
105+
impl std::fmt::Display for TapeCell2D {
106106
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107107
f.write_fmt(format_args!("({}, {})", self.0, self.1))?;
108108
Ok(())

compiler/src/backend/common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::constants_optimiser::calculate_optimal_addition;
22
use crate::{
3-
frontend::{CellLocation, Instruction, MemoryId},
3+
frontend::types::{CellLocation, Instruction, MemoryId},
44
macros::macros::{r_assert, r_panic},
55
misc::{MastermindConfig, MastermindContext},
66
parser::types::TapeCellLocation,
Lines changed: 2 additions & 245 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
use std::{collections::HashMap, fmt::Display, iter::zip};
44

5+
use super::types::*;
56
use crate::{
67
backend::common::{
78
BrainfuckBuilder, BrainfuckBuilderData, CellAllocator, CellAllocatorData, OpcodeVariant,
89
TapeCellVariant,
910
},
10-
macros::macros::{r_assert, r_panic},
11+
macros::macros::*,
1112
misc::MastermindContext,
1213
parser::{
1314
expressions::Expression,
@@ -654,85 +655,6 @@ function arguments are not supported."
654655
}
655656
}
656657

657-
// this is subject to change
658-
#[derive(Debug, Clone)]
659-
pub enum Instruction<TC, OC> {
660-
Allocate(Memory, Option<TC>),
661-
Free(MemoryId), // the number indicates which cell in the allocation stack should be freed (cell 0, is the top of the stack, 1 is the second element, etc)
662-
OpenLoop(CellReference), // same with other numbers here, they indicate the cell in the allocation stack to use in the instruction
663-
CloseLoop(CellReference), // pass in the cell id, this originally wasn't there but may be useful later on
664-
AddToCell(CellReference, u8),
665-
InputToCell(CellReference),
666-
ClearCell(CellReference), // not sure if this should be here, seems common enough that it should be
667-
AssertCellValue(CellReference, Option<u8>), // allows the user to hand-tune optimisations further
668-
OutputCell(CellReference),
669-
InsertBrainfuckAtCell(Vec<OC>, CellLocation<TC>),
670-
}
671-
672-
#[derive(Debug, Clone)]
673-
/// Either a fixed constant cell or a reference to some existing memory
674-
pub enum CellLocation<TC> {
675-
Unspecified,
676-
FixedCell(TC),
677-
MemoryCell(CellReference),
678-
}
679-
680-
#[derive(Debug, Clone)]
681-
pub enum Memory {
682-
Cell {
683-
id: MemoryId,
684-
},
685-
Cells {
686-
id: MemoryId,
687-
len: usize,
688-
},
689-
/// A memory cell that references a previously allocated cell in an outer scope, used for function arguments
690-
MappedCell {
691-
id: MemoryId,
692-
index: Option<usize>,
693-
},
694-
/// Memory mapped cells, referencing previously allocated cells in an outer scope
695-
MappedCells {
696-
id: MemoryId,
697-
start_index: usize,
698-
len: usize,
699-
},
700-
// infinite cell something (TODO?)
701-
}
702-
pub type MemoryId = usize;
703-
704-
#[derive(Debug, Clone, Copy)]
705-
pub struct CellReference {
706-
pub memory_id: MemoryId,
707-
pub index: Option<usize>,
708-
}
709-
710-
impl Memory {
711-
pub fn id(&self) -> MemoryId {
712-
match self {
713-
Memory::Cell { id }
714-
| Memory::Cells { id, len: _ }
715-
| Memory::MappedCell { id, index: _ }
716-
| Memory::MappedCells {
717-
id,
718-
start_index: _,
719-
len: _,
720-
} => *id,
721-
}
722-
}
723-
pub fn len(&self) -> usize {
724-
match self {
725-
Memory::Cell { id: _ } | Memory::MappedCell { id: _, index: _ } => 1,
726-
Memory::Cells { id: _, len }
727-
| Memory::MappedCells {
728-
id: _,
729-
start_index: _,
730-
len,
731-
} => *len,
732-
}
733-
}
734-
}
735-
736658
#[derive(Clone, Debug)]
737659
/// Scope type represents a Mastermind code block,
738660
/// any variables or functions defined within a {block} are owned by the scope and cleaned up before continuing
@@ -758,171 +680,6 @@ pub struct ScopeBuilder<'a, TC, OC> {
758680
instructions: Vec<Instruction<TC, OC>>,
759681
}
760682

761-
#[derive(Clone, Debug)] // probably shouldn't be cloning here but whatever
762-
struct Function<TC, OC> {
763-
arguments: Vec<(String, ValueType)>,
764-
block: Vec<Clause<TC, OC>>,
765-
}
766-
767-
#[derive(Clone, Debug, PartialEq, Eq)]
768-
/// an absolute definition of a type, as opposed to `VariableTypeReference` which is more of a reference
769-
enum ValueType {
770-
Cell,
771-
Array(usize, Box<ValueType>),
772-
DictStruct(Vec<(String, ValueType, Option<usize>)>),
773-
// TupleStruct(Vec<ValueType>),
774-
}
775-
776-
#[derive(Clone, Debug)]
777-
/// equivalent to ValueType::DictStruct enum variant,
778-
/// Rust doesn't support enum variants as types yet so need this workaround for struct definitions in scope object
779-
struct DictStructType(Vec<(String, ValueType, Option<usize>)>);
780-
impl ValueType {
781-
fn from_struct(struct_def: DictStructType) -> Self {
782-
ValueType::DictStruct(struct_def.0)
783-
}
784-
785-
// TODO: make size() and get_and_validate_subfield_cell_map() more efficient,
786-
// currently these two recurse back and forth and are a bit of a monster combo
787-
788-
/// return the type size in cells
789-
fn size(&self) -> Result<usize, String> {
790-
Ok(match self {
791-
ValueType::Cell => 1,
792-
ValueType::Array(len, value_type) => *len * value_type.size()?,
793-
ValueType::DictStruct(fields) => Self::get_and_validate_subfield_cell_map(fields)?.1,
794-
})
795-
}
796-
797-
/// deterministically place all struct subfields on a non-negative cell, return the positions of each and the total length
798-
/// return Err() if location specified subfields overlap
799-
fn get_and_validate_subfield_cell_map(
800-
fields: &Vec<(String, ValueType, Option<usize>)>,
801-
) -> Result<(HashMap<&String, (usize, &ValueType)>, usize), String> {
802-
// (set of cells, max cell)
803-
let mut cell_map = HashMap::new();
804-
805-
// map of field names and their starting cells
806-
let mut subfield_map = HashMap::new();
807-
let mut max_cell = 0usize;
808-
let mut unfixed_fields = vec![];
809-
// handle the cells with specified locations
810-
for (field_name, field_type, field_location) in fields {
811-
match field_location {
812-
Some(location) => {
813-
subfield_map.insert(field_name, (*location, field_type));
814-
for cell_index in *location..(*location + field_type.size()?) {
815-
// this assumes the field locations have been validated
816-
if let Some(other_name) = cell_map.insert(cell_index, field_name) {
817-
r_panic!(
818-
"Subfields \"{other_name}\" and \"{field_name}\" overlap in struct."
819-
);
820-
};
821-
max_cell = max_cell.max(cell_index);
822-
}
823-
}
824-
None => {
825-
unfixed_fields.push((field_name, field_type));
826-
}
827-
}
828-
}
829-
830-
for (field_name, field_type) in unfixed_fields {
831-
let field_size = field_type.size()?;
832-
// repeatedly try to insert the fields into leftover memory locations
833-
let mut start_index = 0usize;
834-
for cur_index in 0.. {
835-
if cell_map.contains_key(&cur_index) {
836-
start_index = cur_index + 1;
837-
} else if (cur_index - start_index + 1) >= field_size {
838-
// found a run with the right amount of cells free
839-
break;
840-
}
841-
}
842-
subfield_map.insert(field_name, (start_index, field_type));
843-
for cell_index in start_index..(start_index + field_size) {
844-
// inefficient but whatever, this insert is not necessary
845-
cell_map.insert(cell_index, field_name);
846-
max_cell = max_cell.max(cell_index);
847-
}
848-
}
849-
850-
let size = max_cell + 1;
851-
852-
Ok((subfield_map, size))
853-
}
854-
855-
/// get a subfield's type as well as memory cell index
856-
pub fn get_subfield(
857-
&self,
858-
subfield_chain: &VariableTargetReferenceChain,
859-
) -> Result<(&ValueType, usize), String> {
860-
let mut cur_field = self;
861-
let mut cur_index = 0;
862-
for subfield_ref in subfield_chain.0.iter() {
863-
match (cur_field, subfield_ref) {
864-
(ValueType::Array(len, element_type), Reference::Index(index)) => {
865-
r_assert!(
866-
index < len,
867-
"Index \"{subfield_ref}\" must be less than array length ({len})."
868-
);
869-
cur_index += element_type.size()? * index;
870-
cur_field = element_type;
871-
}
872-
(ValueType::DictStruct(fields), Reference::NamedField(subfield_name)) => {
873-
let (subfield_map, _size) = Self::get_and_validate_subfield_cell_map(fields)?;
874-
let Some((subfield_cell_offset, subfield_type)) =
875-
subfield_map.get(subfield_name)
876-
else {
877-
r_panic!("Could not find subfield \"{subfield_ref}\" in struct type")
878-
};
879-
cur_index += subfield_cell_offset;
880-
cur_field = subfield_type;
881-
}
882-
883-
(ValueType::DictStruct(_), Reference::Index(_)) => {
884-
r_panic!("Cannot read index subfield \"{subfield_ref}\" of struct type.")
885-
}
886-
(ValueType::Array(_, _), Reference::NamedField(_)) => {
887-
r_panic!("Cannot read named subfield \"{subfield_ref}\" of array type.")
888-
}
889-
(ValueType::Cell, subfield_ref) => {
890-
r_panic!("Attempted to get subfield \"{subfield_ref}\" of cell type.")
891-
}
892-
}
893-
}
894-
Ok((cur_field, cur_index))
895-
}
896-
}
897-
898-
impl Display for ValueType {
899-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
900-
match self {
901-
ValueType::Cell => {
902-
f.write_str("cell")?;
903-
}
904-
ValueType::Array(length, element_type) => {
905-
f.write_fmt(format_args!("{element_type}[{length}]"))?;
906-
}
907-
ValueType::DictStruct(fields) => {
908-
f.write_str("{")?;
909-
let fields_len = fields.len();
910-
for (i, (field_name, field_type, offset)) in fields.iter().enumerate() {
911-
f.write_fmt(format_args!("{field_type} {field_name}"))?;
912-
if let Some(offset) = offset {
913-
f.write_fmt(format_args!(" @{offset}"))?;
914-
}
915-
f.write_str(";")?;
916-
if i < (fields_len - 1) {
917-
f.write_str(" ")?;
918-
}
919-
}
920-
}
921-
}
922-
Ok(())
923-
}
924-
}
925-
926683
impl<TC, OC> ScopeBuilder<'_, TC, OC>
927684
where
928685
TC: Display + Clone,

compiler/src/frontend/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod frontend;
2+
pub mod types;

0 commit comments

Comments
 (0)