Skip to content

Commit dc64aa3

Browse files
committed
feat(diag): report a missing std-namespace import in Xi, not C
Extends missing-import diagnostics to namespaced std modules. `json.foo(...)` without `import "std/json.xi"` now reports `file.xi:3: error: json.foo(...) — the 'json' namespace isn't imported; add: import "std/json.xi"` instead of leaking `undeclared identifier 'json'`. Hooked at the identifier fallback, guarded so it only fires when: the name is a known std namespace (json/yaml/xml/crypto/math/text/bytes/net/fs/path/time/http/ io/proc/vec/web), it's followed by `.`, it isn't a local var, and no `<ns>__<fn>` function exists (i.e. the namespace really isn't imported) — so imported namespaces and locals are never flagged. Verified across every example (0 false positives); the check also caught a genuine latent bug — thread_demo used int_to_string without importing std/convert — now fixed. Fixpoint byte-identical; 22 test files pass.
1 parent abf66f5 commit dc64aa3

3 files changed

Lines changed: 32 additions & 0 deletions

File tree

compiler/impl/codegen/expr.xi

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,15 @@ mapper genPrimary(toks: Token[], pos: Integer, ctx: GCtx) -> ExprRes {
511511
if (ctx.prog).isMachineTypeC(txt) {
512512
return ExprRes { code: txt, pos: pos + 1, xtyp: "machinetype:" + txt , owned: false }
513513
}
514+
// `ns.foo(...)` where `ns` is a std namespace that isn't imported: no
515+
// `ns__foo` function exists, `ns` isn't a local — report the missing import
516+
// in Xi terms rather than leaking a C `undeclared identifier 'ns'` error.
517+
if toks.kindAt(pos + 1) == 107 and string_len(ctx.lookupVar(txt)) == 0 {
518+
let nsImp = txt.stdNamespaceImport()
519+
if string_len(nsImp) > 0 and not (ctx.prog).isFuncNameC(txt + "__" + toks.textAt(pos + 2)) {
520+
diag_error(tokenArrGet(toks, pos).line, txt + "." + toks.textAt(pos + 2) + "(...) — the '" + txt + "' namespace isn't imported; add: import \"" + nsImp + "\"")
521+
}
522+
}
514523
return ExprRes { code: txt, pos: pos + 1, xtyp: ctx.lookupVar(txt) , owned: false }
515524
}
516525
return ExprRes { code: txt, pos: pos + 1, xtyp: "" , owned: false }

compiler/impl/codegen/program_query.xi

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,28 @@ mapper String.stdImportHint() -> String {
317317
return ""
318318
}
319319

320+
// If `this` is a std-library namespace, the import path that provides it; else ""
321+
// (used to report `json.foo(...)` when `std/json.xi` isn't imported).
322+
mapper String.stdNamespaceImport() -> String {
323+
if this == "json" { return "std/json.xi" }
324+
if this == "yaml" { return "std/yaml.xi" }
325+
if this == "xml" { return "std/xml.xi" }
326+
if this == "crypto" { return "std/crypto.xi" }
327+
if this == "math" { return "std/math.xi" }
328+
if this == "text" { return "std/text.xi" }
329+
if this == "bytes" { return "std/bytes.xi" }
330+
if this == "net" { return "std/net.xi" }
331+
if this == "fs" { return "std/fs.xi" }
332+
if this == "path" { return "std/path.xi" }
333+
if this == "time" { return "std/time.xi" }
334+
if this == "http" { return "std/http.xi" }
335+
if this == "io" { return "std/io.xi" }
336+
if this == "proc" { return "std/process.xi" }
337+
if this == "vec" { return "std/vec.xi" }
338+
if this == "web" { return "std/web.xi" }
339+
return ""
340+
}
341+
320342
// The X type of module-scoped const `Module.name`, or "" if there's no such const.
321343
mapper Program.moduleConstXType(moduleName: String, name: String) -> String {
322344
let i = 0

examples/concurrency/thread_demo.xi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// xc examples/thread_demo.xi && ./build/thread_demo
66
import "std/log.xi"
77
import "std/thread.xi"
8+
import "std/convert.xi"
89

910
async entry (logger: Logger) main(args: String[]) -> Integer {
1011
let jobs = thread.channel()

0 commit comments

Comments
 (0)