From a69fe713a93239501742cf8a501fb15cfa9692f2 Mon Sep 17 00:00:00 2001
From: Graham Nelson
Date: Mon, 25 Oct 2021 23:59:20 +0100
Subject: [PATCH] Improvements to memory model
---
docs/final-module/2-cg.html | 6 +-
docs/final-module/2-cg2.html | 2 +-
docs/final-module/5-cgv.html | 17 +
docs/final-module/5-clt.html | 72 +-
docs/final-module/5-cmm.html | 773 +++++++++---------
docs/final-module/5-cnm.html | 16 +-
docs/final-module/5-com.html | 36 +-
docs/final-module/5-cpc.html | 4 +-
docs/final-module/5-fnc.html | 16 +-
inform7/Figures/timings-diagnostics.txt | 16 +-
inform7/Internal/Miscellany/inform7_clib.c | 210 +++--
inform7/Internal/Miscellany/inform7_clib.h | 24 +-
.../Chapter 5/C Global Variables.w | 15 +
inter/final-module/Chapter 5/C Literals.w | 10 +
inter/final-module/Chapter 5/C Memory Model.w | 681 ++++++++-------
inter/final-module/Chapter 5/C Namespace.w | 13 +-
inter/final-module/Chapter 5/C Object Model.w | 14 +-
inter/final-module/Chapter 5/Final C.w | 12 +-
18 files changed, 1007 insertions(+), 930 deletions(-)
diff --git a/docs/final-module/2-cg.html b/docs/final-module/2-cg.html
index 6f41af25c..c63764d8e 100644
--- a/docs/final-module/2-cg.html
+++ b/docs/final-module/2-cg.html
@@ -414,7 +414,7 @@ but for now about 10 layers is plenty.
-segmentation_pos CodeGen::select ( code_generation * gen , int i ) {
+segmentation_pos CodeGen::select ( code_generation * gen , int i ) {
return CodeGen::select_layered ( gen , i , 1 );
}
@@ -431,7 +431,7 @@ but for now about 10 layers is plenty.
return previous_pos ;
}
-void CodeGen::deselect ( code_generation * gen , segmentation_pos saved ) {
+void CodeGen::deselect ( code_generation * gen , segmentation_pos saved ) {
if ( gen -> segmentation . temporarily_diverted ) internal_error ( "poorly timed deselection" );
gen -> segmentation . pos = saved ;
}
@@ -457,7 +457,7 @@ if it has been "temporarily diverted" then the regiular selection is ignored.
-text_stream * CodeGen::current ( code_generation * gen ) {
+text_stream * CodeGen::current ( code_generation * gen ) {
if ( gen -> segmentation . temporarily_diverted )
return gen -> segmentation . temporarily_diverted_to ;
if ( gen -> segmentation . pos . current_segment == NULL ) return NULL ;
diff --git a/docs/final-module/2-cg2.html b/docs/final-module/2-cg2.html
index 2c9c27c4f..46937710a 100644
--- a/docs/final-module/2-cg2.html
+++ b/docs/final-module/2-cg2.html
@@ -336,7 +336,7 @@ I6 code. Still, all pragmas are offered to all generators.
VOID_METHOD_TYPE ( MANGLE_IDENTIFIER_MTID , code_generator * generator , text_stream * OUT , text_stream * identifier )
-void Generators::mangle ( code_generation * gen , text_stream * OUT , text_stream * identifier ) {
+void Generators::mangle ( code_generation * gen , text_stream * OUT , text_stream * identifier ) {
VOID_METHOD_CALL ( gen -> generator , MANGLE_IDENTIFIER_MTID , OUT , identifier );
}
diff --git a/docs/final-module/5-cgv.html b/docs/final-module/5-cgv.html
index 04be02a16..666772f81 100644
--- a/docs/final-module/5-cgv.html
+++ b/docs/final-module/5-cgv.html
@@ -21,6 +21,7 @@ function togglePopup(material_id) {
+
@@ -224,6 +225,22 @@ but has no Inter declaration node.
WRITE ( "]" );
}
+
+
+
+This is part of the extract file inform7_clib.h.
+
+This is part of the extract file inform7_clib.c.
diff --git a/docs/final-module/5-clt.html b/docs/final-module/5-clt.html
index 4f0536916..e9f8ba8dd 100644
--- a/docs/final-module/5-clt.html
+++ b/docs/final-module/5-clt.html
@@ -83,7 +83,8 @@ function togglePopup(material_id) {
METHOD_ADD ( cgt , COMPILE_DICTIONARY_WORD_MTID , CLiteralsModel::compile_dictionary_word );
METHOD_ADD ( cgt , COMPILE_LITERAL_NUMBER_MTID , CLiteralsModel::compile_literal_number );
METHOD_ADD ( cgt , COMPILE_LITERAL_REAL_MTID , CLiteralsModel::compile_literal_real );
- METHOD_ADD ( cgt , COMPILE_LITERAL_TEXT_MTID , CLiteralsModel::compile_literal_text );
+ METHOD_ADD ( cgt , COMPILE_LITERAL_TEXT_MTID , CLiteralsModel::compile_literal_text );
+ METHOD_ADD ( cgt , COMPILE_LITERAL_SYMBOL_MTID , CLiteralsModel::compile_literal_symbol );
METHOD_ADD ( cgt , NEW_ACTION_MTID , CLiteralsModel::new_action );
}
@@ -182,14 +183,14 @@ function togglePopup(material_id) {
int dictlen = C_GEN_DATA ( litdata . C_dword_count );
segmentation_pos saved = CodeGen::select ( gen , c_predeclarations_I7CGS );
- CMemoryModel::begin_array ( NULL , gen , I "#dictionary_table" , NULL , NULL , BYTE_ARRAY_FORMAT , NULL );
+ CMemoryModel::begin_array ( NULL , gen , I "#dictionary_table" , NULL , NULL , BYTE_ARRAY_FORMAT , NULL );
for ( int b =0; b <4; b ++) {
TEMPORARY_TEXT ( N )
WRITE_TO ( N , "I7BYTE_%d(%d)" , b , dictlen );
- CMemoryModel::array_entry ( NULL , gen , N , BYTE_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , N , BYTE_ARRAY_FORMAT );
DISCARD_TEXT ( N )
}
- CMemoryModel::end_array ( NULL , gen , BYTE_ARRAY_FORMAT , NULL );
+ CMemoryModel::end_array ( NULL , gen , BYTE_ARRAY_FORMAT , NULL );
if ( dictlen == 0 ) return ;
C_dword ** sorted = ( C_dword **)
@@ -199,10 +200,10 @@ function togglePopup(material_id) {
qsort ( sorted , ( size_t ) LinkedLists::len ( C_GEN_DATA ( litdata . words )), sizeof ( C_dword *), CLiteralsModel::compare_dwords );
for ( int i =0; i < dictlen ; i ++) {
dw = sorted [ i ];
- CMemoryModel::begin_array ( NULL , gen , sorted [ i ]-> identifier , NULL , NULL , BYTE_ARRAY_FORMAT , NULL );
+ CMemoryModel::begin_array ( NULL , gen , sorted [ i ]-> identifier , NULL , NULL , BYTE_ARRAY_FORMAT , NULL );
TEMPORARY_TEXT ( N )
WRITE_TO ( N , "0x60" );
- CMemoryModel::array_entry ( NULL , gen , N , BYTE_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , N , BYTE_ARRAY_FORMAT );
DISCARD_TEXT ( N );
for ( int i =0; i <9; i ++) {
TEMPORARY_TEXT ( N )
@@ -211,7 +212,7 @@ function togglePopup(material_id) {
else WRITE_TO ( N , "'%c'" , Str::get_at ( dw -> text , i ));
} else
WRITE_TO ( N , "0" );
- CMemoryModel::array_entry ( NULL , gen , N , BYTE_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , N , BYTE_ARRAY_FORMAT );
DISCARD_TEXT ( N );
}
TEMPORARY_TEXT ( DP1H )
@@ -228,17 +229,17 @@ function togglePopup(material_id) {
WRITE_TO ( DP1L , "((%d)%%256)" , f );
WRITE_TO ( DP2H , "((%d)/256)" , 0xFFFF - dw -> verb_number );
WRITE_TO ( DP2L , "((%d)%%256)" , 0xFFFF - dw -> verb_number );
- CMemoryModel::array_entry ( NULL , gen , DP1H , BYTE_ARRAY_FORMAT );
- CMemoryModel::array_entry ( NULL , gen , DP1L , BYTE_ARRAY_FORMAT );
- CMemoryModel::array_entry ( NULL , gen , DP2H , BYTE_ARRAY_FORMAT );
- CMemoryModel::array_entry ( NULL , gen , DP2L , BYTE_ARRAY_FORMAT );
- CMemoryModel::array_entry ( NULL , gen , I "0" , BYTE_ARRAY_FORMAT );
- CMemoryModel::array_entry ( NULL , gen , I "0" , BYTE_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , DP1H , BYTE_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , DP1L , BYTE_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , DP2H , BYTE_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , DP2L , BYTE_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , I "0" , BYTE_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , I "0" , BYTE_ARRAY_FORMAT );
DISCARD_TEXT ( DP1H )
DISCARD_TEXT ( DP1L )
DISCARD_TEXT ( DP2H )
DISCARD_TEXT ( DP2L )
- CMemoryModel::end_array ( NULL , gen , BYTE_ARRAY_FORMAT , NULL );
+ CMemoryModel::end_array ( NULL , gen , BYTE_ARRAY_FORMAT , NULL );
}
Memory::I7_free ( sorted , CODE_GENERATION_MREASON , dictlen );
CodeGen::deselect ( gen , saved );
@@ -258,7 +259,7 @@ function togglePopup(material_id) {
CNamespace::mangle ( cgt , OUT , dw -> identifier );
}
-void CLiteralsModel::verb_grammar ( code_generator * cgt , code_generation * gen ,
+void CLiteralsModel::verb_grammar ( code_generator * cgt , code_generation * gen ,
inter_symbol * array_s , inter_tree_node * P ) {
inter_tree * I = gen -> from ;
int verbnum = C_GEN_DATA ( litdata . verb_count )++;
@@ -492,25 +493,25 @@ function togglePopup(material_id) {
}
void CLiteralsModel::compile_verb_table ( code_generation * gen ) {
- CMemoryModel::begin_array ( NULL , gen , I "#grammar_table" , NULL , NULL , WORD_ARRAY_FORMAT , NULL );
+ CMemoryModel::begin_array ( NULL , gen , I "#grammar_table" , NULL , NULL , WORD_ARRAY_FORMAT , NULL );
TEMPORARY_TEXT ( N )
WRITE_TO ( N , "%d" , C_GEN_DATA ( litdata . verb_count ) - 1 );
- CMemoryModel::array_entry ( NULL , gen , N , WORD_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , N , WORD_ARRAY_FORMAT );
DISCARD_TEXT ( N )
C_dword * dw ; int c = 1 ;
LOOP_OVER_LINKED_LIST ( dw , C_dword , C_GEN_DATA ( litdata . verbs )) {
TEMPORARY_TEXT ( N )
WRITE_TO ( N , "(i7_ss_grammar_table_cont+%d /* %d: %S */ )" , dw -> grammar_table_offset , c ++, dw -> text );
- CMemoryModel::array_entry ( NULL , gen , N , WORD_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , N , WORD_ARRAY_FORMAT );
DISCARD_TEXT ( N )
}
- CMemoryModel::end_array ( NULL , gen , WORD_ARRAY_FORMAT , NULL );
- CMemoryModel::begin_array ( NULL , gen , I "#grammar_table_cont" , NULL , NULL , BYTE_ARRAY_FORMAT , NULL );
+ CMemoryModel::end_array ( NULL , gen , WORD_ARRAY_FORMAT , NULL );
+ CMemoryModel::begin_array ( NULL , gen , I "#grammar_table_cont" , NULL , NULL , BYTE_ARRAY_FORMAT , NULL );
text_stream * entry ;
LOOP_OVER_LINKED_LIST ( entry , text_stream , C_GEN_DATA ( litdata . verb_grammar )) {
- CMemoryModel::array_entry ( NULL , gen , entry , BYTE_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , entry , BYTE_ARRAY_FORMAT );
}
- CMemoryModel::end_array ( NULL , gen , BYTE_ARRAY_FORMAT , NULL );
+ CMemoryModel::end_array ( NULL , gen , BYTE_ARRAY_FORMAT , NULL );
}
void CLiteralsModel::new_action ( code_generator * cgt , code_generation * gen , text_stream * name , int true_action ) {
@@ -527,19 +528,19 @@ function togglePopup(material_id) {
}
void CLiteralsModel::compile_actions_table ( code_generation * gen ) {
- CMemoryModel::begin_array ( NULL , gen , I "#actions_table" , NULL , NULL , WORD_ARRAY_FORMAT , NULL );
+ CMemoryModel::begin_array ( NULL , gen , I "#actions_table" , NULL , NULL , WORD_ARRAY_FORMAT , NULL );
TEMPORARY_TEXT ( N )
WRITE_TO ( N , "%d" , C_GEN_DATA ( litdata . C_action_count ));
- CMemoryModel::array_entry ( NULL , gen , N , WORD_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , N , WORD_ARRAY_FORMAT );
DISCARD_TEXT ( N )
text_stream * an ;
LOOP_OVER_LINKED_LIST ( an , text_stream , C_GEN_DATA ( litdata . actions )) {
TEMPORARY_TEXT ( N )
WRITE_TO ( N , "i7_mgl_%SSub" , an );
- CMemoryModel::array_entry ( NULL , gen , N , WORD_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , N , WORD_ARRAY_FORMAT );
DISCARD_TEXT ( N )
}
- CMemoryModel::end_array ( NULL , gen , WORD_ARRAY_FORMAT , NULL );
+ CMemoryModel::end_array ( NULL , gen , WORD_ARRAY_FORMAT , NULL );
}
The structure C_dword is accessed in 5/com and here.
@@ -749,6 +750,15 @@ function togglePopup(material_id) {
The function CLiteralsModel::pow10_cheap appears nowhere else.
+
+void CLiteralsModel::compile_literal_symbol ( code_generator * cgt , code_generation * gen , inter_symbol * aliased ) {
+ text_stream * OUT = CodeGen::current ( gen );
+ text_stream * S = Inter::Symbols::name ( aliased );
+ Generators::mangle ( gen , OUT , S );
+}
+
+
+
int CLiteralsModel::hex_val ( wchar_t c ) {
if (( c >= '0' ) && ( c <= '9' )) return c - '0' ;
@@ -756,7 +766,7 @@ function togglePopup(material_id) {
if (( c >= 'A' ) && ( c <= 'F' )) return c - 'A' + 10 ;
return -1;
}
-void CLiteralsModel::compile_literal_text ( code_generator * cgt , code_generation * gen ,
+void CLiteralsModel::compile_literal_text ( code_generator * cgt , code_generation * gen ,
text_stream * S , int escape_mode ) {
text_stream * OUT = CodeGen::current ( gen );
@@ -780,7 +790,7 @@ function togglePopup(material_id) {
} else if ( Str::get_at ( S , i +1) == '{' ) {
int cc = 0 ; i ++;
while (( Str::get_at ( S , ++ i ) != '}' ) && ( Str::get_at ( S , i ) != 0 ))
- cc = 16 * cc + CLiteralsModel::hex_val ( Str::get_at ( S , i ));
+ cc = 16 * cc + CLiteralsModel::hex_val ( Str::get_at ( S , i ));
if (( cc == '\n' ) || ( cc == '\"' ) || ( cc == '\\' )) PUT ( '\\' );
PUT ( cc );
} else WRITE ( "@" );
@@ -811,11 +821,11 @@ function togglePopup(material_id) {
if ( gen -> literal_text_mode != PRINTING_LTM ) WRITE ( ",\n" );
}
-int CLiteralsModel::no_strings ( code_generation * gen ) {
+int CLiteralsModel::no_strings ( code_generation * gen ) {
return C_GEN_DATA ( litdata . no_double_quoted_C_strings );
}
-int CLiteralsModel::invoke_primitive ( code_generation * gen , inter_ti bip , inter_tree_node * P ) {
+int CLiteralsModel::invoke_primitive ( code_generation * gen , inter_ti bip , inter_tree_node * P ) {
text_stream * OUT = CodeGen::current ( gen );
switch ( bip ) {
case PRINTSTRING_BIP: WRITE ( "i7_print_C_string(proc, dqs[" ); VNODE_1C ; WRITE ( " - I7VAL_STRINGS_BASE])" ); break ;
@@ -825,7 +835,7 @@ function togglePopup(material_id) {
return FALSE ;
}
-
+
How arrays of all kinds are stored in C.
-
+
-
-
-
-void CMemoryModel::initialise ( code_generator * cgt ) {
- METHOD_ADD ( cgt , BEGIN_ARRAY_MTID , CMemoryModel::begin_array );
- METHOD_ADD ( cgt , ARRAY_ENTRY_MTID , CMemoryModel::array_entry );
- METHOD_ADD ( cgt , COMPILE_LITERAL_SYMBOL_MTID , CMemoryModel::compile_literal_symbol );
- METHOD_ADD ( cgt , ARRAY_ENTRIES_MTID , CMemoryModel::array_entries );
- METHOD_ADD ( cgt , END_ARRAY_MTID , CMemoryModel::end_array );
-}
-
-typedef struct C_generation_memory_model_data {
- int himem ;
- struct text_stream * array_name ;
- int entry_count ;
-} C_generation_memory_model_data ;
-
-void CMemoryModel::initialise_data ( code_generation * gen ) {
- C_GEN_DATA ( memdata . himem ) = 0 ;
- C_GEN_DATA ( memdata . array_name ) = Str::new ();
- C_GEN_DATA ( memdata . entry_count ) = 0 ;
-}
-
-The structure C_generation_memory_model_data is accessed in 5/com and here.
-
(a) Byte-accessible memory must contain all of the arrays. These can but need
@@ -118,10 +94,35 @@ of 2 or 4.
(f) Arrays in memory are free to contain a mixture of bytes and words: some do.
(g) Data may be written in byte form and read back in word form, or vice versa.
-
+void CMemoryModel::initialise ( code_generator * cgt ) {
+ METHOD_ADD ( cgt , BEGIN_ARRAY_MTID , CMemoryModel::begin_array );
+ METHOD_ADD ( cgt , ARRAY_ENTRY_MTID , CMemoryModel::array_entry );
+ METHOD_ADD ( cgt , ARRAY_ENTRIES_MTID , CMemoryModel::array_entries );
+ METHOD_ADD ( cgt , END_ARRAY_MTID , CMemoryModel::end_array );
+}
+
+typedef struct C_generation_memory_model_data {
+ int himem ;
+ struct text_stream * array_name ;
+ int entry_count ;
+} C_generation_memory_model_data ;
+
+void CMemoryModel::initialise_data ( code_generation * gen ) {
+ C_GEN_DATA ( memdata . himem ) = 0 ;
+ C_GEN_DATA ( memdata . array_name ) = Str::new ();
+ C_GEN_DATA ( memdata . entry_count ) = 0 ;
+}
+
+The structure C_generation_memory_model_data is accessed in 5/com and here.
+
-
@@ -134,17 +135,14 @@ of 2 or 4.
CodeGen::deselect ( gen , saved );
}
-
void CMemoryModel::end ( code_generation * gen ) {
segmentation_pos saved = CodeGen::select ( gen , c_mem_I7CGS );
text_stream * OUT = CodeGen::current ( gen );
- WRITE ( "0, 0 };\n" );
-
+ WRITE ( "};\n" );
CodeGen::deselect ( gen , saved );
saved = CodeGen::select ( gen , c_ids_and_maxima_I7CGS );
@@ -153,31 +151,233 @@ in C.
CodeGen::deselect ( gen , saved );
}
-
+
+
+
+int CMemoryModel::begin_array ( code_generator * cgt , code_generation * gen ,
+ text_stream * array_name , inter_symbol * array_s , inter_tree_node * P , int format ,
+ segmentation_pos * saved ) {
+ Str::clear ( C_GEN_DATA ( memdata . array_name ));
+ WRITE_TO ( C_GEN_DATA ( memdata . array_name ), "%S" , array_name );
+ C_GEN_DATA ( memdata . entry_count ) = 0 ;
+ if (( array_s ) && ( Inter::Symbols::read_annotation ( array_s , VERBARRAY_IANN ) == 1 ))
+ Short-circuit the usual Vanilla algorithm by compiling the whole array now 4.1
+ else
+ Declare this array in concert with the usual Vanilla algorithm 4.2 ;
+}
+
+
+
+
+
+
+ if ( saved ) * saved = CodeGen::select ( gen , c_verb_arrays_I7CGS );
+ CLiteralsModel::verb_grammar ( cgt , gen , array_s , P );
+ return FALSE ;
+
+
+
+
+
+ if ( saved ) * saved = CodeGen::select ( gen , c_arrays_I7CGS );
+ text_stream * format_name = I "unknown" ;
+ Work out the format name 4.2.1 ;
+ Define a constant for the byte address in memory where the array begins 4.2.2 ;
+ if (( format == TABLE_ARRAY_FORMAT ) || ( format == BUFFER_ARRAY_FORMAT ))
+ Place the extent entry N at index 0 4.2.3 ;
+ return TRUE ;
+
+
+
+
+
+ switch ( format ) {
+ case BYTE_ARRAY_FORMAT: format_name = I "byte" ; break ;
+ case WORD_ARRAY_FORMAT: format_name = I "word" ; break ;
+ case BUFFER_ARRAY_FORMAT: format_name = I "buffer" ; break ;
+ case TABLE_ARRAY_FORMAT: format_name = I "table" ; break ;
+ }
+
+This code is used in §4.2 .
+
+
+
+
+
+
+
+ segmentation_pos saved = CodeGen::select ( gen , c_predeclarations_I7CGS );
+ text_stream * OUT = CodeGen::current ( gen );
+ WRITE ( "#define " );
+ CNamespace::mangle ( cgt , OUT , array_name );
+ WRITE ( " %d /* = position in memory of %S array %S */\n" ,
+ C_GEN_DATA ( memdata . himem ), format_name , array_name );
+ if ( array_s )
+ Inter::Symbols::annotate_i ( array_s , C_ARRAY_ADDRESS_IANN ,
+ ( inter_ti ) C_GEN_DATA ( memdata . himem ));
+ CodeGen::deselect ( gen , saved );
+
+This code is used in §4.2 .
+
+
+
+
+
+ TEMPORARY_TEXT ( extname )
+ CNamespace::mangle ( cgt , extname , array_name );
+ WRITE_TO ( extname , "__xt" );
+ CMemoryModel::array_entry ( cgt , gen , extname , format );
+ DISCARD_TEXT ( extname )
+
+This code is used in §4.2 .
+
+
+
+void CMemoryModel::array_entry ( code_generator * cgt , code_generation * gen ,
+ text_stream * entry , int format ) {
+ segmentation_pos saved = CodeGen::select ( gen , c_mem_I7CGS );
+ text_stream * OUT = CodeGen::current ( gen );
+ if (( format == TABLE_ARRAY_FORMAT ) || ( format == WORD_ARRAY_FORMAT ))
+ This is a word entry 5.2
+ else
+ This is a byte entry 5.1 ;
+ CodeGen::deselect ( gen , saved );
+ C_GEN_DATA ( memdata . entry_count )++;
+}
+
+
+
+
+ WRITE ( " (i7byte_t) %S, /* %d */\n" , entry , C_GEN_DATA ( memdata . himem ));
+ C_GEN_DATA ( memdata . himem ) += 1 ;
+
+
+
+
+
+
+
+ WRITE ( " I7BYTE_0(%S), I7BYTE_1(%S), I7BYTE_2(%S), I7BYTE_3(%S), /* %d */\n" ,
+ entry , entry , entry , entry , C_GEN_DATA ( memdata . himem ));
+ C_GEN_DATA ( memdata . himem ) += 4 ;
+
+
+
+
+
+void CMemoryModel::array_entries ( code_generator * cgt , code_generation * gen ,
+ int how_many , int format ) {
+ for ( int i =0; i < how_many ; i ++) CMemoryModel::array_entry ( cgt , gen , I "0" , format );
+}
+
+
+
+
+void CMemoryModel::end_array ( code_generator * cgt , code_generation * gen , int format ,
+ segmentation_pos * saved ) {
+ segmentation_pos x_saved = CodeGen::select ( gen , c_predeclarations_I7CGS );
+ text_stream * OUT = CodeGen::current ( gen );
+ WRITE ( "#define " );
+ CNamespace::mangle ( cgt , OUT , C_GEN_DATA ( memdata . array_name ));
+ WRITE ( "__xt %d\n" , C_GEN_DATA ( memdata . entry_count )-1);
+ CodeGen::deselect ( gen , x_saved );
+ if ( saved ) CodeGen::deselect ( gen , * saved );
+}
+
+
+
+
+primitive !lookup val val -> val
+primitive !lookupbyte val val -> val
+
+
+int CMemoryModel::handle_store_by_ref ( code_generation * gen , inter_tree_node * ref ) {
+ if ( Inter::Reference::node_is_ref_to ( gen -> from , ref , LOOKUP_BIP )) return TRUE ;
+ if ( Inter::Reference::node_is_ref_to ( gen -> from , ref , LOOKUPBYTE_BIP )) return TRUE ;
+ return FALSE ;
+}
+
+int CMemoryModel::invoke_primitive ( code_generation * gen , inter_ti bip , inter_tree_node * P ) {
+ text_stream * OUT = CodeGen::current ( gen );
+ switch ( bip ) {
+ case LOOKUP_BIP:
+ WRITE ( "i7_read_word(proc, " ); VNODE_1C ; WRITE ( ", " ); VNODE_2C ; WRITE ( ")" );
+ break ;
+ case LOOKUPBYTE_BIP:
+ WRITE ( "i7_read_byte(proc, " ); VNODE_1C ; WRITE ( " + " ); VNODE_2C ; WRITE ( ")" );
+ break ;
+ default:
+ return NOT_APPLICABLE ;
+ }
+ return FALSE ;
+}
+
+
+
+
+
+● The Release number as a big-endian 16-bit value at ;
+ ● The Serial code as six ASCII characters (in practice digits) at .
+
+
+
+
This is part of the extract file inform7_clib.h.
This is part of the extract file inform7_clib.c.
-
+
+
+
+
+This is part of the extract file inform7_clib.h.
+
+This is part of the extract file inform7_clib.c.
+
+
+
+This is part of the extract file inform7_clib.h.
+
+This is part of the extract file inform7_clib.c.
+
+
+
+This is part of the extract file inform7_clib.h.
+
+This is part of the extract file inform7_clib.c.
+
+
+
+This is part of the extract file inform7_clib.h.
+
+This is part of the extract file inform7_clib.c.
+
@@ -326,320 +641,6 @@ value without causing a memory leak, so we need explicit destructors.
This is part of the extract file inform7_clib.c.
-
-
-
-
-
-This is part of the extract file inform7_clib.h.
-
-This is part of the extract file inform7_clib.c.
-
-
-
-This is part of the extract file inform7_clib.h.
-
-This is part of the extract file inform7_clib.c.
-
-
-
-This is part of the extract file inform7_clib.h.
-
-This is part of the extract file inform7_clib.c.
-
-
-
-This is part of the extract file inform7_clib.h.
-
-This is part of the extract file inform7_clib.c.
-
-
-
-int CMemoryModel::begin_array ( code_generator * cgt , code_generation * gen ,
- text_stream * array_name , inter_symbol * array_s , inter_tree_node * P , int format , segmentation_pos * saved ) {
- if ( saved ) {
- int choice = c_arrays_at_eof_I7CGS ;
- if (( array_s ) && ( Inter::Symbols::read_annotation ( array_s , VERBARRAY_IANN ) == 1 ))
- choice = c_verbs_at_eof_I7CGS ;
- * saved = CodeGen::select ( gen , choice );
- }
- Str::clear ( C_GEN_DATA ( memdata . array_name ));
- WRITE_TO ( C_GEN_DATA ( memdata . array_name ), "%S" , array_name );
- C_GEN_DATA ( memdata . entry_count ) = 0 ;
-
- if (( array_s ) && ( Inter::Symbols::read_annotation ( array_s , VERBARRAY_IANN ) == 1 )) {
- CLiteralsModel::verb_grammar ( cgt , gen , array_s , P );
- return FALSE ;
- }
-
- text_stream * format_name = I "unknown" ;
- Work out the format name 11.1 ;
- Define a constant for the byte address in memory where the array begins 11.2 ;
- if (( format == TABLE_ARRAY_FORMAT ) || ( format == BUFFER_ARRAY_FORMAT ))
- Place the extent entry N at index 0 11.3 ;
- return TRUE ;
-}
-
-
-
-
- switch ( format ) {
- case BYTE_ARRAY_FORMAT: format_name = I "byte" ; break ;
- case WORD_ARRAY_FORMAT: format_name = I "word" ; break ;
- case BUFFER_ARRAY_FORMAT: format_name = I "buffer" ; break ;
- case TABLE_ARRAY_FORMAT: format_name = I "table" ; break ;
- }
-
-This code is used in §11 .
-
-
-
-
-
-
-
- segmentation_pos saved = CodeGen::select ( gen , c_predeclarations_I7CGS );
- text_stream * OUT = CodeGen::current ( gen );
- WRITE ( "#define " );
- CNamespace::mangle ( cgt , OUT , array_name );
- WRITE ( " %d /* = position in memory of %S array %S */\n" ,
- C_GEN_DATA ( memdata . himem ), format_name , array_name );
- if ( array_s )
- Inter::Symbols::annotate_i ( array_s , C_ARRAY_ADDRESS_IANN , ( inter_ti ) C_GEN_DATA ( memdata . himem ));
- CodeGen::deselect ( gen , saved );
-
-This code is used in §11 .
-
-
-
-
-
- TEMPORARY_TEXT ( extname )
- WRITE_TO ( extname , "xt_" );
- CNamespace::mangle ( cgt , extname , array_name );
- CMemoryModel::array_entry ( cgt , gen , extname , format );
- DISCARD_TEXT ( extname )
-
-This code is used in §11 .
-
-
-
-void CMemoryModel::array_entry ( code_generator * cgt , code_generation * gen ,
- text_stream * entry , int format ) {
- segmentation_pos saved = CodeGen::select ( gen , c_mem_I7CGS );
- text_stream * OUT = CodeGen::current ( gen );
- if (( format == TABLE_ARRAY_FORMAT ) || ( format == WORD_ARRAY_FORMAT ))
- This is a word entry 12.2
- else
- This is a byte entry 12.1 ;
- CodeGen::deselect ( gen , saved );
- C_GEN_DATA ( memdata . entry_count )++;
-}
-
-
-
-
- WRITE ( " (i7byte_t) %S, /* %d */\n" , entry , C_GEN_DATA ( memdata . himem ));
- C_GEN_DATA ( memdata . himem ) += 1 ;
-
-This code is used in §12 .
-
-
-
-
-
- WRITE ( " I7BYTE_0(%S), I7BYTE_1(%S), I7BYTE_2(%S), I7BYTE_3(%S), /* %d */\n" ,
- entry , entry , entry , entry , C_GEN_DATA ( memdata . himem ));
- C_GEN_DATA ( memdata . himem ) += 4 ;
-
-This code is used in §12 .
-
-
-
-void CMemoryModel::compile_literal_symbol ( code_generator * cgt , code_generation * gen , inter_symbol * aliased ) {
- text_stream * OUT = CodeGen::current ( gen );
- text_stream * S = Inter::Symbols::name ( aliased );
- Generators::mangle ( gen , OUT , S );
-}
-
-
-
-
-void CMemoryModel::array_entries ( code_generator * cgt , code_generation * gen ,
- int how_many , int format ) {
- for ( int i =0; i < how_many ; i ++) CMemoryModel::array_entry ( cgt , gen , I "0" , format );
-}
-
-
-
-
-void CMemoryModel::end_array ( code_generator * cgt , code_generation * gen , int format , segmentation_pos * saved ) {
- segmentation_pos x_saved = CodeGen::select ( gen , c_predeclarations_I7CGS );
- text_stream * OUT = CodeGen::current ( gen );
- WRITE ( "#define xt_" );
- CNamespace::mangle ( cgt , OUT , C_GEN_DATA ( memdata . array_name ));
- WRITE ( " %d\n" , C_GEN_DATA ( memdata . entry_count )-1);
- CodeGen::deselect ( gen , x_saved );
- if ( saved ) CodeGen::deselect ( gen , * saved );
-}
-
-
-
-
-primitive !lookup val val -> val
-primitive !lookupbyte val val -> val
-
-
-int CMemoryModel::handle_store_by_ref ( code_generation * gen , inter_tree_node * ref ) {
- if ( Inter::Reference::node_is_ref_to ( gen -> from , ref , LOOKUP_BIP )) return TRUE ;
- if ( Inter::Reference::node_is_ref_to ( gen -> from , ref , LOOKUPBYTE_BIP )) return TRUE ;
- return FALSE ;
-}
-
-int CMemoryModel::invoke_primitive ( code_generation * gen , inter_ti bip , inter_tree_node * P ) {
- text_stream * OUT = CodeGen::current ( gen );
- switch ( bip ) {
- case LOOKUP_BIP: WRITE ( "i7_read_word(proc, " ); VNODE_1C ; WRITE ( ", " ); VNODE_2C ; WRITE ( ")" );
- break ;
- case LOOKUPBYTE_BIP: WRITE ( "i7_read_byte(proc, " ); VNODE_1C ; WRITE ( " + " ); VNODE_2C ; WRITE ( ")" );
- break ;
- default: return NOT_APPLICABLE ;
- }
- return FALSE ;
-}
-
diff --git a/docs/final-module/5-cnm.html b/docs/final-module/5-cnm.html
index 4765aeb2d..4e030db17 100644
--- a/docs/final-module/5-cnm.html
+++ b/docs/final-module/5-cnm.html
@@ -110,7 +110,7 @@ sparingly in Inter, and these can never arise.
-void CNamespace::mangle ( code_generator * cgt , OUTPUT_STREAM , text_stream * identifier ) {
+void CNamespace::mangle ( code_generator * cgt , OUTPUT_STREAM , text_stream * identifier ) {
if ( Str::get_first_char ( identifier ) == '#' ) {
WRITE ( "i7_ss_" );
LOOP_THROUGH_TEXT ( pos , identifier )
@@ -207,17 +207,25 @@ to begin with
+
+
void CNamespace::declare_constant ( code_generator * cgt , code_generation * gen ,
inter_symbol * const_s , int form , text_stream * val ) {
- segmentation_pos saved = CodeGen::select_layered ( gen , c_constants_I7CGS ,
+ text_stream * name = Inter::Symbols::name ( const_s );
+ int seg = c_constants_I7CGS ;
+ if ( Str::eq ( name , I "Serial" )) seg = c_ids_and_maxima_I7CGS ;
+ if ( Str::eq ( name , I "Release" )) seg = c_ids_and_maxima_I7CGS ;
+ segmentation_pos saved = CodeGen::select_layered ( gen , seg ,
Inter::Constant::constant_depth ( const_s ));
text_stream * OUT = CodeGen::current ( gen );
WRITE ( "#define " );
- CNamespace::mangle ( cgt , OUT , Inter::Symbols::name ( const_s ));
+ CNamespace::mangle ( cgt , OUT , name );
WRITE ( " " );
VanillaConstants::definition_value ( gen , form , const_s , val );
WRITE ( "\n" );
diff --git a/docs/final-module/5-com.html b/docs/final-module/5-com.html
index d2f704f20..a9089476b 100644
--- a/docs/final-module/5-com.html
+++ b/docs/final-module/5-com.html
@@ -151,8 +151,8 @@ function togglePopup(material_id) {
- CMemoryModel::begin_array ( NULL , gen , I "value_ranges" , NULL , NULL , WORD_ARRAY_FORMAT , NULL );
- CMemoryModel::array_entry ( NULL , gen , I "0" , WORD_ARRAY_FORMAT );
+ CMemoryModel::begin_array ( NULL , gen , I "value_ranges" , NULL , NULL , WORD_ARRAY_FORMAT , NULL );
+ CMemoryModel::array_entry ( NULL , gen , I "0" , WORD_ARRAY_FORMAT );
inter_symbol * max_weak_id = InterSymbolsTables::url_name_to_symbol ( gen -> from , NULL ,
I "/main/synoptic/kinds/BASE_KIND_HWM" );
if ( max_weak_id ) {
@@ -166,23 +166,23 @@ function togglePopup(material_id) {
written = TRUE ;
TEMPORARY_TEXT ( N )
WRITE_TO ( N , "%d" , Inter::Kind::instance_count ( kind_name ));
- CMemoryModel::array_entry ( NULL , gen , N , WORD_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , N , WORD_ARRAY_FORMAT );
DISCARD_TEXT ( N )
}
}
}
- if ( written == FALSE ) CMemoryModel::array_entry ( NULL , gen , I "0" , WORD_ARRAY_FORMAT );
+ if ( written == FALSE ) CMemoryModel::array_entry ( NULL , gen , I "0" , WORD_ARRAY_FORMAT );
}
}
- CMemoryModel::end_array ( NULL , gen , WORD_ARRAY_FORMAT , NULL );
+ CMemoryModel::end_array ( NULL , gen , WORD_ARRAY_FORMAT , NULL );
- CMemoryModel::begin_array ( NULL , gen , I "value_property_holders" , NULL , NULL , WORD_ARRAY_FORMAT , NULL );
- CMemoryModel::array_entry ( NULL , gen , I "0" , WORD_ARRAY_FORMAT );
+ CMemoryModel::begin_array ( NULL , gen , I "value_property_holders" , NULL , NULL , WORD_ARRAY_FORMAT , NULL );
+ CMemoryModel::array_entry ( NULL , gen , I "0" , WORD_ARRAY_FORMAT );
inter_symbol * max_weak_id = InterSymbolsTables::url_name_to_symbol ( gen -> from , NULL ,
I "/main/synoptic/kinds/BASE_KIND_HWM" );
if ( max_weak_id ) {
@@ -196,15 +196,15 @@ function togglePopup(material_id) {
written = TRUE ;
TEMPORARY_TEXT ( N )
WRITE_TO ( N , "i7_mgl_VPH_%d" , w );
- CMemoryModel::array_entry ( NULL , gen , N , WORD_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( NULL , gen , N , WORD_ARRAY_FORMAT );
DISCARD_TEXT ( N )
}
}
}
- if ( written == FALSE ) CMemoryModel::array_entry ( NULL , gen , I "0" , WORD_ARRAY_FORMAT );
+ if ( written == FALSE ) CMemoryModel::array_entry ( NULL , gen , I "0" , WORD_ARRAY_FORMAT );
}
}
- CMemoryModel::end_array ( NULL , gen , WORD_ARRAY_FORMAT , NULL );
+ CMemoryModel::end_array ( NULL , gen , WORD_ARRAY_FORMAT , NULL );
This is part of the extract file inform7_clib.c.
diff --git a/docs/final-module/5-cpc.html b/docs/final-module/5-cpc.html
index 4090c5689..ca9289faa 100644
--- a/docs/final-module/5-cpc.html
+++ b/docs/final-module/5-cpc.html
@@ -87,9 +87,9 @@ function togglePopup(material_id) {
int r = CReferences::invoke_primitive ( gen , bip , P );
if ( r == NOT_APPLICABLE ) r = CArithmetic::invoke_primitive ( gen , bip , P );
-
if ( r == NOT_APPLICABLE ) r = CMemoryModel::invoke_primitive ( gen , bip , P );
+
if ( r == NOT_APPLICABLE ) r = CMemoryModel::invoke_primitive ( gen , bip , P );
if ( r == NOT_APPLICABLE ) r = CObjectModel::invoke_primitive ( gen , bip , P );
-
if ( r == NOT_APPLICABLE ) r = CLiteralsModel::invoke_primitive ( gen , bip , P );
+
if ( r == NOT_APPLICABLE ) r = CLiteralsModel::invoke_primitive ( gen , bip , P );
if ( r == NOT_APPLICABLE ) r = CInputOutputModel::invoke_primitive ( gen , bip , P );
if ( r == NOT_APPLICABLE ) r = CConditions::invoke_primitive ( gen , bip , P );
if ( r == NOT_APPLICABLE ) r = CProgramControl::compile_control_primitive ( gen , bip , P );
diff --git a/docs/final-module/5-fnc.html b/docs/final-module/5-fnc.html
index 186465d5b..f020a8bb1 100644
--- a/docs/final-module/5-fnc.html
+++ b/docs/final-module/5-fnc.html
@@ -112,11 +112,11 @@ code can interface with it. Both are divided into segments. The main file thus:
enum c_early_matter_I7CGS
enum c_text_literals_code_I7CGS
enum c_summations_at_eof_I7CGS
-
enum c_arrays_at_eof_I7CGS
+
enum c_arrays_I7CGS
enum c_main_matter_I7CGS
enum c_functions_at_eof_I7CGS
enum c_code_at_eof_I7CGS
-
enum c_verbs_at_eof_I7CGS
+
enum c_verb_arrays_I7CGS
enum c_stubs_at_eof_I7CGS
enum c_property_offset_creator_I7CGS
enum c_mem_I7CGS
@@ -134,11 +134,11 @@ code can interface with it. Both are divided into segments. The main file thus:
c_early_matter_I7CGS ,
c_text_literals_code_I7CGS ,
c_summations_at_eof_I7CGS ,
-
c_arrays_at_eof_I7CGS ,
+
c_arrays_I7CGS ,
c_main_matter_I7CGS ,
c_functions_at_eof_I7CGS ,
c_code_at_eof_I7CGS ,
-
c_verbs_at_eof_I7CGS ,
+
c_verb_arrays_I7CGS ,
c_stubs_at_eof_I7CGS ,
c_property_offset_creator_I7CGS ,
c_mem_I7CGS ,
@@ -215,7 +215,7 @@ manage the process.
Compile the Clib code inclusion 5.3 ;
CNamespace::fix_locals ( gen );
-
CMemoryModel::begin ( gen );
+
CMemoryModel::begin ( gen );
CFunctionModel::begin ( gen );
CObjectModel::begin ( gen );
CLiteralsModel::begin ( gen );
@@ -285,7 +285,7 @@ manage the process.
CGlobals::end ( gen );
CAssembly::end ( gen );
CInputOutputModel::end ( gen );
-
CMemoryModel::end ( gen );
+
CMemoryModel::end ( gen );
Compile end to clang pragmas 6.1 ;
filename * F = gen -> to_file ;
if (( F ) && ( C_GEN_DATA ( compile_symbols ))) String the symbols header target together 6.2 ;
@@ -642,7 +642,9 @@ like these other functions: see
C Object M
-
+
+
+
diff --git a/inform7/Figures/timings-diagnostics.txt b/inform7/Figures/timings-diagnostics.txt
index 073b901e8..bb810c447 100644
--- a/inform7/Figures/timings-diagnostics.txt
+++ b/inform7/Figures/timings-diagnostics.txt
@@ -1,11 +1,11 @@
100.0% in inform7 run
- 55.1% in compilation to Inter
- 39.7% in //Sequence::undertake_queued_tasks//
+ 55.2% in compilation to Inter
+ 39.8% in //Sequence::undertake_queued_tasks//
3.4% in //MajorNodes::pre_pass//
2.6% in //MajorNodes::pass_1//
2.0% in //RTPhrasebook::compile_entries//
1.3% in //ImperativeDefinitions::assess_all//
- 1.2% in //RTKindConstructors::compile//
+ 1.0% in //RTKindConstructors::compile//
0.4% in //ImperativeDefinitions::compile_first_block//
0.4% in //MajorNodes::pass_2//
0.4% in //Sequence::undertake_queued_tasks//
@@ -16,11 +16,11 @@
0.1% in //RTKindConstructors::compile_permissions//
0.1% in //Task::make_built_in_kind_constructors//
0.1% in //World::stages_II_and_III//
- 1.8% not specifically accounted for
- 42.9% in running Inter pipeline
- 12.2% in step preparation
+ 2.0% not specifically accounted for
+ 42.8% in running Inter pipeline
+ 12.3% in step preparation
9.7% in inter step 7/16: consolidate-text
- 7.9% in inter step 2/16: link
+ 8.0% in inter step 2/16: link
6.4% in inter step 16/16: generate inform6 -> auto.inf
1.5% in inter step 11/16: make-identifiers-unique
0.4% in inter step 12/16: reconcile-verbs
@@ -33,6 +33,6 @@
0.1% in inter step 3/16: merge-template <- none
0.1% in inter step 4/16: parse-linked-matter
0.1% in inter step 5/16: resolve-conditional-compilation
- 2.6% not specifically accounted for
+ 2.4% not specifically accounted for
1.6% in supervisor
0.3% not specifically accounted for
diff --git a/inform7/Internal/Miscellany/inform7_clib.c b/inform7/Internal/Miscellany/inform7_clib.c
index 7997fb2f8..67cff95b9 100644
--- a/inform7/Internal/Miscellany/inform7_clib.c
+++ b/inform7/Internal/Miscellany/inform7_clib.c
@@ -72,7 +72,9 @@ int i7_run_process(i7process_t *proc) {
if (tc == 2) proc->termination_code = 0; /* terminated mid-stream but benignly */
else proc->termination_code = tc; /* terminated mid-stream with a fatal error */
} else {
- i7_initialise_state(proc);
+ i7_initialise_memory_and_stack(proc);
+ i7_initialise_variables(proc);
+ i7_initialise_object_tree(proc);
i7_initializer(proc);
i7_initialise_streams(proc);
fn_i7_mgl_Main(proc);
@@ -90,24 +92,22 @@ void i7_fatal_exit(i7process_t *proc) {
void i7_benign_exit(i7process_t *proc) {
longjmp(proc->execution_env, 2);
}
+void i7_initialise_variables(i7process_t *proc) {
+ proc->state.variables = i7_calloc(proc, i7_no_variables, sizeof(i7word_t));
+ for (int i=0; istate.variables[i] = i7_initial_variable_values[i];
+}
i7byte_t i7_initial_memory[];
-void i7_initialise_state(i7process_t *proc) {
+void i7_initialise_memory_and_stack(i7process_t *proc) {
if (proc->state.memory != NULL) free(proc->state.memory);
- i7byte_t *mem = calloc(i7_static_himem, sizeof(i7byte_t));
- if (mem == NULL) {
- printf("Memory allocation failed\n");
- i7_fatal_exit(proc);
- }
- proc->state.memory = mem;
- proc->state.himem = i7_static_himem;
+
+ i7byte_t *mem = i7_calloc(proc, i7_static_himem, sizeof(i7byte_t));
for (int i=0; istate.stack_pointer = 0;
- proc->state.object_tree_parent = calloc(i7_max_objects, sizeof(i7word_t));
- proc->state.object_tree_child = calloc(i7_max_objects, sizeof(i7word_t));
- proc->state.object_tree_sibling = calloc(i7_max_objects, sizeof(i7word_t));
+ proc->state.memory = mem;
+ proc->state.himem = i7_static_himem;
+ proc->state.stack_pointer = 0;
+}
+i7byte_t i7_read_byte(i7process_t *proc, i7word_t address) {
+ return proc->state.memory[address];
+}
- if ((proc->state.object_tree_parent == NULL) ||
- (proc->state.object_tree_child == NULL) ||
- (proc->state.object_tree_sibling == NULL)) {
- printf("Memory allocation failed\n");
+i7word_t i7_read_word(i7process_t *proc, i7word_t array_address, i7word_t array_index) {
+ i7byte_t *data = proc->state.memory;
+ int byte_position = array_address + 4*array_index;
+ if ((byte_position < 0) || (byte_position >= i7_static_himem)) {
+ printf("Memory access out of range: %d\n", byte_position);
i7_fatal_exit(proc);
}
- for (int i=0; istate.object_tree_parent[i] = 0;
- proc->state.object_tree_child[i] = 0;
- proc->state.object_tree_sibling[i] = 0;
- }
+ return (i7word_t) data[byte_position + 3] +
+ 0x100*((i7word_t) data[byte_position + 2]) +
+ 0x10000*((i7word_t) data[byte_position + 1]) +
+ 0x1000000*((i7word_t) data[byte_position + 0]);
+}
+void i7_write_byte(i7process_t *proc, i7word_t address, i7byte_t new_val) {
+ proc->state.memory[address] = new_val;
+}
- proc->state.variables = calloc(i7_no_variables, sizeof(i7word_t));
- if (proc->state.variables == NULL) {
- printf("Memory allocation failed\n");
+i7byte_t i7_change_byte(i7process_t *proc, i7word_t address, i7byte_t new_val, int way) {
+ i7byte_t old_val = i7_read_byte(proc, address);
+ i7byte_t return_val = new_val;
+ switch (way) {
+ case i7_lvalue_PREDEC: return_val = old_val-1; new_val = old_val-1; break;
+ case i7_lvalue_POSTDEC: return_val = old_val; new_val = old_val-1; break;
+ case i7_lvalue_PREINC: return_val = old_val+1; new_val = old_val+1; break;
+ case i7_lvalue_POSTINC: return_val = old_val; new_val = old_val+1; break;
+ case i7_lvalue_SETBIT: new_val = old_val | new_val; return_val = new_val; break;
+ case i7_lvalue_CLEARBIT: new_val = old_val &(~new_val); return_val = new_val; break;
+ }
+ i7_write_byte(proc, address, new_val);
+ return return_val;
+}
+
+i7word_t i7_write_word(i7process_t *proc, i7word_t array_address, i7word_t array_index, i7word_t new_val, int way) {
+ i7byte_t *data = proc->state.memory;
+ i7word_t old_val = i7_read_word(proc, array_address, array_index);
+ i7word_t return_val = new_val;
+ switch (way) {
+ case i7_lvalue_PREDEC: return_val = old_val-1; new_val = old_val-1; break;
+ case i7_lvalue_POSTDEC: return_val = old_val; new_val = old_val-1; break;
+ case i7_lvalue_PREINC: return_val = old_val+1; new_val = old_val+1; break;
+ case i7_lvalue_POSTINC: return_val = old_val; new_val = old_val+1; break;
+ case i7_lvalue_SETBIT: new_val = old_val | new_val; return_val = new_val; break;
+ case i7_lvalue_CLEARBIT: new_val = old_val &(~new_val); return_val = new_val; break;
+ }
+ int byte_position = array_address + 4*array_index;
+ if ((byte_position < 0) || (byte_position >= i7_static_himem)) {
+ printf("Memory access out of range: %d\n", byte_position);
i7_fatal_exit(proc);
}
- for (int i=0; istate.variables[i] = i7_initial_variable_values[i];
+ data[byte_position] = I7BYTE_0(new_val);
+ data[byte_position+1] = I7BYTE_1(new_val);
+ data[byte_position+2] = I7BYTE_2(new_val);
+ data[byte_position+3] = I7BYTE_3(new_val);
+ return return_val;
+}
+void glulx_aloads(i7process_t *proc, i7word_t x, i7word_t y, i7word_t *z) {
+ if (z) *z = 0x100*((i7word_t) i7_read_byte(proc, x+2*y)) + ((i7word_t) i7_read_byte(proc, x+2*y+1));
+}
+void glulx_mcopy(i7process_t *proc, i7word_t x, i7word_t y, i7word_t z) {
+ if (z < y)
+ for (i7word_t i=0; i=0; i--)
+ i7_write_byte(proc, z+i, i7_read_byte(proc, y+i));
+}
+
+void glulx_malloc(i7process_t *proc, i7word_t x, i7word_t y) {
+ printf("Unimplemented: glulx_malloc.\n");
+ i7_fatal_exit(proc);
+}
+
+void glulx_mfree(i7process_t *proc, i7word_t x) {
+ printf("Unimplemented: glulx_mfree.\n");
+ i7_fatal_exit(proc);
}
void *i7_calloc(i7process_t *proc, size_t how_many, size_t of_size) {
void *p = calloc(how_many, of_size);
@@ -228,85 +286,6 @@ void i7_restore_snapshot_from(i7process_t *proc, i7snapshot_t *ss) {
i7_destroy_state(proc, &(proc->state));
i7_copy_state(proc, &(proc->state), &(ss->then));
}
-i7byte_t i7_read_byte(i7process_t *proc, i7word_t address) {
- return proc->state.memory[address];
-}
-
-i7word_t i7_read_word(i7process_t *proc, i7word_t array_address, i7word_t array_index) {
- i7byte_t *data = proc->state.memory;
- int byte_position = array_address + 4*array_index;
- if ((byte_position < 0) || (byte_position >= i7_static_himem)) {
- printf("Memory access out of range: %d\n", byte_position);
- i7_fatal_exit(proc);
- }
- return (i7word_t) data[byte_position + 3] +
- 0x100*((i7word_t) data[byte_position + 2]) +
- 0x10000*((i7word_t) data[byte_position + 1]) +
- 0x1000000*((i7word_t) data[byte_position + 0]);
-}
-void i7_write_byte(i7process_t *proc, i7word_t address, i7byte_t new_val) {
- proc->state.memory[address] = new_val;
-}
-
-i7byte_t i7_change_byte(i7process_t *proc, i7word_t address, i7byte_t new_val, int way) {
- i7byte_t old_val = i7_read_byte(proc, address);
- i7byte_t return_val = new_val;
- switch (way) {
- case i7_lvalue_PREDEC: return_val = old_val-1; new_val = old_val-1; break;
- case i7_lvalue_POSTDEC: return_val = old_val; new_val = old_val-1; break;
- case i7_lvalue_PREINC: return_val = old_val+1; new_val = old_val+1; break;
- case i7_lvalue_POSTINC: return_val = old_val; new_val = old_val+1; break;
- case i7_lvalue_SETBIT: new_val = old_val | new_val; return_val = new_val; break;
- case i7_lvalue_CLEARBIT: new_val = old_val &(~new_val); return_val = new_val; break;
- }
- i7_write_byte(proc, address, new_val);
- return return_val;
-}
-
-i7word_t i7_write_word(i7process_t *proc, i7word_t array_address, i7word_t array_index, i7word_t new_val, int way) {
- i7byte_t *data = proc->state.memory;
- i7word_t old_val = i7_read_word(proc, array_address, array_index);
- i7word_t return_val = new_val;
- switch (way) {
- case i7_lvalue_PREDEC: return_val = old_val-1; new_val = old_val-1; break;
- case i7_lvalue_POSTDEC: return_val = old_val; new_val = old_val-1; break;
- case i7_lvalue_PREINC: return_val = old_val+1; new_val = old_val+1; break;
- case i7_lvalue_POSTINC: return_val = old_val; new_val = old_val+1; break;
- case i7_lvalue_SETBIT: new_val = old_val | new_val; return_val = new_val; break;
- case i7_lvalue_CLEARBIT: new_val = old_val &(~new_val); return_val = new_val; break;
- }
- int byte_position = array_address + 4*array_index;
- if ((byte_position < 0) || (byte_position >= i7_static_himem)) {
- printf("Memory access out of range: %d\n", byte_position);
- i7_fatal_exit(proc);
- }
- data[byte_position] = I7BYTE_0(new_val);
- data[byte_position+1] = I7BYTE_1(new_val);
- data[byte_position+2] = I7BYTE_2(new_val);
- data[byte_position+3] = I7BYTE_3(new_val);
- return return_val;
-}
-void glulx_aloads(i7process_t *proc, i7word_t x, i7word_t y, i7word_t *z) {
- if (z) *z = 0x100*((i7word_t) i7_read_byte(proc, x+2*y)) + ((i7word_t) i7_read_byte(proc, x+2*y+1));
-}
-void glulx_mcopy(i7process_t *proc, i7word_t x, i7word_t y, i7word_t z) {
- if (z < y)
- for (i7word_t i=0; i=0; i--)
- i7_write_byte(proc, z+i, i7_read_byte(proc, y+i));
-}
-
-void glulx_malloc(i7process_t *proc, i7word_t x, i7word_t y) {
- printf("Unimplemented: glulx_malloc.\n");
- i7_fatal_exit(proc);
-}
-
-void glulx_mfree(i7process_t *proc, i7word_t x) {
- printf("Unimplemented: glulx_mfree.\n");
- i7_fatal_exit(proc);
-}
// i7word_t i7_mgl_sp = 0;
void i7_debug_stack(char *N) {
@@ -1087,6 +1066,17 @@ void i7_move(i7process_t *proc, i7word_t obj, i7word_t to) {
proc->state.object_tree_child[to] = obj;
}
}
+
+void i7_initialise_object_tree(i7process_t *proc) {
+ proc->state.object_tree_parent = i7_calloc(proc, i7_max_objects, sizeof(i7word_t));
+ proc->state.object_tree_child = i7_calloc(proc, i7_max_objects, sizeof(i7word_t));
+ proc->state.object_tree_sibling = i7_calloc(proc, i7_max_objects, sizeof(i7word_t));
+ for (int i=0; istate.object_tree_parent[i] = 0;
+ proc->state.object_tree_child[i] = 0;
+ proc->state.object_tree_sibling[i] = 0;
+ }
+}
i7word_t i7_call_0(i7process_t *proc, i7word_t fn_ref) {
i7word_t args[10]; for (int i=0; i<10; i++) args[i] = 0;
return i7_gen_call(proc, fn_ref, args, 0);
diff --git a/inform7/Internal/Miscellany/inform7_clib.h b/inform7/Internal/Miscellany/inform7_clib.h
index 8168d6060..0639ca8a4 100644
--- a/inform7/Internal/Miscellany/inform7_clib.h
+++ b/inform7/Internal/Miscellany/inform7_clib.h
@@ -68,15 +68,8 @@ void i7_initializer(i7process_t *proc); /* part of the compiled story, not infor
#define i7_lvalue_POSTINC 5
#define i7_lvalue_SETBIT 6
#define i7_lvalue_CLEARBIT 7
-void i7_initialise_state(i7process_t *proc);
-void i7_copy_state(i7process_t *proc, i7state_t *to, i7state_t *from);
-void i7_destroy_state(i7process_t *proc, i7state_t *s);
-void i7_destroy_snapshot(i7process_t *proc, i7snapshot_t *old);
-void i7_save_snapshot(i7process_t *proc);
-int i7_has_snapshot(i7process_t *proc);
-void i7_restore_snapshot(i7process_t *proc);
-void i7_restore_snapshot_from(i7process_t *proc, i7snapshot_t *ss);
-void i7_destroy_latest_snapshot(i7process_t *proc);
+void i7_initialise_variables(i7process_t *proc);
+void i7_initialise_memory_and_stack(i7process_t *proc);
i7byte_t i7_read_byte(i7process_t *proc, i7word_t address);
i7word_t i7_read_word(i7process_t *proc, i7word_t array_address, i7word_t array_index);
#define I7BYTE_0(V) ((V & 0xFF000000) >> 24)
@@ -85,11 +78,21 @@ i7word_t i7_read_word(i7process_t *proc, i7word_t array_address, i7word_t array_
#define I7BYTE_3(V) (V & 0x000000FF)
void i7_write_byte(i7process_t *proc, i7word_t address, i7byte_t new_val);
-i7word_t i7_write_word(i7process_t *proc, i7word_t array_address, i7word_t array_index, i7word_t new_val, int way);
+i7word_t i7_write_word(i7process_t *proc, i7word_t array_address, i7word_t array_index,
+ i7word_t new_val, int way);
void glulx_aloads(i7process_t *proc, i7word_t x, i7word_t y, i7word_t *z);
void glulx_mcopy(i7process_t *proc, i7word_t x, i7word_t y, i7word_t z);
void glulx_malloc(i7process_t *proc, i7word_t x, i7word_t y);
void glulx_mfree(i7process_t *proc, i7word_t x);
+void *i7_calloc(i7process_t *proc, size_t how_many, size_t of_size);
+void i7_copy_state(i7process_t *proc, i7state_t *to, i7state_t *from);
+void i7_destroy_state(i7process_t *proc, i7state_t *s);
+void i7_destroy_snapshot(i7process_t *proc, i7snapshot_t *old);
+void i7_save_snapshot(i7process_t *proc);
+int i7_has_snapshot(i7process_t *proc);
+void i7_restore_snapshot(i7process_t *proc);
+void i7_restore_snapshot_from(i7process_t *proc, i7snapshot_t *ss);
+void i7_destroy_latest_snapshot(i7process_t *proc);
void i7_debug_stack(char *N);
i7word_t i7_pull(i7process_t *proc);
void i7_push(i7process_t *proc, i7word_t x);
@@ -182,6 +185,7 @@ i7word_t i7_change_prop_value(i7process_t *proc, i7word_t K, i7word_t obj, i7wor
void i7_give(i7process_t *proc, i7word_t owner, i7word_t prop, i7word_t val);
i7word_t i7_prop_len(i7process_t *proc, i7word_t K, i7word_t obj, i7word_t pr);
i7word_t i7_prop_addr(i7process_t *proc, i7word_t K, i7word_t obj, i7word_t pr);
+void i7_initialise_object_tree(i7process_t *proc);
int i7_has(i7process_t *proc, i7word_t obj, i7word_t attr);
int i7_provides(i7process_t *proc, i7word_t owner_id, i7word_t prop_id);
int i7_in(i7process_t *proc, i7word_t obj1, i7word_t obj2);
diff --git a/inter/final-module/Chapter 5/C Global Variables.w b/inter/final-module/Chapter 5/C Global Variables.w
index 25b50f0de..97a61898f 100644
--- a/inter/final-module/Chapter 5/C Global Variables.w
+++ b/inter/final-module/Chapter 5/C Global Variables.w
@@ -121,3 +121,18 @@ void CGlobals::evaluate_variable(code_generator *cgt, code_generation *gen,
CNamespace::mangle_variable(OUT, Inter::Symbols::name(var_name));
WRITE("]");
}
+
+@ Finally, this function, part of the C library, initialises the variables for a
+newly-starting process.
+
+= (text to inform7_clib.h)
+void i7_initialise_variables(i7process_t *proc);
+=
+
+= (text to inform7_clib.c)
+void i7_initialise_variables(i7process_t *proc) {
+ proc->state.variables = i7_calloc(proc, i7_no_variables, sizeof(i7word_t));
+ for (int i=0; istate.variables[i] = i7_initial_variable_values[i];
+}
+=
diff --git a/inter/final-module/Chapter 5/C Literals.w b/inter/final-module/Chapter 5/C Literals.w
index 8f4a27e42..dc5e1aa69 100644
--- a/inter/final-module/Chapter 5/C Literals.w
+++ b/inter/final-module/Chapter 5/C Literals.w
@@ -10,6 +10,7 @@ void CLiteralsModel::initialise(code_generator *cgt) {
METHOD_ADD(cgt, COMPILE_LITERAL_NUMBER_MTID, CLiteralsModel::compile_literal_number);
METHOD_ADD(cgt, COMPILE_LITERAL_REAL_MTID, CLiteralsModel::compile_literal_real);
METHOD_ADD(cgt, COMPILE_LITERAL_TEXT_MTID, CLiteralsModel::compile_literal_text);
+ METHOD_ADD(cgt, COMPILE_LITERAL_SYMBOL_MTID, CLiteralsModel::compile_literal_symbol);
METHOD_ADD(cgt, NEW_ACTION_MTID, CLiteralsModel::new_action);
}
@@ -672,6 +673,15 @@ void CLiteralsModel::compile_literal_real(code_generator *cgt,
@
+=
+void CLiteralsModel::compile_literal_symbol(code_generator *cgt, code_generation *gen, inter_symbol *aliased) {
+ text_stream *OUT = CodeGen::current(gen);
+ text_stream *S = Inter::Symbols::name(aliased);
+ Generators::mangle(gen, OUT, S);
+}
+
+@
+
=
int CLiteralsModel::hex_val(wchar_t c) {
if ((c >= '0') && (c <= '9')) return c - '0';
diff --git a/inter/final-module/Chapter 5/C Memory Model.w b/inter/final-module/Chapter 5/C Memory Model.w
index 7902378eb..5aadb1b8e 100644
--- a/inter/final-module/Chapter 5/C Memory Model.w
+++ b/inter/final-module/Chapter 5/C Memory Model.w
@@ -3,29 +3,6 @@
How arrays of all kinds are stored in C.
@h Setting up the model.
-
-=
-void CMemoryModel::initialise(code_generator *cgt) {
- METHOD_ADD(cgt, BEGIN_ARRAY_MTID, CMemoryModel::begin_array);
- METHOD_ADD(cgt, ARRAY_ENTRY_MTID, CMemoryModel::array_entry);
- METHOD_ADD(cgt, COMPILE_LITERAL_SYMBOL_MTID, CMemoryModel::compile_literal_symbol);
- METHOD_ADD(cgt, ARRAY_ENTRIES_MTID, CMemoryModel::array_entries);
- METHOD_ADD(cgt, END_ARRAY_MTID, CMemoryModel::end_array);
-}
-
-typedef struct C_generation_memory_model_data {
- int himem; /* high point of memory: 1 more than the largest legal address */
- struct text_stream *array_name;
- int entry_count;
-} C_generation_memory_model_data;
-
-void CMemoryModel::initialise_data(code_generation *gen) {
- C_GEN_DATA(memdata.himem) = 0;
- C_GEN_DATA(memdata.array_name) = Str::new();
- C_GEN_DATA(memdata.entry_count) = 0;
-}
-
-@h Byte-addressable memory.
The Inter semantics require that there be an area of byte-accessible memory:
(a) Byte-accessible memory must contain all of the arrays. These can but need
@@ -43,9 +20,33 @@ of 2 or 4.
(f) Arrays in memory are free to contain a mixture of bytes and words: some do.
(g) Data may be written in byte form and read back in word form, or vice versa.
-We will manage that with a single C array.
+=
+void CMemoryModel::initialise(code_generator *cgt) {
+ METHOD_ADD(cgt, BEGIN_ARRAY_MTID, CMemoryModel::begin_array);
+ METHOD_ADD(cgt, ARRAY_ENTRY_MTID, CMemoryModel::array_entry);
+ METHOD_ADD(cgt, ARRAY_ENTRIES_MTID, CMemoryModel::array_entries);
+ METHOD_ADD(cgt, END_ARRAY_MTID, CMemoryModel::end_array);
+}
-@ Declaring that array is our main task in this section.
+typedef struct C_generation_memory_model_data {
+ int himem; /* 1 more than the largest legal byte address */
+ struct text_stream *array_name; /* of the array currently being compiled */
+ int entry_count; /* within the array currently being compiled */
+} C_generation_memory_model_data;
+
+void CMemoryModel::initialise_data(code_generation *gen) {
+ C_GEN_DATA(memdata.himem) = 0;
+ C_GEN_DATA(memdata.array_name) = Str::new();
+ C_GEN_DATA(memdata.entry_count) = 0;
+}
+
+@ For a given process |proc|, the current contents of byte-addressable memory will
+be an array called |proc->state.memory|; here, we will compile a single static array
+|i7_initial_memory| holding the initial contents of this memory, so that a new
+process can be initialised from that.
+
+The first 64 bytes of memory are reserved for the "header". We don't write those
+here, and instead blank them out to all 0s.
=
void CMemoryModel::begin(code_generation *gen) {
@@ -57,16 +58,13 @@ void CMemoryModel::begin(code_generation *gen) {
CodeGen::deselect(gen, saved);
}
-@ We will end the array with two dummy bytes (which should never be accessed)
-just in case, and to ensure that it is never empty, which would be illegal
-in C.
+@ And we must close that array declaration, too:
=
void CMemoryModel::end(code_generation *gen) {
segmentation_pos saved = CodeGen::select(gen, c_mem_I7CGS);
text_stream *OUT = CodeGen::current(gen);
- WRITE("0, 0 };\n");
-
+ WRITE("};\n");
CodeGen::deselect(gen, saved);
saved = CodeGen::select(gen, c_ids_and_maxima_I7CGS);
@@ -75,31 +73,193 @@ void CMemoryModel::end(code_generation *gen) {
CodeGen::deselect(gen, saved);
}
-@
+@ What goes into memory are arrays: memory is allocated only in the form of
+such arrays, which are declared one at a time. See //Vanilla Constants//.
+
+
+=
+int CMemoryModel::begin_array(code_generator *cgt, code_generation *gen,
+ text_stream *array_name, inter_symbol *array_s, inter_tree_node *P, int format,
+ segmentation_pos *saved) {
+ Str::clear(C_GEN_DATA(memdata.array_name));
+ WRITE_TO(C_GEN_DATA(memdata.array_name), "%S", array_name);
+ C_GEN_DATA(memdata.entry_count) = 0;
+ if ((array_s) && (Inter::Symbols::read_annotation(array_s, VERBARRAY_IANN) == 1))
+ @
+ else
+ @;
+}
+
+@ Command-grammar arrays are handled differently: note the return value |FALSE|,
+which tells Vanilla not to call us again about this array.
+
+@ =
+ if (saved) *saved = CodeGen::select(gen, c_verb_arrays_I7CGS);
+ CLiteralsModel::verb_grammar(cgt, gen, array_s, P);
+ return FALSE;
+
+@ =
+ if (saved) *saved = CodeGen::select(gen, c_arrays_I7CGS);
+ text_stream *format_name = I"unknown";
+ @;
+ @;
+ if ((format == TABLE_ARRAY_FORMAT) || (format == BUFFER_ARRAY_FORMAT))
+ @;
+ return TRUE;
+
+@ =
+ switch (format) {
+ case BYTE_ARRAY_FORMAT: format_name = I"byte"; break;
+ case WORD_ARRAY_FORMAT: format_name = I"word"; break;
+ case BUFFER_ARRAY_FORMAT: format_name = I"buffer"; break;
+ case TABLE_ARRAY_FORMAT: format_name = I"table"; break;
+ }
+
+@ Crucially, the array names are |#define| constants declared up near the top
+of the source code: they are not variables with pointer types, or something
+like that. This means they can legally be used as values elsewhere in memory,
+or as initial values of variables, and so on.
+
+Object, class and function names can also legally appear as array entries,
+because they too are defined constants, equal to their IDs: see //C Object Model//.
+
+@ =
+ segmentation_pos saved = CodeGen::select(gen, c_predeclarations_I7CGS);
+ text_stream *OUT = CodeGen::current(gen);
+ WRITE("#define ");
+ CNamespace::mangle(cgt, OUT, array_name);
+ WRITE(" %d /* = position in memory of %S array %S */\n",
+ C_GEN_DATA(memdata.himem), format_name, array_name);
+ if (array_s)
+ Inter::Symbols::annotate_i(array_s, C_ARRAY_ADDRESS_IANN,
+ (inter_ti) C_GEN_DATA(memdata.himem));
+ CodeGen::deselect(gen, saved);
+
+@ Of course, right now we don't know |N|, the extent of the array. So we will
+refer to this with a constant like |i7_mgl_myarray__xt| (XT meaning "extent"),
+which we will retrospectively predefine when the array ends.
+
+@ =
+ TEMPORARY_TEXT(extname)
+ CNamespace::mangle(cgt, extname, array_name);
+ WRITE_TO(extname, "__xt");
+ CMemoryModel::array_entry(cgt, gen, extname, format);
+ DISCARD_TEXT(extname)
+
+@ The call to //CMemoryModel::begin_array// is then followed by a series of calls to:
+
+=
+void CMemoryModel::array_entry(code_generator *cgt, code_generation *gen,
+ text_stream *entry, int format) {
+ segmentation_pos saved = CodeGen::select(gen, c_mem_I7CGS);
+ text_stream *OUT = CodeGen::current(gen);
+ if ((format == TABLE_ARRAY_FORMAT) || (format == WORD_ARRAY_FORMAT))
+ @
+ else
+ @;
+ CodeGen::deselect(gen, saved);
+ C_GEN_DATA(memdata.entry_count)++;
+}
+
+@ =
+ WRITE(" (i7byte_t) %S, /* %d */\n", entry, C_GEN_DATA(memdata.himem));
+ C_GEN_DATA(memdata.himem) += 1;
+
+@ Note that |I7BYTE_0| and so on are macros and not functions (see below): they
+use only arithmetic operations which can be constant-folded by the C compiler,
+and therefore if |X| is a valid constant-context expression in C then so is
+|I7BYTE_0(X)|.
+
+@ =
+ WRITE(" I7BYTE_0(%S), I7BYTE_1(%S), I7BYTE_2(%S), I7BYTE_3(%S), /* %d */\n",
+ entry, entry, entry, entry, C_GEN_DATA(memdata.himem));
+ C_GEN_DATA(memdata.himem) += 4;
+
+@ Alternatively, we can just specify how many entries there will be: they will
+then be initialised to 0.
+
+=
+void CMemoryModel::array_entries(code_generator *cgt, code_generation *gen,
+ int how_many, int format) {
+ for (int i=0; i val
+primitive !lookupbyte val val -> val
+=
+
+=
+int CMemoryModel::handle_store_by_ref(code_generation *gen, inter_tree_node *ref) {
+ if (Inter::Reference::node_is_ref_to(gen->from, ref, LOOKUP_BIP)) return TRUE;
+ if (Inter::Reference::node_is_ref_to(gen->from, ref, LOOKUPBYTE_BIP)) return TRUE;
+ return FALSE;
+}
+
+int CMemoryModel::invoke_primitive(code_generation *gen, inter_ti bip, inter_tree_node *P) {
+ text_stream *OUT = CodeGen::current(gen);
+ switch (bip) {
+ case LOOKUP_BIP:
+ WRITE("i7_read_word(proc, "); VNODE_1C; WRITE(", "); VNODE_2C; WRITE(")");
+ break;
+ case LOOKUPBYTE_BIP:
+ WRITE("i7_read_byte(proc, "); VNODE_1C; WRITE(" + "); VNODE_2C; WRITE(")");
+ break;
+ default:
+ return NOT_APPLICABLE;
+ }
+ return FALSE;
+}
+
+@ So, then, time to write some more of the C library. We are going to need to
+define the macros |I7BYTE_0| to |I7BYTE_3|, and also the functions |i7_read_word|
+and |i7_read_byte|, used just above. But we start with the function which resets
+memory to its initial state when a process begins, and with the stack empty.
+
+Note that we fill in ten bytes of the 64-byte header block of memory:
+
+(*) The Release number as a big-endian 16-bit value at |0x34-0x35|;
+(*) The Serial code as six ASCII characters (in practice digits) at |0x36-0x3B|.
+
+We carefully defined those two constants, if they exist, before the inclusion point of
+the C library in order that the conditional compilations in |i7_initialise_memory_and_stack|
+will work correctly. See //CNamespace::declare_constant//.
+
+The rest of the header area remains all zeros.
= (text to inform7_clib.h)
-void i7_initialise_state(i7process_t *proc);
+void i7_initialise_memory_and_stack(i7process_t *proc);
=
= (text to inform7_clib.c)
i7byte_t i7_initial_memory[];
-void i7_initialise_state(i7process_t *proc) {
+void i7_initialise_memory_and_stack(i7process_t *proc) {
if (proc->state.memory != NULL) free(proc->state.memory);
- i7byte_t *mem = calloc(i7_static_himem, sizeof(i7byte_t));
- if (mem == NULL) {
- printf("Memory allocation failed\n");
- i7_fatal_exit(proc);
- }
- proc->state.memory = mem;
- proc->state.himem = i7_static_himem;
+
+ i7byte_t *mem = i7_calloc(proc, i7_static_himem, sizeof(i7byte_t));
for (int i=0; istate.stack_pointer = 0;
-
- proc->state.object_tree_parent = calloc(i7_max_objects, sizeof(i7word_t));
- proc->state.object_tree_child = calloc(i7_max_objects, sizeof(i7word_t));
- proc->state.object_tree_sibling = calloc(i7_max_objects, sizeof(i7word_t));
-
- if ((proc->state.object_tree_parent == NULL) ||
- (proc->state.object_tree_child == NULL) ||
- (proc->state.object_tree_sibling == NULL)) {
- printf("Memory allocation failed\n");
+
+ proc->state.memory = mem;
+ proc->state.himem = i7_static_himem;
+ proc->state.stack_pointer = 0;
+}
+=
+
+@ The array |proc->state.memory| is of |i7byte_t| values, so it's easy to read
+and write bytes. Words are more challenging since we need to pack and unpack them.
+
+The following function reads a word which is in entry |array_index| (counting
+0, 1, 2, ...) in the array which begins at the byte address |array_address|.
+
+= (text to inform7_clib.h)
+i7byte_t i7_read_byte(i7process_t *proc, i7word_t address);
+i7word_t i7_read_word(i7process_t *proc, i7word_t array_address, i7word_t array_index);
+=
+
+= (text to inform7_clib.c)
+i7byte_t i7_read_byte(i7process_t *proc, i7word_t address) {
+ return proc->state.memory[address];
+}
+
+i7word_t i7_read_word(i7process_t *proc, i7word_t array_address, i7word_t array_index) {
+ i7byte_t *data = proc->state.memory;
+ int byte_position = array_address + 4*array_index;
+ if ((byte_position < 0) || (byte_position >= i7_static_himem)) {
+ printf("Memory access out of range: %d\n", byte_position);
i7_fatal_exit(proc);
}
- for (int i=0; istate.object_tree_parent[i] = 0;
- proc->state.object_tree_child[i] = 0;
- proc->state.object_tree_sibling[i] = 0;
+ return (i7word_t) data[byte_position + 3] +
+ 0x100*((i7word_t) data[byte_position + 2]) +
+ 0x10000*((i7word_t) data[byte_position + 1]) +
+ 0x1000000*((i7word_t) data[byte_position + 0]);
+}
+=
+
+@ Packing, unlike unpacking, is done with macros so that it is possible to express
+a packed word in constant context, which we will need later.
+
+= (text to inform7_clib.h)
+#define I7BYTE_0(V) ((V & 0xFF000000) >> 24)
+#define I7BYTE_1(V) ((V & 0x00FF0000) >> 16)
+#define I7BYTE_2(V) ((V & 0x0000FF00) >> 8)
+#define I7BYTE_3(V) (V & 0x000000FF)
+
+void i7_write_byte(i7process_t *proc, i7word_t address, i7byte_t new_val);
+i7word_t i7_write_word(i7process_t *proc, i7word_t array_address, i7word_t array_index,
+ i7word_t new_val, int way);
+=
+
+= (text to inform7_clib.c)
+void i7_write_byte(i7process_t *proc, i7word_t address, i7byte_t new_val) {
+ proc->state.memory[address] = new_val;
+}
+
+i7byte_t i7_change_byte(i7process_t *proc, i7word_t address, i7byte_t new_val, int way) {
+ i7byte_t old_val = i7_read_byte(proc, address);
+ i7byte_t return_val = new_val;
+ switch (way) {
+ case i7_lvalue_PREDEC: return_val = old_val-1; new_val = old_val-1; break;
+ case i7_lvalue_POSTDEC: return_val = old_val; new_val = old_val-1; break;
+ case i7_lvalue_PREINC: return_val = old_val+1; new_val = old_val+1; break;
+ case i7_lvalue_POSTINC: return_val = old_val; new_val = old_val+1; break;
+ case i7_lvalue_SETBIT: new_val = old_val | new_val; return_val = new_val; break;
+ case i7_lvalue_CLEARBIT: new_val = old_val &(~new_val); return_val = new_val; break;
}
-
- proc->state.variables = calloc(i7_no_variables, sizeof(i7word_t));
- if (proc->state.variables == NULL) {
- printf("Memory allocation failed\n");
+ i7_write_byte(proc, address, new_val);
+ return return_val;
+}
+
+i7word_t i7_write_word(i7process_t *proc, i7word_t array_address, i7word_t array_index, i7word_t new_val, int way) {
+ i7byte_t *data = proc->state.memory;
+ i7word_t old_val = i7_read_word(proc, array_address, array_index);
+ i7word_t return_val = new_val;
+ switch (way) {
+ case i7_lvalue_PREDEC: return_val = old_val-1; new_val = old_val-1; break;
+ case i7_lvalue_POSTDEC: return_val = old_val; new_val = old_val-1; break;
+ case i7_lvalue_PREINC: return_val = old_val+1; new_val = old_val+1; break;
+ case i7_lvalue_POSTINC: return_val = old_val; new_val = old_val+1; break;
+ case i7_lvalue_SETBIT: new_val = old_val | new_val; return_val = new_val; break;
+ case i7_lvalue_CLEARBIT: new_val = old_val &(~new_val); return_val = new_val; break;
+ }
+ int byte_position = array_address + 4*array_index;
+ if ((byte_position < 0) || (byte_position >= i7_static_himem)) {
+ printf("Memory access out of range: %d\n", byte_position);
i7_fatal_exit(proc);
}
- for (int i=0; istate.variables[i] = i7_initial_variable_values[i];
+ data[byte_position] = I7BYTE_0(new_val);
+ data[byte_position+1] = I7BYTE_1(new_val);
+ data[byte_position+2] = I7BYTE_2(new_val);
+ data[byte_position+3] = I7BYTE_3(new_val);
+ return return_val;
+}
+=
+
+@ "Short" 16-bit numbers can also be accessed:
+
+= (text to inform7_clib.h)
+void glulx_aloads(i7process_t *proc, i7word_t x, i7word_t y, i7word_t *z);
+=
+
+= (text to inform7_clib.c)
+void glulx_aloads(i7process_t *proc, i7word_t x, i7word_t y, i7word_t *z) {
+ if (z) *z = 0x100*((i7word_t) i7_read_byte(proc, x+2*y)) + ((i7word_t) i7_read_byte(proc, x+2*y+1));
+}
+=
+
+@ A Glulx assembly opcode is provided for fast memory copies:
+
+= (text to inform7_clib.h)
+void glulx_mcopy(i7process_t *proc, i7word_t x, i7word_t y, i7word_t z);
+void glulx_malloc(i7process_t *proc, i7word_t x, i7word_t y);
+void glulx_mfree(i7process_t *proc, i7word_t x);
+=
+
+= (text to inform7_clib.c)
+void glulx_mcopy(i7process_t *proc, i7word_t x, i7word_t y, i7word_t z) {
+ if (z < y)
+ for (i7word_t i=0; i=0; i--)
+ i7_write_byte(proc, z+i, i7_read_byte(proc, y+i));
+}
+
+void glulx_malloc(i7process_t *proc, i7word_t x, i7word_t y) {
+ printf("Unimplemented: glulx_malloc.\n");
+ i7_fatal_exit(proc);
+}
+
+void glulx_mfree(i7process_t *proc, i7word_t x) {
+ printf("Unimplemented: glulx_mfree.\n");
+ i7_fatal_exit(proc);
}
=
@@ -142,6 +411,7 @@ in the arrays they point to. Similarly, we can't just throw away an |i7state_t|
value without causing a memory leak, so we need explicit destructors.
= (text to inform7_clib.h)
+void *i7_calloc(i7process_t *proc, size_t how_many, size_t of_size);
void i7_copy_state(i7process_t *proc, i7state_t *to, i7state_t *from);
void i7_destroy_state(i7process_t *proc, i7state_t *s);
=
@@ -247,286 +517,3 @@ void i7_restore_snapshot_from(i7process_t *proc, i7snapshot_t *ss) {
}
=
-@h Reading and writing memory.
-Given the above array, it's easy to read and write bytes. Words are more
-challenging since we need to pack and unpack them.
-
-The following function reads a word which is in entry |array_index| (counting
-0, 1, 2, ...) in the array which begins at the byte address |array_address|.
-
-= (text to inform7_clib.h)
-i7byte_t i7_read_byte(i7process_t *proc, i7word_t address);
-i7word_t i7_read_word(i7process_t *proc, i7word_t array_address, i7word_t array_index);
-=
-
-= (text to inform7_clib.c)
-i7byte_t i7_read_byte(i7process_t *proc, i7word_t address) {
- return proc->state.memory[address];
-}
-
-i7word_t i7_read_word(i7process_t *proc, i7word_t array_address, i7word_t array_index) {
- i7byte_t *data = proc->state.memory;
- int byte_position = array_address + 4*array_index;
- if ((byte_position < 0) || (byte_position >= i7_static_himem)) {
- printf("Memory access out of range: %d\n", byte_position);
- i7_fatal_exit(proc);
- }
- return (i7word_t) data[byte_position + 3] +
- 0x100*((i7word_t) data[byte_position + 2]) +
- 0x10000*((i7word_t) data[byte_position + 1]) +
- 0x1000000*((i7word_t) data[byte_position + 0]);
-}
-=
-
-@ Packing, unlike unpacking, is done with macros so that it is possible to
-express a packed word in constant context, which we will need later.
-
-= (text to inform7_clib.h)
-#define I7BYTE_0(V) ((V & 0xFF000000) >> 24)
-#define I7BYTE_1(V) ((V & 0x00FF0000) >> 16)
-#define I7BYTE_2(V) ((V & 0x0000FF00) >> 8)
-#define I7BYTE_3(V) (V & 0x000000FF)
-
-void i7_write_byte(i7process_t *proc, i7word_t address, i7byte_t new_val);
-i7word_t i7_write_word(i7process_t *proc, i7word_t array_address, i7word_t array_index, i7word_t new_val, int way);
-=
-
-= (text to inform7_clib.c)
-void i7_write_byte(i7process_t *proc, i7word_t address, i7byte_t new_val) {
- proc->state.memory[address] = new_val;
-}
-
-i7byte_t i7_change_byte(i7process_t *proc, i7word_t address, i7byte_t new_val, int way) {
- i7byte_t old_val = i7_read_byte(proc, address);
- i7byte_t return_val = new_val;
- switch (way) {
- case i7_lvalue_PREDEC: return_val = old_val-1; new_val = old_val-1; break;
- case i7_lvalue_POSTDEC: return_val = old_val; new_val = old_val-1; break;
- case i7_lvalue_PREINC: return_val = old_val+1; new_val = old_val+1; break;
- case i7_lvalue_POSTINC: return_val = old_val; new_val = old_val+1; break;
- case i7_lvalue_SETBIT: new_val = old_val | new_val; return_val = new_val; break;
- case i7_lvalue_CLEARBIT: new_val = old_val &(~new_val); return_val = new_val; break;
- }
- i7_write_byte(proc, address, new_val);
- return return_val;
-}
-
-i7word_t i7_write_word(i7process_t *proc, i7word_t array_address, i7word_t array_index, i7word_t new_val, int way) {
- i7byte_t *data = proc->state.memory;
- i7word_t old_val = i7_read_word(proc, array_address, array_index);
- i7word_t return_val = new_val;
- switch (way) {
- case i7_lvalue_PREDEC: return_val = old_val-1; new_val = old_val-1; break;
- case i7_lvalue_POSTDEC: return_val = old_val; new_val = old_val-1; break;
- case i7_lvalue_PREINC: return_val = old_val+1; new_val = old_val+1; break;
- case i7_lvalue_POSTINC: return_val = old_val; new_val = old_val+1; break;
- case i7_lvalue_SETBIT: new_val = old_val | new_val; return_val = new_val; break;
- case i7_lvalue_CLEARBIT: new_val = old_val &(~new_val); return_val = new_val; break;
- }
- int byte_position = array_address + 4*array_index;
- if ((byte_position < 0) || (byte_position >= i7_static_himem)) {
- printf("Memory access out of range: %d\n", byte_position);
- i7_fatal_exit(proc);
- }
- data[byte_position] = I7BYTE_0(new_val);
- data[byte_position+1] = I7BYTE_1(new_val);
- data[byte_position+2] = I7BYTE_2(new_val);
- data[byte_position+3] = I7BYTE_3(new_val);
- return return_val;
-}
-=
-
-@ "Short" 16-bit numbers can also be accessed:
-
-= (text to inform7_clib.h)
-void glulx_aloads(i7process_t *proc, i7word_t x, i7word_t y, i7word_t *z);
-=
-
-= (text to inform7_clib.c)
-void glulx_aloads(i7process_t *proc, i7word_t x, i7word_t y, i7word_t *z) {
- if (z) *z = 0x100*((i7word_t) i7_read_byte(proc, x+2*y)) + ((i7word_t) i7_read_byte(proc, x+2*y+1));
-}
-=
-
-@ A Glulx assembly opcode is provided for fast memory copies:
-
-= (text to inform7_clib.h)
-void glulx_mcopy(i7process_t *proc, i7word_t x, i7word_t y, i7word_t z);
-void glulx_malloc(i7process_t *proc, i7word_t x, i7word_t y);
-void glulx_mfree(i7process_t *proc, i7word_t x);
-=
-
-= (text to inform7_clib.c)
-void glulx_mcopy(i7process_t *proc, i7word_t x, i7word_t y, i7word_t z) {
- if (z < y)
- for (i7word_t i=0; i=0; i--)
- i7_write_byte(proc, z+i, i7_read_byte(proc, y+i));
-}
-
-void glulx_malloc(i7process_t *proc, i7word_t x, i7word_t y) {
- printf("Unimplemented: glulx_malloc.\n");
- i7_fatal_exit(proc);
-}
-
-void glulx_mfree(i7process_t *proc, i7word_t x) {
- printf("Unimplemented: glulx_mfree.\n");
- i7_fatal_exit(proc);
-}
-=
-
-@h Populating memory with arrays.
-
-=
-int CMemoryModel::begin_array(code_generator *cgt, code_generation *gen,
- text_stream *array_name, inter_symbol *array_s, inter_tree_node *P, int format, segmentation_pos *saved) {
- if (saved) {
- int choice = c_arrays_at_eof_I7CGS;
- if ((array_s) && (Inter::Symbols::read_annotation(array_s, VERBARRAY_IANN) == 1))
- choice = c_verbs_at_eof_I7CGS;
- *saved = CodeGen::select(gen, choice);
- }
- Str::clear(C_GEN_DATA(memdata.array_name));
- WRITE_TO(C_GEN_DATA(memdata.array_name), "%S", array_name);
- C_GEN_DATA(memdata.entry_count) = 0;
-
- if ((array_s) && (Inter::Symbols::read_annotation(array_s, VERBARRAY_IANN) == 1)) {
- CLiteralsModel::verb_grammar(cgt, gen, array_s, P);
- return FALSE;
- }
-
- text_stream *format_name = I"unknown";
- @;
- @;
- if ((format == TABLE_ARRAY_FORMAT) || (format == BUFFER_ARRAY_FORMAT))
- @;
- return TRUE;
-}
-
-@ =
- switch (format) {
- case BYTE_ARRAY_FORMAT: format_name = I"byte"; break;
- case WORD_ARRAY_FORMAT: format_name = I"word"; break;
- case BUFFER_ARRAY_FORMAT: format_name = I"buffer"; break;
- case TABLE_ARRAY_FORMAT: format_name = I"table"; break;
- }
-
-@ Crucially, the array names are |#define| constants declared up at the top
-of the source code: they are not variables with pointer types, or something
-like that. This means they can legally be used as values elsewhere in memory,
-or as initial values of variables, and so on.
-
-Object, class and function names can also legally appear as array entries,
-because they too are defined constants, equal to their IDs: see //C Object Model//.
-
-@ =
- segmentation_pos saved = CodeGen::select(gen, c_predeclarations_I7CGS);
- text_stream *OUT = CodeGen::current(gen);
- WRITE("#define ");
- CNamespace::mangle(cgt, OUT, array_name);
- WRITE(" %d /* = position in memory of %S array %S */\n",
- C_GEN_DATA(memdata.himem), format_name, array_name);
- if (array_s)
- Inter::Symbols::annotate_i(array_s, C_ARRAY_ADDRESS_IANN, (inter_ti) C_GEN_DATA(memdata.himem));
- CodeGen::deselect(gen, saved);
-
-@ Of course, right now we don't know |N|, the extent of the array. So we will
-refer to this with a constant like |xt_myarray|, which we will retrospectively
-predefine when the array ends.
-
-@ =
- TEMPORARY_TEXT(extname)
- WRITE_TO(extname, "xt_");
- CNamespace::mangle(cgt, extname, array_name);
- CMemoryModel::array_entry(cgt, gen, extname, format);
- DISCARD_TEXT(extname)
-
-@ The call to |CMemoryModel::begin_array| is then followed by a series of calls to:
-
-=
-void CMemoryModel::array_entry(code_generator *cgt, code_generation *gen,
- text_stream *entry, int format) {
- segmentation_pos saved = CodeGen::select(gen, c_mem_I7CGS);
- text_stream *OUT = CodeGen::current(gen);
- if ((format == TABLE_ARRAY_FORMAT) || (format == WORD_ARRAY_FORMAT))
- @
- else
- @;
- CodeGen::deselect(gen, saved);
- C_GEN_DATA(memdata.entry_count)++;
-}
-
-@ =
- WRITE(" (i7byte_t) %S, /* %d */\n", entry, C_GEN_DATA(memdata.himem));
- C_GEN_DATA(memdata.himem) += 1;
-
-@ Now we see why it was important for |I7BYTE_0| and so on to be macros: they
-use only arithmetic operations which can be constant-folded by the C compiler,
-and therefore if |X| is a valid constant-context expression in C then so is
-|I7BYTE_0(X)|.
-
-@ =
- WRITE(" I7BYTE_0(%S), I7BYTE_1(%S), I7BYTE_2(%S), I7BYTE_3(%S), /* %d */\n",
- entry, entry, entry, entry, C_GEN_DATA(memdata.himem));
- C_GEN_DATA(memdata.himem) += 4;
-
-@
-
-=
-void CMemoryModel::compile_literal_symbol(code_generator *cgt, code_generation *gen, inter_symbol *aliased) {
- text_stream *OUT = CodeGen::current(gen);
- text_stream *S = Inter::Symbols::name(aliased);
- Generators::mangle(gen, OUT, S);
-}
-
-@ Alternatively, we can just specify how many entries there will be: they will
-then be initialised to 0.
-
-=
-void CMemoryModel::array_entries(code_generator *cgt, code_generation *gen,
- int how_many, int format) {
- for (int i=0; i val
-primitive !lookupbyte val val -> val
-=
-
-=
-int CMemoryModel::handle_store_by_ref(code_generation *gen, inter_tree_node *ref) {
- if (Inter::Reference::node_is_ref_to(gen->from, ref, LOOKUP_BIP)) return TRUE;
- if (Inter::Reference::node_is_ref_to(gen->from, ref, LOOKUPBYTE_BIP)) return TRUE;
- return FALSE;
-}
-
-int CMemoryModel::invoke_primitive(code_generation *gen, inter_ti bip, inter_tree_node *P) {
- text_stream *OUT = CodeGen::current(gen);
- switch (bip) {
- case LOOKUP_BIP: WRITE("i7_read_word(proc, "); VNODE_1C; WRITE(", "); VNODE_2C; WRITE(")");
- break;
- case LOOKUPBYTE_BIP: WRITE("i7_read_byte(proc, "); VNODE_1C; WRITE(" + "); VNODE_2C; WRITE(")");
- break;
- default: return NOT_APPLICABLE;
- }
- return FALSE;
-}
diff --git a/inter/final-module/Chapter 5/C Namespace.w b/inter/final-module/Chapter 5/C Namespace.w
index 94fbd2b02..0acf08bdf 100644
--- a/inter/final-module/Chapter 5/C Namespace.w
+++ b/inter/final-module/Chapter 5/C Namespace.w
@@ -118,16 +118,23 @@ void CNamespace::sweep_for_locals(inter_tree *I, inter_tree_node *P, void *state
}
@ Constants in Inter are indeed directly converted to |#define|d constants in C,
-but with their names of course mangled:
+but with their names of course mangled.
+
+For the reason why |Serial| and |Release| are placed higher-up in the file, see
+//C Memory Model//.
=
void CNamespace::declare_constant(code_generator *cgt, code_generation *gen,
inter_symbol *const_s, int form, text_stream *val) {
- segmentation_pos saved = CodeGen::select_layered(gen, c_constants_I7CGS,
+ text_stream *name = Inter::Symbols::name(const_s);
+ int seg = c_constants_I7CGS;
+ if (Str::eq(name, I"Serial")) seg = c_ids_and_maxima_I7CGS;
+ if (Str::eq(name, I"Release")) seg = c_ids_and_maxima_I7CGS;
+ segmentation_pos saved = CodeGen::select_layered(gen, seg,
Inter::Constant::constant_depth(const_s));
text_stream *OUT = CodeGen::current(gen);
WRITE("#define ");
- CNamespace::mangle(cgt, OUT, Inter::Symbols::name(const_s));
+ CNamespace::mangle(cgt, OUT, name);
WRITE(" ");
VanillaConstants::definition_value(gen, form, const_s, val);
WRITE("\n");
diff --git a/inter/final-module/Chapter 5/C Object Model.w b/inter/final-module/Chapter 5/C Object Model.w
index 39b28b3e0..61536525e 100644
--- a/inter/final-module/Chapter 5/C Object Model.w
+++ b/inter/final-module/Chapter 5/C Object Model.w
@@ -702,7 +702,7 @@ void CObjectModel::write_property_values_table(code_generation *gen) {
CNamespace::mangle(NULL, OUT, owner->name);
WRITE("].len[i7_read_word(proc, ");
CNamespace::mangle(NULL, OUT, pair->prop->name);
- WRITE(", 1)] = xt_%S + 1;\n", pair->val);
+ WRITE(", 1)] = %S__xt + 1;\n", pair->val);
} else {
WRITE("i7_properties[");
CNamespace::mangle(NULL, OUT, owner->name);
@@ -855,6 +855,7 @@ text_stream *CObjectModel::test_with_function(inter_ti bip, int *positive) {
@
= (text to inform7_clib.h)
+void i7_initialise_object_tree(i7process_t *proc);
int i7_has(i7process_t *proc, i7word_t obj, i7word_t attr);
int i7_provides(i7process_t *proc, i7word_t owner_id, i7word_t prop_id);
int i7_in(i7process_t *proc, i7word_t obj1, i7word_t obj2);
@@ -936,4 +937,15 @@ void i7_move(i7process_t *proc, i7word_t obj, i7word_t to) {
proc->state.object_tree_child[to] = obj;
}
}
+
+void i7_initialise_object_tree(i7process_t *proc) {
+ proc->state.object_tree_parent = i7_calloc(proc, i7_max_objects, sizeof(i7word_t));
+ proc->state.object_tree_child = i7_calloc(proc, i7_max_objects, sizeof(i7word_t));
+ proc->state.object_tree_sibling = i7_calloc(proc, i7_max_objects, sizeof(i7word_t));
+ for (int i=0; istate.object_tree_parent[i] = 0;
+ proc->state.object_tree_child[i] = 0;
+ proc->state.object_tree_sibling[i] = 0;
+ }
+}
=
diff --git a/inter/final-module/Chapter 5/Final C.w b/inter/final-module/Chapter 5/Final C.w
index 201de3b03..c819c9504 100644
--- a/inter/final-module/Chapter 5/Final C.w
+++ b/inter/final-module/Chapter 5/Final C.w
@@ -38,11 +38,11 @@ code can interface with it. Both are divided into segments. The main file thus:
@e c_early_matter_I7CGS
@e c_text_literals_code_I7CGS
@e c_summations_at_eof_I7CGS
-@e c_arrays_at_eof_I7CGS
+@e c_arrays_I7CGS
@e c_main_matter_I7CGS
@e c_functions_at_eof_I7CGS
@e c_code_at_eof_I7CGS
-@e c_verbs_at_eof_I7CGS
+@e c_verb_arrays_I7CGS
@e c_stubs_at_eof_I7CGS
@e c_property_offset_creator_I7CGS
@e c_mem_I7CGS
@@ -60,11 +60,11 @@ int C_target_segments[] = {
c_early_matter_I7CGS,
c_text_literals_code_I7CGS,
c_summations_at_eof_I7CGS,
- c_arrays_at_eof_I7CGS,
+ c_arrays_I7CGS,
c_main_matter_I7CGS,
c_functions_at_eof_I7CGS,
c_code_at_eof_I7CGS,
- c_verbs_at_eof_I7CGS,
+ c_verb_arrays_I7CGS,
c_stubs_at_eof_I7CGS,
c_property_offset_creator_I7CGS,
c_mem_I7CGS,
@@ -517,7 +517,9 @@ int i7_run_process(i7process_t *proc) {
if (tc == 2) proc->termination_code = 0; /* terminated mid-stream but benignly */
else proc->termination_code = tc; /* terminated mid-stream with a fatal error */
} else {
- i7_initialise_state(proc);
+ i7_initialise_memory_and_stack(proc);
+ i7_initialise_variables(proc);
+ i7_initialise_object_tree(proc);
i7_initializer(proc);
i7_initialise_streams(proc);
fn_i7_mgl_Main(proc);