aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/compiler.zc76
-rw-r--r--src/lib/modules.txt5
-rw-r--r--src/lib/std.zc4
-rw-r--r--src/lsp/server.zc4
-rw-r--r--src/web/index.html5
5 files changed, 72 insertions, 22 deletions
diff --git a/src/compiler/compiler.zc b/src/compiler/compiler.zc
index 9c24af9..86e00c5 100644
--- a/src/compiler/compiler.zc
+++ b/src/compiler/compiler.zc
@@ -6742,7 +6742,7 @@ int brace_primary() {
// variable the value is.
int primary() {
effect_value = 0; xprojection = 0; if_value = 0;
- int n, i, s, c, k; word[8] bs0; int ft, mn, ms;
+ int n, i, s, c, k, npos, sv; word[8] bs0; int ft, mn, ms;
lv = 0; lvk = LV_NONE; xzero = 0; xbor = -1;
xconst = 0; xfloat = 0; xstr = 0; xlenloc = -1; xstamp = 0; xaf = 0; xvk = 0;
if (tk == T_FLT) { op(OP_FLIT); emit(tv); xvk = 2; xvv = tv; xfloat = 1; xty = tfloat; next(); return C_PLAIN; }
@@ -6839,6 +6839,7 @@ int primary() {
xty = tword;
return C_PLAIN;
}
+ npos = tpack();
next();
xty = tword;
if (s >= 0 && skind[s] == K_CONST) {
@@ -6863,9 +6864,17 @@ int primary() {
if (s >= 0 && skind[s] == K_GARR) { lit(sval[s]); if (stype[s]) xty = stype[s]; return C_PLAIN; }
if (s >= 0 && skind[s] == K_ENH) return enhcall(s);
if (s < 0 && is_op(s_dot)) {
- // Text.itoa with no std: a library's static function, reported as one missing name
peekat(0);
- if (pk_tk == T_ID && export_owner(methname(n, pk_tv))) { next(); n = methname(n, tv); next(); }
+ if (pk_tk == T_ID && lib_file(n)) {
+ // lib.name before include lib, for a library read from a file: the lexer only joins names of loaded modules
+ sv = tpack(); tunpack(npos);
+ errat(); rt.put_s("module access requires `include "); rt.put_s(n); rt.put_s(";`"); errend();
+ tunpack(sv);
+ word link = chk_resize(0, 0, 2); link[0] = missing_imports; link[1] = n; missing_imports = link;
+ next(); n = methname(n, tv); next();
+ }
+ // Text.itoa with no std: a library's static function, reported as one missing name
+ else if (pk_tk == T_ID && export_owner(methname(n, pk_tv))) { next(); n = methname(n, tv); next(); }
}
if (s < 0) s = fwdfn_at(n, callpos);
if (is_op(s_lt) && (sflag[s] & F_GEN)) { // f<int, char*>(...)
@@ -9629,21 +9638,53 @@ word lib_scan(char* s) {
while (list) { entry = list[0]; list[0] = back; back = list; list = entry; }
return back;
}
-// the libraries under src/lib, scanned once: std and icon are embedded, actor is read like its include
-word std_names, icon_names, actor_names; int names_read;
+// the embedded libraries, scanned once
+word std_names, icon_names; int names_read;
word lib_names(char* module) {
- char* save = incres;
- if (!names_read) {
- names_read = 1;
- std_names = lib_scan(std_text()); icon_names = lib_scan(icon_text());
- char* text = inc_open("src/lib/actor.zc");
- if (text) actor_names = lib_scan(text);
- rt.free(text);
- incres = save;
- }
+ if (!names_read) { names_read = 1; std_names = lib_scan(std_text()); icon_names = lib_scan(icon_text()); }
if (rt.eq_w(module, "std")) return std_names;
- if (rt.eq_w(module, "icon")) return icon_names;
- return actor_names;
+ return icon_names;
+}
+// the libraries read from files, named in src/lib/modules.txt (one per line, # starts a
+// comment), as a list of [next, name, declarations, scanned]. the compiler names none of them.
+word file_libs; int file_libs_read;
+word lib_files() {
+ int i = 0, a; word entry, tail = 0; char* save = incres;
+ if (file_libs_read) return file_libs;
+ file_libs_read = 1;
+ char* text = inc_open("src/lib/modules.txt");
+ incres = save;
+ if (!text) return 0;
+ while (text[i]) {
+ while (text[i] == 32 || text[i] == 9 || text[i] == 10 || text[i] == 13) i++;
+ if (text[i] == '#') { while (text[i] && text[i] != 10) i++; continue; }
+ a = i; while (isidc(text[i])) i++;
+ if (i == a) { if (text[i]) i++; continue; }
+ entry = chk_resize(0, 0, 4); entry[1] = lib_copy(text, a, i);
+ if (tail) tail[0] = entry; else file_libs = entry;
+ tail = entry;
+ }
+ rt.free(text);
+ return file_libs;
+}
+// the entry of a file library, or 0
+word lib_file(char* name) {
+ word p = lib_files();
+ while (p) { if (rt.eq_w(p[1], name)) return p; p = p[0]; }
+ return 0;
+}
+// a file library's declarations, read and scanned the first time they are needed
+word lib_file_names(word entry) {
+ char* save = incres;
+ if (entry[3]) return entry[2];
+ entry[3] = 1;
+ char* filename = inc_cat("src/lib", entry[1]); int length = rt.len_w(filename);
+ char* full = chk_resize(0, 0, length + 4); rt.copy_w(full, filename, length); rt.copy_w(full + length, ".zc", 4);
+ char* text = inc_open(full);
+ if (text) entry[2] = lib_scan(text);
+ rt.free(text);
+ incres = save;
+ return entry[2];
}
// where name is in a library's list: Text.itoa is itself, a bare itoa is a top-level
// declaration first, then a static method of some group. 0 when it is not there.
@@ -9678,7 +9719,8 @@ word export_owners(char* name) {
while (p) { export_add(p[1], export_in(p[1], name)); p = p[0]; }
export_add("std", lib_path(lib_names("std"), name));
export_add("icon", lib_path(lib_names("icon"), name));
- export_add("actor", lib_path(lib_names("actor"), name));
+ p = lib_files();
+ while (p) { export_add(p[1], lib_path(lib_file_names(p), name)); p = p[0]; }
return export_list;
}
char* export_owner(char* name) {
diff --git a/src/lib/modules.txt b/src/lib/modules.txt
new file mode 100644
index 0000000..7e157fd
--- /dev/null
+++ b/src/lib/modules.txt
@@ -0,0 +1,5 @@
+# libraries under src/lib that are read from their file by `include name;`.
+# std and icon are embedded in the compiler and are not listed. the compiler
+# reads this list only to suggest a library for a name it can't find, so a
+# library missing here still includes; it just isn't suggested.
+actor
diff --git a/src/lib/std.zc b/src/lib/std.zc
index dfa9841..f0bc390 100644
--- a/src/lib/std.zc
+++ b/src/lib/std.zc
@@ -65,9 +65,9 @@ int libinit() {
// returns it. writes go to the buffer instead of the terminal until end()
// stops it, so the buffer is a string once end() has run:
// let buf = capture.start();
-// put_s("hello world!"); // nothing on the terminal
+// rt.put_s("hello world!"); // nothing on the terminal
// capture.end(buf);
-// put_s(buf); // hello world
+// rt.put_s(buf); // hello world
// one capture at a time, and the buffer belongs to whoever holds it.
struct capture {
diff --git a/src/lsp/server.zc b/src/lsp/server.zc
index 2587c3b..1608c4c 100644
--- a/src/lsp/server.zc
+++ b/src/lsp/server.zc
@@ -3407,11 +3407,13 @@ int do_code_actions(int i) {
start = ca_start;
while (start > 0 && (hid(dc(base, start - 1)) || dc(base, start - 1) == '.')) start--;
dot = start; while (dot < ca_end && dc(base, dot) != '.') dot++;
+ // the error can sit on the qualifier alone: actor in actor.vector
+ if (dot == ca_end && dot < dsize[i] && dc(base, dot) == '.' && run.lib_file(hname) && !run.module_imported(hname)) { ca_add(hname, 0, 0); send(gen_code_actions); return 0; }
if (dot < ca_end) {
// rt.put_c without include rt needs only the include; Text.itoa without std is std.Text.itoa
char* owner = rt.new(dot - start + 1); k = start; n = 0;
while (k < dot) { owner[n] = dc(base, k); n++; k++; } owner[n] = 0;
- if (run.module_known(owner) || run.module_loaded(owner)) { if (!run.module_imported(owner)) ca_add(owner, 0, 0); }
+ if (run.module_known(owner) || run.module_loaded(owner) || run.lib_file(owner)) { if (!run.module_imported(owner)) ca_add(owner, 0, 0); }
else {
char* dotted = rt.new(ca_end - start + 1); k = start; n = 0;
while (k < ca_end) { dotted[n] = dc(base, k); n++; k++; } dotted[n] = 0;
diff --git a/src/web/index.html b/src/web/index.html
index fbc203d..8480d43 100644
--- a/src/web/index.html
+++ b/src/web/index.html
@@ -27,8 +27,9 @@
<button id="run">run</button>
<small id="status">loading</small>
</div>
- <textarea id="src" spellcheck="false">fn main() {
- put_s("hello from the browser\n");
+ <textarea id="src" spellcheck="false">include rt;
+fn main() {
+ rt.put_s("hello from the browser\n");
return 0;
}
</textarea>