To compile any dialogue details in the instances submodule.
§1. Compilation data for dialogue lines. Each dialogue_line object contains this data:
typedef struct dialogue_line_compilation_data { struct parse_node *where_created; struct inter_name *available_fn_iname; struct inter_name *speaker_fn_iname; struct inter_name *interlocutor_fn_iname; struct inter_name *mentioning_fn_iname; struct inter_name *action_fn_iname; struct inter_name *line_array_iname; } dialogue_line_compilation_data; dialogue_line_compilation_data RTDialogueLines::new(parse_node *PN, dialogue_line *dl) { dialogue_line_compilation_data dlcd; dlcd.where_created = PN; dlcd.available_fn_iname = NULL; dlcd.speaker_fn_iname = NULL; dlcd.interlocutor_fn_iname = NULL; dlcd.mentioning_fn_iname = NULL; dlcd.action_fn_iname = NULL; dlcd.line_array_iname = NULL; return dlcd; } package_request *RTDialogueLines::package(dialogue_line *dl) { if (dl->as_instance == NULL) internal_error("not available yet"); return RTInstances::package(dl->as_instance); } inter_name *RTDialogueLines::line_array_iname(dialogue_line *dl) { if (dl->compilation_data.line_array_iname == NULL) dl->compilation_data.line_array_iname = Hierarchy::make_iname_in(LINE_ARRAY_HL, RTDialogueLines::package(dl)); return dl->compilation_data.line_array_iname; } inter_name *RTDialogueLines::available_fn_iname(dialogue_line *dl) { if (dl->compilation_data.available_fn_iname == NULL) dl->compilation_data.available_fn_iname = Hierarchy::make_iname_in(LINE_AVAILABLE_FN_HL, RTDialogueLines::package(dl)); return dl->compilation_data.available_fn_iname; } inter_name *RTDialogueLines::speaker_fn_iname(dialogue_line *dl) { if (dl->compilation_data.speaker_fn_iname == NULL) dl->compilation_data.speaker_fn_iname = Hierarchy::make_iname_in(LINE_SPEAKER_FN_HL, RTDialogueLines::package(dl)); return dl->compilation_data.speaker_fn_iname; } inter_name *RTDialogueLines::interlocutor_fn_iname(dialogue_line *dl) { if (dl->compilation_data.interlocutor_fn_iname == NULL) dl->compilation_data.interlocutor_fn_iname = Hierarchy::make_iname_in(LINE_INTERLOCUTOR_FN_HL, RTDialogueLines::package(dl)); return dl->compilation_data.interlocutor_fn_iname; } inter_name *RTDialogueLines::mentioning_fn_iname(dialogue_line *dl) { if (dl->compilation_data.mentioning_fn_iname == NULL) dl->compilation_data.mentioning_fn_iname = Hierarchy::make_iname_in(LINE_MENTIONING_FN_HL, RTDialogueLines::package(dl)); return dl->compilation_data.mentioning_fn_iname; } inter_name *RTDialogueLines::action_fn_iname(dialogue_line *dl) { if (dl->compilation_data.action_fn_iname == NULL) dl->compilation_data.action_fn_iname = Hierarchy::make_iname_in(LINE_ACTION_FN_HL, RTDialogueLines::package(dl)); return dl->compilation_data.action_fn_iname; }
- The structure dialogue_line_compilation_data is accessed in 3/uo, 5/mlt, 5/tbl, 5/dbi, 5/dci, 5/prp, 5/lp, 5/act2, 5/nap and here.
void RTDialogueLines::compile(void) { dialogue_line *dl; LOOP_OVER(dl, dialogue_line) { text_stream *desc = Str::new(); WRITE_TO(desc, "dialogue line %d", dl->allocation_id); Sequence::queue(&RTDialogueLines::line_compilation_agent, STORE_POINTER_dialogue_line(dl), desc); } }
void RTDialogueLines::line_compilation_agent(compilation_subtask *ct) { dialogue_line *dl = RETRIEVE_POINTER_dialogue_line(ct->data); current_sentence = dl->compilation_data.where_created; package_request *PR = RTDialogueLines::package(dl); inter_name *array_iname = RTDialogueLines::line_array_iname(dl); int make_availability_function = FALSE, make_speaker_function = FALSE, make_interlocutor_function = FALSE, make_mentioning_function = FALSE, make_action_function = FALSE; linked_list *now_list = NEW_LINKED_LIST(parse_node); linked_list *before_list = NEW_LINKED_LIST(parse_node); linked_list *after_list = NEW_LINKED_LIST(parse_node); Scan the clauses further3.1; Hierarchy::apply_metadata_from_iname(PR, LINE_ARRAY_MD_HL, array_iname); packaging_state save = EmitArrays::begin_word(array_iname, K_value); Write the availability entry3.2; Write the speaker entry3.3; Write the interlocutor entry3.4; Write the speech entry3.5; Write the style entry3.6; Write the mentioning entry3.7; Write the action entry3.8; Write the flags entry3.9; EmitArrays::end(save); if (make_availability_function) Compile the available function3.10; if (make_speaker_function) Compile the speaker function3.11; if (make_interlocutor_function) Compile the interlocutor function3.12; if (make_mentioning_function) Compile the mentioning function3.13; if (make_action_function) Compile the action function3.14; }
§3.1. Scan the clauses further3.1 =
for (parse_node *clause = dl->line_at->down; clause; clause = clause->next) { if (Node::is(clause, DIALOGUE_CLAUSE_NT)) { int c = Annotations::read_int(clause, dialogue_line_clause_ANNOT); switch (c) { case NOW_DLC: ADD_TO_LINKED_LIST(clause, parse_node, now_list); break; case BEFORE_DLC: ADD_TO_LINKED_LIST(clause, parse_node, before_list); break; case AFTER_DLC: ADD_TO_LINKED_LIST(clause, parse_node, after_list); break; } } }
- This code is used in §3.
§3.2. Write the availability entry3.2 =
int conditions = 0; for (parse_node *clause = dl->line_at->down; clause; clause = clause->next) { int c = Annotations::read_int(clause, dialogue_line_clause_ANNOT); if ((c == IF_DLC) || (c == UNLESS_DLC)) conditions++; } if (conditions > 0) { make_availability_function = TRUE; EmitArrays::iname_entry(RTDialogueLines::available_fn_iname(dl)); } else { EmitArrays::numeric_entry(0); }
- This code is used in §3.
§3.3. Write the speaker entry3.3 =
if (dl->speaker_description) { instance *I = Rvalues::to_instance(dl->speaker_description); if (I) { EmitArrays::iname_entry(RTInstances::value_iname(I)); } else { make_speaker_function = TRUE; EmitArrays::iname_entry(RTDialogueLines::speaker_fn_iname(dl)); } } else if (dl->speaker_is_player) { EmitArrays::numeric_entry(1); } else { EmitArrays::numeric_entry(0); }
- This code is used in §3.
§3.4. Write the interlocutor entry3.4 =
if (dl->interlocutor_description) { instance *I = Rvalues::to_instance(dl->interlocutor_description); if (I) { EmitArrays::iname_entry(RTInstances::value_iname(I)); } else { make_interlocutor_function = TRUE; EmitArrays::iname_entry(RTDialogueLines::interlocutor_fn_iname(dl)); } } else if (dl->interlocutor_is_player) { EmitArrays::numeric_entry(1); } else { EmitArrays::numeric_entry(0); }
- This code is used in §3.
§3.5. Write the speech entry3.5 =
if (<quoted-text-with-subs>(dl->speech_text)) { stack_frame *frame = Frames::new_nonphrasal(); frame->shared_variables = SharedVariables::new_access_list(); if (AV_performing_dialogue) SharedVariables::add_set_to_access_list( Frames::get_shared_variable_access_list(), AV_performing_dialogue->activity_variables); text_substitution *ts = TextSubstitutions::new_text_substitution(dl->speech_text, frame, NULL, -1); EmitArrays::iname_entry(TextSubstitutions::value_iname(ts)); Frames::remove_nonphrase_stack_frame(); } else { parse_node *text = NULL; if (<s-literal>(dl->speech_text)) { text = <<rp>>; } else { internal_error("somehow not a literal text"); } CompileValues::to_array_entry_of_kind(text, K_text); }
- This code is used in §3.
§3.6. Write the style entry3.6 =
EmitArrays::iname_entry(RTInstances::value_iname(dl->how_performed->as_instance));
- This code is used in §3.
§3.7. Write the mentioning entry3.7 =
int L = LinkedLists::len(dl->mentioning); if (L == 0) { EmitArrays::numeric_entry(0); } else if ((L == 1) && (Rvalues::to_instance(FIRST_IN_LINKED_LIST(parse_node, dl->mentioning)))) { instance *I = Rvalues::to_instance(FIRST_IN_LINKED_LIST(parse_node, dl->mentioning)); EmitArrays::iname_entry(RTInstances::value_iname(I)); } else { make_mentioning_function = TRUE; EmitArrays::iname_entry(RTDialogueLines::mentioning_fn_iname(dl)); }
- This code is used in §3.
§3.8. Write the action entry3.8 =
if ((LinkedLists::len(now_list) > 0) || (LinkedLists::len(before_list) > 0) || (LinkedLists::len(after_list) > 0)) make_action_function = TRUE; if (make_action_function) { EmitArrays::iname_entry(RTDialogueLines::action_fn_iname(dl)); } else { EmitArrays::numeric_entry(0); }
- This code is used in §3.
§3.9. Write the flags entry3.9 =
inter_ti flags = 0; if (dl->narration) flags |= 1; if (dl->without_speaking) flags |= 2; EmitArrays::numeric_entry(flags);
- This code is used in §3.
§3.10. Compile the available function3.10 =
packaging_state save = Functions::begin(RTDialogueLines::available_fn_iname(dl)); Check the if and unless conditions3.10.1; EmitCode::rtrue(); Functions::end(save);
- This code is used in §3.
§3.10.1. Check the if and unless conditions3.10.1 =
current_sentence = dl->line_at; for (parse_node *clause = dl->line_at->down; clause; clause = clause->next) { wording CW = Node::get_text(clause); int c = Annotations::read_int(clause, dialogue_line_clause_ANNOT); switch (c) { case IF_DLC: case UNLESS_DLC: { <dialogue-beat-clause>(CW); wording A = GET_RW(<dialogue-beat-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_DLC) { EmitCode::inv(NOT_BIP); EmitCode::down(); } CompileValues::to_code_val_of_kind(cond, K_truth_state); if (c == IF_DLC) { EmitCode::up(); } EmitCode::code(); EmitCode::down(); EmitCode::rfalse(); EmitCode::up(); EmitCode::up(); } } break; } } }
- This code is used in §3.10.
§3.11. Compile the speaker function3.11 =
packaging_state save = Functions::begin(RTDialogueLines::speaker_fn_iname(dl)); local_variable *speaker = LocalVariables::new_internal_commented(I"speaker", I"potential speaker"); inter_symbol *speaker_s = LocalVariables::declare(speaker); parse_node *desc = dl->speaker_description; instance *I = Rvalues::to_instance(desc); EmitCode::inv(IF_BIP); EmitCode::down(); if (I) { EmitCode::inv(EQ_BIP); EmitCode::down(); EmitCode::val_symbol(K_value, speaker_s); EmitCode::val_iname(K_value, RTInstances::value_iname(I)); EmitCode::up(); } else { pcalc_prop *prop = Descriptions::to_proposition(desc); if (prop) { TypecheckPropositions::type_check(prop, TypecheckPropositions::tc_no_problem_reporting()); CompilePropositions::to_test_as_condition( Lvalues::new_LOCAL_VARIABLE(EMPTY_WORDING, speaker), prop); } else { internal_error("cannot test"); } } EmitCode::code(); EmitCode::down(); EmitCode::rtrue(); EmitCode::up(); EmitCode::up(); EmitCode::rfalse(); Functions::end(save);
- This code is used in §3.
§3.12. Compile the interlocutor function3.12 =
packaging_state save = Functions::begin(RTDialogueLines::interlocutor_fn_iname(dl)); local_variable *interlocutor = LocalVariables::new_internal_commented(I"interlocutor", I"potential interlocutor"); inter_symbol *interlocutor_s = LocalVariables::declare(interlocutor); parse_node *desc = dl->interlocutor_description; instance *I = Rvalues::to_instance(desc); EmitCode::inv(IF_BIP); EmitCode::down(); if (I) { EmitCode::inv(EQ_BIP); EmitCode::down(); EmitCode::val_symbol(K_value, interlocutor_s); EmitCode::val_iname(K_value, RTInstances::value_iname(I)); EmitCode::up(); } else { pcalc_prop *prop = Descriptions::to_proposition(desc); if (prop) { TypecheckPropositions::type_check(prop, TypecheckPropositions::tc_no_problem_reporting()); CompilePropositions::to_test_as_condition( Lvalues::new_LOCAL_VARIABLE(EMPTY_WORDING, interlocutor), prop); } else { internal_error("cannot test"); } } EmitCode::code(); EmitCode::down(); EmitCode::rtrue(); EmitCode::up(); EmitCode::up(); EmitCode::rfalse(); Functions::end(save);
- This code is used in §3.
§3.13. Compile the mentioning function3.13 =
packaging_state save = Functions::begin(RTDialogueLines::mentioning_fn_iname(dl)); local_variable *obj = LocalVariables::new_internal_commented(I"obj", I"mentioned object"); inter_symbol *obj_s = LocalVariables::declare(obj); parse_node *desc; LOOP_OVER_LINKED_LIST(desc, parse_node, dl->mentioning) { instance *I = Rvalues::to_instance(desc); if (I) { EmitCode::call(Hierarchy::find(DIRECTOR_ADD_LIVE_SUBJECT_LIST_HL)); EmitCode::down(); EmitCode::val_iname(K_value, RTInstances::value_iname(I)); EmitCode::up(); } else { CompileLoops::through_matches(desc, obj); EmitCode::code(); EmitCode::down(); EmitCode::call(Hierarchy::find(DIRECTOR_ADD_LIVE_SUBJECT_LIST_HL)); EmitCode::down(); EmitCode::val_symbol(K_value, obj_s); EmitCode::up(); EmitCode::up(); EmitCode::up(); } } Functions::end(save);
- This code is used in §3.
§3.14. Compile the action function3.14 =
packaging_state save = Functions::begin(RTDialogueLines::action_fn_iname(dl)); local_variable *task = LocalVariables::new_internal_commented(I"task", I"what to do"); inter_symbol *task_s = LocalVariables::declare(task); local_variable *speaker = LocalVariables::new_internal_commented(I"speaker", I"who says this"); LocalVariables::set_kind(speaker, K_object); EmitCode::inv(SWITCH_BIP); EmitCode::down(); EmitCode::val_symbol(K_value, task_s); EmitCode::code(); EmitCode::down(); if (LinkedLists::len(now_list) > 0) { EmitCode::inv(CASE_BIP); EmitCode::down(); EmitCode::val_number(1); EmitCode::code(); EmitCode::down(); parse_node *clause; LOOP_OVER_LINKED_LIST(clause, parse_node, now_list) Take action on this now clause3.14.1; EmitCode::up(); EmitCode::up(); } if (LinkedLists::len(before_list) > 0) { EmitCode::inv(CASE_BIP); EmitCode::down(); EmitCode::val_number(2); EmitCode::code(); EmitCode::down(); parse_node *clause; LOOP_OVER_LINKED_LIST(clause, parse_node, before_list) Take action on this action clause3.14.3; EmitCode::up(); EmitCode::up(); } if (LinkedLists::len(after_list) > 0) { EmitCode::inv(CASE_BIP); EmitCode::down(); EmitCode::val_number(3); EmitCode::code(); EmitCode::down(); parse_node *clause; LOOP_OVER_LINKED_LIST(clause, parse_node, after_list) Take action on this action clause3.14.3; EmitCode::up(); EmitCode::up(); } EmitCode::up(); EmitCode::up(); EmitCode::rtrue(); Functions::end(save);
- This code is used in §3.
§3.14.1. Take action on this now clause3.14.1 =
wording CW = Node::get_text(clause); <dialogue-line-clause>(CW); wording NW = GET_RW(<dialogue-line-clause>, 1); CompileBlocksAndLines::compile_a_now(NW);
- This code is used in §3.14.
<silently-modifier> ::= silently ... | ... silently
- This is Preform grammar, not regular C code.
§3.14.3. Take action on this action clause3.14.3 =
wording CW = Node::get_text(clause); <dialogue-line-clause>(CW); wording AW = GET_RW(<dialogue-line-clause>, 1); int silently = FALSE; if (<silently-modifier>(AW)) { silently = TRUE; AW = GET_RW(<silently-modifier>, 1); } if (<s-action-pattern-as-value>(AW)) { parse_node *supplied = <<rp>>; if (Dash::check_value(supplied, K_stored_action)) { if (Rvalues::is_CONSTANT_of_kind(supplied, K_stored_action)) { explicit_action *ea = Node::get_constant_explicit_action(supplied); if (ea->actor == NULL) { parse_node *actor = Lvalues::new_LOCAL_VARIABLE(EMPTY_WORDING, speaker); Dash::check_value(actor, K_object); ea->actor = Lvalues::new_LOCAL_VARIABLE(EMPTY_WORDING, speaker); } CSIInline::compile_try_action(ea, silently); } else { EmitCode::call(Hierarchy::find(STORED_ACTION_TY_TRY_HL)); EmitCode::down(); CompileValues::to_code_val_of_kind(supplied, K_stored_action); if (silently) EmitCode::val_true(); EmitCode::up(); } EmitCode::inv(IF_BIP); EmitCode::down(); EmitCode::inv(NE_BIP); EmitCode::down(); EmitCode::val_iname(K_value, Hierarchy::find(REASON_THE_ACTION_FAILED_HL)); EmitCode::val_number(0); EmitCode::up(); EmitCode::code(); EmitCode::down(); EmitCode::rfalse(); EmitCode::up(); EmitCode::up(); } else { internal_error("oops"); } } else { Problems::quote_source(1, current_sentence); Problems::quote_wording(2, AW); StandardProblems::handmade_problem(Task::syntax_tree(), _p_(...)); Problems::issue_problem_segment( "This dialogue line (%1) wants to try the action '%2', " "but I can't make sense of that."); Problems::issue_problem_end(); }
- This code is used in §3.14 (twice).
instance *RTDialogueLines::speaker_instance(dialogue_line *dl) { if ((dl) && (dl->speaker_description)) return Rvalues::to_instance(dl->speaker_description); return NULL; }