[EmitInterSchemas::] Emitting Inter Schemas. @h Compilation. = void EmitInterSchemas::emit(inter_tree *I, value_holster *VH, inter_schema *sch, void *opaque_state, inter_symbols_table *first_call, inter_symbols_table *second_call, void (*inline_command_handler)(value_holster *VH, inter_schema_token *t, void *opaque_state, int prim_cat), void (*i7_source_handler)(value_holster *VH, text_stream *S, void *opaque_state, int prim_cat)) { int prim_cat = CODE_PRIM_CAT; if (VH->vhmode_wanted == INTER_VAL_VHMODE) { prim_cat = VAL_PRIM_CAT; } else if (VH->vhmode_wanted != INTER_VOID_VHMODE) { internal_error("can only emit schemas in INTER_VAL_VHMODE or INTER_VOID_VHMODE"); } if (sch->mid_case) { Produce::to_last_level(I, 4); } int again = TRUE; while (again) { again = FALSE; for (inter_schema_node *isn = sch->node_tree; isn; isn=isn->next_node) if (EmitInterSchemas::process_conditionals(I, isn, first_call, second_call)) again = TRUE; } for (inter_schema_node *isn = sch->node_tree; isn; isn=isn->next_node) EmitInterSchemas::emit_inner(I, isn, VH, sch, opaque_state, prim_cat, first_call, second_call, inline_command_handler, i7_source_handler); } @ = int EmitInterSchemas::process_conditionals(inter_tree *I, inter_schema_node *isn, inter_symbols_table *first_call, inter_symbols_table *second_call) { if (isn == NULL) return FALSE; if (isn->blocked_by_conditional) return FALSE; if (isn->isn_type == DIRECTIVE_ISNT) @; for (isn=isn->child_node; isn; isn=isn->next_node) if (EmitInterSchemas::process_conditionals(I, isn, first_call, second_call)) return TRUE; return FALSE; } @ = if ((isn->dir_clarifier == IFDEF_I6RW) || (isn->dir_clarifier == IFNDEF_I6RW) || (isn->dir_clarifier == IFTRUE_I6RW) || (isn->dir_clarifier == IFFALSE_I6RW)) { LOGIF(SCHEMA_COMPILATION, "Conditional directive in schema!\n"); inter_schema_node *ifnot_node = NULL, *endif_node = NULL; inter_schema_node *at = isn->next_node; while (at) { if (at->blocked_by_conditional == FALSE) { if (at->dir_clarifier == IFDEF_I6RW) { isn = at; ifnot_node = NULL; } if (at->dir_clarifier == IFNDEF_I6RW) { isn = at; ifnot_node = NULL; } if (at->dir_clarifier == IFTRUE_I6RW) { isn = at; ifnot_node = NULL; } if (at->dir_clarifier == IFFALSE_I6RW) { isn = at; ifnot_node = NULL; } if (at->dir_clarifier == IFNOT_I6RW) ifnot_node = at; if (at->dir_clarifier == ENDIF_I6RW) { endif_node = at; break; } } at = at->next_node; } if (endif_node == NULL) internal_error("no matching #endif"); text_stream *symbol_to_check = NULL; text_stream *value_to_check = NULL; inter_ti operation_to_check = 0; if ((isn->dir_clarifier == IFDEF_I6RW) || (isn->dir_clarifier == IFNDEF_I6RW)) { symbol_to_check = isn->child_node->expression_tokens->material; } else { inter_schema_node *to_eval = isn->child_node; while ((to_eval) && (to_eval->isn_type == SUBEXPRESSION_ISNT)) to_eval = to_eval->child_node; if ((to_eval == NULL) || (to_eval->child_node->expression_tokens == NULL)) internal_error("bad iftrue"); symbol_to_check = to_eval->child_node->expression_tokens->material; operation_to_check = to_eval->isn_clarifier; value_to_check = to_eval->child_node->next_node->expression_tokens->material; } LOGIF(SCHEMA_COMPILATION, "Means checking %S\n", symbol_to_check); if (value_to_check) LOGIF(SCHEMA_COMPILATION, "Against %S\n", value_to_check); int val = -1, def = FALSE; if (Str::eq(symbol_to_check, I"#version_number")) { val = 8; def = TRUE; } else if (Str::eq(symbol_to_check, I"STRICT_MODE")) { def = TRUE; } else { inter_symbol *symb = EmitInterSchemas::find_identifier_text(I, symbol_to_check, Inter::Packages::scope(Packaging::incarnate(Site::veneer_request(I))), second_call); while ((symb) && (symb->equated_to)) symb = symb->equated_to; LOGIF(SCHEMA_COMPILATION, "Symb is $3\n", symb); if (Inter::Symbols::is_defined(symb)) { def = TRUE; val = Inter::Symbols::evaluate_to_int(symb); } } LOGIF(SCHEMA_COMPILATION, "Defined: %d, value: %d\n", def, val); int decision = TRUE; if ((isn->dir_clarifier == IFNDEF_I6RW) || (isn->dir_clarifier == IFDEF_I6RW)) decision = def; else { int h = Str::atoi(value_to_check, 0); LOGIF(SCHEMA_COMPILATION, "Want value %d\n", h); if (operation_to_check == EQ_BIP) decision = (val == h)?TRUE:FALSE; if (operation_to_check == NE_BIP) decision = (val != h)?TRUE:FALSE; if (operation_to_check == GE_BIP) decision = (val >= h)?TRUE:FALSE; if (operation_to_check == GT_BIP) decision = (val > h)?TRUE:FALSE; if (operation_to_check == LE_BIP) decision = (val <= h)?TRUE:FALSE; if (operation_to_check == LT_BIP) decision = (val < h)?TRUE:FALSE; } if (isn->dir_clarifier == IFNDEF_I6RW) decision = decision?FALSE:TRUE; if (isn->dir_clarifier == IFFALSE_I6RW) decision = decision?FALSE:TRUE; isn->blocked_by_conditional = TRUE; endif_node->blocked_by_conditional = TRUE; if (ifnot_node) ifnot_node->blocked_by_conditional = TRUE; if (decision) { inter_schema_node *at = ifnot_node; while ((at) && (at != endif_node)) { at->blocked_by_conditional = TRUE; at = at->next_node; } } else { inter_schema_node *at = isn; while ((at) && (at != endif_node) && (at != ifnot_node)) { at->blocked_by_conditional = TRUE; at = at->next_node; } } if (Log::aspect_switched_on(SCHEMA_COMPILATION_DA)) { LOG("--- Resulting in: ---\n"); for (inter_schema_node *at = isn; at; at = at->next_node) InterSchemas::log_just(at, 0); LOG("------\n"); } return TRUE; } @ = void EmitInterSchemas::emit_inner(inter_tree *I, inter_schema_node *isn, value_holster *VH, inter_schema *sch, void *opaque_state, int prim_cat, inter_symbols_table *first_call, inter_symbols_table *second_call, void (*inline_command_handler)(value_holster *VH, inter_schema_token *t, void *opaque_state, int prim_cat), void (*i7_source_handler)(value_holster *VH, text_stream *S, void *opaque_state, int prim_cat)) { if (isn == NULL) return; if (isn->blocked_by_conditional) return; switch (isn->isn_type) { case LABEL_ISNT: @; break; case CODE_ISNT: @; break; case EVAL_ISNT: @; break; case EXPRESSION_ISNT: @; break; case SUBEXPRESSION_ISNT: @; break; case STATEMENT_ISNT: @; break; case OPERATION_ISNT: @; break; case ASSEMBLY_ISNT: @; break; case CALL_ISNT: @; break; case MESSAGE_ISNT: @; break; case CALLMESSAGE_ISNT: @; break; case DIRECTIVE_ISNT: @; break; default: internal_error("unknown schema node type"); } } @ = if (prim_cat != CODE_PRIM_CAT) internal_error("label outside code"); TEMPORARY_TEXT(L) WRITE_TO(L, "."); for (inter_schema_node *at = isn->child_node; at; at=at->next_node) { for (inter_schema_token *t = at->expression_tokens; t; t=t->next) { if (t->ist_type == IDENTIFIER_ISTT) WRITE_TO(L, "%S", t->material); else if ((t->ist_type == INLINE_ISTT) && (t->inline_command == label_ISINC)) { #ifdef CORE_MODULE JumpLabels::write(L, t->operand); #endif #ifndef CORE_MODULE internal_error("label namespaces are unavailable in assimilation mode"); #endif } else if ((t->ist_type == INLINE_ISTT) && ((t->inline_command == counter_up_ISINC) || (t->inline_command == counter_down_ISINC))) { value_holster VN = Holsters::new(INTER_DATA_VHMODE); if (inline_command_handler) (*inline_command_handler)(&VN, t, opaque_state, VAL_PRIM_CAT); } else internal_error("bad label stuff"); } } Produce::place_label(I, Produce::reserve_label(I, L)); DISCARD_TEXT(L) @ = if (prim_cat != CODE_PRIM_CAT) internal_error("code block in expression"); if (isn->unopened == FALSE) { Produce::code(I); Produce::down(I); } for (inter_schema_node *at = isn->child_node; at; at=at->next_node) EmitInterSchemas::emit_inner(I, at, VH, sch, opaque_state, CODE_PRIM_CAT, first_call, second_call, inline_command_handler, i7_source_handler); if (isn->unclosed == FALSE) { Produce::up(I); } if (isn->unopened) Produce::to_last_level(I, 0); @ = if (prim_cat != CODE_PRIM_CAT) internal_error("assembly in expression"); inter_schema_node *at = isn->child_node; if (at) { text_stream *opcode_text = NULL; if (at->isn_type == EXPRESSION_ISNT) { inter_schema_token *tok = at->expression_tokens; if ((tok->ist_type == OPCODE_ISTT) && (tok->next == NULL)) opcode_text = tok->material; } if (opcode_text == NULL) internal_error("assembly malformed"); Produce::inv_assembly(I, opcode_text); Produce::down(I); for (at = at->next_node; at; at=at->next_node) EmitInterSchemas::emit_inner(I, at, VH, sch, opaque_state, VAL_PRIM_CAT, first_call, second_call, inline_command_handler, i7_source_handler); Produce::up(I); } @ = if (isn->child_node) { inter_schema_node *at = isn->child_node; inter_symbol *to_call = NULL; if (at->isn_type == EXPRESSION_ISNT) { inter_schema_token *tok = at->expression_tokens; if ((tok->ist_type == IDENTIFIER_ISTT) && (tok->next == NULL)) { to_call = EmitInterSchemas::find_identifier(I, tok, first_call, second_call); if (Inter::Symbols::is_local(to_call)) to_call = NULL; } } if (to_call) { Produce::inv_call(I, to_call); at = at->next_node; } else { int argc = 0; for (inter_schema_node *n = isn->child_node; n; n=n->next_node) { if ((n->expression_tokens) && (n->expression_tokens->inline_command == combine_ISINC)) argc++; argc++; } switch (argc) { case 1: Produce::inv_primitive(I, INDIRECT0_BIP); break; case 2: Produce::inv_primitive(I, INDIRECT1_BIP); break; case 3: Produce::inv_primitive(I, INDIRECT2_BIP); break; case 4: Produce::inv_primitive(I, INDIRECT3_BIP); break; case 5: Produce::inv_primitive(I, INDIRECT4_BIP); break; default: internal_error("too many args for indirect call"); break; } } Produce::down(I); for (; at; at=at->next_node) EmitInterSchemas::emit_inner(I, at, VH, sch, opaque_state, VAL_PRIM_CAT, first_call, second_call, inline_command_handler, i7_source_handler); Produce::up(I); } @ = if (isn->child_node) { inter_schema_node *at = isn->child_node; int argc = 0; for (inter_schema_node *n = isn->child_node; n; n=n->next_node) argc++; switch (argc) { case 2: Produce::inv_primitive(I, MESSAGE0_BIP); break; case 3: Produce::inv_primitive(I, MESSAGE1_BIP); break; case 4: Produce::inv_primitive(I, MESSAGE2_BIP); break; case 5: Produce::inv_primitive(I, MESSAGE3_BIP); break; default: internal_error("too many args for message"); break; } Produce::down(I); for (; at; at=at->next_node) EmitInterSchemas::emit_inner(I, at, VH, sch, opaque_state, VAL_PRIM_CAT, first_call, second_call, inline_command_handler, i7_source_handler); Produce::up(I); } @ = if (isn->child_node) { inter_schema_node *at = isn->child_node; int argc = 0; for (inter_schema_node *n = isn->child_node; n; n=n->next_node) argc++; switch (argc) { case 1: Produce::inv_primitive(I, CALLMESSAGE0_BIP); break; case 2: Produce::inv_primitive(I, CALLMESSAGE1_BIP); break; case 3: Produce::inv_primitive(I, CALLMESSAGE2_BIP); break; case 4: Produce::inv_primitive(I, CALLMESSAGE3_BIP); break; default: internal_error("too many args for call-message"); break; } Produce::down(I); for (; at; at=at->next_node) EmitInterSchemas::emit_inner(I, at, VH, sch, opaque_state, VAL_PRIM_CAT, first_call, second_call, inline_command_handler, i7_source_handler); Produce::up(I); } @ = if ((prim_cat != CODE_PRIM_CAT) && (prim_cat != VAL_PRIM_CAT)) internal_error("eval block outside evaluation context"); if (isn->child_node == NULL) Produce::val(I, K_value, LITERAL_IVAL, 1); else { int d = 0; for (inter_schema_node *at = isn->child_node; at; at=at->next_node) { if (at->next_node) { d++; Produce::inv_primitive(I, SEQUENTIAL_BIP); Produce::down(I); } EmitInterSchemas::emit_inner(I, at, VH, sch, opaque_state, VAL_PRIM_CAT, first_call, second_call, inline_command_handler, i7_source_handler); } while (d > 0) { Produce::up(I); d--; } } @ = if (prim_cat == REF_PRIM_CAT) { Produce::reference(I); Produce::down(I); } Produce::inv_primitive(I, isn->isn_clarifier); Produce::down(I); int pc = VAL_PRIM_CAT; if (InterSchemas::first_operand_ref(isn->isn_clarifier)) pc = REF_PRIM_CAT; EmitInterSchemas::emit_inner(I, isn->child_node, VH, sch, opaque_state, pc, first_call, second_call, inline_command_handler, i7_source_handler); if (InterSchemas::arity(isn->isn_clarifier) == 2) EmitInterSchemas::emit_inner(I, isn->child_node->next_node, VH, sch, opaque_state, VAL_PRIM_CAT, first_call, second_call, inline_command_handler, i7_source_handler); Produce::up(I); if (prim_cat == REF_PRIM_CAT) { Produce::up(I); } @ = int d = 0; for (inter_schema_node *at = isn->child_node; at; at=at->next_node) { if (at->next_node) { d++; Produce::inv_primitive(I, SEQUENTIAL_BIP); Produce::down(I); } EmitInterSchemas::emit_inner(I, at, VH, sch, opaque_state, prim_cat, first_call, second_call, inline_command_handler, i7_source_handler); } while (d > 0) { Produce::up(I); d--; } @ = if (prim_cat != CODE_PRIM_CAT) internal_error("statement in expression"); if (isn->isn_clarifier == CASE_BIP) Produce::to_last_level(I, 2); Produce::inv_primitive(I, isn->isn_clarifier); int arity = InterSchemas::ip_arity(isn->isn_clarifier); if (arity > 0) { Produce::down(I); if (isn->isn_clarifier == OBJECTLOOP_BIP) @; inter_schema_node *at = isn->child_node; inter_schema_node *last = NULL; int actual_arity = 0; for (int i = 0; ((at) && (iisn_clarifier, i), first_call, second_call, inline_command_handler, i7_source_handler); last = at; at = at->next_node; } if (!((last) && (last->unclosed))) { Produce::up(I); } } @ = inter_schema_node *oc_node = isn->child_node; while ((oc_node) && ((oc_node->isn_type != OPERATION_ISNT) || (oc_node->isn_clarifier != OFCLASS_BIP))) oc_node = oc_node->child_node; if (oc_node) { inter_schema_node *var_node = oc_node->child_node; inter_schema_node *cl_node = var_node?(var_node->next_node):NULL; if ((var_node) && (cl_node)) { EmitInterSchemas::emit_inner(I, var_node, VH, sch, opaque_state, REF_PRIM_CAT, first_call, second_call, inline_command_handler, i7_source_handler); EmitInterSchemas::emit_inner(I, cl_node, VH, sch, opaque_state, VAL_PRIM_CAT, first_call, second_call, inline_command_handler, i7_source_handler); } else internal_error("malformed OC node"); } else { inter_schema_node *var_node = isn->child_node; while ((var_node) && (var_node->isn_type != EXPRESSION_ISNT)) var_node = var_node->child_node; if (var_node) { EmitInterSchemas::emit_inner(I, var_node, VH, sch, opaque_state, REF_PRIM_CAT, first_call, second_call, inline_command_handler, i7_source_handler); #ifdef CORE_MODULE Produce::val_iname(I, K_value, RTKindDeclarations::iname(K_object)); #endif #ifndef CORE_MODULE Produce::val_symbol(I, K_value, Site::veneer_symbol(I, OBJECT_VSYMB)); #endif } else internal_error("objectloop without visible variable"); } @ = int cat_me = FALSE, lab_me = FALSE, print_ret_me = FALSE; int tc = 0; for (inter_schema_token *t = isn->expression_tokens; t; t=t->next) tc++; if ((tc > 1) && (prim_cat == VAL_PRIM_CAT)) cat_me = TRUE; if ((tc == 1) && (prim_cat == CODE_PRIM_CAT) && (isn->expression_tokens->ist_type == DQUOTED_ISTT)) print_ret_me = TRUE; if ((tc == 1) && (prim_cat == LAB_PRIM_CAT)) lab_me = TRUE; if (cat_me) { Produce::evaluation(I); Produce::down(I); } if (prim_cat == REF_PRIM_CAT) { Produce::reference(I); Produce::down(I); } for (inter_schema_token *t = isn->expression_tokens; t; t=t->next) { switch (t->ist_type) { case IDENTIFIER_ISTT: { if (lab_me) Produce::lab(I, Produce::reserve_label(I, t->material)); else { #ifdef CORE_MODULE local_variable *lvar = LocalVariables::by_identifier(t->material); if (lvar) { inter_symbol *lvar_s = LocalVariables::declare(lvar); Produce::val_symbol(I, K_value, lvar_s); } else { Produce::val_symbol(I, K_value, EmitInterSchemas::find_identifier(I, t, first_call, second_call)); } #endif #ifndef CORE_MODULE Produce::val_symbol(I, K_value, EmitInterSchemas::find_identifier(I, t, first_call, second_call)); #endif } break; } case ASM_ARROW_ISTT: Produce::val_symbol(I, K_value, Site::veneer_symbol(I, ASM_ARROW_VSYMB)); break; case ASM_SP_ISTT: Produce::val_symbol(I, K_value, Site::veneer_symbol(I, ASM_SP_VSYMB)); break; case ASM_NEGATED_LABEL_ISTT: if (Str::eq(t->material, I"rtrue")) Produce::val_symbol(I, K_value, Site::veneer_symbol(I, ASM_NEG_RTRUE_VSYMB)); else if (Str::eq(t->material, I"rfalse")) Produce::val_symbol(I, K_value, Site::veneer_symbol(I, ASM_NEG_RFALSE_VSYMB)); else { Produce::val_symbol(I, K_value, Site::veneer_symbol(I, ASM_NEG_VSYMB)); Produce::lab(I, Produce::reserve_label(I, t->material)); } break; case ASM_LABEL_ISTT: if (Str::eq(t->material, I"rtrue")) Produce::val_symbol(I, K_value, Site::veneer_symbol(I, ASM_RTRUE_VSYMB)); else if (Str::eq(t->material, I"rfalse")) Produce::val_symbol(I, K_value, Site::veneer_symbol(I, ASM_RFALSE_VSYMB)); else Produce::lab(I, Produce::reserve_label(I, t->material)); break; case NUMBER_ISTT: case BIN_NUMBER_ISTT: case HEX_NUMBER_ISTT: { inter_ti v1 = 0, v2 = 0; if (t->constant_number >= 0) { v1 = LITERAL_IVAL; v2 = (inter_ti) t->constant_number; } else if (Inter::Types::read_int_in_I6_notation(t->material, &v1, &v2) == FALSE) internal_error("bad number"); Produce::val(I, K_value, v1, v2); break; } case REAL_NUMBER_ISTT: Produce::val_real_from_text(I, t->material); break; case DQUOTED_ISTT: if (print_ret_me) { Produce::inv_primitive(I, PRINTRET_BIP); Produce::down(I); } Produce::val_text(I, t->material); if (print_ret_me) { Produce::up(I); } break; case SQUOTED_ISTT: if (Str::len(t->material) == 1) { Produce::val_char(I, Str::get_at(t->material, 0)); } else { Produce::val_dword(I, t->material); } break; case I7_ISTT: if (i7_source_handler) (*i7_source_handler)(VH, t->material, opaque_state, prim_cat); break; case INLINE_ISTT: if (inline_command_handler) (*inline_command_handler)(VH, t, opaque_state, prim_cat); break; default: internal_error("bad expression token"); } } if (cat_me) { Produce::up(I); } if (prim_cat == REF_PRIM_CAT) { Produce::up(I); } @ = internal_error("unknown directive"); @ = inter_symbol *EmitInterSchemas::find_identifier(inter_tree *I, inter_schema_token *t, inter_symbols_table *first_call, inter_symbols_table *second_call) { if (t->as_quoted) return InterNames::to_symbol(t->as_quoted); return EmitInterSchemas::find_identifier_text(I, t->material, first_call, second_call); } inter_symbol *EmitInterSchemas::find_identifier_text(inter_tree *I, text_stream *name, inter_symbols_table *first_call, inter_symbols_table *second_call) { if (Str::get_at(name, 0) == 0x00A7) { TEMPORARY_TEXT(SR) Str::copy(SR, name); Str::delete_first_character(SR); Str::delete_last_character(SR); inter_symbol *S = InterSymbolsTables::url_name_to_symbol(I, NULL, SR); DISCARD_TEXT(SR) if (S) return S; } if (first_call) { inter_symbol *S = Produce::seek_symbol(first_call, name); if (S) return S; } if (second_call) { inter_symbol *S = Produce::seek_symbol(second_call, name); if (S) return S; } inter_symbol *S = Veneer::find(I, name, Produce::kind_to_symbol(NULL)); if (S) return S; S = Produce::seek_symbol(Produce::connectors_scope(I), name); if (S) return S; S = Produce::seek_symbol(Produce::main_scope(I), name); if (S) return S; S = InterNames::to_symbol(Produce::find_by_name(I, name)); if (S) return S; LOG("Defeated on %S\n", name); internal_error("unable to find identifier"); return NULL; }