- Source
- Compiler Modules
- core
- Chapter 22: Phrases
- Timed Phrases
Another way phrases can be invoked is as timed events, which need no special Inform data structure and are simply compiled into a pair of timetable I6 arrays to be processed at run-time.
§2. The timing of an event records the time at which a phrase should spontaneously happen. This is ordinarily a time value, in minutes from 12 midnight, for a phrase happening at a specific time — for instance, one defined as "At 9:00 AM: ..." But two values are special:
define NOT_A_TIMED_EVENT -1 as for the vast majority of phrases define NO_FIXED_TIME -2 for phrases like "When the clock strikes: ..." define NOT_AN_EVENT -3 not even syntactically
§3. And here we record where events are used:
typedef struct use_as_event { struct parse_node *where_triggered; sentence which specifies when this occurs struct use_as_event *next; MEMORY_MANAGEMENT } use_as_event;
The structure use_as_event is accessed in 3/pd, 5/lp, 5/ut, 5/un, 5/ins, 6/rlt, 6/nv, 7/ns, 7/oaf, 7/rs, 9/tfa, 9/tbath, 9/rpt, 9/tc, 9/ma, 9/rk, 9/ass, 9/imp, 9/pd, 10/teav, 10/cap, 11/ap, 11/pr, 11/bas, 11/tc, 11/sm, 12/dtd, 12/cdp, 14/rv, 14/lv, 14/cn, 14/ds, 14/ds2, 15/cp, 16/is, 16/in, 19/tb, 19/rsft, 19/tod, 20/eq, 21/rl, 21/rl2, 21/fao, 21/rps, 21/sv, 21/ac, 22/ph, 22/tp, 23/ad, 24/lv, 24/sf, 25/in, 25/pi, 25/cii, 25/cp, 26/uo, 26/tti, 26/pc, 26/ts, 27/cm and here.
§4. Timed events are stored in two simple arrays, processed by run-time code.
void Phrases::Timed::TimedEventsTable(void) { inter_name *iname = Hierarchy::find(TIMEDEVENTSTABLE_HL); packaging_state save = Emit::named_table_array_begin(iname, K_value); int when_count = 0; phrase *ph; LOOP_OVER(ph, phrase) { int t = Phrases::Usage::get_timing_of_event(&(ph->usage_data)); if (t == NOT_A_TIMED_EVENT) continue; if (t == NO_FIXED_TIME) when_count++; else Emit::array_iname_entry(Phrases::iname(ph)); } for (int i=0; i<when_count+1; i++) { Emit::array_numeric_entry(0); Emit::array_numeric_entry(0); } Emit::array_end(save); Hierarchy::make_available(Emit::tree(), iname); } void Phrases::Timed::TimedEventTimesTable(void) { inter_name *iname = Hierarchy::find(TIMEDEVENTTIMESTABLE_HL); packaging_state save = Emit::named_table_array_begin(iname, K_number); int when_count = 0; phrase *ph; LOOP_OVER(ph, phrase) { int t = Phrases::Usage::get_timing_of_event(&(ph->usage_data)); if (t == NOT_A_TIMED_EVENT) continue; if (t == NO_FIXED_TIME) when_count++; else Emit::array_numeric_entry((inter_t) t); } for (int i=0; i<when_count+1; i++) { Emit::array_numeric_entry(0); Emit::array_numeric_entry(0); } Emit::array_end(save); Hierarchy::make_available(Emit::tree(), iname); }
The function Phrases::Timed::TimedEventsTable is used in 1/htc (§2.8), 22/cs (§11).
The function Phrases::Timed::TimedEventTimesTable is used in 1/htc (§2.8), 22/cs (§11).
§5. That's it, really: everything else is just indexing.
void Phrases::Timed::note_usage(phrase *ph, parse_node *at) { int t = Phrases::Usage::get_timing_of_event(&(ph->usage_data)); if (t == NO_FIXED_TIME) { use_as_event *uae = CREATE(use_as_event); uae->where_triggered = at; uae->next = NULL; use_as_event *prev = ph->usage_data.uses_as_event; if (prev == NULL) ph->usage_data.uses_as_event = uae; else { while ((prev) && (prev->next)) prev = prev->next; prev->next = uae; } } }
The function Phrases::Timed::note_usage is used in 25/cii (§3.1.1.4.12).
§6. An interesting case where the Problem is arguably only a warning and arguably shouldn't block compilation. Then again...
void Phrases::Timed::check_for_unused(void) { phrase *ph; LOOP_OVER(ph, phrase) if (Phrases::Usage::get_timing_of_event(&(ph->usage_data)) == NO_FIXED_TIME) { if (ph->usage_data.uses_as_event == NULL) { current_sentence = ph->declaration_node; Problems::Issue::sentence_problem(Task::syntax_tree(), _p_(PM_UnusedTimedEvent), "this sets up a timed event which is never used", "since you never use any of the phrases which could cause it. " "(A timed event is just a name, and it needs other instructions " "elsewhere before it can have any effect.)"); } } }
The function Phrases::Timed::check_for_unused is used in 1/htc (§2.8).
§7. And here's the actual index segment.
void Phrases::Timed::index(OUTPUT_STREAM) { int when_count = 0, tt_count = 0; <Index events with no specific time 7.1>; <Index timetabled events 7.2>; if ((when_count == 0) && (tt_count == 0)) { HTML_OPEN("p"); WRITE("<i>None.</i>"); HTML_CLOSE("p"); } }
The function Phrases::Timed::index appears nowhere else.
§7.1.
<Index events with no specific time 7.1> =
phrase *ph; LOOP_OVER(ph, phrase) { int t = Phrases::Usage::get_timing_of_event(&(ph->usage_data)); if (t == NO_FIXED_TIME) { if (when_count == 0) { HTML_OPEN("p"); WRITE("<i>Events with no specific time</i>"); HTML_CLOSE("p"); } when_count++; HTML_OPEN_WITH("p", "class=\"tightin2\""); Phrases::Usage::index_preamble(OUT, &(ph->usage_data)); if ((ph->declaration_node) && (Wordings::nonempty(ParseTree::get_text(ph->declaration_node)))) Index::link(OUT, Wordings::first_wn(ParseTree::get_text(ph->declaration_node))); WRITE(" (where triggered: "); use_as_event *uae; for (uae = ph->usage_data.uses_as_event; uae; uae=uae->next) Index::link(OUT, Wordings::first_wn(ParseTree::get_text(uae->where_triggered))); WRITE(")"); HTML_CLOSE("p"); } }
This code is used in §7.
§7.2.
<Index timetabled events 7.2> =
phrase *ph; LOOP_OVER(ph, phrase) { int t = Phrases::Usage::get_timing_of_event(&(ph->usage_data)); if (t >= 0) { i.e., an actual time of day in minutes since midnight if (tt_count == 0) { HTML_OPEN("p"); WRITE("<i>Timetable</i>"); HTML_CLOSE("p"); } tt_count++; HTML_OPEN_WITH("p", "class=\"in2\""); Phrases::Usage::index_preamble(OUT, &(ph->usage_data)); if ((ph->declaration_node) && (Wordings::nonempty(ParseTree::get_text(ph->declaration_node)))) Index::link(OUT, Wordings::first_wn(ParseTree::get_text(ph->declaration_node))); HTML_CLOSE("p"); } }
This code is used in §7.