feat: Charter编译器完整扩展支持标准库语法
已完成功能(生产级别): 1. 顶层函数支持(pub fn) 2. Rust风格类型别名(u256, i256等) 3. require关键字支持 4. 所有比较操作符(>=, <=, !=等) 5. if表达式(三元表达式) 6. 文档注释(///)支持 7. 函数参数作用域管理 8. 类型转换(as关键字) 9. 可变变量(mut关键字) 每个功能包含完整的: - 词法分析(Token定义) - 语法分析(AST节点和解析器) - 语义分析(类型推断和验证) - 代码生成(NVM字节码生成) 模块:charter-compiler 状态:生产级别(零错误零警告) 测试:所有单元测试通过
This commit is contained in:
parent
1031508b6c
commit
0eace448bc
|
|
@ -1,6 +1,6 @@
|
||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
|
|
@ -108,9 +108,9 @@ checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.10.0"
|
version = "2.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitvec"
|
name = "bitvec"
|
||||||
|
|
@ -173,9 +173,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.55"
|
version = "1.2.56"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29"
|
checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"find-msvc-tools",
|
"find-msvc-tools",
|
||||||
"shlex",
|
"shlex",
|
||||||
|
|
@ -192,7 +192,6 @@ name = "charter-compiler"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"blake3",
|
|
||||||
"clap",
|
"clap",
|
||||||
"criterion",
|
"criterion",
|
||||||
"hex",
|
"hex",
|
||||||
|
|
@ -201,6 +200,7 @@ dependencies = [
|
||||||
"pest",
|
"pest",
|
||||||
"pest_derive",
|
"pest_derive",
|
||||||
"serde",
|
"serde",
|
||||||
|
"sha3",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|
@ -250,9 +250,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.57"
|
version = "4.5.59"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6899ea499e3fb9305a65d5ebf6e3d2248c5fab291f300ad0a704fbe142eae31a"
|
checksum = "c5caf74d17c3aec5495110c34cc3f78644bfa89af6c8993ed4de2790e49b6499"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
|
|
@ -260,9 +260,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.5.57"
|
version = "4.5.59"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b12c8b680195a62a8364d16b8447b01b6c2c8f9aaf68bee653be34d4245e238"
|
checksum = "370daa45065b80218950227371916a1633217ae42b2715b2287b606dcd618e24"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
|
|
@ -284,9 +284,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_lex"
|
name = "clap_lex"
|
||||||
version = "0.7.7"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32"
|
checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorchoice"
|
name = "colorchoice"
|
||||||
|
|
@ -474,6 +474,12 @@ version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foldhash"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "funty"
|
name = "funty"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
|
@ -503,14 +509,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.3.4"
|
version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"r-efi",
|
"r-efi",
|
||||||
"wasip2",
|
"wasip2",
|
||||||
|
"wasip3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -524,6 +531,15 @@ dependencies = [
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.15.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||||
|
dependencies = [
|
||||||
|
"foldhash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.16.1"
|
version = "0.16.1"
|
||||||
|
|
@ -572,6 +588,12 @@ dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "id-arena"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "impl-codec"
|
name = "impl-codec"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
|
@ -599,7 +621,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown",
|
"hashbrown 0.16.1",
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -646,9 +670,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "keccak"
|
name = "keccak"
|
||||||
version = "0.1.5"
|
version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654"
|
checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
]
|
]
|
||||||
|
|
@ -660,10 +684,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "leb128fmt"
|
||||||
version = "0.2.180"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.182"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
|
|
@ -881,6 +911,16 @@ dependencies = [
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prettyplease"
|
||||||
|
version = "0.2.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "primitive-types"
|
name = "primitive-types"
|
||||||
version = "0.12.2"
|
version = "0.12.2"
|
||||||
|
|
@ -1050,6 +1090,12 @@ dependencies = [
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.228"
|
version = "1.0.228"
|
||||||
|
|
@ -1149,9 +1195,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.114"
|
version = "2.0.116"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
|
checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -1166,12 +1212,12 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.24.0"
|
version = "3.25.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c"
|
checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"getrandom 0.3.4",
|
"getrandom 0.4.1",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix",
|
"rustix",
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
|
|
@ -1239,9 +1285,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_parser"
|
name = "toml_parser"
|
||||||
version = "1.0.6+spec-1.1.0"
|
version = "1.0.9+spec-1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44"
|
checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
@ -1329,9 +1375,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.23"
|
version = "1.0.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e"
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
|
|
@ -1382,6 +1428,15 @@ dependencies = [
|
||||||
"wit-bindgen",
|
"wit-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasip3"
|
||||||
|
version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
|
||||||
|
dependencies = [
|
||||||
|
"wit-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.108"
|
version = "0.2.108"
|
||||||
|
|
@ -1427,6 +1482,40 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-encoder"
|
||||||
|
version = "0.244.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
|
||||||
|
dependencies = [
|
||||||
|
"leb128fmt",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-metadata"
|
||||||
|
version = "0.244.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"indexmap",
|
||||||
|
"wasm-encoder",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasmparser"
|
||||||
|
version = "0.244.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"hashbrown 0.15.5",
|
||||||
|
"indexmap",
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.85"
|
version = "0.3.85"
|
||||||
|
|
@ -1528,6 +1617,88 @@ name = "wit-bindgen"
|
||||||
version = "0.51.0"
|
version = "0.51.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
||||||
|
dependencies = [
|
||||||
|
"wit-bindgen-rust-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-core"
|
||||||
|
version = "0.51.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"heck",
|
||||||
|
"wit-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-rust"
|
||||||
|
version = "0.51.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"heck",
|
||||||
|
"indexmap",
|
||||||
|
"prettyplease",
|
||||||
|
"syn",
|
||||||
|
"wasm-metadata",
|
||||||
|
"wit-bindgen-core",
|
||||||
|
"wit-component",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-rust-macro"
|
||||||
|
version = "0.51.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"prettyplease",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wit-bindgen-core",
|
||||||
|
"wit-bindgen-rust",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-component"
|
||||||
|
version = "0.244.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"bitflags",
|
||||||
|
"indexmap",
|
||||||
|
"log",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"wasm-encoder",
|
||||||
|
"wasm-metadata",
|
||||||
|
"wasmparser",
|
||||||
|
"wit-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-parser"
|
||||||
|
version = "0.244.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"id-arena",
|
||||||
|
"indexmap",
|
||||||
|
"log",
|
||||||
|
"semver",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"unicode-xid",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wyz"
|
name = "wyz"
|
||||||
|
|
@ -1560,6 +1731,6 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zmij"
|
name = "zmij"
|
||||||
version = "1.0.20"
|
version = "1.0.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4de98dfa5d5b7fef4ee834d0073d560c9ca7b6c46a71d058c48db7960f8cfaf7"
|
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,9 @@ impl CodeGenerator {
|
||||||
TopLevelItem::Contract(contract) => {
|
TopLevelItem::Contract(contract) => {
|
||||||
self.generate_contract(contract)?;
|
self.generate_contract(contract)?;
|
||||||
}
|
}
|
||||||
|
TopLevelItem::Function(function) => {
|
||||||
|
self.generate_function(function)?;
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -155,6 +158,20 @@ impl CodeGenerator {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_function(&mut self, function: &FunctionDeclaration) -> Result<(), CodegenError> {
|
||||||
|
self.emit_comment(&format!("Function: {}", function.name));
|
||||||
|
|
||||||
|
// 添加参数到变量映射
|
||||||
|
for (i, param) in function.parameters.iter().enumerate() {
|
||||||
|
self.variables.insert(param.name.clone(), i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成函数体
|
||||||
|
self.generate_block(&function.body)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn generate_method(&mut self, method: &MethodDeclaration) -> Result<(), CodegenError> {
|
fn generate_method(&mut self, method: &MethodDeclaration) -> Result<(), CodegenError> {
|
||||||
self.emit_comment(&format!("Method: {}", method.name));
|
self.emit_comment(&format!("Method: {}", method.name));
|
||||||
|
|
||||||
|
|
@ -353,8 +370,22 @@ impl CodeGenerator {
|
||||||
BinaryOp::Div => self.emit(OpCode::DIV),
|
BinaryOp::Div => self.emit(OpCode::DIV),
|
||||||
BinaryOp::Mod => self.emit(OpCode::MOD),
|
BinaryOp::Mod => self.emit(OpCode::MOD),
|
||||||
BinaryOp::Equal => self.emit(OpCode::EQ),
|
BinaryOp::Equal => self.emit(OpCode::EQ),
|
||||||
|
BinaryOp::NotEqual => {
|
||||||
|
self.emit(OpCode::EQ);
|
||||||
|
self.emit(OpCode::IS_ZERO);
|
||||||
|
}
|
||||||
BinaryOp::Less => self.emit(OpCode::LT),
|
BinaryOp::Less => self.emit(OpCode::LT),
|
||||||
|
BinaryOp::LessEqual => {
|
||||||
|
// a <= b 等价于 !(a > b)
|
||||||
|
self.emit(OpCode::GT);
|
||||||
|
self.emit(OpCode::IS_ZERO);
|
||||||
|
}
|
||||||
BinaryOp::Greater => self.emit(OpCode::GT),
|
BinaryOp::Greater => self.emit(OpCode::GT),
|
||||||
|
BinaryOp::GreaterEqual => {
|
||||||
|
// a >= b 等价于 !(a < b)
|
||||||
|
self.emit(OpCode::LT);
|
||||||
|
self.emit(OpCode::IS_ZERO);
|
||||||
|
}
|
||||||
BinaryOp::And => self.emit(OpCode::AND),
|
BinaryOp::And => self.emit(OpCode::AND),
|
||||||
BinaryOp::Or => self.emit(OpCode::OR),
|
BinaryOp::Or => self.emit(OpCode::OR),
|
||||||
_ => return Err(CodegenError::UnsupportedOperation(format!("{:?}", op))),
|
_ => return Err(CodegenError::UnsupportedOperation(format!("{:?}", op))),
|
||||||
|
|
@ -362,6 +393,35 @@ impl CodeGenerator {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Expression::Cast(expr, _target_type) => {
|
||||||
|
// 生成表达式(类型转换在NVM层面是透明的)
|
||||||
|
self.generate_expression(expr)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Expression::If(condition, then_expr, else_expr) => {
|
||||||
|
// 生成条件
|
||||||
|
self.generate_expression(condition)?;
|
||||||
|
|
||||||
|
// 如果条件为false,跳转到else分支
|
||||||
|
let else_label = self.create_label();
|
||||||
|
let end_label = self.create_label();
|
||||||
|
|
||||||
|
self.emit(OpCode::IS_ZERO);
|
||||||
|
self.emit_jumpi(&else_label);
|
||||||
|
|
||||||
|
// then分支
|
||||||
|
self.generate_expression(then_expr)?;
|
||||||
|
self.emit_jump(&end_label);
|
||||||
|
|
||||||
|
// else分支
|
||||||
|
self.place_label(&else_label);
|
||||||
|
self.generate_expression(else_expr)?;
|
||||||
|
|
||||||
|
// 结束
|
||||||
|
self.place_label(&end_label);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Expression::Unary(op, expr) => {
|
Expression::Unary(op, expr) => {
|
||||||
self.generate_expression(expr)?;
|
self.generate_expression(expr)?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Logos, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Logos, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[logos(skip r"[ \t\r\n]+")]
|
#[logos(skip r"[ \t\r\n]+")]
|
||||||
|
#[logos(skip r"///[^\n]*")]
|
||||||
#[logos(skip r"//[^\n]*")]
|
#[logos(skip r"//[^\n]*")]
|
||||||
#[logos(skip r"/\*([^*]|\*[^/])*\*/")]
|
#[logos(skip r"/\*([^*]|\*[^/])*\*/")]
|
||||||
pub enum Token {
|
pub enum Token {
|
||||||
|
|
@ -22,6 +23,9 @@ pub enum Token {
|
||||||
#[token("let")]
|
#[token("let")]
|
||||||
Let,
|
Let,
|
||||||
|
|
||||||
|
#[token("mut")]
|
||||||
|
Mut,
|
||||||
|
|
||||||
#[token("if")]
|
#[token("if")]
|
||||||
If,
|
If,
|
||||||
|
|
||||||
|
|
@ -49,6 +53,9 @@ pub enum Token {
|
||||||
#[token("import")]
|
#[token("import")]
|
||||||
Import,
|
Import,
|
||||||
|
|
||||||
|
#[token("as")]
|
||||||
|
As,
|
||||||
|
|
||||||
// NAC特有关键字
|
// NAC特有关键字
|
||||||
#[token("gnacs")]
|
#[token("gnacs")]
|
||||||
Gnacs,
|
Gnacs,
|
||||||
|
|
@ -56,6 +63,9 @@ pub enum Token {
|
||||||
#[token("sovereignty")]
|
#[token("sovereignty")]
|
||||||
Sovereignty,
|
Sovereignty,
|
||||||
|
|
||||||
|
#[token("require")]
|
||||||
|
Require,
|
||||||
|
|
||||||
#[token("requires")]
|
#[token("requires")]
|
||||||
Requires,
|
Requires,
|
||||||
|
|
||||||
|
|
@ -69,6 +79,9 @@ pub enum Token {
|
||||||
VerifyCR,
|
VerifyCR,
|
||||||
|
|
||||||
// 修饰符
|
// 修饰符
|
||||||
|
#[token("pub")]
|
||||||
|
Pub,
|
||||||
|
|
||||||
#[token("public")]
|
#[token("public")]
|
||||||
Public,
|
Public,
|
||||||
|
|
||||||
|
|
@ -89,39 +102,51 @@ pub enum Token {
|
||||||
|
|
||||||
// 基础类型
|
// 基础类型
|
||||||
#[token("uint8")]
|
#[token("uint8")]
|
||||||
|
#[token("u8")]
|
||||||
Uint8,
|
Uint8,
|
||||||
|
|
||||||
#[token("uint16")]
|
#[token("uint16")]
|
||||||
|
#[token("u16")]
|
||||||
Uint16,
|
Uint16,
|
||||||
|
|
||||||
#[token("uint32")]
|
#[token("uint32")]
|
||||||
|
#[token("u32")]
|
||||||
Uint32,
|
Uint32,
|
||||||
|
|
||||||
#[token("uint64")]
|
#[token("uint64")]
|
||||||
|
#[token("u64")]
|
||||||
Uint64,
|
Uint64,
|
||||||
|
|
||||||
#[token("uint128")]
|
#[token("uint128")]
|
||||||
|
#[token("u128")]
|
||||||
Uint128,
|
Uint128,
|
||||||
|
|
||||||
#[token("uint256")]
|
#[token("uint256")]
|
||||||
|
#[token("u256")]
|
||||||
Uint256,
|
Uint256,
|
||||||
|
|
||||||
#[token("int8")]
|
#[token("int8")]
|
||||||
|
#[token("i8")]
|
||||||
Int8,
|
Int8,
|
||||||
|
|
||||||
#[token("int16")]
|
#[token("int16")]
|
||||||
|
#[token("i16")]
|
||||||
Int16,
|
Int16,
|
||||||
|
|
||||||
#[token("int32")]
|
#[token("int32")]
|
||||||
|
#[token("i32")]
|
||||||
Int32,
|
Int32,
|
||||||
|
|
||||||
#[token("int64")]
|
#[token("int64")]
|
||||||
|
#[token("i64")]
|
||||||
Int64,
|
Int64,
|
||||||
|
|
||||||
#[token("int128")]
|
#[token("int128")]
|
||||||
|
#[token("i128")]
|
||||||
Int128,
|
Int128,
|
||||||
|
|
||||||
#[token("int256")]
|
#[token("int256")]
|
||||||
|
#[token("i256")]
|
||||||
Int256,
|
Int256,
|
||||||
|
|
||||||
#[token("bool")]
|
#[token("bool")]
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,17 @@ pub enum TopLevelItem {
|
||||||
Import(ImportStatement),
|
Import(ImportStatement),
|
||||||
Asset(AssetDefinition),
|
Asset(AssetDefinition),
|
||||||
Contract(ContractDefinition),
|
Contract(ContractDefinition),
|
||||||
|
Function(FunctionDeclaration),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 函数声明(顶层函数,用于标准库)
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct FunctionDeclaration {
|
||||||
|
pub modifiers: Vec<MethodModifier>,
|
||||||
|
pub name: String,
|
||||||
|
pub parameters: Vec<Parameter>,
|
||||||
|
pub return_type: Option<TypeAnnotation>,
|
||||||
|
pub body: Block,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 模块声明
|
/// 模块声明
|
||||||
|
|
@ -150,6 +161,7 @@ pub enum Statement {
|
||||||
/// Let语句
|
/// Let语句
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct LetStatement {
|
pub struct LetStatement {
|
||||||
|
pub mutable: bool,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub type_annotation: Option<TypeAnnotation>,
|
pub type_annotation: Option<TypeAnnotation>,
|
||||||
pub value: Expression,
|
pub value: Expression,
|
||||||
|
|
@ -226,6 +238,12 @@ pub enum Expression {
|
||||||
|
|
||||||
// 数组访问
|
// 数组访问
|
||||||
ArrayAccess(Box<Expression>, Box<Expression>),
|
ArrayAccess(Box<Expression>, Box<Expression>),
|
||||||
|
|
||||||
|
// If表达式(三元表达式)
|
||||||
|
If(Box<Expression>, Box<Expression>, Box<Expression>),
|
||||||
|
|
||||||
|
// 类型转换
|
||||||
|
Cast(Box<Expression>, TypeAnnotation),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 二元运算符
|
/// 二元运算符
|
||||||
|
|
|
||||||
|
|
@ -104,8 +104,11 @@ impl Parser {
|
||||||
Some(Token::Contract) => {
|
Some(Token::Contract) => {
|
||||||
Ok(TopLevelItem::Contract(self.parse_contract_definition()?))
|
Ok(TopLevelItem::Contract(self.parse_contract_definition()?))
|
||||||
}
|
}
|
||||||
|
Some(Token::Pub) | Some(Token::Public) | Some(Token::Fn) => {
|
||||||
|
Ok(TopLevelItem::Function(self.parse_function_declaration()?))
|
||||||
|
}
|
||||||
_ => Err(ParseError::UnexpectedToken {
|
_ => Err(ParseError::UnexpectedToken {
|
||||||
expected: "module, import, asset, or contract".to_string(),
|
expected: "module, import, asset, contract, or function".to_string(),
|
||||||
actual: format!("{:?}", self.peek()),
|
actual: format!("{:?}", self.peek()),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
@ -198,6 +201,51 @@ impl Parser {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_function_declaration(&mut self) -> Result<FunctionDeclaration, ParseError> {
|
||||||
|
// 解析修饰符
|
||||||
|
let mut modifiers = Vec::new();
|
||||||
|
while let Some(modifier) = self.parse_method_modifier() {
|
||||||
|
modifiers.push(modifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.expect(Token::Fn)?;
|
||||||
|
let name = self.parse_identifier()?;
|
||||||
|
self.expect(Token::LeftParen)?;
|
||||||
|
|
||||||
|
// 解析参数
|
||||||
|
let mut parameters = Vec::new();
|
||||||
|
if !matches!(self.peek(), Some(Token::RightParen)) {
|
||||||
|
loop {
|
||||||
|
parameters.push(self.parse_parameter()?);
|
||||||
|
if matches!(self.peek(), Some(Token::Comma)) {
|
||||||
|
self.advance();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.expect(Token::RightParen)?;
|
||||||
|
|
||||||
|
// 解析返回类型
|
||||||
|
let return_type = if matches!(self.peek(), Some(Token::Arrow)) {
|
||||||
|
self.advance();
|
||||||
|
Some(self.parse_type_annotation()?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// 解析函数体
|
||||||
|
let body = self.parse_block()?;
|
||||||
|
|
||||||
|
Ok(FunctionDeclaration {
|
||||||
|
modifiers,
|
||||||
|
name,
|
||||||
|
parameters,
|
||||||
|
return_type,
|
||||||
|
body,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_method_declaration(&mut self) -> Result<MethodDeclaration, ParseError> {
|
fn parse_method_declaration(&mut self) -> Result<MethodDeclaration, ParseError> {
|
||||||
// 解析修饰符
|
// 解析修饰符
|
||||||
let mut modifiers = Vec::new();
|
let mut modifiers = Vec::new();
|
||||||
|
|
@ -277,7 +325,7 @@ impl Parser {
|
||||||
|
|
||||||
fn parse_method_modifier(&mut self) -> Option<MethodModifier> {
|
fn parse_method_modifier(&mut self) -> Option<MethodModifier> {
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(Token::Public) => {
|
Some(Token::Pub) | Some(Token::Public) => {
|
||||||
self.advance();
|
self.advance();
|
||||||
Some(MethodModifier::Public)
|
Some(MethodModifier::Public)
|
||||||
}
|
}
|
||||||
|
|
@ -396,6 +444,15 @@ impl Parser {
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(Token::Let) => {
|
Some(Token::Let) => {
|
||||||
self.advance();
|
self.advance();
|
||||||
|
|
||||||
|
// 检查是否有mut关键字
|
||||||
|
let mutable = if matches!(self.peek(), Some(Token::Mut)) {
|
||||||
|
self.advance();
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
let name = self.parse_identifier()?;
|
let name = self.parse_identifier()?;
|
||||||
|
|
||||||
let type_annotation = if matches!(self.peek(), Some(Token::Colon)) {
|
let type_annotation = if matches!(self.peek(), Some(Token::Colon)) {
|
||||||
|
|
@ -410,6 +467,7 @@ impl Parser {
|
||||||
self.expect(Token::Semicolon)?;
|
self.expect(Token::Semicolon)?;
|
||||||
|
|
||||||
Ok(Statement::Let(LetStatement {
|
Ok(Statement::Let(LetStatement {
|
||||||
|
mutable,
|
||||||
name,
|
name,
|
||||||
type_annotation,
|
type_annotation,
|
||||||
value,
|
value,
|
||||||
|
|
@ -694,6 +752,11 @@ impl Parser {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some(Token::As) => {
|
||||||
|
self.advance();
|
||||||
|
let target_type = self.parse_type_annotation()?;
|
||||||
|
expr = Expression::Cast(Box::new(expr), target_type);
|
||||||
|
}
|
||||||
_ => break,
|
_ => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -736,6 +799,22 @@ impl Parser {
|
||||||
self.advance();
|
self.advance();
|
||||||
Ok(Expression::DID(value))
|
Ok(Expression::DID(value))
|
||||||
}
|
}
|
||||||
|
Some(Token::If) => {
|
||||||
|
self.advance();
|
||||||
|
let condition = self.parse_expression()?;
|
||||||
|
self.expect(Token::LeftBrace)?;
|
||||||
|
let then_expr = self.parse_expression()?;
|
||||||
|
self.expect(Token::RightBrace)?;
|
||||||
|
self.expect(Token::Else)?;
|
||||||
|
self.expect(Token::LeftBrace)?;
|
||||||
|
let else_expr = self.parse_expression()?;
|
||||||
|
self.expect(Token::RightBrace)?;
|
||||||
|
Ok(Expression::If(Box::new(condition), Box::new(then_expr), Box::new(else_expr)))
|
||||||
|
}
|
||||||
|
Some(Token::Require) => {
|
||||||
|
self.advance();
|
||||||
|
Ok(Expression::Identifier("require".to_string()))
|
||||||
|
}
|
||||||
Some(Token::Identifier(s)) => {
|
Some(Token::Identifier(s)) => {
|
||||||
let name = s.clone();
|
let name = s.clone();
|
||||||
self.advance();
|
self.advance();
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ pub struct SemanticAnalyzer {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
struct FunctionSignature {
|
struct FunctionSignature {
|
||||||
|
name: String,
|
||||||
parameters: Vec<TypeAnnotation>,
|
parameters: Vec<TypeAnnotation>,
|
||||||
return_type: Option<TypeAnnotation>,
|
return_type: Option<TypeAnnotation>,
|
||||||
}
|
}
|
||||||
|
|
@ -75,6 +76,9 @@ impl SemanticAnalyzer {
|
||||||
TopLevelItem::Contract(contract) => {
|
TopLevelItem::Contract(contract) => {
|
||||||
self.collect_contract(contract)?;
|
self.collect_contract(contract)?;
|
||||||
}
|
}
|
||||||
|
TopLevelItem::Function(function) => {
|
||||||
|
self.collect_function(function)?;
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -88,6 +92,9 @@ impl SemanticAnalyzer {
|
||||||
TopLevelItem::Contract(contract) => {
|
TopLevelItem::Contract(contract) => {
|
||||||
self.validate_contract(contract)?;
|
self.validate_contract(contract)?;
|
||||||
}
|
}
|
||||||
|
TopLevelItem::Function(function) => {
|
||||||
|
self.validate_function(function)?;
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -113,6 +120,22 @@ impl SemanticAnalyzer {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn collect_function(&mut self, function: &FunctionDeclaration) -> Result<(), SemanticError> {
|
||||||
|
if self.functions.contains_key(&function.name) {
|
||||||
|
return Err(SemanticError::DuplicateDefinition(function.name.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造函数签名
|
||||||
|
let signature = FunctionSignature {
|
||||||
|
name: function.name.clone(),
|
||||||
|
parameters: function.parameters.iter().map(|p| p.type_annotation.clone()).collect(),
|
||||||
|
return_type: function.return_type.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.functions.insert(function.name.clone(), signature);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn validate_asset(&mut self, asset: &AssetDefinition) -> Result<(), SemanticError> {
|
fn validate_asset(&mut self, asset: &AssetDefinition) -> Result<(), SemanticError> {
|
||||||
// 验证GNACS编码
|
// 验证GNACS编码
|
||||||
self.validate_gnacs_code(&asset.gnacs_code)?;
|
self.validate_gnacs_code(&asset.gnacs_code)?;
|
||||||
|
|
@ -149,6 +172,24 @@ impl SemanticAnalyzer {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn validate_function(&mut self, function: &FunctionDeclaration) -> Result<(), SemanticError> {
|
||||||
|
// 创建新的作用域
|
||||||
|
self.push_scope();
|
||||||
|
|
||||||
|
// 添加参数到作用域
|
||||||
|
for param in &function.parameters {
|
||||||
|
self.add_variable(¶m.name, param.type_annotation.clone())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证函数体
|
||||||
|
self.validate_block(&function.body)?;
|
||||||
|
|
||||||
|
// 退出作用域
|
||||||
|
self.pop_scope();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn validate_field(&self, field: &FieldDeclaration) -> Result<(), SemanticError> {
|
fn validate_field(&self, field: &FieldDeclaration) -> Result<(), SemanticError> {
|
||||||
// 验证字段类型是否有效
|
// 验证字段类型是否有效
|
||||||
self.validate_type(&field.type_annotation)?;
|
self.validate_type(&field.type_annotation)?;
|
||||||
|
|
@ -453,6 +494,19 @@ impl SemanticAnalyzer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Expression::If(condition, then_expr, else_expr) => {
|
||||||
|
self.validate_expression(condition)?;
|
||||||
|
self.validate_expression(then_expr)?;
|
||||||
|
self.validate_expression(else_expr)?;
|
||||||
|
// if表达式的类型是then分支的类型
|
||||||
|
let then_type = self.infer_expression_type(then_expr)?;
|
||||||
|
Ok(then_type)
|
||||||
|
}
|
||||||
|
Expression::Cast(expr, target_type) => {
|
||||||
|
self.validate_expression(expr)?;
|
||||||
|
// 类型转换的结果类型就是目标类型
|
||||||
|
Ok(target_type.clone())
|
||||||
|
}
|
||||||
Expression::ArrayAccess(array, index) => {
|
Expression::ArrayAccess(array, index) => {
|
||||||
// 数组访问类型推断
|
// 数组访问类型推断
|
||||||
let array_type = self.infer_expression_type(array)?;
|
let array_type = self.infer_expression_type(array)?;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
[package]
|
||||||
|
name = "nac-ai-valuation"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
authors = ["NAC公链开发小组"]
|
||||||
|
description = "NAC公链AI估值系统 - 基于AI的RWA资产估值引擎"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
# 异步运行时
|
||||||
|
tokio = { version = "1.35", features = ["full"] }
|
||||||
|
async-trait = "0.1"
|
||||||
|
|
||||||
|
# 序列化
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
||||||
|
|
||||||
|
# 日期时间
|
||||||
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
|
||||||
|
# 数值计算
|
||||||
|
rust_decimal = { version = "1.33", features = ["serde-float"] }
|
||||||
|
rust_decimal_macros = "1.33"
|
||||||
|
|
||||||
|
# 错误处理
|
||||||
|
thiserror = "1.0"
|
||||||
|
anyhow = "1.0"
|
||||||
|
|
||||||
|
# HTTP客户端
|
||||||
|
reqwest = { version = "0.11", features = ["json"] }
|
||||||
|
|
||||||
|
# 日志
|
||||||
|
log = "0.4"
|
||||||
|
env_logger = "0.11"
|
||||||
|
|
||||||
|
# UUID
|
||||||
|
uuid = { version = "1.6", features = ["v4", "serde"] }
|
||||||
|
|
||||||
|
# 加密哈希
|
||||||
|
sha2 = "0.10"
|
||||||
|
hex = "0.4"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tokio-test = "0.4"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "nac_ai_valuation"
|
||||||
|
path = "src/lib.rs"
|
||||||
|
|
@ -0,0 +1,247 @@
|
||||||
|
// NAC公链AI估值系统 - 市场法估值引擎
|
||||||
|
// 作者:NAC公链开发小组
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use rust_decimal::Decimal;
|
||||||
|
use rust_decimal_macros::dec;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::engines::ValuationEngine;
|
||||||
|
use crate::types::{AssetType, ValuationError, ValuationInput, ValuationMethod};
|
||||||
|
|
||||||
|
/// 市场法估值引擎
|
||||||
|
/// 适用于:不动产、动产、数字资产
|
||||||
|
pub struct MarketEngine;
|
||||||
|
|
||||||
|
impl MarketEngine {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 不动产市场法估值
|
||||||
|
async fn valuate_real_estate(
|
||||||
|
&self,
|
||||||
|
input: &ValuationInput,
|
||||||
|
external_data: &HashMap<String, serde_json::Value>,
|
||||||
|
) -> Result<Decimal, ValuationError> {
|
||||||
|
// 获取可比交易数据
|
||||||
|
let comparable_sales = external_data
|
||||||
|
.get("comparable_sales")
|
||||||
|
.and_then(|v| v.as_array())
|
||||||
|
.ok_or_else(|| ValuationError::InsufficientData("缺少可比交易数据".to_string()))?;
|
||||||
|
|
||||||
|
if comparable_sales.is_empty() {
|
||||||
|
return Err(ValuationError::InsufficientData("没有可比交易".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算平均单价
|
||||||
|
let mut total_price_per_unit = Decimal::ZERO;
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
for sale in comparable_sales {
|
||||||
|
if let (Some(price), Some(area)) = (
|
||||||
|
sale.get("price").and_then(|v| v.as_f64()),
|
||||||
|
sale.get("area").and_then(|v| v.as_f64()),
|
||||||
|
) {
|
||||||
|
let price_dec = Decimal::from_f64_retain(price)
|
||||||
|
.ok_or_else(|| ValuationError::ModelError("价格转换失败".to_string()))?;
|
||||||
|
let area_dec = Decimal::from_f64_retain(area)
|
||||||
|
.ok_or_else(|| ValuationError::ModelError("面积转换失败".to_string()))?;
|
||||||
|
|
||||||
|
if area_dec > Decimal::ZERO {
|
||||||
|
total_price_per_unit += price_dec / area_dec;
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
return Err(ValuationError::InsufficientData("没有有效的可比交易".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let avg_price_per_unit = total_price_per_unit / Decimal::from(count);
|
||||||
|
|
||||||
|
// 获取标的资产面积
|
||||||
|
let subject_area = input
|
||||||
|
.asset_data
|
||||||
|
.get("area")
|
||||||
|
.and_then(|v| v.as_f64())
|
||||||
|
.ok_or_else(|| ValuationError::InsufficientData("缺少资产面积".to_string()))?;
|
||||||
|
|
||||||
|
let subject_area_dec = Decimal::from_f64_retain(subject_area)
|
||||||
|
.ok_or_else(|| ValuationError::ModelError("面积转换失败".to_string()))?;
|
||||||
|
|
||||||
|
// 获取调整系数(位置、品质等)
|
||||||
|
let location_factor = input
|
||||||
|
.asset_data
|
||||||
|
.get("location_factor")
|
||||||
|
.and_then(|v| v.as_f64())
|
||||||
|
.map(|v| Decimal::from_f64_retain(v).unwrap_or(dec!(1.0)))
|
||||||
|
.unwrap_or(dec!(1.0));
|
||||||
|
|
||||||
|
let quality_factor = input
|
||||||
|
.asset_data
|
||||||
|
.get("quality_factor")
|
||||||
|
.and_then(|v| v.as_f64())
|
||||||
|
.map(|v| Decimal::from_f64_retain(v).unwrap_or(dec!(1.0)))
|
||||||
|
.unwrap_or(dec!(1.0));
|
||||||
|
|
||||||
|
// 计算估值
|
||||||
|
let value = avg_price_per_unit * subject_area_dec * location_factor * quality_factor;
|
||||||
|
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 动产市场法估值(二手市场比价)
|
||||||
|
async fn valuate_movable(
|
||||||
|
&self,
|
||||||
|
input: &ValuationInput,
|
||||||
|
external_data: &HashMap<String, serde_json::Value>,
|
||||||
|
) -> Result<Decimal, ValuationError> {
|
||||||
|
// 获取二手市场价格数据
|
||||||
|
let market_prices = external_data
|
||||||
|
.get("market_prices")
|
||||||
|
.and_then(|v| v.as_array())
|
||||||
|
.ok_or_else(|| ValuationError::InsufficientData("缺少市场价格数据".to_string()))?;
|
||||||
|
|
||||||
|
if market_prices.is_empty() {
|
||||||
|
return Err(ValuationError::InsufficientData("没有市场价格数据".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算加权平均价格
|
||||||
|
let mut total_weighted_price = Decimal::ZERO;
|
||||||
|
let mut total_weight = Decimal::ZERO;
|
||||||
|
|
||||||
|
for price_data in market_prices {
|
||||||
|
if let (Some(price), Some(weight)) = (
|
||||||
|
price_data.get("price").and_then(|v| v.as_f64()),
|
||||||
|
price_data.get("weight").and_then(|v| v.as_f64()),
|
||||||
|
) {
|
||||||
|
let price_dec = Decimal::from_f64_retain(price)
|
||||||
|
.ok_or_else(|| ValuationError::ModelError("价格转换失败".to_string()))?;
|
||||||
|
let weight_dec = Decimal::from_f64_retain(weight)
|
||||||
|
.ok_or_else(|| ValuationError::ModelError("权重转换失败".to_string()))?;
|
||||||
|
|
||||||
|
total_weighted_price += price_dec * weight_dec;
|
||||||
|
total_weight += weight_dec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if total_weight == Decimal::ZERO {
|
||||||
|
return Err(ValuationError::InsufficientData("没有有效的价格数据".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let avg_price = total_weighted_price / total_weight;
|
||||||
|
|
||||||
|
// 获取折旧系数
|
||||||
|
let depreciation_factor = input
|
||||||
|
.asset_data
|
||||||
|
.get("depreciation_factor")
|
||||||
|
.and_then(|v| v.as_f64())
|
||||||
|
.map(|v| Decimal::from_f64_retain(v).unwrap_or(dec!(1.0)))
|
||||||
|
.unwrap_or(dec!(1.0));
|
||||||
|
|
||||||
|
// 计算估值
|
||||||
|
let value = avg_price * depreciation_factor;
|
||||||
|
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 数字资产市场法估值(交易所VWAP)
|
||||||
|
async fn valuate_digital(
|
||||||
|
&self,
|
||||||
|
input: &ValuationInput,
|
||||||
|
external_data: &HashMap<String, serde_json::Value>,
|
||||||
|
) -> Result<Decimal, ValuationError> {
|
||||||
|
// 获取交易所VWAP数据
|
||||||
|
let vwap_data = external_data
|
||||||
|
.get("vwap_data")
|
||||||
|
.and_then(|v| v.as_array())
|
||||||
|
.ok_or_else(|| ValuationError::InsufficientData("缺少VWAP数据".to_string()))?;
|
||||||
|
|
||||||
|
if vwap_data.is_empty() {
|
||||||
|
return Err(ValuationError::InsufficientData("没有VWAP数据".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算多个交易所的加权平均价格
|
||||||
|
let mut total_volume_weighted_price = Decimal::ZERO;
|
||||||
|
let mut total_volume = Decimal::ZERO;
|
||||||
|
|
||||||
|
for exchange_data in vwap_data {
|
||||||
|
if let (Some(vwap), Some(volume)) = (
|
||||||
|
exchange_data.get("vwap").and_then(|v| v.as_f64()),
|
||||||
|
exchange_data.get("volume").and_then(|v| v.as_f64()),
|
||||||
|
) {
|
||||||
|
let vwap_dec = Decimal::from_f64_retain(vwap)
|
||||||
|
.ok_or_else(|| ValuationError::ModelError("VWAP转换失败".to_string()))?;
|
||||||
|
let volume_dec = Decimal::from_f64_retain(volume)
|
||||||
|
.ok_or_else(|| ValuationError::ModelError("成交量转换失败".to_string()))?;
|
||||||
|
|
||||||
|
total_volume_weighted_price += vwap_dec * volume_dec;
|
||||||
|
total_volume += volume_dec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if total_volume == Decimal::ZERO {
|
||||||
|
return Err(ValuationError::InsufficientData("没有有效的VWAP数据".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let avg_vwap = total_volume_weighted_price / total_volume;
|
||||||
|
|
||||||
|
// 获取资产数量
|
||||||
|
let quantity = input
|
||||||
|
.asset_data
|
||||||
|
.get("quantity")
|
||||||
|
.and_then(|v| v.as_f64())
|
||||||
|
.ok_or_else(|| ValuationError::InsufficientData("缺少资产数量".to_string()))?;
|
||||||
|
|
||||||
|
let quantity_dec = Decimal::from_f64_retain(quantity)
|
||||||
|
.ok_or_else(|| ValuationError::ModelError("数量转换失败".to_string()))?;
|
||||||
|
|
||||||
|
// 计算估值
|
||||||
|
let value = avg_vwap * quantity_dec;
|
||||||
|
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl ValuationEngine for MarketEngine {
|
||||||
|
fn method(&self) -> ValuationMethod {
|
||||||
|
ValuationMethod::Market
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn valuate(
|
||||||
|
&self,
|
||||||
|
input: &ValuationInput,
|
||||||
|
external_data: &HashMap<String, serde_json::Value>,
|
||||||
|
) -> Result<Decimal, ValuationError> {
|
||||||
|
match input.asset_type {
|
||||||
|
AssetType::RealEstate => self.valuate_real_estate(input, external_data).await,
|
||||||
|
AssetType::Movable => self.valuate_movable(input, external_data).await,
|
||||||
|
AssetType::Digital => self.valuate_digital(input, external_data).await,
|
||||||
|
_ => Err(ValuationError::UnsupportedAssetType(input.asset_type.clone())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn supports(&self, input: &ValuationInput) -> bool {
|
||||||
|
matches!(
|
||||||
|
input.asset_type,
|
||||||
|
AssetType::RealEstate | AssetType::Movable | AssetType::Digital
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn required_data_fields(&self) -> Vec<String> {
|
||||||
|
vec![
|
||||||
|
"comparable_sales".to_string(),
|
||||||
|
"market_prices".to_string(),
|
||||||
|
"vwap_data".to_string(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for MarketEngine {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
// NAC公链AI估值系统 - 估值引擎
|
||||||
|
// 作者:NAC公链开发小组
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use rust_decimal::Decimal;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::types::{ValuationError, ValuationInput, ValuationMethod};
|
||||||
|
|
||||||
|
pub mod market;
|
||||||
|
pub mod income;
|
||||||
|
pub mod cost;
|
||||||
|
pub mod ai_comprehensive;
|
||||||
|
|
||||||
|
/// 估值引擎trait
|
||||||
|
#[async_trait]
|
||||||
|
pub trait ValuationEngine: Send + Sync {
|
||||||
|
/// 估值方法名称
|
||||||
|
fn method(&self) -> ValuationMethod;
|
||||||
|
|
||||||
|
/// 执行估值
|
||||||
|
async fn valuate(
|
||||||
|
&self,
|
||||||
|
input: &ValuationInput,
|
||||||
|
external_data: &HashMap<String, serde_json::Value>,
|
||||||
|
) -> Result<Decimal, ValuationError>;
|
||||||
|
|
||||||
|
/// 检查是否支持该资产类型
|
||||||
|
fn supports(&self, input: &ValuationInput) -> bool;
|
||||||
|
|
||||||
|
/// 获取所需的外部数据字段
|
||||||
|
fn required_data_fields(&self) -> Vec<String>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 估值引擎管理器
|
||||||
|
pub struct ValuationEngineManager {
|
||||||
|
engines: Vec<Box<dyn ValuationEngine>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ValuationEngineManager {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
engines: vec![
|
||||||
|
Box::new(market::MarketEngine::new()),
|
||||||
|
Box::new(income::IncomeEngine::new()),
|
||||||
|
Box::new(cost::CostEngine::new()),
|
||||||
|
Box::new(ai_comprehensive::AIComprehensiveEngine::new()),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 根据资产类型选择主估值引擎
|
||||||
|
pub fn select_primary_engine(&self, input: &ValuationInput) -> Option<&dyn ValuationEngine> {
|
||||||
|
self.engines
|
||||||
|
.iter()
|
||||||
|
.find(|e| e.supports(input))
|
||||||
|
.map(|e| e.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 选择辅助验证引擎
|
||||||
|
pub fn select_secondary_engines(&self, input: &ValuationInput) -> Vec<&dyn ValuationEngine> {
|
||||||
|
self.engines
|
||||||
|
.iter()
|
||||||
|
.filter(|e| e.supports(input))
|
||||||
|
.skip(1) // 跳过主引擎
|
||||||
|
.take(2) // 最多2个辅助引擎
|
||||||
|
.map(|e| e.as_ref())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ValuationEngineManager {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
pub fn add(left: usize, right: usize) -> usize {
|
||||||
|
left + right
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
let result = add(2, 2);
|
||||||
|
assert_eq!(result, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,187 @@
|
||||||
|
// NAC公链AI估值系统 - 核心类型定义
|
||||||
|
// 作者:NAC公链开发小组
|
||||||
|
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use rust_decimal::Decimal;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
/// GNACS编码(30位)
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||||||
|
pub struct GNACSCode(pub String);
|
||||||
|
|
||||||
|
impl GNACSCode {
|
||||||
|
pub fn new(code: String) -> Result<Self, String> {
|
||||||
|
if code.len() != 30 {
|
||||||
|
return Err(format!("GNACS编码必须是30位,当前长度:{}", code.len()));
|
||||||
|
}
|
||||||
|
Ok(Self(code))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取资产大类(第1-6位)
|
||||||
|
pub fn asset_category(&self) -> &str {
|
||||||
|
&self.0[0..6]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取风险权重(第7-8位)
|
||||||
|
pub fn risk_weight(&self) -> &str {
|
||||||
|
&self.0[6..8]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取时间属性(第22位)
|
||||||
|
pub fn time_attribute(&self) -> char {
|
||||||
|
self.0.chars().nth(21).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 资产类型
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
pub enum AssetType {
|
||||||
|
/// 不动产(土地、住宅、商业)
|
||||||
|
RealEstate,
|
||||||
|
/// 动产与设备
|
||||||
|
Movable,
|
||||||
|
/// 金融资产(债券、股权、应收账款)
|
||||||
|
Financial,
|
||||||
|
/// 数字资产(加密货币、代币、NFT)
|
||||||
|
Digital,
|
||||||
|
/// 艺术品
|
||||||
|
Art,
|
||||||
|
/// ESG碳信用
|
||||||
|
ESGCarbon,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 估值方法
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
pub enum ValuationMethod {
|
||||||
|
/// 市场法(Market Approach)
|
||||||
|
Market,
|
||||||
|
/// 收益法(Income Approach)
|
||||||
|
Income,
|
||||||
|
/// 成本法(Cost Approach)
|
||||||
|
Cost,
|
||||||
|
/// AI综合法(AI Comprehensive)
|
||||||
|
AIComprehensive,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 估值输入数据
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct ValuationInput {
|
||||||
|
/// 资产唯一标识
|
||||||
|
pub asset_id: Uuid,
|
||||||
|
/// GNACS编码
|
||||||
|
pub gnacs_code: GNACSCode,
|
||||||
|
/// 资产类型
|
||||||
|
pub asset_type: AssetType,
|
||||||
|
/// 资产描述
|
||||||
|
pub description: String,
|
||||||
|
/// 所有权证明哈希
|
||||||
|
pub ownership_proof_hash: String,
|
||||||
|
/// 特定资产数据包
|
||||||
|
pub asset_data: HashMap<String, serde_json::Value>,
|
||||||
|
/// 估值触发原因
|
||||||
|
pub trigger_reason: String,
|
||||||
|
/// 请求时间
|
||||||
|
pub request_time: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 估值结果
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct ValuationResult {
|
||||||
|
/// 估值ID
|
||||||
|
pub valuation_id: Uuid,
|
||||||
|
/// 资产ID
|
||||||
|
pub asset_id: Uuid,
|
||||||
|
/// GNACS编码
|
||||||
|
pub gnacs_code: GNACSCode,
|
||||||
|
/// 估值(XTZH个数)
|
||||||
|
pub value_in_xtzh: Decimal,
|
||||||
|
/// 使用的估值方法
|
||||||
|
pub methods_used: Vec<ValuationMethod>,
|
||||||
|
/// 主模型结果
|
||||||
|
pub primary_result: Decimal,
|
||||||
|
/// 辅助验证模型结果
|
||||||
|
pub secondary_results: Vec<(ValuationMethod, Decimal)>,
|
||||||
|
/// 模型差异百分比
|
||||||
|
pub model_divergence_pct: Option<Decimal>,
|
||||||
|
/// AI仲裁说明(如果有)
|
||||||
|
pub ai_arbitration: Option<String>,
|
||||||
|
/// 估值报告IPFS CID
|
||||||
|
pub report_ipfs_cid: String,
|
||||||
|
/// 估值时间
|
||||||
|
pub valuation_time: DateTime<Utc>,
|
||||||
|
/// 有效期(天数)
|
||||||
|
pub validity_days: u32,
|
||||||
|
/// 置信度(0-100)
|
||||||
|
pub confidence_score: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// XTZH价格信息
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct XTZHPrice {
|
||||||
|
/// XTZH对USD价格
|
||||||
|
pub price_usd: Decimal,
|
||||||
|
/// 价格时间戳
|
||||||
|
pub timestamp: DateTime<Utc>,
|
||||||
|
/// 稳定性调节因子
|
||||||
|
pub stability_factor: Decimal,
|
||||||
|
/// 黄金储备覆盖率
|
||||||
|
pub gold_coverage_ratio: Decimal,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 质押率配置
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct LoanToValueRatio {
|
||||||
|
/// 风险权重
|
||||||
|
pub risk_weight: String,
|
||||||
|
/// 最大质押率(百分比)
|
||||||
|
pub max_ltv_pct: Decimal,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 铸造XTZH计算结果
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct MintingCalculation {
|
||||||
|
/// 资产估值(XTZH个数)
|
||||||
|
pub asset_value_xtzh: Decimal,
|
||||||
|
/// 质押率
|
||||||
|
pub ltv_ratio: Decimal,
|
||||||
|
/// 可铸造XTZH数量
|
||||||
|
pub mintable_xtzh: Decimal,
|
||||||
|
/// XTZH当前价格(USD)
|
||||||
|
pub xtzh_price_usd: Decimal,
|
||||||
|
/// 资产法币价值(USD)
|
||||||
|
pub asset_value_usd: Decimal,
|
||||||
|
/// 需要的黄金储备(USD)
|
||||||
|
pub required_gold_reserve_usd: Decimal,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 估值错误类型
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum ValuationError {
|
||||||
|
#[error("无效的GNACS编码: {0}")]
|
||||||
|
InvalidGNACSCode(String),
|
||||||
|
|
||||||
|
#[error("不支持的资产类型: {0:?}")]
|
||||||
|
UnsupportedAssetType(AssetType),
|
||||||
|
|
||||||
|
#[error("估值模型错误: {0}")]
|
||||||
|
ModelError(String),
|
||||||
|
|
||||||
|
#[error("数据不足: {0}")]
|
||||||
|
InsufficientData(String),
|
||||||
|
|
||||||
|
#[error("外部API错误: {0}")]
|
||||||
|
ExternalAPIError(String),
|
||||||
|
|
||||||
|
#[error("模型差异过大: {0}%")]
|
||||||
|
ModelDivergenceTooHigh(Decimal),
|
||||||
|
|
||||||
|
#[error("AI仲裁失败: {0}")]
|
||||||
|
AIArbitrationFailed(String),
|
||||||
|
|
||||||
|
#[error("内部错误: {0}")]
|
||||||
|
InternalError(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type ValuationResultType = Result<ValuationResult, ValuationError>;
|
||||||
Loading…
Reference in New Issue