Generating C code to effect loops, branches and the like.
void CProgramControl::initialise(code_generation_target *cgt) { METHOD_ADD(c_target, COMPILE_PRIMITIVE_MTID, CProgramControl::compile_primitive); } int CProgramControl::compile_primitive(code_generation_target *cgt, code_generation *gen, inter_symbol *prim_name, inter_tree_node *P) { 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 = CArithmetic::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; r = CLiteralsModel::compile_primitive(gen, bip, P); if (r != NOT_APPLICABLE) return r; r = CInputOutputModel::compile_primitive(gen, bip, P); if (r != NOT_APPLICABLE) return r; r = CConditions::compile_primitive(gen, bip, P); if (r != NOT_APPLICABLE) return r; return CProgramControl::compile_control_primitive(gen, bip, P); } int CProgramControl::compile_control_primitive(code_generation *gen, inter_ti bip, inter_tree_node *P) { int suppress_terminal_semicolon = FALSE; text_stream *OUT = CodeGen::current(gen); inter_tree *I = gen->from; switch (bip) { case PUSH_BIP: WRITE("i7_push("); INV_A1; WRITE(")"); break; case PULL_BIP: INV_A1; WRITE(" = i7_pull()"); break; case BREAK_BIP: WRITE("break"); break; case CONTINUE_BIP: WRITE("continue"); break; case RETURN_BIP: Generate primitive for return1.1; break; case JUMP_BIP: WRITE("goto "); INV_A1; break; case QUIT_BIP: WRITE("exit(0)"); break; case RESTORE_BIP: break; we won't support this in C case INDIRECT0_BIP: case INDIRECT0V_BIP: WRITE("i7_call_0("); INV_A1; WRITE(")"); break; case INDIRECT1_BIP: case INDIRECT1V_BIP: WRITE("i7_call_1("); INV_A1; WRITE(", "); INV_A2; WRITE(")"); break; case INDIRECT2_BIP: case INDIRECT2V_BIP: WRITE("i7_call_2("); INV_A1; WRITE(", "); INV_A2; WRITE(", "); INV_A3; WRITE(")"); break; case INDIRECT3_BIP: case INDIRECT3V_BIP: WRITE("i7_call_3("); INV_A1; WRITE(", "); INV_A2; WRITE(", "); INV_A3; WRITE(", "); INV_A4; WRITE(")"); break; case INDIRECT4_BIP: case INDIRECT4V_BIP: WRITE("i7_call_4("); INV_A1; WRITE(", "); INV_A2; WRITE(", "); INV_A3; WRITE(", "); INV_A4; WRITE(", "); INV_A5; WRITE(")"); break; case INDIRECT5_BIP: case INDIRECT5V_BIP: WRITE("i7_call_5("); INV_A1; WRITE(", "); INV_A2; WRITE(", "); INV_A3; WRITE(", "); INV_A4; WRITE(", "); INV_A5; WRITE(", "); INV_A6; 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; case CALLMESSAGE2_BIP: WRITE("i7_ccall_2("); INV_A1; WRITE(", "); INV_A2; WRITE(", "); INV_A3; WRITE(")"); break; case CALLMESSAGE3_BIP: WRITE("i7_ccall_3("); INV_A1; WRITE(", "); INV_A2; WRITE(", "); INV_A3; WRITE(", "); INV_A4; WRITE(")"); break; case IF_BIP: Generate primitive for if1.2; break; case IFDEBUG_BIP: Generate primitive for ifdebug1.3; break; case IFSTRICT_BIP: Generate primitive for ifstrict1.4; break; case IFELSE_BIP: Generate primitive for ifelse1.5; break; case WHILE_BIP: Generate primitive for while1.6; break; case DO_BIP: Generate primitive for do1.7; break; case FOR_BIP: Generate primitive for for1.8; break; case OBJECTLOOP_BIP: Generate primitive for objectloop1.9; break; case OBJECTLOOPX_BIP: Generate primitive for objectloopx1.10; break; case LOOP_BIP: Generate primitive for loop1.11; break; case SWITCH_BIP: Generate primitive for switch1.12; break; case CASE_BIP: Generate primitive for case1.13; break; case ALTERNATIVECASE_BIP: INV_A1; WRITE(", "); INV_A2; break; case DEFAULT_BIP: Generate primitive for default1.14; break; default: internal_error("unimplemented prim"); } return suppress_terminal_semicolon; }
§1.1. Generate primitive for return1.1 =
int rboolean = NOT_APPLICABLE; inter_tree_node *V = InterTree::first_child(P); if (V->W.data[ID_IFLD] == VAL_IST) { inter_ti val1 = V->W.data[VAL1_VAL_IFLD]; inter_ti val2 = V->W.data[VAL2_VAL_IFLD]; if (val1 == LITERAL_IVAL) { if (val2 == 0) rboolean = FALSE; if (val2 == 1) rboolean = TRUE; } } switch (rboolean) { case FALSE: WRITE("return 0"); break; case TRUE: WRITE("return 1"); break; case NOT_APPLICABLE: WRITE("return (i7val) "); CodeGen::FC::frame(gen, V); break; }
- This code is used in §1.
§1.2. Generate primitive for if1.2 =
WRITE("if ("); INV_A1; WRITE(") {\n"); INDENT; INV_A2; OUTDENT; WRITE("}\n"); suppress_terminal_semicolon = TRUE;
- This code is used in §1.
§1.3. Generate primitive for ifdebug1.3 =
WRITE("#ifdef DEBUG\n"); INDENT; INV_A1; OUTDENT; WRITE("#endif\n"); suppress_terminal_semicolon = TRUE;
- This code is used in §1.
§1.4. Generate primitive for ifstrict1.4 =
WRITE("#ifdef STRICT_MODE\n"); INDENT; INV_A1; OUTDENT; WRITE("#endif\n"); suppress_terminal_semicolon = TRUE;
- This code is used in §1.
§1.5. Generate primitive for ifelse1.5 =
WRITE("if ("); INV_A1; WRITE(") {\n"); INDENT; INV_A2; OUTDENT; WRITE("} else {\n"); INDENT; INV_A3; OUTDENT; WRITE("}\n"); suppress_terminal_semicolon = TRUE;
- This code is used in §1.
§1.6. Generate primitive for while1.6 =
WRITE("while ("); INV_A1; WRITE(") {\n"); INDENT; INV_A2; OUTDENT; WRITE("}\n"); suppress_terminal_semicolon = TRUE;
- This code is used in §1.
§1.7. Generate primitive for do1.7 =
WRITE("do {"); INV_A2; WRITE("} until (\n"); INDENT; INV_A1; OUTDENT; WRITE(")\n");
- This code is used in §1.
§1.8. Generate primitive for for1.8 =
WRITE("for ("); inter_tree_node *INIT = InterTree::first_child(P); if (!((INIT->W.data[ID_IFLD] == VAL_IST) && (INIT->W.data[VAL1_VAL_IFLD] == LITERAL_IVAL) && (INIT->W.data[VAL2_VAL_IFLD] == 1))) INV_A1; WRITE(";"); INV_A2; WRITE(";"); inter_tree_node *U = InterTree::third_child(P); if (U->W.data[ID_IFLD] != VAL_IST) CodeGen::FC::frame(gen, U); WRITE(") {\n"); INDENT; INV_A4; OUTDENT; WRITE("}\n"); suppress_terminal_semicolon = TRUE;
- This code is used in §1.
§1.9. Generate primitive for objectloop1.9 =
int in_flag = FALSE; inter_tree_node *U = InterTree::third_child(P); if ((U->W.data[ID_IFLD] == INV_IST) && (U->W.data[METHOD_INV_IFLD] == INVOKED_PRIMITIVE)) { inter_symbol *prim = Inter::Inv::invokee(U); if ((prim) && (Primitives::to_bip(I, prim) == IN_BIP)) in_flag = TRUE; } WRITE("for (i7val "); INV_A1; WRITE(" = 1; "); INV_A1; WRITE(" < i7_max_objects; "); INV_A1; WRITE("++) "); if (in_flag == FALSE) { WRITE("if (i7_ofclass("); INV_A1; WRITE(", "); INV_A2; WRITE(")) "); } WRITE("if ("); INV_A3; WRITE(") {\n"); INDENT; INV_A4; OUTDENT; WRITE("}\n"); suppress_terminal_semicolon = TRUE;
- This code is used in §1.
§1.10. Generate primitive for objectloopx1.10 =
WRITE("for (i7val "); INV_A1; WRITE(" = 1; "); INV_A1; WRITE(" < i7_max_objects; "); INV_A1; WRITE("++) "); WRITE("if (i7_ofclass("); INV_A1; WRITE(", "); INV_A2; WRITE(")) "); WRITE(" {\n"); INDENT; INV_A3; OUTDENT; WRITE("}\n"); suppress_terminal_semicolon = TRUE;
- This code is used in §1.
§1.11. Generate primitive for loop1.11 =
WRITE("{\n"); INDENT; INV_A1; OUTDENT; WRITE("}\n"); suppress_terminal_semicolon = TRUE;
- This code is used in §1.
§1.12. Generate primitive for switch1.12 =
WRITE("switch ("); INV_A1; WRITE(") {\n"); INDENT; INV_A2; OUTDENT; WRITE("}\n"); suppress_terminal_semicolon = TRUE;
- This code is used in §1.
§1.13. Generate primitive for case1.13 =
CProgramControl::caser(gen, InterTree::first_child(P)); INDENT; INV_A2; WRITE(";\n"); WRITE("break;\n"); OUTDENT; suppress_terminal_semicolon = TRUE;
- This code is used in §1.
§1.14. Generate primitive for default1.14 =
WRITE("default:\n"); INDENT; INV_A1; WRITE(";\n"); WRITE("break;\n"); OUTDENT; suppress_terminal_semicolon = TRUE;
- This code is used in §1.
void CProgramControl::caser(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); inter_ti xbip = Primitives::to_bip(gen->from, prim); if (xbip == ALTERNATIVECASE_BIP) { CProgramControl::caser(gen, InterTree::first_child(X)); CProgramControl::caser(gen, InterTree::second_child(X)); return; } } } text_stream *OUT = CodeGen::current(gen); WRITE("case "); CodeGen::FC::frame(gen, X); WRITE(": "); }