diff --git a/layout/src/parser.rs b/layout/src/parser.rs index c7d4b2f5..9cfd3b15 100644 --- a/layout/src/parser.rs +++ b/layout/src/parser.rs @@ -1239,6 +1239,12 @@ impl Parser { if symbol::lookup(&t.value).word == "add" { return self.parse_pratt(UNARY_PREC); } + // 一元前缀 & = 取址:&x ≡ kv·abs(x)(中缀 & 仍为按位与,走 pratt 中缀路径)。 + if symbol::lookup(&t.value).word == "bitand" { + let arg = self.parse_pratt(UNARY_PREC)?; + let op = format!("kv{}abs", keytree::MEMBER_SEP); + return Some(ast::call(&op, vec![arg])); + } let arg = self.parse_pratt(UNARY_PREC)?; return Some(ast::call(&t.value, vec![arg])); } diff --git a/layout/src/symbol.rs b/layout/src/symbol.rs index e4ed3f38..af842463 100644 --- a/layout/src/symbol.rs +++ b/layout/src/symbol.rs @@ -260,7 +260,7 @@ static ENTRIES: &[Entry] = &[ precedence: 80, arith: true, cmp: false, - unary: false, + unary: true, }, Entry { word: "bitor", diff --git "a/stdlib/kvlang/spec/01-\350\257\215\346\263\225/08-\350\277\220\347\256\227\347\254\246\345\237\272\347\241\200.kv" "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/08-\350\277\220\347\256\227\347\254\246\345\237\272\347\241\200.kv" index 5bdefb5f..1e18ea58 100644 --- "a/stdlib/kvlang/spec/01-\350\257\215\346\263\225/08-\350\277\220\347\256\227\347\254\246\345\237\272\347\241\200.kv" +++ "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/08-\350\277\220\347\256\227\347\254\246\345\237\272\347\241\200.kv" @@ -44,7 +44,8 @@ x = 42 // 左写、右读 - `/`(U+002F)**不是**除号。它只用于绝对路径字面量与注释(`//`、`/*`);出现在其他位置的裸 `/` 不承 载算术除法语义。 -一元 `+`、`-` 作前缀;`√`(U+221A,平方根)亦为一元前缀运算符。 +一元 `+`、`-` 作前缀;`√`(U+221A,平方根)亦为一元前缀运算符。`&` 亦兼一元前缀(取址, +`&x ≡ kv·abs(x)`);其中缀身份(按位与)与前缀身份靠位置区分,同 C,详见 [[逻辑位运算与优先级]]。 ## 比较运算符 diff --git "a/stdlib/kvlang/spec/01-\350\257\215\346\263\225/09-\351\200\273\350\276\221\344\275\215\350\277\220\347\256\227\344\270\216\344\274\230\345\205\210\347\272\247.kv" "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/09-\351\200\273\350\276\221\344\275\215\350\277\220\347\256\227\344\270\216\344\274\230\345\205\210\347\272\247.kv" index 5ca65a4d..83786a31 100644 --- "a/stdlib/kvlang/spec/01-\350\257\215\346\263\225/09-\351\200\273\350\276\221\344\275\215\350\277\220\347\256\227\344\270\216\344\274\230\345\205\210\347\272\247.kv" +++ "b/stdlib/kvlang/spec/01-\350\257\215\346\263\225/09-\351\200\273\350\276\221\344\275\215\350\277\220\347\256\227\344\270\216\344\274\230\345\205\210\347\272\247.kv" @@ -18,9 +18,27 @@ lib kvlang/spec/词法/逻辑位运算与优先级 { 分别为按位与、按位或、按位异或、左移、右移。 +`&` 一符二用,靠位置区分(同 C):操作数之后为中缀**按位与**;表达式起始或运算符之后为一元前缀 +**取址**(见下 [[取址运算符 `&`]])。 + +## 取址运算符 `&` + +一元前缀 `&loc` 求值为 `loc` 所在节点的绝对 KV 路径字符串,等价 `kv·abs(loc)`。操作数须为位置 +(location):帧内裸名、容器/成员链(`x`、`list·1`、`base·field`)。 + +产物是普通路径串,与指针惯例同型(可 `-> p` 存指针、`+ "·n"` 拼子节点、赋给 `next` 字段);与 +`*T` ref 标注互补——`&` 造路径,`*` 标注该路径所指目标的形态(见 [[ptr]])。 + +``` +list·1 -> x +&x -> p // p = x 的绝对路径串,等价 kv·abs(x) +p + "·next" -> q +``` + ## 优先级 -中缀运算符的优先级如下(数值越大结合越紧);一元前缀运算符(`+ - ! √`)优先级高于全部中缀。 +中缀运算符的优先级如下(数值越大结合越紧);一元前缀运算符(`+ - ! √ &`)优先级高于全部中缀。 +故 `&a·b ≡ &(a·b)`(成员链先结合,同 C 的 `&a.b`)。 | 运算符 | 优先级 | |--------|--------| diff --git "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/16-ptr.kv" "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/16-ptr.kv" index 493f806a..c1e52684 100644 --- "a/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/16-ptr.kv" +++ "b/stdlib/kvlang/spec/03-\347\261\273\345\236\213\347\263\273\347\273\237/16-ptr.kv" @@ -16,5 +16,8 @@ lib kvlang/spec/类型系统/ptr { "/n1" -> p // 引号 = 路径串(指针) p·val -> v // 按值解引用:读 /n1·val ``` + +局部变量/容器成员取指针用一元前缀 `&`(`&x ≡ kv·abs(x)`,返回绝对路径串),与 `*` ref 标注互补—— +`&` 造路径、`*` 标注目标形态(见 [[逻辑位运算与优先级]] 取址运算符)。 "#### -> /lib/kvlang/spec/类型系统/ptr } diff --git "a/stdlib/kvlang/spec/\351\231\204\345\275\225/05-\350\241\250\350\276\276\345\274\217.kv" "b/stdlib/kvlang/spec/\351\231\204\345\275\225/05-\350\241\250\350\276\276\345\274\217.kv" index 5e1ca965..b6b52911 100644 --- "a/stdlib/kvlang/spec/\351\231\204\345\275\225/05-\350\241\250\350\276\276\345\274\217.kv" +++ "b/stdlib/kvlang/spec/\351\231\204\345\275\225/05-\350\241\250\350\276\276\345\274\217.kv" @@ -18,7 +18,7 @@ primary = literal | ident | path | struct_literal | map_literal -prefix_unary = "-" | "!" | "√" (* √ = sqrt(U+221A),一元 *) +prefix_unary = "-" | "!" | "√" | "&" (* √ = sqrt(U+221A);&x ≡ kv·abs(x) 取址 *) infix_primary = binary_op expr diff --git "a/stdlib/kvlang/spec/\351\231\204\345\275\225/07-\345\206\205\345\273\272\345\207\275\346\225\260.kv" "b/stdlib/kvlang/spec/\351\231\204\345\275\225/07-\345\206\205\345\273\272\345\207\275\346\225\260.kv" index 9fb757c1..92473604 100644 --- "a/stdlib/kvlang/spec/\351\231\204\345\275\225/07-\345\206\205\345\273\272\345\207\275\346\225\260.kv" +++ "b/stdlib/kvlang/spec/\351\231\204\345\275\225/07-\345\206\205\345\273\272\345\207\275\346\225\260.kv" @@ -32,6 +32,7 @@ builtin_call = ( "abs" | "neg" | "sign" | "pow" | "sqrt" | "exp" | "log" (* ÷ : 两侧 int → 整除(C 风格);任一侧 float → 浮除 *) (* s[i] 读返单字符字符串,越界返 "";s[i]="X" 单字符替换写回新串 *) (* + 作用在 string∧string → 拼接 *) +(* &x 是 kv·abs(x) 的语法糖(一元前缀取址,返回 x 的绝对路径串);与中缀按位与 a & b 靠位置区分 *) ``` "## -> /lib/kvlang/spec/附录/内建函数 } diff --git a/tutorial/08-leetcode/002_add_two_numbers.kv b/tutorial/08-leetcode/002_add_two_numbers.kv index f8c775c8..b738e009 100644 --- a/tutorial/08-leetcode/002_add_two_numbers.kv +++ b/tutorial/08-leetcode/002_add_two_numbers.kv @@ -47,23 +47,15 @@ rwfunc add(a:[]char/utf32, b:[]char/utf32) -> () { } rwfunc test() -> () { - l1:[int64]·Node = {} - kv·abs(l1) -> b1 - b1 + "·2" -> a2 - b1 + "·3" -> a3 - l1·1:Node = {val=2 next=a2} - l1·2:Node = {val=4 next=a3} - l1·3:Node = {val=3 next=""} - b1 + "·1" -> h1 + a3:Node = {val=3} + a2:Node = {val=4 next=&a3} + a1:Node = {val=2 next=&a2} + &a1 -> h1 - l2:[int64]·Node = {} - kv·abs(l2) -> b2 - b2 + "·2" -> c2 - b2 + "·3" -> c3 - l2·1:Node = {val=5 next=c2} - l2·2:Node = {val=6 next=c3} - l2·3:Node = {val=4 next=""} - b2 + "·1" -> h2 + b3:Node = {val=4} + b2:Node = {val=6 next=&b3} + b1:Node = {val=5 next=&b2} + &b1 -> h2 lc·add(h1, h2) } diff --git a/tutorial/08-leetcode/021_merge_two_lists.kv b/tutorial/08-leetcode/021_merge_two_lists.kv index a77c1971..964cc630 100644 --- a/tutorial/08-leetcode/021_merge_two_lists.kv +++ b/tutorial/08-leetcode/021_merge_two_lists.kv @@ -44,23 +44,15 @@ rwfunc merge(a:[]char/utf32, b:[]char/utf32) -> () { } rwfunc test() -> () { - a:[int64]·Node = {} - kv·abs(a) -> ab - ab + "·2" -> a2 - ab + "·3" -> a3 - a·1:Node = {val=1 next=a2} - a·2:Node = {val=2 next=a3} - a·3:Node = {val=4 next=""} - ab + "·1" -> ha + a3:Node = {val=4} + a2:Node = {val=2 next=&a3} + a1:Node = {val=1 next=&a2} + &a1 -> ha - b:[int64]·Node = {} - kv·abs(b) -> bb - bb + "·2" -> b2 - bb + "·3" -> b3 - b·1:Node = {val=1 next=b2} - b·2:Node = {val=3 next=b3} - b·3:Node = {val=4 next=""} - bb + "·1" -> hb + b3:Node = {val=4} + b2:Node = {val=3 next=&b3} + b1:Node = {val=1 next=&b2} + &b1 -> hb merge(ha, hb) } diff --git a/tutorial/08-leetcode/083_remove_dup_list.kv b/tutorial/08-leetcode/083_remove_dup_list.kv index 27aea8b1..78ce11e1 100644 --- a/tutorial/08-leetcode/083_remove_dup_list.kv +++ b/tutorial/08-leetcode/083_remove_dup_list.kv @@ -43,29 +43,19 @@ rwfunc show(head:[]char/utf32) -> () { } rwfunc test() -> () { - e:[int64]·Node = {} - kv·abs(e) -> eb - eb + "·2" -> e2 - eb + "·3" -> e3 - e·1:Node = {val=1 next=e2} - e·2:Node = {val=1 next=e3} - e·3:Node = {val=2 next=""} - eb + "·1" -> e1 - dedup(e1) - show(e1) + e3:Node = {val=2} + e2:Node = {val=1 next=&e3} + e1:Node = {val=1 next=&e2} + &e1 -> eh + dedup(eh) + show(eh) - f:[int64]·Node = {} - kv·abs(f) -> fb - fb + "·2" -> f2 - fb + "·3" -> f3 - fb + "·4" -> f4 - fb + "·5" -> f5 - f·1:Node = {val=1 next=f2} - f·2:Node = {val=1 next=f3} - f·3:Node = {val=2 next=f4} - f·4:Node = {val=3 next=f5} - f·5:Node = {val=3 next=""} - fb + "·1" -> f1 - dedup(f1) - show(f1) + f5:Node = {val=3} + f4:Node = {val=3 next=&f5} + f3:Node = {val=2 next=&f4} + f2:Node = {val=1 next=&f3} + f1:Node = {val=1 next=&f2} + &f1 -> fh + dedup(fh) + show(fh) } diff --git a/tutorial/08-leetcode/141_linked_list_cycle.kv b/tutorial/08-leetcode/141_linked_list_cycle.kv index 39231fc1..b1042622 100644 --- a/tutorial/08-leetcode/141_linked_list_cycle.kv +++ b/tutorial/08-leetcode/141_linked_list_cycle.kv @@ -32,23 +32,19 @@ struct Node { } rwfunc test() -> () { - c:[int64]·Node = {} - kv·abs(c) -> cb - cb + "·1" -> c1 - cb + "·2" -> c2 - cb + "·3" -> c3 - c·1:Node = {val=3 next=c2} - c·2:Node = {val=2 next=c3} - c·3:Node = {val=0 next=c1} - r1 = has_cycle(c1) + c1:Node = {val=3} + c2:Node = {val=2} + c3:Node = {val=0} + c1·next = &c2 + c2·next = &c3 + c3·next = &c1 + &c1 -> h1 + r1 = has_cycle(h1) println(r1) - n:[int64]·Node = {} - kv·abs(n) -> nb - nb + "·1" -> n1 - nb + "·2" -> n2 - n·1:Node = {val=1 next=n2} - n·2:Node = {val=2 next=""} - has_cycle(n1) -> r2 + d2:Node = {val=2} + d1:Node = {val=1 next=&d2} + &d1 -> h2 + has_cycle(h2) -> r2 println(r2) } diff --git a/tutorial/08-leetcode/160_intersection_list.kv b/tutorial/08-leetcode/160_intersection_list.kv index 8d8e7773..13ef2111 100644 --- a/tutorial/08-leetcode/160_intersection_list.kv +++ b/tutorial/08-leetcode/160_intersection_list.kv @@ -45,32 +45,20 @@ rwfunc get_intersection(ha:[]char/utf32, hb:[]char/utf32) -> () { rwfunc test() -> () { // common tail: 8→4→5 - t:[int64]·Node = {} - kv·abs(t) -> tb - tb + "·1" -> t8 - tb + "·2" -> t4 - tb + "·3" -> t5 - t·1:Node = {val=8 next=t4} - t·2:Node = {val=4 next=t5} - t·3:Node = {val=5 next=""} + t5:Node = {val=5} + t4:Node = {val=4 next=&t5} + t8:Node = {val=8 next=&t4} // list A: 4→1→t8 - a:[int64]·Node = {} - kv·abs(a) -> ab - ab + "·2" -> a2 - a·1:Node = {val=4 next=a2} - a·2:Node = {val=1 next=t8} - ab + "·1" -> ha + a2:Node = {val=1 next=&t8} + a1:Node = {val=4 next=&a2} + &a1 -> ha // list B: 5→6→1→t8 - b:[int64]·Node = {} - kv·abs(b) -> bb - bb + "·2" -> b2 - bb + "·3" -> b3 - b·1:Node = {val=5 next=b2} - b·2:Node = {val=6 next=b3} - b·3:Node = {val=1 next=t8} - bb + "·1" -> hb + b3:Node = {val=1 next=&t8} + b2:Node = {val=6 next=&b3} + b1:Node = {val=5 next=&b2} + &b1 -> hb get_intersection(ha, hb) } diff --git a/tutorial/08-leetcode/203_remove_linked_elements.kv b/tutorial/08-leetcode/203_remove_linked_elements.kv index 5f8244c9..e7a92bb3 100644 --- a/tutorial/08-leetcode/203_remove_linked_elements.kv +++ b/tutorial/08-leetcode/203_remove_linked_elements.kv @@ -27,21 +27,13 @@ rwfunc remove(head:[]char/utf32, val:int64) -> () { } rwfunc test() -> () { - n:[int64]·Node = {} - kv·abs(n) -> nb - nb + "·2" -> n2 - nb + "·3" -> n3 - nb + "·4" -> n4 - nb + "·5" -> n5 - nb + "·6" -> n6 - nb + "·7" -> n7 - n·1:Node = {val=1 next=n2} - n·2:Node = {val=2 next=n3} - n·3:Node = {val=6 next=n4} - n·4:Node = {val=3 next=n5} - n·5:Node = {val=4 next=n6} - n·6:Node = {val=5 next=n7} - n·7:Node = {val=6 next=""} - nb + "·1" -> h + n7:Node = {val=6} + n6:Node = {val=5 next=&n7} + n5:Node = {val=4 next=&n6} + n4:Node = {val=3 next=&n5} + n3:Node = {val=6 next=&n4} + n2:Node = {val=2 next=&n3} + n1:Node = {val=1 next=&n2} + &n1 -> h remove(h, 6) } diff --git a/tutorial/08-leetcode/206_reverse_linked_list.kv b/tutorial/08-leetcode/206_reverse_linked_list.kv index 4ddb6658..bc57be31 100644 --- a/tutorial/08-leetcode/206_reverse_linked_list.kv +++ b/tutorial/08-leetcode/206_reverse_linked_list.kv @@ -29,17 +29,11 @@ rwfunc reverse(head:[]char/utf32) -> () { } rwfunc test() -> () { - n:[int64]·Node = {} - kv·abs(n) -> nb - nb + "·2" -> p2 - nb + "·3" -> p3 - nb + "·4" -> p4 - nb + "·5" -> p5 - n·1:Node = {val=1 next=p2} - n·2:Node = {val=2 next=p3} - n·3:Node = {val=3 next=p4} - n·4:Node = {val=4 next=p5} - n·5:Node = {val=5 next=""} - nb + "·1" -> h + n5:Node = {val=5} + n4:Node = {val=4 next=&n5} + n3:Node = {val=3 next=&n4} + n2:Node = {val=2 next=&n3} + n1:Node = {val=1 next=&n2} + &n1 -> h reverse(h) } diff --git a/tutorial/08-leetcode/234_palindrome_list.kv b/tutorial/08-leetcode/234_palindrome_list.kv index 5b82f876..c7e3c3b6 100644 --- a/tutorial/08-leetcode/234_palindrome_list.kv +++ b/tutorial/08-leetcode/234_palindrome_list.kv @@ -40,23 +40,15 @@ rwfunc is_pal(head:[]char/utf32) -> () { } rwfunc test() -> () { - p:[int64]·Node = {} - kv·abs(p) -> pb - pb + "·2" -> p2 - pb + "·3" -> p3 - pb + "·4" -> p4 - p·1:Node = {val=1 next=p2} - p·2:Node = {val=2 next=p3} - p·3:Node = {val=2 next=p4} - p·4:Node = {val=1 next=""} - pb + "·1" -> hp + p4:Node = {val=1} + p3:Node = {val=2 next=&p4} + p2:Node = {val=2 next=&p3} + p1:Node = {val=1 next=&p2} + &p1 -> hp is_pal(hp) - q:[int64]·Node = {} - kv·abs(q) -> qb - qb + "·2" -> q2 - q·1:Node = {val=1 next=q2} - q·2:Node = {val=2 next=""} - qb + "·1" -> hq + q2:Node = {val=2} + q1:Node = {val=1 next=&q2} + &q1 -> hq is_pal(hq) } diff --git a/tutorial/12-struct/03-linked-list.kv b/tutorial/12-struct/03-linked-list.kv index 2e86187d..c88a07c3 100644 --- a/tutorial/12-struct/03-linked-list.kv +++ b/tutorial/12-struct/03-linked-list.kv @@ -1,6 +1,6 @@ -// linked-list: struct 节点存进 map(int 键、struct 值),指针用绝对路径 -// 语义: /list 是 [int64]·Node 的 map;节点存在自增整数键 ·1 ·2 ·3; -// next 字段存下一节点的绝对路径串(""=尾);"路径"·field 解引用。 +// linked-list: 局部 struct 节点变量 + & 取址串成链表 +// 语义: 每个节点是帧内 struct 局部变量;next 存下一节点地址(&node ≡ kv·abs(node)); +// ""=尾;cur·field 按 next 路径解引用遍历。尾节点先建,&node 恒指向已存在节点。 // 期望输出: // 10 // 20 @@ -11,11 +11,10 @@ struct Node { } rwfunc test() -> () { - /list:[int64]·Node = {} - /list·1:Node = {val=10 next="/list·2"} - /list·2:Node = {val=20 next="/list·3"} - /list·3:Node = {val=30} - cur = "/list·1" + n3:Node = {val=30} + n2:Node = {val=20 next=&n3} + n1:Node = {val=10 next=&n2} + cur = &n1 while (cur != "") { cur·val -> v println(v) diff --git a/tutorial/12-struct/06-list-reverse.kv b/tutorial/12-struct/06-list-reverse.kv index 91404034..00f414aa 100644 --- a/tutorial/12-struct/06-list-reverse.kv +++ b/tutorial/12-struct/06-list-reverse.kv @@ -12,12 +12,11 @@ struct Node { } rwfunc test() -> () { - /list:[int64]·Node = {} - /list·1:Node = {val=10 next="/list·2"} - /list·2:Node = {val=20 next="/list·3"} - /list·3:Node = {val=30} + n3:Node = {val=30} + n2:Node = {val=20 next=&n3} + n1:Node = {val=10 next=&n2} prev = "" - cur = "/list·1" + cur = &n1 while (cur != "") { cur·next -> nxt prev -> cur·next diff --git a/tutorial/12-struct/07-list-local.kv b/tutorial/12-struct/07-list-local.kv index 6002b791..9f4bbb36 100644 --- a/tutorial/12-struct/07-list-local.kv +++ b/tutorial/12-struct/07-list-local.kv @@ -1,29 +1,24 @@ -// list-local: 用局部变量容器实现链表(不放全局绝对路径) -// 语义: list 是局部 map(帧内,路径含动态 vthread id,源码写不死); -// kv·abs(list) 取容器运行期绝对路径,拼 ·n 造节点指针串; -// struct 赋值 list·n:X = {…} 由 layout 下沉为 kv·cpdir 深拷子树(成员随之落位)。 +// list-local: 局部 struct 节点变量 + & 建链,遍历求和 +// 语义: 节点是帧内 struct 局部变量,next 存下一节点地址(&node ≡ kv·abs(node)); +// ""=尾;尾节点先建,&node 恒指向已存在节点。遍历累加各节点 val。 // 链表: 10→20→30 // 期望输出: -// 10 -// 20 -// 30 +// 60 struct Node { val:int64=0 next:[]char/utf32="" } rwfunc test() -> () { - list:[int64]·Node = {} - kv·abs(list) -> base - base + "·2" -> p2 - base + "·3" -> p3 - list·1:Node = {val=10 next=p2} - list·2:Node = {val=20 next=p3} - list·3:Node = {val=30} - base + "·1" -> cur + n3:Node = {val=30} + n2:Node = {val=20 next=&n3} + n1:Node = {val=10 next=&n2} + cur = &n1 + sum = 0 while (cur != "") { cur·val -> v - println(v) + sum + v -> sum cur·next -> cur } + println(sum) }