To compile any dialogue details in the instances submodule.
§1. Compilation data for dialogue choices. Each dialogue_choice object contains this data:
typedef struct dialogue_choice_compilation_data { struct parse_node *where_created; struct inter_name *choice_array_iname; struct inter_name *available_fn_iname; struct inter_name *action_match_fn_iname; struct inter_name *performance_fn_iname; } dialogue_choice_compilation_data; dialogue_choice_compilation_data RTDialogueChoices::new(parse_node *PN, dialogue_choice *dc) { dialogue_choice_compilation_data dccd; dccd.where_created = PN; dccd.choice_array_iname = NULL; dccd.available_fn_iname = NULL; dccd.action_match_fn_iname = NULL; dccd.performance_fn_iname = NULL; return dccd; } package_request *RTDialogueChoices::package(dialogue_choice *dc) { if (dc->as_instance == NULL) internal_error("not available yet"); return RTInstances::package(dc->as_instance); } inter_name *RTDialogueChoices::choice_array_iname(dialogue_choice *dc) { if (dc->compilation_data.choice_array_iname == NULL) dc->compilation_data.choice_array_iname = Hierarchy::make_iname_in(CHOICE_ARRAY_HL, RTDialogueChoices::package(dc)); return dc->compilation_data.choice_array_iname; } inter_name *RTDialogueChoices::available_fn_iname(dialogue_choice *dc) { if (dc->compilation_data.available_fn_iname == NULL) dc->compilation_data.available_fn_iname = Hierarchy::make_iname_in(CHOICE_AVAILABLE_FN_HL, RTDialogueChoices::package(dc)); return dc->compilation_data.available_fn_iname; } inter_name *RTDialogueChoices::action_match_fn_iname(dialogue_choice *dc) { if (dc->compilation_data.action_match_fn_iname == NULL) dc->compilation_data.action_match_fn_iname = Hierarchy::make_iname_in(CHOICE_ACTION_MATCH_FN_HL, RTDialogueChoices::package(dc)); return dc->compilation_data.action_match_fn_iname; } inter_name *RTDialogueChoices::performance_fn_iname(dialogue_choice *dc) { if (dc->compilation_data.performance_fn_iname == NULL) dc->compilation_data.performance_fn_iname = Hierarchy::make_iname_in(CHOICE_PERFORMANCE_FN_HL, RTDialogueChoices::package(dc)); return dc->compilation_data.performance_fn_iname; }
- The structure dialogue_choice_compilation_data is accessed in 3/uo, 5/mlt, 5/tbl, 5/dbi, 5/dli, 5/prp, 5/lp, 5/act2, 5/nap and here.
void RTDialogueChoices::compile(void) { dialogue_choice *dc; LOOP_OVER(dc, dialogue_choice) { text_stream *desc = Str::new(); WRITE_TO(desc, "dialogue choice %d", dc->allocation_id); Sequence::queue(&RTDialogueChoices::choice_compilation_agent, STORE_POINTER_dialogue_choice(dc), desc); } }
void RTDialogueChoices::choice_compilation_agent(compilation_subtask *ct) { dialogue_choice *dc = RETRIEVE_POINTER_dialogue_choice(ct->data); current_sentence = dc->compilation_data.where_created; package_request *PR = RTDialogueChoices::package(dc); int make_availability_function = FALSE; wording APW = EMPTY_WORDING; Scan the clauses further3.1; inter_name *array_iname = RTDialogueChoices::choice_array_iname(dc); Hierarchy::apply_metadata_from_iname(PR, CHOICE_ARRAY_MD_HL, array_iname); packaging_state save = EmitArrays::begin_word(array_iname, K_value); Write the type entry3.2; Write the availability entry3.3; Write the details entry3.4; Write the state word3.5; EmitArrays::end(save); if (make_availability_function) Compile the available function3.6; if (dc->to_perform_expression) Compile the performance function3.7; if (Wordings::nonempty(APW)) Compile the action-matching function3.8; }
§3.1. Scan the clauses further3.1 =
for (parse_node *clause = dc->choice_at->down; clause; clause = clause->next) { if (Node::is(clause, DIALOGUE_CLAUSE_NT)) { int c = Annotations::read_int(clause, dialogue_choice_clause_ANNOT); switch (c) { case IF_DCC: case UNLESS_DCC: make_availability_function = TRUE; break; } } }
- This code is used in §3.
§3.2. Write the type entry3.2 =
EmitArrays::numeric_entry((inter_ti) dc->selection_type);
- This code is used in §3.
§3.3. Write the availability entry3.3 =
if (make_availability_function) { EmitArrays::iname_entry(RTDialogueChoices::available_fn_iname(dc)); } else { EmitArrays::numeric_entry(0); }
- This code is used in §3.
§3.4. Write the details entry3.4 =
wording CW = Node::get_text(dc->selection); switch (dc->selection_type) { case TEXTUAL_DSEL: if (<s-literal>(CW)) { parse_node *text = <<rp>>; CompileValues::to_array_entry_of_kind(text, K_text); } else { internal_error("somehow not a literal text"); } break; case PERFORM_DSEL: if (dc->to_perform) EmitArrays::iname_entry(RTInstances::value_iname(dc->to_perform->as_instance)); else EmitArrays::iname_entry(RTDialogueChoices::performance_fn_iname(dc)); break; case INSTEAD_OF_DSEL: case AFTER_DSEL: case BEFORE_DSEL: if (<dialogue-selection>(CW)) { APW = GET_RW(<dialogue-selection>, 1); EmitArrays::iname_entry(RTDialogueChoices::action_match_fn_iname(dc)); } else { internal_error("somehow didn't reparse"); } break; case ENDING_DSEL: case ENDING_FINALLY_DSEL: EmitArrays::numeric_entry(3); break; case ENDING_SAYING_DSEL: case ENDING_FINALLY_SAYING_DSEL: { wording EW = dc->selection_parameter; if (<s-literal>(EW)) { parse_node *text = <<rp>>; CompileValues::to_array_entry(text); } else { internal_error("somehow not a literal text"); } break; } default: EmitArrays::numeric_entry(0); break; }
- This code is used in §3.
§3.5. Write the state word3.5 =
EmitArrays::numeric_entry(0);
- This code is used in §3.
§3.6. Compile the available function3.6 =
packaging_state save = Functions::begin(RTDialogueChoices::available_fn_iname(dc)); Check the if and unless conditions3.6.1; EmitCode::rtrue(); Functions::end(save);
- This code is used in §3.
§3.6.1. Check the if and unless conditions3.6.1 =
current_sentence = dc->choice_at; for (parse_node *clause = dc->choice_at->down; clause; clause = clause->next) { wording CW = Node::get_text(clause); int c = Annotations::read_int(clause, dialogue_choice_clause_ANNOT); switch (c) { case IF_DCC: case UNLESS_DCC: { <dialogue-choice-clause>(CW); wording A = GET_RW(<dialogue-choice-clause>, 1); if (<s-condition>(A)) { parse_node *cond = <<rp>>; if (Dash::validate_conditional_clause(cond)) { EmitCode::inv(IF_BIP); EmitCode::down(); if (c == IF_DCC) { EmitCode::inv(NOT_BIP); EmitCode::down(); } CompileValues::to_code_val_of_kind(cond, K_truth_state); if (c == IF_DCC) { EmitCode::up(); } EmitCode::code(); EmitCode::down(); EmitCode::rfalse(); EmitCode::up(); EmitCode::up(); } } else { Problems::quote_source(1, current_sentence); Problems::quote_wording(2, A); StandardProblems::handmade_problem(Task::syntax_tree(), _p_(...)); Problems::issue_problem_segment( "This dialogue choice (%1) seems to be performed depending " "on whether or not '%2', " "but I can't make sense of that condition."); Problems::issue_problem_end(); } break; } } }
- This code is used in §3.6.
§3.7. Compile the performance function3.7 =
packaging_state save = Functions::begin(RTDialogueChoices::performance_fn_iname(dc)); EmitCode::inv(RETURN_BIP); EmitCode::down(); CompileValues::to_code_val_of_kind(dc->to_perform_expression, K_dialogue_beat); EmitCode::up(); Functions::end(save);
- This code is used in §3.
§3.8. Compile the action-matching function3.8 =
packaging_state save = Functions::begin(RTDialogueChoices::action_match_fn_iname(dc)); if (<s-action-pattern-as-value>(APW)) { parse_node *cond = <<rp>>; if (Dash::check_condition(cond)) { EmitCode::inv(IF_BIP); EmitCode::down(); CompileValues::to_code_val_of_kind(cond, K_truth_state); EmitCode::code(); EmitCode::down(); EmitCode::rtrue(); EmitCode::up(); EmitCode::up(); } } else { Problems::quote_source(1, current_sentence); Problems::quote_wording(2, APW); StandardProblems::handmade_problem(Task::syntax_tree(), _p_(...)); Problems::issue_problem_segment( "This dialogue choice (%1) seems to depend on the action '%2', " "but I can't make sense of what action that is."); Problems::issue_problem_end(); } EmitCode::rfalse(); Functions::end(save);
- This code is used in §3.