diff --git a/README.md b/README.md
index dba3e59f4..11766955e 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Inform 7
-v10.1.0-alpha.1+6S96 'Krypton' (11 August 2021)
+v10.1.0-alpha.1+6S97 'Krypton' (12 August 2021)
## About Inform 7
diff --git a/build.txt b/build.txt
index 27fb03b94..5a886cc03 100644
--- a/build.txt
+++ b/build.txt
@@ -1,3 +1,3 @@
Prerelease: alpha.1
-Build Date: 11 August 2021
-Build Number: 6S96
+Build Date: 12 August 2021
+Build Number: 6S97
diff --git a/docs/final-module/2-cal.html b/docs/final-module/2-cal.html
index 5bc8ead2a..4e99e8be1 100644
--- a/docs/final-module/2-cal.html
+++ b/docs/final-module/2-cal.html
@@ -461,6 +461,42 @@ is 20. We instead compile this as
}
The structure text_literal_holder is private to this section.
+
+
+
+int CodeGen::CL::node_is_word_array_ref ( inter_tree * I , inter_tree_node * P ) {
+ int reffed = FALSE ;
+ while ( P -> W . data [ ID_IFLD ] == REFERENCE_IST ) {
+ P = InterTree::first_child ( P );
+ reffed = TRUE ;
+ }
+ if ( P -> W . data [ ID_IFLD ] == INV_IST ) {
+ if ( P -> W . data [ METHOD_INV_IFLD ] == INVOKED_PRIMITIVE ) {
+ inter_symbol * prim = Inter::Inv::invokee ( P );
+ inter_ti bip = Primitives::to_bip ( I , prim );
+ if ( bip == LOOKUPREF_BIP ) return TRUE ;
+ if (( bip == LOOKUP_BIP ) && ( reffed )) return TRUE ;
+ }
+ }
+ return FALSE ;
+}
+
+int CodeGen::CL::node_is_property_ref ( inter_tree * I , inter_tree_node * P ) {
+ int reffed = FALSE ;
+ while ( P -> W . data [ ID_IFLD ] == REFERENCE_IST ) {
+ P = InterTree::first_child ( P );
+ reffed = TRUE ;
+ }
+ if ( P -> W . data [ ID_IFLD ] == INV_IST ) {
+ if ( P -> W . data [ METHOD_INV_IFLD ] == INVOKED_PRIMITIVE ) {
+ inter_symbol * prim = Inter::Inv::invokee ( P );
+ inter_ti bip = Primitives::to_bip ( I , prim );
+ if ( bip == PROPERTYVALUE_BIP ) return TRUE ;
+ }
+ }
+ return FALSE ;
+}
+
diff --git a/docs/final-module/2-cg.html b/docs/final-module/2-cg.html
index 586ed3ae1..f6b3aab0a 100644
--- a/docs/final-module/2-cg.html
+++ b/docs/final-module/2-cg.html
@@ -157,7 +157,7 @@ only when assembling other material, and not for the final output.
return gen ;
}
-The structure code_generation is accessed in 2/fc, 2/cal, 2/iap, 2/vrb, 2/ft, 3/fti, 3/fbi, 3/fi, 4/fi6, 5/fnc, 5/cim and here.
+The structure code_generation is accessed in 2/fc, 2/cal, 2/iap, 2/vrb, 2/ft, 3/fti, 3/fbi, 3/fi, 4/fi6, 5/fnc, 5/crf, 5/cim and here.
@@ -174,7 +174,7 @@ But we abstract it in case it's ever useful for it to be more.
return seg ;
}
-void CodeGen::create_segments ( code_generation * gen , void * data , int codes []) {
+void CodeGen::create_segments ( code_generation * gen , void * data , int codes []) {
gen -> segment_sequence = NEW_LINKED_LIST ( generated_segment );
for ( int i =0; codes [ i ] >= 0 ; i ++) {
if (( codes [ i ] >= MAX_CG_SEGMENTS ) ||
@@ -201,7 +201,7 @@ always be done in a way which is then undone, restoring the previous state:
-generated_segment * CodeGen::select ( code_generation * gen , int i ) {
+generated_segment * CodeGen::select ( code_generation * gen , int i ) {
generated_segment * saved = gen -> current_segment ;
if (( i < 0 ) || ( i >= MAX_CG_SEGMENTS )) internal_error ( "out of range" );
if ( gen -> temporarily_diverted ) internal_error ( "poorly timed selection" );
@@ -209,7 +209,7 @@ always be done in a way which is then undone, restoring the previous state:
return saved ;
}
-void CodeGen::deselect ( code_generation * gen , generated_segment * saved ) {
+void CodeGen::deselect ( code_generation * gen , generated_segment * saved ) {
if ( gen -> temporarily_diverted ) internal_error ( "poorly timed deselection" );
gen -> current_segment = saved ;
}
@@ -238,7 +238,7 @@ we also have to direct it to a given text.
-text_stream * CodeGen::current ( code_generation * gen ) {
+text_stream * CodeGen::current ( code_generation * gen ) {
if ( gen -> temporarily_diverted )
return gen -> segments [ temporary_I7CGS ]-> generated_code ;
if ( gen -> current_segment == NULL ) return NULL ;
diff --git a/docs/final-module/2-fc.html b/docs/final-module/2-fc.html
index f763d743d..c4d4f1573 100644
--- a/docs/final-module/2-fc.html
+++ b/docs/final-module/2-fc.html
@@ -148,7 +148,7 @@ function togglePopup(material_id) {
}
}
-void CodeGen::FC::frame ( code_generation * gen , inter_tree_node * P ) {
+void CodeGen::FC::frame ( code_generation * gen , inter_tree_node * P ) {
switch ( P -> W . data [ ID_IFLD ]) {
case SYMBOL_IST: break ;
case CONSTANT_IST: {
diff --git a/docs/final-module/5-cim.html b/docs/final-module/5-cim.html
index dc5b2ea92..45035a300 100644
--- a/docs/final-module/5-cim.html
+++ b/docs/final-module/5-cim.html
@@ -82,10 +82,6 @@ function togglePopup(material_id) {
-
-
-
-
@@ -94,39 +90,6 @@ function togglePopup(material_id) {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -568,28 +531,25 @@ function togglePopup(material_id) {
+
+
+
+
This is part of the extract file inform7_clib.h.
-
-void CTarget::begin_memory ( code_generation * gen ) {
- generated_segment * saved = CodeGen::select ( gen , c_header_matter_I7CGS );
- text_stream * OUT = CodeGen::current ( gen );
- WRITE ( "i7byte i7mem[];\n" );
- CodeGen::deselect ( gen , saved );
-
- saved = CodeGen::select ( gen , c_mem_I7CGS );
- OUT = CodeGen::current ( gen );
- WRITE ( "i7byte i7mem[] = {\n" );
- CodeGen::deselect ( gen , saved );
+void CTarget::begin_dictionary_words ( code_generation * gen ) {
}
-void CTarget::end_memory ( code_generation * gen ) {
- generated_segment * saved = CodeGen::select ( gen , c_mem_I7CGS );
+void CTarget::end_dictionary_words ( code_generation * gen ) {
+ generated_segment * saved = CodeGen::select ( gen , c_predeclarations_I7CGS );
text_stream * OUT = CodeGen::current ( gen );
- WRITE ( "0, 0 };\n" );
+ for ( int i =0; i < C_GEN_DATA ( C_dword_count ); i ++) {
+ WRITE ( "#define i7_s_dword_%d %d\n" , i , 2 * i );
+ WRITE ( "#define i7_p_dword_%d %d\n" , i , 2 * i + 1 );
+ }
CodeGen::deselect ( gen , saved );
saved = CodeGen::select ( gen , c_predeclarations_I7CGS );
@@ -598,20 +558,7 @@ function togglePopup(material_id) {
CodeGen::deselect ( gen , saved );
}
-void CTarget::begin_dictionary_words ( code_generation * gen ) {
-}
-
-void CTarget::end_dictionary_words ( code_generation * gen ) {
- generated_segment * saved = CodeGen::select ( gen , c_predeclarations_I7CGS );
- text_stream * OUT = CodeGen::current ( gen );
- for ( int i =0; i < C_GEN_DATA ( C_dword_count ); i ++) {
- WRITE ( "#define i7_s_dword_%d %d\n" , i , 2 * i );
- WRITE ( "#define i7_p_dword_%d %d\n" , i , 2 * i + 1 );
- }
- CodeGen::deselect ( gen , saved );
-}
-
-void CTarget::end_functions ( code_generation * gen ) {
+void CTarget::end_functions ( code_generation * gen ) {
generated_segment * saved = CodeGen::select ( gen , c_globals_array_I7CGS );
text_stream * OUT = CodeGen::current ( gen );
WRITE ( "#ifdef i7_defined_i7_mgl_I7S_Comp\n" );
@@ -631,7 +578,7 @@ function togglePopup(material_id) {
CodeGen::deselect ( gen , saved );
}
-void CTarget::fix_locals ( code_generation * gen ) {
+void CTarget::fix_locals ( code_generation * gen ) {
InterTree::traverse ( gen -> from , CTarget::sweep_for_locals , gen , NULL , LOCAL_IST );
}
@@ -645,7 +592,7 @@ function togglePopup(material_id) {
DISCARD_TEXT ( T )
}
-int CTarget::general_segment ( code_generation_target * cgt , code_generation * gen , inter_tree_node * P ) {
+int CTarget::general_segment ( code_generation_target * cgt , code_generation * gen , inter_tree_node * P ) {
switch ( P -> W . data [ ID_IFLD ]) {
case CONSTANT_IST: {
inter_symbol * con_name =
@@ -665,28 +612,28 @@ function togglePopup(material_id) {
return CTarget::default_segment ( cgt );
}
-int CTarget::default_segment ( code_generation_target * cgt ) {
+int CTarget::default_segment ( code_generation_target * cgt ) {
return c_main_matter_I7CGS ;
}
-int CTarget::constant_segment ( code_generation_target * cgt , code_generation * gen ) {
+int CTarget::constant_segment ( code_generation_target * cgt , code_generation * gen ) {
return c_early_matter_I7CGS ;
}
-int CTarget::basic_constant_segment ( code_generation_target * cgt , code_generation * gen , int depth ) {
+int CTarget::basic_constant_segment ( code_generation_target * cgt , code_generation * gen , int depth ) {
if ( depth >= 10 ) depth = 10 ;
return c_constants_1_I7CGS + depth - 1 ;
}
-int CTarget::property_segment ( code_generation_target * cgt ) {
+int CTarget::property_segment ( code_generation_target * cgt ) {
return c_predeclarations_I7CGS ;
}
-int CTarget::tl_segment ( code_generation_target * cgt ) {
+int CTarget::tl_segment ( code_generation_target * cgt ) {
return c_text_literals_code_I7CGS ;
}
-void CTarget::offer_pragma ( code_generation_target * cgt , code_generation * gen ,
+void CTarget::offer_pragma ( code_generation_target * cgt , code_generation * gen ,
inter_tree_node * P , text_stream * tag , text_stream * content ) {
}
-void CTarget::mangle ( code_generation_target * cgt , OUTPUT_STREAM , text_stream * identifier ) {
+void CTarget::mangle ( code_generation_target * cgt , OUTPUT_STREAM , text_stream * identifier ) {
if ( Str::get_first_char ( identifier ) == '(' ) WRITE ( "%S" , identifier );
else if ( Str::get_first_char ( identifier ) == '#' ) {
WRITE ( "i7_mgl_sharp_" );
@@ -696,14 +643,20 @@ function togglePopup(material_id) {
} else WRITE ( "i7_mgl_%S" , identifier );
}
-int C_write_lookup_mode = FALSE ;
-
-int CTarget::compile_primitive ( code_generation_target * cgt , code_generation * gen ,
+int CTarget::compile_primitive ( code_generation_target * cgt , code_generation * gen ,
inter_symbol * prim_name , inter_tree_node * P ) {
text_stream * OUT = CodeGen::current ( gen );
int suppress_terminal_semicolon = FALSE ;
inter_tree * I = gen -> from ;
inter_ti bip = Primitives::to_bip ( I , prim_name );
+
+ int r = CReferences::compile_primitive ( gen , bip , P );
+ if ( r != NOT_APPLICABLE ) return r ;
+ r = CMemoryModel::compile_primitive ( gen , bip , P );
+ if ( r != NOT_APPLICABLE ) return r ;
+ r = CObjectModel::compile_primitive ( gen , bip , P );
+ if ( r != NOT_APPLICABLE ) return r ;
+
switch ( bip ) {
case INVERSION_BIP: break ;
@@ -736,34 +689,9 @@ function togglePopup(material_id) {
case PUSH_BIP: WRITE ( "i7_push(" ); INV_A1 ; WRITE ( ")" ); break ;
case PULL_BIP: INV_A1 ; WRITE ( " = i7_pull()" ); break ;
- case PREINCREMENT_BIP: Generate primitive for store 2.2 ; break ;
- case POSTINCREMENT_BIP: Generate primitive for store 2.2 ; break ;
- case PREDECREMENT_BIP: Generate primitive for store 2.2 ; break ;
- case POSTDECREMENT_BIP: Generate primitive for store 2.2 ; break ;
- case STORE_BIP: Generate primitive for store 2.2 ; break ;
- case SETBIT_BIP: INV_A1 ; WRITE ( " = " ); INV_A1 ; WRITE ( " | " ); INV_A2 ; break ;
- case CLEARBIT_BIP: INV_A1 ; WRITE ( " = " ); INV_A1 ; WRITE ( " &~ (" ); INV_A2 ; WRITE ( ")" ); break ;
- case LOOKUP_BIP: if ( C_write_lookup_mode ) {
- C_write_lookup_mode = FALSE ;
- Generate primitive for lookupref 2.4 ;
- } else {
- Generate primitive for lookup 2.3 ;
- }
- break ;
- case LOOKUPBYTE_BIP: Generate primitive for lookupbyte 2.5 ; break ;
- case LOOKUPREF_BIP: Generate primitive for lookupref 2.4 ; break ;
- case PROPERTYADDRESS_BIP: WRITE ( "i7_prop_addr(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ")" ); break ;
- case PROPERTYLENGTH_BIP: WRITE ( "i7_prop_len(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ")" ); break ;
- case PROPERTYVALUE_BIP: if ( C_write_lookup_mode ) {
- C_write_lookup_mode = FALSE ;
- WRITE ( "i7_change_prop_value(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ", " );
- } else {
- WRITE ( "i7_read_prop_value(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ")" );
- }
- break ;
case BREAK_BIP: WRITE ( "break" ); break ;
case CONTINUE_BIP: WRITE ( "continue" ); break ;
- case RETURN_BIP: Generate primitive for return 2.6 ; break ;
+ case RETURN_BIP: Generate primitive for return 2.2 ; break ;
case JUMP_BIP: WRITE ( "goto " ); INV_A1 ; break ;
case QUIT_BIP: WRITE ( "exit(0)" ); break ;
case RESTORE_BIP: break ;
@@ -787,13 +715,6 @@ function togglePopup(material_id) {
WRITE ( "i7_call_5(" ); INV_A1 ; WRITE ( ", " );
INV_A2 ; WRITE ( ", " ); INV_A3 ; WRITE ( ", " ); INV_A4 ; WRITE ( ", " );
INV_A5 ; WRITE ( ", " ); INV_A6 ; WRITE ( ")" ); break ;
- case MESSAGE0_BIP: WRITE ( "i7_call_0(i7_read_prop_value(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( "))" ); break ;
- case MESSAGE1_BIP: WRITE ( "i7_call_1(i7_read_prop_value(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( "), " );
- INV_A3 ; WRITE ( ")" ); break ;
- case MESSAGE2_BIP: WRITE ( "i7_call_2(i7_read_prop_value(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( "), " );
- INV_A3 ; WRITE ( ", " ); INV_A4 ; WRITE ( ")" ); break ;
- case MESSAGE3_BIP: WRITE ( "i7_call_3(i7_read_prop_value(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( "), " );
- INV_A3 ; WRITE ( ", " ); INV_A4 ; WRITE ( ", " ); INV_A5 ; WRITE ( ")" ); break ;
case CALLMESSAGE0_BIP: WRITE ( "i7_ccall_0(" ); INV_A1 ; WRITE ( ")" ); break ;
case CALLMESSAGE1_BIP: WRITE ( "i7_ccall_1(" ); INV_A1 ; WRITE ( ", " );
INV_A2 ; WRITE ( ")" ); break ;
@@ -814,12 +735,10 @@ function togglePopup(material_id) {
case MOVE_BIP: WRITE ( "i7_move(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ")" ); break ;
case REMOVE_BIP: WRITE ( "i7_move(" ); INV_A1 ; WRITE ( ", 0)" ); break ;
- case GIVE_BIP: WRITE ( "i7_give(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ", 1)" ); break ;
- case TAKE_BIP: WRITE ( "i7_give(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ", 0)" ); break ;
case ALTERNATIVECASE_BIP: INV_A1 ; WRITE ( ", " ); INV_A2 ; break ;
case SEQUENTIAL_BIP: WRITE ( "(" ); INV_A1 ; WRITE ( "," ); INV_A2 ; WRITE ( ")" ); break ;
- case TERNARYSEQUENTIAL_BIP: Generate primitive for ternarysequential 2.7 ; break ;
+ case TERNARYSEQUENTIAL_BIP: Generate primitive for ternarysequential 2.3 ; break ;
case PRINT_BIP: WRITE ( "printf(\"%%s\", " ); INV_A1_PRINTMODE ; WRITE ( ")" ); break ;
case PRINTRET_BIP: WRITE ( "printf(\"%%s\", " ); INV_A1_PRINTMODE ; WRITE ( "); return 1" ); break ;
@@ -837,19 +756,19 @@ function togglePopup(material_id) {
case PRINTCINDEF_BIP: WRITE ( "i7_print_cindef_art(" ); INV_A1 ; WRITE ( ")" ); break ;
case BOX_BIP: WRITE ( "i7_print_box(" ); INV_A1_BOXMODE ; WRITE ( ")" ); break ;
- case IF_BIP: Generate primitive for if 2.8 ; break ;
- case IFDEBUG_BIP: Generate primitive for ifdebug 2.9 ; break ;
- case IFSTRICT_BIP: Generate primitive for ifstrict 2.10 ; break ;
- case IFELSE_BIP: Generate primitive for ifelse 2.11 ; break ;
- case WHILE_BIP: Generate primitive for while 2.12 ; break ;
- case DO_BIP: Generate primitive for do 2.13 ; break ;
- case FOR_BIP: Generate primitive for for 2.14 ; break ;
- case OBJECTLOOP_BIP: Generate primitive for objectloop 2.15 ; break ;
- case OBJECTLOOPX_BIP: Generate primitive for objectloopx 2.16 ; break ;
- case LOOP_BIP: Generate primitive for loop 2.17 ; break ;
- case SWITCH_BIP: Generate primitive for switch 2.18 ; break ;
- case CASE_BIP: Generate primitive for case 2.19 ; break ;
- case DEFAULT_BIP: Generate primitive for default 2.20 ; break ;
+ case IF_BIP: Generate primitive for if 2.4 ; break ;
+ case IFDEBUG_BIP: Generate primitive for ifdebug 2.5 ; break ;
+ case IFSTRICT_BIP: Generate primitive for ifstrict 2.6 ; break ;
+ case IFELSE_BIP: Generate primitive for ifelse 2.7 ; break ;
+ case WHILE_BIP: Generate primitive for while 2.8 ; break ;
+ case DO_BIP: Generate primitive for do 2.9 ; break ;
+ case FOR_BIP: Generate primitive for for 2.10 ; break ;
+ case OBJECTLOOP_BIP: Generate primitive for objectloop 2.11 ; break ;
+ case OBJECTLOOPX_BIP: Generate primitive for objectloopx 2.12 ; break ;
+ case LOOP_BIP: Generate primitive for loop 2.13 ; break ;
+ case SWITCH_BIP: Generate primitive for switch 2.14 ; break ;
+ case CASE_BIP: Generate primitive for case 2.15 ; break ;
+ case DEFAULT_BIP: Generate primitive for default 2.16 ; break ;
case RANDOM_BIP: WRITE ( "fn_i7_mgl_random(1, " ); INV_A1 ; WRITE ( ")" ); break ;
@@ -867,60 +786,7 @@ function togglePopup(material_id) {
CTarget::comparison ( cgt , gen , bip , InterTree::first_child ( P ), InterTree::second_child ( P ));
This code is used in §2 (12 times).
-
-
-
- text_stream * store_form = NULL ;
- switch ( bip ) {
- case PREINCREMENT_BIP: store_form = I "i7_cpv_PREINC" ; break ;
- case POSTINCREMENT_BIP: store_form = I "i7_cpv_POSTINC" ; break ;
- case PREDECREMENT_BIP: store_form = I "i7_cpv_PREDEC" ; break ;
- case POSTDECREMENT_BIP: store_form = I "i7_cpv_POSTDEC" ; break ;
- case STORE_BIP: store_form = I "i7_cpv_SET" ; break ;
- }
- inter_tree_node * ref = InterTree::first_child ( P );
- if ( CTarget::basically_an_array_write ( gen -> from , ref )) {
- WRITE ( "(" ); C_write_lookup_mode = TRUE ; INV_A1 ; C_write_lookup_mode = FALSE ;
- if ( bip == STORE_BIP ) { INV_A2 ; } else { WRITE ( "0" ); }
- WRITE ( ", %S))" , store_form );
- } else if ( CTarget::basically_a_property_write ( gen -> from , ref )) {
- WRITE ( "(" ); C_write_lookup_mode = TRUE ; INV_A1 ; C_write_lookup_mode = FALSE ;
- if ( bip == STORE_BIP ) { INV_A2 ; } else { WRITE ( "0" ); }
- WRITE ( ", %S))" , store_form );
- } else {
- switch ( bip ) {
- case PREINCREMENT_BIP: WRITE ( "++(" ); INV_A1 ; WRITE ( ")" ); break ;
- case POSTINCREMENT_BIP: WRITE ( "(" ); INV_A1 ; WRITE ( ")++" ); break ;
- case PREDECREMENT_BIP: WRITE ( "--(" ); INV_A1 ; WRITE ( ")" ); break ;
- case POSTDECREMENT_BIP: WRITE ( "(" ); INV_A1 ; WRITE ( ")--" ); break ;
- case STORE_BIP: WRITE ( "(" ); INV_A1 ; WRITE ( " = " ); INV_A2 ; WRITE ( ")" ); break ;
- }
- }
-
-This code is used in §2 (five times).
-
-
-
- WRITE ( "i7_lookup(i7mem, " ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ")" );
-
-
-
-
-
- WRITE ( "write_i7_lookup(i7mem, " ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ", " );
-
-This code is used in §2 (twice).
-
-
-
- WRITE ( "i7mem[" ); INV_A1 ; WRITE ( " + " ); INV_A2 ; WRITE ( "]" );
-
-
-
@@ -941,7 +807,7 @@ function togglePopup(material_id) {
}
-
@@ -954,7 +820,7 @@ function togglePopup(material_id) {
WRITE ( ")" );
-
@@ -963,7 +829,7 @@ function togglePopup(material_id) {
suppress_terminal_semicolon = TRUE ;
-
@@ -971,7 +837,7 @@ function togglePopup(material_id) {
suppress_terminal_semicolon = TRUE ;
-
@@ -979,7 +845,7 @@ function togglePopup(material_id) {
suppress_terminal_semicolon = TRUE ;
-
@@ -988,7 +854,7 @@ function togglePopup(material_id) {
suppress_terminal_semicolon = TRUE ;
-
@@ -996,14 +862,14 @@ function togglePopup(material_id) {
suppress_terminal_semicolon = TRUE ;
-
WRITE ( "do {" ); INV_A2 ; WRITE ( "} until (\n" ); INDENT ; INV_A1 ; OUTDENT ; WRITE ( ")\n" );
-
@@ -1020,7 +886,7 @@ function togglePopup(material_id) {
suppress_terminal_semicolon = TRUE ;
-
@@ -1045,7 +911,7 @@ function togglePopup(material_id) {
suppress_terminal_semicolon = TRUE ;
-
@@ -1059,7 +925,7 @@ function togglePopup(material_id) {
suppress_terminal_semicolon = TRUE ;
-
@@ -1067,7 +933,7 @@ function togglePopup(material_id) {
suppress_terminal_semicolon = TRUE ;
-
@@ -1076,7 +942,7 @@ function togglePopup(material_id) {
suppress_terminal_semicolon = TRUE ;
-
@@ -1085,7 +951,7 @@ function togglePopup(material_id) {
suppress_terminal_semicolon = TRUE ;
-
@@ -1096,7 +962,7 @@ function togglePopup(material_id) {
-void CTarget::caser ( code_generation_target * cgt , code_generation * gen , inter_tree_node * X ) {
+void CTarget::caser ( code_generation_target * cgt , code_generation * gen , inter_tree_node * X ) {
if ( X -> W . data [ ID_IFLD ] == INV_IST ) {
if ( X -> W . data [ METHOD_INV_IFLD ] == INVOKED_PRIMITIVE ) {
inter_symbol * prim = Inter::Inv::invokee ( X );
@@ -1114,7 +980,7 @@ function togglePopup(material_id) {
WRITE ( ": " );
}
-void CTarget::comparison ( code_generation_target * cgt , code_generation * gen ,
+void CTarget::comparison ( code_generation_target * cgt , code_generation * gen ,
inter_ti bip , inter_tree_node * X , inter_tree_node * Y ) {
CTarget::comparison_r ( cgt , gen , bip , X , Y , 0 );
}
@@ -1170,7 +1036,7 @@ function togglePopup(material_id) {
-void CTarget::compile_dictionary_word ( code_generation_target * cgt , code_generation * gen ,
+void CTarget::compile_dictionary_word ( code_generation_target * cgt , code_generation * gen ,
text_stream * S , int pluralise ) {
text_stream * OUT = CodeGen::current ( gen );
text_stream * val = Dictionaries::get_text ( C_GEN_DATA ( C_vm_dictionary ), S );
@@ -1187,7 +1053,7 @@ function togglePopup(material_id) {
-void CTarget::compile_literal_number ( code_generation_target * cgt ,
+void CTarget::compile_literal_number ( code_generation_target * cgt ,
code_generation * gen , inter_ti val , int hex_mode ) {
text_stream * OUT = CodeGen::current ( gen );
if ( hex_mode ) WRITE ( "0x%x" , val );
@@ -1197,7 +1063,7 @@ function togglePopup(material_id) {
-void CTarget::compile_literal_text ( code_generation_target * cgt , code_generation * gen ,
+void CTarget::compile_literal_text ( code_generation_target * cgt , code_generation * gen ,
text_stream * S , int printing_mode , int box_mode ) {
text_stream * OUT = CodeGen::current ( gen );
@@ -1236,7 +1102,7 @@ function togglePopup(material_id) {
-int CTarget::prepare_variable ( code_generation_target * cgt , code_generation * gen ,
+int CTarget::prepare_variable ( code_generation_target * cgt , code_generation * gen ,
inter_tree_node * P , inter_symbol * var_name , int k ) {
if ( Inter::Symbols::read_annotation ( var_name , EXPLICIT_VARIABLE_IANN ) != 1 ) {
if ( Inter::Symbols::read_annotation ( var_name , ASSIMILATED_IANN ) != 1 ) {
@@ -1251,7 +1117,7 @@ function togglePopup(material_id) {
return k ;
}
-int CTarget::declare_variable ( code_generation_target * cgt , code_generation * gen ,
+int CTarget::declare_variable ( code_generation_target * cgt , code_generation * gen ,
inter_tree_node * P , inter_symbol * var_name , int k , int of ) {
if ( Inter::Symbols::read_annotation ( var_name , ASSIMILATED_IANN ) == 1 ) {
generated_segment * saved = CodeGen::select ( gen , c_globals_array_I7CGS );
@@ -1267,26 +1133,26 @@ function togglePopup(material_id) {
CodeGen::deselect ( gen , saved );
}
if ( Inter::Symbols::read_annotation ( var_name , EXPLICIT_VARIABLE_IANN ) != 1 ) {
- if ( k == 0 ) CTarget::begin_array ( cgt , gen , I "Global_Vars" , WORD_ARRAY_FORMAT );
+ if ( k == 0 ) CMemoryModel::begin_array ( cgt , gen , I "Global_Vars" , WORD_ARRAY_FORMAT );
TEMPORARY_TEXT ( val )
CodeGen::select_temporary ( gen , val );
CodeGen::CL::literal ( gen , NULL , Inter::Packages::scope_of ( P ), P -> W . data [ VAL1_VAR_IFLD ], P -> W . data [ VAL2_VAR_IFLD ], FALSE );
CodeGen::deselect_temporary ( gen );
- CTarget::array_entry ( cgt , gen , val , WORD_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( cgt , gen , val , WORD_ARRAY_FORMAT );
DISCARD_TEXT ( val )
k ++;
if ( k == of ) {
if ( k < 2 ) {
- CTarget::array_entry ( cgt , gen , I "0" , WORD_ARRAY_FORMAT );
- CTarget::array_entry ( cgt , gen , I "0" , WORD_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( cgt , gen , I "0" , WORD_ARRAY_FORMAT );
+ CMemoryModel::array_entry ( cgt , gen , I "0" , WORD_ARRAY_FORMAT );
}
- CTarget::end_array ( cgt , gen , WORD_ARRAY_FORMAT );
+ CMemoryModel::end_array ( cgt , gen , WORD_ARRAY_FORMAT );
}
}
return k ;
}
-void CTarget::begin_constant ( code_generation_target * cgt , code_generation * gen , text_stream * const_name , int continues , int ifndef_me ) {
+void CTarget::begin_constant ( code_generation_target * cgt , code_generation * gen , text_stream * const_name , int continues , int ifndef_me ) {
text_stream * OUT = CodeGen::current ( gen );
if ( ifndef_me ) {
WRITE ( "#ifndef " );
@@ -1297,7 +1163,7 @@ function togglePopup(material_id) {
CTarget::mangle ( cgt , OUT , const_name );
if ( continues ) WRITE ( " " );
}
-void CTarget::end_constant ( code_generation_target * cgt , code_generation * gen , text_stream * const_name , int ifndef_me ) {
+void CTarget::end_constant ( code_generation_target * cgt , code_generation * gen , text_stream * const_name , int ifndef_me ) {
text_stream * OUT = CodeGen::current ( gen );
WRITE ( "\n" );
if ( ifndef_me ) WRITE ( "#endif\n" );
@@ -1330,7 +1196,7 @@ function togglePopup(material_id) {
CodeGen::deselect ( gen , saved );
}
-void CTarget::begin_functions ( code_generation * gen ) {
+void CTarget::begin_functions ( code_generation * gen ) {
CTarget::add_main ( gen );
CTarget::make_veneer_fcf ( gen , I "Z__Region" );
CTarget::make_veneer_fcf ( gen , I "CP__Tab" );
@@ -1359,7 +1225,7 @@ function togglePopup(material_id) {
final_c_function * C_fn_being_found = NULL ;
-void CTarget::begin_function ( code_generation_target * cgt , int pass , code_generation * gen , inter_symbol * fn ) {
+void CTarget::begin_function ( code_generation_target * cgt , int pass , code_generation * gen , inter_symbol * fn ) {
text_stream * fn_name = CodeGen::CL::name ( fn );
C_fn_parameter_count = 0 ;
if ( pass == 1 ) {
@@ -1380,7 +1246,7 @@ function togglePopup(material_id) {
}
}
-void CTarget::begin_function_code ( code_generation_target * cgt , code_generation * gen ) {
+void CTarget::begin_function_code ( code_generation_target * cgt , code_generation * gen ) {
text_stream * OUT = CodeGen::current ( gen );
WRITE ( ") {" );
if ( C_fn_being_found ) {
@@ -1390,7 +1256,7 @@ function togglePopup(material_id) {
}
}
-void CTarget::place_label ( code_generation_target * cgt , code_generation * gen , text_stream * label_name ) {
+void CTarget::place_label ( code_generation_target * cgt , code_generation * gen , text_stream * label_name ) {
text_stream * OUT = CodeGen::current ( gen );
LOOP_THROUGH_TEXT ( pos , label_name )
if ( Str::get ( pos ) != '.' )
@@ -1398,7 +1264,7 @@ function togglePopup(material_id) {
WRITE ( ": ;\n" , label_name );
}
-void CTarget::end_function ( code_generation_target * cgt , int pass , code_generation * gen , inter_symbol * fn ) {
+void CTarget::end_function ( code_generation_target * cgt , int pass , code_generation * gen , inter_symbol * fn ) {
if ( pass == 1 ) {
WRITE_TO ( C_fn_prototype , ")" );
@@ -1417,7 +1283,7 @@ function togglePopup(material_id) {
}
}
-void CTarget::begin_function_call ( code_generation_target * cgt , code_generation * gen , inter_symbol * fn , int argc ) {
+void CTarget::begin_function_call ( code_generation_target * cgt , code_generation * gen , inter_symbol * fn , int argc ) {
inter_tree_node * D = fn -> definition ;
if (( D ) && ( D -> W . data [ ID_IFLD ] == CONSTANT_IST ) && ( D -> W . data [ FORMAT_CONST_IFLD ] == CONSTANT_DIRECT )) {
inter_ti val1 = D -> W . data [ DATA_CONST_IFLD ];
@@ -1440,7 +1306,7 @@ function togglePopup(material_id) {
}
}
}
-void CTarget::argument ( code_generation_target * cgt , code_generation * gen , inter_tree_node * F , inter_symbol * fn , int argc , int of_argc ) {
+void CTarget::argument ( code_generation_target * cgt , code_generation * gen , inter_tree_node * F , inter_symbol * fn , int argc , int of_argc ) {
text_stream * OUT = CodeGen::current ( gen );
if ( GENERAL_POINTER_IS_NULL ( fn -> translation_data ) == FALSE ) {
final_c_function * fcf = RETRIEVE_POINTER_final_c_function ( fn -> translation_data );
@@ -1451,7 +1317,7 @@ function togglePopup(material_id) {
CodeGen::FC::frame ( gen , F );
}
}
-void CTarget::end_function_call ( code_generation_target * cgt , code_generation * gen , inter_symbol * fn , int argc ) {
+void CTarget::end_function_call ( code_generation_target * cgt , code_generation * gen , inter_symbol * fn , int argc ) {
if ( GENERAL_POINTER_IS_NULL ( fn -> translation_data )) {
text_stream * OUT = CodeGen::current ( gen );
WRITE ( ")" );
@@ -1478,7 +1344,7 @@ function togglePopup(material_id) {
int C_operand_count = 0 , C_operand_branches = FALSE ; inter_tree_node * C_operand_label = NULL ;
int C_pointer_on_operand = -1;
-void CTarget::begin_opcode ( code_generation_target * cgt , code_generation * gen , text_stream * opcode ) {
+void CTarget::begin_opcode ( code_generation_target * cgt , code_generation * gen , text_stream * opcode ) {
text_stream * OUT = CodeGen::current ( gen );
C_operand_branches = FALSE ;
C_operand_label = NULL ;
@@ -1511,7 +1377,7 @@ function togglePopup(material_id) {
if ( Str::eq ( opcode , I "@tan" )) C_pointer_on_operand = 2 ;
}
-void CTarget::supply_operand ( code_generation_target * cgt , code_generation * gen , inter_tree_node * F , int is_label ) {
+void CTarget::supply_operand ( code_generation_target * cgt , code_generation * gen , inter_tree_node * F , int is_label ) {
text_stream * OUT = CodeGen::current ( gen );
if ( is_label ) {
C_operand_label = F ;
@@ -1530,7 +1396,7 @@ function togglePopup(material_id) {
}
}
}
-void CTarget::end_opcode ( code_generation_target * cgt , code_generation * gen ) {
+void CTarget::end_opcode ( code_generation_target * cgt , code_generation * gen ) {
text_stream * OUT = CodeGen::current ( gen );
WRITE ( ")" );
if ( C_operand_branches ) {
@@ -1541,7 +1407,7 @@ function togglePopup(material_id) {
}
}
-void CTarget::declare_local_variable ( code_generation_target * cgt , int pass ,
+void CTarget::declare_local_variable ( code_generation_target * cgt , int pass ,
code_generation * gen , inter_tree_node * P , inter_symbol * var_name ) {
TEMPORARY_TEXT ( name )
CTarget::mangle ( cgt , name , CodeGen::CL::name ( var_name ));
@@ -1570,96 +1436,17 @@ function togglePopup(material_id) {
DISCARD_TEXT ( name )
}
-int C_array_entry_count = 0 ;
-text_stream * C_array_name = NULL ;
-void CTarget::begin_array ( code_generation_target * cgt , code_generation * gen , text_stream * array_name , int format ) {
+void CTarget::new_fake_action ( code_generation_target * cgt , code_generation * gen , text_stream * name ) {
generated_segment * saved = CodeGen::select ( gen , c_predeclarations_I7CGS );
text_stream * OUT = CodeGen::current ( gen );
- WRITE ( "#define " );
- CTarget::mangle ( cgt , OUT , array_name );
- WRITE ( " %d
- CodeGen::deselect(gen, saved);
-
- if (C_array_name == NULL) C_array_name = Str::new();
- Str::clear(C_array_name); WRITE_TO(C_array_name, " % S ", array_name);
- C_array_entry_count = 0;
-
- if ((format == TABLE_ARRAY_FORMAT) || (format == BUFFER_ARRAY_FORMAT)) {
- TEMPORARY_TEXT(extname)
- WRITE_TO(extname, " xt_ % S ", array_name);
- CTarget::array_entry(cgt, gen, extname, format);
- DISCARD_TEXT(extname)
- }
-}
-
-void CTarget::array_entry(code_generation_target *cgt, code_generation *gen, text_stream *entry, int format) {
- generated_segment *saved = CodeGen::select(gen, c_mem_I7CGS);
- text_stream *OUT = CodeGen::current(gen);
- if ((format == TABLE_ARRAY_FORMAT) || (format == WORD_ARRAY_FORMAT)) {
- WRITE(" I7BYTE_0 (% S ), I7BYTE_1 (% S ), I7BYTE_2 (% S ), I7BYTE_3 (% S ),\ n ",
- entry, entry, entry, entry);
- C_GEN_DATA(extent_of_i7mem) += 4;
- } else {
- WRITE(" ( i7byte ) % S ,\ n ", entry);
- C_GEN_DATA(extent_of_i7mem) += 1;
- }
- CodeGen::deselect(gen, saved);
- C_array_entry_count++;
-}
-
-void CTarget::end_array(code_generation_target *cgt, code_generation *gen, int format) {
- generated_segment *saved = CodeGen::select(gen, c_predeclarations_I7CGS);
- text_stream *OUT = CodeGen::current(gen);
- if ((format == TABLE_ARRAY_FORMAT) || (format == BUFFER_ARRAY_FORMAT)) {
- WRITE(" # define xt_ % S % d \ n ", C_array_name, C_array_entry_count-1);
- }
- CodeGen::deselect(gen, saved);
-}
-
-int CTarget::basically_an_array_write(inter_tree *I, inter_tree_node *P) {
- int reffed = FALSE;
- while (P->W.data[ID_IFLD] == REFERENCE_IST) {
- P = InterTree::first_child(P);
- reffed = TRUE;
- }
- if (P->W.data[ID_IFLD] == INV_IST) {
- if (P->W.data[METHOD_INV_IFLD] == INVOKED_PRIMITIVE) {
- inter_symbol *prim = Inter::Inv::invokee(P);
- inter_ti bip = Primitives::to_bip(I, prim);
- if (bip == LOOKUPREF_BIP) return TRUE;
- if ((bip == LOOKUP_BIP) && (reffed)) return TRUE;
- }
- }
- return FALSE;
-}
-
-int CTarget::basically_a_property_write(inter_tree *I, inter_tree_node *P) {
- int reffed = FALSE;
- while (P->W.data[ID_IFLD] == REFERENCE_IST) {
- P = InterTree::first_child(P);
- reffed = TRUE;
- }
- if (P->W.data[ID_IFLD] == INV_IST) {
- if (P->W.data[METHOD_INV_IFLD] == INVOKED_PRIMITIVE) {
- inter_symbol *prim = Inter::Inv::invokee(P);
- inter_ti bip = Primitives::to_bip(I, prim);
- if (bip == PROPERTYVALUE_BIP) return TRUE;
- }
- }
- return FALSE;
-}
-
-void CTarget::new_fake_action(code_generation_target *cgt, code_generation *gen, text_stream *name) {
- generated_segment *saved = CodeGen::select(gen, c_predeclarations_I7CGS);
- text_stream *OUT = CodeGen::current(gen);
- WRITE(" # define i7_ss_ % S % d \ n ", name, C_GEN_DATA(C_action_count)++);
- CodeGen::deselect(gen, saved);
-}
+ WRITE ( "#define i7_ss_%S %d\n" , name , C_GEN_DATA ( C_action_count )++);
+ CodeGen::deselect ( gen , saved );
+}
- The function CTarget::array_entry is used in Generating C (§1 ). The function CTarget::end_array is used in Generating C (§1 ). The function CTarget::basically_an_array_write is used in §2.2 . The function CTarget::basically_a_property_write is used in §2.2 . The function CTarget::new_fake_action is used in Generating C (§1 ). The structure final_c_function is private to this section.
+The structure final_c_function is private to this section.
+
diff --git a/docs/final-module/5-cmm.html b/docs/final-module/5-cmm.html
new file mode 100644
index 000000000..198ae8735
--- /dev/null
+++ b/docs/final-module/5-cmm.html
@@ -0,0 +1,409 @@
+
+
+
+ C Memory Model
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Compiler Webs Inbuild Modules Inform7 Modules Inter Modules Services
+
+
+
+
+How arrays of all kinds are stored in C.
+
+
+
+
+
+
+void CMemoryModel::initialise ( code_generation_target * cgt ) {
+ METHOD_ADD ( cgt , BEGIN_ARRAY_MTID , CMemoryModel::begin_array );
+ METHOD_ADD ( cgt , ARRAY_ENTRY_MTID , CMemoryModel::array_entry );
+ 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 ;
+ int next_node_is_a_ref ;
+} 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 ;
+ C_GEN_DATA ( memdata . next_node_is_a_ref ) = FALSE ;
+}
+
+The structure C_generation_memory_model_data is accessed in 5/crf and here.
+
+
+(a) Byte-accessible memory must contain all of the arrays. These can but need
+not have alignment gaps in between them. (For C, they do not.)
+ (b) "Addresses" in this memory identify individual byte positions in it. These
+can but need not start at 0. (For C, they do.) They must not be too large to
+fit into an Inter value.
+ (c) When an array name is compiled, its runtime value must be its address.
+ (d) When an Inter value is stored in byte-accessible memory, it occupies either
+2 or 4 consecutive bytes, with the little end first. The result is called a
+"word". (For C, always 4, which is always .) Conversion between
+a word stored in memory and an Inter value must be faithful in both directions.
+ (e) Words can be stored at any byte position, and not only at (say) multiples
+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.
+
+
+
+
+This is part of the extract file inform7_clib.h.
+
+
+
+void CMemoryModel::begin ( code_generation * gen ) {
+ generated_segment * saved = CodeGen::select ( gen , c_mem_I7CGS );
+ text_stream * OUT = CodeGen::current ( gen );
+ WRITE ( "i7byte i7mem[] = {\n" );
+ CodeGen::deselect ( gen , saved );
+}
+
+
+
+
+void CMemoryModel::end ( code_generation * gen ) {
+ generated_segment * saved = CodeGen::select ( gen , c_mem_I7CGS );
+ text_stream * OUT = CodeGen::current ( gen );
+ WRITE ( "0, 0 };\n" );
+ CodeGen::deselect ( gen , saved );
+}
+
+
+
+
+
+
+
+
+This is part of the extract file inform7_clib.h.
+
+
+
+This is part of the extract file inform7_clib.h.
+
+
+
+This is part of the extract file inform7_clib.h.
+
+
+
+ | entries count 0, 1, 2,... | entry 0 is N, then entries count 1, 2, ..., N
+-------------+-------------------------------+-----------------------------------------------
+byte entries | BYTE_ARRAY_FORMAT | BUFFER_ARRAY_FORMAT
+-------------+-------------------------------+-----------------------------------------------
+word entries | WORD_ARRAY_FORMAT | TABLE_ARRAY_FORMAT
+-------------+-------------------------------+-----------------------------------------------
+
+
+void CMemoryModel::begin_array ( code_generation_target * cgt , code_generation * gen ,
+ text_stream * array_name , int format ) {
+ 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 ;
+
+ text_stream * format_name = I "unknown" ;
+ Work out the format name 7.1 ;
+ Define a constant for the byte address in memory where the array begins 7.2 ;
+ if (( format == TABLE_ARRAY_FORMAT ) || ( format == BUFFER_ARRAY_FORMAT ))
+ Place the extent entry N at index 0 7.3 ;
+}
+
+
+
+
+ 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 ;
+ }
+
+
+
+
+
+
+
+
+
+ generated_segment * saved = CodeGen::select ( gen , c_predeclarations_I7CGS );
+ text_stream * OUT = CodeGen::current ( gen );
+ WRITE ( "#define " );
+ CTarget::mangle ( cgt , OUT , array_name );
+ WRITE ( " %d /* = position in i7mem of %S array %S */\n" ,
+ C_GEN_DATA ( memdata . himem ), format_name , array_name );
+ CodeGen::deselect ( gen , saved );
+
+
+
+
+
+
+
+ TEMPORARY_TEXT ( extname )
+ WRITE_TO ( extname , "xt_%S" , array_name );
+ CMemoryModel::array_entry ( cgt , gen , extname , format );
+ DISCARD_TEXT ( extname )
+
+
+
+
+
+void CMemoryModel::array_entry ( code_generation_target * cgt , code_generation * gen ,
+ text_stream * entry , int format ) {
+ generated_segment * 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 8.2
+ else
+ This is a byte entry 8.1 ;
+ CodeGen::deselect ( gen , saved );
+ C_GEN_DATA ( memdata . entry_count )++;
+}
+
+
+
+
+ WRITE ( " (i7byte) %S,\n" , entry );
+ C_GEN_DATA ( memdata . himem ) += 1 ;
+
+
+
+
+
+
+
+ WRITE ( " I7BYTE_0(%S), I7BYTE_1(%S), I7BYTE_2(%S), I7BYTE_3(%S),\n" ,
+ entry , entry , entry , entry );
+ C_GEN_DATA ( memdata . himem ) += 4 ;
+
+
+
+
+
+void CMemoryModel::end_array ( code_generation_target * cgt , code_generation * gen , int format ) {
+ if (( format == TABLE_ARRAY_FORMAT ) || ( format == BUFFER_ARRAY_FORMAT )) {
+ generated_segment * saved = CodeGen::select ( gen , c_predeclarations_I7CGS );
+ text_stream * OUT = CodeGen::current ( gen );
+ WRITE ( "#define xt_%S %d\n" ,
+ C_GEN_DATA ( memdata . array_name ), C_GEN_DATA ( memdata . entry_count )-1);
+ CodeGen::deselect ( gen , saved );
+ }
+}
+
+
+
+
+primitive !lookup val val -> val
+primitive !lookupbyte val val -> val
+primitive !lookupref val val -> ref
+
+
+
+
+int CMemoryModel::compile_primitive ( code_generation * gen , inter_ti bip , inter_tree_node * P ) {
+ text_stream * OUT = CodeGen::current ( gen );
+ switch ( bip ) {
+ case LOOKUP_BIP: if ( CReferences::am_I_a_ref ( gen )) {
+ Word value as reference 10.3 ;
+ } else {
+ Word value as value 10.1 ;
+ }
+ break ;
+ case LOOKUPBYTE_BIP: Byte value as value 10.2 ; break ;
+ case LOOKUPREF_BIP: Word value as reference 10.3 ; break ;
+ default: return NOT_APPLICABLE ;
+ }
+ return FALSE ;
+}
+
+
+
+
+ WRITE ( "i7_read_word(i7mem, " ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ")" );
+
+This code is used in §10 .
+
+
+
+ WRITE ( "i7mem[" ); INV_A1 ; WRITE ( " + " ); INV_A2 ; WRITE ( "]" );
+
+This code is used in §10 .
+
+
+
+ WRITE ( "i7_write_word(i7mem, " ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ", " );
+
+This code is used in §10 (twice).
+
+
+
+
+
+
+
diff --git a/docs/final-module/5-com.html b/docs/final-module/5-com.html
index c04bf9650..50f2fda1d 100644
--- a/docs/final-module/5-com.html
+++ b/docs/final-module/5-com.html
@@ -74,7 +74,7 @@ function togglePopup(material_id) {
How objects, classes and properties are compiled to C.
-
+
@@ -104,7 +104,7 @@ function togglePopup(material_id) {
int is_class ;
} C_property_owner ;
-void CObjectModel::initialise_data ( code_generation * gen ) {
+void CObjectModel::initialise_data ( code_generation * gen ) {
C_GEN_DATA ( objdata . owner_id_count ) = 0 ;
C_GEN_DATA ( objdata . property_id_counter ) = 0 ;
C_GEN_DATA ( objdata . C_property_offsets_made ) = 0 ;
@@ -112,13 +112,13 @@ function togglePopup(material_id) {
C_GEN_DATA ( objdata . owners_capacity ) = 0 ;
}
-void CObjectModel::begin ( code_generation * gen ) {
+void CObjectModel::begin ( code_generation * gen ) {
CObjectModel::initialise_data ( gen );
Begin the initialiser function 1.5 ;
CObjectModel::declare_property_by_name ( gen , I "value_range" , TRUE );
}
-void CObjectModel::end ( code_generation * gen ) {
+void CObjectModel::end ( code_generation * gen ) {
Complete the initialiser function 1.6 ;
Complete the property-offset creator function 1.4 ;
Predeclare the object count and class array 1.3 ;
@@ -369,12 +369,12 @@ properties at runtime.
if ( C_GEN_DATA ( objdata . C_property_offsets_made )++ == 0 )
Begin the property-offset creator function 8.1 ;
- WRITE ( "write_i7_lookup(i7mem, " );
+ WRITE ( "i7_write_word(i7mem, " );
if ( as_attr ) CTarget::mangle ( cgt , OUT , I "attributed_property_offsets" );
else CTarget::mangle ( cgt , OUT , I "valued_property_offsets" );
WRITE ( ", " );
CTarget::mangle ( cgt , OUT , prop );
- WRITE ( ", %d, i7_cpv_SET);\n" , pos );
+ WRITE ( ", %d, i7_lvalue_SET);\n" , pos );
CodeGen::deselect ( gen , saved );
}
@@ -389,9 +389,9 @@ not deriving from an Inform program.
WRITE ( "i7val fn_i7_mgl_CreatePropertyOffsets(int argc) {\n" ); INDENT ;
WRITE ( "for (int i=0; i<i7_mgl_attributed_property_offsets_SIZE; i++)\n" ); INDENT ;
- WRITE ( "write_i7_lookup(i7mem, i7_mgl_attributed_property_offsets, i, -1, i7_cpv_SET);\n" ); OUTDENT ;
+ WRITE ( "i7_write_word(i7mem, i7_mgl_attributed_property_offsets, i, -1, i7_lvalue_SET);\n" ); OUTDENT ;
WRITE ( "for (int i=0; i<i7_mgl_valued_property_offsets_SIZE; i++)\n" ); INDENT ;
- WRITE ( "write_i7_lookup(i7mem, i7_mgl_valued_property_offsets, i, -1, i7_cpv_SET);\n" ); OUTDENT ;
+ WRITE ( "i7_write_word(i7mem, i7_mgl_valued_property_offsets, i, -1, i7_lvalue_SET);\n" ); OUTDENT ;
+
+
+int CObjectModel::compile_primitive ( code_generation * gen , inter_ti bip , inter_tree_node * P ) {
+ text_stream * OUT = CodeGen::current ( gen );
+ switch ( bip ) {
+ case PROPERTYADDRESS_BIP: WRITE ( "i7_prop_addr(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ")" ); break ;
+ case PROPERTYLENGTH_BIP: WRITE ( "i7_prop_len(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ")" ); break ;
+ case PROPERTYVALUE_BIP: if ( CReferences::am_I_a_ref ( gen )) {
+ WRITE ( "i7_change_prop_value(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ", " );
+ } else {
+ WRITE ( "i7_read_prop_value(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ")" );
+ }
+ break ;
+ case MESSAGE0_BIP: WRITE ( "i7_call_0(i7_read_prop_value(" ); INV_A1 ;
+ WRITE ( ", " ); INV_A2 ; WRITE ( "))" ); break ;
+ case MESSAGE1_BIP: WRITE ( "i7_call_1(i7_read_prop_value(" ); INV_A1 ;
+ WRITE ( ", " ); INV_A2 ; WRITE ( "), " ); INV_A3 ; WRITE ( ")" ); break ;
+ case MESSAGE2_BIP: WRITE ( "i7_call_2(i7_read_prop_value(" ); INV_A1 ;
+ WRITE ( ", " ); INV_A2 ; WRITE ( "), " );
+ INV_A3 ; WRITE ( ", " ); INV_A4 ; WRITE ( ")" ); break ;
+ case MESSAGE3_BIP: WRITE ( "i7_call_3(i7_read_prop_value(" ); INV_A1 ;
+ WRITE ( ", " ); INV_A2 ; WRITE ( "), " );
+ INV_A3 ; WRITE ( ", " ); INV_A4 ; WRITE ( ", " ); INV_A5 ; WRITE ( ")" ); break ;
+ case GIVE_BIP: WRITE ( "i7_give(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ", 1)" ); break ;
+ case TAKE_BIP: WRITE ( "i7_give(" ); INV_A1 ; WRITE ( ", " ); INV_A2 ; WRITE ( ", 0)" ); break ;
+ default: return NOT_APPLICABLE ;
+ }
+ return FALSE ;
+}
+
+
@@ -480,14 +513,6 @@ property values are not stored in the memory map.
-
-
-
-
-
-
-
-
@@ -499,17 +524,28 @@ property values are not stored in the memory map.
This is part of the extract file inform7_clib.h.
-
+
This is part of the extract file inform7_clib.h.
+
diff --git a/docs/final-module/5-crf.html b/docs/final-module/5-crf.html
new file mode 100644
index 000000000..3ebfcd177
--- /dev/null
+++ b/docs/final-module/5-crf.html
@@ -0,0 +1,227 @@
+
+
+
+ C References
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Compiler Webs Inbuild Modules Inform7 Modules Inter Modules Services
+
+
+
+
+How changes to storage objects are translated into C.
+
+
+
+
+
+
+This is part of the extract file inform7_clib.h.
+
+
+
+primitive !store ref val -> val
+primitive !preincrement ref -> val
+primitive !postincrement ref -> val
+primitive !predecrement ref -> val
+primitive !postdecrement ref -> val
+primitive !setbit ref val -> void
+primitive !clearbit ref val -> void
+
+
+
+
+
+
+void CReferences::A1_as_ref ( code_generation * gen , inter_tree_node * P ) {
+ C_GEN_DATA ( memdata . next_node_is_a_ref ) = TRUE ;
+ CodeGen::FC::frame ( gen , InterTree::first_child ( P ));
+ C_GEN_DATA ( memdata . next_node_is_a_ref ) = FALSE ;
+}
+
+
+
+
+
+
+int CReferences::am_I_a_ref ( code_generation * gen ) {
+ int answer = C_GEN_DATA ( memdata . next_node_is_a_ref );
+ C_GEN_DATA ( memdata . next_node_is_a_ref ) = FALSE ;
+ return answer ;
+}
+
+
+
+
+int CReferences::compile_primitive ( code_generation * gen , inter_ti bip , inter_tree_node * P ) {
+ text_stream * OUT = CodeGen::current ( gen );
+ text_stream * store_form = NULL ;
+ switch ( bip ) {
+ case STORE_BIP: store_form = I "i7_lvalue_SET" ; break ;
+ case PREINCREMENT_BIP: store_form = I "i7_lvalue_PREINC" ; break ;
+ case POSTINCREMENT_BIP: store_form = I "i7_lvalue_POSTINC" ; break ;
+ case PREDECREMENT_BIP: store_form = I "i7_lvalue_PREDEC" ; break ;
+ case POSTDECREMENT_BIP: store_form = I "i7_lvalue_POSTDEC" ; break ;
+ case SETBIT_BIP: store_form = I "i7_lvalue_SETBIT" ; break ;
+ case CLEARBIT_BIP: store_form = I "i7_lvalue_CLEARBIT" ; break ;
+ default: return NOT_APPLICABLE ;
+ }
+ if ( store_form ) This does indeed modify a value by reference 4.1 ;
+ return FALSE ;
+}
+
+
+
+
+
+
+
+
+
+ inter_tree_node * ref = InterTree::first_child ( P );
+ if (( CodeGen::CL::node_is_word_array_ref ( gen -> from , ref )) ||
+ ( CodeGen::CL::node_is_property_ref ( gen -> from , ref ))) {
+ Handle the ref using the incomplete-function mode 4.1.1 ;
+ } else {
+ Handle the ref with C code working either as lvalue or rvalue 4.1.2 ;
+ }
+
+
+
+
+
+ WRITE ( "(" ); CReferences::A1_as_ref ( gen , P );
+ if ( bip == STORE_BIP ) { INV_A2 ; } else { WRITE ( "0" ); }
+ WRITE ( ", %S))" , store_form );
+
+This code is used in §4.1 .
+
+
+
+ switch ( bip ) {
+ case PREINCREMENT_BIP: WRITE ( "++(" ); INV_A1 ; WRITE ( ")" ); break ;
+ case POSTINCREMENT_BIP: WRITE ( "(" ); INV_A1 ; WRITE ( ")++" ); break ;
+ case PREDECREMENT_BIP: WRITE ( "--(" ); INV_A1 ; WRITE ( ")" ); break ;
+ case POSTDECREMENT_BIP: WRITE ( "(" ); INV_A1 ; WRITE ( ")--" ); break ;
+ case STORE_BIP: WRITE ( "(" ); INV_A1 ; WRITE ( " = " ); INV_A2 ; WRITE ( ")" ); break ;
+ case SETBIT_BIP: INV_A1 ; WRITE ( " = " ); INV_A1 ; WRITE ( " | " ); INV_A2 ; break ;
+ case CLEARBIT_BIP: INV_A1 ; WRITE ( " = " ); INV_A1 ; WRITE ( " &~ (" ); INV_A2 ; WRITE ( ")" ); break ;
+ }
+
+This code is used in §4.1 .
+
+
+
+
+
+
+
diff --git a/docs/final-module/5-fnc.html b/docs/final-module/5-fnc.html
index 0085d5bc3..48687e7a3 100644
--- a/docs/final-module/5-fnc.html
+++ b/docs/final-module/5-fnc.html
@@ -21,6 +21,7 @@ function togglePopup(material_id) {
+
@@ -73,19 +74,19 @@ function togglePopup(material_id) {
To generate I6 code from intermediate code.
-
+
-
+
code_generation_target * c_target = NULL ;
void CTarget::create_target ( void ) {
c_target = CodeGen::Targets::new ( I "c" );
- METHOD_ADD ( c_target , BEGIN_GENERATION_MTID , CTarget::begin_generation );
- METHOD_ADD ( c_target , END_GENERATION_MTID , CTarget::end_generation );
+ METHOD_ADD ( c_target , BEGIN_GENERATION_MTID , CTarget::begin_generation );
+ METHOD_ADD ( c_target , END_GENERATION_MTID , CTarget::end_generation );
+ CMemoryModel::initialise ( c_target );
CObjectModel::initialise ( c_target );
METHOD_ADD ( c_target , GENERAL_SEGMENT_MTID , CTarget::general_segment );
@@ -114,110 +115,129 @@ function togglePopup(material_id) {
METHOD_ADD ( c_target , BEGIN_OPCODE_MTID , CTarget::begin_opcode );
METHOD_ADD ( c_target , SUPPLY_OPERAND_MTID , CTarget::supply_operand );
METHOD_ADD ( c_target , END_OPCODE_MTID , CTarget::end_opcode );
- METHOD_ADD ( c_target , BEGIN_ARRAY_MTID , CTarget::begin_array );
- METHOD_ADD ( c_target , ARRAY_ENTRY_MTID , CTarget::array_entry );
- METHOD_ADD ( c_target , END_ARRAY_MTID , CTarget::end_array );
METHOD_ADD ( c_target , OFFER_PRAGMA_MTID , CTarget::offer_pragma )
METHOD_ADD ( c_target , NEW_FAKE_ACTION_MTID , CTarget::new_fake_action );
}
-
+
-enum c_fundamental_types_I7CGS
-enum c_ids_and_maxima_I7CGS
-enum c_header_matter_I7CGS
-enum c_predeclarations_I7CGS
-enum c_very_early_matter_I7CGS
-enum c_constants_1_I7CGS
-enum c_constants_2_I7CGS
-enum c_constants_3_I7CGS
-enum c_constants_4_I7CGS
-enum c_constants_5_I7CGS
-enum c_constants_6_I7CGS
-enum c_constants_7_I7CGS
-enum c_constants_8_I7CGS
-enum c_constants_9_I7CGS
-enum c_constants_10_I7CGS
-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_globals_array_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_stubs_at_eof_I7CGS
-enum c_property_offset_creator_I7CGS
-enum c_mem_I7CGS
-enum c_initialiser_I7CGS
-
-
-int C_target_segments [] = {
- c_fundamental_types_I7CGS ,
- c_ids_and_maxima_I7CGS ,
- c_header_matter_I7CGS ,
- c_predeclarations_I7CGS ,
- c_very_early_matter_I7CGS ,
- c_constants_1_I7CGS ,
- c_constants_2_I7CGS ,
- c_constants_3_I7CGS ,
- c_constants_4_I7CGS ,
- c_constants_5_I7CGS ,
- c_constants_6_I7CGS ,
- c_constants_7_I7CGS ,
- c_constants_8_I7CGS ,
- c_constants_9_I7CGS ,
- c_constants_10_I7CGS ,
- c_early_matter_I7CGS ,
- c_text_literals_code_I7CGS ,
- c_summations_at_eof_I7CGS ,
- c_arrays_at_eof_I7CGS ,
- c_globals_array_I7CGS ,
- c_main_matter_I7CGS ,
- c_functions_at_eof_I7CGS ,
- c_code_at_eof_I7CGS ,
- c_verbs_at_eof_I7CGS ,
- c_stubs_at_eof_I7CGS ,
- c_property_offset_creator_I7CGS ,
- c_mem_I7CGS ,
- c_initialiser_I7CGS ,
- -1
-};
-
-
+
-define C_GEN_DATA ( x ) (( C_generation_data *) ( gen -> target_specific_data ))-> x
+
+This is part of the extract file inform7_clib.h.
+
+
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+enum
+
+
+This is part of the extract file inform7_clib.h.
+
+
+define
typedef struct C_generation_data {
text_stream * double_quoted_C ;
int no_double_quoted_C_strings ;
- int extent_of_i7mem ;
int C_dword_count ;
int C_action_count ;
struct dictionary * C_vm_dictionary ;
+ struct C_generation_memory_model_data memdata ;
struct C_generation_object_model_data objdata ;
CLASS_DEFINITION
} C_generation_data ;
-void CTarget::initialise_data ( code_generation * gen ) {
+void CTarget::initialise_data ( code_generation * gen ) {
+ CMemoryModel::initialise_data ( gen );
CObjectModel::initialise_data ( gen );
C_GEN_DATA ( double_quoted_C ) = Str::new ();
C_GEN_DATA ( no_double_quoted_C_strings ) = 0 ;
- C_GEN_DATA ( extent_of_i7mem ) = 0 ;
C_GEN_DATA ( C_dword_count ) = 0 ;
C_GEN_DATA ( C_action_count ) = 0 ;
C_GEN_DATA ( C_vm_dictionary ) = Dictionaries::new (1024, TRUE );
}
The structure C_generation_data is private to this section.
-
+
int CTarget::begin_generation ( code_generation_target * cgt , code_generation * gen ) {
CodeGen::create_segments ( gen , CREATE ( C_generation_data ), C_target_segments );
- CTarget::initialise_data ( gen );
+ CTarget::initialise_data ( gen );
CTarget::fix_locals ( gen );
@@ -232,7 +252,7 @@ function togglePopup(material_id) {
WRITE ( "#include \"inform7_clib.h\"\n" );
CodeGen::deselect ( gen , saved );
- CTarget::begin_memory ( gen );
+ CMemoryModel::begin ( gen );
CTarget::begin_functions ( gen );
CObjectModel::begin ( gen );
CTarget::begin_dictionary_words ( gen );
@@ -241,7 +261,7 @@ function togglePopup(material_id) {
}
int CTarget::end_generation ( code_generation_target * cgt , code_generation * gen ) {
- CTarget::end_memory ( gen );
+ CMemoryModel::end ( gen );
CTarget::end_functions ( gen );
CObjectModel::end ( gen );
CTarget::end_dictionary_words ( gen );
@@ -250,7 +270,7 @@ function togglePopup(material_id) {
}
+
diff --git a/docs/final-module/index.html b/docs/final-module/index.html
index bfeca4efc..2a938d50b 100644
--- a/docs/final-module/index.html
+++ b/docs/final-module/index.html
@@ -151,6 +151,16 @@
Generating C -
To generate I6 code from intermediate code.
+
+
+ C References -
+ How changes to storage objects are translated into C.
+
+
+
+ C Memory Model -
+ How arrays of all kinds are stored in C.
+
C Implementation -
diff --git a/inform7/Figures/memory-diagnostics.txt b/inform7/Figures/memory-diagnostics.txt
index aceb6fc5a..653fd223f 100644
--- a/inform7/Figures/memory-diagnostics.txt
+++ b/inform7/Figures/memory-diagnostics.txt
@@ -1,9 +1,9 @@
-Total memory consumption was 399081K = 390 MB
+Total memory consumption was 399082K = 390 MB
-60.3% was used for 1995521 objects, in 371145 frames in 301 x 800K = 240800K = 235 MB:
+60.3% was used for 1995621 objects, in 371146 frames in 301 x 800K = 240800K = 235 MB:
10.2% inter_tree_node_array 58 x 8192 = 475136 objects, 41813824 bytes
- 7.0% text_stream_array 5128 x 100 = 512800 objects, 28880896 bytes
+ 7.0% text_stream_array 5129 x 100 = 512900 objects, 28886528 bytes
4.2% linked_list 30848 objects, 17274880 bytes
3.9% inter_symbol_array 139 x 1024 = 142336 objects, 15946080 bytes
2.5% parse_node 129399 objects, 10351920 bytes
@@ -238,7 +238,7 @@ Total memory consumption was 399081K = 390 MB
39.6% was used for memory not allocated for objects:
- 21.1% text stream storage 86232716 bytes in 530547 claims
+ 21.1% text stream storage 86234244 bytes in 530559 claims
4.4% dictionary storage 18153984 bytes in 33230 claims
---- sorting 744 bytes in 3 claims
1.7% source text 7200000 bytes in 3 claims
@@ -256,5 +256,5 @@ Total memory consumption was 399081K = 390 MB
---- code generation workspace for objects 9648 bytes in 9 claims
---- emitter array storage 161920 bytes in 2064 claims
-18.7% was overhead - 76757816 bytes = 74958K = 73 MB
+18.7% was overhead - 76752184 bytes = 74953K = 73 MB
diff --git a/inform7/Figures/timings-diagnostics.txt b/inform7/Figures/timings-diagnostics.txt
index 656b70a6e..e7e78b5de 100644
--- a/inform7/Figures/timings-diagnostics.txt
+++ b/inform7/Figures/timings-diagnostics.txt
@@ -1,6 +1,6 @@
100.0% in inform7 run
- 55.1% in compilation to Inter
- 40.1% in //Sequence::undertake_queued_tasks//
+ 55.3% in compilation to Inter
+ 40.2% in //Sequence::undertake_queued_tasks//
3.5% in //MajorNodes::pre_pass//
2.5% in //MajorNodes::pass_1//
1.5% in //RTPhrasebook::compile_entries//
@@ -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.8% in running Inter pipeline
- 10.7% in step preparation
- 9.7% in inter step 7/14: consolidate-text
- 8.3% in inter step 14/14: generate inform6 -> auto.inf
+ 1.9% not specifically accounted for
+ 42.6% in running Inter pipeline
+ 10.9% in step preparation
+ 9.8% in inter step 7/14: consolidate-text
+ 8.2% in inter step 14/14: generate inform6 -> auto.inf
7.9% in inter step 2/14: link
1.5% in inter step 10/14: make-identifiers-unique
0.4% in inter step 11/14: reconcile-verbs
@@ -31,6 +31,6 @@
0.1% in inter step 12/14: eliminate-redundant-labels
0.1% in inter step 4/14: parse-linked-matter
0.1% in inter step 5/14: resolve-conditional-compilation
- 2.4% not specifically accounted for
+ 2.1% not specifically accounted for
1.7% in supervisor
0.3% not specifically accounted for
diff --git a/inform7/Internal/Miscellany/inform7_clib.h b/inform7/Internal/Miscellany/inform7_clib.h
index 24527dfa6..4beb88f04 100644
--- a/inform7/Internal/Miscellany/inform7_clib.h
+++ b/inform7/Internal/Miscellany/inform7_clib.h
@@ -1,9 +1,57 @@
+/* This is a library of C code to support Inform or other Inter programs compiled
+ tp ANSI C. It was generated mechanically from the Inter source code, so to
+ change it, edit that and not this. */
+
#include
#include
-typedef struct i7varargs {
- i7val args[10];
-} i7varargs;
+#define i7_lvalue_SET 1
+#define i7_lvalue_PREDEC 2
+#define i7_lvalue_POSTDEC 3
+#define i7_lvalue_PREINC 4
+#define i7_lvalue_POSTINC 5
+#define i7_lvalue_SETBIT 6
+#define i7_lvalue_CLEARBIT 7
+i7byte i7mem[];
+i7val i7_read_word(i7byte data[], i7val array_address, i7val array_index) {
+ int byte_position = array_address + 4*array_index;
+ return (i7val) data[byte_position] +
+ 0x100*((i7val) data[byte_position + 1]) +
+ 0x10000*((i7val) data[byte_position + 2]) +
+ 0x1000000*((i7val) data[byte_position + 3]);
+}
+#define i7_lvalue_SET 1
+#define i7_lvalue_PREDEC 2
+#define i7_lvalue_POSTDEC 3
+#define i7_lvalue_PREINC 4
+#define i7_lvalue_POSTINC 5
+#define i7_lvalue_SETBIT 6
+#define i7_lvalue_CLEARBIT 7
+#define I7BYTE_3(V) ((V & 0xFF000000) >> 24)
+#define I7BYTE_2(V) ((V & 0x00FF0000) >> 16)
+#define I7BYTE_1(V) ((V & 0x0000FF00) >> 8)
+#define I7BYTE_0(V) (V & 0x000000FF)
+
+i7val i7_write_word(i7byte data[], i7val array_address, i7val array_index, i7val new_val, int way) {
+ i7val old_val = i7_read_word(data, array_address, array_index);
+ i7val return_val = new_val;
+ switch (way) {
+ case i7_lvalue_PREDEC: return_val = old_val; new_val = old_val-1; break;
+ case i7_lvalue_POSTDEC: return_val = old_val-1; new_val = old_val-1; break;
+ case i7_lvalue_PREINC: return_val = old_val; new_val = old_val+1; break;
+ case i7_lvalue_POSTINC: return_val = old_val+1; 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;
+ 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;
+}
+#include
+#include
i7val i7_mgl_self = 0;
i7val i7_mgl_sp = 0;
@@ -13,39 +61,6 @@ i7val i7_mgl_debug_flag = 0;
i7val i7_tmp = 0;
int i7_seed = 197;
-#define i7_cpv_SET 1
-#define i7_cpv_PREDEC 2
-#define i7_cpv_POSTDEC 3
-#define i7_cpv_PREINC 4
-#define i7_cpv_POSTINC 5
-
-#define I7BYTE_3(V) ((V & 0xFF000000) >> 24)
-#define I7BYTE_2(V) ((V & 0x00FF0000) >> 16)
-#define I7BYTE_1(V) ((V & 0x0000FF00) >> 8)
-#define I7BYTE_0(V) (V & 0x000000FF)
-
-i7val i7_lookup(i7byte i7bytes[], i7val offset, i7val ind) {
- ind = offset + 4*ind;
- return ((i7val) i7bytes[ind]) + 0x100*((i7val) i7bytes[ind+1]) +
- 0x10000*((i7val) i7bytes[ind+2]) + 0x1000000*((i7val) i7bytes[ind+3]);
-}
-
-i7val write_i7_lookup(i7byte i7bytes[], i7val offset, i7val ind, i7val V, int way) {
- i7val val = i7_lookup(i7bytes, offset, ind);
- i7val RV = V;
- switch (way) {
- case i7_cpv_PREDEC: RV = val; V = val-1; break;
- case i7_cpv_POSTDEC: RV = val-1; V = val-1; break;
- case i7_cpv_PREINC: RV = val; V = val+1; break;
- case i7_cpv_POSTINC: RV = val+1; V = val+1; break;
- }
- ind = offset + 4*ind;
- i7bytes[ind] = I7BYTE_0(V);
- i7bytes[ind+1] = I7BYTE_1(V);
- i7bytes[ind+2] = I7BYTE_2(V);
- i7bytes[ind+3] = I7BYTE_3(V);
- return RV;
-}
void glulx_accelfunc(i7val x, i7val y) {
printf("Unimplemented: glulx_accelfunc.\n");
@@ -487,6 +502,11 @@ i7val i7_mgl_sharp_dictionary_table = 0;
i7val i7_mgl_sharp_grammar_table = 0;
#define i7_mgl_FLOAT_NAN 0
+
+typedef struct i7varargs {
+ i7val args[10];
+} i7varargs;
+
i7val fn_i7_mgl_metaclass(int n, i7val id) {
if (id <= 0) return 0;
if (id >= I7VAL_FUNCTIONS_BASE) return i7_mgl_Routine;
@@ -520,14 +540,6 @@ typedef struct i7_property_set {
} i7_property_set;
i7_property_set i7_properties[i7_max_objects];
-i7val i7_read_prop_value(i7val owner_id, i7val prop_id) {
- if ((owner_id <= 0) || (owner_id >= i7_max_objects) ||
- (prop_id < 0) || (prop_id >= i7_no_property_ids)) return 0;
- while (i7_properties[(int) owner_id].value_set[(int) prop_id] == 0)
- owner_id = i7_class_of[owner_id];
- return i7_properties[(int) owner_id].value[(int) prop_id];
-}
-
void i7_write_prop_value(i7val owner_id, i7val prop_id, i7val val) {
if ((owner_id <= 0) || (owner_id >= i7_max_objects) ||
(prop_id < 0) || (prop_id >= i7_no_property_ids)) {
@@ -537,14 +549,24 @@ void i7_write_prop_value(i7val owner_id, i7val prop_id, i7val val) {
i7_properties[(int) owner_id].value[(int) prop_id] = val;
i7_properties[(int) owner_id].value_set[(int) prop_id] = 1;
}
+i7val i7_read_prop_value(i7val owner_id, i7val prop_id) {
+ if ((owner_id <= 0) || (owner_id >= i7_max_objects) ||
+ (prop_id < 0) || (prop_id >= i7_no_property_ids)) return 0;
+ while (i7_properties[(int) owner_id].value_set[(int) prop_id] == 0)
+ owner_id = i7_class_of[owner_id];
+ return i7_properties[(int) owner_id].value[(int) prop_id];
+}
+
i7val i7_change_prop_value(i7val obj, i7val pr, i7val to, int way) {
i7val val = i7_read_prop_value(obj, pr), new_val = val;
switch (way) {
- case i7_cpv_SET: i7_write_prop_value(obj, pr, to); new_val = to; break;
- case i7_cpv_PREDEC: new_val = val; i7_write_prop_value(obj, pr, val-1); break;
- case i7_cpv_POSTDEC: new_val = val-1; i7_write_prop_value(obj, pr, new_val); break;
- case i7_cpv_PREINC: new_val = val; i7_write_prop_value(obj, pr, val+1); break;
- case i7_cpv_POSTINC: new_val = val+1; i7_write_prop_value(obj, pr, new_val); break;
+ case i7_lvalue_SET: i7_write_prop_value(obj, pr, to); new_val = to; break;
+ case i7_lvalue_PREDEC: new_val = val; i7_write_prop_value(obj, pr, val-1); break;
+ case i7_lvalue_POSTDEC: new_val = val-1; i7_write_prop_value(obj, pr, new_val); break;
+ case i7_lvalue_PREINC: new_val = val; i7_write_prop_value(obj, pr, val+1); break;
+ case i7_lvalue_POSTINC: new_val = val+1; i7_write_prop_value(obj, pr, new_val); break;
+ case i7_lvalue_SETBIT: new_val = val | new_val; i7_write_prop_value(obj, pr, new_val); break;
+ case i7_lvalue_CLEARBIT: new_val = val &(~new_val); i7_write_prop_value(obj, pr, new_val); break;
}
return new_val;
}
diff --git a/inter/final-module/Chapter 2/Constants and Literals.w b/inter/final-module/Chapter 2/Constants and Literals.w
index 068ae7e1a..ad57d3793 100644
--- a/inter/final-module/Chapter 2/Constants and Literals.w
+++ b/inter/final-module/Chapter 2/Constants and Literals.w
@@ -385,3 +385,37 @@ text_stream *CodeGen::CL::name(inter_symbol *symb) {
if (Inter::Symbols::get_translate(symb)) return Inter::Symbols::get_translate(symb);
return symb->symbol_name;
}
+
+@ =
+int CodeGen::CL::node_is_word_array_ref(inter_tree *I, inter_tree_node *P) {
+ int reffed = FALSE;
+ while (P->W.data[ID_IFLD] == REFERENCE_IST) {
+ P = InterTree::first_child(P);
+ reffed = TRUE;
+ }
+ if (P->W.data[ID_IFLD] == INV_IST) {
+ if (P->W.data[METHOD_INV_IFLD] == INVOKED_PRIMITIVE) {
+ inter_symbol *prim = Inter::Inv::invokee(P);
+ inter_ti bip = Primitives::to_bip(I, prim);
+ if (bip == LOOKUPREF_BIP) return TRUE;
+ if ((bip == LOOKUP_BIP) && (reffed)) return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+int CodeGen::CL::node_is_property_ref(inter_tree *I, inter_tree_node *P) {
+ int reffed = FALSE;
+ while (P->W.data[ID_IFLD] == REFERENCE_IST) {
+ P = InterTree::first_child(P);
+ reffed = TRUE;
+ }
+ if (P->W.data[ID_IFLD] == INV_IST) {
+ if (P->W.data[METHOD_INV_IFLD] == INVOKED_PRIMITIVE) {
+ inter_symbol *prim = Inter::Inv::invokee(P);
+ inter_ti bip = Primitives::to_bip(I, prim);
+ if (bip == PROPERTYVALUE_BIP) return TRUE;
+ }
+ }
+ return FALSE;
+}
diff --git a/inter/final-module/Chapter 5/C Implementation.w b/inter/final-module/Chapter 5/C Implementation.w
index 690ddaef7..0c7b1de2d 100644
--- a/inter/final-module/Chapter 5/C Implementation.w
+++ b/inter/final-module/Chapter 5/C Implementation.w
@@ -8,10 +8,6 @@ To generate I6 code from intermediate code.
#include
#include
-typedef struct i7varargs {
- i7val args[10];
-} i7varargs;
-
i7val i7_mgl_self = 0;
i7val i7_mgl_sp = 0;
#define i7_mgl_Grammar__Version 2
@@ -20,39 +16,6 @@ i7val i7_mgl_debug_flag = 0;
i7val i7_tmp = 0;
int i7_seed = 197;
-#define i7_cpv_SET 1
-#define i7_cpv_PREDEC 2
-#define i7_cpv_POSTDEC 3
-#define i7_cpv_PREINC 4
-#define i7_cpv_POSTINC 5
-
-#define I7BYTE_3(V) ((V & 0xFF000000) >> 24)
-#define I7BYTE_2(V) ((V & 0x00FF0000) >> 16)
-#define I7BYTE_1(V) ((V & 0x0000FF00) >> 8)
-#define I7BYTE_0(V) (V & 0x000000FF)
-
-i7val i7_lookup(i7byte i7bytes[], i7val offset, i7val ind) {
- ind = offset + 4*ind;
- return ((i7val) i7bytes[ind]) + 0x100*((i7val) i7bytes[ind+1]) +
- 0x10000*((i7val) i7bytes[ind+2]) + 0x1000000*((i7val) i7bytes[ind+3]);
-}
-
-i7val write_i7_lookup(i7byte i7bytes[], i7val offset, i7val ind, i7val V, int way) {
- i7val val = i7_lookup(i7bytes, offset, ind);
- i7val RV = V;
- switch (way) {
- case i7_cpv_PREDEC: RV = val; V = val-1; break;
- case i7_cpv_POSTDEC: RV = val-1; V = val-1; break;
- case i7_cpv_PREINC: RV = val; V = val+1; break;
- case i7_cpv_POSTINC: RV = val+1; V = val+1; break;
- }
- ind = offset + 4*ind;
- i7bytes[ind] = I7BYTE_0(V);
- i7bytes[ind+1] = I7BYTE_1(V);
- i7bytes[ind+2] = I7BYTE_2(V);
- i7bytes[ind+3] = I7BYTE_3(V);
- return RV;
-}
void glulx_accelfunc(i7val x, i7val y) {
printf("Unimplemented: glulx_accelfunc.\n");
@@ -494,36 +457,16 @@ i7val i7_mgl_sharp_dictionary_table = 0;
i7val i7_mgl_sharp_grammar_table = 0;
#define i7_mgl_FLOAT_NAN 0
+
+typedef struct i7varargs {
+ i7val args[10];
+} i7varargs;
+
=
@
=
-
-void CTarget::begin_memory(code_generation *gen) {
- generated_segment *saved = CodeGen::select(gen, c_header_matter_I7CGS);
- text_stream *OUT = CodeGen::current(gen);
- WRITE("i7byte i7mem[];\n");
- CodeGen::deselect(gen, saved);
-
- saved = CodeGen::select(gen, c_mem_I7CGS);
- OUT = CodeGen::current(gen);
- WRITE("i7byte i7mem[] = {\n");
- CodeGen::deselect(gen, saved);
-}
-
-void CTarget::end_memory(code_generation *gen) {
- generated_segment *saved = CodeGen::select(gen, c_mem_I7CGS);
- text_stream *OUT = CodeGen::current(gen);
- WRITE("0, 0 };\n");
- CodeGen::deselect(gen, saved);
-
- saved = CodeGen::select(gen, c_predeclarations_I7CGS);
- OUT = CodeGen::current(gen);
- WRITE("char *dqs[] = {\n%S\"\" };\n", C_GEN_DATA(double_quoted_C));
- CodeGen::deselect(gen, saved);
-}
-
void CTarget::begin_dictionary_words(code_generation *gen) {
}
@@ -535,6 +478,11 @@ void CTarget::end_dictionary_words(code_generation *gen) {
WRITE("#define i7_p_dword_%d %d\n", i, 2*i + 1);
}
CodeGen::deselect(gen, saved);
+
+ saved = CodeGen::select(gen, c_predeclarations_I7CGS);
+ OUT = CodeGen::current(gen);
+ WRITE("char *dqs[] = {\n%S\"\" };\n", C_GEN_DATA(double_quoted_C));
+ CodeGen::deselect(gen, saved);
}
void CTarget::end_functions(code_generation *gen) {
@@ -622,14 +570,20 @@ void CTarget::mangle(code_generation_target *cgt, OUTPUT_STREAM, text_stream *id
} else WRITE("i7_mgl_%S", identifier);
}
-int C_write_lookup_mode = FALSE;
-
int CTarget::compile_primitive(code_generation_target *cgt, code_generation *gen,
inter_symbol *prim_name, inter_tree_node *P) {
text_stream *OUT = CodeGen::current(gen);
int suppress_terminal_semicolon = FALSE;
inter_tree *I = gen->from;
inter_ti bip = Primitives::to_bip(I, prim_name);
+
+ int r = CReferences::compile_primitive(gen, bip, P);
+ if (r != NOT_APPLICABLE) return r;
+ r = CMemoryModel::compile_primitive(gen, bip, P);
+ if (r != NOT_APPLICABLE) return r;
+ r = CObjectModel::compile_primitive(gen, bip, P);
+ if (r != NOT_APPLICABLE) return r;
+
switch (bip) {
case INVERSION_BIP: break; /* we won't support this in C */
@@ -662,31 +616,6 @@ int CTarget::compile_primitive(code_generation_target *cgt, code_generation *gen
case PUSH_BIP: WRITE("i7_push("); INV_A1; WRITE(")"); break;
case PULL_BIP: INV_A1; WRITE(" = i7_pull()"); break;
- case PREINCREMENT_BIP: @; break;
- case POSTINCREMENT_BIP: @; break;
- case PREDECREMENT_BIP: @; break;
- case POSTDECREMENT_BIP: @; break;
- case STORE_BIP: @; break;
- case SETBIT_BIP: INV_A1; WRITE(" = "); INV_A1; WRITE(" | "); INV_A2; break;
- case CLEARBIT_BIP: INV_A1; WRITE(" = "); INV_A1; WRITE(" &~ ("); INV_A2; WRITE(")"); break;
- case LOOKUP_BIP: if (C_write_lookup_mode) {
- C_write_lookup_mode = FALSE;
- @;
- } else {
- @;
- }
- break;
- case LOOKUPBYTE_BIP: @; break;
- case LOOKUPREF_BIP: @; break;
- case PROPERTYADDRESS_BIP: WRITE("i7_prop_addr("); INV_A1; WRITE(", "); INV_A2; WRITE(")"); break;
- case PROPERTYLENGTH_BIP: WRITE("i7_prop_len("); INV_A1; WRITE(", "); INV_A2; WRITE(")"); break;
- case PROPERTYVALUE_BIP: if (C_write_lookup_mode) {
- C_write_lookup_mode = FALSE;
- WRITE("i7_change_prop_value("); INV_A1; WRITE(", "); INV_A2; WRITE(", ");
- } else {
- WRITE("i7_read_prop_value("); INV_A1; WRITE(", "); INV_A2; WRITE(")");
- }
- break;
case BREAK_BIP: WRITE("break"); break;
case CONTINUE_BIP: WRITE("continue"); break;
case RETURN_BIP: @; break;
@@ -713,13 +642,6 @@ int CTarget::compile_primitive(code_generation_target *cgt, code_generation *gen
WRITE("i7_call_5("); INV_A1; WRITE(", ");
INV_A2; WRITE(", "); INV_A3; WRITE(", "); INV_A4; WRITE(", ");
INV_A5; WRITE(", "); INV_A6; WRITE(")"); break;
- case MESSAGE0_BIP: WRITE("i7_call_0(i7_read_prop_value("); INV_A1; WRITE(", "); INV_A2; WRITE("))"); break;
- case MESSAGE1_BIP: WRITE("i7_call_1(i7_read_prop_value("); INV_A1; WRITE(", "); INV_A2; WRITE("), ");
- INV_A3; WRITE(")"); break;
- case MESSAGE2_BIP: WRITE("i7_call_2(i7_read_prop_value("); INV_A1; WRITE(", "); INV_A2; WRITE("), ");
- INV_A3; WRITE(", "); INV_A4; WRITE(")"); break;
- case MESSAGE3_BIP: WRITE("i7_call_3(i7_read_prop_value("); INV_A1; WRITE(", "); INV_A2; WRITE("), ");
- INV_A3; WRITE(", "); INV_A4; WRITE(", "); INV_A5; WRITE(")"); break;
case CALLMESSAGE0_BIP: WRITE("i7_ccall_0("); INV_A1; WRITE(")"); break;
case CALLMESSAGE1_BIP: WRITE("i7_ccall_1("); INV_A1; WRITE(", ");
INV_A2; WRITE(")"); break;
@@ -740,8 +662,6 @@ int CTarget::compile_primitive(code_generation_target *cgt, code_generation *gen
case MOVE_BIP: WRITE("i7_move("); INV_A1; WRITE(", "); INV_A2; WRITE(")"); break;
case REMOVE_BIP: WRITE("i7_move("); INV_A1; WRITE(", 0)"); break;
- case GIVE_BIP: WRITE("i7_give("); INV_A1; WRITE(", "); INV_A2; WRITE(", 1)"); break;
- case TAKE_BIP: WRITE("i7_give("); INV_A1; WRITE(", "); INV_A2; WRITE(", 0)"); break;
case ALTERNATIVECASE_BIP: INV_A1; WRITE(", "); INV_A2; break;
case SEQUENTIAL_BIP: WRITE("("); INV_A1; WRITE(","); INV_A2; WRITE(")"); break;
@@ -789,43 +709,6 @@ int CTarget::compile_primitive(code_generation_target *cgt, code_generation *gen
@ =
CTarget::comparison(cgt, gen, bip, InterTree::first_child(P), InterTree::second_child(P));
-@ =
- text_stream *store_form = NULL;
- switch (bip) {
- case PREINCREMENT_BIP: store_form = I"i7_cpv_PREINC"; break;
- case POSTINCREMENT_BIP: store_form = I"i7_cpv_POSTINC"; break;
- case PREDECREMENT_BIP: store_form = I"i7_cpv_PREDEC"; break;
- case POSTDECREMENT_BIP: store_form = I"i7_cpv_POSTDEC"; break;
- case STORE_BIP: store_form = I"i7_cpv_SET"; break;
- }
- inter_tree_node *ref = InterTree::first_child(P);
- if (CTarget::basically_an_array_write(gen->from, ref)) {
- WRITE("("); C_write_lookup_mode = TRUE; INV_A1; C_write_lookup_mode = FALSE;
- if (bip == STORE_BIP) { INV_A2; } else { WRITE("0"); }
- WRITE(", %S))", store_form);
- } else if (CTarget::basically_a_property_write(gen->from, ref)) {
- WRITE("("); C_write_lookup_mode = TRUE; INV_A1; C_write_lookup_mode = FALSE;
- if (bip == STORE_BIP) { INV_A2; } else { WRITE("0"); }
- WRITE(", %S))", store_form);
- } else {
- switch (bip) {
- case PREINCREMENT_BIP: WRITE("++("); INV_A1; WRITE(")"); break;
- case POSTINCREMENT_BIP: WRITE("("); INV_A1; WRITE(")++"); break;
- case PREDECREMENT_BIP: WRITE("--("); INV_A1; WRITE(")"); break;
- case POSTDECREMENT_BIP: WRITE("("); INV_A1; WRITE(")--"); break;
- case STORE_BIP: WRITE("("); INV_A1; WRITE(" = "); INV_A2; WRITE(")"); break;
- }
- }
-
-@ =
- WRITE("i7_lookup(i7mem, "); INV_A1; WRITE(", "); INV_A2; WRITE(")");
-
-@ =
- WRITE("write_i7_lookup(i7mem, "); INV_A1; WRITE(", "); INV_A2; WRITE(", ");
-
-@ =
- WRITE("i7mem["); INV_A1; WRITE(" + "); INV_A2; WRITE("]");
-
@ =
int rboolean = NOT_APPLICABLE;
inter_tree_node *V = InterTree::first_child(P);
@@ -1103,20 +986,20 @@ int CTarget::declare_variable(code_generation_target *cgt, code_generation *gen,
CodeGen::deselect(gen, saved);
}
if (Inter::Symbols::read_annotation(var_name, EXPLICIT_VARIABLE_IANN) != 1) {
- if (k == 0) CTarget::begin_array(cgt, gen, I"Global_Vars", WORD_ARRAY_FORMAT);
+ if (k == 0) CMemoryModel::begin_array(cgt, gen, I"Global_Vars", WORD_ARRAY_FORMAT);
TEMPORARY_TEXT(val)
CodeGen::select_temporary(gen, val);
CodeGen::CL::literal(gen, NULL, Inter::Packages::scope_of(P), P->W.data[VAL1_VAR_IFLD], P->W.data[VAL2_VAR_IFLD], FALSE);
CodeGen::deselect_temporary(gen);
- CTarget::array_entry(cgt, gen, val, WORD_ARRAY_FORMAT);
+ CMemoryModel::array_entry(cgt, gen, val, WORD_ARRAY_FORMAT);
DISCARD_TEXT(val)
k++;
if (k == of) {
if (k < 2) {
- CTarget::array_entry(cgt, gen, I"0", WORD_ARRAY_FORMAT);
- CTarget::array_entry(cgt, gen, I"0", WORD_ARRAY_FORMAT);
+ CMemoryModel::array_entry(cgt, gen, I"0", WORD_ARRAY_FORMAT);
+ CMemoryModel::array_entry(cgt, gen, I"0", WORD_ARRAY_FORMAT);
}
- CTarget::end_array(cgt, gen, WORD_ARRAY_FORMAT);
+ CMemoryModel::end_array(cgt, gen, WORD_ARRAY_FORMAT);
}
}
return k;
@@ -1406,85 +1289,6 @@ void CTarget::declare_local_variable(code_generation_target *cgt, int pass,
DISCARD_TEXT(name)
}
-int C_array_entry_count = 0;
-text_stream *C_array_name = NULL;
-
-void CTarget::begin_array(code_generation_target *cgt, code_generation *gen, text_stream *array_name, int format) {
- generated_segment *saved = CodeGen::select(gen, c_predeclarations_I7CGS);
- text_stream *OUT = CodeGen::current(gen);
- WRITE("#define ");
- CTarget::mangle(cgt, OUT, array_name);
- WRITE(" %d // An array in format %d\n", C_GEN_DATA(extent_of_i7mem), format);
- CodeGen::deselect(gen, saved);
-
- if (C_array_name == NULL) C_array_name = Str::new();
- Str::clear(C_array_name); WRITE_TO(C_array_name, "%S", array_name);
- C_array_entry_count = 0;
-
- if ((format == TABLE_ARRAY_FORMAT) || (format == BUFFER_ARRAY_FORMAT)) {
- TEMPORARY_TEXT(extname)
- WRITE_TO(extname, "xt_%S", array_name);
- CTarget::array_entry(cgt, gen, extname, format);
- DISCARD_TEXT(extname)
- }
-}
-
-void CTarget::array_entry(code_generation_target *cgt, code_generation *gen, text_stream *entry, int format) {
- generated_segment *saved = CodeGen::select(gen, c_mem_I7CGS);
- text_stream *OUT = CodeGen::current(gen);
- if ((format == TABLE_ARRAY_FORMAT) || (format == WORD_ARRAY_FORMAT)) {
- WRITE(" I7BYTE_0(%S), I7BYTE_1(%S), I7BYTE_2(%S), I7BYTE_3(%S),\n",
- entry, entry, entry, entry);
- C_GEN_DATA(extent_of_i7mem) += 4;
- } else {
- WRITE(" (i7byte) %S,\n", entry);
- C_GEN_DATA(extent_of_i7mem) += 1;
- }
- CodeGen::deselect(gen, saved);
- C_array_entry_count++;
-}
-
-void CTarget::end_array(code_generation_target *cgt, code_generation *gen, int format) {
- generated_segment *saved = CodeGen::select(gen, c_predeclarations_I7CGS);
- text_stream *OUT = CodeGen::current(gen);
- if ((format == TABLE_ARRAY_FORMAT) || (format == BUFFER_ARRAY_FORMAT)) {
- WRITE("#define xt_%S %d\n", C_array_name, C_array_entry_count-1);
- }
- CodeGen::deselect(gen, saved);
-}
-
-int CTarget::basically_an_array_write(inter_tree *I, inter_tree_node *P) {
- int reffed = FALSE;
- while (P->W.data[ID_IFLD] == REFERENCE_IST) {
- P = InterTree::first_child(P);
- reffed = TRUE;
- }
- if (P->W.data[ID_IFLD] == INV_IST) {
- if (P->W.data[METHOD_INV_IFLD] == INVOKED_PRIMITIVE) {
- inter_symbol *prim = Inter::Inv::invokee(P);
- inter_ti bip = Primitives::to_bip(I, prim);
- if (bip == LOOKUPREF_BIP) return TRUE;
- if ((bip == LOOKUP_BIP) && (reffed)) return TRUE;
- }
- }
- return FALSE;
-}
-
-int CTarget::basically_a_property_write(inter_tree *I, inter_tree_node *P) {
- int reffed = FALSE;
- while (P->W.data[ID_IFLD] == REFERENCE_IST) {
- P = InterTree::first_child(P);
- reffed = TRUE;
- }
- if (P->W.data[ID_IFLD] == INV_IST) {
- if (P->W.data[METHOD_INV_IFLD] == INVOKED_PRIMITIVE) {
- inter_symbol *prim = Inter::Inv::invokee(P);
- inter_ti bip = Primitives::to_bip(I, prim);
- if (bip == PROPERTYVALUE_BIP) return TRUE;
- }
- }
- return FALSE;
-}
void CTarget::new_fake_action(code_generation_target *cgt, code_generation *gen, text_stream *name) {
generated_segment *saved = CodeGen::select(gen, c_predeclarations_I7CGS);
diff --git a/inter/final-module/Chapter 5/C Memory Model.w b/inter/final-module/Chapter 5/C Memory Model.w
new file mode 100644
index 000000000..a0363fc9e
--- /dev/null
+++ b/inter/final-module/Chapter 5/C Memory Model.w
@@ -0,0 +1,279 @@
+[CMemoryModel::] C Memory Model.
+
+How arrays of all kinds are stored in C.
+
+@h Setting up the model.
+
+=
+void CMemoryModel::initialise(code_generation_target *cgt) {
+ METHOD_ADD(cgt, BEGIN_ARRAY_MTID, CMemoryModel::begin_array);
+ METHOD_ADD(cgt, ARRAY_ENTRY_MTID, CMemoryModel::array_entry);
+ 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;
+ int next_node_is_a_ref;
+} 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;
+ C_GEN_DATA(memdata.next_node_is_a_ref) = FALSE;
+}
+
+@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
+not have alignment gaps in between them. (For C, they do not.)
+(b) "Addresses" in this memory identify individual byte positions in it. These
+can but need not start at 0. (For C, they do.) They must not be too large to
+fit into an Inter value.
+(c) When an array name is compiled, its runtime value must be its address.
+(d) When an Inter value is stored in byte-accessible memory, it occupies either
+2 or 4 consecutive bytes, with the little end first. The result is called a
+"word". (For C, always 4, which is always |sizeof(i7val)|.) Conversion between
+a word stored in memory and an Inter value must be faithful in both directions.
+(e) Words can be stored at any byte position, and not only at (say) multiples
+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. This is first predeclared here:
+
+= (text to inform7_clib.h)
+i7byte i7mem[];
+=
+
+@ Declaring that array is our main task in this section.
+
+=
+void CMemoryModel::begin(code_generation *gen) {
+ generated_segment *saved = CodeGen::select(gen, c_mem_I7CGS);
+ text_stream *OUT = CodeGen::current(gen);
+ WRITE("i7byte i7mem[] = {\n");
+ 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.
+
+=
+void CMemoryModel::end(code_generation *gen) {
+ generated_segment *saved = CodeGen::select(gen, c_mem_I7CGS);
+ text_stream *OUT = CodeGen::current(gen);
+ WRITE("0, 0 };\n");
+ CodeGen::deselect(gen, saved);
+}
+
+@h Reading and writing memory.
+Given the above array, it's easy to read and write bytes: if |a| is the address
+then we can simply refer to |i7mem[a]|. 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| in
+the bank of memory |data|. In practice, we will only every use this function
+with |data| set to |i7mem|.
+
+The equivalent for reading a byte entry is |data[array_address + array_index]|.
+
+= (text to inform7_clib.h)
+i7val i7_read_word(i7byte data[], i7val array_address, i7val array_index) {
+ int byte_position = array_address + 4*array_index;
+ return (i7val) data[byte_position] +
+ 0x100*((i7val) data[byte_position + 1]) +
+ 0x10000*((i7val) data[byte_position + 2]) +
+ 0x1000000*((i7val) data[byte_position + 3]);
+}
+=
+
+Now for writing. Memory locations (like variables and property values) can not
+only be "set", that is, written to, but also pre-decremented, post-decremented,
+pre-incremented and post-incremented. This is the equivalent of being able to
+apply |++| or |--| either side, in C terms. The following enumerated constants
+identify which of these five operations to perform:
+
+= (text to inform7_clib.h)
+#define i7_lvalue_SET 1
+#define i7_lvalue_PREDEC 2
+#define i7_lvalue_POSTDEC 3
+#define i7_lvalue_PREINC 4
+#define i7_lvalue_POSTINC 5
+#define i7_lvalue_SETBIT 6
+#define i7_lvalue_CLEARBIT 7
+=
+
+@ 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_3(V) ((V & 0xFF000000) >> 24)
+#define I7BYTE_2(V) ((V & 0x00FF0000) >> 16)
+#define I7BYTE_1(V) ((V & 0x0000FF00) >> 8)
+#define I7BYTE_0(V) (V & 0x000000FF)
+
+i7val i7_write_word(i7byte data[], i7val array_address, i7val array_index, i7val new_val, int way) {
+ i7val old_val = i7_read_word(data, array_address, array_index);
+ i7val return_val = new_val;
+ switch (way) {
+ case i7_lvalue_PREDEC: return_val = old_val; new_val = old_val-1; break;
+ case i7_lvalue_POSTDEC: return_val = old_val-1; new_val = old_val-1; break;
+ case i7_lvalue_PREINC: return_val = old_val; new_val = old_val+1; break;
+ case i7_lvalue_POSTINC: return_val = old_val+1; 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;
+ 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;
+}
+=
+
+@h Populating memory with arrays.
+Inter supports four sorts of arrays, with behaviour as laid out in this 2x2 grid:
+= (text)
+ | entries count 0, 1, 2,... | entry 0 is N, then entries count 1, 2, ..., N
+-------------+-------------------------------+-----------------------------------------------
+byte entries | BYTE_ARRAY_FORMAT | BUFFER_ARRAY_FORMAT
+-------------+-------------------------------+-----------------------------------------------
+word entries | WORD_ARRAY_FORMAT | TABLE_ARRAY_FORMAT
+-------------+-------------------------------+-----------------------------------------------
+=
+
+=
+void CMemoryModel::begin_array(code_generation_target *cgt, code_generation *gen,
+ text_stream *array_name, int format) {
+ 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;
+
+ text_stream *format_name = I"unknown";
+ @;
+ @;
+ if ((format == TABLE_ARRAY_FORMAT) || (format == BUFFER_ARRAY_FORMAT))
+ @;
+}
+
+@ =
+ 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 |i7mem|,
+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//.
+
+@ =
+ generated_segment *saved = CodeGen::select(gen, c_predeclarations_I7CGS);
+ text_stream *OUT = CodeGen::current(gen);
+ WRITE("#define ");
+ CTarget::mangle(cgt, OUT, array_name);
+ WRITE(" %d /* = position in i7mem of %S array %S */\n",
+ C_GEN_DATA(memdata.himem), format_name, array_name);
+ 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_%S", 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_generation_target *cgt, code_generation *gen,
+ text_stream *entry, int format) {
+ generated_segment *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) %S,\n", entry);
+ 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),\n",
+ entry, entry, entry, entry);
+ C_GEN_DATA(memdata.himem) += 4;
+
+@ When all the entries have been placed, the following is called. It does nothing
+except to predeclare the extent constant, if one was used.
+
+=
+void CMemoryModel::end_array(code_generation_target *cgt, code_generation *gen, int format) {
+ if ((format == TABLE_ARRAY_FORMAT) || (format == BUFFER_ARRAY_FORMAT)) {
+ generated_segment *saved = CodeGen::select(gen, c_predeclarations_I7CGS);
+ text_stream *OUT = CodeGen::current(gen);
+ WRITE("#define xt_%S %d\n",
+ C_GEN_DATA(memdata.array_name), C_GEN_DATA(memdata.entry_count)-1);
+ CodeGen::deselect(gen, saved);
+ }
+}
+
+@h Primitives for byte and word lookup.
+The signatures here are:
+
+= (text)
+primitive !lookup val val -> val
+primitive !lookupbyte val val -> val
+primitive !lookupref val val -> ref
+=
+|!lookupref| is a slightly redundant abbreviation for |reference| with |!lookup|
+as a child. At present, there is no equivalent |!lookupbyteref|.
+
+=
+int CMemoryModel::compile_primitive(code_generation *gen, inter_ti bip, inter_tree_node *P) {
+ text_stream *OUT = CodeGen::current(gen);
+ switch (bip) {
+ case LOOKUP_BIP: if (CReferences::am_I_a_ref(gen)) {
+ @;
+ } else {
+ @;
+ }
+ break;
+ case LOOKUPBYTE_BIP: @; break;
+ case LOOKUPREF_BIP: @; break;
+ default: return NOT_APPLICABLE;
+ }
+ return FALSE;
+}
+
+@ =
+ WRITE("i7_read_word(i7mem, "); INV_A1; WRITE(", "); INV_A2; WRITE(")");
+
+@ =
+ WRITE("i7mem["); INV_A1; WRITE(" + "); INV_A2; WRITE("]");
+
+@ =
+ WRITE("i7_write_word(i7mem, "); INV_A1; WRITE(", "); INV_A2; WRITE(", ");
diff --git a/inter/final-module/Chapter 5/C Object Model.w b/inter/final-module/Chapter 5/C Object Model.w
index fac5ce273..41ed0b338 100644
--- a/inter/final-module/Chapter 5/C Object Model.w
+++ b/inter/final-module/Chapter 5/C Object Model.w
@@ -280,12 +280,12 @@ void CObjectModel::property_offset(code_generation_target *cgt, code_generation
if (C_GEN_DATA(objdata.C_property_offsets_made)++ == 0)
@;
- WRITE("write_i7_lookup(i7mem, ");
+ WRITE("i7_write_word(i7mem, ");
if (as_attr) CTarget::mangle(cgt, OUT, I"attributed_property_offsets");
else CTarget::mangle(cgt, OUT, I"valued_property_offsets");
WRITE(", ");
CTarget::mangle(cgt, OUT, prop);
- WRITE(", %d, i7_cpv_SET);\n", pos);
+ WRITE(", %d, i7_lvalue_SET);\n", pos);
CodeGen::deselect(gen, saved);
}
@@ -296,9 +296,9 @@ not deriving from an Inform program.
@ =
WRITE("i7val fn_i7_mgl_CreatePropertyOffsets(int argc) {\n"); INDENT;
WRITE("for (int i=0; i= i7_max_objects) ||
- (prop_id < 0) || (prop_id >= i7_no_property_ids)) return 0;
- while (i7_properties[(int) owner_id].value_set[(int) prop_id] == 0)
- owner_id = i7_class_of[owner_id];
- return i7_properties[(int) owner_id].value[(int) prop_id];
-}
-
void i7_write_prop_value(i7val owner_id, i7val prop_id, i7val val) {
if ((owner_id <= 0) || (owner_id >= i7_max_objects) ||
(prop_id < 0) || (prop_id >= i7_no_property_ids)) {
@@ -390,17 +415,27 @@ void i7_write_prop_value(i7val owner_id, i7val prop_id, i7val val) {
}
=
-@h Other things to do with properties.
+@ And here sre the functions called by the above primitives:
= (text to inform7_clib.h)
+i7val i7_read_prop_value(i7val owner_id, i7val prop_id) {
+ if ((owner_id <= 0) || (owner_id >= i7_max_objects) ||
+ (prop_id < 0) || (prop_id >= i7_no_property_ids)) return 0;
+ while (i7_properties[(int) owner_id].value_set[(int) prop_id] == 0)
+ owner_id = i7_class_of[owner_id];
+ return i7_properties[(int) owner_id].value[(int) prop_id];
+}
+
i7val i7_change_prop_value(i7val obj, i7val pr, i7val to, int way) {
i7val val = i7_read_prop_value(obj, pr), new_val = val;
switch (way) {
- case i7_cpv_SET: i7_write_prop_value(obj, pr, to); new_val = to; break;
- case i7_cpv_PREDEC: new_val = val; i7_write_prop_value(obj, pr, val-1); break;
- case i7_cpv_POSTDEC: new_val = val-1; i7_write_prop_value(obj, pr, new_val); break;
- case i7_cpv_PREINC: new_val = val; i7_write_prop_value(obj, pr, val+1); break;
- case i7_cpv_POSTINC: new_val = val+1; i7_write_prop_value(obj, pr, new_val); break;
+ case i7_lvalue_SET: i7_write_prop_value(obj, pr, to); new_val = to; break;
+ case i7_lvalue_PREDEC: new_val = val; i7_write_prop_value(obj, pr, val-1); break;
+ case i7_lvalue_POSTDEC: new_val = val-1; i7_write_prop_value(obj, pr, new_val); break;
+ case i7_lvalue_PREINC: new_val = val; i7_write_prop_value(obj, pr, val+1); break;
+ case i7_lvalue_POSTINC: new_val = val+1; i7_write_prop_value(obj, pr, new_val); break;
+ case i7_lvalue_SETBIT: new_val = val | new_val; i7_write_prop_value(obj, pr, new_val); break;
+ case i7_lvalue_CLEARBIT: new_val = val &(~new_val); i7_write_prop_value(obj, pr, new_val); break;
}
return new_val;
}
diff --git a/inter/final-module/Chapter 5/C References.w b/inter/final-module/Chapter 5/C References.w
new file mode 100644
index 000000000..21ce7d3d7
--- /dev/null
+++ b/inter/final-module/Chapter 5/C References.w
@@ -0,0 +1,118 @@
+[CReferences::] C References.
+
+How changes to storage objects are translated into C.
+
+@ References identify storage objects which are being written to or otherwise
+modified, rather than having their current contents read.
+
+There are seven possible ways to modify something identified by a reference,
+and we need constants to identify these ways at runtime:
+
+= (text to inform7_clib.h)
+#define i7_lvalue_SET 1
+#define i7_lvalue_PREDEC 2
+#define i7_lvalue_POSTDEC 3
+#define i7_lvalue_PREINC 4
+#define i7_lvalue_POSTINC 5
+#define i7_lvalue_SETBIT 6
+#define i7_lvalue_CLEARBIT 7
+=
+
+@ Those seven ways correspond to seven Inter primitives, with the following
+signatures:
+= (text)
+primitive !store ref val -> val
+primitive !preincrement ref -> val
+primitive !postincrement ref -> val
+primitive !predecrement ref -> val
+primitive !postdecrement ref -> val
+primitive !setbit ref val -> void
+primitive !clearbit ref val -> void
+=
+Since C functions can have their return values freely ignored, we will in fact
+implement |!setbit| and |!clearbit| as if they too had the signature
+|ref val -> val|.
+
+For all these primitives, then, the first operand A1 is a |ref|, and the following
+function should be used to generate from it:
+
+=
+void CReferences::A1_as_ref(code_generation *gen, inter_tree_node *P) {
+ C_GEN_DATA(memdata.next_node_is_a_ref) = TRUE;
+ CodeGen::FC::frame(gen, InterTree::first_child(P));
+ C_GEN_DATA(memdata.next_node_is_a_ref) = FALSE;
+}
+
+@ That sets a temporary mode which is immediately detected and cleared by
+the generator for whatever A1 actually is. That generator is expected to call
+this function to detect whether it's a ref. In this mode, A1 is compiled not
+to a valid C expression to evaluate the contents of A1, but instead to a
+function call which will modify A1, and which is missing one or two final
+arguments.
+
+Note that the mode is auto-exited at once. This is all a bit clumsy, but is
+correct.
+
+=
+int CReferences::am_I_a_ref(code_generation *gen) {
+ int answer = C_GEN_DATA(memdata.next_node_is_a_ref);
+ C_GEN_DATA(memdata.next_node_is_a_ref) = FALSE;
+ return answer;
+}
+
+@ So, then, here goes:
+
+=
+int CReferences::compile_primitive(code_generation *gen, inter_ti bip, inter_tree_node *P) {
+ text_stream *OUT = CodeGen::current(gen);
+ text_stream *store_form = NULL;
+ switch (bip) {
+ case STORE_BIP: store_form = I"i7_lvalue_SET"; break;
+ case PREINCREMENT_BIP: store_form = I"i7_lvalue_PREINC"; break;
+ case POSTINCREMENT_BIP: store_form = I"i7_lvalue_POSTINC"; break;
+ case PREDECREMENT_BIP: store_form = I"i7_lvalue_PREDEC"; break;
+ case POSTDECREMENT_BIP: store_form = I"i7_lvalue_POSTDEC"; break;
+ case SETBIT_BIP: store_form = I"i7_lvalue_SETBIT"; break;
+ case CLEARBIT_BIP: store_form = I"i7_lvalue_CLEARBIT"; break;
+ default: return NOT_APPLICABLE;
+ }
+ if (store_form) @;
+ return FALSE;
+}
+
+@ Some storage objects, like variables, can be generated to C code which works
+in either an lvalue or rvalue context. For example, the Inter variable |frog|
+generates just as the C variable |i7_mgl_frog|.[1] It's then fine to generate
+code like either |10 + i7_mgl_frog|, where it is used in a |val| context, or
+like |i7_mgl_frog++|, where it is used in a |ref| context.
+
+But other storage objects are not so lucky, and those need to generate to
+different function calls, one used in a |ref| setting, one used in a |val|.
+That's what is done by the "A1 as ref" mode set up above.
+
+[1] In real life, do not mangle frogs. See C. S. Lewis, "Perelandra", 1943.
+
+@ =
+ inter_tree_node *ref = InterTree::first_child(P);
+ if ((CodeGen::CL::node_is_word_array_ref(gen->from, ref)) ||
+ (CodeGen::CL::node_is_property_ref(gen->from, ref))) {
+ @;
+ } else {
+ @;
+ }
+
+@ =
+ WRITE("("); CReferences::A1_as_ref(gen, P);
+ if (bip == STORE_BIP) { INV_A2; } else { WRITE("0"); }
+ WRITE(", %S))", store_form);
+
+@ =
+ switch (bip) {
+ case PREINCREMENT_BIP: WRITE("++("); INV_A1; WRITE(")"); break;
+ case POSTINCREMENT_BIP: WRITE("("); INV_A1; WRITE(")++"); break;
+ case PREDECREMENT_BIP: WRITE("--("); INV_A1; WRITE(")"); break;
+ case POSTDECREMENT_BIP: WRITE("("); INV_A1; WRITE(")--"); break;
+ case STORE_BIP: WRITE("("); INV_A1; WRITE(" = "); INV_A2; WRITE(")"); break;
+ case SETBIT_BIP: INV_A1; WRITE(" = "); INV_A1; WRITE(" | "); INV_A2; break;
+ case CLEARBIT_BIP: INV_A1; WRITE(" = "); INV_A1; WRITE(" &~ ("); INV_A2; WRITE(")"); break;
+ }
diff --git a/inter/final-module/Chapter 5/Final C.w b/inter/final-module/Chapter 5/Final C.w
index e376712b9..94f551f6c 100644
--- a/inter/final-module/Chapter 5/Final C.w
+++ b/inter/final-module/Chapter 5/Final C.w
@@ -2,7 +2,7 @@
To generate I6 code from intermediate code.
-@h Target,
+@h Target.
=
code_generation_target *c_target = NULL;
@@ -12,6 +12,7 @@ void CTarget::create_target(void) {
METHOD_ADD(c_target, BEGIN_GENERATION_MTID, CTarget::begin_generation);
METHOD_ADD(c_target, END_GENERATION_MTID, CTarget::end_generation);
+ CMemoryModel::initialise(c_target);
CObjectModel::initialise(c_target);
METHOD_ADD(c_target, GENERAL_SEGMENT_MTID, CTarget::general_segment);
@@ -40,13 +41,30 @@ void CTarget::create_target(void) {
METHOD_ADD(c_target, BEGIN_OPCODE_MTID, CTarget::begin_opcode);
METHOD_ADD(c_target, SUPPLY_OPERAND_MTID, CTarget::supply_operand);
METHOD_ADD(c_target, END_OPCODE_MTID, CTarget::end_opcode);
- METHOD_ADD(c_target, BEGIN_ARRAY_MTID, CTarget::begin_array);
- METHOD_ADD(c_target, ARRAY_ENTRY_MTID, CTarget::array_entry);
- METHOD_ADD(c_target, END_ARRAY_MTID, CTarget::end_array);
METHOD_ADD(c_target, OFFER_PRAGMA_MTID, CTarget::offer_pragma)
METHOD_ADD(c_target, NEW_FAKE_ACTION_MTID, CTarget::new_fake_action);
}
+@h Static supporting code.
+The C code generated here would not compile as a stand-alone file. It needs
+to use variables and functions from a small unchanging library called
+|inform7_clib.h|. (The |.h| there is questionable, since this is not purely
+a header file: it contains actual content and not only predeclarations. On
+the other hand, it serves the same basic purpose.)
+
+The code we generate here can only make sense if read alongside |inform7_clib.h|,
+and vice versa, so the file is presented here in installments. This is the
+first of those:
+
+= (text to inform7_clib.h)
+/* This is a library of C code to support Inform or other Inter programs compiled
+ tp ANSI C. It was generated mechanically from the Inter source code, so to
+ change it, edit that and not this. */
+
+#include
+#include
+=
+
@h Segmentation.
@e c_fundamental_types_I7CGS
@@ -119,19 +137,19 @@ int C_target_segments[] = {
typedef struct C_generation_data {
text_stream *double_quoted_C;
int no_double_quoted_C_strings;
- int extent_of_i7mem;
int C_dword_count;
int C_action_count;
struct dictionary *C_vm_dictionary;
+ struct C_generation_memory_model_data memdata;
struct C_generation_object_model_data objdata;
CLASS_DEFINITION
} C_generation_data;
void CTarget::initialise_data(code_generation *gen) {
+ CMemoryModel::initialise_data(gen);
CObjectModel::initialise_data(gen);
C_GEN_DATA(double_quoted_C) = Str::new();
C_GEN_DATA(no_double_quoted_C_strings) = 0;
- C_GEN_DATA(extent_of_i7mem) = 0;
C_GEN_DATA(C_dword_count) = 0;
C_GEN_DATA(C_action_count) = 0;
C_GEN_DATA(C_vm_dictionary) = Dictionaries::new(1024, TRUE);
@@ -157,7 +175,7 @@ int CTarget::begin_generation(code_generation_target *cgt, code_generation *gen)
WRITE("#include \"inform7_clib.h\"\n");
CodeGen::deselect(gen, saved);
- CTarget::begin_memory(gen);
+ CMemoryModel::begin(gen);
CTarget::begin_functions(gen);
CObjectModel::begin(gen);
CTarget::begin_dictionary_words(gen);
@@ -166,7 +184,7 @@ int CTarget::begin_generation(code_generation_target *cgt, code_generation *gen)
}
int CTarget::end_generation(code_generation_target *cgt, code_generation *gen) {
- CTarget::end_memory(gen);
+ CMemoryModel::end(gen);
CTarget::end_functions(gen);
CObjectModel::end(gen);
CTarget::end_dictionary_words(gen);
diff --git a/inter/final-module/Contents.w b/inter/final-module/Contents.w
index a19234ca5..f1cf21946 100644
--- a/inter/final-module/Contents.w
+++ b/inter/final-module/Contents.w
@@ -25,5 +25,7 @@ Chapter 4: Inform 6
Chapter 5: C
Final C
+ C References
+ C Memory Model
C Implementation
C Object Model