1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-07 17:44:22 +03:00

Plumbing for the OrigSource construct.

This commit is contained in:
Andrew Plotkin 2023-05-24 17:36:02 -04:00
parent cde27e8068
commit e2d7e25045
6 changed files with 119 additions and 0 deletions

View file

@ -140,6 +140,7 @@ int CompileBlocksAndLines::code_line(int statement_count, parse_node *p, int as_
EmitCode::comment(C); EmitCode::comment(C);
DISCARD_TEXT(C) DISCARD_TEXT(C)
*last_loc = sl; *last_loc = sl;
EmitCode::origsource(last_loc);
} }
} }

View file

@ -70,6 +70,14 @@ void EmitCode::comment(text_stream *text) {
(inter_ti) EmitCode::level())); (inter_ti) EmitCode::level()));
} }
@h OrigSource directives.
=
void EmitCode::origsource(source_location *sl) {
Produce::guard(OrigSourceInstruction::new(EmitCode::at(), sl->file_of_origin->name, (unsigned int)sl->line_number, NULL,
(inter_ti) EmitCode::level()));
}
@h In value context. @h In value context.
These functions all generate a |val| opcode: These functions all generate a |val| opcode:

View file

@ -334,6 +334,11 @@ instead specify something else about the tree:
@e SOCKET_IST @e SOCKET_IST
@e VERSION_IST @e VERSION_IST
@ This can go inside or outside function bodies, like COMMENT_IST. I put it
at the end so that it wouldn't change //The Inter Version//.
@e ORIGSOURCE_IST
@ Since these IDs are stored in the bytecode for an instruction, in fact in the @ Since these IDs are stored in the bytecode for an instruction, in fact in the
0th word of the frame, we will need to convert them to their //inter_construct// 0th word of the frame, we will need to convert them to their //inter_construct//
equivalents quickly. So we store a lookup table: equivalents quickly. So we store a lookup table:
@ -380,6 +385,7 @@ void InterInstruction::create_language(void) {
InterInstruction::define_invalid_construct(); InterInstruction::define_invalid_construct();
NopInstruction::define_construct(); NopInstruction::define_construct();
CommentInstruction::define_construct(); CommentInstruction::define_construct();
OrigSourceInstruction::define_construct();
PlugInstruction::define_construct(); PlugInstruction::define_construct();
SocketInstruction::define_construct(); SocketInstruction::define_construct();
VersionInstruction::define_construct(); VersionInstruction::define_construct();

View file

@ -0,0 +1,102 @@
[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)
=
inter_error_message *OrigSourceInstruction::new(inter_bookmark *IBM,
filename *file, inter_ti line_number,
inter_error_location *eloc, inter_ti level) {
TEMPORARY_TEXT(file_as_text)
if (file) WRITE_TO(file_as_text, "%f", file);
inter_warehouse *warehouse = InterBookmark::warehouse(IBM);
inter_package *pack = InterBookmark::package(IBM);
inter_ti FID = InterWarehouse::create_text(warehouse, pack);
Str::copy(InterWarehouse::get_text(warehouse, FID), file_as_text);
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;
}
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) {
*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) {
filename *F = NULL;
if (Str::len(file_as_text) > 0) F = Filenames::from_text(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, F, line_number,
eloc, (inter_ti) ilp->indent_level);
}
DISCARD_TEXT(file_as_text)
}
@h Writing to textual Inter syntax.
=
void OrigSourceInstruction::write(inter_construct *IC, OUTPUT_STREAM, inter_tree_node *P) {
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();
return Provenance::at_file_and_line(
Inode::ID_to_text(P, P->W.instruction[PROVENANCEFILE_ORIGSOURCE_IFLD]),
(int) P->W.instruction[PROVENANCELINE_ORIGSOURCE_IFLD]);
}

View file

@ -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] != LABEL_IST) &&
(C->W.instruction[0] != VAL_IST) && (C->W.instruction[0] != VAL_IST) &&
(C->W.instruction[0] != COMMENT_IST) && (C->W.instruction[0] != COMMENT_IST) &&
(C->W.instruction[0] != ORIGSOURCE_IST) &&
(C->W.instruction[0] != NOP_IST)) { (C->W.instruction[0] != NOP_IST)) {
*E = Inode::error(C, I"only executable matter can be below a code", NULL); *E = Inode::error(C, I"only executable matter can be below a code", NULL);
return; return;

View file

@ -42,6 +42,7 @@ Chapter 4: Void Constructs
The Insert Construct The Insert Construct
The Instance Construct The Instance Construct
The Nop Construct The Nop Construct
The OrigSource Construct
The Package Construct The Package Construct
The PackageType Construct The PackageType Construct
The Permission Construct The Permission Construct