1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-03 07:24:58 +03:00
inform7/inter/codegen-module/Chapter 2/Assimilate.w
2021-05-16 11:37:28 +01:00

835 lines
35 KiB
OpenEdge ABL

[CodeGen::Assimilate::] Assimilate Linked Matter.
To assimilate the material in parsed non-code splats.
@h Pipeline stage.
=
void CodeGen::Assimilate::create_pipeline_stage(void) {
CodeGen::Stage::new(I"assimilate", CodeGen::Assimilate::run_pipeline_stage, NO_STAGE_ARG, FALSE);
}
int current_assimilation_pass = 0;
int no_assimilated_actions = 0;
int no_assimilated_commands = 0;
int no_assimilated_arrays = 0;
int trace_AME = TRUE;
int CodeGen::Assimilate::run_pipeline_stage(pipeline_step *step) {
inter_tree *I = step->repository;
++current_assimilation_pass;
no_assimilated_actions = 0;
no_assimilated_commands = 0;
no_assimilated_arrays = 0;
Site::ensure_assimilation_package(I, plain_ptype_symbol);
// SynopticHierarchy::establish(I);
CodeGen::Assimilate::ensure(I, &verb_directive_reverse_symbol, I"VERB_DIRECTIVE_REVERSE");
CodeGen::Assimilate::ensure(I, &verb_directive_slash_symbol, I"VERB_DIRECTIVE_SLASH");
CodeGen::Assimilate::ensure(I, &verb_directive_divider_symbol, I"VERB_DIRECTIVE_DIVIDER");
CodeGen::Assimilate::ensure(I, &verb_directive_result_symbol, I"VERB_DIRECTIVE_RESULT");
CodeGen::Assimilate::ensure(I, &verb_directive_special_symbol, I"VERB_DIRECTIVE_SPECIAL");
CodeGen::Assimilate::ensure(I, &verb_directive_number_symbol, I"VERB_DIRECTIVE_NUMBER");
CodeGen::Assimilate::ensure(I, &verb_directive_noun_symbol, I"VERB_DIRECTIVE_NOUN");
CodeGen::Assimilate::ensure(I, &verb_directive_multi_symbol, I"VERB_DIRECTIVE_MULTI");
CodeGen::Assimilate::ensure(I, &verb_directive_multiinside_symbol, I"VERB_DIRECTIVE_MULTIINSIDE");
CodeGen::Assimilate::ensure(I, &verb_directive_multiheld_symbol, I"VERB_DIRECTIVE_MULTIHELD");
CodeGen::Assimilate::ensure(I, &verb_directive_held_symbol, I"VERB_DIRECTIVE_HELD");
CodeGen::Assimilate::ensure(I, &verb_directive_creature_symbol, I"VERB_DIRECTIVE_CREATURE");
CodeGen::Assimilate::ensure(I, &verb_directive_topic_symbol, I"VERB_DIRECTIVE_TOPIC");
CodeGen::Assimilate::ensure(I, &verb_directive_multiexcept_symbol, I"VERB_DIRECTIVE_MULTIEXCEPT");
if (Inter::Connectors::find_socket(I, I"self") == NULL) {
inter_symbol *ss = Veneer::find_by_index(I, SELF_VSYMB, unchecked_kind_symbol);
if (ss == NULL) internal_error("stuck");
Inter::Connectors::socket(I, I"self", ss);
}
InterTree::traverse(I, CodeGen::Assimilate::visitor1, NULL, NULL, SPLAT_IST);
InterTree::traverse(I, CodeGen::Assimilate::visitor2, NULL, NULL, SPLAT_IST);
CodeGen::Assimilate::function_bodies(I);
InterTree::traverse(I, CodeGen::Assimilate::visitor3, NULL, NULL, SPLAT_IST);
return TRUE;
}
void CodeGen::Assimilate::ensure(inter_tree *I, inter_symbol **S, text_stream *identifier) {
if (*S == NULL) *S = Inter::Connectors::plug(I, identifier);
}
@h Parsing.
=
inter_bookmark CodeGen::Assimilate::template_submodule(inter_tree *I, text_stream *name, inter_tree_node *P) {
if (submodule_ptype_symbol) {
inter_package *template_package = Site::ensure_assimilation_package(I, plain_ptype_symbol);
inter_package *t_p = Inter::Packages::by_name(template_package, name);
if (t_p == NULL) {
inter_bookmark IBM = Inter::Bookmarks::after_this_node(I, P);
t_p = CodeGen::Assimilate::new_package_named(&IBM, name, submodule_ptype_symbol);
}
if (t_p == NULL) internal_error("failed to define");
return Inter::Bookmarks::at_end_of_this_package(t_p);
}
return Inter::Bookmarks::after_this_node(I, P);
}
void CodeGen::Assimilate::visitor1(inter_tree *I, inter_tree_node *P, void *state) {
switch (P->W.data[PLM_SPLAT_IFLD]) {
case PROPERTY_PLM:
if (unchecked_kind_symbol) @<Assimilate definition@>;
break;
case ATTRIBUTE_PLM:
if (truth_state_kind_symbol) @<Assimilate definition@>;
break;
case ROUTINE_PLM:
case STUB_PLM:
if ((unchecked_kind_symbol) && (unchecked_function_symbol))
@<Assimilate routine@>;
break;
}
}
void CodeGen::Assimilate::visitor2(inter_tree *I, inter_tree_node *P, void *state) {
switch (P->W.data[PLM_SPLAT_IFLD]) {
case DEFAULT_PLM:
case CONSTANT_PLM:
case FAKEACTION_PLM:
case OBJECT_PLM:
case VERB_PLM:
if (unchecked_kind_symbol) @<Assimilate definition@>;
break;
case ARRAY_PLM:
if (list_of_unchecked_kind_symbol) @<Assimilate definition@>;
break;
}
}
void CodeGen::Assimilate::visitor3(inter_tree *I, inter_tree_node *P, void *state) {
switch (P->W.data[PLM_SPLAT_IFLD]) {
case GLOBAL_PLM:
if (unchecked_kind_symbol) @<Assimilate definition@>;
break;
}
}
@
@d MAX_ASSIMILATED_ARRAY_ENTRIES 2048
@<Assimilate definition@> =
inter_ti plm = P->W.data[PLM_SPLAT_IFLD];
match_results mr = Regexp::create_mr();
text_stream *identifier = NULL;
text_stream *value = NULL;
int proceed = FALSE;
@<Parse text of splat for identifier and value@>;
if ((proceed) && (unchecked_kind_symbol)) {
if ((plm == DEFAULT_PLM) && (Inter::Connectors::find_socket(I, identifier) == NULL))
plm = CONSTANT_PLM;
if (plm != DEFAULT_PLM) @<Act on parsed constant definition@>;
InterTree::remove_node(P);
}
Regexp::dispose_of(&mr);
@<Parse text of splat for identifier and value@> =
text_stream *S = Inode::ID_to_text(P, P->W.data[MATTER_SPLAT_IFLD]);
if (plm == VERB_PLM) {
if (Regexp::match(&mr, S, L" *%C+ (%c*?) *;%c*")) {
identifier = I"assim_gv"; value = mr.exp[0]; proceed = TRUE;
} else LOG("Stuck on this! %S\n", S);
} else {
if (Regexp::match(&mr, S, L" *%C+ *(%C+?)(--> *%c*?) *;%c*")) {
identifier = mr.exp[0]; value = mr.exp[1]; proceed = TRUE;
} else if (Regexp::match(&mr, S, L" *%C+ *(%C+?)(-> *%c*?) *;%c*")) {
identifier = mr.exp[0]; value = mr.exp[1]; proceed = TRUE;
} else if (Regexp::match(&mr, S, L" *%C+ (%C*?) *;%c*")) {
identifier = mr.exp[0]; proceed = TRUE;
} else if (Regexp::match(&mr, S, L" *%C+ (%C*) *= *(%c*?) *;%c*")) {
identifier = mr.exp[0]; value = mr.exp[1]; proceed = TRUE;
} else if (Regexp::match(&mr, S, L" *%C+ (%C*) (%c*?) *;%c*")) {
identifier = mr.exp[0]; value = mr.exp[1]; proceed = TRUE;
} else LOG("Stuck on this! %S\n", S);
}
if (identifier) Str::trim_all_white_space_at_end(identifier);
if (plm == FAKEACTION_PLM) {
text_stream *old = identifier;
identifier = Str::new();
WRITE_TO(identifier, "##%S", old);
}
if (plm == OBJECT_PLM) value = NULL;
@<Act on parsed constant definition@> =
inter_bookmark IBM_d = Inter::Bookmarks::after_this_node(I, P);
inter_bookmark *IBM = &IBM_d;
text_stream *submodule_name = NULL;
text_stream *suffix = NULL;
inter_symbol *subpackage_type = plain_ptype_symbol;
switch (plm) {
case VERB_PLM:
if (command_ptype_symbol) subpackage_type = command_ptype_symbol;
submodule_name = I"commands"; suffix = NULL; break;
case ARRAY_PLM:
submodule_name = I"arrays"; suffix = I"arr"; break;
case CONSTANT_PLM:
case FAKEACTION_PLM:
case OBJECT_PLM:
submodule_name = I"constants"; suffix = I"con"; break;
case GLOBAL_PLM:
submodule_name = I"variables"; suffix = I"var"; break;
case ATTRIBUTE_PLM:
case PROPERTY_PLM:
if (property_ptype_symbol) subpackage_type = property_ptype_symbol;
submodule_name = I"properties"; suffix = I"prop"; break;
}
if (submodule_name) {
IBM_d = CodeGen::Assimilate::template_submodule(I, submodule_name, P);
TEMPORARY_TEXT(subpackage_name)
if (suffix) {
WRITE_TO(subpackage_name, "%S_%S", identifier, suffix);
} else {
WRITE_TO(subpackage_name, "assim_command_%d", ++no_assimilated_commands);
}
Inter::Bookmarks::set_current_package(IBM,
CodeGen::Assimilate::new_package_named(IBM, subpackage_name, subpackage_type));
DISCARD_TEXT(subpackage_name)
}
inter_symbol *con_name = CodeGen::Assimilate::make_socketed_symbol(I, identifier, Inter::Bookmarks::scope(IBM));
Inter::Symbols::annotate_i(con_name, ASSIMILATED_IANN, 1);
if (plm == FAKEACTION_PLM)
Inter::Symbols::annotate_i(con_name, FAKE_ACTION_IANN, 1);
if (plm == OBJECT_PLM)
Inter::Symbols::annotate_i(con_name, OBJECT_IANN, 1);
inter_symbol *id_s = NULL;
if ((plm == ATTRIBUTE_PLM) || (plm == PROPERTY_PLM)) {
id_s = CodeGen::Assimilate::make_socketed_symbol(I, I"property_id", Inter::Bookmarks::scope(IBM));
}
if (id_s) {
Inter::Symbols::set_flag(id_s, MAKE_NAME_UNIQUE);
Produce::guard(Inter::Constant::new_numerical(IBM,
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), id_s),
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), unchecked_kind_symbol),
LITERAL_IVAL, 0,
(inter_ti) Inter::Bookmarks::baseline(IBM) + 1, NULL));
}
if (con_name->equated_to) {
inter_symbol *external_name = con_name->equated_to;
external_name->equated_to = con_name;
con_name->equated_to = NULL;
}
inter_ti v1 = 0, v2 = 0;
switch (plm) {
case CONSTANT_PLM:
case FAKEACTION_PLM:
case OBJECT_PLM: {
@<Assimilate a value@>;
Produce::guard(Inter::Constant::new_numerical(IBM,
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), con_name),
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), unchecked_kind_symbol), v1, v2,
(inter_ti) Inter::Bookmarks::baseline(IBM) + 1, NULL));
CodeGen::Assimilate::install_socket(I, con_name, identifier);
break;
}
case GLOBAL_PLM:
@<Assimilate a value@>;
Produce::guard(Inter::Variable::new(IBM,
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), con_name),
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), unchecked_kind_symbol), v1, v2,
(inter_ti) Inter::Bookmarks::baseline(IBM) + 1, NULL));
CodeGen::Assimilate::install_socket(I, con_name, identifier);
break;
case ATTRIBUTE_PLM: {
TEMPORARY_TEXT(A)
WRITE_TO(A, "P_%S", con_name->symbol_name);
inter_symbol *attr_symbol = InterSymbolsTables::symbol_from_name(Inter::Bookmarks::scope(IBM), A);
if ((attr_symbol == NULL) || (!Inter::Symbols::is_defined(attr_symbol))) {
if (attr_symbol == NULL) attr_symbol = con_name;
Produce::guard(Inter::Property::new(IBM,
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), attr_symbol),
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), truth_state_kind_symbol),
(inter_ti) Inter::Bookmarks::baseline(IBM) + 1, NULL));
Inter::Symbols::annotate_i(attr_symbol, ATTRIBUTE_IANN, 1);
Inter::Symbols::annotate_i(attr_symbol, EITHER_OR_IANN, 1);
Inter::Symbols::set_translate(attr_symbol, con_name->symbol_name);
if (Str::ne(attr_symbol->symbol_name, con_name->symbol_name)) {
inter_symbol *alias_symbol = InterSymbolsTables::symbol_from_name_creating(Inter::Bookmarks::scope(IBM), con_name->symbol_name);
InterSymbolsTables::equate(alias_symbol, attr_symbol);
}
} else {
Inter::Symbols::annotate_i(attr_symbol, ASSIMILATED_IANN, 1);
if (Str::ne(attr_symbol->symbol_name, Inter::Symbols::get_translate(attr_symbol))) {
inter_symbol *alias_symbol = InterSymbolsTables::symbol_from_name_creating(Inter::Bookmarks::scope(IBM), Inter::Symbols::get_translate(attr_symbol));
InterSymbolsTables::equate(alias_symbol, attr_symbol);
}
}
CodeGen::Assimilate::install_socket(I, attr_symbol, A);
CodeGen::Assimilate::install_socket(I, attr_symbol, con_name->symbol_name);
if (Str::ne(attr_symbol->symbol_name, Inter::Symbols::get_translate(attr_symbol)))
CodeGen::Assimilate::install_socket(I, attr_symbol, Inter::Symbols::get_translate(attr_symbol));
DISCARD_TEXT(A)
break;
}
case PROPERTY_PLM: {
Produce::guard(Inter::Property::new(IBM,
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), con_name),
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), unchecked_kind_symbol),
(inter_ti) Inter::Bookmarks::baseline(IBM) + 1, NULL));
CodeGen::Assimilate::install_socket(I, con_name, identifier);
if (Str::eq(identifier, I"absent"))
CodeGen::Assimilate::install_socket(I, con_name, I"P_absent");
break;
}
case VERB_PLM:
case ARRAY_PLM: {
inter_ti annot = 0;
match_results mr2 = Regexp::create_mr();
text_stream *conts = NULL;
if (plm == ARRAY_PLM) {
if (Regexp::match(&mr2, value, L" *--> *(%c*?) *")) conts = mr2.exp[0];
else if (Regexp::match(&mr2, value, L" *-> *(%c*?) *")) { conts = mr2.exp[0]; annot = BYTEARRAY_IANN; }
else if (Regexp::match(&mr2, value, L" *table *(%c*?) *")) { conts = mr2.exp[0]; annot = TABLEARRAY_IANN; }
else if (Regexp::match(&mr2, value, L" *buffer *(%c*?) *")) { conts = mr2.exp[0]; annot = BUFFERARRAY_IANN; }
else {
LOG("Identifier = <%S>, Value = <%S>", identifier, value);
TemplateReader::error("invalid Inform 6 array declaration in the template", NULL);
}
} else {
conts = value; annot = VERBARRAY_IANN;
}
if (annot != 0) Inter::Symbols::annotate_i(con_name, annot, 1);
inter_ti v1_pile[MAX_ASSIMILATED_ARRAY_ENTRIES];
inter_ti v2_pile[MAX_ASSIMILATED_ARRAY_ENTRIES];
int no_assimilated_array_entries = 0;
string_position spos = Str::start(conts);
int NT = 0, next_is_action = FALSE;
while (TRUE) {
TEMPORARY_TEXT(value)
if (next_is_action) WRITE_TO(value, "##");
@<Extract a token@>;
if ((next_is_action) && (action_kind_symbol)) {
CodeGen::Assimilate::ensure_action(I, P, value);
}
next_is_action = FALSE;
if (plm == ARRAY_PLM) {
if (Str::eq(value, I"+")) TemplateReader::error("Inform 6 array declaration in the template using operator '+'", NULL);
if (Str::eq(value, I"-")) TemplateReader::error("Inform 6 array declaration in the template using operator '-'", NULL);
if (Str::eq(value, I"*")) TemplateReader::error("Inform 6 array declaration in the template using operator '*'", NULL);
if (Str::eq(value, I"/")) TemplateReader::error("Inform 6 array declaration in the template using operator '/'", NULL);
}
if ((NT == 0) && (plm == VERB_PLM) && (Str::eq(value, I"meta"))) {
Inter::Symbols::annotate_i(con_name, METAVERB_IANN, 1);
} else {
@<Assimilate a value@>;
if (Str::len(value) == 0) break;
NT++;
if (no_assimilated_array_entries >= MAX_ASSIMILATED_ARRAY_ENTRIES) {
TemplateReader::error("excessively long Inform 6 array in the template", NULL);
break;
}
v1_pile[no_assimilated_array_entries] = v1;
v2_pile[no_assimilated_array_entries] = v2;
no_assimilated_array_entries++;
if ((plm == VERB_PLM) && (verb_directive_result_symbol) &&
(InterSymbolsTables::symbol_from_data_pair_and_table(v1, v2, Inter::Bookmarks::scope(IBM)) == verb_directive_result_symbol))
next_is_action = TRUE;
}
DISCARD_TEXT(value)
}
inter_tree_node *array_in_progress =
Inode::fill_3(IBM, CONSTANT_IST,
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), con_name),
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), list_of_unchecked_kind_symbol),
CONSTANT_INDIRECT_LIST, NULL, (inter_ti) Inter::Bookmarks::baseline(IBM) + 1);
int pos = array_in_progress->W.extent;
if (Inode::extend(array_in_progress, (unsigned int) (2*no_assimilated_array_entries)) == FALSE)
internal_error("can't extend frame");
for (int i=0; i<no_assimilated_array_entries; i++) {
array_in_progress->W.data[pos++] = v1_pile[i];
array_in_progress->W.data[pos++] = v2_pile[i];
}
Produce::guard(Inter::Defn::verify_construct(Inter::Bookmarks::package(IBM), array_in_progress));
Inter::Bookmarks::insert(IBM, array_in_progress);
if (plm == ARRAY_PLM) {
CodeGen::Assimilate::install_socket(I, con_name, identifier);
}
break;
}
}
@<Extract a token@> =
int squoted = FALSE, dquoted = FALSE, bracketed = 0;
while ((Str::in_range(spos)) && (Characters::is_whitespace(Str::get(spos))))
spos = Str::forward(spos);
while (Str::in_range(spos)) {
wchar_t c = Str::get(spos);
if ((Characters::is_whitespace(c)) && (squoted == FALSE) && (dquoted == FALSE) && (bracketed == 0)) break;
if ((c == '\'') && (dquoted == FALSE)) squoted = (squoted)?FALSE:TRUE;
if ((c == '\"') && (squoted == FALSE)) dquoted = (dquoted)?FALSE:TRUE;
if ((c == '(') && (dquoted == FALSE) && (squoted == FALSE)) bracketed++;
if ((c == ')') && (dquoted == FALSE) && (squoted == FALSE)) bracketed--;
PUT_TO(value, c);
spos = Str::forward(spos);
}
@<Assimilate a value@> =
if (Str::len(value) > 0) {
CodeGen::Assimilate::value(I, Inter::Bookmarks::package(IBM), IBM, value, &v1, &v2,
(plm == VERB_PLM)?TRUE:FALSE);
} else {
v1 = LITERAL_IVAL; v2 = 0;
}
@<Assimilate routine@> =
text_stream *identifier = NULL, *chain = NULL, *body = NULL;
match_results mr = Regexp::create_mr();
@<Parse the routine or stub header@>;
if (identifier) @<Act on parsed header@>;
@<Parse the routine or stub header@> =
text_stream *S = Inode::ID_to_text(P, P->W.data[MATTER_SPLAT_IFLD]);
if (P->W.data[PLM_SPLAT_IFLD] == ROUTINE_PLM) {
if (Regexp::match(&mr, S, L" *%[ *(%i+) *; *(%c*)")) {
identifier = mr.exp[0]; body = mr.exp[1];
} else if (Regexp::match(&mr, S, L" *%[ *(%i+) *(%c*?); *(%c*)")) {
identifier = mr.exp[0]; chain = mr.exp[1]; body = mr.exp[2];
} else {
TemplateReader::error("invalid Inform 6 routine declaration in the template", NULL);
}
} else {
if (Regexp::match(&mr, S, L" *%C+ *(%i+) (%d+);%c*")) {
identifier = mr.exp[0];
chain = Str::new();
int N = Str::atoi(mr.exp[1], 0);
if ((N<0) || (N>15)) N = 1;
for (int i=1; i<=N; i++) WRITE_TO(chain, "x%d ", i);
body = Str::duplicate(I"rfalse; ];");
} else TemplateReader::error("invalid Inform 6 Stub declaration in the template", NULL);
}
@<Act on parsed header@> =
inter_bookmark IBM_d = CodeGen::Assimilate::template_submodule(I, I"functions", P);
inter_bookmark *IBM = &IBM_d;
inter_symbol *fnt = function_ptype_symbol;
if (fnt == NULL) fnt = plain_ptype_symbol;
TEMPORARY_TEXT(fname)
WRITE_TO(fname, "%S_fn", identifier);
inter_package *FP = CodeGen::Assimilate::new_package_named(IBM, fname, fnt);
DISCARD_TEXT(fname)
inter_bookmark outer_save = Inter::Bookmarks::snapshot(IBM);
Inter::Bookmarks::set_current_package(IBM, FP);
TEMPORARY_TEXT(bname)
WRITE_TO(bname, "%S_B", identifier);
inter_package *IP = CodeGen::Assimilate::new_package_named(IBM, bname, code_ptype_symbol);
DISCARD_TEXT(bname)
inter_bookmark inner_save = Inter::Bookmarks::snapshot(IBM);
Inter::Bookmarks::set_current_package(IBM, IP);
inter_bookmark block_bookmark = Inter::Bookmarks::snapshot(IBM);
if (chain) {
string_position spos = Str::start(chain);
while (TRUE) {
TEMPORARY_TEXT(value)
@<Extract a token@>;
if (Str::len(value) == 0) break;
inter_symbol *loc_name = InterSymbolsTables::create_with_unique_name(Inter::Packages::scope(IP), value);
Inter::Symbols::local(loc_name);
Produce::guard(Inter::Local::new(IBM, loc_name, unchecked_kind_symbol, 0, (inter_ti) Inter::Bookmarks::baseline(IBM) + 1, NULL));
DISCARD_TEXT(value)
}
}
Produce::guard(Inter::Code::new(IBM, (int) (inter_ti) Inter::Bookmarks::baseline(IBM) + 1, NULL));
if (Str::len(body) > 0) {
int L = Str::len(body) - 1;
while ((L>0) && (Str::get_at(body, L) != ']')) L--;
while ((L>0) && (Characters::is_whitespace(Str::get_at(body, L-1)))) L--;
Str::truncate(body, L);
CodeGen::Assimilate::routine_body(IBM, IP, (inter_ti) Inter::Bookmarks::baseline(IBM) + 1, body, block_bookmark);
}
*IBM = inner_save;
inter_symbol *rsymb = CodeGen::Assimilate::make_socketed_symbol(I, identifier, Inter::Bookmarks::scope(IBM));
Inter::Symbols::annotate_i(rsymb, ASSIMILATED_IANN, 1);
Produce::guard(Inter::Constant::new_function(IBM,
InterSymbolsTables::id_from_symbol(I, FP, rsymb),
InterSymbolsTables::id_from_symbol(I, FP, unchecked_function_symbol),
IP,
(inter_ti) Inter::Bookmarks::baseline(IBM) + 1, NULL));
*IBM = outer_save;
CodeGen::Assimilate::install_socket(I, rsymb, rsymb->symbol_name);
InterTree::remove_node(P);
@ =
inter_package *CodeGen::Assimilate::new_package_named(inter_bookmark *IBM, text_stream *name, inter_symbol *ptype) {
inter_package *P = NULL;
Produce::guard(Inter::Package::new_package_named(IBM, name, TRUE,
ptype, (inter_ti) Inter::Bookmarks::baseline(IBM) + 1, NULL, &P));
return P;
}
void CodeGen::Assimilate::install_socket(inter_tree *I, inter_symbol *con_name, text_stream *aka_text) {
inter_symbol *socket = Inter::Connectors::find_socket(I, aka_text);
if (socket == NULL) Inter::Connectors::socket(I, aka_text, con_name);
}
inter_symbol *CodeGen::Assimilate::make_socketed_symbol(inter_tree *I, text_stream *identifier, inter_symbols_table *into_scope) {
inter_symbol *new_symbol = InterSymbolsTables::create_with_unique_name(into_scope, identifier);
CodeGen::Assimilate::install_socket(I, new_symbol, identifier);
return new_symbol;
}
@ =
void CodeGen::Assimilate::ensure_action(inter_tree *I, inter_tree_node *P, text_stream *value) {
if (Inter::Connectors::find_socket(I, value) == NULL) {
inter_bookmark IBM_d = CodeGen::Assimilate::template_submodule(I, I"actions", P);
inter_bookmark *IBM = &IBM_d;
inter_symbol *ptype = action_ptype_symbol;
if (ptype == NULL) ptype = plain_ptype_symbol;
TEMPORARY_TEXT(an)
WRITE_TO(an, "assim_action_%d", ++no_assimilated_actions);
Inter::Bookmarks::set_current_package(IBM, CodeGen::Assimilate::new_package_named(IBM, an, ptype));
DISCARD_TEXT(an)
inter_symbol *aid_s = InterSymbolsTables::create_with_unique_name(Inter::Bookmarks::scope(IBM), I"action_id");
Produce::guard(Inter::Constant::new_numerical(IBM,
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), aid_s),
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), unchecked_kind_symbol),
LITERAL_IVAL, 0, (inter_ti) Inter::Bookmarks::baseline(IBM) + 1, NULL));
Inter::Symbols::set_flag(aid_s, MAKE_NAME_UNIQUE);
inter_symbol *asymb = CodeGen::Assimilate::make_socketed_symbol(I, value, Inter::Bookmarks::scope(IBM));
TEMPORARY_TEXT(unsharped)
WRITE_TO(unsharped, "%SSub", value);
Str::delete_first_character(unsharped);
Str::delete_first_character(unsharped);
inter_symbol *txsymb = Inter::Connectors::find_socket(I, unsharped);
inter_symbol *xsymb = InterSymbolsTables::create_with_unique_name(Inter::Bookmarks::scope(IBM), unsharped);
if (txsymb) InterSymbolsTables::equate(xsymb, txsymb);
DISCARD_TEXT(unsharped)
Produce::guard(Inter::Constant::new_numerical(IBM,
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), asymb),
InterSymbolsTables::id_from_symbol(I, Inter::Bookmarks::package(IBM), action_kind_symbol),
LITERAL_IVAL, 10000, (inter_ti) Inter::Bookmarks::baseline(IBM) + 1, NULL));
Inter::Symbols::annotate_i(asymb, ACTION_IANN, 1);
}
}
@ =
void CodeGen::Assimilate::value(inter_tree *I, inter_package *pack, inter_bookmark *IBM, text_stream *S, inter_ti *val1, inter_ti *val2, int Verbal) {
int sign = 1, base = 10, from = 0, to = Str::len(S)-1, bad = FALSE;
if ((Str::get_at(S, from) == '\'') && (Str::get_at(S, to) == '\'')) {
from++;
to--;
TEMPORARY_TEXT(dw)
LOOP_THROUGH_TEXT(pos, S) {
if (pos.index < from) continue;
if (pos.index > to) continue;
int c = Str::get(pos);
PUT_TO(dw, c);
}
inter_ti ID = Inter::Warehouse::create_text(InterTree::warehouse(I), pack);
text_stream *glob_storage = Inter::Warehouse::get_text(InterTree::warehouse(I), ID);
Str::copy(glob_storage, dw);
*val1 = DWORD_IVAL; *val2 = ID;
DISCARD_TEXT(dw)
return;
}
if ((Str::get_at(S, from) == '"') && (Str::get_at(S, to) == '"')) {
from++;
to--;
TEMPORARY_TEXT(dw)
LOOP_THROUGH_TEXT(pos, S) {
if (pos.index < from) continue;
if (pos.index > to) continue;
int c = Str::get(pos);
PUT_TO(dw, c);
}
inter_ti ID = Inter::Warehouse::create_text(InterTree::warehouse(I), pack);
text_stream *glob_storage = Inter::Warehouse::get_text(InterTree::warehouse(I), ID);
Str::copy(glob_storage, dw);
*val1 = LITERAL_TEXT_IVAL; *val2 = ID;
DISCARD_TEXT(dw)
return;
}
if ((Str::get_at(S, from) == '(') && (Str::get_at(S, to) == ')')) { from++; to--; }
while (Characters::is_whitespace(Str::get_at(S, from))) from++;
while (Characters::is_whitespace(Str::get_at(S, to))) to--;
if (Str::get_at(S, from) == '-') { sign = -1; from++; }
else if (Str::get_at(S, from) == '$') {
from++; base = 16;
if (Str::get_at(S, from) == '$') {
from++; base = 2;
}
}
long long int N = 0;
LOOP_THROUGH_TEXT(pos, S) {
if (pos.index < from) continue;
if (pos.index > to) continue;
int c = Str::get(pos), d = 0;
if ((c >= 'a') && (c <= 'z')) d = c-'a'+10;
else if ((c >= 'A') && (c <= 'Z')) d = c-'A'+10;
else if ((c >= '0') && (c <= '9')) d = c-'0';
else { bad = TRUE; break; }
if (d > base) { bad = TRUE; break; }
N = base*N + (long long int) d;
if (pos.index > 34) { bad = TRUE; break; }
}
if (bad == FALSE) {
N = sign*N;
*val1 = LITERAL_IVAL; *val2 = (inter_ti) N; return;
}
if (Str::eq(S, I"true")) {
*val1 = LITERAL_IVAL; *val2 = 1; return;
}
if (Str::eq(S, I"false")) {
*val1 = LITERAL_IVAL; *val2 = 0; return;
}
if (Verbal) {
if ((Str::eq(S, I"*")) && (verb_directive_divider_symbol)) {
Inter::Symbols::to_data(I, pack, verb_directive_divider_symbol, val1, val2); return;
}
if ((Str::eq(S, I"->")) && (verb_directive_result_symbol)) {
Inter::Symbols::to_data(I, pack, verb_directive_result_symbol, val1, val2); return;
}
if ((Str::eq(S, I"reverse")) && (verb_directive_reverse_symbol)) {
Inter::Symbols::to_data(I, pack, verb_directive_reverse_symbol, val1, val2); return;
}
if ((Str::eq(S, I"/")) && (verb_directive_slash_symbol)) {
Inter::Symbols::to_data(I, pack, verb_directive_slash_symbol, val1, val2); return;
}
if ((Str::eq(S, I"special")) && (verb_directive_special_symbol)) {
Inter::Symbols::to_data(I, pack, verb_directive_special_symbol, val1, val2); return;
}
if ((Str::eq(S, I"number")) && (verb_directive_number_symbol)) {
Inter::Symbols::to_data(I, pack, verb_directive_number_symbol, val1, val2); return;
}
match_results mr = Regexp::create_mr();
if (Regexp::match(&mr, S, L"scope=(%i+)")) {
inter_symbol *symb = Inter::Connectors::find_socket(I, mr.exp[0]);
while ((symb) && (symb->equated_to)) symb = symb->equated_to;
if (symb) {
if (Inter::Symbols::read_annotation(symb, SCOPE_FILTER_IANN) != 1)
Inter::Symbols::annotate_i(symb, SCOPE_FILTER_IANN, 1);
Inter::Symbols::to_data(I, pack, symb, val1, val2); return;
}
}
if (Regexp::match(&mr, S, L"noun=(%i+)")) {
inter_symbol *symb = Inter::Connectors::find_socket(I, mr.exp[0]);
while ((symb) && (symb->equated_to)) symb = symb->equated_to;
if (symb) {
if (Inter::Symbols::read_annotation(symb, NOUN_FILTER_IANN) != 1)
Inter::Symbols::annotate_i(symb, NOUN_FILTER_IANN, 1);
Inter::Symbols::to_data(I, pack, symb, val1, val2); return;
}
}
}
inter_symbol *symb = Inter::Connectors::find_socket(I, S);
if (symb) {
Inter::Symbols::to_data(I, pack, symb, val1, val2); return;
}
inter_schema *sch = InterSchemas::from_text(S, FALSE, 0, NULL);
inter_symbol *mcc_name = CodeGen::Assimilate::compute_constant(I, pack, IBM, sch);
Inter::Symbols::to_data(I, pack, mcc_name, val1, val2);
}
inter_symbol *CodeGen::Assimilate::compute_constant(inter_tree *I, inter_package *pack, inter_bookmark *IBM, inter_schema *sch) {
inter_symbol *try = CodeGen::Assimilate::compute_constant_r(I, pack, IBM, sch->node_tree);
if (try) return try;
InterSchemas::log(DL, sch);
LOG("Forced to glob: %S\n", sch->converted_from);
WRITE_TO(STDERR, "Forced to glob: %S\n", sch->converted_from);
internal_error("Reduced to glob in assimilation");
inter_ti ID = Inter::Warehouse::create_text(InterTree::warehouse(I), pack);
text_stream *glob_storage = Inter::Warehouse::get_text(InterTree::warehouse(I), ID);
Str::copy(glob_storage, sch->converted_from);
inter_symbol *mcc_name = CodeGen::Assimilate::computed_constant_symbol(pack);
Produce::guard(Inter::Constant::new_numerical(IBM,
InterSymbolsTables::id_from_symbol(I, pack, mcc_name),
InterSymbolsTables::id_from_symbol(I, pack, unchecked_kind_symbol), GLOB_IVAL, ID,
(inter_ti) Inter::Bookmarks::baseline(IBM) + 1, NULL));
return mcc_name;
}
inter_symbol *CodeGen::Assimilate::compute_constant_r(inter_tree *I, inter_package *pack, inter_bookmark *IBM, inter_schema_node *isn) {
if (isn->isn_type == SUBEXPRESSION_ISNT)
return CodeGen::Assimilate::compute_constant_r(I, pack, IBM, isn->child_node);
if (isn->isn_type == OPERATION_ISNT) {
inter_ti op = 0;
if (isn->isn_clarifier == PLUS_BIP) op = CONSTANT_SUM_LIST;
else if (isn->isn_clarifier == TIMES_BIP) op = CONSTANT_PRODUCT_LIST;
else if (isn->isn_clarifier == MINUS_BIP) op = CONSTANT_DIFFERENCE_LIST;
else if (isn->isn_clarifier == DIVIDE_BIP) op = CONSTANT_QUOTIENT_LIST;
else if (isn->isn_clarifier == UNARYMINUS_BIP)
return CodeGen::Assimilate::compute_constant_unary_operation(I, pack, IBM, isn->child_node);
else return NULL;
inter_symbol *i1 = CodeGen::Assimilate::compute_constant_r(I, pack, IBM, isn->child_node);
inter_symbol *i2 = CodeGen::Assimilate::compute_constant_r(I, pack, IBM, isn->child_node->next_node);
if ((i1 == NULL) || (i2 == NULL)) return NULL;
return CodeGen::Assimilate::compute_constant_binary_operation(op, I, pack, IBM, i1, i2);
}
if (isn->isn_type == EXPRESSION_ISNT) {
inter_schema_token *t = isn->expression_tokens;
if (t->next) {
if (t->next->next) return NULL;
inter_symbol *i1 = CodeGen::Assimilate::compute_constant_eval(I, pack, IBM, t);
inter_symbol *i2 = CodeGen::Assimilate::compute_constant_eval(I, pack, IBM, t->next);
if ((i1 == NULL) || (i2 == NULL)) return NULL;
return CodeGen::Assimilate::compute_constant_binary_operation(CONSTANT_SUM_LIST, I, pack, IBM, i1, i2);
}
return CodeGen::Assimilate::compute_constant_eval(I, pack, IBM, t);
}
return NULL;
}
inter_symbol *CodeGen::Assimilate::compute_constant_eval(inter_tree *I, inter_package *pack, inter_bookmark *IBM, inter_schema_token *t) {
inter_ti v1 = UNDEF_IVAL, v2 = 0;
switch (t->ist_type) {
case IDENTIFIER_ISTT: {
inter_symbol *symb = Inter::Connectors::find_socket(I, t->material);
if (symb) return symb;
return Inter::Connectors::plug(I, t->material);
}
case NUMBER_ISTT:
case BIN_NUMBER_ISTT:
case HEX_NUMBER_ISTT:
if (t->constant_number >= 0) { v1 = LITERAL_IVAL; v2 = (inter_ti) t->constant_number; }
else if (Inter::Types::read_int_in_I6_notation(t->material, &v1, &v2) == FALSE)
internal_error("bad number");
break;
}
if (v1 == UNDEF_IVAL) return NULL;
inter_symbol *mcc_name = CodeGen::Assimilate::computed_constant_symbol(pack);
Produce::guard(Inter::Constant::new_numerical(IBM,
InterSymbolsTables::id_from_symbol(I, pack, mcc_name),
InterSymbolsTables::id_from_symbol(I, pack, unchecked_kind_symbol), v1, v2,
(inter_ti) Inter::Bookmarks::baseline(IBM) + 1, NULL));
return mcc_name;
}
inter_symbol *CodeGen::Assimilate::compute_constant_unary_operation(inter_tree *I, inter_package *pack, inter_bookmark *IBM, inter_schema_node *operand1) {
inter_symbol *i1 = CodeGen::Assimilate::compute_constant_r(I, pack, IBM, operand1);
if (i1 == NULL) return NULL;
inter_symbol *mcc_name = CodeGen::Assimilate::computed_constant_symbol(pack);
inter_tree_node *array_in_progress =
Inode::fill_3(IBM, CONSTANT_IST, InterSymbolsTables::id_from_IRS_and_symbol(IBM, mcc_name), InterSymbolsTables::id_from_symbol(I, pack, unchecked_kind_symbol), CONSTANT_DIFFERENCE_LIST, NULL, (inter_ti) Inter::Bookmarks::baseline(IBM) + 1);
int pos = array_in_progress->W.extent;
if (Inode::extend(array_in_progress, 4) == FALSE)
internal_error("can't extend frame");
array_in_progress->W.data[pos] = LITERAL_IVAL; array_in_progress->W.data[pos+1] = 0;
Inter::Symbols::to_data(I, pack, i1, &(array_in_progress->W.data[pos+2]), &(array_in_progress->W.data[pos+3]));
Produce::guard(Inter::Defn::verify_construct(Inter::Bookmarks::package(IBM), array_in_progress));
Inter::Bookmarks::insert(IBM, array_in_progress);
return mcc_name;
}
inter_symbol *CodeGen::Assimilate::compute_constant_binary_operation(inter_ti op, inter_tree *I, inter_package *pack, inter_bookmark *IBM, inter_symbol *i1, inter_symbol *i2) {
inter_symbol *mcc_name = CodeGen::Assimilate::computed_constant_symbol(pack);
inter_tree_node *array_in_progress =
Inode::fill_3(IBM, CONSTANT_IST, InterSymbolsTables::id_from_IRS_and_symbol(IBM, mcc_name), InterSymbolsTables::id_from_symbol(I, pack, unchecked_kind_symbol), op, NULL, (inter_ti) Inter::Bookmarks::baseline(IBM) + 1);
int pos = array_in_progress->W.extent;
if (Inode::extend(array_in_progress, 4) == FALSE)
internal_error("can't extend frame");
Inter::Symbols::to_data(I, pack, i1, &(array_in_progress->W.data[pos]), &(array_in_progress->W.data[pos+1]));
Inter::Symbols::to_data(I, pack, i2, &(array_in_progress->W.data[pos+2]), &(array_in_progress->W.data[pos+3]));
Produce::guard(Inter::Defn::verify_construct(Inter::Bookmarks::package(IBM), array_in_progress));
Inter::Bookmarks::insert(IBM, array_in_progress);
return mcc_name;
}
int ccs_count = 0;
inter_symbol *CodeGen::Assimilate::computed_constant_symbol(inter_package *pack) {
TEMPORARY_TEXT(NN)
WRITE_TO(NN, "Computed_Constant_Value_%d", ccs_count++);
inter_symbol *mcc_name = InterSymbolsTables::symbol_from_name_creating(Inter::Packages::scope(pack), NN);
Inter::Symbols::set_flag(mcc_name, MAKE_NAME_UNIQUE);
DISCARD_TEXT(NN)
return mcc_name;
}
typedef struct routine_body_request {
int assimilation_pass;
struct inter_bookmark position;
struct inter_bookmark block_bookmark;
struct package_request *enclosure;
struct inter_package *block_package;
int pass2_offset;
struct text_stream *body;
CLASS_DEFINITION
} routine_body_request;
int rb_splat_count = 1;
int CodeGen::Assimilate::routine_body(inter_bookmark *IBM, inter_package *block_package, inter_ti offset, text_stream *body, inter_bookmark bb) {
if (Str::is_whitespace(body)) return FALSE;
routine_body_request *req = CREATE(routine_body_request);
req->assimilation_pass = current_assimilation_pass;
req->block_bookmark = bb;
req->enclosure = Packaging::enclosure(Inter::Bookmarks::tree(IBM));
req->position = Packaging::bubble_at(IBM);
req->block_package = block_package;
req->pass2_offset = (int) offset - 2;
req->body = Str::duplicate(body);
return TRUE;
}
void CodeGen::Assimilate::function_bodies(inter_tree *I) {
routine_body_request *req;
LOOP_OVER(req, routine_body_request)
if (req->assimilation_pass == current_assimilation_pass) {
LOGIF(SCHEMA_COMPILATION, "=======\n\nRoutine (%S) len %d: '%S'\n\n", Inter::Packages::name(req->block_package), Str::len(req->body), req->body);
inter_schema *sch = InterSchemas::from_text(req->body, FALSE, 0, NULL);
if (Log::aspect_switched_on(SCHEMA_COMPILATION_DA)) {
if (sch == NULL) LOG("NULL SCH\n");
else if (sch->node_tree == NULL) {
LOG("Lint fail: Non-empty text but empty scheme\n");
internal_error("inter schema empty");
} else InterSchemas::log(DL, sch);
}
Site::set_cir(I, req->block_package);
Packaging::set_state(I, &(req->position), req->enclosure);
Produce::push_code_position(I, Produce::new_cip(I, &(req->position)), Inter::Bookmarks::snapshot(Packaging::at(I)));
value_holster VH = Holsters::new(INTER_VOID_VHMODE);
inter_symbols_table *scope1 = Inter::Packages::scope(req->block_package);
inter_package *template_package = Site::assimilation_package(I);
inter_symbols_table *scope2 = Inter::Packages::scope(template_package);
EmitInterSchemas::emit(I, &VH, sch, NULL, scope1, scope2, NULL, NULL);
Produce::pop_code_position(I);
Site::set_cir(I, NULL);
}
}