diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/compiler/compiler.zc | 76 | ||||
| -rw-r--r-- | src/lib/modules.txt | 5 | ||||
| -rw-r--r-- | src/lib/std.zc | 4 | ||||
| -rw-r--r-- | src/lsp/server.zc | 4 | ||||
| -rw-r--r-- | src/web/index.html | 5 |
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> |
