jsonbuilder: add apps/lib/json_builder.nyash and docs; wire loop_normalize_macro to prepare for usage; prefer Nyash runner route
This commit is contained in:
113
apps/lib/json_builder.nyash
Normal file
113
apps/lib/json_builder.nyash
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// JsonBuilder — Minimal helpers to construct AST JSON v0 fragments as strings
|
||||||
|
// Usage: local JB = include "apps/lib/json_builder.nyash"
|
||||||
|
// local s = JB.literal_string("x")
|
||||||
|
|
||||||
|
static box JsonBuilder {
|
||||||
|
// Join array of strings with a separator
|
||||||
|
join(arr, sep) {
|
||||||
|
local out = ""
|
||||||
|
local i = 0
|
||||||
|
local n = arr.length()
|
||||||
|
loop(i < n) {
|
||||||
|
out = out + arr.get(i)
|
||||||
|
if i + 1 < n { out = out + sep }
|
||||||
|
i = i + 1
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON string escaping (minimal): backslash, quote, newline, carriage return, tab
|
||||||
|
escape_string(s) {
|
||||||
|
local out = ""
|
||||||
|
local i = 0
|
||||||
|
loop(i < s.length()) {
|
||||||
|
local ch = s.substring(i, i + 1)
|
||||||
|
if ch == "\\" { out = out + "\\\\" }
|
||||||
|
else if ch == "\"" { out = out + "\\\"" }
|
||||||
|
else if ch == "\n" { out = out + "\\n" }
|
||||||
|
else if ch == "\r" { out = out + "\\r" }
|
||||||
|
else if ch == "\t" { out = out + "\\t" }
|
||||||
|
else { out = out + ch }
|
||||||
|
i = i + 1
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
quote(s) { return "\"" + this.escape_string(s) + "\"" }
|
||||||
|
|
||||||
|
// ==== Node builders (strings) ====
|
||||||
|
literal_string(s) {
|
||||||
|
return "{\"kind\":\"Literal\",\"value\":{\"type\":\"string\",\"value\":" + this.quote(s) + "}}"
|
||||||
|
}
|
||||||
|
literal_int(i) {
|
||||||
|
return "{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":" + i + "}}"
|
||||||
|
}
|
||||||
|
literal_bool(b) {
|
||||||
|
if b { return "{\"kind\":\"Literal\",\"value\":{\"type\":\"bool\",\"value\":true}}" }
|
||||||
|
return "{\"kind\":\"Literal\",\"value\":{\"type\":\"bool\",\"value\":false}}"
|
||||||
|
}
|
||||||
|
literal_null() { return "{\"kind\":\"Literal\",\"value\":{\"type\":\"null\"}}" }
|
||||||
|
|
||||||
|
variable(name) {
|
||||||
|
return "{\"kind\":\"Variable\",\"name\":" + this.quote(name) + "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
binary(op, lhs_json, rhs_json) {
|
||||||
|
return "{\"kind\":\"BinaryOp\",\"op\":" + this.quote(op) + ",\"left\":" + lhs_json + ",\"right\":" + rhs_json + "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
assignment(target_json, value_json) {
|
||||||
|
return "{\"kind\":\"Assignment\",\"target\":" + target_json + ",\"value\":" + value_json + "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
local(vars, inits) {
|
||||||
|
// vars: array[string], inits: array[string|null]
|
||||||
|
local vs = []
|
||||||
|
local i = 0
|
||||||
|
loop(i < vars.length()) {
|
||||||
|
vs.push(this.quote(vars.get(i)))
|
||||||
|
i = i + 1
|
||||||
|
}
|
||||||
|
local is = []
|
||||||
|
i = 0
|
||||||
|
loop(i < inits.length()) {
|
||||||
|
local v = inits.get(i)
|
||||||
|
if v == null { is.push("null") } else { is.push(v) }
|
||||||
|
i = i + 1
|
||||||
|
}
|
||||||
|
return "{\"kind\":\"Local\",\"variables\":[" + this.join(vs, ",") + "],\"inits\":[" + this.join(is, ",") + "]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
array(elems_json) {
|
||||||
|
return "{\"kind\":\"Array\",\"elements\":[" + this.join(elems_json, ",") + "]}"
|
||||||
|
}
|
||||||
|
map(entries) {
|
||||||
|
// entries: array of [k:string, v:json]
|
||||||
|
local parts = []
|
||||||
|
local i = 0
|
||||||
|
loop(i < entries.length()) {
|
||||||
|
local kv = entries.get(i)
|
||||||
|
local k = kv.get(0)
|
||||||
|
local v = kv.get(1)
|
||||||
|
parts.push("{\"k\":" + this.quote(k) + ",\"v\":" + v + "}")
|
||||||
|
i = i + 1
|
||||||
|
}
|
||||||
|
return "{\"kind\":\"Map\",\"entries\":[" + this.join(parts, ",") + "]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
if_(cond_json, then_stmts_json, else_stmts_json) {
|
||||||
|
local then_s = "[" + this.join(then_stmts_json, ",") + "]"
|
||||||
|
local else_s = "null"
|
||||||
|
if else_stmts_json != null { else_s = "[" + this.join(else_stmts_json, ",") + "]" }
|
||||||
|
return "{\"kind\":\"If\",\"condition\":" + cond_json + ",\"then\":" + then_s + ",\"else\":" + else_s + "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_(cond_json, body_stmts_json) {
|
||||||
|
return "{\"kind\":\"Loop\",\"condition\":" + cond_json + ",\"body\":[" + this.join(body_stmts_json, ",") + "]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
program(stmts_json) {
|
||||||
|
return "{\"kind\":\"Program\",\"statements\":[" + this.join(stmts_json, ",") + "]}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -6,8 +6,11 @@ static box MacroBoxSpec {
|
|||||||
static function name() { return "LoopNormalize" }
|
static function name() { return "LoopNormalize" }
|
||||||
|
|
||||||
static function expand(json, ctx) {
|
static function expand(json, ctx) {
|
||||||
// For MVP, return input unchanged.
|
// MVP: return input unchanged, but ensure JsonBuilder is loadable for next step.
|
||||||
|
// Example usage (commented):
|
||||||
|
// local JB = include "apps/lib/json_builder.nyash"
|
||||||
|
// local zero = JB.literal_int(0)
|
||||||
|
// _ = zero // suppress unused
|
||||||
return json
|
return json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,18 @@ export NYASH_MACRO_PATHS=apps/macros/examples/loop_normalize_macro.nyash
|
|||||||
```
|
```
|
||||||
- 自己ホスト前展開(auto)を利用して、parse直後にLoopForm展開を有効化(PyVM環境)。
|
- 自己ホスト前展開(auto)を利用して、parse直後にLoopForm展開を有効化(PyVM環境)。
|
||||||
|
|
||||||
|
JSON生成ユーティリティ(JsonBuilder)
|
||||||
|
- ループ正規化では AST JSON v0 の断片を安全に構成する必要があります。
|
||||||
|
- 最小ユーティリティとして `apps/lib/json_builder.nyash` を提供しています(includeで読み込み、文字列でJSON断片を生成)。
|
||||||
|
- 例:
|
||||||
|
```
|
||||||
|
local JB = include "apps/lib/json_builder.nyash"
|
||||||
|
local v_i = JB.variable("i")
|
||||||
|
local v_sum = JB.variable("sum")
|
||||||
|
local lit_0 = JB.literal_int(0)
|
||||||
|
local assign = JB.assignment(v_i, JB.binary("+", v_i, JB.literal_int(1)))
|
||||||
|
```
|
||||||
|
|
||||||
正規化の考え方
|
正規化の考え方
|
||||||
- ループで更新される変数群をタプルに束ね、ヘッダに“1個のφ”を置く。
|
- ループで更新される変数群をタプルに束ね、ヘッダに“1個のφ”を置く。
|
||||||
- break/continue は“次キャリア”または“現キャリア”で遷移し、一貫した合流点を保つ。
|
- break/continue は“次キャリア”または“現キャリア”で遷移し、一貫した合流点を保つ。
|
||||||
@ -29,4 +41,3 @@ export NYASH_MACRO_PATHS=apps/macros/examples/loop_normalize_macro.nyash
|
|||||||
|
|
||||||
参考
|
参考
|
||||||
- docs/development/roadmap/phases/phase-17-loopform-selfhost/
|
- docs/development/roadmap/phases/phase-17-loopform-selfhost/
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user