wip(0.S2): migrate - a var nothing writes becomes a let; a state is keyed by its module, directory or program, so every program's plan agrees; paths normalized; program states named SceneDemoState / scene_demo_st; the LSP reads state, mut and entry/handler parameters
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
3eda72e8c2
commit
5ffe50ed02
463 changed files with 72045 additions and 67421 deletions
|
|
@ -184,38 +184,71 @@ function mgx_apply(lines: []pointer, dry: bool) -> int {
|
|||
let vpos2 = new []int
|
||||
let vstate = new []pointer
|
||||
let sname = new []pointer
|
||||
let sat = new []pointer # where each is declared: file:pos
|
||||
let sfile = new []pointer
|
||||
let spos = new []int
|
||||
let sexp = new []int
|
||||
let smore = new []int # 1: the state is already declared, and gains fields
|
||||
let reports = new []pointer
|
||||
let lfile = new []pointer
|
||||
let lpos = new []int
|
||||
for i in 0 .. len(lines) {
|
||||
let w = dp_words(lines[i])
|
||||
if len(w) == 0 { continue }
|
||||
if w[0] == "VAR" and len(w) == 5 {
|
||||
if w[0] == "VAR" and len(w) == 6 {
|
||||
push(vfile, w[1])
|
||||
push(vpos, s_to_int(w[2]))
|
||||
push(vpos2, s_to_int(w[3]))
|
||||
push(vstate, w[4])
|
||||
} else if w[0] == "STATE" and len(w) >= 6 {
|
||||
push(vstate, w[5]) # the state by where it is declared, not by its name
|
||||
} else if w[0] == "STATE" and len(w) >= 7 {
|
||||
# one state from several programs' plans: exported if any of them needs it outside
|
||||
# one state from several programs' plans, which saw different files of it: declared where one
|
||||
# is declared already, else at the first of its vars any of them saw; exported if any needs it
|
||||
let at = w[6]
|
||||
let more = len(w) >= 8
|
||||
var known = -1
|
||||
for k in 0 .. len(sname) { if sname[k] == w[1] { known = k } }
|
||||
for k in 0 .. len(sat) { if sat[k] == at { known = k } }
|
||||
if known >= 0 {
|
||||
if s_to_int(w[4]) == 1 { sexp[known] = 1 }
|
||||
let earlier = s_less(w[2], sfile[known]) or (w[2] == sfile[known] and s_to_int(w[3]) < spos[known])
|
||||
if smore[known] == 0 and (more or earlier) {
|
||||
sfile[known] = w[2]
|
||||
spos[known] = s_to_int(w[3])
|
||||
if more { smore[known] = 1 }
|
||||
}
|
||||
continue
|
||||
}
|
||||
push(sname, w[1])
|
||||
push(sat, at)
|
||||
push(sfile, w[2])
|
||||
push(spos, s_to_int(w[3]))
|
||||
push(sexp, s_to_int(w[4]))
|
||||
if len(w) >= 7 { push(smore, 1) } else { push(smore, 0) }
|
||||
if more { push(smore, 1) } else { push(smore, 0) }
|
||||
} else if (w[0] == "REF") and len(w) == 5 {
|
||||
mgx_edit(w[1], s_to_int(w[2]), s_to_int(w[3]), mgx_unesc(w[4]))
|
||||
} else if (w[0] == "INS") and len(w) == 4 {
|
||||
mgx_edit(w[1], s_to_int(w[2]), 0, mgx_unesc(w[3]))
|
||||
} else if w[0] == "LET" and len(w) == 3 {
|
||||
push(lfile, w[1])
|
||||
push(lpos, s_to_int(w[2]))
|
||||
} else if w[0] == "?" { push(reports, lines[i]) }
|
||||
}
|
||||
# a var nothing writes is a let - unless another program's plan saw it written
|
||||
var lets = 0
|
||||
for l in 0 .. len(lfile) {
|
||||
var moved = false
|
||||
for v in 0 .. len(vfile) { if vfile[v] == lfile[l] and vpos[v] == lpos[l] { moved = true } }
|
||||
if not moved {
|
||||
let t = mgx_text_of(lfile[l])
|
||||
var k = lpos[l] - 3
|
||||
let ls = mgx_line_start(t, lpos[l])
|
||||
while k >= ls and not (t[k] == 'v' and t[k + 1] == 'a' and t[k + 2] == 'r') { k -= 1 }
|
||||
if k >= ls {
|
||||
mgx_edit(lfile[l], k, 3, "let")
|
||||
lets += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
# the vars: each line goes, and the first of each state's becomes the state
|
||||
let del_file = new []pointer
|
||||
let del_a = new []int
|
||||
|
|
@ -253,7 +286,7 @@ function mgx_apply(lines: []pointer, dry: bool) -> int {
|
|||
var ff = ""
|
||||
for ov in 0 .. len(order) {
|
||||
let v = order[ov]
|
||||
if vstate[v] == sname[s] { ff = ff + `{indent} {mgx_field(mgx_text_of(vfile[v]), vpos[v], vpos2[v])}\n` }
|
||||
if vstate[v] == sat[s] { ff = ff + `{indent} {mgx_field(mgx_text_of(vfile[v]), vpos[v], vpos2[v])}\n` }
|
||||
}
|
||||
let close = mgx_close(t, spos[s])
|
||||
if close >= 0 { mgx_edit(sfile[s], mgx_line_start(t, close), 0, ff) }
|
||||
|
|
@ -261,7 +294,7 @@ function mgx_apply(lines: []pointer, dry: bool) -> int {
|
|||
}
|
||||
for ov in 0 .. len(order) {
|
||||
let v = order[ov]
|
||||
if vstate[v] == sname[s] {
|
||||
if vstate[v] == sat[s] {
|
||||
let t = mgx_text_of(vfile[v])
|
||||
if vfile[v] == sfile[s] and vpos[v] == spos[s] {
|
||||
at = v
|
||||
|
|
@ -333,7 +366,7 @@ function mgx_apply(lines: []pointer, dry: bool) -> int {
|
|||
if n > cur { file_write(out, data_at(t, cur), n - cur) }
|
||||
file_close(out)
|
||||
}
|
||||
print(`migrate: {string(len(vfile))} vars into {string(len(sname))} states; {string(edits)} edits in {string(files)} files`)
|
||||
print(`migrate: {string(len(vfile))} vars into {string(len(sname))} states, {string(lets)} into lets; {string(edits)} edits in {string(files)} files`)
|
||||
for r in 0 .. len(reports) { print(` by hand: {sslice(reports[r], 2, slen(reports[r]))}`) }
|
||||
return 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ program LudicLsp {
|
|||
}
|
||||
function is_keyword_word(w: pointer) -> bool {
|
||||
if (w == "program") or (w == "import") or (w == "property") or (w == "model") or (w == "enum") or (w == "ui") { return true }
|
||||
if (w == "const") or (w == "var") or (w == "function") or (w == "extern") or (w == "handler") or (w == "entry") or (w == "event") or (w == "scene") { return true }
|
||||
if (w == "const") or (w == "var") or (w == "function") or (w == "extern") or (w == "handler") or (w == "entry") or (w == "event") or (w == "scene") or (w == "mut") { return true }
|
||||
if (w == "phase") or (w == "query") or (w == "on") or (w == "cancellable") or (w == "public") or (w == "layer") or (w == "start") { return true }
|
||||
if (w == "let") or (w == "return") or (w == "if") or (w == "else") or (w == "while") or (w == "for") or (w == "in") or (w == "spawn") or (w == "despawn") { return true }
|
||||
if (w == "enable") or (w == "disable") or (w == "match") or (w == "machine") or (w == "state") or (w == "become") or (w == "where") or (w == "prefab") { return true }
|
||||
|
|
@ -471,10 +471,15 @@ program LudicLsp {
|
|||
let nt = pname()
|
||||
if nt < 0 { padv(); continue }
|
||||
var ty = ""
|
||||
if pis(":") { padv(); let tt = pname(); if tt >= 0 { ty = ttext(pD, tt) } }
|
||||
var mu = ""
|
||||
if pis(":") {
|
||||
padv()
|
||||
if pis("mut") { padv(); mu = "mut " } # a state it may change
|
||||
let tt = pname(); if tt >= 0 { ty = ttext(pD, tt) }
|
||||
}
|
||||
let sidx = sym_add(kind, nt, owner)
|
||||
pD.syms[sidx].ty = ty
|
||||
pD.syms[sidx].detail = concat3("param ", pD.syms[sidx].name, concat3(": ", ty, ""))
|
||||
pD.syms[sidx].detail = concat3("param ", pD.syms[sidx].name, concat3(": ", mu, ty))
|
||||
if not first { buf_puts(sig, ", ") }
|
||||
buf_puts(sig, pD.syms[sidx].name); buf_puts(sig, ": ")
|
||||
if ty == "" { buf_puts(sig, "?") } else { buf_puts(sig, ty) }
|
||||
|
|
@ -655,8 +660,10 @@ program LudicLsp {
|
|||
}
|
||||
return
|
||||
}
|
||||
if (w == "property") or (w == "model") {
|
||||
let is_comp = (w == "property")
|
||||
var wd = w
|
||||
if w == "export" and tis(pD, pi + 1, "state") { padv(); wd = "state" }
|
||||
if (wd == "property") or (wd == "model") or (wd == "state") { # a state: a record with one instance
|
||||
let is_comp = (wd == "property") or (wd == "state")
|
||||
padv(); let nt = pname(); if nt < 0 { return }
|
||||
var kind = LS_ARCHETYPE
|
||||
if is_comp { kind = LS_COMPONENT }
|
||||
|
|
@ -748,7 +755,16 @@ program LudicLsp {
|
|||
}
|
||||
if w == "entry" {
|
||||
padv()
|
||||
if pis("{") { let close = cur_match(); var endo = cstr_len(pD.text); if close >= 0 { endo = pD.tk_end[close] }; lp_block(parent, endo) }
|
||||
let first_param = len(pD.syms)
|
||||
if pis("(") { lp_params(parent, LS_PARAM, buf_new()) } # entry (h: mut Hiker): its states
|
||||
if pis("{") {
|
||||
let close = cur_match()
|
||||
var endo = cstr_len(pD.text)
|
||||
if close >= 0 { endo = pD.tk_end[close] }
|
||||
var q = first_param
|
||||
while q < len(pD.syms) { if pD.syms[q].kind == LS_PARAM { pD.syms[q].bstart = pD.tk_start[pi]; pD.syms[q].bend = endo }; q += 1 }
|
||||
lp_block(parent, endo)
|
||||
}
|
||||
return
|
||||
}
|
||||
if (w == "handler") or (w == "edge") {
|
||||
|
|
@ -758,6 +774,7 @@ program LudicLsp {
|
|||
let sidx = sym_add(LS_SYSTEM, nt, parent)
|
||||
pD.syms[sidx].doc = collect_doc(pD, decl_tok)
|
||||
pD.syms[sidx].ty = "Update"
|
||||
if pis("(") { lp_params(sidx, LS_PARAM, buf_new()) } # handler Draw(h: Hiker): its states
|
||||
while pk() == LT_ANNO { padv() }
|
||||
let vars = new []int
|
||||
var nv = 0
|
||||
|
|
@ -788,6 +805,8 @@ program LudicLsp {
|
|||
let close = cur_match()
|
||||
pD.syms[sidx].bstart = pD.tk_start[pi]
|
||||
if close >= 0 { pD.syms[sidx].bend = pD.tk_end[close] } else { pD.syms[sidx].bend = cstr_len(pD.text) }
|
||||
var q = 0
|
||||
while q < len(pD.syms) { if pD.syms[q].parent == sidx and pD.syms[q].kind == LS_PARAM { pD.syms[q].bstart = pD.syms[sidx].bstart; pD.syms[q].bend = pD.syms[sidx].bend }; q += 1 }
|
||||
lp_block(sidx, pD.syms[sidx].bend)
|
||||
}
|
||||
return
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue