To issue problem messages when parsing malformed I6-syntax code.
§1. Errors like these used to be basically failed assertions, but inevitably people reported that as a bug (Mantis 0001596). It was never intended that Inform 6-syntax hacking should be part of the outside-facing Inform language; but if you leave power tools just lying around, people will eventually pick them up and wonder what the red button marked "danger" does.
Note that i6_syntax_error_location is initially uninitialised and thus has undefined contents, so we take care to blank it out if it is read before being written to for the first time.
text_provenance i6_syntax_error_location; int i6_syntax_error_location_set = FALSE; text_provenance I6Errors::get_current_location(void) { if (i6_syntax_error_location_set == FALSE) I6Errors::clear_current_location(); return i6_syntax_error_location; } void I6Errors::clear_current_location(void) { I6Errors::set_current_location(Provenance::nowhere()); } void I6Errors::set_current_location(text_provenance where) { i6_syntax_error_location_set = TRUE; i6_syntax_error_location = where; } void I6Errors::set_current_location_near_splat(inter_tree_node *P) { I6Errors::clear_current_location(); if ((P) && (Inode::is(P, SPLAT_IST))) I6Errors::set_current_location(SplatInstruction::provenance(P)); }
§2. The issuing mechanism, or rather, the mechanism used if the main Inform compiler doesn't gazump us (in order to provide something better-looking in the GUI apps).
int i6_syntax_error_count = 0; void I6Errors::issue(char *message, text_stream *quote) { text_provenance at = I6Errors::get_current_location(); #ifdef CORE_MODULE SourceProblems::I6_level_error(message, quote, at); #endif #ifndef CORE_MODULE if (Provenance::is_somewhere(at)) { filename *F = Provenance::get_filename(at); TEMPORARY_TEXT(M) WRITE_TO(M, message, quote); Errors::at_position_S(M, F, Provenance::get_line(at)); DISCARD_TEXT(M) } else { Errors::with_text(message, quote); } #endif i6_syntax_error_count++; } void I6Errors::reset_count(void) { I6Errors::clear_current_location(); i6_syntax_error_count = 0; } int I6Errors::errors_occurred(void) { if (i6_syntax_error_count != 0) return TRUE; return FALSE; }
§3. The functions below are for errors detected when parsing text into schemas, or when emitting code from them.
Note that the parsing_errors field of a schema is null until the first error is detected — which, of course, it usually isn't. It holds a linked list of these:
typedef struct schema_parsing_error { struct text_stream *message; struct text_provenance provenance; CLASS_DEFINITION } schema_parsing_error;
- The structure schema_parsing_error is accessed in 2/is and here.
void I6Errors::issue_at_node(inter_schema_node *at, text_stream *message) { if (at->parent_schema->parsing_errors == NULL) at->parent_schema->parsing_errors = NEW_LINKED_LIST(schema_parsing_error); schema_parsing_error *err = CREATE(schema_parsing_error); err->message = Str::duplicate(message); if (at) { if (Provenance::is_somewhere(at->provenance)) err->provenance = at->provenance; else if (at->parent_schema) err->provenance = at->parent_schema->provenance; else err->provenance = Provenance::nowhere(); } else { err->provenance = Provenance::nowhere(); } ADD_TO_LINKED_LIST(err, schema_parsing_error, at->parent_schema->parsing_errors); LOG("Schema error: %S\n", message); if ((at->parent_schema) && (Provenance::is_somewhere(at->parent_schema->provenance))) LOG("Schema provenance %f, line %d\n", Provenance::get_filename(at->parent_schema->provenance), Provenance::get_line(at->parent_schema->provenance)); LOG("$1\n", at->parent_schema); }
§5. That function of course caches schema errors for playback later: well, here's the later. Unless the main Inform compiler takes over from us, the result will be drastic, halting what is presumably the inter tool:
void I6Errors::internal_error_on_schema_errors(inter_schema *sch) { if (LinkedLists::len(sch->parsing_errors) > 0) { #ifdef CORE_MODULE SourceProblems::inter_schema_errors(sch); #endif #ifndef CORE_MODULE WRITE_TO(STDERR, "Parsing error(s) in the internal schema '%S':\n", sch->converted_from); schema_parsing_error *err; LOOP_OVER_LINKED_LIST(err, schema_parsing_error, sch->parsing_errors) WRITE_TO(STDERR, "- %S\n", err->message); exit(1); #endif } }