Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/ISSUE_TEMPLATE/issue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
name: 通用 issue
about: 提交一个 kvlang issue(标题格式:类别/子类/题目)
title: "类别/子类/题目"
labels: []
---

<!-- 标题格式:类别/子类/题目,例如 1-layout/lower/rwir按kind特化 -->

<!-- 类别(子类不约束):
- 1-layout 编译期(parser / lower / 类型推断 / layout / format / vet)
- 2-runtime 执行期(kvcpu / dispatch / vthread / handoff / frame / pc)
- 3-tutorial 教程 / 回归用例
- 4-rwirext 扩展运行时(框架 + term / json / op-gpu / llm / agent)
- 0-kvspace kvspace 存储后端
- other 其他(perf / docs / infra)
-->

## 背景

## 需求描述

## 预期结果

## 方案简述
2 changes: 0 additions & 2 deletions keytree/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ const (
SegMsg = "msg" // 终态附加描述
SegSeq = "seq" // vtid 自增序列

SegRwir = "rwir" // /rwir

)

var (
Expand Down
5 changes: 3 additions & 2 deletions keytree/sys.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package keytree

const RwirRoot = PathSegSep + SegRwir
// RwirRoot rwir 签名统一落在 /lib 下(与 rwfunc 同根,靠 kind 区分)。
const RwirRoot = LibRoot

func Rwir(opcode string) string { return RwirRoot + PathSegSep + opcode }

// RwirRuntime 返回 /rwir/{runtime}/{opcode}。{runtime} 反射自可执行文件名。
// RwirRuntime 返回 /lib/{runtime}/{opcode}。{runtime} 反射自可执行文件名。
func RwirRuntime(runtime, opcode string) string {
return RwirRoot + PathSegSep + runtime + PathSegSep + opcode
}
3 changes: 2 additions & 1 deletion layout/layout.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ func countDirectInsts(body []ast.Stmt) int32 {
// ...
func WriteFunc(kv kvspace.KVSpace, pkg string, fn *ast.Func) {
typeMap := lower.InferTypes(fn)
lower.Specialize(fn, typeMap)
funcDir := keytree.LibFunc(pkg, fn.Sig.Name)
kv.DelTree(funcDir)
kvspace.MkIndexRecursive(kv, funcDir+"/")
Expand All @@ -376,7 +377,7 @@ func WriteFunc(kv kvspace.KVSpace, pkg string, fn *ast.Func) {
WriteBody(kv, pkg, fn.Sig.Name, fn.Body, typeMap, 1) // 指令从 [1,0] 开始
}

// WriteRwirDecl 将用户声明的 rwir(读写码,无体)写入 /rwir/<opcode>,kind=rwir。
// WriteRwirDecl 将用户声明的 rwir(读写码,无体)写入 /lib/<opcode>,kind=rwir。
func WriteRwirDecl(kv kvspace.KVSpace, decl *ast.RwirDecl) {
opcode := decl.Sig.Name
if decl.Pkg != "" {
Expand Down
45 changes: 42 additions & 3 deletions lower/infer.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ func inferInst(inst *ast.Instruction, tm map[string]string) {
if inst.Expr == nil || len(inst.Writes) == 0 {
return
}
// 记录显式声明的写类型(如 a:[]int64 → tm[a]="[]int64")
for j, w := range inst.Writes {
if j < len(inst.WriteTypes) && inst.WriteTypes[j] != "" {
if _, exists := tm[w]; !exists {
tm[w] = inst.WriteTypes[j]
}
}
}
// 快速路径:叶节点字面量直接从 Lit 字段获取类型,无需 Flat() → slotType() 字符串重解析。
if inst.Expr.IsLeaf() && inst.Expr.Lit != ast.LitNone {
if inferred := litToType(inst.Expr.Lit); inferred != "" {
Expand Down Expand Up @@ -155,12 +163,43 @@ func inferOpType(opcode string, reads []string, tm map[string]string) string {
switch opcode {
case "kvhas":
return "bool"
case "kvlen":
case "kvlen", "len", "string.len", "string.ord", "string.cmp", "string.find":
return "int64"
case "string.char", "string.set", "string.slice", "string.concat":
return "char/utf32"
case "random.int63":
return "int64"
case "random.intn", "random.uint64":
return "uint64"
case "pow", "sqrt", "exp", "log":
return "float64"
case "sign":
return "int64"
case "kvat":
// at 的返回类型取决于存储的值,无法静态推断
case "abs", "neg", "max", "min":
if len(reads) > 0 {
return slotType(reads[0], tm)
}
return ""
case "kvat", "at":
// 从数组首散 key 成员(base.0)或紧凑数组声明([]T)推断元素类型
if len(reads) > 0 {
if t := tm[reads[0]+".0"]; t != "" {
return t
}
if t := tm[reads[0]]; strings.HasPrefix(t, "[]") {
return t[2:]
}
}
return ""
case "set":
// set(base, k, v) -> base:记录数组首元素类型(供 kvat 推断元素类型)
if len(reads) >= 3 {
if t := slotType(reads[2], tm); t != "" {
if _, exists := tm[reads[0]+".0"]; !exists {
tm[reads[0]+".0"] = t
}
}
}
// set 回写原值,类型同 base
if len(reads) > 0 {
return slotType(reads[0], tm)
Expand Down
71 changes: 71 additions & 0 deletions lower/specialize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package lower

import (
"kvlang/ast"
"kvlang/rwir/builtin"
"kvlang/symbol"
)

// Specialize 将多态数值 op(add/+、eq/== 等)按读参类型特化为 /lib/{kind}/{op}。
// 选项 A:同 kind 保 kind,混型取更宽(int 按位宽、float 比 int 宽)。
func Specialize(fn *ast.Func, tm map[string]string) {
specializeBody(fn.Body, tm)
}

func specializeBody(body []ast.Stmt, tm map[string]string) {
for _, st := range body {
switch s := st.(type) {
case *ast.Instruction:
specializeInst(s, tm)
case *ast.ScopeStmt:
specializeBody(s.Body, tm)
case *ast.IfStmt:
if s.Cond != nil {
specializeInst(s.Cond, tm)
}
specializeBody(s.Then, tm)
specializeBody(s.Else, tm)
case *ast.WhileStmt:
if s.Cond != nil {
specializeInst(s.Cond, tm)
}
specializeBody(s.Body, tm)
case *ast.ForStmt:
specializeBody(s.Body, tm)
}
}
}

func specializeInst(inst *ast.Instruction, tm map[string]string) {
if inst.Expr == nil || inst.Expr.IsLeaf() {
return
}
opcode := inst.Expr.Op
word := symbol.Lookup(opcode).Word
if word == "" {
word = opcode
}
if !builtin.NumOp(word) {
return
}
kind := ""
for _, arg := range inst.Expr.Args {
t := slotType(arg.Val, tm)
if !builtin.IsNumKind(t) {
continue
}
if kind == "" {
kind = t
} else {
kind = builtin.WiderNumKind(kind, t)
}
}
if kind == "" {
return
}
kind = builtin.OpKind(word, kind)
if kind == "" {
return
}
inst.Expr.Op = kind + "." + word
}
4 changes: 2 additions & 2 deletions parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ var validKinds = map[string]bool{
"uint8": true, "uint16": true, "uint32": true, "uint64": true,
"float32": true, "float64": true,
"bool": true, "char/utf32": true, "char/utf8": true, "char/ascii": true,
"num": true, "any": true,
"any": true,
}

// validKindexp 校验类型表达式(kindexp):前缀修饰符序列 + 基础 kind。
Expand Down Expand Up @@ -337,7 +337,7 @@ func (p *parser) checkParamTypes(sig *ast.FuncSig) {
if kind == "string" || kind == "bytes" {
return "unknown type — use char/utf32 instead"
}
return "unknown type — valid: int8/16/32/64, uint8/16/32/64, float32/64, bool, char/utf32, num, any, []T, [N]T, *T"
return "unknown type — valid: int8/16/32/64, uint8/16/32/64, float32/64, bool, char/utf32, any, []T, [N]T, *T"
}
for _, param := range sig.Params {
if !validKindexp(param.Type) {
Expand Down
10 changes: 5 additions & 5 deletions rwir/builtin/arith.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import (
)

func init() {
registerWord("add", "rwir add(A:num, B:num) -> (C:num)", arith{f: func(a, b float64) float64 { return a + b }, fi: func(a, b int64) int64 { return a + b }, concat: true})
registerWord("sub", "rwir sub(A:num, B:num) -> (C:num)", arith{f: func(a, b float64) float64 { return a - b }, fi: func(a, b int64) int64 { return a - b }, unary: true})
registerWord("mul", "rwir mul(A:num, B:num) -> (C:num)", arith{f: func(a, b float64) float64 { return a * b }, fi: func(a, b int64) int64 { return a * b }})
registerWord("div", "rwir div(A:num, B:num) -> (C:num)", div{})
registerWord("mod", "rwir mod(A:int64, B:int64) -> (C:int64)", mod{})
registerKinds("add", 2, "", numKinds, arith{f: func(a, b float64) float64 { return a + b }, fi: func(a, b int64) int64 { return a + b }, concat: true})
registerKinds("sub", 2, "", numKinds, arith{f: func(a, b float64) float64 { return a - b }, fi: func(a, b int64) int64 { return a - b }, unary: true})
registerKinds("mul", 2, "", numKinds, arith{f: func(a, b float64) float64 { return a * b }, fi: func(a, b int64) int64 { return a * b }})
registerKinds("div", 2, "", numKinds, div{})
registerKinds("mod", 2, "", allIntKinds, mod{})
}

type arith struct{ f func(float64, float64) float64; fi func(int64, int64) int64; unary, concat bool }
Expand Down
12 changes: 6 additions & 6 deletions rwir/builtin/bit.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import (
)

func init() {
registerWord("bitand", "rwir bitand(A:int64, B:int64) -> (C:int64)", bit{f: func(a, b int64) int64 { return a & b }})
registerWord("bitor", "rwir bitor(A:int64, B:int64) -> (C:int64)", bit{f: func(a, b int64) int64 { return a | b }})
registerWord("bitxor", "rwir bitxor(A:int64, B:int64) -> (C:int64)", bit{f: func(a, b int64) int64 { return a ^ b }})
registerWord("shl", "rwir shl(A:int64, B:int64) -> (C:int64)", bit{f: func(a, b int64) int64 { return a << uint64(b) }})
registerWord("shr", "rwir shr(A:int64, B:int64) -> (C:int64)", bit{f: func(a, b int64) int64 { return a >> uint64(b) }})
registerKinds("bitand", 2, "", []string{"int64", "uint64"}, bit{f: func(a, b int64) int64 { return a & b }})
registerKinds("bitor", 2, "", []string{"int64", "uint64"}, bit{f: func(a, b int64) int64 { return a | b }})
registerKinds("bitxor", 2, "", []string{"int64", "uint64"}, bit{f: func(a, b int64) int64 { return a ^ b }})
registerKinds("shl", 2, "", []string{"int64", "uint64"}, bit{f: func(a, b int64) int64 { return a << uint64(b) }})
registerKinds("shr", 2, "", []string{"int64", "uint64"}, bit{f: func(a, b int64) int64 { return a >> uint64(b) }})
}

type bit struct{ f func(int64, int64) int64 }
Expand All @@ -30,5 +30,5 @@ func evalBinaryInt(inputs []kvspace.XValue, fn func(int64, int64) int64) (kvspac
}
// 位运算仅整数(五语言一致:C/Rust/Go/JS 均禁止浮点位运算,Python & 是 set intersection)
if err := requireInt(inputs[0], inputs[1]); err != nil { return kvspace.None{}, err }
return kvspace.NewInt64(fn(asInt64(inputs[0]), asInt64(inputs[1]))), nil
return narrowInt(inputs[0].Kind(), inputs[1].Kind(), fn(asInt64(inputs[0]), asInt64(inputs[1]))), nil
}
12 changes: 6 additions & 6 deletions rwir/builtin/cmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import (

func init() {
eqCmp := cmp{f: func(a, b float64) bool { return a == b }, p: func(c int) bool { return c == 0 }, s: func(a, b string) bool { return a == b }, allowNull: true}
registerWord("eq", "rwir eq(A:num, B:num) -> (C:bool)", eqCmp)
registerKinds("eq", 2, "bool", numKinds, eqCmp)
neqCmp := cmp{f: func(a, b float64) bool { return a != b }, p: func(c int) bool { return c != 0 }, s: func(a, b string) bool { return a != b }, allowNull: true}
registerWord("neq", "rwir neq(A:num, B:num) -> (C:bool)", neqCmp)
registerWord("lt", "rwir lt(A:num, B:num) -> (C:bool)", cmp{f: func(a, b float64) bool { return a < b }, p: func(c int) bool { return c < 0 }, s: func(a, b string) bool { return a < b }})
registerWord("gt", "rwir gt(A:num, B:num) -> (C:bool)", cmp{f: func(a, b float64) bool { return a > b }, p: func(c int) bool { return c > 0 }, s: func(a, b string) bool { return a > b }})
registerWord("le", "rwir le(A:num, B:num) -> (C:bool)", cmp{f: func(a, b float64) bool { return a <= b }, p: func(c int) bool { return c <= 0 }, s: func(a, b string) bool { return a <= b }})
registerWord("ge", "rwir ge(A:num, B:num) -> (C:bool)", cmp{f: func(a, b float64) bool { return a >= b }, p: func(c int) bool { return c >= 0 }, s: func(a, b string) bool { return a >= b }})
registerKinds("neq", 2, "bool", numKinds, neqCmp)
registerKinds("lt", 2, "bool", numKinds, cmp{f: func(a, b float64) bool { return a < b }, p: func(c int) bool { return c < 0 }, s: func(a, b string) bool { return a < b }})
registerKinds("gt", 2, "bool", numKinds, cmp{f: func(a, b float64) bool { return a > b }, p: func(c int) bool { return c > 0 }, s: func(a, b string) bool { return a > b }})
registerKinds("le", 2, "bool", numKinds, cmp{f: func(a, b float64) bool { return a <= b }, p: func(c int) bool { return c <= 0 }, s: func(a, b string) bool { return a <= b }})
registerKinds("ge", 2, "bool", numKinds, cmp{f: func(a, b float64) bool { return a >= b }, p: func(c int) bool { return c >= 0 }, s: func(a, b string) bool { return a >= b }})
}

type cmp struct {
Expand Down
12 changes: 6 additions & 6 deletions rwir/builtin/coerce.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ func isUnsignedKind(k string) bool {
return false
}

func intKindWidth(k string) int {
func IntKindWidth(k string) int {
switch k {
case "int8", "uint8":
return 8
Expand All @@ -194,8 +194,8 @@ func intKindWidth(k string) int {
return 0
}

func widerIntKind(ak, bk string) string {
aw, bw := intKindWidth(ak), intKindWidth(bk)
func WiderIntKind(ak, bk string) string {
aw, bw := IntKindWidth(ak), IntKindWidth(bk)
au, bu := isUnsignedKind(ak), isUnsignedKind(bk)
if au && bu {
if aw >= bw {
Expand Down Expand Up @@ -225,7 +225,7 @@ func widerIntKind(ak, bk string) string {
}
}

func widerFloatKind(ak, bk string) string {
func WiderFloatKind(ak, bk string) string {
if ak == "float64" || bk == "float64" {
return "float64"
}
Expand All @@ -236,7 +236,7 @@ func widerFloatKind(ak, bk string) string {
}

func narrowInt(ak, bk string, v int64) kvspace.XValue {
kind := widerIntKind(ak, bk)
kind := WiderIntKind(ak, bk)
switch kind {
case "int8":
return kvspace.NewInt8(int8(v))
Expand All @@ -260,7 +260,7 @@ func narrowInt(ak, bk string, v int64) kvspace.XValue {
}

func narrowFloat(ak, bk string, v float64) kvspace.XValue {
if widerFloatKind(ak, bk) == "float32" {
if WiderFloatKind(ak, bk) == "float32" {
return kvspace.NewFloat32(float32(v))
}
return kvspace.NewFloat64(v)
Expand Down
Loading
Loading