From 07973d0704c66493203df4153411d4db8e9abfc1 Mon Sep 17 00:00:00 2001 From: Graham Nelson Date: Sat, 20 Jul 2019 07:18:40 +0100 Subject: [PATCH] Added link symbols and linkage packages --- docs/inter-module/2-bkm.html | 2 +- docs/inter-module/2-iibf.html | 17 +++++++++- docs/inter-module/2-pck.html | 24 +++++++++++++- docs/inter-module/2-st.html | 10 ++++++ docs/inter-module/2-sym.html | 20 +++++++----- docs/inter-module/3-dfn.html | 1 + docs/inter-module/4-tpc2.html | 6 ++-- docs/inter-module/4-tpc3.html | 2 ++ docs/inter-module/4-tsc.html | 28 ++++++++++++++--- docs/words-module/2-vcb.html | 3 ++ inter/Tests/Valid/linkage.intert | 31 +++++++++++++++++++ .../Chapter 2/Inter in Binary Files.w | 17 +++++++++- inter/inter-module/Chapter 2/Packages.w | 18 ++++++++++- inter/inter-module/Chapter 2/Symbols Tables.w | 8 +++++ inter/inter-module/Chapter 2/Symbols.w | 20 +++++++----- inter/inter-module/Chapter 3/Definition.w | 1 + .../Chapter 4/The Package Construct.w | 2 ++ .../Chapter 4/The PackageType Construct.w | 6 ++-- .../Chapter 4/The Symbol Construct.w | 28 ++++++++++++++--- 19 files changed, 211 insertions(+), 33 deletions(-) create mode 100644 inter/Tests/Valid/linkage.intert diff --git a/docs/inter-module/2-bkm.html b/docs/inter-module/2-bkm.html index 6466682ae..6a3abd607 100644 --- a/docs/inter-module/2-bkm.html +++ b/docs/inter-module/2-bkm.html @@ -148,7 +148,7 @@

The function Inter::Bookmarks::scope is used in 4/tmc (§2), 4/tsc (§1), 4/tpc (§2), 4/tac (§2), 4/tpc2 (§2), 4/tpc3 (§2), 4/tkc (§2), 4/tdc (§2), 4/tvc2 (§2), 4/tcc2 (§2), 4/trc (§2), 4/tic (§2), 4/tpc4 (§2), 4/tpc5 (§2), 4/tpc6 (§2), 4/tpc7 (§2), 5/tlc2 (§2), 5/tic (§2), 5/trc (§2), 5/tvc (§2), 5/tcc2 (§2).

-

The function Inter::Bookmarks::package is used in 2/st (§8, §9), 2/frm (§3), 3/dfn (§5), 4/tnc (§1), 4/tcc (§1), 4/tmc (§2), 4/tvc (§2), 4/tpc (§2), 4/tlc (§2), 4/tac (§2), 4/tpc2 (§2), 4/tpc3 (§2), 4/tkc (§2), 4/tdc (§2), 4/tvc2 (§2), 4/tcc2 (§2), 4/trc (§2), 4/tic (§2), 4/tpc4 (§2), 4/tpc5 (§2), 4/tpc6 (§2), 4/tpc7 (§2), 5/tlc (§2), 5/tlc2 (§2), 5/tic (§2), 5/trc (§2), 5/tvc (§2), 5/tlc3 (§2), 5/tcc (§2), 5/tec (§2), 5/trc2 (§2), 5/tcc2 (§2), 5/tsc (§2).

+

The function Inter::Bookmarks::package is used in 2/st (§8, §9), 2/frm (§3), 3/dfn (§5), 4/tnc (§1), 4/tcc (§1), 4/tmc (§2), 4/tsc (§1), 4/tvc (§2), 4/tpc (§2), 4/tlc (§2), 4/tac (§2), 4/tpc2 (§2), 4/tpc3 (§2), 4/tkc (§2), 4/tdc (§2), 4/tvc2 (§2), 4/tcc2 (§2), 4/trc (§2), 4/tic (§2), 4/tpc4 (§2), 4/tpc5 (§2), 4/tpc6 (§2), 4/tpc7 (§2), 5/tlc (§2), 5/tlc2 (§2), 5/tic (§2), 5/trc (§2), 5/tvc (§2), 5/tlc3 (§2), 5/tcc (§2), 5/tec (§2), 5/trc2 (§2), 5/tcc2 (§2), 5/tsc (§2).



diff --git a/docs/inter-module/2-iibf.html b/docs/inter-module/2-iibf.html index 4dcf5c364..c45e7dedd 100644 --- a/docs/inter-module/2-iibf.html +++ b/docs/inter-module/2-iibf.html @@ -311,8 +311,18 @@ that's the end of the list and therefore the block. if (Inter::Defn::is_invalid(IA)) Inter::Binary::read_error(&eloc, ftell(fh), I"invalid annotation"); Inter::Symbols::annotate(I, S, IA); } + if (S->symbol_scope == LINK_ISYMS) { + S->equated_name = Str::new(); + while (TRUE) { + unsigned int c; + if (BinaryFiles::read_int32(fh, &c) == FALSE) + Inter::Binary::read_error(&eloc, ftell(fh), I"bytecode incomplete"); + if (c == 0) break; + PUT_TO(S->equated_name, (wchar_t) c); + } + } - if (S) LOGIF(INTER_BINARY, "Read symbol $3\n", S); + LOGIF(INTER_BINARY, "Read symbol $3\n", S); DISCARD_TEXT(name); DISCARD_TEXT(trans); } @@ -349,6 +359,11 @@ that's the end of the list and therefore the block. BinaryFiles::write_int32(fh, (unsigned int) c1); BinaryFiles::write_int32(fh, (unsigned int) c2); } + if (symb->symbol_scope == LINK_ISYMS) { + LOOP_THROUGH_TEXT(pos, symb->equated_name) + BinaryFiles::write_int32(fh, (unsigned int) Str::get(pos)); + BinaryFiles::write_int32(fh, 0); + } } } } diff --git a/docs/inter-module/2-pck.html b/docs/inter-module/2-pck.html index ffb1ec84a..460d61623 100644 --- a/docs/inter-module/2-pck.html +++ b/docs/inter-module/2-pck.html @@ -36,7 +36,8 @@
     define CODELIKE_PACKAGE_FLAG 1
-    define USED_PACKAGE_FLAG 2
+    define LINKAGE_PACKAGE_FLAG 2
+    define USED_PACKAGE_FLAG 4
 

§3.

@@ -63,6 +64,17 @@ } } + int Inter::Packages::is_linklike(inter_package *pack) { + if ((pack) && (pack->package_flags & LINKAGE_PACKAGE_FLAG)) return TRUE; + return FALSE; + } + + void Inter::Packages::make_linklike(inter_package *pack) { + if (pack) { + pack->package_flags |= LINKAGE_PACKAGE_FLAG; + } + } + inter_package *Inter::Packages::parent(inter_package *pack) { if (pack) { inter_frame D = Inter::Symbols::defining_frame(pack->package_name); @@ -207,6 +219,10 @@ } return NULL; } + + void Inter::Packages::wrap(inter_package *P) { + } +

@@ -217,6 +233,10 @@

The function Inter::Packages::make_codelike is used in 2/iibf (§1.5.3), 4/tpc3 (§2).

+

The function Inter::Packages::is_linklike is used in 2/st (§10), 4/tsc (§1).

+ +

The function Inter::Packages::make_linklike is used in 4/tpc3 (§2).

+

The function Inter::Packages::parent is used in 2/st (§11), 2/iibf (§1.1.3.3), 3/dfn (§5).

The function Inter::Packages::unmark_all appears nowhere else.

@@ -257,6 +277,8 @@

The function Inter::Packages::read_metadata appears nowhere else.

+

The function Inter::Packages::wrap appears nowhere else.

+

diff --git a/docs/inter-module/2-st.html b/docs/inter-module/2-st.html index ce0ed99fe..7220e39e4 100644 --- a/docs/inter-module/2-st.html +++ b/docs/inter-module/2-st.html @@ -440,6 +440,13 @@ a global symbol in any non-global context. S_from->symbol_scope = EXTERNAL_ISYMS; } + void Inter::SymbolsTables::link(inter_symbol *S_from, text_stream *name) { + if ((S_from == NULL) || (name == NULL)) internal_error("bad link equation"); + S_from->equated_to = NULL; + S_from->equated_name = Str::duplicate(name); + S_from->symbol_scope = LINK_ISYMS; + } + void Inter::SymbolsTables::resolve_forward_references(inter_repository *I, inter_error_location *eloc) { Inter::traverse_tree(I, Inter::SymbolsTables::rfr_visitor, eloc, NULL, PACKAGE_IST); } @@ -447,6 +454,7 @@ a global symbol in any non-global context. void Inter::SymbolsTables::rfr_visitor(inter_repository *I, inter_frame P, void *state) { inter_error_location *eloc = (inter_error_location *) state; inter_package *pack = Inter::Package::defined_by_frame(P); + if (Inter::Packages::is_linklike(pack)) return; inter_symbols_table *T = Inter::Packages::scope(pack); for (int i=0; i<T->size; i++) { inter_symbol *symb = T->symbol_array[i]; @@ -466,6 +474,8 @@ a global symbol in any non-global context.

The function Inter::SymbolsTables::equate_textual is used in 4/tsc (§1).

+

The function Inter::SymbolsTables::link is used in 4/tsc (§1).

+

The function Inter::SymbolsTables::resolve_forward_references is used in 2/iitf (§1).

The function Inter::SymbolsTables::rfr_visitor appears nowhere else.

diff --git a/docs/inter-module/2-sym.html b/docs/inter-module/2-sym.html index f88ddb10f..03d14943a 100644 --- a/docs/inter-module/2-sym.html +++ b/docs/inter-module/2-sym.html @@ -32,6 +32,7 @@ enum PRIVATE_ISYMS from 1 enum PUBLIC_ISYMS enum EXTERNAL_ISYMS + enum LINK_ISYMS typedef struct inter_symbol { inter_t symbol_ID; struct inter_symbols_table *owning_table; @@ -141,6 +142,7 @@ case PRIVATE_ISYMS: WRITE("private"); break; case PUBLIC_ISYMS: WRITE("public"); break; case EXTERNAL_ISYMS: WRITE("external"); break; + case LINK_ISYMS: WRITE("link"); break; default: internal_error("unknown symbol type"); break; } WRITE(" "); @@ -153,13 +155,17 @@ } WRITE(" %S", mark->symbol_name); if (Inter::Symbols::get_flag(mark, MAKE_NAME_UNIQUE)) WRITE("*"); - text_stream *trans_name = Inter::Symbols::get_translate(mark); - if (Str::len(trans_name) > 0) - WRITE(" -> %S", trans_name); - inter_symbol *eq = mark->equated_to; - if (eq) { - WRITE(" == "); - Inter::SymbolsTables::symbol_to_url_name(OUT, eq); + if (mark->symbol_scope == LINK_ISYMS) { + WRITE(" == %S", mark->equated_name); + } else { + text_stream *trans_name = Inter::Symbols::get_translate(mark); + if (Str::len(trans_name) > 0) + WRITE(" -> %S", trans_name); + inter_symbol *eq = mark->equated_to; + if (eq) { + WRITE(" == "); + Inter::SymbolsTables::symbol_to_url_name(OUT, eq); + } } } diff --git a/docs/inter-module/3-dfn.html b/docs/inter-module/3-dfn.html index 1f2b95e72..397649843 100644 --- a/docs/inter-module/3-dfn.html +++ b/docs/inter-module/3-dfn.html @@ -88,6 +88,7 @@ inter_symbol *plain_packagetype = NULL; inter_symbol *code_packagetype = NULL; + inter_symbol *linkage_packagetype = NULL;

diff --git a/docs/inter-module/4-tpc2.html b/docs/inter-module/4-tpc2.html index 70e3b1b3e..9c30aa9e8 100644 --- a/docs/inter-module/4-tpc2.html +++ b/docs/inter-module/4-tpc2.html @@ -57,8 +57,10 @@ } inter_error_message *Inter::PackageType::new_packagetype(inter_bookmark *IBM, inter_symbol *ptype, inter_t level, inter_error_location *eloc) { - if (plain_packagetype == NULL) plain_packagetype = ptype; - else if (code_packagetype == NULL) code_packagetype = ptype; + text_stream *name = ptype->symbol_name; + if (Str::eq(name, I"_plain")) plain_packagetype = ptype; + if (Str::eq(name, I"_code")) code_packagetype = ptype; + if (Str::eq(name, I"_linkage")) linkage_packagetype = ptype; inter_frame P = Inter::Frame::fill_1(IBM, PACKAGETYPE_IST, Inter::SymbolsTables::id_from_IRS_and_symbol(IBM, ptype), eloc, level); inter_error_message *E = Inter::Defn::verify_construct(Inter::Bookmarks::package(IBM), P); diff --git a/docs/inter-module/4-tpc3.html b/docs/inter-module/4-tpc3.html index 6b8f15af1..6664c7382 100644 --- a/docs/inter-module/4-tpc3.html +++ b/docs/inter-module/4-tpc3.html @@ -77,6 +77,8 @@ inter_package *pack = Inter::Packages::from_PID(IBM->read_into, PID); Inter::Packages::set_name(pack, package_name); if (ptype_name == code_packagetype) Inter::Packages::make_codelike(pack); + if ((linkage_packagetype) && (ptype_name == linkage_packagetype)) + Inter::Packages::make_linklike(pack); Inter::Packages::set_scope(pack, Inter::Package::local_symbols(package_name)); P.data[PID_PACKAGE_IFLD] = PID; diff --git a/docs/inter-module/4-tsc.html b/docs/inter-module/4-tsc.html index 01c4e91c4..bdea99e5c 100644 --- a/docs/inter-module/4-tsc.html +++ b/docs/inter-module/4-tsc.html @@ -71,6 +71,7 @@ if (Str::eq(ilp->mr.exp[0], I"private")) name_name->symbol_scope = PRIVATE_ISYMS; else if (Str::eq(ilp->mr.exp[0], I"public")) name_name->symbol_scope = PUBLIC_ISYMS; else if (Str::eq(ilp->mr.exp[0], I"external")) name_name->symbol_scope = EXTERNAL_ISYMS; + else if (Str::eq(ilp->mr.exp[0], I"link")) name_name->symbol_scope = LINK_ISYMS; else { *E = Inter::Errors::plain(I"unknown scope keyword", eloc); return; } if (Str::eq(ilp->mr.exp[1], I"label")) name_name->symbol_type = LABEL_ISYMT; @@ -79,11 +80,28 @@ else if (Str::eq(ilp->mr.exp[1], I"packagetype")) name_name->symbol_type = PTYPE_ISYMT; else { *E = Inter::Errors::plain(I"unknown symbol-type keyword", eloc); return; } - if (trans_name) Inter::Symbols::set_translate(name_name, trans_name); - if (equate_name) { - inter_symbol *eq = Inter::SymbolsTables::url_name_to_symbol(IBM->read_into, Inter::Bookmarks::scope(IBM), equate_name); - if (eq == NULL) Inter::SymbolsTables::equate_textual(name_name, equate_name); - else Inter::SymbolsTables::equate(name_name, eq); + if ((trans_name) && (equate_name)) { + *E = Inter::Errors::plain(I"a symbol cannot be both translated and equated", eloc); return; + } + + if (Inter::Packages::is_linklike(Inter::Bookmarks::package(IBM))) { + if (name_name->symbol_scope != LINK_ISYMS) { + *E = Inter::Errors::plain(I"in a _linkage package, all symbols must be links", eloc); return; + } + if (equate_name) Inter::SymbolsTables::link(name_name, equate_name); + else { + *E = Inter::Errors::plain(I"link symbol not equated", eloc); return; + } + } else { + if (name_name->symbol_scope == LINK_ISYMS) { + *E = Inter::Errors::plain(I"links may only occur in a _linkage package", eloc); return; + } + if (trans_name) Inter::Symbols::set_translate(name_name, trans_name); + if (equate_name) { + inter_symbol *eq = Inter::SymbolsTables::url_name_to_symbol(IBM->read_into, Inter::Bookmarks::scope(IBM), equate_name); + if (eq == NULL) Inter::SymbolsTables::equate_textual(name_name, equate_name); + else Inter::SymbolsTables::equate(name_name, eq); + } } if (starred) { diff --git a/docs/words-module/2-vcb.html b/docs/words-module/2-vcb.html index 0d95022c3..d0f7daf82 100644 --- a/docs/words-module/2-vcb.html +++ b/docs/words-module/2-vcb.html @@ -507,6 +507,9 @@ These begin empty.

§16. And that leaves only one routine: for finding the unique vocabulary entry pointer associated with the material in text. We search the hash table to see if we have the word already, and if not, we add it. +Either way, we return a valid pointer. (Compare Isaiah 55:11, "So shall +my word be that goeth forth out of my mouth: it shall not return unto +me void.")

It is in order to set the initial values of the flags for the new diff --git a/inter/Tests/Valid/linkage.intert b/inter/Tests/Valid/linkage.intert new file mode 100644 index 000000000..2383fa3c3 --- /dev/null +++ b/inter/Tests/Valid/linkage.intert @@ -0,0 +1,31 @@ +packagetype _plain +packagetype _code +packagetype _linkage + +package main _plain + symbol public misc K_number + symbol public misc C_alpha + symbol public misc sub + symbol public misc references + kind K_number int32 + constant C_alpha K_number = 1 + package references _linkage + symbol link misc faraway == /main/template/timbuktu + symbol link misc distant == /main/template/ultima/thule + package sub _plain + symbol public misc C_beta + symbol public misc subsub + symbol external misc C_gamma == /main/sub/subsub/C_gamma + symbol external misc C_alpha == /main/C_alpha + symbol external misc K_number == /main/K_number + symbol public misc C_epislon + constant C_beta K_number = C_alpha + package subsub _plain + symbol public misc C_gamma + symbol public misc C_delta + symbol external misc C_alpha == /main/C_alpha + symbol external misc K_number == /main/K_number + symbol external misc C_beta == /main/sub/C_beta + constant C_gamma K_number = C_alpha + constant C_delta K_number = C_beta + constant C_epislon K_number = C_gamma diff --git a/inter/inter-module/Chapter 2/Inter in Binary Files.w b/inter/inter-module/Chapter 2/Inter in Binary Files.w index c144357e3..83184a757 100644 --- a/inter/inter-module/Chapter 2/Inter in Binary Files.w +++ b/inter/inter-module/Chapter 2/Inter in Binary Files.w @@ -193,8 +193,18 @@ that's the end of the list and therefore the block. if (Inter::Defn::is_invalid(IA)) Inter::Binary::read_error(&eloc, ftell(fh), I"invalid annotation"); Inter::Symbols::annotate(I, S, IA); } + if (S->symbol_scope == LINK_ISYMS) { + S->equated_name = Str::new(); + while (TRUE) { + unsigned int c; + if (BinaryFiles::read_int32(fh, &c) == FALSE) + Inter::Binary::read_error(&eloc, ftell(fh), I"bytecode incomplete"); + if (c == 0) break; + PUT_TO(S->equated_name, (wchar_t) c); + } + } - if (S) LOGIF(INTER_BINARY, "Read symbol $3\n", S); + LOGIF(INTER_BINARY, "Read symbol $3\n", S); DISCARD_TEXT(name); DISCARD_TEXT(trans); } @@ -221,6 +231,11 @@ that's the end of the list and therefore the block. BinaryFiles::write_int32(fh, (unsigned int) c1); BinaryFiles::write_int32(fh, (unsigned int) c2); } + if (symb->symbol_scope == LINK_ISYMS) { + LOOP_THROUGH_TEXT(pos, symb->equated_name) + BinaryFiles::write_int32(fh, (unsigned int) Str::get(pos)); + BinaryFiles::write_int32(fh, 0); + } } } } diff --git a/inter/inter-module/Chapter 2/Packages.w b/inter/inter-module/Chapter 2/Packages.w index d99aa5774..dcdb4c08d 100644 --- a/inter/inter-module/Chapter 2/Packages.w +++ b/inter/inter-module/Chapter 2/Packages.w @@ -17,7 +17,8 @@ typedef struct inter_package { @ @d CODELIKE_PACKAGE_FLAG 1 -@d USED_PACKAGE_FLAG 2 +@d LINKAGE_PACKAGE_FLAG 2 +@d USED_PACKAGE_FLAG 4 @ = inter_package *Inter::Packages::new(inter_repository *I, inter_t n) { @@ -41,6 +42,17 @@ void Inter::Packages::make_codelike(inter_package *pack) { } } +int Inter::Packages::is_linklike(inter_package *pack) { + if ((pack) && (pack->package_flags & LINKAGE_PACKAGE_FLAG)) return TRUE; + return FALSE; +} + +void Inter::Packages::make_linklike(inter_package *pack) { + if (pack) { + pack->package_flags |= LINKAGE_PACKAGE_FLAG; + } +} + inter_package *Inter::Packages::parent(inter_package *pack) { if (pack) { inter_frame D = Inter::Symbols::defining_frame(pack->package_name); @@ -185,3 +197,7 @@ text_stream *Inter::Packages::read_metadata(inter_package *P, text_stream *key) } return NULL; } + +void Inter::Packages::wrap(inter_package *P) { +} + diff --git a/inter/inter-module/Chapter 2/Symbols Tables.w b/inter/inter-module/Chapter 2/Symbols Tables.w index 4258c387d..09e474692 100644 --- a/inter/inter-module/Chapter 2/Symbols Tables.w +++ b/inter/inter-module/Chapter 2/Symbols Tables.w @@ -325,6 +325,13 @@ void Inter::SymbolsTables::equate_textual(inter_symbol *S_from, text_stream *nam S_from->symbol_scope = EXTERNAL_ISYMS; } +void Inter::SymbolsTables::link(inter_symbol *S_from, text_stream *name) { + if ((S_from == NULL) || (name == NULL)) internal_error("bad link equation"); + S_from->equated_to = NULL; + S_from->equated_name = Str::duplicate(name); + S_from->symbol_scope = LINK_ISYMS; +} + void Inter::SymbolsTables::resolve_forward_references(inter_repository *I, inter_error_location *eloc) { Inter::traverse_tree(I, Inter::SymbolsTables::rfr_visitor, eloc, NULL, PACKAGE_IST); } @@ -332,6 +339,7 @@ void Inter::SymbolsTables::resolve_forward_references(inter_repository *I, inter void Inter::SymbolsTables::rfr_visitor(inter_repository *I, inter_frame P, void *state) { inter_error_location *eloc = (inter_error_location *) state; inter_package *pack = Inter::Package::defined_by_frame(P); + if (Inter::Packages::is_linklike(pack)) return; inter_symbols_table *T = Inter::Packages::scope(pack); for (int i=0; isize; i++) { inter_symbol *symb = T->symbol_array[i]; diff --git a/inter/inter-module/Chapter 2/Symbols.w b/inter/inter-module/Chapter 2/Symbols.w index 9ac9ea850..67010ec7c 100644 --- a/inter/inter-module/Chapter 2/Symbols.w +++ b/inter/inter-module/Chapter 2/Symbols.w @@ -16,6 +16,7 @@ To manage named symbols in inter code. @e PRIVATE_ISYMS from 1 @e PUBLIC_ISYMS @e EXTERNAL_ISYMS +@e LINK_ISYMS = typedef struct inter_symbol { @@ -99,6 +100,7 @@ void Inter::Symbols::write_declaration(OUTPUT_STREAM, inter_symbol *mark, int N) case PRIVATE_ISYMS: WRITE("private"); break; case PUBLIC_ISYMS: WRITE("public"); break; case EXTERNAL_ISYMS: WRITE("external"); break; + case LINK_ISYMS: WRITE("link"); break; default: internal_error("unknown symbol type"); break; } WRITE(" "); @@ -111,13 +113,17 @@ void Inter::Symbols::write_declaration(OUTPUT_STREAM, inter_symbol *mark, int N) } WRITE(" %S", mark->symbol_name); if (Inter::Symbols::get_flag(mark, MAKE_NAME_UNIQUE)) WRITE("*"); - text_stream *trans_name = Inter::Symbols::get_translate(mark); - if (Str::len(trans_name) > 0) - WRITE(" -> %S", trans_name); - inter_symbol *eq = mark->equated_to; - if (eq) { - WRITE(" == "); - Inter::SymbolsTables::symbol_to_url_name(OUT, eq); + if (mark->symbol_scope == LINK_ISYMS) { + WRITE(" == %S", mark->equated_name); + } else { + text_stream *trans_name = Inter::Symbols::get_translate(mark); + if (Str::len(trans_name) > 0) + WRITE(" -> %S", trans_name); + inter_symbol *eq = mark->equated_to; + if (eq) { + WRITE(" == "); + Inter::SymbolsTables::symbol_to_url_name(OUT, eq); + } } } diff --git a/inter/inter-module/Chapter 3/Definition.w b/inter/inter-module/Chapter 3/Definition.w index 5c8971b97..912f01485 100644 --- a/inter/inter-module/Chapter 3/Definition.w +++ b/inter/inter-module/Chapter 3/Definition.w @@ -66,6 +66,7 @@ inter_construct *Inter::Defn::create_construct(inter_t ID, wchar_t *syntax, inter_symbol *plain_packagetype = NULL; inter_symbol *code_packagetype = NULL; +inter_symbol *linkage_packagetype = NULL; @ diff --git a/inter/inter-module/Chapter 4/The Package Construct.w b/inter/inter-module/Chapter 4/The Package Construct.w index 8297a57ca..a0938e8b4 100644 --- a/inter/inter-module/Chapter 4/The Package Construct.w +++ b/inter/inter-module/Chapter 4/The Package Construct.w @@ -57,6 +57,8 @@ inter_error_message *Inter::Package::new_package(inter_bookmark *IBM, inter_symb inter_package *pack = Inter::Packages::from_PID(IBM->read_into, PID); Inter::Packages::set_name(pack, package_name); if (ptype_name == code_packagetype) Inter::Packages::make_codelike(pack); + if ((linkage_packagetype) && (ptype_name == linkage_packagetype)) + Inter::Packages::make_linklike(pack); Inter::Packages::set_scope(pack, Inter::Package::local_symbols(package_name)); P.data[PID_PACKAGE_IFLD] = PID; diff --git a/inter/inter-module/Chapter 4/The PackageType Construct.w b/inter/inter-module/Chapter 4/The PackageType Construct.w index b596262ad..d1a9e15ed 100644 --- a/inter/inter-module/Chapter 4/The PackageType Construct.w +++ b/inter/inter-module/Chapter 4/The PackageType Construct.w @@ -38,8 +38,10 @@ void Inter::PackageType::read(inter_construct *IC, inter_bookmark *IBM, inter_li } inter_error_message *Inter::PackageType::new_packagetype(inter_bookmark *IBM, inter_symbol *ptype, inter_t level, inter_error_location *eloc) { - if (plain_packagetype == NULL) plain_packagetype = ptype; - else if (code_packagetype == NULL) code_packagetype = ptype; + text_stream *name = ptype->symbol_name; + if (Str::eq(name, I"_plain")) plain_packagetype = ptype; + if (Str::eq(name, I"_code")) code_packagetype = ptype; + if (Str::eq(name, I"_linkage")) linkage_packagetype = ptype; inter_frame P = Inter::Frame::fill_1(IBM, PACKAGETYPE_IST, Inter::SymbolsTables::id_from_IRS_and_symbol(IBM, ptype), eloc, level); inter_error_message *E = Inter::Defn::verify_construct(Inter::Bookmarks::package(IBM), P); diff --git a/inter/inter-module/Chapter 4/The Symbol Construct.w b/inter/inter-module/Chapter 4/The Symbol Construct.w index 796c71f9b..dbac4714d 100644 --- a/inter/inter-module/Chapter 4/The Symbol Construct.w +++ b/inter/inter-module/Chapter 4/The Symbol Construct.w @@ -59,6 +59,7 @@ void Inter::Symbol::read(inter_construct *IC, inter_bookmark *IBM, inter_line_pa if (Str::eq(ilp->mr.exp[0], I"private")) name_name->symbol_scope = PRIVATE_ISYMS; else if (Str::eq(ilp->mr.exp[0], I"public")) name_name->symbol_scope = PUBLIC_ISYMS; else if (Str::eq(ilp->mr.exp[0], I"external")) name_name->symbol_scope = EXTERNAL_ISYMS; + else if (Str::eq(ilp->mr.exp[0], I"link")) name_name->symbol_scope = LINK_ISYMS; else { *E = Inter::Errors::plain(I"unknown scope keyword", eloc); return; } if (Str::eq(ilp->mr.exp[1], I"label")) name_name->symbol_type = LABEL_ISYMT; @@ -67,11 +68,28 @@ void Inter::Symbol::read(inter_construct *IC, inter_bookmark *IBM, inter_line_pa else if (Str::eq(ilp->mr.exp[1], I"packagetype")) name_name->symbol_type = PTYPE_ISYMT; else { *E = Inter::Errors::plain(I"unknown symbol-type keyword", eloc); return; } - if (trans_name) Inter::Symbols::set_translate(name_name, trans_name); - if (equate_name) { - inter_symbol *eq = Inter::SymbolsTables::url_name_to_symbol(IBM->read_into, Inter::Bookmarks::scope(IBM), equate_name); - if (eq == NULL) Inter::SymbolsTables::equate_textual(name_name, equate_name); - else Inter::SymbolsTables::equate(name_name, eq); + if ((trans_name) && (equate_name)) { + *E = Inter::Errors::plain(I"a symbol cannot be both translated and equated", eloc); return; + } + + if (Inter::Packages::is_linklike(Inter::Bookmarks::package(IBM))) { + if (name_name->symbol_scope != LINK_ISYMS) { + *E = Inter::Errors::plain(I"in a _linkage package, all symbols must be links", eloc); return; + } + if (equate_name) Inter::SymbolsTables::link(name_name, equate_name); + else { + *E = Inter::Errors::plain(I"link symbol not equated", eloc); return; + } + } else { + if (name_name->symbol_scope == LINK_ISYMS) { + *E = Inter::Errors::plain(I"links may only occur in a _linkage package", eloc); return; + } + if (trans_name) Inter::Symbols::set_translate(name_name, trans_name); + if (equate_name) { + inter_symbol *eq = Inter::SymbolsTables::url_name_to_symbol(IBM->read_into, Inter::Bookmarks::scope(IBM), equate_name); + if (eq == NULL) Inter::SymbolsTables::equate_textual(name_name, equate_name); + else Inter::SymbolsTables::equate(name_name, eq); + } } if (starred) {