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
2 changes: 1 addition & 1 deletion layout/src/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1098,7 +1098,7 @@ fn infer_op_type(opcode: &str, reads: &[String], tm: &mut HashMap<String, String
| "string·formatuint" => return "char/utf32".to_string(),
"random.int63" => return "int64".to_string(),
"random·intn" | "random.uint64" | "string·parseuint" => return "uint64".to_string(),
"pow" | "sqrt" | "exp" | "log" => return "float64".to_string(),
"pow" | "sqrt" | "exp" | "log" | "string·parsefloat" => return "float64".to_string(),
"sign" => return "int64".to_string(),
"abs" | "neg" | "max" | "min" => {
return if !reads.is_empty() {
Expand Down
1 change: 1 addition & 0 deletions runtime/src/myrwircaps.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ static const struct { const char *op; kvlangBuiltinFn fn; } myrwircaps[] = {
{"string·slice", kvlangBuiltinStringSlice}, {"string·concat", kvlangBuiltinStringConcat},
{"string·formatint", kvlangBuiltinStringFormatInt}, {"string·formatuint", kvlangBuiltinStringFormatUint},
{"string·parseint", kvlangBuiltinStringParseInt}, {"string·parseuint", kvlangBuiltinStringParseUint},
{"string·parsefloat", kvlangBuiltinStringParseFloat},
{"time·now", kvlangBuiltinTimeNow}, {"time·sub", kvlangBuiltinTimeSub}, {"time·add", kvlangBuiltinTimeAdd},
{"time/duration·nanos", kvlangBuiltinDurFrom}, {"time/duration·millis", kvlangBuiltinDurFrom},
{"time/duration·seconds", kvlangBuiltinDurFrom}, {"time/duration·minutes", kvlangBuiltinDurFrom},
Expand Down
1 change: 1 addition & 0 deletions runtime/src/rwir_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ int kvlangBuiltinArray(kvlangFrame_t *f),
kvlangBuiltinStringFormatUint(kvlangFrame_t *f),
kvlangBuiltinStringParseInt(kvlangFrame_t *f),
kvlangBuiltinStringParseUint(kvlangFrame_t *f),
kvlangBuiltinStringParseFloat(kvlangFrame_t *f),
kvlangBuiltinTimeNow(kvlangFrame_t *f),
kvlangBuiltinTimeSub(kvlangFrame_t *f),
kvlangBuiltinTimeAdd(kvlangFrame_t *f),
Expand Down
16 changes: 16 additions & 0 deletions runtime/src/rwir_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,3 +260,19 @@ int kvlangBuiltinStringParseUint(kvlangFrame_t *f) {
int rc = kvlangBuiltinWriteResult(f, &e); kvlangXvalueFree(&e); kvlangBuiltinFreeInputs(in, n);
return rc;
}

/* string·parsefloat(s) -> f:对齐 Go strconv.ParseFloat / Python float() / Rust parse::<f64>()。
* 与 parseint 同形:整串须消费完(无尾随空白/垃圾),否则 ValueError;无 base(浮点无进制)。 */
int kvlangBuiltinStringParseFloat(kvlangFrame_t *f) {
kvlangXvalue_t in[2]; int n = kvlangBuiltinReadInputs(f, in, 2);
if (n < 1) return kvlangBuiltinSetErr(f, "TypeError: string.parsefloat requires a string");
char *s = kvlangXvalueValueString(&in[0]);
char *end = NULL; double v = strtod(s, &end);
int bad = s[0] == '\0' || end == s || *end != '\0';
free(s);
if (bad) { kvlangBuiltinFreeInputs(in, n); return kvlangBuiltinSetErr(f, "ValueError: string.parsefloat: invalid syntax"); }
uint8_t r[8]; memcpy(r, &v, 8);
kvlangXvalue_t e; kvlangXvalueNewTlv(&e, KVSPACE_KIND_FLOAT64, r, 8, 1);
int rc = kvlangBuiltinWriteResult(f, &e); kvlangXvalueFree(&e); kvlangBuiltinFreeInputs(in, n);
return rc;
}
6 changes: 5 additions & 1 deletion stdlib/kvlang/kvlangbrief.kv
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ rwfunc main() -> () {
### 外部进程/文件系统(networld)
- `networld/proc·exec(args, envs) -> code[, out, err]`:args/envs 是 `{...}` 数组字面量,args 首元素=可执行文件;out/err 是 `@[]uint8` 捕获句柄(绑定即捕获)。
- `networld/fs·size(p)->n`、`·read(p,start,len)->raw`、`·write(p,bytes)->n`、`·append(p,bytes)->n`、`·list(p)->names`、`·del(p)->code`、`·mkdir(p)->code`、`·exists(p)->b`。
- 文本级(rwfunc):`readtext(p)->(t,sz)`、`writetext(p,t)->n`(UTF-8 往返)、`match(name,pat)->b`(`*`/`?` 通配)、`glob(pat)->paths`、`grep(pat,path,glob)->hits`(`路径:行号:文本`)、`multi(path,olds,news)->(done,bad)`(逐条精确替换,全成才落盘)。
- 字符串↔字节:`xv·reinterpret("s","[]uint8")` 或 `xv·reinterpret(raw,"[]char/utf8")`。

```kv
Expand All @@ -216,7 +217,10 @@ networld/fs·write("/tmp/x.txt", xv·reinterpret("hi", "[]uint8")) -> n
- `kvlang·abs(x)`(= `&x`,取址)、`kvspace·cp(src,dst)`、`kvspace·cpdir(src,dst)`、`kvspace·cplist(src,dst)`、`kvspace·has(path)`。

### 字符串(string·*)
- `len / char / ord / cmp / find / slice / concat / formatint / formatuint / parseint / parseuint`。
- `len / char / ord / cmp / find / slice / concat / set / formatint / formatuint / parseint / parseuint / parsefloat`。
- rwfunc 判定/查找/替换:`eq / ne / empty / contains / startswith / endswith / eqfold`、`count / rfind`、`replace / replacen / cut`。
- rwfunc 修剪/切分:`trim / trimstart / trimend / padstart / padend`、`split / splitn / lines / fields / join`。
- rwfunc 变换/分类:`reverse / repeat / upper / lower / capitalize / title / swapcase`、`allinset / isalpha / isdigit / isalnum / isspace / isupper / islower / isxdigit / ispunct`(大小写与分类一律 ASCII)。

### 数组(ndarray·* / xv·*)
- `ndarray·numel / dim / shape`;`xv·at / set / reshape / reinterpret / langtype / bodylen`。
Expand Down
208 changes: 208 additions & 0 deletions stdlib/networld/fs.kv
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
// 欢迎加入kvspace世界
// lib networld/fs —— 宿主文件系统的文本级工具(rwfunc,kv 源码)。
// native rwir(字节级,runtime-rs):size / read(p,start,off) / write(p,bytes)
// / append / list / del / mkdir / exists。本库在其上补文本级组合:
// readtext / writetext 文件 ↔ []char/utf32 文本(UTF-8 解码 / 编码往返)
// match 名字段 shell 通配(* 任意串、? 单字符)
// glob 按通配展开路径
// grep 逐行查找(文件或目录下匹配 glob 的成员)
// multi 事务式多处编辑(逐条精确替换,全部成功才落盘)
// 文本约定:文件按 UTF-8 解码为 []char/utf32 后操作(只有定宽的 char/utf32 可
// 索引 / 切片);落盘再编码回 UTF-8。字节级 I/O 仍走 native rwir。

lib networld/fs {
// readtext(p) -> (t, sz):整文件读为文本;sz = 字节数(缺失 = -1,t = "")
rwfunc readtext(p:[]char/utf32) -> (t:[]char/utf32, sz:int64) {
networld/fs·size(p) -> sz
"" -> t
if (sz > 0) {
networld/fs·read(p, 0, sz) -> raw
xv·reinterpret(raw, "[]char/utf8") -> u8
char/utf32(u8) -> t
}
}
// writetext(p, t) -> n:文本按 UTF-8 覆盖写盘,返回字节数(失败 -1)
rwfunc writetext(p:[]char/utf32, t:[]char/utf32) -> (n:int64) {
char/utf8(t) -> u8
xv·reinterpret(u8, "[]uint8") -> bytes
networld/fs·write(p, bytes) -> n
}
// match(name, pat) -> b:名字段通配匹配(* 任意串、? 单字符,其余按字面)
rwfunc match(name:[]char/utf32, pat:[]char/utf32) -> (b:bool) {
nn = string·len(name)
pn = string·len(pat)
if (pn == 0) {
b = nn == 0
} else {
string·slice(pat, 1, pn) -> ptail
if (string·startswith(pat, "*")) {
networld/fs·match(name, ptail) -> b
if (!b && nn > 0) {
string·slice(name, 1, nn) -> ntail
networld/fs·match(ntail, pat) -> b
}
} else {
if (nn == 0) {
b = false
} else {
string·slice(name, 1, nn) -> ntail
if (string·startswith(pat, "?")) {
networld/fs·match(ntail, ptail) -> b
} else {
string·slice(name, 0, 1) -> nc
string·slice(pat, 0, 1) -> pc
if (string·cmp(nc, pc) == 0) {
networld/fs·match(ntail, ptail) -> b
} else {
b = false
}
}
}
}
}
}
// glob(pat) -> paths:按通配展开路径(\n 连接;无匹配 = 空串)。
// 仅最后一段可含 *?,其前目录须为字面路径,如 "/tmp/*.kv"、"src/*.c"。
rwfunc glob(pat:[]char/utf32) -> (paths:[]char/utf32) {
"" -> paths
ln = string·len(pat)
cut = -1
i = 0
while (i < ln) {
string·slice(pat, i, i + 1) -> c
if (string·cmp(c, "/") == 0) {
cut = i
}
i = i + 1
}
if (cut < 0) {
"." -> dir
pat -> np
} else {
string·slice(pat, 0, cut) -> dir
string·slice(pat, cut + 1, ln) -> np
}
dir -> scan
if (string·len(dir) == 0) {
"/" -> scan
}
networld/fs·list(scan) -> ns
kvspace·listlen(ns) -> nc
i = 0
while (i < nc) {
kvspace·listn(ns, i) -> k
kvspace·get(ns, k) -> nm
networld/fs·match(nm, np) -> ok
if (ok) {
string·concat(dir, "/") -> d
string·concat(d, nm) -> cp
string·concat(paths, cp) -> paths
string·concat(paths, "\n") -> paths
}
i = i + 1
}
}
// scan(text, path, pat) -> hits:逐行找含 pat 的行,输出 "path:行号:文本"\n
rwfunc scan(text:[]char/utf32, path:[]char/utf32,
pat:[]char/utf32) -> (hits:[]char/utf32) {
"" -> hits
ln = string·len(text)
pos = 0
no = 0
while (pos < ln) {
string·slice(text, pos, ln) -> rest
string·find(rest, "\n") -> e
no = no + 1
if (e == -1) {
string·slice(text, pos, ln) -> line
pos = ln
} else {
string·slice(text, pos, pos + e) -> line
pos = pos + e + 1
}
string·find(line, pat) -> h
if (h != -1) {
string·concat(hits, path) -> hits
string·concat(hits, ":") -> hits
string·formatint(no, 10) -> sn
string·concat(hits, sn) -> hits
string·concat(hits, ":") -> hits
string·concat(hits, line) -> hits
string·concat(hits, "\n") -> hits
}
}
}
// grep(pat, path, glob) -> hits:path 是文件则扫它本身;是目录则扫其下匹配
// glob 的成员(glob 空 = 全部成员)。命中输出 "路径:行号:文本",多行 \n 连接。
rwfunc grep(pat:[]char/utf32, path:[]char/utf32,
glob:[]char/utf32) -> (hits:[]char/utf32) {
"" -> hits
networld/fs·list(path) -> ns
kvspace·listlen(ns) -> nc
if (nc == 0) {
networld/fs·readtext(path) -> (t, sz)
if (sz > 0) {
networld/fs·scan(t, path, pat) -> h
string·concat(hits, h) -> hits
}
} else {
gl = string·len(glob)
i = 0
while (i < nc) {
kvspace·listn(ns, i) -> k
kvspace·get(ns, k) -> nm
networld/fs·match(nm, glob) -> ok
if (gl == 0 || ok) {
string·concat(path, "/") -> d
string·concat(d, nm) -> cp
networld/fs·readtext(cp) -> (t, sz)
if (sz > 0) {
networld/fs·scan(t, cp, pat) -> h
string·concat(hits, h) -> hits
}
}
i = i + 1
}
}
}
// multi(path, olds, news) -> (done, bad):事务式多处编辑。按序对文件文本做
// 逐条精确替换,每条 old 须恰命中 1 处;全部成功才落盘。
// bad = -1 全部成功,done = 条数(文件已落盘)
// bad >= 0 该下标编辑失败(未命中或多处命中),文件不变
// bad = -2 文件不可读 bad = -3 olds / news 长度不等
rwfunc multi(path:[]char/utf32, olds:*[int64]·[]char/utf32,
news:*[int64]·[]char/utf32) -> (done:int64, bad:int64) {
kvspace·listlen(olds) -> cnt
kvspace·listlen(news) -> m
done = 0
bad = -1
if (cnt != m) {
bad = -3
} else {
networld/fs·readtext(path) -> (t, sz)
if (sz < 0) {
bad = -2
} else {
i = 0
while (i < cnt) {
kvspace·listn(olds, i) -> ko
kvspace·listn(news, i) -> kn
kvspace·get(olds, ko) -> o
kvspace·get(news, kn) -> w
string·count(t, o) -> c
if (c != 1) {
bad = i
break
}
string·replace(t, o, w) -> (t2, _)
t = t2
done = done + 1
i = i + 1
}
if (bad < 0) {
networld/fs·writetext(path, t) -> wn
}
}
}
}
}
Loading
Loading