first version

This commit is contained in:
2026-08-16 12:46:15 +08:00
commit 932fce1b9e
40 changed files with 4005 additions and 0 deletions
+95
View File
@@ -0,0 +1,95 @@
macro package simapi.macros
import std.ast.*
import std.fs.*
import std.collection.*
/**
* 编译期宏:从指定 cjpm.toml 读取 version 字段并替换变量声明。
*
* 用法:
* ```
* @ReadTomlVersion[path: "cjpm.toml"] // 读取当前包(编译目录)的版本
* let appVersion: String = ""
* @ReadTomlVersion[path: "../simapi-cj/cjpm.toml"] // 读取父包版本
* let simApiVersion: String = ""
* ```
*
* 说明:宏在编译期执行,工作目录为 cjpm build 的运行目录(应用项目根)。
* 版本号仅匹配 `version = "x.y.z"`(排除 cjc-version)。
*/
public macro ReadTomlVersion(attr: Tokens, input: Tokens): Tokens {
var path = "cjpm.toml"
try {
let attrText = attr.toString()
if (let Some(idx) <- attrText.indexOf("path")) {
let rest = attrText[idx..]
if (let Some(q1) <- rest.indexOf("\"")) {
let after = rest[(q1 + 1)..]
if (let Some(q2) <- after.indexOf("\"")) {
path = after[0..q2]
}
}
}
} catch (_: Exception) {
}
var version = "0.0.0"
try {
let f = File(path, Read)
var buf = Array<Byte>(8192, repeat: 0)
var bytes = ArrayList<Byte>()
var n = f.read(buf)
while (n > 0) {
for (i in 0..n) {
bytes.add(buf[i])
}
n = f.read(buf)
}
f.close()
// 按行解析(version 行是纯 ASCII;避免整体 UTF-8 解码含中文的 description 失败)
let data = bytes.toArray()
var lineStart = 0
for (i in 0..data.size) {
let isLast = (i == data.size - 1)
if (data[i] == 10 || isLast) {
let end = if (data[i] == 10) { i } else { i + 1 }
let lineBytes = data[lineStart..end]
let lineText = String.fromUtf8(lineBytes)
if (!lineText.contains("cjc-version") && lineText.contains("version")) {
let parts = lineText.split("\"")
if (parts.size >= 2) {
version = parts[1]
}
}
lineStart = i + 1
}
}
} catch (ex: Exception) {
version = "error:${ex.message}"
}
// 生成替换声明:保留原声明的修饰符与变量名,只把值替换为版本号
// declPrefix 例:"public static let" / "private let" / "let"
var declPrefix = "let"
var varName = "v"
try {
let inputText = input.toString()
if (let Some(letIdx) <- inputText.indexOf("let")) {
let prefix = inputText[0..letIdx].trimEnd()
if (!prefix.isEmpty()) {
declPrefix = "${prefix} let"
}
let rest = inputText[letIdx..]
let afterLet = rest[3..].trimStart()
if (let Some(nameEnd) <- afterLet.indexOf(":")) {
varName = afterLet[0..nameEnd].trimEnd()
}
}
} catch (_: Exception) {
}
// 用 cangjieLex 把 "public static let name: String = "version"" 整体解析为 token 流
let declText = "${declPrefix} ${varName}: String = \"${version}\""
cangjieLex(declText)
}