236
Cargo.lock
generated
236
Cargo.lock
generated
@@ -128,9 +128,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "borsh"
|
name = "borsh"
|
||||||
version = "1.5.7"
|
version = "1.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce"
|
checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"borsh-derive",
|
"borsh-derive",
|
||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
@@ -138,15 +138,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "borsh-derive"
|
name = "borsh-derive"
|
||||||
version = "1.5.7"
|
version = "1.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fdd1d3c0c2f5833f22386f252fe8ed005c7f59fdcddeef025c01b4c3b9fd9ac3"
|
checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn 2.0.111",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -226,7 +226,7 @@ dependencies = [
|
|||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn 2.0.111",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -265,41 +265,6 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ext-trait"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d772df1c1a777963712fb68e014235e80863d6a91a85c4e06ba2d16243a310e5"
|
|
||||||
dependencies = [
|
|
||||||
"ext-trait-proc_macros",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ext-trait-proc_macros"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1ab7934152eaf26aa5aa9f7371408ad5af4c31357073c9e84c3b9d7f11ad639a"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "extension-traits"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a296e5a895621edf9fa8329c83aa1cb69a964643e36cf54d8d7a69b789089537"
|
|
||||||
dependencies = [
|
|
||||||
"ext-trait",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "extern-c"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "320bea982e85d42441eb25c49b41218e7eaa2657e8f90bc4eca7437376751e23"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "funty"
|
name = "funty"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
@@ -363,15 +328,6 @@ dependencies = [
|
|||||||
"rustversion",
|
"rustversion",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "inventory"
|
|
||||||
version = "0.3.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e"
|
|
||||||
dependencies = [
|
|
||||||
"rustversion",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is_terminal_polyfill"
|
name = "is_terminal_polyfill"
|
||||||
version = "1.70.2"
|
version = "1.70.2"
|
||||||
@@ -400,22 +356,6 @@ version = "0.2.177"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "macro_rules_attribute"
|
|
||||||
version = "0.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cf0c9b980bf4f3a37fd7b1c066941dd1b1d0152ce6ee6e8fe8c49b9f6810d862"
|
|
||||||
dependencies = [
|
|
||||||
"macro_rules_attribute-proc_macro",
|
|
||||||
"paste",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "macro_rules_attribute-proc_macro"
|
|
||||||
version = "0.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "58093314a45e00c77d5c508f76e77c3396afbbc0d01506e7fae47b018bac2b1d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.6"
|
version = "2.7.6"
|
||||||
@@ -470,12 +410,6 @@ dependencies = [
|
|||||||
"tokenizer",
|
"tokenizer",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "paste"
|
|
||||||
version = "1.0.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.21"
|
version = "0.2.21"
|
||||||
@@ -495,16 +429,6 @@ dependencies = [
|
|||||||
"yansi",
|
"yansi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "prettyplease"
|
|
||||||
version = "0.1.25"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-crate"
|
name = "proc-macro-crate"
|
||||||
version = "3.4.0"
|
version = "3.4.0"
|
||||||
@@ -654,15 +578,6 @@ version = "0.1.26"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc_version"
|
|
||||||
version = "0.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
|
||||||
dependencies = [
|
|
||||||
"semver",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.22"
|
version = "1.0.22"
|
||||||
@@ -675,56 +590,12 @@ version = "1.0.20"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "safer-ffi"
|
|
||||||
version = "0.1.13"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "435fdd58b61a6f1d8545274c1dfa458e905ff68c166e65e294a0130ef5e675bd"
|
|
||||||
dependencies = [
|
|
||||||
"extern-c",
|
|
||||||
"inventory",
|
|
||||||
"libc",
|
|
||||||
"macro_rules_attribute",
|
|
||||||
"paste",
|
|
||||||
"safer_ffi-proc_macros",
|
|
||||||
"scopeguard",
|
|
||||||
"stabby",
|
|
||||||
"uninit",
|
|
||||||
"unwind_safe",
|
|
||||||
"with_builtin_macros",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "safer_ffi-proc_macros"
|
|
||||||
version = "0.1.13"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f0f25be5ba5f319542edb31925517e0380245ae37df50a9752cdbc05ef948156"
|
|
||||||
dependencies = [
|
|
||||||
"macro_rules_attribute",
|
|
||||||
"prettyplease",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "scopeguard"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "seahash"
|
name = "seahash"
|
||||||
version = "4.1.0"
|
version = "4.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||||
|
|
||||||
[[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"
|
||||||
@@ -751,7 +622,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn 2.0.111",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -767,53 +638,12 @@ dependencies = [
|
|||||||
"serde_core",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sha2-const-stable"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5f179d4e11094a893b82fff208f74d448a7512f99f5a0acbd5c679b705f83ed9"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "simdutf8"
|
name = "simdutf8"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stabby"
|
|
||||||
version = "36.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "89b7e94eaf470c2e76b5f15fb2fb49714471a36cc512df5ee231e62e82ec79f8"
|
|
||||||
dependencies = [
|
|
||||||
"rustversion",
|
|
||||||
"stabby-abi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stabby-abi"
|
|
||||||
version = "36.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0dc7a63b8276b54e51bfffe3d85da56e7906b2dcfcb29018a8ab666c06734c1a"
|
|
||||||
dependencies = [
|
|
||||||
"rustc_version",
|
|
||||||
"rustversion",
|
|
||||||
"sha2-const-stable",
|
|
||||||
"stabby-macros",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stabby-macros"
|
|
||||||
version = "36.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "eecb7ec5611ec93ec79d120fbe55f31bea234dc1bed1001d4a071bb688651615"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro-crate",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"rand",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stationlang"
|
name = "stationlang"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -824,7 +654,6 @@ dependencies = [
|
|||||||
"parser",
|
"parser",
|
||||||
"quick-error",
|
"quick-error",
|
||||||
"rust_decimal",
|
"rust_decimal",
|
||||||
"safer-ffi",
|
|
||||||
"tokenizer",
|
"tokenizer",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -847,9 +676,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.110"
|
version = "2.0.111"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea"
|
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -922,21 +751,6 @@ version = "1.0.22"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "uninit"
|
|
||||||
version = "0.5.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3e130f2ed46ca5d8ec13c7ff95836827f92f5f5f37fd2b2bf16f33c408d98bb6"
|
|
||||||
dependencies = [
|
|
||||||
"extension-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unwind_safe"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0976c77def3f1f75c4ef892a292c31c0bbe9e3d0702c63044d7c76db298171a3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@@ -997,7 +811,7 @@ dependencies = [
|
|||||||
"bumpalo",
|
"bumpalo",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn 2.0.111",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1034,26 +848,6 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "with_builtin_macros"
|
|
||||||
version = "0.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a59d55032495429b87f9d69954c6c8602e4d3f3e0a747a12dea6b0b23de685da"
|
|
||||||
dependencies = [
|
|
||||||
"with_builtin_macros-proc_macros",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "with_builtin_macros-proc_macros"
|
|
||||||
version = "0.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "15bd7679c15e22924f53aee34d4e448c45b674feb6129689af88593e129f8f42"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wyz"
|
name = "wyz"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@@ -1071,20 +865,20 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.8.28"
|
version = "0.8.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "43fa6694ed34d6e57407afbccdeecfa268c470a7d2a5b0cf49ce9fcc345afb90"
|
checksum = "4ea879c944afe8a2b25fef16bb4ba234f47c694565e97383b36f3a878219065c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy-derive",
|
"zerocopy-derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy-derive"
|
name = "zerocopy-derive"
|
||||||
version = "0.8.28"
|
version = "0.8.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c640b22cd9817fae95be82f0d2f90b11f7605f6c319d16705c459b27ac2cbc26"
|
checksum = "cf955aa904d6040f70dc8e9384444cb1030aed272ba3cb09bbc4ab9e7c1f34f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.110",
|
"syn 2.0.111",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ members = ["libs/*"]
|
|||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
quick-error = "2"
|
quick-error = "2"
|
||||||
rust_decimal = "1"
|
rust_decimal = "1"
|
||||||
safer-ffi = { version = "^0.1" }
|
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
strip = true
|
strip = true
|
||||||
@@ -30,10 +29,7 @@ rust_decimal = { workspace = true }
|
|||||||
tokenizer = { path = "libs/tokenizer" }
|
tokenizer = { path = "libs/tokenizer" }
|
||||||
parser = { path = "libs/parser" }
|
parser = { path = "libs/parser" }
|
||||||
compiler = { path = "libs/compiler" }
|
compiler = { path = "libs/compiler" }
|
||||||
safer-ffi = { workspace = true }
|
|
||||||
|
|
||||||
[features]
|
|
||||||
headers = ["safer-ffi/headers"]
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
anyhow = { version = "^1.0", features = ["backtrace"] }
|
anyhow = { version = "^1.0", features = ["backtrace"] }
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ fn test_while_loop() -> anyhow::Result<()> {
|
|||||||
fn test_loop_continue() -> anyhow::Result<()> {
|
fn test_loop_continue() -> anyhow::Result<()> {
|
||||||
let compiled = compile! {
|
let compiled = compile! {
|
||||||
debug
|
debug
|
||||||
"
|
r#"
|
||||||
let a = 0;
|
let a = 0;
|
||||||
loop {
|
loop {
|
||||||
a = a + 1;
|
a = a + 1;
|
||||||
@@ -120,7 +120,7 @@ fn test_loop_continue() -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
"
|
"#
|
||||||
};
|
};
|
||||||
|
|
||||||
// Labels: L1 (start), L2 (end), L3 (if end)
|
// Labels: L1 (start), L2 (end), L3 (if end)
|
||||||
|
|||||||
@@ -47,3 +47,4 @@ mod declaration_literal;
|
|||||||
mod function_declaration;
|
mod function_declaration;
|
||||||
mod logic_expression;
|
mod logic_expression;
|
||||||
mod loops;
|
mod loops;
|
||||||
|
mod syscall;
|
||||||
|
|||||||
159
libs/compiler/src/test/syscall.rs
Normal file
159
libs/compiler/src/test/syscall.rs
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
use crate::compile;
|
||||||
|
use indoc::indoc;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_yield() -> anyhow::Result<()> {
|
||||||
|
let compiled = compile! {
|
||||||
|
debug
|
||||||
|
"
|
||||||
|
yield();
|
||||||
|
"
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
compiled,
|
||||||
|
indoc! {
|
||||||
|
"
|
||||||
|
j main
|
||||||
|
main:
|
||||||
|
yield
|
||||||
|
"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sleep() -> anyhow::Result<()> {
|
||||||
|
let compiled = compile! {
|
||||||
|
debug
|
||||||
|
"
|
||||||
|
sleep(3);
|
||||||
|
let sleepAmount = 15;
|
||||||
|
sleep(sleepAmount);
|
||||||
|
sleep(sleepAmount * 2);
|
||||||
|
"
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
compiled,
|
||||||
|
indoc! {
|
||||||
|
"
|
||||||
|
j main
|
||||||
|
main:
|
||||||
|
sleep 3
|
||||||
|
move r8 15 #sleepAmount
|
||||||
|
sleep r8
|
||||||
|
mul r1 r8 2
|
||||||
|
sleep r1
|
||||||
|
"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_on_device() -> anyhow::Result<()> {
|
||||||
|
let compiled = compile! {
|
||||||
|
debug
|
||||||
|
r#"
|
||||||
|
device airConditioner = "d0";
|
||||||
|
let internalTemp = 20c;
|
||||||
|
|
||||||
|
setOnDevice(airConditioner, "On", internalTemp > 25c);
|
||||||
|
"#
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
compiled,
|
||||||
|
indoc! {
|
||||||
|
"
|
||||||
|
j main
|
||||||
|
main:
|
||||||
|
move r8 293.15 #internalTemp
|
||||||
|
sgt r1 r8 298.15
|
||||||
|
s d0 On r1
|
||||||
|
"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_on_device_batched() -> anyhow::Result<()> {
|
||||||
|
let compiled = compile! {
|
||||||
|
debug
|
||||||
|
r#"
|
||||||
|
let doorHash = hash("Door");
|
||||||
|
setOnDeviceBatched(doorHash, "Lock", true);
|
||||||
|
"#
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
compiled,
|
||||||
|
indoc! {
|
||||||
|
r#"
|
||||||
|
j main
|
||||||
|
main:
|
||||||
|
move r15 HASH("Door") #hash_ret
|
||||||
|
move r8 r15 #doorHash
|
||||||
|
sb r8 Lock 1
|
||||||
|
"#
|
||||||
|
}
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_load_from_device() -> anyhow::Result<()> {
|
||||||
|
let compiled = compile! {
|
||||||
|
debug
|
||||||
|
r#"
|
||||||
|
device airCon = "d0";
|
||||||
|
|
||||||
|
let setting = loadFromDevice(airCon, "On");
|
||||||
|
"#
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
compiled,
|
||||||
|
indoc! {
|
||||||
|
"
|
||||||
|
j main
|
||||||
|
main:
|
||||||
|
l r15 d0 On
|
||||||
|
move r8 r15 #setting
|
||||||
|
"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_hash() -> anyhow::Result<()> {
|
||||||
|
let compiled = compile! {
|
||||||
|
debug
|
||||||
|
r#"
|
||||||
|
let nameHash = hash("testValue");
|
||||||
|
"#
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
compiled,
|
||||||
|
indoc! {
|
||||||
|
r#"
|
||||||
|
j main
|
||||||
|
main:
|
||||||
|
move r15 HASH("testValue") #hash_ret
|
||||||
|
move r8 r15 #nameHash
|
||||||
|
"#
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
use crate::variable_manager::{self, LocationRequest, VariableLocation, VariableScope};
|
use crate::variable_manager::{self, LocationRequest, VariableLocation, VariableScope};
|
||||||
use parser::{
|
use parser::{
|
||||||
Parser as ASTParser,
|
Parser as ASTParser,
|
||||||
|
sys_call::{SysCall, System},
|
||||||
tree_node::{
|
tree_node::{
|
||||||
AssignmentExpression, BinaryExpression, BlockExpression, DeviceDeclarationExpression,
|
AssignmentExpression, BinaryExpression, BlockExpression, DeviceDeclarationExpression,
|
||||||
Expression, FunctionExpression, IfExpression, InvocationExpression, Literal,
|
Expression, FunctionExpression, IfExpression, InvocationExpression, Literal,
|
||||||
LogicalExpression, LoopExpression, WhileExpression,
|
LiteralOrVariable, LogicalExpression, LoopExpression, WhileExpression,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use quick_error::quick_error;
|
use quick_error::quick_error;
|
||||||
@@ -152,6 +153,9 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
self.expression_loop(expr_loop, scope)?;
|
self.expression_loop(expr_loop, scope)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
Expression::Syscall(SysCall::System(system_syscall)) => {
|
||||||
|
self.expression_syscall_system(system_syscall, scope)
|
||||||
|
}
|
||||||
Expression::While(expr_while) => {
|
Expression::While(expr_while) => {
|
||||||
self.expression_while(expr_while, scope)?;
|
self.expression_while(expr_while, scope)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@@ -169,11 +173,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
Expression::Declaration(var_name, expr) => {
|
Expression::Declaration(var_name, expr) => {
|
||||||
let loc = self.expression_declaration(var_name, *expr, scope)?;
|
self.expression_declaration(var_name, *expr, scope)
|
||||||
Ok(loc.map(|l| CompilationResult {
|
|
||||||
location: l,
|
|
||||||
temp_name: None,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
Expression::Assignment(assign_expr) => {
|
Expression::Assignment(assign_expr) => {
|
||||||
self.expression_assignment(assign_expr, scope)?;
|
self.expression_assignment(assign_expr, scope)?;
|
||||||
@@ -284,23 +284,26 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
var_name: String,
|
var_name: String,
|
||||||
expr: Expression,
|
expr: Expression,
|
||||||
scope: &mut VariableScope<'v>,
|
scope: &mut VariableScope<'v>,
|
||||||
) -> Result<Option<VariableLocation>, Error> {
|
) -> Result<Option<CompilationResult>, Error> {
|
||||||
// optimization. Check for a negated numeric literal
|
// optimization. Check for a negated numeric literal
|
||||||
if let Expression::Negation(box_expr) = &expr
|
if let Expression::Negation(box_expr) = &expr
|
||||||
&& let Expression::Literal(Literal::Number(neg_num)) = &**box_expr
|
&& let Expression::Literal(Literal::Number(neg_num)) = &**box_expr
|
||||||
{
|
{
|
||||||
let loc = scope.add_variable(&var_name, LocationRequest::Persist)?;
|
let loc = scope.add_variable(&var_name, LocationRequest::Persist)?;
|
||||||
self.emit_variable_assignment(&var_name, &loc, format!("-{neg_num}"))?;
|
self.emit_variable_assignment(&var_name, &loc, format!("-{neg_num}"))?;
|
||||||
return Ok(Some(loc));
|
return Ok(Some(CompilationResult {
|
||||||
|
location: loc,
|
||||||
|
temp_name: None,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let loc = match expr {
|
let (loc, temp_name) = match expr {
|
||||||
Expression::Literal(Literal::Number(num)) => {
|
Expression::Literal(Literal::Number(num)) => {
|
||||||
let var_location =
|
let var_location =
|
||||||
scope.add_variable(var_name.clone(), LocationRequest::Persist)?;
|
scope.add_variable(var_name.clone(), LocationRequest::Persist)?;
|
||||||
|
|
||||||
self.emit_variable_assignment(&var_name, &var_location, num)?;
|
self.emit_variable_assignment(&var_name, &var_location, num)?;
|
||||||
var_location
|
(var_location, None)
|
||||||
}
|
}
|
||||||
Expression::Literal(Literal::Boolean(b)) => {
|
Expression::Literal(Literal::Boolean(b)) => {
|
||||||
let val = if b { "1" } else { "0" };
|
let val = if b { "1" } else { "0" };
|
||||||
@@ -308,7 +311,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
scope.add_variable(var_name.clone(), LocationRequest::Persist)?;
|
scope.add_variable(var_name.clone(), LocationRequest::Persist)?;
|
||||||
|
|
||||||
self.emit_variable_assignment(&var_name, &var_location, val)?;
|
self.emit_variable_assignment(&var_name, &var_location, val)?;
|
||||||
var_location
|
(var_location, None)
|
||||||
}
|
}
|
||||||
Expression::Invocation(invoke_expr) => {
|
Expression::Invocation(invoke_expr) => {
|
||||||
self.expression_function_invocation(invoke_expr, scope)?;
|
self.expression_function_invocation(invoke_expr, scope)?;
|
||||||
@@ -319,7 +322,21 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
&loc,
|
&loc,
|
||||||
format!("r{}", VariableScope::RETURN_REGISTER),
|
format!("r{}", VariableScope::RETURN_REGISTER),
|
||||||
)?;
|
)?;
|
||||||
loc
|
(loc, None)
|
||||||
|
}
|
||||||
|
Expression::Syscall(SysCall::System(call)) => {
|
||||||
|
if self.expression_syscall_system(call, scope)?.is_none() {
|
||||||
|
return Err(Error::Unknown("SysCall did not return a value".into()));
|
||||||
|
};
|
||||||
|
|
||||||
|
let loc = scope.add_variable(&var_name, LocationRequest::Persist)?;
|
||||||
|
self.emit_variable_assignment(
|
||||||
|
&var_name,
|
||||||
|
&loc,
|
||||||
|
format!("r{}", VariableScope::RETURN_REGISTER),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
(loc, None)
|
||||||
}
|
}
|
||||||
// Support assigning binary expressions to variables directly
|
// Support assigning binary expressions to variables directly
|
||||||
Expression::Binary(bin_expr) => {
|
Expression::Binary(bin_expr) => {
|
||||||
@@ -334,7 +351,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
if let Some(name) = result.temp_name {
|
if let Some(name) = result.temp_name {
|
||||||
scope.free_temp(name)?;
|
scope.free_temp(name)?;
|
||||||
}
|
}
|
||||||
var_loc
|
(var_loc, None)
|
||||||
}
|
}
|
||||||
Expression::Logical(log_expr) => {
|
Expression::Logical(log_expr) => {
|
||||||
let result = self.expression_logical(log_expr, scope)?;
|
let result = self.expression_logical(log_expr, scope)?;
|
||||||
@@ -348,7 +365,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
if let Some(name) = result.temp_name {
|
if let Some(name) = result.temp_name {
|
||||||
scope.free_temp(name)?;
|
scope.free_temp(name)?;
|
||||||
}
|
}
|
||||||
var_loc
|
(var_loc, None)
|
||||||
}
|
}
|
||||||
Expression::Variable(name) => {
|
Expression::Variable(name) => {
|
||||||
let src_loc = scope.get_location_of(&name)?;
|
let src_loc = scope.get_location_of(&name)?;
|
||||||
@@ -372,7 +389,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.emit_variable_assignment(&var_name, &var_loc, src_str)?;
|
self.emit_variable_assignment(&var_name, &var_loc, src_str)?;
|
||||||
var_loc
|
(var_loc, None)
|
||||||
}
|
}
|
||||||
Expression::Priority(inner) => {
|
Expression::Priority(inner) => {
|
||||||
return self.expression_declaration(var_name, *inner, scope);
|
return self.expression_declaration(var_name, *inner, scope);
|
||||||
@@ -384,7 +401,10 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some(loc))
|
Ok(Some(CompilationResult {
|
||||||
|
location: loc,
|
||||||
|
temp_name,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expression_assignment<'v>(
|
fn expression_assignment<'v>(
|
||||||
@@ -740,6 +760,18 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compile_literal_or_variable(
|
||||||
|
&mut self,
|
||||||
|
val: LiteralOrVariable,
|
||||||
|
scope: &mut VariableScope,
|
||||||
|
) -> Result<(String, Option<String>), Error> {
|
||||||
|
let expr = match val {
|
||||||
|
LiteralOrVariable::Literal(l) => Expression::Literal(l),
|
||||||
|
LiteralOrVariable::Variable(v) => Expression::Variable(v),
|
||||||
|
};
|
||||||
|
self.compile_operand(expr, scope)
|
||||||
|
}
|
||||||
|
|
||||||
fn expression_binary<'v>(
|
fn expression_binary<'v>(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: BinaryExpression,
|
expr: BinaryExpression,
|
||||||
@@ -978,6 +1010,127 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
Ok(VariableLocation::Persistant(VariableScope::RETURN_REGISTER))
|
Ok(VariableLocation::Persistant(VariableScope::RETURN_REGISTER))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// syscalls that return values will be stored in the VariableScope::RETURN_REGISTER
|
||||||
|
// register
|
||||||
|
fn expression_syscall_system<'v>(
|
||||||
|
&mut self,
|
||||||
|
expr: System,
|
||||||
|
scope: &mut VariableScope<'v>,
|
||||||
|
) -> Result<Option<CompilationResult>, Error> {
|
||||||
|
match expr {
|
||||||
|
System::Yield => {
|
||||||
|
self.write_output("yield")?;
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
System::Sleep(amt) => {
|
||||||
|
let (var, cleanup) = self.compile_operand(*amt, scope)?;
|
||||||
|
self.write_output(format!("sleep {var}"))?;
|
||||||
|
if let Some(temp) = cleanup {
|
||||||
|
scope.free_temp(temp)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
System::Hash(hash_arg) => {
|
||||||
|
let Literal::String(str_lit) = hash_arg else {
|
||||||
|
return Err(Error::AgrumentMismatch(
|
||||||
|
"Arg1 expected to be a string literal.".into(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
let loc = VariableLocation::Persistant(VariableScope::RETURN_REGISTER);
|
||||||
|
self.emit_variable_assignment("hash_ret", &loc, format!(r#"HASH("{}")"#, str_lit))?;
|
||||||
|
|
||||||
|
Ok(Some(CompilationResult {
|
||||||
|
location: loc,
|
||||||
|
temp_name: None,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
System::SetOnDevice(device, logic_type, variable) => {
|
||||||
|
let (variable, var_cleanup) = self.compile_operand(*variable, scope)?;
|
||||||
|
|
||||||
|
let LiteralOrVariable::Variable(device) = device else {
|
||||||
|
return Err(Error::AgrumentMismatch(
|
||||||
|
"Arg1 expected to be a variable".into(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(device) = self.devices.get(&device) else {
|
||||||
|
return Err(Error::InvalidDevice(device));
|
||||||
|
};
|
||||||
|
|
||||||
|
let Literal::String(logic_type) = logic_type else {
|
||||||
|
return Err(Error::AgrumentMismatch(
|
||||||
|
"Arg2 expected to be a string".into(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
self.write_output(format!("s {} {} {}", device, logic_type, variable))?;
|
||||||
|
|
||||||
|
if let Some(temp_var) = var_cleanup {
|
||||||
|
scope.free_temp(temp_var)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
System::SetOnDeviceBatched(device_hash, logic_type, variable) => {
|
||||||
|
let (var, var_cleanup) = self.compile_operand(*variable, scope)?;
|
||||||
|
let (device_hash, device_hash_cleanup) =
|
||||||
|
self.compile_literal_or_variable(device_hash, scope)?;
|
||||||
|
let Literal::String(logic_type) = logic_type else {
|
||||||
|
return Err(Error::AgrumentMismatch(
|
||||||
|
"Arg2 expected to be a string".into(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
self.write_output(format!("sb {} {} {}", device_hash, logic_type, var))?;
|
||||||
|
|
||||||
|
if let Some(var_cleanup) = var_cleanup {
|
||||||
|
scope.free_temp(var_cleanup)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(device_cleanup) = device_hash_cleanup {
|
||||||
|
scope.free_temp(device_cleanup)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
System::LoadFromDevice(device, logic_type) => {
|
||||||
|
let LiteralOrVariable::Variable(device) = device else {
|
||||||
|
return Err(Error::AgrumentMismatch(
|
||||||
|
"Arg1 expected to be a variable".into(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(device) = self.devices.get(&device) else {
|
||||||
|
return Err(Error::InvalidDevice(device));
|
||||||
|
};
|
||||||
|
|
||||||
|
let Literal::String(logic_type) = logic_type else {
|
||||||
|
return Err(Error::AgrumentMismatch(
|
||||||
|
"Arg2 expected to be a string".into(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
self.write_output(format!(
|
||||||
|
"l r{} {} {}",
|
||||||
|
VariableScope::RETURN_REGISTER,
|
||||||
|
device,
|
||||||
|
logic_type
|
||||||
|
))?;
|
||||||
|
|
||||||
|
Ok(Some(CompilationResult {
|
||||||
|
location: VariableLocation::Temporary(VariableScope::RETURN_REGISTER),
|
||||||
|
temp_name: None,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Compile a function declaration.
|
/// Compile a function declaration.
|
||||||
/// Calees are responsible for backing up any registers they wish to use.
|
/// Calees are responsible for backing up any registers they wish to use.
|
||||||
fn expression_function<'v>(
|
fn expression_function<'v>(
|
||||||
@@ -1092,4 +1245,3 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
9
libs/compiler/test_files/deviceIo.slang
Normal file
9
libs/compiler/test_files/deviceIo.slang
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
device airConditioner = "d0";
|
||||||
|
device gasSensor = "d1";
|
||||||
|
|
||||||
|
loop {
|
||||||
|
yield();
|
||||||
|
let indoorTemp = loadFromDevice(gasSensor, "Temperature");
|
||||||
|
let shouldSet = indoorTemp > 30c;
|
||||||
|
setOnDevice(airConditioner, "On", shouldSet);
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fn addTemperatures(temp1, temp2) {
|
|
||||||
return temp1 + temp2;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
let newTemp1 = addTemperatures(15c, 120c);
|
|
||||||
let newTemp2 = addTemperatures(50c, 20c);
|
|
||||||
@@ -13,6 +13,8 @@ use tokenizer::{
|
|||||||
};
|
};
|
||||||
use tree_node::*;
|
use tree_node::*;
|
||||||
|
|
||||||
|
use crate::sys_call::System;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
/// A macro to create a boxed value.
|
/// A macro to create a boxed value.
|
||||||
macro_rules! boxed {
|
macro_rules! boxed {
|
||||||
@@ -63,6 +65,12 @@ macro_rules! token_from_option {
|
|||||||
None => return Err(Error::UnexpectedEOF),
|
None => return Err(Error::UnexpectedEOF),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
(owned $token:expr) => {
|
||||||
|
match $token {
|
||||||
|
Some(token) => token,
|
||||||
|
None => return Err(Error::UnexpectedEOF),
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! extract_token_data {
|
macro_rules! extract_token_data {
|
||||||
@@ -1039,9 +1047,22 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
"sleep" => {
|
"sleep" => {
|
||||||
check_length(self, &invocation.arguments, 1)?;
|
check_length(self, &invocation.arguments, 1)?;
|
||||||
let mut arg = invocation.arguments.iter();
|
let mut arg = invocation.arguments.into_iter();
|
||||||
let argument = literal_or_variable!(arg.next());
|
let expr = token_from_option!(owned arg.next());
|
||||||
Ok(SysCall::System(sys_call::System::Sleep(argument)))
|
Ok(SysCall::System(System::Sleep(boxed!(expr))))
|
||||||
|
}
|
||||||
|
"hash" => {
|
||||||
|
check_length(self, &invocation.arguments, 1)?;
|
||||||
|
let mut args = invocation.arguments.into_iter();
|
||||||
|
let lit_str = literal_or_variable!(args.next());
|
||||||
|
|
||||||
|
let LiteralOrVariable::Literal(lit_str) = lit_str else {
|
||||||
|
return Err(Error::UnexpectedToken(
|
||||||
|
token_from_option!(self.current_token).clone(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(SysCall::System(System::Hash(lit_str)))
|
||||||
}
|
}
|
||||||
"loadFromDevice" => {
|
"loadFromDevice" => {
|
||||||
check_length(self, &invocation.arguments, 2)?;
|
check_length(self, &invocation.arguments, 2)?;
|
||||||
@@ -1057,7 +1078,7 @@ impl Parser {
|
|||||||
|
|
||||||
Ok(SysCall::System(sys_call::System::LoadFromDevice(
|
Ok(SysCall::System(sys_call::System::LoadFromDevice(
|
||||||
device,
|
device,
|
||||||
LiteralOrVariable::Variable(variable.clone()),
|
Literal::String(variable.clone()),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
"loadBatch" => {
|
"loadBatch" => {
|
||||||
@@ -1076,23 +1097,23 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
"loadBatchNamed" => {
|
"loadBatchNamed" => {
|
||||||
check_length(self, &invocation.arguments, 4)?;
|
check_length(self, &invocation.arguments, 4)?;
|
||||||
let mut args = invocation.arguments.iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
|
|
||||||
let device_hash = literal_or_variable!(args.next());
|
let device_hash = literal_or_variable!(args.next());
|
||||||
let name_hash = get_arg!(Literal, literal_or_variable!(args.next()));
|
let name_hash = token_from_option!(owned args.next());
|
||||||
let logic_type = get_arg!(Literal, literal_or_variable!(args.next()));
|
let logic_type = get_arg!(Literal, literal_or_variable!(args.next()));
|
||||||
let batch_mode = get_arg!(Literal, literal_or_variable!(args.next()));
|
let batch_mode = get_arg!(Literal, literal_or_variable!(args.next()));
|
||||||
|
|
||||||
Ok(SysCall::System(sys_call::System::LoadBatchNamed(
|
Ok(SysCall::System(sys_call::System::LoadBatchNamed(
|
||||||
device_hash,
|
device_hash,
|
||||||
name_hash,
|
boxed!(name_hash),
|
||||||
logic_type,
|
logic_type,
|
||||||
batch_mode,
|
batch_mode,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
"setOnDevice" => {
|
"setOnDevice" => {
|
||||||
check_length(self, &invocation.arguments, 3)?;
|
check_length(self, &invocation.arguments, 3)?;
|
||||||
let mut args = invocation.arguments.iter();
|
let mut args = invocation.arguments.into_iter();
|
||||||
|
|
||||||
let device = literal_or_variable!(args.next());
|
let device = literal_or_variable!(args.next());
|
||||||
|
|
||||||
@@ -1104,12 +1125,54 @@ impl Parser {
|
|||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
let variable = literal_or_variable!(args.next());
|
let variable = token_from_option!(owned args.next());
|
||||||
|
|
||||||
Ok(SysCall::System(sys_call::System::SetOnDevice(
|
Ok(SysCall::System(sys_call::System::SetOnDevice(
|
||||||
device,
|
device,
|
||||||
Literal::String(logic_type),
|
Literal::String(logic_type),
|
||||||
variable,
|
boxed!(variable),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
"setOnDeviceBatched" => {
|
||||||
|
check_length(self, &invocation.arguments, 3)?;
|
||||||
|
let mut args = invocation.arguments.into_iter();
|
||||||
|
|
||||||
|
let device = literal_or_variable!(args.next());
|
||||||
|
let Literal::String(logic_type) =
|
||||||
|
get_arg!(Literal, literal_or_variable!(args.next()))
|
||||||
|
else {
|
||||||
|
return Err(Error::UnexpectedToken(
|
||||||
|
token_from_option!(self.current_token).clone(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
let variable = token_from_option!(owned args.next());
|
||||||
|
|
||||||
|
Ok(SysCall::System(System::SetOnDeviceBatched(
|
||||||
|
device,
|
||||||
|
Literal::String(logic_type),
|
||||||
|
boxed!(variable),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
"setOnDeviceBatchedNamed" => {
|
||||||
|
check_length(self, &invocation.arguments, 4)?;
|
||||||
|
let mut args = invocation.arguments.into_iter();
|
||||||
|
|
||||||
|
let device = literal_or_variable!(args.next());
|
||||||
|
let name = literal_or_variable!(args.next());
|
||||||
|
let Literal::String(logic_type) =
|
||||||
|
get_arg!(Literal, literal_or_variable!(args.next()))
|
||||||
|
else {
|
||||||
|
return Err(Error::UnexpectedToken(
|
||||||
|
token_from_option!(self.current_token).clone(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
let variable = token_from_option!(owned args.next());
|
||||||
|
|
||||||
|
Ok(SysCall::System(System::SetOnDeviceBatchedNamed(
|
||||||
|
device,
|
||||||
|
name,
|
||||||
|
Literal::String(logic_type),
|
||||||
|
boxed!(variable),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
// math calls
|
// math calls
|
||||||
@@ -1202,4 +1265,3 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::tree_node::Literal;
|
use crate::tree_node::{Expression, Literal};
|
||||||
|
|
||||||
use super::LiteralOrVariable;
|
use super::LiteralOrVariable;
|
||||||
|
|
||||||
@@ -102,25 +102,25 @@ pub enum System {
|
|||||||
/// Represents a function that can be called to sleep for a certain amount of time.
|
/// Represents a function that can be called to sleep for a certain amount of time.
|
||||||
/// ## In Game
|
/// ## In Game
|
||||||
/// `sleep a(r?|num)`
|
/// `sleep a(r?|num)`
|
||||||
Sleep(LiteralOrVariable),
|
Sleep(Box<Expression>),
|
||||||
/// Gets the in-game hash for a specific prefab name.
|
/// Gets the in-game hash for a specific prefab name.
|
||||||
/// ## In Game
|
/// ## In Game
|
||||||
/// `HASH("prefabName")`
|
/// `HASH("prefabName")`
|
||||||
Hash(LiteralOrVariable),
|
Hash(Literal),
|
||||||
/// Represents a function which loads a device variable into a register.
|
/// Represents a function which loads a device variable into a register.
|
||||||
/// ## In Game
|
/// ## In Game
|
||||||
/// `l r? d? var`
|
/// `l r? d? var`
|
||||||
/// ## Examples
|
/// ## Examples
|
||||||
/// `l r0 d0 Setting`
|
/// `l r0 d0 Setting`
|
||||||
/// `l r1 d5 Pressure`
|
/// `l r1 d5 Pressure`
|
||||||
LoadFromDevice(LiteralOrVariable, LiteralOrVariable),
|
LoadFromDevice(LiteralOrVariable, Literal),
|
||||||
/// Function which gets a LogicType from all connected network devices that match
|
/// Function which gets a LogicType from all connected network devices that match
|
||||||
/// the provided device hash and name, aggregating them via a batchMode
|
/// the provided device hash and name, aggregating them via a batchMode
|
||||||
/// ## In Game
|
/// ## In Game
|
||||||
/// lbn r? deviceHash nameHash logicType batchMode
|
/// lbn r? deviceHash nameHash logicType batchMode
|
||||||
/// ## Examples
|
/// ## Examples
|
||||||
/// lbn r0 HASH("StructureWallLight") HASH("wallLight") On Minimum
|
/// lbn r0 HASH("StructureWallLight") HASH("wallLight") On Minimum
|
||||||
LoadBatchNamed(LiteralOrVariable, Literal, Literal, Literal),
|
LoadBatchNamed(LiteralOrVariable, Box<Expression>, Literal, Literal),
|
||||||
/// Loads a LogicType from all connected network devices, aggregating them via a
|
/// Loads a LogicType from all connected network devices, aggregating them via a
|
||||||
/// batchMode
|
/// batchMode
|
||||||
/// ## In Game
|
/// ## In Game
|
||||||
@@ -133,7 +133,26 @@ pub enum System {
|
|||||||
/// `s d? logicType r?`
|
/// `s d? logicType r?`
|
||||||
/// ## Example
|
/// ## Example
|
||||||
/// `s d0 Setting r0`
|
/// `s d0 Setting r0`
|
||||||
SetOnDevice(LiteralOrVariable, Literal, LiteralOrVariable),
|
SetOnDevice(LiteralOrVariable, Literal, Box<Expression>),
|
||||||
|
/// Represents a function which stores a setting to all devices that match
|
||||||
|
/// the given deviceHash
|
||||||
|
/// ## In Game
|
||||||
|
/// `sb deviceHash logictype r?`
|
||||||
|
/// ## Example
|
||||||
|
/// `sb HASH("Doors") Lock 1`
|
||||||
|
SetOnDeviceBatched(LiteralOrVariable, Literal, Box<Expression>),
|
||||||
|
/// Represents a function which stores a setting to all devices that match
|
||||||
|
/// both the given deviceHash AND the given nameHash
|
||||||
|
/// ## In Game
|
||||||
|
/// `sbn deviceHash nameHash logicType r?`
|
||||||
|
/// ## Example
|
||||||
|
/// `sbn HASH("Doors") HASH("Exterior") Lock 1`
|
||||||
|
SetOnDeviceBatchedNamed(
|
||||||
|
LiteralOrVariable,
|
||||||
|
LiteralOrVariable,
|
||||||
|
Literal,
|
||||||
|
Box<Expression>,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for System {
|
impl std::fmt::Display for System {
|
||||||
@@ -141,13 +160,19 @@ impl std::fmt::Display for System {
|
|||||||
match self {
|
match self {
|
||||||
System::Yield => write!(f, "yield()"),
|
System::Yield => write!(f, "yield()"),
|
||||||
System::Sleep(a) => write!(f, "sleep({})", a),
|
System::Sleep(a) => write!(f, "sleep({})", a),
|
||||||
System::Hash(a) => write!(f, "HASH({})", a),
|
System::Hash(a) => write!(f, "hash({})", a),
|
||||||
System::LoadFromDevice(a, b) => write!(f, "loadFromDevice({}, {})", a, b),
|
System::LoadFromDevice(a, b) => write!(f, "loadFromDevice({}, {})", a, b),
|
||||||
System::LoadBatch(a, b, c) => write!(f, "loadBatch({}, {}, {})", a, b, c),
|
System::LoadBatch(a, b, c) => write!(f, "loadBatch({}, {}, {})", a, b, c),
|
||||||
System::LoadBatchNamed(a, b, c, d) => {
|
System::LoadBatchNamed(a, b, c, d) => {
|
||||||
write!(f, "loadBatchNamed({}, {}, {}, {})", a, b, c, d)
|
write!(f, "loadBatchNamed({}, {}, {}, {})", a, b, c, d)
|
||||||
}
|
}
|
||||||
System::SetOnDevice(a, b, c) => write!(f, "setOnDevice({}, {}, {})", a, b, c),
|
System::SetOnDevice(a, b, c) => write!(f, "setOnDevice({}, {}, {})", a, b, c),
|
||||||
|
System::SetOnDeviceBatched(a, b, c) => {
|
||||||
|
write!(f, "setOnDeviceBatched({}, {}, {})", a, b, c)
|
||||||
|
}
|
||||||
|
System::SetOnDeviceBatchedNamed(a, b, c, d) => {
|
||||||
|
write!(f, "setOnDeviceBatchedNamed({}, {}, {}, {})", a, b, c, d)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,9 +200,11 @@ impl SysCall {
|
|||||||
identifier,
|
identifier,
|
||||||
"yield"
|
"yield"
|
||||||
| "sleep"
|
| "sleep"
|
||||||
| "HASH"
|
| "hash"
|
||||||
| "loadFromDevice"
|
| "loadFromDevice"
|
||||||
| "setOnDevice"
|
| "setOnDevice"
|
||||||
|
| "setOnDeviceBatched"
|
||||||
|
| "setOnDeviceBatchedNamed"
|
||||||
| "acos"
|
| "acos"
|
||||||
| "asin"
|
| "asin"
|
||||||
| "atan"
|
| "atan"
|
||||||
|
|||||||
@@ -76,6 +76,12 @@ impl From<String> for Tokenizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&str> for Tokenizer {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
Self::from(value.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Tokenizer {
|
impl Tokenizer {
|
||||||
/// Consumes the tokenizer and returns the next token in the stream
|
/// Consumes the tokenizer and returns the next token in the stream
|
||||||
/// If there are no more tokens in the stream, this function returns None
|
/// If there are no more tokens in the stream, this function returns None
|
||||||
|
|||||||
58
src/lib.rs
58
src/lib.rs
@@ -1,34 +1,58 @@
|
|||||||
use compiler::Compiler;
|
use compiler::Compiler;
|
||||||
use parser::Parser;
|
use parser::Parser;
|
||||||
use safer_ffi::ffi_export;
|
use std::{
|
||||||
use std::io::BufWriter;
|
ffi::{CStr, CString},
|
||||||
|
io::BufWriter,
|
||||||
|
};
|
||||||
use tokenizer::Tokenizer;
|
use tokenizer::Tokenizer;
|
||||||
|
|
||||||
#[ffi_export]
|
/// Takes a raw pointer to a string and compiles the `slang` code into valid IC10
|
||||||
fn compile_from_string(
|
/// # Safety
|
||||||
input: &safer_ffi::string::String,
|
/// This must be called with a valid string pointer from C# (or wherever is calling this function)
|
||||||
output: &mut safer_ffi::string::String,
|
#[no_mangle]
|
||||||
) -> bool {
|
pub unsafe extern "C" fn compile_from_string(
|
||||||
let mut writer = BufWriter::new(Vec::new());
|
input_ptr: *const std::os::raw::c_char,
|
||||||
|
) -> *mut std::os::raw::c_char {
|
||||||
|
if input_ptr.is_null() {
|
||||||
|
return std::ptr::null_mut();
|
||||||
|
}
|
||||||
|
|
||||||
let tokenizer = Tokenizer::from(input.to_string());
|
let c_str = unsafe { CStr::from_ptr(input_ptr) };
|
||||||
|
|
||||||
|
let Ok(input_str) = c_str.to_str() else {
|
||||||
|
return std::ptr::null_mut();
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut writer = BufWriter::new(Vec::new());
|
||||||
|
let tokenizer = Tokenizer::from(input_str);
|
||||||
let parser = Parser::new(tokenizer);
|
let parser = Parser::new(tokenizer);
|
||||||
|
|
||||||
let compiler = Compiler::new(parser, &mut writer, None);
|
let compiler = Compiler::new(parser, &mut writer, None);
|
||||||
|
|
||||||
let Ok(()) = compiler.compile() else {
|
let Ok(()) = compiler.compile() else {
|
||||||
return false;
|
return std::ptr::null_mut();
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(buffer) = writer.into_inner() else {
|
let Ok(buffer) = writer.into_inner() else {
|
||||||
return false;
|
return std::ptr::null_mut();
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(output_string) = String::from_utf8(buffer) else {
|
let c_string = CString::from_vec_unchecked(buffer);
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
*output = output_string.into();
|
c_string.into_raw()
|
||||||
|
}
|
||||||
return true;
|
|
||||||
|
/// Takes ownership of the string pointer and drops it, freeing the memory
|
||||||
|
/// # Safety
|
||||||
|
/// Must be called with a valid string pointer
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn free_slang_string(input_ptr: *mut std::os::raw::c_char) {
|
||||||
|
if input_ptr.is_null() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
// Takes ownership of the input string, and then drops it immediately
|
||||||
|
let _ = CString::from_raw(input_ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user