compiler: text keys' follow-up (Master's rulings) - a Key in a template literal's hole is an error (the parser marks each hole's string(), TPL_HOLE; write trf(k"...", ...)), trn takes only a plural key kn"..." and tr / trf refuse one (with or without en.po), and a program with no lang line (a package test) uses key literals unchecked and silently - the warning stays for a lang line whose en.po is missing; rejected/i18n_keys gains key_hole (2) and key_rules (3), key_missing's plural moves to trn; LANGUAGE.md and the changeset say so; reseeded, bootstrap-cfree fixpoint holds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
66b8e51026
commit
9f9ac4a7ce
13 changed files with 72839 additions and 72164 deletions
|
|
@ -100,6 +100,7 @@ function ck_builtin(e: Node, name: pointer) -> pointer {
|
|||
ck_walk_args(e)
|
||||
return "string"
|
||||
}
|
||||
if (name == "string") and ck_tpl_hole(e) { return ck_hole(e) }
|
||||
if (name == "string") or (name == "int") or (name == "float") or (name == "fixed") or (name == "long") or (name == "double") {
|
||||
ck_walk_args(e)
|
||||
return name
|
||||
|
|
@ -313,3 +314,12 @@ function ck_emit(s: Node) -> void {
|
|||
i += 1
|
||||
}
|
||||
}
|
||||
# a template literal's {hole}: text, never a key - a Key there would draw its marked name untranslated
|
||||
function ck_tpl_hole(e: Node) -> bool {
|
||||
return e.a != null and (e.a.uns == TPL_HOLE or e.a.uns == TPL_COPY) and len(e.kids) == 1
|
||||
}
|
||||
function ck_hole(e: Node) -> pointer {
|
||||
let t = ck_expr(e.kids[0])
|
||||
if ck_is_key(t) { ck_err("key", e.kids[0], "a Key in a template's {hole}: a key names a text, it is not one - translate it with trf(k\"...\", ...) (tr(key) for no values), or say string(key) outside the template if the marked name is really wanted") }
|
||||
return "string"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -225,15 +225,14 @@ function i18n_ks_name(kind: int) -> pointer {
|
|||
if kind == KS_DATA { return "data" }
|
||||
return "code"
|
||||
}
|
||||
# a key used: in en.po, and a plural one as a plural there. Nothing to check against: said once
|
||||
# a key used: in en.po, and a plural one as a plural there. A lang line with no en.po: said once;
|
||||
# no lang line at all (a package test) checks nothing and says nothing
|
||||
function i18n_use(key: pointer, plural: bool, kind: int, file: pointer, line: int, col: int) -> void {
|
||||
if not i18n_site(key, kind, file, line, col) { return }
|
||||
if g_i18n_en == null {
|
||||
if kind != KS_TEMPLATE and not g_i18n_nopo_warned {
|
||||
if g_i18n_on and kind != KS_TEMPLATE and not g_i18n_nopo_warned {
|
||||
g_i18n_nopo_warned = true
|
||||
var why = "this program's package.ludic has no `lang \"assets/lang\" en` line"
|
||||
if g_i18n_on { why = `{g_i18n_en_path} is not there` }
|
||||
pwarn_at(file, line, col, `k"{key}": no en.po to check against - {why}; no key is checked`)
|
||||
pwarn_at(file, line, col, `k"{key}": no en.po to check against - {g_i18n_en_path} is not there; no key is checked`)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -312,7 +311,7 @@ function i18n_walk(n: Node) -> void {
|
|||
if i18n_is_key(n) and not i18n_is_data_file(n.file) {
|
||||
i18n_use(i18n_key_text(n), n.ival == KEY_PLURAL, KS_CODE, n.file, n.line, i18n_col(n))
|
||||
}
|
||||
if n.kind == E_CALL and n.a != null and n.a.kind == E_ID and g_i18n_en != null { i18n_call(n) }
|
||||
if n.kind == E_CALL and n.a != null and n.a.kind == E_ID { i18n_call(n) }
|
||||
i18n_walk(n.a)
|
||||
i18n_walk(n.b)
|
||||
i18n_walk(n.c)
|
||||
|
|
@ -322,15 +321,25 @@ function i18n_walk(n: Node) -> void {
|
|||
i += 1
|
||||
}
|
||||
}
|
||||
# trf(k"...", a, b) / trn(kn"...", n, a): the values after the key against its holes
|
||||
# tr(k"...") / trf(k"...", a, b) / trn(kn"...", n, a): a plural key only with trn, and trn only with
|
||||
# one (en.po or not); then the values after the key against its holes
|
||||
function i18n_call(n: Node) -> void {
|
||||
let nm = vis_plain(n.a.s)
|
||||
if not (nm == "trf") and not (nm == "trn") { return }
|
||||
if not (nm == "tr") and not (nm == "trf") and not (nm == "trn") { return }
|
||||
var k = 0
|
||||
while k < len(n.kids) and not i18n_is_key(n.kids[k]) { k += 1 }
|
||||
if k >= len(n.kids) { return }
|
||||
let e = n.kids[k]
|
||||
i18n_holes(i18n_key_text(e), len(n.kids) - k - 1, nm, e.file, e.line, i18n_col(e))
|
||||
let key = i18n_key_text(e)
|
||||
let plural = e.ival == KEY_PLURAL
|
||||
if nm == "trn" and not plural {
|
||||
perr_at(e.file, e.line, i18n_col(e), `trn(k"{key}", ...): trn counts, so its key is a plural one - write kn"{key}" (and give en.po a msgid_plural)`)
|
||||
}
|
||||
if plural and not (nm == "trn") {
|
||||
perr_at(e.file, e.line, i18n_col(e), `{nm}(kn"{key}", ...): a plural key needs its count - write trn(kn"{key}", n, ...)`)
|
||||
}
|
||||
if nm == "tr" or g_i18n_en == null { return }
|
||||
i18n_holes(key, len(n.kids) - k - 1, nm, e.file, e.line, i18n_col(e))
|
||||
}
|
||||
# a node's column in its file: a template literal's hole is lexed on its own, so its tokens' columns
|
||||
# are the hole's - the file offset says where it really is
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ function interp_add(acc: Node, part: Node) -> Node {
|
|||
return mkbin("+", acc, part)
|
||||
}
|
||||
function interp_str(e: Node) -> Node { # wrap a hole in string(...)
|
||||
let c = node(E_CALL); let id = node(E_ID); id.s = "string"; c.a = id; push(c.kids, e); return c
|
||||
let c = node(E_CALL); let id = node(E_ID); id.s = "string"; id.uns = TPL_HOLE; c.a = id; push(c.kids, e); return c
|
||||
}
|
||||
var g_interp_line: int = 1 # the line the interpolated string sits on
|
||||
var g_interp_pos: int = -1 # the backtick's place in its file
|
||||
|
|
@ -297,6 +297,7 @@ function parse_interp(raw: pointer) -> Node {
|
|||
return acc
|
||||
}
|
||||
const TPL_COPY: int = 91 # on the callee of a template's lone string(hole)
|
||||
const TPL_HOLE: int = 92 # on the callee of every other string(hole) (a Key is refused there)
|
||||
|
||||
# emit E(field: v, ...) — shared by the statement form and the expression form.
|
||||
# As an expression it yields a cancellable event's cancelled flag (0/1); a
|
||||
|
|
|
|||
70737
selfhost/ludicc.seed.ll
70737
selfhost/ludicc.seed.ll
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue