mirror of
https://github.com/ganelson/inform.git
synced 2024-06-30 22:14:58 +03:00
commit
8e4b0d14c7
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,16 +1,17 @@
|
|||
Inform 7 v10.2.0 has started.
|
||||
I've now read your source text, which is 12 words long.
|
||||
I've also read Basic Inform by Graham Nelson, which is 7792 words long.
|
||||
I've also read English Language by Graham Nelson, which is 2330 words long.
|
||||
I've also read Standard Rules by Graham Nelson, which is 34311 words long.
|
||||
I've also read version 1 of Basic Inform by Graham Nelson, which is 7888 words long.
|
||||
I've also read version 1 of English Language by Graham Nelson, which is 2330 words long.
|
||||
I've also read version 6 of Standard Rules by Graham Nelson, which is 34398 words long.
|
||||
Problem__ PM_I6SyntaxError
|
||||
>--> Inform 6 syntax error near here (source text, line 24): this is not an
|
||||
Inform 6 directive.
|
||||
Problem__ PM_I6SyntaxError
|
||||
>--> Inform 6 syntax error near here (source text, line 25): this Inform 6
|
||||
directive is not supported in kits or '(-' inclusions: 'Link;' (only
|
||||
#Ifdef, #Ifndef, #Iftrue, #Ifnot, #Endif, #Stub, Constant, Global, Array,
|
||||
Attribute, Property, Verb, Fake_action, Object, Default are supported).
|
||||
#Ifdef, #Ifndef, #Iftrue, #Ifnot, #Endif, #OrigSource, #Stub, Constant,
|
||||
Global, Array, Attribute, Property, Verb, Fake_action, Object, Default are
|
||||
supported).
|
||||
Problem__ PM_I6SyntaxError
|
||||
>--> Inform 6 syntax error near here (source text, line 36): in a +namespace
|
||||
annotation, the 'access' must be 'private' or 'public', not 'whimsical'.
|
||||
|
|
|
@ -46,7 +46,12 @@ always hangs from a single top-level |CODE_BLOCK_NT|.
|
|||
=
|
||||
void CompileBlocksAndLines::full_definition_body(int statement_count, parse_node *body,
|
||||
int allow_implied_newlines) {
|
||||
CompileBlocksAndLines::code_block(statement_count, body, TRUE, allow_implied_newlines);
|
||||
text_provenance last_loc = Provenance::nowhere();
|
||||
CompileBlocksAndLines::code_block(statement_count, body, TRUE, allow_implied_newlines, &last_loc);
|
||||
if (Provenance::is_somewhere(last_loc)) {
|
||||
last_loc = Provenance::nowhere();
|
||||
EmitCode::origsource(&last_loc);
|
||||
}
|
||||
}
|
||||
|
||||
@ See //words: Nonterminals// for an explanation of what it means for a nonterminal
|
||||
|
@ -57,7 +62,7 @@ most "likely" interpretation.
|
|||
|
||||
=
|
||||
int CompileBlocksAndLines::code_block(int statement_count, parse_node *block, int top_level,
|
||||
int allow_implied_newlines) {
|
||||
int allow_implied_newlines, text_provenance *last_loc) {
|
||||
if (block) {
|
||||
if (Node::get_type(block) != CODE_BLOCK_NT) internal_error("not a code block");
|
||||
int saved_mult = <s-value-uncached>->multiplicitous;
|
||||
|
@ -68,7 +73,7 @@ int CompileBlocksAndLines::code_block(int statement_count, parse_node *block, in
|
|||
for (parse_node *p = block->down; p; p = p->next)
|
||||
statement_count =
|
||||
CompileBlocksAndLines::code_line(statement_count, p, singleton,
|
||||
allow_implied_newlines);
|
||||
allow_implied_newlines, last_loc);
|
||||
<s-value-uncached>->multiplicitous = saved_mult;
|
||||
}
|
||||
return statement_count;
|
||||
|
@ -97,7 +102,7 @@ So, then, this is called on each child node of a |CODE_BLOCK_NT| in turn:
|
|||
|
||||
=
|
||||
int CompileBlocksAndLines::code_line(int statement_count, parse_node *p, int as_singleton,
|
||||
int allow_implied_newlines) {
|
||||
int allow_implied_newlines, text_provenance *last_loc) {
|
||||
compiling_single_line_block = as_singleton;
|
||||
control_structure_phrase *csp = Node::get_control_structure_used(p);
|
||||
parse_node *to_compile = p;
|
||||
|
@ -107,6 +112,7 @@ int CompileBlocksAndLines::code_line(int statement_count, parse_node *p, int as_
|
|||
}
|
||||
statement_count++;
|
||||
@<Compile a comment about this line@>;
|
||||
@<Compile a location reference for this line@>;
|
||||
int L = EmitCode::level();
|
||||
@<Compile the head@>;
|
||||
@<Compile the midriff@>;
|
||||
|
@ -125,6 +131,19 @@ int CompileBlocksAndLines::code_line(int statement_count, parse_node *p, int as_
|
|||
DISCARD_TEXT(C)
|
||||
}
|
||||
|
||||
@<Compile a location reference for this line@> =
|
||||
source_location sl = Wordings::location(Node::get_text(to_compile));
|
||||
if (sl.file_of_origin) {
|
||||
TEMPORARY_TEXT(fname);
|
||||
WRITE_TO(fname, "%f", sl.file_of_origin->name);
|
||||
text_provenance loc = Provenance::at_file_and_line(fname, sl.line_number);
|
||||
DISCARD_TEXT(fname);
|
||||
if (Str::ne(loc.textual_filename, last_loc->textual_filename) || loc.line_number != last_loc->line_number) {
|
||||
*last_loc = loc;
|
||||
EmitCode::origsource(last_loc);
|
||||
}
|
||||
}
|
||||
|
||||
@h Head code for lines.
|
||||
We divide the work of compiling the line into "head" code, "midriff" code
|
||||
and then "tail" code. For the head, there's usually nothing to do, except
|
||||
|
@ -260,14 +279,14 @@ is false:
|
|||
EmitCode::down();
|
||||
CodeBlocks::open_code_block();
|
||||
statement_count = CompileBlocksAndLines::code_block(statement_count,
|
||||
p->down->next, FALSE, allow_implied_newlines);
|
||||
p->down->next, FALSE, allow_implied_newlines, last_loc);
|
||||
if (p->down->next->next) {
|
||||
EmitCode::up();
|
||||
EmitCode::code();
|
||||
EmitCode::down();
|
||||
CodeBlocks::divide_code_block();
|
||||
statement_count = CompileBlocksAndLines::code_block(statement_count,
|
||||
p->down->next->next, FALSE, allow_implied_newlines);
|
||||
p->down->next->next, FALSE, allow_implied_newlines, last_loc);
|
||||
}
|
||||
CodeBlocks::close_code_block();
|
||||
EmitCode::up();
|
||||
|
@ -417,7 +436,7 @@ of |downs| is how many times we have called |Produce::down|.
|
|||
EmitCode::code();
|
||||
EmitCode::down();
|
||||
statement_count = CompileBlocksAndLines::code_block(statement_count,
|
||||
ow_node, FALSE, allow_implied_newlines);
|
||||
ow_node, FALSE, allow_implied_newlines, last_loc);
|
||||
if (final_flag == FALSE) {
|
||||
EmitCode::up();
|
||||
EmitCode::code();
|
||||
|
@ -429,7 +448,7 @@ of |downs| is how many times we have called |Produce::down|.
|
|||
|
||||
@<Handle a pointery default@> =
|
||||
statement_count = CompileBlocksAndLines::code_block(statement_count, ow_node,
|
||||
FALSE, allow_implied_newlines);
|
||||
FALSE, allow_implied_newlines, last_loc);
|
||||
|
||||
@<End a pointery switch@> =
|
||||
while (downs-- > 0) EmitCode::up();
|
||||
|
@ -452,7 +471,7 @@ of |downs| is how many times we have called |Produce::down|.
|
|||
EmitCode::code();
|
||||
EmitCode::down();
|
||||
statement_count = CompileBlocksAndLines::code_block(statement_count,
|
||||
ow_node, FALSE, allow_implied_newlines);
|
||||
ow_node, FALSE, allow_implied_newlines, last_loc);
|
||||
EmitCode::up();
|
||||
EmitCode::up();
|
||||
|
||||
|
@ -462,7 +481,7 @@ of |downs| is how many times we have called |Produce::down|.
|
|||
EmitCode::code();
|
||||
EmitCode::down();
|
||||
statement_count = CompileBlocksAndLines::code_block(statement_count,
|
||||
ow_node, FALSE, allow_implied_newlines);
|
||||
ow_node, FALSE, allow_implied_newlines, last_loc);
|
||||
EmitCode::up();
|
||||
EmitCode::up();
|
||||
|
||||
|
@ -522,7 +541,7 @@ inline definitions for "say if" and similar.
|
|||
|
||||
@<Compile a say tail@> =
|
||||
statement_count = CompileBlocksAndLines::code_block(statement_count, p,
|
||||
FALSE, allow_implied_newlines);
|
||||
FALSE, allow_implied_newlines, last_loc);
|
||||
|
||||
TEMPORARY_TEXT(SAYL)
|
||||
WRITE_TO(SAYL, ".");
|
||||
|
@ -546,7 +565,7 @@ inline definitions for "say if" and similar.
|
|||
@<Compile a loop tail@> =
|
||||
CodeBlocks::open_code_block();
|
||||
statement_count = CompileBlocksAndLines::code_block(statement_count, p->down->next,
|
||||
FALSE, allow_implied_newlines);
|
||||
FALSE, allow_implied_newlines, last_loc);
|
||||
while (EmitCode::level() > L) EmitCode::up();
|
||||
CodeBlocks::close_code_block();
|
||||
|
||||
|
|
|
@ -70,6 +70,14 @@ void EmitCode::comment(text_stream *text) {
|
|||
(inter_ti) EmitCode::level()));
|
||||
}
|
||||
|
||||
@h OrigSource directives.
|
||||
|
||||
=
|
||||
void EmitCode::origsource(text_provenance *from) {
|
||||
Produce::guard(OrigSourceInstruction::new_from_provenance(EmitCode::at(), *from,
|
||||
(inter_ti) EmitCode::level(), NULL));
|
||||
}
|
||||
|
||||
@h In value context.
|
||||
These functions all generate a |val| opcode:
|
||||
|
||||
|
|
|
@ -30,17 +30,21 @@ package main _plain
|
|||
package Falsity_fn _function
|
||||
package Falsity _code
|
||||
code
|
||||
origsource "inter/Tests/General/Assim.intert" 10
|
||||
inv !return
|
||||
val 0
|
||||
origsource
|
||||
package Demo_fn _function
|
||||
package Demo _code
|
||||
local x
|
||||
local y
|
||||
code
|
||||
origsource "inter/Tests/General/Assim.intert" 11
|
||||
inv !return
|
||||
inv !plus
|
||||
val x
|
||||
val y
|
||||
origsource
|
||||
package arrays _submodule
|
||||
package XA_arr _plain
|
||||
constant (list of unchecked) XA = { 2, 4, 56 } __assimilated
|
||||
|
@ -65,13 +69,17 @@ package main _plain
|
|||
local x1
|
||||
local x2
|
||||
code
|
||||
origsource "inter/Tests/General/Assim.intert" 23
|
||||
inv !return
|
||||
val 0
|
||||
origsource
|
||||
package Peach_fn _function
|
||||
package Peach _code
|
||||
code
|
||||
origsource "inter/Tests/General/Assim.intert" 24
|
||||
inv !return
|
||||
val 0
|
||||
origsource
|
||||
package marmorial_prop _property
|
||||
constant property_id = 0
|
||||
property (int2) marmorial __assimilated
|
||||
|
|
|
@ -11,6 +11,7 @@ Constant Budger = 32738;
|
|||
Constant Danza = (2 + 34);
|
||||
Constant Sahara = (Danza + Bidger + 1);
|
||||
#Ifdef TARGET_ZCODE;
|
||||
#OrigSource "inter/final-module/Chapter 4/Final Inform 6.w" 155;
|
||||
Global max_z_object;
|
||||
#Ifdef Z__Region;
|
||||
[ OC__Cl obj cla j a n objflag;
|
||||
|
@ -75,6 +76,7 @@ Global max_z_object;
|
|||
rfalse;
|
||||
];
|
||||
#Endif;
|
||||
#OrigSource;
|
||||
#Endif;
|
||||
[ DebugAttribute a anames str;
|
||||
print "<attribute ", a, ">";
|
||||
|
|
|
@ -22,6 +22,7 @@ Class K_mica
|
|||
class K_stone
|
||||
;
|
||||
#Ifdef TARGET_ZCODE;
|
||||
#OrigSource "inter/final-module/Chapter 4/Final Inform 6.w" 155;
|
||||
Global max_z_object;
|
||||
#Ifdef Z__Region;
|
||||
[ OC__Cl obj cla j a n objflag;
|
||||
|
@ -86,6 +87,7 @@ Global max_z_object;
|
|||
rfalse;
|
||||
];
|
||||
#Endif;
|
||||
#OrigSource;
|
||||
#Endif;
|
||||
[ DebugAttribute a anames str;
|
||||
print "<attribute ", a, ">";
|
||||
|
|
|
@ -7,6 +7,7 @@ Global or_tmp_var;
|
|||
Constant Banana = 2;
|
||||
Constant Peach = Banana;
|
||||
#Ifdef TARGET_ZCODE;
|
||||
#OrigSource "inter/final-module/Chapter 4/Final Inform 6.w" 155;
|
||||
Global max_z_object;
|
||||
#Ifdef Z__Region;
|
||||
[ OC__Cl obj cla j a n objflag;
|
||||
|
@ -71,6 +72,7 @@ Global max_z_object;
|
|||
rfalse;
|
||||
];
|
||||
#Endif;
|
||||
#OrigSource;
|
||||
#Endif;
|
||||
[ DebugAttribute a anames str;
|
||||
print "<attribute ", a, ">";
|
||||
|
|
|
@ -5,6 +5,7 @@ Constant Grammar__Version 2;
|
|||
Global debug_flag;
|
||||
Global or_tmp_var;
|
||||
#Ifdef TARGET_ZCODE;
|
||||
#OrigSource "inter/final-module/Chapter 4/Final Inform 6.w" 155;
|
||||
Global max_z_object;
|
||||
#Ifdef Z__Region;
|
||||
[ OC__Cl obj cla j a n objflag;
|
||||
|
@ -69,6 +70,7 @@ Global max_z_object;
|
|||
rfalse;
|
||||
];
|
||||
#Endif;
|
||||
#OrigSource;
|
||||
#Endif;
|
||||
[ MyRoutine x y;
|
||||
return x;
|
||||
|
|
|
@ -7,6 +7,7 @@ Global or_tmp_var;
|
|||
Constant I_green = 1;
|
||||
Constant I_red = 17;
|
||||
#Ifdef TARGET_ZCODE;
|
||||
#OrigSource "inter/final-module/Chapter 4/Final Inform 6.w" 155;
|
||||
Global max_z_object;
|
||||
#Ifdef Z__Region;
|
||||
[ OC__Cl obj cla j a n objflag;
|
||||
|
@ -71,6 +72,7 @@ Global max_z_object;
|
|||
rfalse;
|
||||
];
|
||||
#Endif;
|
||||
#OrigSource;
|
||||
#Endif;
|
||||
[ DebugAttribute a anames str;
|
||||
print "<attribute ", a, ">";
|
||||
|
|
|
@ -5,6 +5,7 @@ Constant Grammar__Version 2;
|
|||
Global debug_flag;
|
||||
Global or_tmp_var;
|
||||
#Ifdef TARGET_ZCODE;
|
||||
#OrigSource "inter/final-module/Chapter 4/Final Inform 6.w" 155;
|
||||
Global max_z_object;
|
||||
#Ifdef Z__Region;
|
||||
[ OC__Cl obj cla j a n objflag;
|
||||
|
@ -69,6 +70,7 @@ Global max_z_object;
|
|||
rfalse;
|
||||
];
|
||||
#Endif;
|
||||
#OrigSource;
|
||||
#Endif;
|
||||
[ Falsity;
|
||||
return false;];
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
inter: inter/Tests/Invalid/inversion.intert, line 1: file holds Inter written for specification v0.1.2, but I expect v5.0.0
|
||||
inter: inter/Tests/Invalid/inversion.intert, line 1: file holds Inter written for specification v0.1.2, but I expect v6.0.0
|
||||
>--> version 0.1.2
|
||||
|
|
|
@ -495,13 +495,31 @@ more natural |{ ... }|.
|
|||
}
|
||||
if (node->unopened) Produce::set_level_to_current_code_block_plus(I, 0);
|
||||
|
||||
@ Note that conditional directives have already been taken care of, and that
|
||||
other Inform 6 directives are not valid inside function bodies, which is the
|
||||
only part of I6 syntax covered by schemas. Therefore:
|
||||
@ Note that conditional directives have already been taken care of. The
|
||||
only other Inform 6 directive valid inside a function body is OrigSource.
|
||||
Therefore:
|
||||
|
||||
@<Non-conditional directive@> =
|
||||
I6Errors::issue_at_node(node, I"misplaced directive");
|
||||
return;
|
||||
if (node->dir_clarifier == ORIGSOURCE_I6RW) {
|
||||
@<OrigSource directive@>;
|
||||
}
|
||||
else {
|
||||
I6Errors::issue_at_node(node, I"misplaced directive");
|
||||
return;
|
||||
}
|
||||
|
||||
@<OrigSource directive@> =
|
||||
text_stream *origfilename = NULL;
|
||||
int origlinenum = 0;
|
||||
if (node->child_node) {
|
||||
origfilename = node->child_node->expression_tokens->material;
|
||||
if (node->child_node->expression_tokens->next) {
|
||||
origlinenum = Str::atoi(node->child_node->expression_tokens->next->material, 0);
|
||||
}
|
||||
}
|
||||
inter_bookmark *IBM = Produce::at(I);
|
||||
Produce::guard(OrigSourceInstruction::new(IBM, origfilename, (unsigned int)origlinenum, (inter_ti) Produce::level(I), NULL));
|
||||
|
||||
|
||||
@ An |EVAL_ISNT| node can have any number of children, they are sequentially
|
||||
evaluated for their potential side-effects, but only the last produces a value.
|
||||
|
|
|
@ -314,6 +314,7 @@ inter_schema_token *InterSchemas::new_token(int type, text_stream *material,
|
|||
@e IFFALSE_I6RW
|
||||
@e IFNOT_I6RW
|
||||
@e ENDIF_I6RW
|
||||
@e ORIGSOURCE_I6RW
|
||||
|
||||
@ The value of |inline_command|, in an |INLINE_ISTT| node, must be one of:
|
||||
|
||||
|
@ -506,6 +507,7 @@ void InterSchemas::log_just(inter_schema_node *isn, int depth) {
|
|||
case IFFALSE_I6RW: LOG("#iffalse"); break;
|
||||
case IFNOT_I6RW: LOG("#ifnot"); break;
|
||||
case ENDIF_I6RW: LOG("#endif"); break;
|
||||
case ORIGSOURCE_I6RW: LOG("#origsource"); break;
|
||||
default: LOG("<unknown>"); break;
|
||||
}
|
||||
LOG("\n");
|
||||
|
|
|
@ -778,6 +778,7 @@ but speed is not quite important enough to make it worthwhile.
|
|||
if (Str::eq_insensitive(T, I"#IFFALSE")) { is = DIRECTIVE_ISTT; which_rw = IFFALSE_I6RW; }
|
||||
if (Str::eq_insensitive(T, I"#IFNOT")) { is = DIRECTIVE_ISTT; which_rw = IFNOT_I6RW; }
|
||||
if (Str::eq_insensitive(T, I"#ENDIF")) { is = DIRECTIVE_ISTT; which_rw = ENDIF_I6RW; }
|
||||
if (Str::eq_insensitive(T, I"#ORIGSOURCE")) { is = DIRECTIVE_ISTT; which_rw = ORIGSOURCE_I6RW; }
|
||||
|
||||
if (Str::eq(T, I",")) is = COMMA_ISTT;
|
||||
if (Str::eq(T, I":")) is = COLON_ISTT;
|
||||
|
|
|
@ -58,11 +58,13 @@ in Inform kits.
|
|||
5.0.0 (24 April 2023) added (further) new fields to |SPLAT_IST| instructions, to
|
||||
record their provenance and so make better error reporting possible.
|
||||
|
||||
6.0.0 (25 May 2023) added the |ORIGSOURCE_IST| instruction.
|
||||
|
||||
@ Anyway, the implementation, such as it is:
|
||||
|
||||
=
|
||||
semantic_version_number InterVersion::current(void) {
|
||||
semantic_version_number V = VersionNumbers::from_text(I"5.0.0");
|
||||
semantic_version_number V = VersionNumbers::from_text(I"6.0.0");
|
||||
if (VersionNumbers::is_null(V)) internal_error("malformed version number");
|
||||
return V;
|
||||
}
|
||||
|
|
|
@ -302,6 +302,7 @@ These are constructs used for instructions outside function bodies:
|
|||
@e INSTANCE_IST
|
||||
@e INSERT_IST
|
||||
@e NOP_IST
|
||||
@e ORIGSOURCE_IST
|
||||
@e PACKAGE_IST
|
||||
@e PACKAGETYPE_IST
|
||||
@e PERMISSION_IST
|
||||
|
@ -380,6 +381,7 @@ void InterInstruction::create_language(void) {
|
|||
InterInstruction::define_invalid_construct();
|
||||
NopInstruction::define_construct();
|
||||
CommentInstruction::define_construct();
|
||||
OrigSourceInstruction::define_construct();
|
||||
PlugInstruction::define_construct();
|
||||
SocketInstruction::define_construct();
|
||||
VersionInstruction::define_construct();
|
||||
|
|
124
inter/bytecode-module/Chapter 4/The OrigSource Construct.w
Normal file
124
inter/bytecode-module/Chapter 4/The OrigSource Construct.w
Normal file
|
@ -0,0 +1,124 @@
|
|||
[OrigSourceInstruction::] The OrigSource Construct.
|
||||
|
||||
Defining the OrigSource construct.
|
||||
|
||||
@h Definition.
|
||||
The OrigSource construct is a marker in the bytecode which indicates the
|
||||
source location that generated that bytecode.
|
||||
|
||||
=
|
||||
void OrigSourceInstruction::define_construct(void) {
|
||||
inter_construct *IC = InterInstruction::create_construct(ORIGSOURCE_IST, I"origsource");
|
||||
InterInstruction::specify_syntax(IC, I"origsource TEXT NUMBER");
|
||||
InterInstruction::data_extent_always(IC, 2);
|
||||
METHOD_ADD(IC, CONSTRUCT_TRANSPOSE_MTID, OrigSourceInstruction::transpose);
|
||||
METHOD_ADD(IC, CONSTRUCT_VERIFY_MTID, OrigSourceInstruction::verify);
|
||||
METHOD_ADD(IC, CONSTRUCT_READ_MTID, OrigSourceInstruction::read);
|
||||
METHOD_ADD(IC, CONSTRUCT_WRITE_MTID, OrigSourceInstruction::write);
|
||||
InterInstruction::allow_in_depth_range(IC, 0, INFINITELY_DEEP);
|
||||
InterInstruction::permit(IC, OUTSIDE_OF_PACKAGES_ICUP);
|
||||
InterInstruction::permit(IC, INSIDE_PLAIN_PACKAGE_ICUP);
|
||||
InterInstruction::permit(IC, INSIDE_CODE_PACKAGE_ICUP);
|
||||
}
|
||||
|
||||
@h Instructions.
|
||||
In bytecode, the frame of an |origsource| instruction is laid out with the
|
||||
compulsory words -- see //Inter Nodes// -- followed by:
|
||||
|
||||
@d PROVENANCEFILE_ORIGSOURCE_IFLD (DATA_IFLD + 0)
|
||||
@d PROVENANCELINE_ORIGSOURCE_IFLD (DATA_IFLD + 1)
|
||||
|
||||
If |PROVENANCEFILE| is zero, the instruction means "Following bytecode is not
|
||||
from any specific source location." The line number is ignored in this case.
|
||||
|
||||
=
|
||||
inter_error_message *OrigSourceInstruction::new(inter_bookmark *IBM,
|
||||
text_stream *file_name, inter_ti line_number,
|
||||
inter_ti level, inter_error_location *eloc) {
|
||||
inter_ti FID = 0;
|
||||
if (Str::len(file_name) > 0) {
|
||||
inter_warehouse *warehouse = InterBookmark::warehouse(IBM);
|
||||
inter_package *pack = InterBookmark::package(IBM);
|
||||
FID = InterWarehouse::create_text(warehouse, pack);
|
||||
Str::copy(InterWarehouse::get_text(warehouse, FID), file_name);
|
||||
}
|
||||
inter_tree_node *P = Inode::new_with_2_data_fields(IBM, ORIGSOURCE_IST,
|
||||
/* PROVENANCEFILE_ORIGSOURCE_IFLD: */ FID,
|
||||
/* PROVENANCELINE_ORIGSOURCE_IFLD: */ line_number,
|
||||
eloc, level);
|
||||
inter_error_message *E = VerifyingInter::instruction(InterBookmark::package(IBM), P);
|
||||
if (E) return E;
|
||||
NodePlacement::move_to_moving_bookmark(P, IBM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inter_error_message *OrigSourceInstruction::new_from_provenance(inter_bookmark *IBM,
|
||||
text_provenance prov,
|
||||
inter_ti level, inter_error_location *eloc) {
|
||||
return OrigSourceInstruction::new(IBM, prov.textual_filename, (unsigned int)prov.line_number, level, eloc);
|
||||
}
|
||||
|
||||
void OrigSourceInstruction::transpose(inter_construct *IC, inter_tree_node *P,
|
||||
inter_ti *grid, inter_ti grid_extent, inter_error_message **E) {
|
||||
P->W.instruction[PROVENANCEFILE_ORIGSOURCE_IFLD] = grid[P->W.instruction[PROVENANCEFILE_ORIGSOURCE_IFLD]];
|
||||
}
|
||||
|
||||
@ Verification consists only of sanity checks.
|
||||
|
||||
=
|
||||
void OrigSourceInstruction::verify(inter_construct *IC, inter_tree_node *P,
|
||||
inter_package *owner, inter_error_message **E) {
|
||||
if (!P->W.instruction[PROVENANCEFILE_ORIGSOURCE_IFLD]) {
|
||||
/* (0,anything) is valid */
|
||||
}
|
||||
else {
|
||||
*E = VerifyingInter::text_field(owner, P, PROVENANCEFILE_ORIGSOURCE_IFLD);
|
||||
}
|
||||
if (*E) return;
|
||||
}
|
||||
|
||||
@h Creating from textual Inter syntax.
|
||||
|
||||
=
|
||||
void OrigSourceInstruction::read(inter_construct *IC, inter_bookmark *IBM, inter_line_parse *ilp,
|
||||
inter_error_location *eloc, inter_error_message **E) {
|
||||
text_stream *fn = ilp->mr.exp[0];
|
||||
text_stream *lc = ilp->mr.exp[1];
|
||||
TEMPORARY_TEXT(file_as_text)
|
||||
*E = TextualInter::parse_literal_text(file_as_text, fn, 0, Str::len(fn), eloc);
|
||||
if (*E == NULL) {
|
||||
text_stream *temp_filename = NULL;
|
||||
if (Str::len(file_as_text) > 0) temp_filename = file_as_text;
|
||||
inter_ti line_number = 0;
|
||||
if (Str::len(lc) > 0) line_number = (inter_ti) Str::atoi(lc, 0);
|
||||
*E = OrigSourceInstruction::new(IBM, temp_filename, line_number,
|
||||
(inter_ti) ilp->indent_level, eloc);
|
||||
}
|
||||
DISCARD_TEXT(file_as_text)
|
||||
}
|
||||
|
||||
@h Writing to textual Inter syntax.
|
||||
|
||||
=
|
||||
void OrigSourceInstruction::write(inter_construct *IC, OUTPUT_STREAM, inter_tree_node *P) {
|
||||
if (!P->W.instruction[PROVENANCEFILE_ORIGSOURCE_IFLD]) {
|
||||
WRITE("origsource");
|
||||
}
|
||||
else {
|
||||
WRITE("origsource ");
|
||||
Provenance::write(OUT, OrigSourceInstruction::provenance(P));
|
||||
}
|
||||
}
|
||||
|
||||
@h Access functions.
|
||||
|
||||
=
|
||||
text_provenance OrigSourceInstruction::provenance(inter_tree_node *P) {
|
||||
if (P == NULL) return Provenance::nowhere();
|
||||
if (Inode::isnt(P, ORIGSOURCE_IST)) return Provenance::nowhere();
|
||||
if (!P->W.instruction[PROVENANCEFILE_ORIGSOURCE_IFLD])
|
||||
return Provenance::nowhere();
|
||||
return Provenance::at_file_and_line(
|
||||
Inode::ID_to_text(P, P->W.instruction[PROVENANCEFILE_ORIGSOURCE_IFLD]),
|
||||
(int) P->W.instruction[PROVENANCELINE_ORIGSOURCE_IFLD]);
|
||||
}
|
|
@ -45,6 +45,7 @@ void CodeInstruction::verify_children(inter_construct *IC, inter_tree_node *P,
|
|||
(C->W.instruction[0] != LABEL_IST) &&
|
||||
(C->W.instruction[0] != VAL_IST) &&
|
||||
(C->W.instruction[0] != COMMENT_IST) &&
|
||||
(C->W.instruction[0] != ORIGSOURCE_IST) &&
|
||||
(C->W.instruction[0] != NOP_IST)) {
|
||||
*E = Inode::error(C, I"only executable matter can be below a code", NULL);
|
||||
return;
|
||||
|
|
|
@ -180,6 +180,7 @@ The other names here are taken from their corresponding I6 directives.
|
|||
@e IFNOT_PLM
|
||||
@e ENDIF_PLM
|
||||
@e IFTRUE_PLM
|
||||
@e ORIGSOURCE_PLM
|
||||
@e CONSTANT_PLM
|
||||
@e ARRAY_PLM
|
||||
@e GLOBAL_PLM
|
||||
|
|
|
@ -42,6 +42,7 @@ Chapter 4: Void Constructs
|
|||
The Insert Construct
|
||||
The Instance Construct
|
||||
The Nop Construct
|
||||
The OrigSource Construct
|
||||
The Package Construct
|
||||
The PackageType Construct
|
||||
The Permission Construct
|
||||
|
|
|
@ -245,6 +245,18 @@ void Generators::evaluate_label(code_generation *gen, text_stream *label_name) {
|
|||
VOID_METHOD_CALL(gen->generator, EVALUATE_LABEL_MTID, gen, label_name);
|
||||
}
|
||||
|
||||
@ OrigSource directives. These identify the original source location that
|
||||
generated the current code.
|
||||
|
||||
@e PLACE_ORIGSOURCE_MTID
|
||||
|
||||
=
|
||||
VOID_METHOD_TYPE(PLACE_ORIGSOURCE_MTID, code_generator *generator, code_generation *gen,
|
||||
text_provenance *source_loc)
|
||||
void Generators::place_origsource(code_generation *gen, text_provenance *source_loc) {
|
||||
VOID_METHOD_CALL(gen->generator, PLACE_ORIGSOURCE_MTID, gen, source_loc);
|
||||
}
|
||||
|
||||
@ The three ways to invoke (and a doohickey for assembly opcodes):
|
||||
|
||||
@e INVOKE_PRIMITIVE_MTID
|
||||
|
|
|
@ -144,3 +144,12 @@ void VanillaCode::assembly(code_generation *gen, inter_tree_node *P) {
|
|||
inter_ti which = AssemblyInstruction::which_marker(P);
|
||||
Generators::assembly_marker(gen, which);
|
||||
}
|
||||
|
||||
@ OrigSource directives are passed through to the generator.
|
||||
|
||||
=
|
||||
void VanillaCode::place_origsource(code_generation *gen, inter_tree_node *P) {
|
||||
text_provenance prov = OrigSourceInstruction::provenance(P);
|
||||
Generators::place_origsource(gen, &prov);
|
||||
}
|
||||
|
||||
|
|
|
@ -112,6 +112,7 @@ void Vanilla::node(code_generation *gen, inter_tree_node *P) {
|
|||
case LOCAL_IST: break;
|
||||
case NOP_IST: break;
|
||||
case COMMENT_IST: break;
|
||||
case ORIGSOURCE_IST: VanillaCode::place_origsource(gen, P); break;
|
||||
|
||||
case INVALID_IST: InterErrors::backtrace(DL, P);
|
||||
internal_error("INVALID node type in Inter tree");
|
||||
|
|
|
@ -152,6 +152,7 @@ Document for a specification.
|
|||
segmentation_pos saved = CodeGen::select(gen, functions_I7CGS);
|
||||
text_stream *OUT = CodeGen::current(gen);
|
||||
WRITE("#Ifdef TARGET_ZCODE;\n");
|
||||
WRITE("#OrigSource \"%s\" %d;\n", __FILE__, __LINE__);
|
||||
WRITE("Global max_z_object;\n");
|
||||
WRITE("#Ifdef Z__Region;\n");
|
||||
WRITE("[ OC__Cl obj cla j a n objflag;\n"); INDENT;
|
||||
|
@ -216,6 +217,7 @@ Document for a specification.
|
|||
WRITE("rfalse;\n");
|
||||
OUTDENT; WRITE("];\n");
|
||||
WRITE("#Endif;\n");
|
||||
WRITE("#OrigSource;\n");
|
||||
WRITE("#Endif;\n");
|
||||
CodeGen::deselect(gen, saved);
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ void I6TargetCode::create_generator(code_generator *gtr) {
|
|||
METHOD_ADD(gtr, DECLARE_FUNCTION_MTID, I6TargetCode::declare_function);
|
||||
METHOD_ADD(gtr, PLACE_LABEL_MTID, I6TargetCode::place_label);
|
||||
METHOD_ADD(gtr, EVALUATE_LABEL_MTID, I6TargetCode::evaluate_label);
|
||||
METHOD_ADD(gtr, PLACE_ORIGSOURCE_MTID, I6TargetCode::place_origsource);
|
||||
METHOD_ADD(gtr, INVOKE_PRIMITIVE_MTID, I6TargetCode::invoke_primitive);
|
||||
METHOD_ADD(gtr, INVOKE_FUNCTION_MTID, I6TargetCode::invoke_function);
|
||||
METHOD_ADD(gtr, INVOKE_OPCODE_MTID, I6TargetCode::invoke_opcode);
|
||||
|
@ -176,6 +177,29 @@ void I6TargetCode::evaluate_label(code_generator *gtr, code_generation *gen,
|
|||
PUT(Str::get(pos));
|
||||
}
|
||||
|
||||
@h Origsource references.
|
||||
|
||||
The conversion of filenames to I6 string literals doesn't really account
|
||||
for special characters. We're leaving it up to the end user to decode all
|
||||
of I6's confusing escape sequences. But at least we guarantee that the
|
||||
I6 compiler won't choke on the directive.
|
||||
=
|
||||
void I6TargetCode::place_origsource(code_generator *gtr, code_generation *gen,
|
||||
text_provenance *source_loc) {
|
||||
text_stream *OUT = CodeGen::current(gen);
|
||||
if (Provenance::is_somewhere(*source_loc)) {
|
||||
WRITE("#OrigSource ");
|
||||
Generators::compile_literal_text(gen, source_loc->textual_filename, TRUE);
|
||||
if (source_loc->line_number > 0)
|
||||
WRITE(" %d;\n", source_loc->line_number);
|
||||
else
|
||||
WRITE(";\n");
|
||||
}
|
||||
else {
|
||||
WRITE("#OrigSource;\n");
|
||||
}
|
||||
}
|
||||
|
||||
@h Function invocations.
|
||||
Or in other words, function calls. These are easy: the syntax is exactly what
|
||||
it would be for C.
|
||||
|
|
|
@ -11,7 +11,7 @@ the conditional compilation splats gone, we are left with these:
|
|||
= (text)
|
||||
ARRAY_PLM ATTRIBUTE_PLM CONSTANT_PLM DEFAULT_PLM
|
||||
FAKEACTION_PLM GLOBAL_PLM OBJECT_PLM PROPERTY_PLM
|
||||
ROUTINE_PLM STUB_PLM VERB_PLM
|
||||
ROUTINE_PLM STUB_PLM VERB_PLM ORIGSOURCE_PLM
|
||||
=
|
||||
And we must turn those into splatless Inter code with the same effect. In some
|
||||
cases, notably |ROUTINE_PLM| which contains an entire Inform 6-notation
|
||||
|
@ -86,6 +86,9 @@ void CompileSplatsStage::visitor1(inter_tree *I, inter_tree_node *P, void *state
|
|||
case STUB_PLM:
|
||||
@<Assimilate routine@>;
|
||||
break;
|
||||
case ORIGSOURCE_PLM:
|
||||
@<Assimilate origsource directive@>;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,6 +136,32 @@ void CompileSplatsStage::visitor3(inter_tree *I, inter_tree_node *P, void *state
|
|||
}
|
||||
}
|
||||
|
||||
@h How OrigSource definitions are assimilated.
|
||||
|
||||
@ Note that the #OrigSource directive (with hash sign) is also valid
|
||||
within a function body. We will handle that case later; see
|
||||
//Emitting Inter Schemas//.
|
||||
|
||||
This is not yet useful. It converts a top-level #Origsource directive
|
||||
to a top-level ORIGSOURCE_IST node, but it doesn't put it anywhere
|
||||
meaningful; the node just winds up tacked onto the end of the kit.
|
||||
|
||||
@<Assimilate origsource directive@> =
|
||||
I6Errors::set_current_location_near_splat(P);
|
||||
match_results mr = Regexp::create_mr();
|
||||
text_stream *origfilestr = NULL;
|
||||
int origline = 0;
|
||||
int proceed = TRUE;
|
||||
@<Parse text of splat for optional string and number@>;
|
||||
if (proceed) {
|
||||
inter_bookmark content_at = InterBookmark::after_this_node(P);
|
||||
inter_bookmark *IBM = &content_at;
|
||||
inter_ti B = (inter_ti) InterBookmark::baseline(IBM) + 1;
|
||||
Produce::guard(OrigSourceInstruction::new(IBM, origfilestr, (unsigned int)origline, B, NULL));
|
||||
NodePlacement::remove(P);
|
||||
}
|
||||
Regexp::dispose_of(&mr);
|
||||
|
||||
@h How definitions are assimilated.
|
||||
|
||||
@<Assimilate definition@> =
|
||||
|
@ -191,6 +220,28 @@ meaningfully have a value, even though a third token is present.
|
|||
}
|
||||
Str::trim_all_white_space_at_end(raw_identifier);
|
||||
|
||||
@ The following finds |"STRING" NUMBER|, or |"STRING"|, or nothing.
|
||||
(In its pocketses.) This is needed for the |OrigSource| directive.
|
||||
In I6 that directive can accept a second number, but we won't
|
||||
worry about that here.
|
||||
|
||||
@<Parse text of splat for optional string and number@> =
|
||||
text_stream *S = SplatInstruction::splatter(P);
|
||||
if (Regexp::match(&mr, S, L" *%C+ \"(%C*)\" (%d+) *; *")) {
|
||||
origfilestr = mr.exp[0];
|
||||
origline = Str::atoi(mr.exp[1], 0);
|
||||
}
|
||||
else if (Regexp::match(&mr, S, L" *%C+ \"(%C*)\" *; *")) {
|
||||
origfilestr = mr.exp[0];
|
||||
}
|
||||
else if (Regexp::match(&mr, S, L" *%C+ *; *")) {
|
||||
/* bare "Origsource;" is okay */
|
||||
}
|
||||
else {
|
||||
I6Errors::issue("Unable to parse ORIGSOURCE_PLM: '%S'", S);
|
||||
proceed = FALSE;
|
||||
}
|
||||
|
||||
@ An eccentricity of Inform 6 syntax is that fake action names ought to be given
|
||||
in the form |Fake_Action ##Bake|, but are not. The constant created by |Fake_Action Bake|
|
||||
is nevertheless |##Bake|, so we take care of that here.
|
||||
|
@ -229,7 +280,7 @@ But in fact it's easier to handle it here.
|
|||
@ So if we're here, we have reduced the possibilities to:
|
||||
= (text)
|
||||
ARRAY_PLM ATTRIBUTE_PLM CONSTANT_PLM FAKEACTION_PLM
|
||||
GLOBAL_PLM OBJECT_PLM PROPERTY_PLM VERB_PLM
|
||||
GLOBAL_PLM OBJECT_PLM PROPERTY_PLM VERB_PLM
|
||||
=
|
||||
We basically do the same thing in all of these cases: decide where to put
|
||||
the result, declare a symbol for it, and then define that symbol.
|
||||
|
@ -1436,7 +1487,9 @@ int CompileSplatsStage::function_bodies(pipeline_step *step, compile_splats_stat
|
|||
IdentifierFinders::next_priority(&finder, scope1);
|
||||
IdentifierFinders::next_priority(&finder, scope2);
|
||||
IdentifierFinders::set_namespace(&finder, req->namespace);
|
||||
Produce::guard(OrigSourceInstruction::new_from_provenance(Produce::at(I), req->provenance, (inter_ti) Produce::level(I), NULL));
|
||||
EmitInterSchemas::emit(I, &VH, sch, finder, NULL, NULL, NULL);
|
||||
Produce::guard(OrigSourceInstruction::new(Produce::at(I), NULL, 0, (inter_ti) Produce::level(I), NULL));
|
||||
CompileSplatsStage::report_kit_errors(sch, req);
|
||||
Produce::pop_code_position(I);
|
||||
Produce::set_function(I, NULL);
|
||||
|
|
|
@ -368,6 +368,7 @@ the directive type as 0.
|
|||
else if (Str::eq_insensitive(mr.exp[0], I"Iftrue")) I6_dir = IFTRUE_PLM;
|
||||
else if (Str::eq_insensitive(mr.exp[0], I"Ifnot")) I6_dir = IFNOT_PLM;
|
||||
else if (Str::eq_insensitive(mr.exp[0], I"Endif")) I6_dir = ENDIF_PLM;
|
||||
else if (Str::eq_insensitive(mr.exp[0], I"OrigSource")) I6_dir = ORIGSOURCE_PLM;
|
||||
else if (Str::eq_insensitive(mr.exp[0], I"Stub")) I6_dir = STUB_PLM;
|
||||
else if (Str::eq_insensitive(mr.exp[0], I"Constant")) I6_dir = CONSTANT_PLM;
|
||||
else if (Str::eq_insensitive(mr.exp[0], I"Global")) I6_dir = GLOBAL_PLM;
|
||||
|
@ -397,7 +398,7 @@ the directive type as 0.
|
|||
else if (Str::eq_insensitive(mr.exp[0], I"Import")) known = TRUE;
|
||||
else if (Str::eq_insensitive(mr.exp[0], I"Link")) known = TRUE;
|
||||
else if (Str::eq_insensitive(mr.exp[0], I"Lowstring")) known = TRUE;
|
||||
else if (Str::eq_insensitive(mr.exp[0], I"Origsource")) known = TRUE;
|
||||
else if (Str::eq_insensitive(mr.exp[0], I"Message")) known = TRUE;
|
||||
else if (Str::eq_insensitive(mr.exp[0], I"Replace")) known = TRUE;
|
||||
else if (Str::eq_insensitive(mr.exp[0], I"Switches")) known = TRUE;
|
||||
else if (Str::eq_insensitive(mr.exp[0], I"Trace")) known = TRUE;
|
||||
|
@ -406,7 +407,7 @@ the directive type as 0.
|
|||
if (known)
|
||||
I6Errors::issue(
|
||||
"this Inform 6 directive is not supported in kits or '(-' inclusions: '%S' "
|
||||
"(only #Ifdef, #Ifndef, #Iftrue, #Ifnot, #Endif, #Stub, Constant, Global, "
|
||||
"(only #Ifdef, #Ifndef, #Iftrue, #Ifnot, #Endif, #OrigSource, #Stub, Constant, Global, "
|
||||
"Array, Attribute, Property, Verb, Fake_action, Object, Default are "
|
||||
"supported)", R);
|
||||
else
|
||||
|
|
Loading…
Reference in a new issue