22
33use std:: { collections:: HashMap , fmt:: Display , iter:: zip} ;
44
5+ use super :: types:: * ;
56use 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-
926683impl < TC , OC > ScopeBuilder < ' _ , TC , OC >
927684where
928685 TC : Display + Clone ,
0 commit comments