refactor(vm) helpful codegen round 1~

This commit is contained in:
Rachel Powers
2024-05-07 21:59:06 -07:00
parent 2d8b35c5b2
commit 5cc935b826
49 changed files with 21966 additions and 3999 deletions

439
Cargo.lock generated
View File

@@ -156,9 +156,31 @@ dependencies = [
[[package]]
name = "base64"
version = "0.21.7"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bindgen"
version = "0.64.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4"
dependencies = [
"bitflags 1.3.2",
"cexpr",
"clang-sys",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn 1.0.109",
"which",
]
[[package]]
name = "bitflags"
@@ -166,6 +188,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "bumpalo"
version = "3.15.4"
@@ -204,6 +232,15 @@ version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -223,6 +260,17 @@ dependencies = [
"windows-targets 0.52.4",
]
[[package]]
name = "clang-sys"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "clap"
version = "4.5.4"
@@ -263,6 +311,33 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "color-eyre"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5"
dependencies = [
"backtrace",
"color-spantrace",
"eyre",
"indenter",
"once_cell",
"owo-colors",
"tracing-error",
]
[[package]]
name = "color-spantrace"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2"
dependencies = [
"once_cell",
"owo-colors",
"tracing-core",
"tracing-error",
]
[[package]]
name = "colorchoice"
version = "1.0.0"
@@ -370,6 +445,26 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "eyre"
version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec"
dependencies = [
"indenter",
"once_cell",
]
[[package]]
name = "fnv"
version = "1.0.7"
@@ -493,6 +588,12 @@ version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "hashbrown"
version = "0.12.3"
@@ -529,6 +630,15 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "home"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "httparse"
version = "1.8.0"
@@ -649,6 +759,12 @@ dependencies = [
"unicode-normalization",
]
[[package]]
name = "indenter"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
[[package]]
name = "indexmap"
version = "1.9.3"
@@ -695,12 +811,40 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libloading"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
dependencies = [
"cfg-if",
"windows-targets 0.52.4",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]]
name = "lock_api"
version = "0.4.11"
@@ -723,7 +867,7 @@ version = "0.94.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"serde",
"serde_json",
"serde_repr",
@@ -746,12 +890,27 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8dd856d451cc0da70e2ef2ce95a18e39a93b7558bedf10201ad28503f918568"
[[package]]
name = "matchers"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
"regex-automata 0.1.10",
]
[[package]]
name = "memchr"
version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.7.2"
@@ -772,6 +931,26 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]]
name = "num-conv"
version = "0.1.0"
@@ -821,6 +1000,39 @@ version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "onig"
version = "6.4.0"
source = "git+https://github.com/rust-onig/rust-onig#fa90c0e97e90a056af89f183b23cd417b59ee6a2"
dependencies = [
"bitflags 1.3.2",
"libc",
"once_cell",
"onig_sys",
]
[[package]]
name = "onig_sys"
version = "69.8.1"
source = "git+https://github.com/rust-onig/rust-onig#fa90c0e97e90a056af89f183b23cd417b59ee6a2"
dependencies = [
"bindgen",
"cc",
"pkg-config",
]
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "owo-colors"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
[[package]]
name = "parking_lot"
version = "0.12.1"
@@ -850,6 +1062,12 @@ version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "percent-encoding"
version = "2.3.1"
@@ -984,6 +1202,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]]
name = "powerfmt"
version = "0.2.0"
@@ -1056,7 +1280,7 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags",
"bitflags 1.3.2",
]
[[package]]
@@ -1067,8 +1291,17 @@ checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
"regex-automata 0.4.6",
"regex-syntax 0.8.3",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
"regex-syntax 0.6.29",
]
[[package]]
@@ -1079,9 +1312,15 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"regex-syntax 0.8.3",
]
[[package]]
name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.8.3"
@@ -1094,6 +1333,25 @@ version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [
"bitflags 2.5.0",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
]
[[package]]
name = "rustversion"
version = "1.0.14"
@@ -1114,9 +1372,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.197"
version = "1.0.200"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f"
dependencies = [
"serde_derive",
]
@@ -1145,9 +1403,9 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.197"
version = "1.0.200"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb"
dependencies = [
"proc-macro2",
"quote",
@@ -1166,16 +1424,35 @@ dependencies = [
]
[[package]]
name = "serde_json"
version = "1.0.115"
name = "serde_ignored"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
checksum = "a8e319a36d1b52126a0d608f24e93b2d81297091818cd70625fcf50a15d84ddf"
dependencies = [
"serde",
]
[[package]]
name = "serde_json"
version = "1.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_path_to_error"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6"
dependencies = [
"itoa",
"serde",
]
[[package]]
name = "serde_repr"
version = "0.1.18"
@@ -1189,9 +1466,9 @@ dependencies = [
[[package]]
name = "serde_with"
version = "3.7.0"
version = "3.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a"
checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20"
dependencies = [
"base64",
"chrono",
@@ -1207,9 +1484,9 @@ dependencies = [
[[package]]
name = "serde_with_macros"
version = "3.7.0"
version = "3.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655"
checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2"
dependencies = [
"darling",
"proc-macro2",
@@ -1217,6 +1494,21 @@ dependencies = [
"syn 2.0.57",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
@@ -1314,6 +1606,12 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "textwrap"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
[[package]]
name = "thiserror"
version = "1.0.58"
@@ -1334,6 +1632,16 @@ dependencies = [
"syn 2.0.57",
]
[[package]]
name = "thread_local"
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
dependencies = [
"cfg-if",
"once_cell",
]
[[package]]
name = "time"
version = "0.3.34"
@@ -1517,6 +1825,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-error"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e"
dependencies = [
"tracing",
"tracing-subscriber",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
dependencies = [
"matchers",
"nu-ansi-term",
"once_cell",
"regex",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
]
[[package]]
@@ -1629,6 +1977,12 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
@@ -1725,6 +2079,40 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "which"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
"either",
"home",
"once_cell",
"rustix",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
version = "0.52.0"
@@ -1871,5 +2259,20 @@ name = "xtask"
version = "0.2.3"
dependencies = [
"clap",
"color-eyre",
"convert_case",
"indexmap 2.2.6",
"onig",
"phf_codegen",
"regex",
"serde",
"serde_derive",
"serde_ignored",
"serde_json",
"serde_path_to_error",
"serde_with",
"textwrap",
"thiserror",
"tracing",
"tracing-subscriber",
]

View File

@@ -12,3 +12,7 @@ opt-level = "s"
lto = true
[profile.dev]
opt-level = 1
[patch.crates-io]
onig_sys = { git = "https://github.com/rust-onig/rust-onig", revision = "fa90c0e97e90a056af89f183b23cd417b59ee6a2" }

1
data/database.json Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,12 @@
{
"bapz": "Branch to line c if abs(a) <= max(b * abs(a), float.epsilon * 8)",
"bapzal": "Branch to line c if abs(a) <= max(b * abs(a), float.epsilon * 8) and store next line number in ra",
"bnaz": "Branch to line c if abs(a) > max (b * abs(a), float.epsilon * 8)",
"bnazal": "Branch to line c if abs(a) > max (b * abs(a), float.epsilon * 8) and store next line number in ra",
"brapz": "Relative branch to line c if abs(a) <= max(b * abs(a), float.epsilon * 8)",
"brnaz": "Relative branch to line c if abs(a) > max(b * abs(a), float.epsilon * 8)",
"sapz": "Register = 1 if abs(a) <= max(b * abs(a), float.epsilon * 8), otherwise 0",
"snaz": "Register = 1 if abs(a) > max(b * abs(a), float.epsilon), otherwise 0",
"log": "Register = base e log(a) or ln(a)",
"exp": "Register = exp(a) or e^a"
}

View File

@@ -14,7 +14,7 @@ const-crc32 = "1.3.0"
itertools = "0.12.1"
macro_rules_attribute = "0.2.0"
paste = "1.0.14"
phf = "0.11.2"
phf = { version = "0.11.2", features = ["macros"] }
rand = "0.8.5"
regex = "1.10.3"
serde = { version = "1.0.197", features = ["derive"] }

View File

@@ -1,421 +0,0 @@
use convert_case::{Case, Casing};
use std::{
collections::BTreeSet,
env,
fmt::Display,
fs::{self, File},
io::{BufWriter, Write},
path::Path,
str::FromStr,
};
struct EnumVariant<P>
where
P: Display + FromStr,
{
pub aliases: Vec<String>,
pub value: Option<P>,
pub deprecated: bool,
}
struct ReprEnumVariant<P>
where
P: Display + FromStr,
{
pub value: P,
pub deprecated: bool,
pub props: Vec<(String, String)>
}
fn write_repr_enum<'a, T: std::io::Write, I, P>(
writer: &mut BufWriter<T>,
name: &str,
variants: I,
use_phf: bool,
) where
P: Display + FromStr + 'a,
I: IntoIterator<Item = &'a (String, ReprEnumVariant<P>)>,
{
let additional_strum = if use_phf { "#[strum(use_phf)]\n" } else { "" };
let repr = std::any::type_name::<P>();
write!(
writer,
"#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, EnumString, AsRefStr, EnumProperty, EnumIter, FromRepr, Serialize, Deserialize)]\n\
{additional_strum}\
#[repr({repr})]\n\
pub enum {name} {{\n"
)
.unwrap();
for (name, variant) in variants {
let variant_name = name.replace('.', "").to_case(Case::Pascal);
let serialize = vec![name.clone()];
let serialize_str = serialize
.into_iter()
.map(|s| format!("serialize = \"{s}\""))
.collect::<Vec<String>>()
.join(", ");
let mut props = Vec::new();
if variant.deprecated {
props.push("deprecated = \"true\"".to_owned());
}
for (prop_name, prop_val) in &variant.props {
props.push(format!("{prop_name} = \"{prop_val}\""));
}
let val = &variant.value;
props.push(format!("value = \"{val}\""));
let props_str = if !props.is_empty() {
format!(", props( {} )", props.join(", "))
} else {
"".to_owned()
};
writeln!(
writer,
" #[strum({serialize_str}{props_str})] {variant_name} = {val}{repr},"
)
.unwrap();
}
writeln!(writer, "}}").unwrap();
}
fn write_enum<'a, T: std::io::Write, I, P>(
writer: &mut BufWriter<T>,
name: &str,
variants: I,
use_phf: bool,
) where
P: Display + FromStr + 'a,
I: IntoIterator<Item = &'a (String, EnumVariant<P>)>,
{
let additional_strum = if use_phf { "#[strum(use_phf)]\n" } else { "" };
write!(
writer,
"#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, EnumString, AsRefStr, EnumProperty, EnumIter, Serialize, Deserialize)]\n\
{additional_strum}\
pub enum {name} {{\n"
)
.unwrap();
for (name, variant) in variants {
let variant_name = name.replace('.', "").to_case(Case::Pascal);
let mut serialize = vec![name.clone()];
serialize.extend(variant.aliases.iter().cloned());
let serialize_str = serialize
.into_iter()
.map(|s| format!("serialize = \"{s}\""))
.collect::<Vec<String>>()
.join(", ");
let mut props = Vec::new();
if variant.deprecated {
props.push("deprecated = \"true\"".to_owned());
}
if let Some(val) = &variant.value {
props.push(format!("value = \"{val}\""));
}
let props_str = if !props.is_empty() {
format!(", props( {} )", props.join(", "))
} else {
"".to_owned()
};
writeln!(
writer,
" #[strum({serialize_str}{props_str})] {variant_name},"
)
.unwrap();
}
writeln!(writer, "}}").unwrap();
}
fn write_logictypes() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("logictypes.rs");
let output_file = File::create(dest_path).unwrap();
let mut writer = BufWriter::new(&output_file);
let mut logictypes: Vec<(String, ReprEnumVariant<u16>)> = Vec::new();
let l_infile = Path::new("data/logictypes.txt");
let l_contents = fs::read_to_string(l_infile).unwrap();
for line in l_contents.lines().filter(|l| !l.trim().is_empty()) {
let mut it = line.splitn(3, ' ');
let name = it.next().unwrap();
let val_str = it.next().unwrap();
let value: u16 = val_str.parse().unwrap_or_else(|err| panic!("'{val_str}' not valid u16: {err}"));
let docs = it.next();
let deprecated = docs
.map(|docs| docs.trim().to_uppercase() == "DEPRECATED")
.unwrap_or(false);
let mut props = Vec::new();
if let Some(docs) = docs {
props.push(("docs".to_owned(), docs.to_owned()));
}
logictypes.push((
name.to_string(),
ReprEnumVariant {
value,
deprecated,
props,
},
));
}
let mut slotlogictypes: Vec<(String, ReprEnumVariant<u8>)> = Vec::new();
let sl_infile = Path::new("data/slotlogictypes.txt");
let sl_contents = fs::read_to_string(sl_infile).unwrap();
for line in sl_contents.lines().filter(|l| !l.trim().is_empty()) {
let mut it = line.splitn(3, ' ');
let name = it.next().unwrap();
let val_str = it.next().unwrap();
let value: u8 = val_str.parse().unwrap_or_else(|err| panic!("'{val_str}' not valid u8: {err}"));
let docs = it.next();
let deprecated = docs
.map(|docs| docs.trim().to_uppercase() == "DEPRECATED")
.unwrap_or(false);
let mut props = Vec::new();
if let Some(docs) = docs {
props.push(("docs".to_owned(), docs.to_owned()));
}
slotlogictypes.push((
name.to_string(),
ReprEnumVariant {
value,
deprecated,
props,
},
));
}
write_repr_enum(&mut writer, "LogicType", &logictypes, true);
println!("cargo:rerun-if-changed=data/logictypes.txt");
write_repr_enum(&mut writer, "SlotLogicType", &slotlogictypes, true);
println!("cargo:rerun-if-changed=data/slotlogictypes.txt");
}
fn write_enums() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("enums.rs");
let output_file = File::create(dest_path).unwrap();
let mut writer = BufWriter::new(&output_file);
let mut enums_map: Vec<(String, EnumVariant<u32>)> = Vec::new();
let e_infile = Path::new("data/enums.txt");
let e_contents = fs::read_to_string(e_infile).unwrap();
for line in e_contents.lines().filter(|l| !l.trim().is_empty()) {
let mut it = line.splitn(3, ' ');
let name = it.next().unwrap();
let val_str = it.next().unwrap();
let val: Option<u32> = val_str.parse().ok();
let docs = it.next();
let deprecated = docs
.map(|docs| docs.trim().to_uppercase() == "DEPRECATED")
.unwrap_or(false);
enums_map.push((
name.to_string(),
EnumVariant {
aliases: Vec::new(),
value: val,
deprecated,
},
));
}
write_enum(&mut writer, "LogicEnums", &enums_map, true);
println!("cargo:rerun-if-changed=data/enums.txt");
}
fn write_modes() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("modes.rs");
let output_file = File::create(dest_path).unwrap();
let mut writer = BufWriter::new(&output_file);
let mut batchmodes: Vec<(String, ReprEnumVariant<u8>)> = Vec::new();
let b_infile = Path::new("data/batchmodes.txt");
let b_contents = fs::read_to_string(b_infile).unwrap();
for line in b_contents.lines().filter(|l| !l.trim().is_empty()) {
let mut it = line.splitn(3, ' ');
let name = it.next().unwrap();
let val_str = it.next().unwrap();
let value: u8 = val_str.parse().unwrap_or_else(|err| panic!("'{val_str}' not valid u8: {err}"));
batchmodes.push((
name.to_string(),
ReprEnumVariant {
value,
deprecated: false,
props: Vec::new(),
},
));
}
let mut reagentmodes: Vec<(String, ReprEnumVariant<u8>)> = Vec::new();
let r_infile = Path::new("data/reagentmodes.txt");
let r_contents = fs::read_to_string(r_infile).unwrap();
for line in r_contents.lines().filter(|l| !l.trim().is_empty()) {
let mut it = line.splitn(3, ' ');
let name = it.next().unwrap();
let val_str = it.next().unwrap();
let value: u8 = val_str.parse().unwrap_or_else(|err| panic!("'{val_str}' not valid u8: {err}"));
reagentmodes.push((
name.to_string(),
ReprEnumVariant {
value,
deprecated: false,
props: Vec::new(),
},
));
}
write_repr_enum(&mut writer, "BatchMode", &batchmodes, false);
println!("cargo:rerun-if-changed=data/batchmodes.txt");
write_repr_enum(&mut writer, "ReagentMode", &reagentmodes, false);
println!("cargo:rerun-if-changed=data/reagentmodes.txt");
}
fn write_constants() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("constants.rs");
let output_file = File::create(dest_path).unwrap();
let mut writer = BufWriter::new(&output_file);
let mut constants_lookup_map_builder = ::phf_codegen::Map::new();
let infile = Path::new("data/constants.txt");
let contents = fs::read_to_string(infile).unwrap();
for line in contents.lines().filter(|l| !l.trim().is_empty()) {
let mut it = line.splitn(3, ' ');
let name = it.next().unwrap();
let constant = it.next().unwrap();
constants_lookup_map_builder.entry(name, constant);
}
writeln!(
&mut writer,
"#[allow(clippy::approx_constant)] pub(crate) const CONSTANTS_LOOKUP: phf::Map<&'static str, f64> = {};",
constants_lookup_map_builder.build()
)
.unwrap();
println!("cargo:rerun-if-changed=data/constants.txt");
}
fn write_instructions_enum() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("instructions.rs");
let output_file = File::create(dest_path).unwrap();
let mut writer = BufWriter::new(&output_file);
let mut instructions = BTreeSet::new();
let infile = Path::new("data/instructions.txt");
let contents = fs::read_to_string(infile).unwrap();
for line in contents.lines() {
let mut it = line.split(' ');
let instruction = it.next().unwrap();
instructions.insert(instruction.to_string());
}
write!(
&mut writer,
"#[derive(Debug, Display, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]\n\
pub enum InstructionOp {{\n\
"
)
.unwrap();
writeln!(&mut writer, " Nop,").unwrap();
for typ in &instructions {
writeln!(&mut writer, " {},", typ.to_case(Case::Pascal)).unwrap();
}
writeln!(&mut writer, "}}").unwrap();
write!(
&mut writer,
"impl FromStr for InstructionOp {{\n \
type Err = ParseError;\n \
fn from_str(s: &str) -> Result<Self, Self::Err> {{\n \
let end = s.len();\n \
match s {{\n"
)
.unwrap();
for typ in &instructions {
let name = typ.to_case(Case::Pascal);
writeln!(&mut writer, " \"{typ}\" => Ok(Self::{name}),").unwrap();
}
write!(
&mut writer,
" _ => Err(crate::grammar::ParseError {{ line: 0, start: 0, end, msg: format!(\"Unknown instruction '{{}}'\", s) }})\n \
}}\n \
}}\n\
}}"
)
.unwrap();
println!("cargo:rerun-if-changed=data/instructions.txt");
}
fn write_stationpedia() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("stationpedia_prefabs.rs");
let output_file = File::create(dest_path).unwrap();
let mut writer = BufWriter::new(&output_file);
let mut prefabs: Vec<(String, ReprEnumVariant<i32>)> = Vec::new();
let l_infile = Path::new("data/stationpedia.txt");
let l_contents = fs::read_to_string(l_infile).unwrap();
for line in l_contents.lines().filter(|l| !l.trim().is_empty()) {
let mut it = line.splitn(3, ' ');
let val_str = it.next().unwrap();
let value: i32 = val_str.parse().unwrap_or_else(|err| panic!("'{val_str}' not valid i32: {err}"));
let name = it.next().unwrap();
let title = it.next();
let mut props = Vec::new();
if let Some(title) = title {
props.push(("title".to_owned(), title.to_owned()));
}
prefabs.push((
name.to_string(),
ReprEnumVariant {
value,
deprecated: false,
props,
},
));
}
write_repr_enum(&mut writer, "StationpediaPrefab", &prefabs, true);
println!("cargo:rerun-if-changed=data/stationpdeia.txt");
}
fn main() {
write_logictypes();
write_modes();
write_constants();
write_enums();
write_instructions_enum();
write_stationpedia();
}

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +0,0 @@
Average 0 Average of all read values
Maximum 3 Highest of all read values
Minimum 2 Lowest of all read values
Sum 1 All read values added together

View File

@@ -1,7 +0,0 @@
nan f64::NAN A constant representing 'not a number'. This constants technically provides a 'quiet' NaN, a signal NaN from some instructions will result in an exception and halt execution
pinf f64::INFINITY A constant representing a positive infinite value
ninf f64::NEG_INFINITY A constant representing a negative infinite value
pi 3.141592653589793f64 \nA constant representing the ratio of the circumference of a circle to its diameter, provided in double percision
deg2rad 0.0174532923847437f64 \nDegrees to radians conversion constant
rad2deg 57.2957801818848f64 \nRadians to degrees conversion constant
epsilon f64::EPSILON A constant representing the smallest value representable in double precision

View File

@@ -1,475 +0,0 @@
AirCon.Cold 0
AirCon.Hot 1
AirControl.Draught 4
AirControl.None 0
AirControl.Offline 1
AirControl.Pressure 2
Color.Black 7 Black
Color.Blue 0 Blue
Color.Brown 8 Brown
Color.Gray 1 Gray
Color.Green 2 Green
Color.Khaki 9 Khaki
Color.Orange 3 Orange
Color.Pink 10 Pink
Color.Purple 11 Purple
Color.Red 4 Red
Color.White 6 White
Color.Yellow 5 Yellow
DaylightSensorMode.Default 0
DaylightSensorMode.Horizontal 1
DaylightSensorMode.Vertical 2
ElevatorMode.Downward 2
ElevatorMode.Stationary 0
ElevatorMode.Upward 1
EntityState.Alive 0
EntityState.Dead 1
EntityState.Decay 3
EntityState.Unconscious 2
Equals 0
GasType.CarbonDioxide 4
GasType.Hydrogen 16384
GasType.LiquidCarbonDioxide 2048
GasType.LiquidHydrogen 32768
GasType.LiquidNitrogen 128
GasType.LiquidNitrousOxide 8192
GasType.LiquidOxygen 256
GasType.LiquidPollutant 4096
GasType.LiquidVolatiles 512
GasType.Nitrogen 2
GasType.NitrousOxide 64
GasType.Oxygen 1
GasType.Pollutant 16
GasType.PollutedWater 65536
GasType.Steam 1024
GasType.Undefined 0
GasType.Volatiles 8
GasType.Water 32
Greater 1
Less 2
LogicSlotType.Charge 10 returns current energy charge the slot occupant is holding
LogicSlotType.ChargeRatio 11 returns current energy charge the slot occupant is holding as a ratio between 0 and 1 of its maximum
LogicSlotType.Class 12 returns integer representing the class of object
LogicSlotType.Damage 4 returns the damage state of the item in the slot
LogicSlotType.Efficiency 5 returns the growth efficiency of the plant in the slot
LogicSlotType.FilterType 25
LogicSlotType.Growth 7 returns the current growth state of the plant in the slot
LogicSlotType.Health 6 returns the health of the plant in the slot
LogicSlotType.LineNumber 19
LogicSlotType.Lock 23
LogicSlotType.Mature 16 returns 1 if the plant in this slot is mature, 0 when it isn't
LogicSlotType.MaxQuantity 15 returns the max stack size of the item in the slot
LogicSlotType.None 0 No description
LogicSlotType.OccupantHash 2 returns the has of the current occupant, the unique identifier of the thing
LogicSlotType.Occupied 1 returns 0 when slot is not occupied, 1 when it is
LogicSlotType.On 22
LogicSlotType.Open 21
LogicSlotType.PrefabHash 17 returns the hash of the structure in the slot
LogicSlotType.Pressure 8 returns pressure of the slot occupants internal atmosphere
LogicSlotType.PressureAir 14 returns pressure in the air tank of the jetpack in this slot
LogicSlotType.PressureWaste 13 returns pressure in the waste tank of the jetpack in this slot
LogicSlotType.Quantity 3 returns the current quantity, such as stack size, of the item in the slot
LogicSlotType.ReferenceId 26
LogicSlotType.Seeding 18 Whether a plant is seeding (ready to harvest seeds from). Returns 1 if seeding or 0 if not.
LogicSlotType.SortingClass 24
LogicSlotType.Temperature 9 returns temperature of the slot occupants internal atmosphere
LogicSlotType.Volume 20
LogicType.Acceleration 216 Change in velocity. Rockets that are deccelerating when landing will show this as negative value.
LogicType.Activate 9 1 if device is activated (usually means running), otherwise 0
LogicType.AirRelease 75 The current state of the air release system, for example AirRelease = 1 for a Hardsuit sets Air Release to On
LogicType.AlignmentError 243
LogicType.Apex 238
LogicType.AutoLand 226 Engages the automatic landing algorithm. The rocket will automatically throttle and turn on and off its engines to achieve a smooth landing.
LogicType.AutoShutOff 218 Turns off all devices in the rocket upon reaching destination
LogicType.BestContactFilter 267
LogicType.Bpm 103 Bpm
LogicType.BurnTimeRemaining 225 Estimated time in seconds until fuel is depleted. Calculated based on current fuel usage.
LogicType.CelestialHash 242
LogicType.CelestialParentHash 250
LogicType.Channel0 165
LogicType.Channel1 166
LogicType.Channel2 167
LogicType.Channel3 168
LogicType.Channel4 169
LogicType.Channel5 170
LogicType.Channel6 171
LogicType.Channel7 172
LogicType.Charge 11 The current charge the device has
LogicType.Chart 256
LogicType.ChartedNavPoints 259
LogicType.ClearMemory 62 When set to 1, clears the counter memory (e.g. ExportCount). Will set itself back to 0 when actioned
LogicType.CollectableGoods 101
LogicType.Color 38 \n Whether driven by concerns for clarity, safety or simple aesthetics, {LINK:Stationeers;Stationeers} have access to a small rainbow of colors for their constructions. These are the color setting for devices, represented as an integer.\n\n0: Blue\n1: Grey\n2: Green\n3: Orange\n4: Red\n5: Yellow\n6: White\n7: Black\n8: Brown\n9: Khaki\n10: Pink\n11: Purple\n\n It is an unwavering universal law that anything higher than 11 will be purple. The {LINK:ODA;ODA} is powerless to change this. Similarly, anything lower than 0 will be Blue.\n
LogicType.Combustion 98 The assess atmosphere is on fire. Returns 1 if atmosphere is on fire, 0 if not.
LogicType.CombustionInput 146 The assess atmosphere is on fire. Returns 1 if device's input network is on fire, 0 if not.
LogicType.CombustionInput2 147 The assess atmosphere is on fire. Returns 1 if device's Input2 network is on fire, 0 if not.
LogicType.CombustionLimiter 153 Retards the rate of combustion inside the machine (range: 0-100), with 0 being the slowest rate of combustion and 100 being the fastest
LogicType.CombustionOutput 148 The assess atmosphere is on fire. Returns 1 if device's Output network is on fire, 0 if not.
LogicType.CombustionOutput2 149 The assess atmosphere is on fire. Returns 1 if device's Output2 network is on fire, 0 if not.
LogicType.CompletionRatio 61 How complete the current production is for this device, between 0 and 1
LogicType.ContactTypeId 198 The type id of the contact.
LogicType.CurrentCode 261
LogicType.CurrentResearchPodType 93
LogicType.Density 262
LogicType.DestinationCode 215 Unique identifier code for a destination on the space map.
LogicType.Discover 255
LogicType.DistanceAu 244
LogicType.DistanceKm 249
LogicType.DrillCondition 240
LogicType.DryMass 220 The Mass in kilograms of the rocket excluding fuel. The more massive the rocket the more fuel will be required to move to a new location in space.
LogicType.Eccentricity 247
LogicType.ElevatorLevel 40 Level the elevator is currently at
LogicType.ElevatorSpeed 39 Current speed of the elevator
LogicType.EntityState 239
LogicType.EnvironmentEfficiency 104 The Environment Efficiency reported by the machine, as a float between 0 and 1
LogicType.Error 4 1 if device is in error state, otherwise 0
LogicType.ExhaustVelocity 235
LogicType.ExportCount 63 How many items exported since last ClearMemory
LogicType.ExportQuantity 31 Total quantity of items exported by the device
LogicType.ExportSlotHash 42 DEPRECATED
LogicType.ExportSlotOccupant 32 DEPRECATED
LogicType.Filtration 74 The current state of the filtration system, for example Filtration = 1 for a Hardsuit sets filtration to On
LogicType.FlightControlRule 236
LogicType.Flush 174 Set to 1 to activate the flush function on the device
LogicType.ForceWrite 85 Forces Logic Writer devices to rewrite value
LogicType.ForwardX 227
LogicType.ForwardY 228
LogicType.ForwardZ 229
LogicType.Fuel 99
LogicType.Harvest 69 Performs the harvesting action for any plant based machinery
LogicType.Horizontal 20 Horizontal setting of the device
LogicType.HorizontalRatio 34 Radio of horizontal setting for device
LogicType.Idle 37 Returns 1 if the device is currently idle, otherwise 0
LogicType.ImportCount 64 How many items imported since last ClearMemory
LogicType.ImportQuantity 29 Total quantity of items imported by the device
LogicType.ImportSlotHash 43 DEPRECATED
LogicType.ImportSlotOccupant 30 DEPRECATED
LogicType.Inclination 246
LogicType.Index 241
LogicType.InterrogationProgress 157 Progress of this sattellite dish's interrogation of its current target, as a ratio from 0-1
LogicType.LineNumber 173 The line number of current execution for an integrated circuit running on this device. While this number can be written, use with caution
LogicType.Lock 10 1 if device is locked, otherwise 0, can be set in most devices and prevents the user from access the values
LogicType.ManualResearchRequiredPod 94
LogicType.Mass 219 The total Mass of the rocket in kilograms including fuel and cargo. The more massive the rocket the more fuel will be required to move to a new location in space.
LogicType.Maximum 23 Maximum setting of the device
LogicType.MineablesInQueue 96
LogicType.MineablesInVicinity 95
LogicType.MinedQuantity 266
LogicType.MinimumWattsToContact 163
LogicType.Mode 3 Integer for mode state, different devices will have different mode states available to them
LogicType.NavPoints 258
LogicType.NextWeatherEventTime 97
LogicType.None 0 No description
LogicType.On 28 The current state of the device, 0 for off, 1 for on
LogicType.Open 2 1 if device is open, otherwise 0
LogicType.OperationalTemperatureEfficiency 150 How the input pipe's temperature effects the machines efficiency
LogicType.OrbitPeriod 245
LogicType.Orientation 230
LogicType.Output 70 The output operation for a sort handling device, such as a stacker or sorter, when in logic mode the device will only action one repetition when set zero or above and then back to -1 and await further instructions
LogicType.PassedMoles 234
LogicType.Plant 68 Performs the planting action for any plant based machinery
LogicType.PlantEfficiency1 52 DEPRECATED
LogicType.PlantEfficiency2 53 DEPRECATED
LogicType.PlantEfficiency3 54 DEPRECATED
LogicType.PlantEfficiency4 55 DEPRECATED
LogicType.PlantGrowth1 48 DEPRECATED
LogicType.PlantGrowth2 49 DEPRECATED
LogicType.PlantGrowth3 50 DEPRECATED
LogicType.PlantGrowth4 51 DEPRECATED
LogicType.PlantHash1 56 DEPRECATED
LogicType.PlantHash2 57 DEPRECATED
LogicType.PlantHash3 58 DEPRECATED
LogicType.PlantHash4 59 DEPRECATED
LogicType.PlantHealth1 44 DEPRECATED
LogicType.PlantHealth2 45 DEPRECATED
LogicType.PlantHealth3 46 DEPRECATED
LogicType.PlantHealth4 47 DEPRECATED
LogicType.PositionX 76 The current position in X dimension in world coordinates
LogicType.PositionY 77 The current position in Y dimension in world coordinates
LogicType.PositionZ 78 The current position in Z dimension in world coordinates
LogicType.Power 1 Can be read to return if the device is correctly powered or not, set via the power system, return 1 if powered and 0 if not
LogicType.PowerActual 26 How much energy the device or network is actually using
LogicType.PowerGeneration 65 Returns how much power is being generated
LogicType.PowerPotential 25 How much energy the device or network potentially provides
LogicType.PowerRequired 36 Power requested from the device and/or network
LogicType.PrefabHash 84 The hash of the structure
LogicType.Pressure 5 The current pressure reading of the device
LogicType.PressureEfficiency 152 How the pressure of the input pipe and waste pipe effect the machines efficiency
LogicType.PressureExternal 7 Setting for external pressure safety, in KPa
LogicType.PressureInput 106 The current pressure reading of the device's Input Network
LogicType.PressureInput2 116 The current pressure reading of the device's Input2 Network
LogicType.PressureInternal 8 Setting for internal pressure safety, in KPa
LogicType.PressureOutput 126 The current pressure reading of the device's Output Network
LogicType.PressureOutput2 136 The current pressure reading of the device's Output2 Network
LogicType.PressureSetting 71 The current setting for the internal pressure of the object (e.g. the Hardsuit Air release), in KPa
LogicType.Progress 214 Progress of the rocket to the next node on the map expressed as a value between 0-1.
LogicType.Quantity 27 Total quantity on the device
LogicType.Ratio 24 Context specific value depending on device, 0 to 1 based ratio
LogicType.RatioCarbonDioxide 15 The ratio of {GAS:CarbonDioxide} in device atmosphere
LogicType.RatioCarbonDioxideInput 109 The ratio of {GAS:CarbonDioxide} in device's input network
LogicType.RatioCarbonDioxideInput2 119 The ratio of {GAS:CarbonDioxide} in device's Input2 network
LogicType.RatioCarbonDioxideOutput 129 The ratio of {GAS:CarbonDioxide} in device's Output network
LogicType.RatioCarbonDioxideOutput2 139 The ratio of {GAS:CarbonDioxide} in device's Output2 network
LogicType.RatioHydrogen 252 The ratio of {GAS:Hydrogen} in device's Atmopshere
LogicType.RatioLiquidCarbonDioxide 199 The ratio of {GAS:LiquidCarbonDioxide} in device's Atmosphere
LogicType.RatioLiquidCarbonDioxideInput 200 The ratio of {GAS:LiquidCarbonDioxide} in device's Input Atmosphere
LogicType.RatioLiquidCarbonDioxideInput2 201 The ratio of {GAS:LiquidCarbonDioxide} in device's Input2 Atmosphere
LogicType.RatioLiquidCarbonDioxideOutput 202 The ratio of {GAS:LiquidCarbonDioxide} in device's device's Output Atmosphere
LogicType.RatioLiquidCarbonDioxideOutput2 203 The ratio of {GAS:LiquidCarbonDioxide} in device's Output2 Atmopshere
LogicType.RatioLiquidHydrogen 253 The ratio of {GAS:LiquidHydrogen} in device's Atmopshere
LogicType.RatioLiquidNitrogen 177 The ratio of {GAS:LiquidNitrogen} in device atmosphere
LogicType.RatioLiquidNitrogenInput 178 The ratio of {GAS:LiquidNitrogen} in device's input network
LogicType.RatioLiquidNitrogenInput2 179 The ratio of {GAS:LiquidNitrogen} in device's Input2 network
LogicType.RatioLiquidNitrogenOutput 180 The ratio of {GAS:LiquidNitrogen} in device's Output network
LogicType.RatioLiquidNitrogenOutput2 181 The ratio of {GAS:LiquidNitrogen} in device's Output2 network
LogicType.RatioLiquidNitrousOxide 209 The ratio of {GAS:LiquidNitrousOxide} in device's Atmosphere
LogicType.RatioLiquidNitrousOxideInput 210 The ratio of {GAS:LiquidNitrousOxide} in device's Input Atmosphere
LogicType.RatioLiquidNitrousOxideInput2 211 The ratio of {GAS:LiquidNitrousOxide} in device's Input2 Atmosphere
LogicType.RatioLiquidNitrousOxideOutput 212 The ratio of {GAS:LiquidNitrousOxide} in device's device's Output Atmosphere
LogicType.RatioLiquidNitrousOxideOutput2 213 The ratio of {GAS:LiquidNitrousOxide} in device's Output2 Atmopshere
LogicType.RatioLiquidOxygen 183 The ratio of {GAS:LiquidOxygen} in device's Atmosphere
LogicType.RatioLiquidOxygenInput 184 The ratio of {GAS:LiquidOxygen} in device's Input Atmosphere
LogicType.RatioLiquidOxygenInput2 185 The ratio of {GAS:LiquidOxygen} in device's Input2 Atmosphere
LogicType.RatioLiquidOxygenOutput 186 The ratio of {GAS:LiquidOxygen} in device's device's Output Atmosphere
LogicType.RatioLiquidOxygenOutput2 187 The ratio of {GAS:LiquidOxygen} in device's Output2 Atmopshere
LogicType.RatioLiquidPollutant 204 The ratio of {GAS:LiquidPollutant} in device's Atmosphere
LogicType.RatioLiquidPollutantInput 205 The ratio of {GAS:LiquidPollutant} in device's Input Atmosphere
LogicType.RatioLiquidPollutantInput2 206 The ratio of {GAS:LiquidPollutant} in device's Input2 Atmosphere
LogicType.RatioLiquidPollutantOutput 207 The ratio of {GAS:LiquidPollutant} in device's device's Output Atmosphere
LogicType.RatioLiquidPollutantOutput2 208 The ratio of {GAS:LiquidPollutant} in device's Output2 Atmopshere
LogicType.RatioLiquidVolatiles 188 The ratio of {GAS:LiquidVolatiles} in device's Atmosphere
LogicType.RatioLiquidVolatilesInput 189 The ratio of {GAS:LiquidVolatiles} in device's Input Atmosphere
LogicType.RatioLiquidVolatilesInput2 190 The ratio of {GAS:LiquidVolatiles} in device's Input2 Atmosphere
LogicType.RatioLiquidVolatilesOutput 191 The ratio of {GAS:LiquidVolatiles} in device's device's Output Atmosphere
LogicType.RatioLiquidVolatilesOutput2 192 The ratio of {GAS:LiquidVolatiles} in device's Output2 Atmopshere
LogicType.RatioNitrogen 16 The ratio of nitrogen in device atmosphere
LogicType.RatioNitrogenInput 110 The ratio of nitrogen in device's input network
LogicType.RatioNitrogenInput2 120 The ratio of nitrogen in device's Input2 network
LogicType.RatioNitrogenOutput 130 The ratio of nitrogen in device's Output network
LogicType.RatioNitrogenOutput2 140 The ratio of nitrogen in device's Output2 network
LogicType.RatioNitrousOxide 83 The ratio of {GAS:NitrousOxide} in device atmosphere
LogicType.RatioNitrousOxideInput 114 The ratio of {GAS:NitrousOxide} in device's input network
LogicType.RatioNitrousOxideInput2 124 The ratio of {GAS:NitrousOxide} in device's Input2 network
LogicType.RatioNitrousOxideOutput 134 The ratio of {GAS:NitrousOxide} in device's Output network
LogicType.RatioNitrousOxideOutput2 144 The ratio of {GAS:NitrousOxide} in device's Output2 network
LogicType.RatioOxygen 14 The ratio of oxygen in device atmosphere
LogicType.RatioOxygenInput 108 The ratio of oxygen in device's input network
LogicType.RatioOxygenInput2 118 The ratio of oxygen in device's Input2 network
LogicType.RatioOxygenOutput 128 The ratio of oxygen in device's Output network
LogicType.RatioOxygenOutput2 138 The ratio of oxygen in device's Output2 network
LogicType.RatioPollutant 17 The ratio of pollutant in device atmosphere
LogicType.RatioPollutantInput 111 The ratio of pollutant in device's input network
LogicType.RatioPollutantInput2 121 The ratio of pollutant in device's Input2 network
LogicType.RatioPollutantOutput 131 The ratio of pollutant in device's Output network
LogicType.RatioPollutantOutput2 141 The ratio of pollutant in device's Output2 network
LogicType.RatioPollutedWater 254 The ratio of polluted water in device atmosphere
LogicType.RatioSteam 193 The ratio of {GAS:Steam} in device's Atmosphere
LogicType.RatioSteamInput 194 The ratio of {GAS:Steam} in device's Input Atmosphere
LogicType.RatioSteamInput2 195 The ratio of {GAS:Steam} in device's Input2 Atmosphere
LogicType.RatioSteamOutput 196 The ratio of {GAS:Steam} in device's device's Output Atmosphere
LogicType.RatioSteamOutput2 197 The ratio of {GAS:Steam} in device's Output2 Atmopshere
LogicType.RatioVolatiles 18 The ratio of volatiles in device atmosphere
LogicType.RatioVolatilesInput 112 The ratio of volatiles in device's input network
LogicType.RatioVolatilesInput2 122 The ratio of volatiles in device's Input2 network
LogicType.RatioVolatilesOutput 132 The ratio of volatiles in device's Output network
LogicType.RatioVolatilesOutput2 142 The ratio of volatiles in device's Output2 network
LogicType.RatioWater 19 The ratio of water in device atmosphere
LogicType.RatioWaterInput 113 The ratio of water in device's input network
LogicType.RatioWaterInput2 123 The ratio of water in device's Input2 network
LogicType.RatioWaterOutput 133 The ratio of water in device's Output network
LogicType.RatioWaterOutput2 143 The ratio of water in device's Output2 network
LogicType.ReEntryAltitude 237
LogicType.Reagents 13 Total number of reagents recorded by the device
LogicType.RecipeHash 41 Current hash of the recipe the device is set to produce
LogicType.ReferenceId 217
LogicType.RequestHash 60 When set to the unique identifier, requests an item of the provided type from the device
LogicType.RequiredPower 33 Idle operating power quantity, does not necessarily include extra demand power
LogicType.ReturnFuelCost 100
LogicType.Richness 263
LogicType.Rpm 155 The number of revolutions per minute that the device's spinning mechanism is doing
LogicType.SemiMajorAxis 248
LogicType.Setting 12 A variable setting that can be read or written, depending on the device
LogicType.SettingInput 91
LogicType.SettingOutput 92
LogicType.SignalID 87 Returns the contact ID of the strongest signal from this Satellite
LogicType.SignalStrength 86 Returns the degree offset of the strongest contact
LogicType.Sites 260
LogicType.Size 264
LogicType.SizeX 160 Size on the X (right) axis of the object in largeGrids (a largeGrid is 2meters)
LogicType.SizeY 161 Size on the Y(Up) axis of the object in largeGrids (a largeGrid is 2meters)
LogicType.SizeZ 162 Size on the Z(Forward) axis of the object in largeGrids (a largeGrid is 2meters)
LogicType.SolarAngle 22 Solar angle of the device
LogicType.SolarIrradiance 176
LogicType.SoundAlert 175 Plays a sound alert on the devices speaker
LogicType.Stress 156 Machines get stressed when working hard. When Stress reaches 100 the machine will automatically shut down
LogicType.Survey 257
LogicType.TargetPadIndex 158 The index of the trader landing pad on this devices data network that it will try to call a trader in to land
LogicType.TargetX 88 The target position in X dimension in world coordinates
LogicType.TargetY 89 The target position in Y dimension in world coordinates
LogicType.TargetZ 90 The target position in Z dimension in world coordinates
LogicType.Temperature 6 The current temperature reading of the device
LogicType.TemperatureDifferentialEfficiency 151 How the difference between the input pipe and waste pipe temperatures effect the machines efficiency
LogicType.TemperatureExternal 73 The temperature of the outside of the device, usually the world atmosphere surrounding it
LogicType.TemperatureInput 107 The current temperature reading of the device's Input Network
LogicType.TemperatureInput2 117 The current temperature reading of the device's Input2 Network
LogicType.TemperatureOutput 127 The current temperature reading of the device's Output Network
LogicType.TemperatureOutput2 137 The current temperature reading of the device's Output2 Network
LogicType.TemperatureSetting 72 The current setting for the internal temperature of the object (e.g. the Hardsuit A/C)
LogicType.Throttle 154 Increases the rate at which the machine works (range: 0-100)
LogicType.Thrust 221 Total current thrust of all rocket engines on the rocket in Newtons.
LogicType.ThrustToWeight 223 Ratio of thrust to weight of rocket. Weight is effected by local body gravity. A rocket with a low thrust to weight will expend more fuel during launch and landing.
LogicType.Time 102 Time
LogicType.TimeToDestination 224 Estimated time in seconds until rocket arrives at target destination.
LogicType.TotalMoles 66 Returns the total moles of the device
LogicType.TotalMolesInput 115 Returns the total moles of the device's Input Network
LogicType.TotalMolesInput2 125 Returns the total moles of the device's Input2 Network
LogicType.TotalMolesOutput 135 Returns the total moles of the device's Output Network
LogicType.TotalMolesOutput2 145 Returns the total moles of the device's Output2 Network
LogicType.TotalQuantity 265
LogicType.TrueAnomaly 251
LogicType.VelocityMagnitude 79 The current magnitude of the velocity vector
LogicType.VelocityRelativeX 80 The current velocity X relative to the forward vector of this
LogicType.VelocityRelativeY 81 The current velocity Y relative to the forward vector of this
LogicType.VelocityRelativeZ 82 The current velocity Z relative to the forward vector of this
LogicType.VelocityX 231
LogicType.VelocityY 232
LogicType.VelocityZ 233
LogicType.Vertical 21 Vertical setting of the device
LogicType.VerticalRatio 35 Radio of vertical setting for device
LogicType.Volume 67 Returns the device atmosphere volume
LogicType.VolumeOfLiquid 182 The total volume of all liquids in Liters in the atmosphere
LogicType.WattsReachingContact 164 The amount of watts actually hitting the contact. This is effected by the power of the dish and how far off-axis the dish is from the contact vector
LogicType.Weight 222 Weight of Rocket in Newtons (Including fuel and cargo). Weight is effected by local body gravity.
LogicType.WorkingGasEfficiency 105 The Working Gas Efficiency reported by the machine, as a float between 0 and 1
NotEquals 3
PowerMode.Charged 4
PowerMode.Charging 3
PowerMode.Discharged 1
PowerMode.Discharging 2
PowerMode.Idle 0
ReEntryProfile.High 3
ReEntryProfile.Max 4
ReEntryProfile.Medium 2
ReEntryProfile.None 0
ReEntryProfile.Optimal 1
RobotMode.Follow 1
RobotMode.MoveToTarget 2
RobotMode.None 0
RobotMode.PathToTarget 5
RobotMode.Roam 3
RobotMode.StorageFull 6
RobotMode.Unload 4
RocketMode.Chart 5
RocketMode.Discover 4
RocketMode.Invalid 0
RocketMode.Mine 2
RocketMode.None 1
RocketMode.Survey 3
SlotClass.AccessCard 22
SlotClass.Appliance 18
SlotClass.Back 3
SlotClass.Battery 14
SlotClass.Belt 16
SlotClass.Blocked 38
SlotClass.Bottle 25
SlotClass.Cartridge 21
SlotClass.Circuit 24
SlotClass.Circuitboard 7
SlotClass.CreditCard 28
SlotClass.DataDisk 8
SlotClass.DirtCanister 29
SlotClass.DrillHead 35
SlotClass.Egg 15
SlotClass.Entity 13
SlotClass.Flare 37
SlotClass.GasCanister 5
SlotClass.GasFilter 4
SlotClass.Glasses 27
SlotClass.Helmet 1
SlotClass.Ingot 19
SlotClass.LiquidBottle 32
SlotClass.LiquidCanister 31
SlotClass.Magazine 23
SlotClass.Motherboard 6
SlotClass.None 0
SlotClass.Ore 10
SlotClass.Organ 9
SlotClass.Plant 11
SlotClass.ProgrammableChip 26
SlotClass.ScanningHead 36
SlotClass.SensorProcessingUnit 30
SlotClass.SoundCartridge 34
SlotClass.Suit 2
SlotClass.SuitMod 39
SlotClass.Tool 17
SlotClass.Torpedo 20
SlotClass.Uniform 12
SlotClass.Wreckage 33
SorterInstruction.FilterPrefabHashEquals 1
SorterInstruction.FilterPrefabHashNotEquals 2
SorterInstruction.FilterQuantityCompare 5
SorterInstruction.FilterSlotTypeCompare 4
SorterInstruction.FilterSortingClassCompare 3
SorterInstruction.LimitNextExecutionByCount 6
SorterInstruction.None 0
SortingClass.Appliances 6
SortingClass.Atmospherics 7
SortingClass.Clothing 5
SortingClass.Default 0
SortingClass.Food 4
SortingClass.Ices 10
SortingClass.Kits 1
SortingClass.Ores 9
SortingClass.Resources 3
SortingClass.Storage 8
SortingClass.Tools 2
Sound.AirlockCycling 22
Sound.Alarm1 45
Sound.Alarm10 12
Sound.Alarm11 13
Sound.Alarm12 14
Sound.Alarm2 1
Sound.Alarm3 2
Sound.Alarm4 3
Sound.Alarm5 4
Sound.Alarm6 5
Sound.Alarm7 6
Sound.Alarm8 10
Sound.Alarm9 11
Sound.Alert 17
Sound.Danger 15
Sound.Depressurising 20
Sound.FireFireFire 28
Sound.Five 33
Sound.Floor 34
Sound.Four 32
Sound.HaltWhoGoesThere 27
Sound.HighCarbonDioxide 44
Sound.IntruderAlert 19
Sound.LiftOff 36
Sound.MalfunctionDetected 26
Sound.Music1 7
Sound.Music2 8
Sound.Music3 9
Sound.None 0
Sound.One 29
Sound.PollutantsDetected 43
Sound.PowerLow 23
Sound.PressureHigh 39
Sound.PressureLow 40
Sound.Pressurising 21
Sound.RocketLaunching 35
Sound.StormIncoming 18
Sound.SystemFailure 24
Sound.TemperatureHigh 41
Sound.TemperatureLow 42
Sound.Three 31
Sound.TraderIncoming 37
Sound.TraderLanded 38
Sound.Two 30
Sound.Warning 16
Sound.Welcome 25
TransmitterMode.Active 1
TransmitterMode.Passive 0
Vent.Inward 1
Vent.Outward 0

View File

@@ -1,14 +0,0 @@
{
"english": {
"bapz": "Branch to line c if abs(a) <= max(b * abs(a), float.epsilon * 8)",
"bapzal": "Branch to line c if abs(a) <= max(b * abs(a), float.epsilon * 8) and store next line number in ra",
"bnaz": "Branch to line c if abs(a) > max (b * abs(a), float.epsilon * 8)",
"bnazal": "Branch to line c if abs(a) > max (b * abs(a), float.epsilon * 8) and store next line number in ra",
"brapz": "Relative branch to line c if abs(a) <= max(b * abs(a), float.epsilon * 8)",
"brnaz": "Relative branch to line c if abs(a) > max(b * abs(a), float.epsilon * 8)",
"sapz": "Register = 1 if abs(a) <= max(b * abs(a), float.epsilon * 8), otherwise 0",
"snaz": "Register = 1 if abs(a) > max(b * abs(a), float.epsilon), otherwise 0",
"log": "Register = base e log(a) or ln(a)",
"exp": "Register = exp(a) or e^a"
}
}

View File

@@ -1,140 +0,0 @@
abs REGISTER VALUE
acos REGISTER VALUE
add REGISTER VALUE VALUE
alias NAME REGISTER_DEVICE
and REGISTER VALUE VALUE
asin REGISTER VALUE
atan REGISTER VALUE
atan2 REGISTER VALUE VALUE
bap VALUE VALUE VALUE VALUE
bapal VALUE VALUE VALUE VALUE
bapz VALUE VALUE VALUE
bapzal VALUE VALUE VALUE
bdns DEVICE VALUE
bdnsal DEVICE VALUE
bdse DEVICE VALUE
bdseal DEVICE VALUE
beq VALUE VALUE VALUE
beqal VALUE VALUE VALUE
beqz VALUE VALUE
beqzal VALUE VALUE
bge VALUE VALUE VALUE
bgeal VALUE VALUE VALUE
bgez VALUE VALUE
bgezal VALUE VALUE
bgt VALUE VALUE VALUE
bgtal VALUE VALUE VALUE
bgtz VALUE VALUE
bgtzal VALUE VALUE
ble VALUE VALUE VALUE
bleal VALUE VALUE VALUE
blez VALUE VALUE
blezal VALUE VALUE
blt VALUE VALUE VALUE
bltal VALUE VALUE VALUE
bltz VALUE VALUE
bltzal VALUE VALUE
bna VALUE VALUE VALUE VALUE
bnaal VALUE VALUE VALUE VALUE
bnan VALUE VALUE
bnaz VALUE VALUE VALUE
bnazal VALUE VALUE VALUE
bne VALUE VALUE VALUE
bneal VALUE VALUE VALUE
bnez VALUE VALUE
bnezal VALUE VALUE
brap VALUE VALUE VALUE VALUE
brapz VALUE VALUE VALUE
brdns DEVICE VALUE
brdse DEVICE VALUE
breq VALUE VALUE VALUE
breqz VALUE VALUE
brge VALUE VALUE VALUE
brgez VALUE VALUE
brgt VALUE VALUE VALUE
brgtz VALUE VALUE
brle VALUE VALUE VALUE
brlez VALUE VALUE
brlt VALUE VALUE VALUE
brltz VALUE VALUE
brna VALUE VALUE VALUE VALUE
brnan VALUE VALUE
brnaz VALUE VALUE VALUE
brne VALUE VALUE VALUE
brnez VALUE VALUE
ceil REGISTER VALUE
cos REGISTER VALUE
define NAME NUMBER
div REGISTER VALUE VALUE
exp REGISTER VALUE
floor REGISTER VALUE
get REGISTER DEVICE ADDRESS
getd REGISTER DEVICE_ID ADDRESS
hcf
j VALUE
jal VALUE
jr VALUE
l REGISTER DEVICE LOGIC_TYPE
lb REGISTER DEVICE_TYPE LOGIC_TYPE BATCH_MODE
lbn REGISTER DEVICE_TYPE DEVICE_NAME LOGIC_TYPE BATCH_MODE
lbns REGISTER DEVICE_TYPE DEVICE_NAME INDEX SLOT_LOGIC_TYPE BATCH_MODE
lbs REGISTER DEVICE_TYPE INDEX SLOT_LOGIC_TYPE BATCH_MODE
ld REGISTER DEVICE_ID LOGIC_TYPE
log REGISTER VALUE
lr REGISTER DEVICE REAGENT_MODE VALUE
ls REGISTER DEVICE VALUE SLOT_LOGIC_TYPE
max REGISTER VALUE VALUE
min REGISTER VALUE VALUE
mod REGISTER VALUE VALUE
move REGISTER VALUE
mul REGISTER VALUE VALUE
nor REGISTER VALUE VALUE
not REGISTER VALUE
or REGISTER VALUE VALUE
peek REGISTER
poke ADDRESS VALUE
pop REGISTER
push VALUE
put DEVICE ADDRESS VALUE
putd DEVICE_ID ADDRESS VALUE
rand REGISTER
round REGISTER VALUE
s DEVICE LOGIC_TYPE VALUE
sap REGISTER VALUE VALUE VALUE
sapz REGISTER VALUE VALUE
sb DEVICE_TYPE LOGIC_TYPE VALUE
sbn DEVICE_TYPE DEVICE_NAME LOGIC_TYPE VALUE
sbs DEVICE_TYPE INDEX SLOT_LOGIC_TYPE VALUE
sd DEVICE_ID LOGIC_TYPE VALUE
sdns REGISTER DEVICE
sdse REGISTER DEVICE
select REGISTER VALUE VALUE VALUE
seq REGISTER VALUE VALUE
seqz REGISTER VALUE
sge REGISTER VALUE VALUE
sgez REGISTER VALUE
sgt REGISTER VALUE VALUE
sgtz REGISTER VALUE
sin REGISTER VALUE
sla REGISTER VALUE VALUE
sle REGISTER VALUE VALUE
sleep VALUE
slez REGISTER VALUE
sll REGISTER VALUE VALUE
slt REGISTER VALUE VALUE
sltz REGISTER VALUE
sna REGISTER VALUE VALUE VALUE
snan REGISTER VALUE
snanz REGISTER VALUE
snaz REGISTER VALUE VALUE
sne REGISTER VALUE VALUE
snez REGISTER VALUE
sqrt REGISTER VALUE
sra REGISTER VALUE VALUE
srl REGISTER VALUE VALUE
ss DEVICE VALUE SLOT_LOGIC_TYPE REGISTER
sub REGISTER VALUE VALUE
tan REGISTER VALUE
trunc REGISTER VALUE
xor REGISTER VALUE VALUE
yield

View File

@@ -1,136 +0,0 @@
abs Register = the absolute value of a
acos Returns the angle (radians) whos cosine is the specified value
add Register = a + b.
alias Labels register or device reference with name, device references also affect what shows on the screws on the IC base.
and Performs a bitwise logical AND operation on the binary representation of two values. Each bit of the result is determined by evaluating the corresponding bits of the input values. If both bits are 1, the resulting bit is set to 1. Otherwise the resulting bit is set to 0.
asin Returns the angle (radians) whos sine is the specified value
atan Returns the angle (radians) whos tan is the specified value
atan2 Returns the angle (radians) whose tangent is the quotient of two specified values: a (y) and b (x)
bap Branch to line d if abs(a - b) <= max(c * max(abs(a), abs(b)), float.epsilon * 8)
bapal Branch to line d if abs(a - b) <= max(c * max(abs(a), abs(b)), float.epsilon * 8) and store next line number in ra
bapz Branch to line c if abs(a) <= max(b * abs(a), float.epsilon * 8)
bapzal Branch to line c if abs(a) <= max(b * abs(a), float.epsilon * 8) and store next line number in ra
bdns Branch to line a if device d isn't set
bdnsal Jump execution to line a and store next line number if device is not set
bdse Branch to line a if device d is set
bdseal Jump execution to line a and store next line number if device is set
beq Branch to line c if a == b
beqal Branch to line c if a == b and store next line number in ra
beqz Branch to line b if a == 0
beqzal Branch to line b if a == 0 and store next line number in ra
bge Branch to line c if a >= b
bgeal Branch to line c if a >= b and store next line number in ra
bgez Branch to line b if a >= 0
bgezal Branch to line b if a >= 0 and store next line number in ra
bgt Branch to line c if a > b
bgtal Branch to line c if a > b and store next line number in ra
bgtz Branch to line b if a > 0
bgtzal Branch to line b if a > 0 and store next line number in ra
ble Branch to line c if a <= b
bleal Branch to line c if a <= b and store next line number in ra
blez Branch to line b if a <= 0
blezal Branch to line b if a <= 0 and store next line number in ra
blt Branch to line c if a < b
bltal Branch to line c if a < b and store next line number in ra
bltz Branch to line b if a < 0
bltzal Branch to line b if a < 0 and store next line number in ra
bna Branch to line d if abs(a - b) > max(c * max(abs(a), abs(b)), float.epsilon * 8)
bnaal Branch to line d if abs(a - b) <= max(c * max(abs(a), abs(b)), float.epsilon * 8) and store next line number in ra
bnan Branch to line b if a is not a number (NaN)
bnaz Branch to line c if abs(a) > max (b * abs(a), float.epsilon * 8)
bnazal Branch to line c if abs(a) > max (b * abs(a), float.epsilon * 8) and store next line number in ra
bne Branch to line c if a != b
bneal Branch to line c if a != b and store next line number in ra
bnez branch to line b if a != 0
bnezal Branch to line b if a != 0 and store next line number in ra
brap Relative branch to line d if abs(a - b) <= max(c * max(abs(a), abs(b)), float.epsilon * 8)
brapz Relative branch to line c if abs(a) <= max(b * abs(a), float.epsilon * 8)
brdns Relative jump to line a if device is not set
brdse Relative jump to line a if device is set
breq Relative branch to line c if a == b
breqz Relative branch to line b if a == 0
brge Relative jump to line c if a >= b
brgez Relative branch to line b if a >= 0
brgt relative jump to line c if a > b
brgtz Relative branch to line b if a > 0
brle Relative jump to line c if a <= b
brlez Relative branch to line b if a <= 0
brlt Relative jump to line c if a < b
brltz Relative branch to line b if a < 0
brna Relative branch to line d if abs(a - b) > max(c * max(abs(a), abs(b)), float.epsilon * 8)
brnan Relative branch to line b if a is not a number (NaN)
brnaz Relative branch to line c if abs(a) > max(b * abs(a), float.epsilon * 8)
brne Relative branch to line c if a != b
brnez Relative branch to line b if a != 0
ceil Register = smallest integer greater than a
cos Returns the cosine of the specified angle (radians)
define Creates a label that will be replaced throughout the program with the provided value.
div Register = a / b
exp Register = exp(a) or e^a
floor Register = largest integer less than a
hcf Halt and catch fire
j Jump execution to line a
jal Jump execution to line a and store next line number in ra
jr Relative jump to line a
l Loads device LogicType to register by housing index value.
label DEPRECATED
lb Loads LogicType from all output network devices with provided type hash using the provide batch mode. Average (0), Sum (1), Minimum (2), Maximum (3). Can use either the word, or the number.
lbn Loads LogicType from all output network devices with provided type and name hashes using the provide batch mode. Average (0), Sum (1), Minimum (2), Maximum (3). Can use either the word, or the number.
lbns Loads LogicSlotType from slotIndex from all output network devices with provided type and name hashes using the provide batch mode. Average (0), Sum (1), Minimum (2), Maximum (3). Can use either the word, or the number.
lbs Loads LogicSlotType from slotIndex from all output network devices with provided type hash using the provide batch mode. Average (0), Sum (1), Minimum (2), Maximum (3). Can use either the word, or the number.
ld Loads device LogicType to register by direct ID reference.
log Register = base e log(a) or ln(a)
lr Loads reagent of device's ReagentMode where a hash of the reagent type to check for. ReagentMode can be either Contents (0), Required (1), Recipe (2). Can use either the word, or the number.
ls Loads slot LogicSlotType on device to register.
max Register = max of a or b
min Register = min of a or b
mod Register = a mod b (note: NOT a % b)
move Register = provided num or register value.
mul Register = a * b
nor Performs a bitwise logical NOR (NOT OR) operation on the binary representation of two values. Each bit of the result is determined by evaluating the corresponding bits of the input values. If both bits are 0, the resulting bit is set to 1. Otherwise, if at least one bit is 1, the resulting bit is set to 0.
not Performs a bitwise logical NOT operation flipping each bit of the input value, resulting in a binary complement. If a bit is 1, it becomes 0, and if a bit is 0, it becomes 1.
or Performs a bitwise logical OR operation on the binary representation of two values. Each bit of the result is determined by evaluating the corresponding bits of the input values. If either bit is 1, the resulting bit is set to 1. If both bits are 0, the resulting bit is set to 0.
peek Register = the value at the top of the stack
pop Register = the value at the top of the stack and decrements sp
push Pushes the value of a to the stack at sp and increments sp
rand Register = a random value x with 0 <= x < 1
round Register = a rounded to nearest integer
s Stores register value to LogicType on device by housing index value.
sap Register = 1 if abs(a - b) <= max(c * max(abs(a), abs(b)), float.epsilon * 8), otherwise 0
sapz Register = 1 if abs(a) <= max(b * abs(a), float.epsilon * 8), otherwise 0
sb Stores register value to LogicType on all output network devices with provided type hash.
sbn Stores register value to LogicType on all output network devices with provided type hash and name.
sbs Stores register value to LogicSlotType on all output network devices with provided type hash in the provided slot.
sd Stores register value to LogicType on device by direct ID reference.
sdns Register = 1 if device is not set, otherwise 0
sdse Register = 1 if device is set, otherwise 0.
select Register = b if a is non-zero, otherwise c
seq Register = 1 if a == b, otherwise 0
seqz Register = 1 if a == 0, otherwise 0
sge Register = 1 if a >= b, otherwise 0
sgez Register = 1 if a >= 0, otherwise 0
sgt Register = 1 if a > b, otherwise 0
sgtz Register = 1 if a > 0, otherwise 0
sin Returns the sine of the specified angle (radians)
sla Performs a bitwise arithmetic left shift operation on the binary representation of a value. It shifts the bits to the left and fills the vacated rightmost bits with a copy of the sign bit (the most significant bit).
sle Register = 1 if a <= b, otherwise 0
sleep Pauses execution on the IC for a seconds
slez Register = 1 if a <= 0, otherwise 0
sll Performs a bitwise logical left shift operation on the binary representation of a value. It shifts the bits to the left and fills the vacated rightmost bits with zeros.
slt Register = 1 if a < b, otherwise 0
sltz Register = 1 if a < 0, otherwise 0
sna Register = 1 if abs(a - b) > max(c * max(abs(a), abs(b)), float.epsilon * 8), otherwise 0
snan Register = 1 if a is NaN, otherwise 0
snanz Register = 0 if a is NaN, otherwise 1
snaz Register = 1 if abs(a) > max(b * abs(a), float.epsilon), otherwise 0
sne Register = 1 if a != b, otherwise 0
snez Register = 1 if a != 0, otherwise 0
sqrt Register = square root of a
sra Performs a bitwise arithmetic right shift operation on the binary representation of a value. It shifts the bits to the right and fills the vacated leftmost bits with a copy of the sign bit (the most significant bit).
srl Performs a bitwise logical right shift operation on the binary representation of a value. It shifts the bits to the right and fills the vacated leftmost bits with zeros
ss Stores register value to device stored in a slot LogicSlotType on device.
sub Register = a - b.
tan Returns the tan of the specified angle (radians)
trunc Register = a with fractional part removed
xor Performs a bitwise logical XOR (exclusive OR) operation on the binary representation of two values. Each bit of the result is determined by evaluating the corresponding bits of the input values. If the bits are different (one bit is 0 and the other is 1), the resulting bit is set to 1. If the bits are the same (both 0 or both 1), the resulting bit is set to 0.
yield Pauses execution for 1 tick

View File

@@ -1,267 +0,0 @@
Acceleration 216 Change in velocity. Rockets that are deccelerating when landing will show this as negative value.
Activate 9 1 if device is activated (usually means running), otherwise 0
AirRelease 75 The current state of the air release system, for example AirRelease = 1 for a Hardsuit sets Air Release to On
AlignmentError 243
Apex 238
AutoLand 226 Engages the automatic landing algorithm. The rocket will automatically throttle and turn on and off its engines to achieve a smooth landing.
AutoShutOff 218 Turns off all devices in the rocket upon reaching destination
BestContactFilter 267
Bpm 103 Bpm
BurnTimeRemaining 225 Estimated time in seconds until fuel is depleted. Calculated based on current fuel usage.
CelestialHash 242
CelestialParentHash 250
Channel0 165 Channel 0 on a cable network which should be considered volatile
Channel1 166 Channel 1 on a cable network which should be considered volatile
Channel2 167 Channel 2 on a cable network which should be considered volatile
Channel3 168 Channel 3 on a cable network which should be considered volatile
Channel4 169 Channel 4 on a cable network which should be considered volatile
Channel5 170 Channel 5 on a cable network which should be considered volatile
Channel6 171 Channel 6 on a cable network which should be considered volatile
Channel7 172 Channel 7 on a cable network which should be considered volatile
Charge 11 The current charge the device has
Chart 256
ChartedNavPoints 259
ClearMemory 62 When set to 1, clears the counter memory (e.g. ExportCount). Will set itself back to 0 when actioned
CollectableGoods 101
Color 38 \n Whether driven by concerns for clarity, safety or simple aesthetics, {LINK:Stationeers;Stationeers} have access to a small rainbow of colors for their constructions. These are the color setting for devices, represented as an integer.\n\n0: Blue\n1: Grey\n2: Green\n3: Orange\n4: Red\n5: Yellow\n6: White\n7: Black\n8: Brown\n9: Khaki\n10: Pink\n11: Purple\n\n It is an unwavering universal law that anything higher than 11 will be purple. The {LINK:ODA;ODA} is powerless to change this. Similarly, anything lower than 0 will be Blue.\n
Combustion 98 The assess atmosphere is on fire. Returns 1 if atmosphere is on fire, 0 if not.
CombustionInput 146 The assess atmosphere is on fire. Returns 1 if device's input network is on fire, 0 if not.
CombustionInput2 147 The assess atmosphere is on fire. Returns 1 if device's Input2 network is on fire, 0 if not.
CombustionLimiter 153 Retards the rate of combustion inside the machine (range: 0-100), with 0 being the slowest rate of combustion and 100 being the fastest
CombustionOutput 148 The assess atmosphere is on fire. Returns 1 if device's Output network is on fire, 0 if not.
CombustionOutput2 149 The assess atmosphere is on fire. Returns 1 if device's Output2 network is on fire, 0 if not.
CompletionRatio 61 How complete the current production is for this device, between 0 and 1
ContactTypeId 198 The type id of the contact.
CurrentCode 261
CurrentResearchPodType 93
Density 262
DestinationCode 215 Unique identifier code for a destination on the space map.
Discover 255
DistanceAu 244
DistanceKm 249
DrillCondition 240
DryMass 220 The Mass in kilograms of the rocket excluding fuel. The more massive the rocket the more fuel will be required to move to a new location in space.
Eccentricity 247
ElevatorLevel 40 Level the elevator is currently at
ElevatorSpeed 39 Current speed of the elevator
EntityState 239
EnvironmentEfficiency 104 The Environment Efficiency reported by the machine, as a float between 0 and 1
Error 4 1 if device is in error state, otherwise 0
ExhaustVelocity 235
ExportCount 63 How many items exported since last ClearMemory
ExportQuantity 31 Total quantity of items exported by the device
ExportSlotHash 42 DEPRECATED
ExportSlotOccupant 32 DEPRECATED
Filtration 74 The current state of the filtration system, for example Filtration = 1 for a Hardsuit sets filtration to On
FlightControlRule 236
Flush 174 Set to 1 to activate the flush function on the device
ForceWrite 85 Forces Logic Writer devices to rewrite value
ForwardX 227
ForwardY 228
ForwardZ 229
Fuel 99
Harvest 69 Performs the harvesting action for any plant based machinery
Horizontal 20 Horizontal setting of the device
HorizontalRatio 34 Radio of horizontal setting for device
Idle 37 Returns 1 if the device is currently idle, otherwise 0
ImportCount 64 How many items imported since last ClearMemory
ImportQuantity 29 Total quantity of items imported by the device
ImportSlotHash 43 DEPRECATED
ImportSlotOccupant 30 DEPRECATED
Inclination 246
Index 241
InterrogationProgress 157 Progress of this sattellite dish's interrogation of its current target, as a ratio from 0-1
LineNumber 173 The line number of current execution for an integrated circuit running on this device. While this number can be written, use with caution
Lock 10 1 if device is locked, otherwise 0, can be set in most devices and prevents the user from access the values
ManualResearchRequiredPod 94
Mass 219 The total Mass of the rocket in kilograms including fuel and cargo. The more massive the rocket the more fuel will be required to move to a new location in space.
Maximum 23 Maximum setting of the device
MineablesInQueue 96
MineablesInVicinity 95
MinedQuantity 266
MinimumWattsToContact 163 Minimum required amount of watts from the dish hitting the target trader contact to start interrogating the contact
Mode 3 Integer for mode state, different devices will have different mode states available to them
NavPoints 258
NextWeatherEventTime 97
None 0 No description
On 28 The current state of the device, 0 for off, 1 for on
Open 2 1 if device is open, otherwise 0
OperationalTemperatureEfficiency 150 How the input pipe's temperature effects the machines efficiency
OrbitPeriod 245
Orientation 230
Output 70 The output operation for a sort handling device, such as a stacker or sorter, when in logic mode the device will only action one repetition when set zero or above and then back to -1 and await further instructions
PassedMoles 234
Plant 68 Performs the planting action for any plant based machinery
PlantEfficiency1 52 DEPRECATED
PlantEfficiency2 53 DEPRECATED
PlantEfficiency3 54 DEPRECATED
PlantEfficiency4 55 DEPRECATED
PlantGrowth1 48 DEPRECATED
PlantGrowth2 49 DEPRECATED
PlantGrowth3 50 DEPRECATED
PlantGrowth4 51 DEPRECATED
PlantHash1 56 DEPRECATED
PlantHash2 57 DEPRECATED
PlantHash3 58 DEPRECATED
PlantHash4 59 DEPRECATED
PlantHealth1 44 DEPRECATED
PlantHealth2 45 DEPRECATED
PlantHealth3 46 DEPRECATED
PlantHealth4 47 DEPRECATED
PositionX 76 The current position in X dimension in world coordinates
PositionY 77 The current position in Y dimension in world coordinates
PositionZ 78 The current position in Z dimension in world coordinates
Power 1 Can be read to return if the device is correctly powered or not, set via the power system, return 1 if powered and 0 if not
PowerActual 26 How much energy the device or network is actually using
PowerGeneration 65 Returns how much power is being generated
PowerPotential 25 How much energy the device or network potentially provides
PowerRequired 36 Power requested from the device and/or network
PrefabHash 84 The hash of the structure
Pressure 5 The current pressure reading of the device
PressureEfficiency 152 How the pressure of the input pipe and waste pipe effect the machines efficiency
PressureExternal 7 Setting for external pressure safety, in KPa
PressureInput 106 The current pressure reading of the device's Input Network
PressureInput2 116 The current pressure reading of the device's Input2 Network
PressureInternal 8 Setting for internal pressure safety, in KPa
PressureOutput 126 The current pressure reading of the device's Output Network
PressureOutput2 136 The current pressure reading of the device's Output2 Network
PressureSetting 71 The current setting for the internal pressure of the object (e.g. the Hardsuit Air release), in KPa
Progress 214 Progress of the rocket to the next node on the map expressed as a value between 0-1.
Quantity 27 Total quantity on the device
Ratio 24 Context specific value depending on device, 0 to 1 based ratio
RatioCarbonDioxide 15 The ratio of {GAS:CarbonDioxide} in device atmosphere
RatioCarbonDioxideInput 109 The ratio of {GAS:CarbonDioxide} in device's input network
RatioCarbonDioxideInput2 119 The ratio of {GAS:CarbonDioxide} in device's Input2 network
RatioCarbonDioxideOutput 129 The ratio of {GAS:CarbonDioxide} in device's Output network
RatioCarbonDioxideOutput2 139 The ratio of {GAS:CarbonDioxide} in device's Output2 network
RatioHydrogen 252 The ratio of {GAS:Hydrogen} in device's Atmopshere
RatioLiquidCarbonDioxide 199 The ratio of {GAS:LiquidCarbonDioxide} in device's Atmosphere
RatioLiquidCarbonDioxideInput 200 The ratio of {GAS:LiquidCarbonDioxide} in device's Input Atmosphere
RatioLiquidCarbonDioxideInput2 201 The ratio of {GAS:LiquidCarbonDioxide} in device's Input2 Atmosphere
RatioLiquidCarbonDioxideOutput 202 The ratio of {GAS:LiquidCarbonDioxide} in device's device's Output Atmosphere
RatioLiquidCarbonDioxideOutput2 203 The ratio of {GAS:LiquidCarbonDioxide} in device's Output2 Atmopshere
RatioLiquidHydrogen 253 The ratio of {GAS:LiquidHydrogen} in device's Atmopshere
RatioLiquidNitrogen 177 The ratio of {GAS:LiquidNitrogen} in device atmosphere
RatioLiquidNitrogenInput 178 The ratio of {GAS:LiquidNitrogen} in device's input network
RatioLiquidNitrogenInput2 179 The ratio of {GAS:LiquidNitrogen} in device's Input2 network
RatioLiquidNitrogenOutput 180 The ratio of {GAS:LiquidNitrogen} in device's Output network
RatioLiquidNitrogenOutput2 181 The ratio of {GAS:LiquidNitrogen} in device's Output2 network
RatioLiquidNitrousOxide 209 The ratio of {GAS:LiquidNitrousOxide} in device's Atmosphere
RatioLiquidNitrousOxideInput 210 The ratio of {GAS:LiquidNitrousOxide} in device's Input Atmosphere
RatioLiquidNitrousOxideInput2 211 The ratio of {GAS:LiquidNitrousOxide} in device's Input2 Atmosphere
RatioLiquidNitrousOxideOutput 212 The ratio of {GAS:LiquidNitrousOxide} in device's device's Output Atmosphere
RatioLiquidNitrousOxideOutput2 213 The ratio of {GAS:LiquidNitrousOxide} in device's Output2 Atmopshere
RatioLiquidOxygen 183 The ratio of {GAS:LiquidOxygen} in device's Atmosphere
RatioLiquidOxygenInput 184 The ratio of {GAS:LiquidOxygen} in device's Input Atmosphere
RatioLiquidOxygenInput2 185 The ratio of {GAS:LiquidOxygen} in device's Input2 Atmosphere
RatioLiquidOxygenOutput 186 The ratio of {GAS:LiquidOxygen} in device's device's Output Atmosphere
RatioLiquidOxygenOutput2 187 The ratio of {GAS:LiquidOxygen} in device's Output2 Atmopshere
RatioLiquidPollutant 204 The ratio of {GAS:LiquidPollutant} in device's Atmosphere
RatioLiquidPollutantInput 205 The ratio of {GAS:LiquidPollutant} in device's Input Atmosphere
RatioLiquidPollutantInput2 206 The ratio of {GAS:LiquidPollutant} in device's Input2 Atmosphere
RatioLiquidPollutantOutput 207 The ratio of {GAS:LiquidPollutant} in device's device's Output Atmosphere
RatioLiquidPollutantOutput2 208 The ratio of {GAS:LiquidPollutant} in device's Output2 Atmopshere
RatioLiquidVolatiles 188 The ratio of {GAS:LiquidVolatiles} in device's Atmosphere
RatioLiquidVolatilesInput 189 The ratio of {GAS:LiquidVolatiles} in device's Input Atmosphere
RatioLiquidVolatilesInput2 190 The ratio of {GAS:LiquidVolatiles} in device's Input2 Atmosphere
RatioLiquidVolatilesOutput 191 The ratio of {GAS:LiquidVolatiles} in device's device's Output Atmosphere
RatioLiquidVolatilesOutput2 192 The ratio of {GAS:LiquidVolatiles} in device's Output2 Atmopshere
RatioNitrogen 16 The ratio of nitrogen in device atmosphere
RatioNitrogenInput 110 The ratio of nitrogen in device's input network
RatioNitrogenInput2 120 The ratio of nitrogen in device's Input2 network
RatioNitrogenOutput 130 The ratio of nitrogen in device's Output network
RatioNitrogenOutput2 140 The ratio of nitrogen in device's Output2 network
RatioNitrousOxide 83 The ratio of {GAS:NitrousOxide} in device atmosphere
RatioNitrousOxideInput 114 The ratio of {GAS:NitrousOxide} in device's input network
RatioNitrousOxideInput2 124 The ratio of {GAS:NitrousOxide} in device's Input2 network
RatioNitrousOxideOutput 134 The ratio of {GAS:NitrousOxide} in device's Output network
RatioNitrousOxideOutput2 144 The ratio of {GAS:NitrousOxide} in device's Output2 network
RatioOxygen 14 The ratio of oxygen in device atmosphere
RatioOxygenInput 108 The ratio of oxygen in device's input network
RatioOxygenInput2 118 The ratio of oxygen in device's Input2 network
RatioOxygenOutput 128 The ratio of oxygen in device's Output network
RatioOxygenOutput2 138 The ratio of oxygen in device's Output2 network
RatioPollutant 17 The ratio of pollutant in device atmosphere
RatioPollutantInput 111 The ratio of pollutant in device's input network
RatioPollutantInput2 121 The ratio of pollutant in device's Input2 network
RatioPollutantOutput 131 The ratio of pollutant in device's Output network
RatioPollutantOutput2 141 The ratio of pollutant in device's Output2 network
RatioPollutedWater 254 The ratio of polluted water in device atmosphere
RatioSteam 193 The ratio of {GAS:Steam} in device's Atmosphere
RatioSteamInput 194 The ratio of {GAS:Steam} in device's Input Atmosphere
RatioSteamInput2 195 The ratio of {GAS:Steam} in device's Input2 Atmosphere
RatioSteamOutput 196 The ratio of {GAS:Steam} in device's device's Output Atmosphere
RatioSteamOutput2 197 The ratio of {GAS:Steam} in device's Output2 Atmopshere
RatioVolatiles 18 The ratio of volatiles in device atmosphere
RatioVolatilesInput 112 The ratio of volatiles in device's input network
RatioVolatilesInput2 122 The ratio of volatiles in device's Input2 network
RatioVolatilesOutput 132 The ratio of volatiles in device's Output network
RatioVolatilesOutput2 142 The ratio of volatiles in device's Output2 network
RatioWater 19 The ratio of water in device atmosphere
RatioWaterInput 113 The ratio of water in device's input network
RatioWaterInput2 123 The ratio of water in device's Input2 network
RatioWaterOutput 133 The ratio of water in device's Output network
RatioWaterOutput2 143 The ratio of water in device's Output2 network
ReEntryAltitude 237
Reagents 13 Total number of reagents recorded by the device
RecipeHash 41 Current hash of the recipe the device is set to produce
ReferenceId 217
RequestHash 60 When set to the unique identifier, requests an item of the provided type from the device
RequiredPower 33 Idle operating power quantity, does not necessarily include extra demand power
ReturnFuelCost 100
Richness 263
Rpm 155 The number of revolutions per minute that the device's spinning mechanism is doing
SemiMajorAxis 248
Setting 12 A variable setting that can be read or written, depending on the device
SettingInput 91 The input setting for the device
SettingOutput 92 The output setting for the device
SignalID 87 Returns the contact ID of the strongest signal from this Satellite
SignalStrength 86 Returns the degree offset of the strongest contact
Sites 260
Size 264
SizeX 160 Size on the X (right) axis of the object in largeGrids (a largeGrid is 2meters)
SizeY 161 Size on the Y(Up) axis of the object in largeGrids (a largeGrid is 2meters)
SizeZ 162 Size on the Z(Forward) axis of the object in largeGrids (a largeGrid is 2meters)
SolarAngle 22 Solar angle of the device
SolarIrradiance 176
SoundAlert 175 Plays a sound alert on the devices speaker
Stress 156 Machines get stressed when working hard. When Stress reaches 100 the machine will automatically shut down
Survey 257
TargetPadIndex 158 The index of the trader landing pad on this devices data network that it will try to call a trader in to land
TargetX 88 The target position in X dimension in world coordinates
TargetY 89 The target position in Y dimension in world coordinates
TargetZ 90 The target position in Z dimension in world coordinates
Temperature 6 The current temperature reading of the device
TemperatureDifferentialEfficiency 151 How the difference between the input pipe and waste pipe temperatures effect the machines efficiency
TemperatureExternal 73 The temperature of the outside of the device, usually the world atmosphere surrounding it
TemperatureInput 107 The current temperature reading of the device's Input Network
TemperatureInput2 117 The current temperature reading of the device's Input2 Network
TemperatureOutput 127 The current temperature reading of the device's Output Network
TemperatureOutput2 137 The current temperature reading of the device's Output2 Network
TemperatureSetting 72 The current setting for the internal temperature of the object (e.g. the Hardsuit A/C)
Throttle 154 Increases the rate at which the machine works (range: 0-100)
Thrust 221 Total current thrust of all rocket engines on the rocket in Newtons.
ThrustToWeight 223 Ratio of thrust to weight of rocket. Weight is effected by local body gravity. A rocket with a low thrust to weight will expend more fuel during launch and landing.
Time 102 Time
TimeToDestination 224 Estimated time in seconds until rocket arrives at target destination.
TotalMoles 66 Returns the total moles of the device
TotalMolesInput 115 Returns the total moles of the device's Input Network
TotalMolesInput2 125 Returns the total moles of the device's Input2 Network
TotalMolesOutput 135 Returns the total moles of the device's Output Network
TotalMolesOutput2 145 Returns the total moles of the device's Output2 Network
TotalQuantity 265
TrueAnomaly 251
VelocityMagnitude 79 The current magnitude of the velocity vector
VelocityRelativeX 80 The current velocity X relative to the forward vector of this
VelocityRelativeY 81 The current velocity Y relative to the forward vector of this
VelocityRelativeZ 82 The current velocity Z relative to the forward vector of this
VelocityX 231
VelocityY 232
VelocityZ 233
Vertical 21 Vertical setting of the device
VerticalRatio 35 Radio of vertical setting for device
Volume 67 Returns the device atmosphere volume
VolumeOfLiquid 182 The total volume of all liquids in Liters in the atmosphere
WattsReachingContact 164 The amount of watts actually hitting the contact. This is effected by the power of the dish and how far off-axis the dish is from the contact vector
Weight 222 Weight of Rocket in Newtons (Including fuel and cargo). Weight is effected by local body gravity.
WorkingGasEfficiency 105 The Working Gas Efficiency reported by the machine, as a float between 0 and 1

View File

@@ -1,4 +0,0 @@
Contents 0 The amount of this Reagent present in the machine
Recipe 2 The amount of this Reagent required by the Machine's current recipe
Required 1 The amount of this Reagent needed to complete the Machine's current recipe after subtracting the amount currently present
TotalContents 3

View File

@@ -1,27 +0,0 @@
Charge 10 returns current energy charge the slot occupant is holding
ChargeRatio 11 returns current energy charge the slot occupant is holding as a ratio between 0 and 1 of its maximum
Class 12 returns integer representing the class of object
Damage 4 returns the damage state of the item in the slot
Efficiency 5 returns the growth efficiency of the plant in the slot
FilterType 25
Growth 7 returns the current growth state of the plant in the slot
Health 6 returns the health of the plant in the slot
LineNumber 19
Lock 23
Mature 16 returns 1 if the plant in this slot is mature, 0 when it isn't
MaxQuantity 15 returns the max stack size of the item in the slot
None 0 No description
OccupantHash 2 returns the has of the current occupant, the unique identifier of the thing
Occupied 1 returns 0 when slot is not occupied, 1 when it is
On 22
Open 21
PrefabHash 17 returns the hash of the structure in the slot
Pressure 8 returns pressure of the slot occupants internal atmosphere
PressureAir 14 returns pressure in the air tank of the jetpack in this slot
PressureWaste 13 returns pressure in the waste tank of the jetpack in this slot
Quantity 3 returns the current quantity, such as stack size, of the item in the slot
ReferenceId 26
Seeding 18 Whether a plant is seeding (ready to harvest seeds from). Returns 1 if seeding or 0 if not.
SortingClass 24
Temperature 9 returns temperature of the slot occupants internal atmosphere
Volume 20

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,11 @@
use crate::{
grammar::{LogicType, ReagentMode, SlotLogicType},
interpreter::{ICError, ICState},
errors::ICError,
interpreter::ICState,
network::{CableConnectionType, Connection},
vm::enums::script_enums::{
LogicBatchMethod as BatchMode, LogicReagentMode as ReagentMode,
LogicSlotType as SlotLogicType, LogicType,
},
vm::VM,
};
use std::{collections::BTreeMap, ops::Deref};

209
ic10emu/src/errors.rs Normal file
View File

@@ -0,0 +1,209 @@
use crate::vm::instructions::enums::InstructionOp;
use serde::{Deserialize, Serialize};
use std::error::Error as StdError;
use std::fmt::Display;
use thiserror::Error;
#[derive(Error, Debug, Serialize, Deserialize)]
pub enum VMError {
#[error("device with id '{0}' does not exist")]
UnknownId(u32),
#[error("ic with id '{0}' does not exist")]
UnknownIcId(u32),
#[error("device with id '{0}' does not have a ic slot")]
NoIC(u32),
#[error("ic encountered an error: {0}")]
ICError(#[from] ICError),
#[error("ic encountered an error: {0}")]
LineError(#[from] LineError),
#[error("invalid network id {0}")]
InvalidNetwork(u32),
#[error("device {0} not visible to device {1} (not on the same networks)")]
DeviceNotVisible(u32, u32),
#[error("a device with id {0} already exists")]
IdInUse(u32),
#[error("device(s) with ids {0:?} already exist")]
IdsInUse(Vec<u32>),
#[error("atempt to use a set of id's with duplicates: id(s) {0:?} exsist more than once")]
DuplicateIds(Vec<u32>),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LineError {
pub error: ICError,
pub line: u32,
}
impl Display for LineError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Error on line {}: {}", self.line, self.error)
}
}
impl StdError for LineError {}
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct ParseError {
pub line: usize,
pub start: usize,
pub end: usize,
pub msg: String,
}
impl Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{} at line {} {}:{}",
self.msg, self.line, self.start, self.end
)
}
}
impl StdError for ParseError {}
impl ParseError {
/// Offset the ParseError in it's line, adding the passed values to it's `start` and `end`
#[must_use]
pub fn offset(self, offset: usize) -> Self {
ParseError {
start: self.start + offset,
end: self.end + offset,
..self
}
}
/// Offset the ParseError line, adding the passed value to it's `line`
#[must_use]
pub fn offset_line(self, offset: usize) -> Self {
ParseError {
line: self.line + offset,
start: self.start,
..self
}
}
/// Mark the parse error as extending 'length' bytes from `start`
#[must_use]
pub fn span(self, length: usize) -> Self {
ParseError {
start: self.start,
end: self.start + length,
..self
}
}
}
#[derive(Debug, Error, Clone, Serialize, Deserialize)]
pub enum ICError {
#[error("error compiling code: {0}")]
ParseError(#[from] ParseError),
#[error("duplicate label {0}")]
DuplicateLabel(String),
#[error("instruction pointer out of range: '{0}'")]
InstructionPointerOutOfRange(u32),
#[error("register pointer out of range: '{0}'")]
RegisterIndexOutOfRange(f64),
#[error("device pointer out of range: '{0}'")]
DeviceIndexOutOfRange(f64),
#[error("stack index out of range: '{0}'")]
StackIndexOutOfRange(f64),
#[error("slot index out of range: '{0}'")]
SlotIndexOutOfRange(f64),
#[error("pin index {0} out of range 0-6")]
PinIndexOutOfRange(usize),
#[error("connection index {0} out of range {1}")]
ConnectionIndexOutOfRange(usize, usize),
#[error("unknown device ID '{0}'")]
UnknownDeviceID(f64),
#[error("too few operands!: provide: '{provided}', desired: '{desired}'")]
TooFewOperands { provided: u32, desired: u32 },
#[error("too many operands!: provide: '{provided}', desired: '{desired}'")]
TooManyOperands { provided: u32, desired: u32 },
#[error("incorrect operand type for instruction `{inst}` operand {index}, not a {desired} ")]
IncorrectOperandType {
inst: InstructionOp,
index: u32,
desired: String,
},
#[error("unknown identifier {0}")]
UnknownIdentifier(String),
#[error("device Not Set")]
DeviceNotSet,
#[error("shift Underflow i64(signed long)")]
ShiftUnderflowI64,
#[error("shift Overflow i64(signed long)")]
ShiftOverflowI64,
#[error("shift underflow i32(signed int)")]
ShiftUnderflowI32,
#[error("shift overflow i32(signed int)")]
ShiftOverflowI32,
#[error("stack underflow")]
StackUnderflow,
#[error("stack overflow")]
StackOverflow,
#[error("duplicate define '{0}'")]
DuplicateDefine(String),
#[error("read only field '{0}'")]
ReadOnlyField(String),
#[error("write only field '{0}'")]
WriteOnlyField(String),
#[error("device has no field '{0}'")]
DeviceHasNoField(String),
#[error("device has not ic")]
DeviceHasNoIC,
#[error("unknown device '{0}'")]
UnknownDeviceId(f64),
#[error("unknown logic type '{0}'")]
UnknownLogicType(f64),
#[error("unknown slot logic type '{0}'")]
UnknownSlotLogicType(f64),
#[error("unknown batch mode '{0}'")]
UnknownBatchMode(f64),
#[error("unknown reagent mode '{0}'")]
UnknownReagentMode(f64),
#[error("type value not known")]
TypeValueNotKnown,
#[error("empty device list")]
EmptyDeviceList,
#[error("connection specifier missing")]
MissingConnectionSpecifier,
#[error("no data network on connection '{0}'")]
NotACableConnection(usize),
#[error("network not connected on connection '{0}'")]
NetworkNotConnected(usize),
#[error("bad network Id '{0}'")]
BadNetworkId(u32),
#[error("channel index out of range '{0}'")]
ChannelIndexOutOfRange(usize),
#[error("slot has no occupant")]
SlotNotOccupied,
#[error("generated Enum {0} has no value attached. Report this error.")]
NoGeneratedValue(String),
#[error("generated Enum {0}'s value does not parse as {1} . Report this error.")]
BadGeneratedValueParse(String, String),
}
impl ICError {
pub const fn too_few_operands(provided: usize, desired: u32) -> Self {
ICError::TooFewOperands {
provided: provided as u32,
desired,
}
}
pub const fn too_many_operands(provided: usize, desired: u32) -> Self {
ICError::TooManyOperands {
provided: provided as u32,
desired,
}
}
pub const fn mismatch_operands(provided: usize, desired: u32) -> Self {
if provided < desired as usize {
ICError::too_few_operands(provided, desired)
} else {
ICError::too_many_operands(provided, desired)
}
}
}

View File

@@ -1,138 +1,62 @@
use crate::interpreter::{self, ICError};
use crate::interpreter;
use crate::tokens::{SplitConsecutiveIndicesExt, SplitConsecutiveWithIndices};
use crate::vm::enums::script_enums::{
LogicBatchMethod, LogicReagentMode, LogicSlotType, LogicType,
};
use crate::vm::instructions::{
enums::InstructionOp,
operands::{Device, DeviceSpec, Identifier, Number, Operand, RegisterSpec},
Instruction, CONSTANTS_LOOKUP,
};
use crate::{
errors::{ICError, ParseError},
vm::enums::basic_enums::BasicEnum,
};
use itertools::Itertools;
use std::error::Error;
use std::fmt::Display;
use std::str::FromStr;
use strum::EnumProperty;
use strum::{EnumProperty, IntoEnumIterator};
pub mod generated {
use super::ParseError;
use crate::interpreter::ICError;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use strum::{
AsRefStr, Display, EnumIter, EnumProperty, EnumString, FromRepr, IntoEnumIterator,
};
include!(concat!(env!("OUT_DIR"), "/instructions.rs"));
include!(concat!(env!("OUT_DIR"), "/logictypes.rs"));
include!(concat!(env!("OUT_DIR"), "/modes.rs"));
include!(concat!(env!("OUT_DIR"), "/constants.rs"));
include!(concat!(env!("OUT_DIR"), "/enums.rs"));
impl TryFrom<f64> for LogicType {
type Error = ICError;
fn try_from(value: f64) -> Result<Self, <LogicType as TryFrom<f64>>::Error> {
if let Some(lt) = LogicType::iter().find(|lt| {
lt.get_str("value")
.map(|val| val.parse::<u16>().unwrap() as f64 == value)
.unwrap_or(false)
}) {
Ok(lt)
} else {
Err(crate::interpreter::ICError::UnknownLogicType(value))
}
}
}
impl TryFrom<f64> for SlotLogicType {
type Error = ICError;
fn try_from(value: f64) -> Result<Self, <SlotLogicType as TryFrom<f64>>::Error> {
if let Some(slt) = SlotLogicType::iter().find(|lt| {
lt.get_str("value")
.map(|val| val.parse::<u8>().unwrap() as f64 == value)
.unwrap_or(false)
}) {
Ok(slt)
} else {
Err(crate::interpreter::ICError::UnknownSlotLogicType(value))
}
}
}
impl TryFrom<f64> for BatchMode {
type Error = ICError;
fn try_from(value: f64) -> Result<Self, <BatchMode as TryFrom<f64>>::Error> {
if let Some(bm) = BatchMode::iter().find(|lt| {
lt.get_str("value")
.map(|val| val.parse::<u8>().unwrap() as f64 == value)
.unwrap_or(false)
}) {
Ok(bm)
} else {
Err(crate::interpreter::ICError::UnknownBatchMode(value))
}
}
}
impl TryFrom<f64> for ReagentMode {
type Error = ICError;
fn try_from(value: f64) -> Result<Self, <ReagentMode as TryFrom<f64>>::Error> {
if let Some(rm) = ReagentMode::iter().find(|lt| {
lt.get_str("value")
.map(|val| val.parse::<u8>().unwrap() as f64 == value)
.unwrap_or(false)
}) {
Ok(rm)
} else {
Err(crate::interpreter::ICError::UnknownReagentMode(value))
}
impl TryFrom<f64> for LogicType {
type Error = ICError;
fn try_from(value: f64) -> Result<Self, <LogicType as TryFrom<f64>>::Error> {
if let Some(lt) = LogicType::iter().find(|lt| *lt as u16 as f64 == value) {
Ok(lt)
} else {
Err(ICError::UnknownLogicType(value))
}
}
}
pub use generated::*;
use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct ParseError {
pub line: usize,
pub start: usize,
pub end: usize,
pub msg: String,
}
impl Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{} at line {} {}:{}",
self.msg, self.line, self.start, self.end
)
impl TryFrom<f64> for LogicSlotType {
type Error = ICError;
fn try_from(value: f64) -> Result<Self, <LogicSlotType as TryFrom<f64>>::Error> {
if let Some(slt) = LogicSlotType::iter().find(|lt| *lt as u8 as f64 == value) {
Ok(slt)
} else {
Err(ICError::UnknownSlotLogicType(value))
}
}
}
impl Error for ParseError {}
impl ParseError {
/// Offset the ParseError in it's line, adding the passed values to it's `start` and `end`
#[must_use]
pub fn offset(self, offset: usize) -> Self {
ParseError {
start: self.start + offset,
end: self.end + offset,
..self
impl TryFrom<f64> for LogicBatchMethod {
type Error = ICError;
fn try_from(value: f64) -> Result<Self, <LogicBatchMethod as TryFrom<f64>>::Error> {
if let Some(bm) = LogicBatchMethod::iter().find(|lt| *lt as u8 as f64 == value) {
Ok(bm)
} else {
Err(ICError::UnknownBatchMode(value))
}
}
}
/// Offset the ParseError line, adding the passed value to it's `line`
#[must_use]
pub fn offset_line(self, offset: usize) -> Self {
ParseError {
line: self.line + offset,
start: self.start,
..self
}
}
/// Mark the parse error as extending 'length' bytes from `start`
#[must_use]
pub fn span(self, length: usize) -> Self {
ParseError {
start: self.start,
end: self.start + length,
..self
impl TryFrom<f64> for LogicReagentMode {
type Error = ICError;
fn try_from(value: f64) -> Result<Self, <LogicReagentMode as TryFrom<f64>>::Error> {
if let Some(rm) = LogicReagentMode::iter().find(|lt| *lt as u8 as f64 == value) {
Ok(rm)
} else {
Err(ICError::UnknownReagentMode(value))
}
}
}
@@ -246,12 +170,6 @@ impl FromStr for Comment {
}
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct Instruction {
pub instruction: InstructionOp,
pub operands: Vec<Operand>,
}
impl FromStr for Instruction {
type Err = ParseError;
/// parse a non-empty string for an instruction and it's operands
@@ -259,9 +177,16 @@ impl FromStr for Instruction {
let mut tokens_iter = s.split_consecutive_with_indices(&[' ', '\t'][..]);
let instruction: InstructionOp = {
if let Some((index, token)) = tokens_iter.next() {
token
.parse::<InstructionOp>()
.map_err(|e| e.offset(index).span(token.len()))
token.parse::<InstructionOp>().map_err(|_e| {
ParseError {
line: 0,
start: 0,
end: 0,
msg: format!("unknown instruction '{token}'"),
}
.offset(index)
.span(token.len())
})
} else {
Err(ParseError {
line: 0,
@@ -320,290 +245,6 @@ fn get_operand_tokens<'a>(
operand_tokens
}
#[derive(PartialEq, Eq, Debug, Clone, Copy, Serialize, Deserialize)]
pub enum Device {
Db,
Numbered(u32),
Indirect { indirection: u32, target: u32 },
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct RegisterSpec {
pub indirection: u32,
pub target: u32,
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct DeviceSpec {
pub device: Device,
pub connection: Option<usize>,
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub enum Operand {
RegisterSpec(RegisterSpec),
DeviceSpec(DeviceSpec),
Number(Number),
Type {
logic_type: Option<LogicType>,
slot_logic_type: Option<SlotLogicType>,
batch_mode: Option<BatchMode>,
reagent_mode: Option<ReagentMode>,
identifier: Identifier,
},
Identifier(Identifier),
}
impl Operand {
pub fn as_value(
&self,
ic: &interpreter::IC,
inst: InstructionOp,
index: u32,
) -> Result<f64, interpreter::ICError> {
match self.translate_alias(ic) {
Operand::RegisterSpec(RegisterSpec {
indirection,
target,
}) => ic.get_register(indirection, target),
Operand::Number(num) => Ok(num.value()),
Operand::Type {
logic_type,
slot_logic_type,
batch_mode,
reagent_mode,
identifier: _,
} => {
if let Some(lt) = logic_type {
Ok(lt
.get_str("value")
.ok_or_else(|| ICError::NoGeneratedValue(lt.to_string()))?
.parse::<u16>()
.map_err(|_| {
ICError::BadGeneratedValueParse(lt.to_string(), "u16".to_owned())
})? as f64)
} else if let Some(slt) = slot_logic_type {
Ok(slt
.get_str("value")
.ok_or_else(|| ICError::NoGeneratedValue(slt.to_string()))?
.parse::<u8>()
.map_err(|_| {
ICError::BadGeneratedValueParse(slt.to_string(), "u8".to_owned())
})? as f64)
} else if let Some(bm) = batch_mode {
Ok(bm
.get_str("value")
.ok_or_else(|| ICError::NoGeneratedValue(bm.to_string()))?
.parse::<u8>()
.map_err(|_| {
ICError::BadGeneratedValueParse(bm.to_string(), "u8".to_owned())
})? as f64)
} else if let Some(rm) = reagent_mode {
Ok(rm
.get_str("value")
.ok_or_else(|| ICError::NoGeneratedValue(rm.to_string()))?
.parse::<u8>()
.map_err(|_| {
ICError::BadGeneratedValueParse(rm.to_string(), "u8".to_owned())
})? as f64)
} else {
Err(interpreter::ICError::TypeValueNotKnown)
}
}
Operand::Identifier(id) => {
Err(interpreter::ICError::UnknownIdentifier(id.name.to_string()))
}
Operand::DeviceSpec { .. } => Err(interpreter::ICError::IncorrectOperandType {
inst,
index,
desired: "Value".to_owned(),
}),
}
}
pub fn as_value_i64(
&self,
ic: &interpreter::IC,
signed: bool,
inst: InstructionOp,
index: u32,
) -> Result<i64, interpreter::ICError> {
match self {
Self::Number(num) => Ok(num.value_i64(signed)),
_ => {
let val = self.as_value(ic, inst, index)?;
if val < -9.223_372_036_854_776E18 {
Err(interpreter::ICError::ShiftUnderflowI64)
} else if val <= 9.223_372_036_854_776E18 {
Ok(interpreter::f64_to_i64(val, signed))
} else {
Err(interpreter::ICError::ShiftOverflowI64)
}
}
}
}
pub fn as_value_i32(
&self,
ic: &interpreter::IC,
signed: bool,
inst: InstructionOp,
index: u32,
) -> Result<i32, interpreter::ICError> {
match self {
Self::Number(num) => Ok(num.value_i64(signed) as i32),
_ => {
let val = self.as_value(ic, inst, index)?;
if val < -2147483648.0 {
Err(interpreter::ICError::ShiftUnderflowI32)
} else if val <= 2147483647.0 {
Ok(val as i32)
} else {
Err(interpreter::ICError::ShiftOverflowI32)
}
}
}
}
pub fn as_register(
&self,
ic: &interpreter::IC,
inst: InstructionOp,
index: u32,
) -> Result<RegisterSpec, interpreter::ICError> {
match self.translate_alias(ic) {
Operand::RegisterSpec(reg) => Ok(reg),
Operand::Identifier(id) => {
Err(interpreter::ICError::UnknownIdentifier(id.name.to_string()))
}
_ => Err(interpreter::ICError::IncorrectOperandType {
inst,
index,
desired: "Register".to_owned(),
}),
}
}
pub fn as_device(
&self,
ic: &interpreter::IC,
inst: InstructionOp,
index: u32,
) -> Result<(Option<u32>, Option<usize>), interpreter::ICError> {
match self.translate_alias(ic) {
Operand::DeviceSpec(DeviceSpec { device, connection }) => match device {
Device::Db => Ok((Some(ic.device), connection)),
Device::Numbered(p) => {
let dp = ic
.pins
.borrow()
.get(p as usize)
.ok_or(interpreter::ICError::DeviceIndexOutOfRange(p as f64))
.copied()?;
Ok((dp, connection))
}
Device::Indirect {
indirection,
target,
} => {
let val = ic.get_register(indirection, target)?;
let dp = ic
.pins
.borrow()
.get(val as usize)
.ok_or(interpreter::ICError::DeviceIndexOutOfRange(val))
.copied()?;
Ok((dp, connection))
}
},
Operand::Identifier(id) => {
Err(interpreter::ICError::UnknownIdentifier(id.name.to_string()))
}
_ => Err(interpreter::ICError::IncorrectOperandType {
inst,
index,
desired: "Value".to_owned(),
}),
}
}
pub fn as_logic_type(
&self,
ic: &interpreter::IC,
inst: InstructionOp,
index: u32,
) -> Result<LogicType, ICError> {
match &self {
Operand::Type {
logic_type: Some(lt),
..
} => Ok(*lt),
_ => LogicType::try_from(self.as_value(ic, inst, index)?),
}
}
pub fn as_slot_logic_type(
&self,
ic: &interpreter::IC,
inst: InstructionOp,
index: u32,
) -> Result<SlotLogicType, ICError> {
match &self {
Operand::Type {
slot_logic_type: Some(slt),
..
} => Ok(*slt),
_ => SlotLogicType::try_from(self.as_value(ic, inst, index)?),
}
}
pub fn as_batch_mode(
&self,
ic: &interpreter::IC,
inst: InstructionOp,
index: u32,
) -> Result<BatchMode, ICError> {
match &self {
Operand::Type {
batch_mode: Some(bm),
..
} => Ok(*bm),
_ => BatchMode::try_from(self.as_value(ic, inst, index)?),
}
}
pub fn as_reagent_mode(
&self,
ic: &interpreter::IC,
inst: InstructionOp,
index: u32,
) -> Result<ReagentMode, ICError> {
match &self {
Operand::Type {
reagent_mode: Some(rm),
..
} => Ok(*rm),
_ => ReagentMode::try_from(self.as_value(ic, inst, index)?),
}
}
pub fn translate_alias(&self, ic: &interpreter::IC) -> Self {
match &self {
Operand::Identifier(id) | Operand::Type { identifier: id, .. } => {
if let Some(alias) = ic.aliases.borrow().get(&id.name) {
alias.clone()
} else if let Some(define) = ic.defines.borrow().get(&id.name) {
Operand::Number(Number::Float(*define))
} else if let Some(label) = ic.program.borrow().labels.get(&id.name) {
Operand::Number(Number::Float(*label as f64))
} else {
self.clone()
}
}
_ => self.clone(),
}
}
}
impl FromStr for Operand {
type Err = ParseError;
/// Parse a str containing an single instruction operand
@@ -874,15 +515,13 @@ impl FromStr for Operand {
}
} else if let Some(val) = CONSTANTS_LOOKUP.get(s) {
Ok(Operand::Number(Number::Constant(*val)))
} else if let Ok(val) = LogicEnums::from_str(s) {
Ok(Operand::Number(Number::Enum(
val.get_str("value").unwrap().parse().unwrap(),
)))
} else if let Ok(val) = BasicEnum::from_str(s) {
Ok(Operand::Number(Number::Enum(val.get_value() as f64)))
} else {
let lt = LogicType::from_str(s).ok();
let slt = SlotLogicType::from_str(s).ok();
let bm = BatchMode::from_str(s).ok();
let rm = ReagentMode::from_str(s).ok();
let slt = LogicSlotType::from_str(s).ok();
let bm = LogicBatchMethod::from_str(s).ok();
let rm = LogicReagentMode::from_str(s).ok();
let identifier = Identifier::from_str(s)?;
if lt.is_some() || slt.is_some() || bm.is_some() || rm.is_some() {
Ok(Operand::Type {
@@ -1007,11 +646,6 @@ impl FromStr for Label {
}
}
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
pub struct Identifier {
pub name: String,
}
impl FromStr for Identifier {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
@@ -1057,16 +691,6 @@ impl Display for Identifier {
}
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub enum Number {
Float(f64),
Binary(i64),
Hexadecimal(i64),
Constant(f64),
String(String),
Enum(f64),
}
impl Number {
pub fn value(&self) -> f64 {
match self {
@@ -1249,7 +873,7 @@ mod tests {
}),
Operand::Type {
logic_type: Some(LogicType::On),
slot_logic_type: Some(SlotLogicType::On),
slot_logic_type: Some(LogicSlotType::On),
batch_mode: None,
reagent_mode: None,
identifier: Identifier {
@@ -1458,9 +1082,9 @@ mod tests {
test_roundtrip("1.2345");
test_roundtrip("-1.2345");
test_roundtrip(LogicType::Pressure.as_ref());
test_roundtrip(SlotLogicType::Occupied.as_ref());
test_roundtrip(BatchMode::Average.as_ref());
test_roundtrip(ReagentMode::Recipe.as_ref());
test_roundtrip(LogicSlotType::Occupied.as_ref());
test_roundtrip(LogicBatchMethod::Average.as_ref());
test_roundtrip(LogicReagentMode::Recipe.as_ref());
test_roundtrip("pi");
test_roundtrip("pinf");
test_roundtrip("ninf");
@@ -1478,30 +1102,35 @@ mod tests {
let value = lt.get_str("value");
assert!(value.is_some());
assert!(value.unwrap().parse::<u16>().is_ok());
assert_eq!(lt as u16, value.unwrap());
}
for slt in SlotLogicType::iter() {
for slt in LogicSlotType::iter() {
println!("testing SlotLogicType.{slt}");
let value = slt.get_str("value");
assert!(value.is_some());
assert!(value.unwrap().parse::<u8>().is_ok());
assert_eq!(slt as u8, value.unwrap());
}
for bm in BatchMode::iter() {
for bm in LogicReagentMode::iter() {
println!("testing BatchMode.{bm}");
let value = bm.get_str("value");
assert!(value.is_some());
assert!(value.unwrap().parse::<u8>().is_ok());
assert_eq!(bm as u8, value.unwrap());
}
for rm in ReagentMode::iter() {
for rm in LogicReagentMode::iter() {
println!("testing ReagentMode.{rm}");
let value = rm.get_str("value");
assert!(value.is_some());
assert!(value.unwrap().parse::<u8>().is_ok());
assert_eq!(rm as u8, value.unwrap());
}
for le in LogicEnums::iter() {
println!("testing Enum.{le}");
for le in BasicEnum::iter() {
println!("testing BasicEnum {le}");
let value = le.get_str("value");
assert!(value.is_some());
assert!(value.unwrap().parse::<u32>().is_ok());
assert_eq!(le.get_value(), value.unwrap());
}
}

View File

@@ -18,142 +18,21 @@ use time::format_description;
use crate::{
device::SlotType,
grammar::{self, LogicType, ParseError, SlotLogicType},
vm::VM,
errors::{ICError, LineError, ParseError},
grammar,
vm::{
enums::script_enums::{LogicSlotType as SlotLogicType, LogicType},
instructions::{
enums::InstructionOp,
operands::{DeviceSpec, Operand, RegisterSpec},
Instruction,
},
VM,
},
};
use serde_with::serde_as;
use thiserror::Error;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LineError {
error: ICError,
line: u32,
}
impl Display for LineError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Error on line {}: {}", self.line, self.error)
}
}
impl Error for LineError {}
#[derive(Debug, Error, Clone, Serialize, Deserialize)]
pub enum ICError {
#[error("error compiling code: {0}")]
ParseError(#[from] ParseError),
#[error("duplicate label {0}")]
DuplicateLabel(String),
#[error("instruction pointer out of range: '{0}'")]
InstructionPointerOutOfRange(u32),
#[error("register pointer out of range: '{0}'")]
RegisterIndexOutOfRange(f64),
#[error("device pointer out of range: '{0}'")]
DeviceIndexOutOfRange(f64),
#[error("stack index out of range: '{0}'")]
StackIndexOutOfRange(f64),
#[error("slot index out of range: '{0}'")]
SlotIndexOutOfRange(f64),
#[error("pin index {0} out of range 0-6")]
PinIndexOutOfRange(usize),
#[error("connection index {0} out of range {1}")]
ConnectionIndexOutOfRange(usize, usize),
#[error("unknown device ID '{0}'")]
UnknownDeviceID(f64),
#[error("too few operands!: provide: '{provided}', desired: '{desired}'")]
TooFewOperands { provided: u32, desired: u32 },
#[error("too many operands!: provide: '{provided}', desired: '{desired}'")]
TooManyOperands { provided: u32, desired: u32 },
#[error("incorrect operand type for instruction `{inst}` operand {index}, not a {desired} ")]
IncorrectOperandType {
inst: grammar::InstructionOp,
index: u32,
desired: String,
},
#[error("unknown identifier {0}")]
UnknownIdentifier(String),
#[error("device Not Set")]
DeviceNotSet,
#[error("shift Underflow i64(signed long)")]
ShiftUnderflowI64,
#[error("shift Overflow i64(signed long)")]
ShiftOverflowI64,
#[error("shift underflow i32(signed int)")]
ShiftUnderflowI32,
#[error("shift overflow i32(signed int)")]
ShiftOverflowI32,
#[error("stack underflow")]
StackUnderflow,
#[error("stack overflow")]
StackOverflow,
#[error("duplicate define '{0}'")]
DuplicateDefine(String),
#[error("read only field '{0}'")]
ReadOnlyField(String),
#[error("write only field '{0}'")]
WriteOnlyField(String),
#[error("device has no field '{0}'")]
DeviceHasNoField(String),
#[error("device has not ic")]
DeviceHasNoIC,
#[error("unknown device '{0}'")]
UnknownDeviceId(f64),
#[error("unknown logic type '{0}'")]
UnknownLogicType(f64),
#[error("unknown slot logic type '{0}'")]
UnknownSlotLogicType(f64),
#[error("unknown batch mode '{0}'")]
UnknownBatchMode(f64),
#[error("unknown reagent mode '{0}'")]
UnknownReagentMode(f64),
#[error("type value not known")]
TypeValueNotKnown,
#[error("empty device list")]
EmptyDeviceList,
#[error("connection specifier missing")]
MissingConnectionSpecifier,
#[error("no data network on connection '{0}'")]
NotACableConnection(usize),
#[error("network not connected on connection '{0}'")]
NetworkNotConnected(usize),
#[error("bad network Id '{0}'")]
BadNetworkId(u32),
#[error("channel index out of range '{0}'")]
ChannelIndexOutOfRange(usize),
#[error("slot has no occupant")]
SlotNotOccupied,
#[error("generated Enum {0} has no value attached. Report this error.")]
NoGeneratedValue(String),
#[error("generated Enum {0}'s value does not parse as {1} . Report this error.")]
BadGeneratedValueParse(String, String),
}
impl ICError {
pub const fn too_few_operands(provided: usize, desired: u32) -> Self {
ICError::TooFewOperands {
provided: provided as u32,
desired,
}
}
pub const fn too_many_operands(provided: usize, desired: u32) -> Self {
ICError::TooManyOperands {
provided: provided as u32,
desired,
}
}
pub const fn mismatch_operands(provided: usize, desired: u32) -> Self {
if provided < desired as usize {
ICError::too_few_operands(provided, desired)
} else {
ICError::too_many_operands(provided, desired)
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ICState {
Start,
@@ -195,7 +74,7 @@ pub struct IC {
/// Instruction Count since last yield
pub ic: Cell<u16>,
pub stack: RefCell<[f64; 512]>,
pub aliases: RefCell<BTreeMap<String, grammar::Operand>>,
pub aliases: RefCell<BTreeMap<String, Operand>>,
pub defines: RefCell<BTreeMap<String, f64>>,
pub pins: RefCell<[Option<u32>; 6]>,
pub code: RefCell<String>,
@@ -215,7 +94,7 @@ pub struct FrozenIC {
pub ic: u16,
#[serde_as(as = "[_; 512]")]
pub stack: [f64; 512],
pub aliases: BTreeMap<String, grammar::Operand>,
pub aliases: BTreeMap<String, Operand>,
pub defines: BTreeMap<String, f64>,
pub pins: [Option<u32>; 6],
pub state: ICState,
@@ -264,7 +143,7 @@ impl From<FrozenIC> for IC {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Program {
pub instructions: Vec<grammar::Instruction>,
pub instructions: Vec<Instruction>,
pub errors: Vec<ICError>,
pub labels: BTreeMap<String, u32>,
}
@@ -293,8 +172,8 @@ impl Program {
.into_iter()
.enumerate()
.map(|(line_number, line)| match line.code {
None => Ok(grammar::Instruction {
instruction: grammar::InstructionOp::Nop,
None => Ok(Instruction {
instruction: InstructionOp::Nop,
operands: vec![],
}),
Some(code) => match code {
@@ -304,8 +183,8 @@ impl Program {
} else {
labels_set.insert(label.id.name.clone());
labels.insert(label.id.name, line_number as u32);
Ok(grammar::Instruction {
instruction: grammar::InstructionOp::Nop,
Ok(Instruction {
instruction: InstructionOp::Nop,
operands: vec![],
})
}
@@ -331,8 +210,8 @@ impl Program {
.into_iter()
.enumerate()
.map(|(line_number, line)| match line.code {
None => grammar::Instruction {
instruction: grammar::InstructionOp::Nop,
None => Instruction {
instruction: InstructionOp::Nop,
operands: vec![],
},
Some(code) => match code {
@@ -343,16 +222,16 @@ impl Program {
labels_set.insert(label.id.name.clone());
labels.insert(label.id.name, line_number as u32);
}
grammar::Instruction {
instruction: grammar::InstructionOp::Nop,
Instruction {
instruction: InstructionOp::Nop,
operands: vec![],
}
}
grammar::Code::Instruction(instruction) => instruction,
grammar::Code::Invalid(err) => {
errors.push(err.into());
grammar::Instruction {
instruction: grammar::InstructionOp::Nop,
Instruction {
instruction: InstructionOp::Nop,
operands: vec![],
}
}
@@ -366,7 +245,7 @@ impl Program {
}
}
pub fn get_line(&self, line: u32) -> Result<&grammar::Instruction, ICError> {
pub fn get_line(&self, line: u32) -> Result<&Instruction, ICError> {
self.instructions
.get(line as usize)
.ok_or(ICError::InstructionPointerOutOfRange(line))
@@ -560,14 +439,13 @@ impl IC {
}
fn internal_step(&self, vm: &VM, advance_ip_on_err: bool) -> Result<(), ICError> {
use grammar::*;
use ICError::*;
let mut next_ip = self.ip() + 1;
// XXX: This closure should be replaced with a try block
// https://github.com/rust-lang/rust/issues/31436
let mut process_op = |this: &Self| -> Result<(), ICError> {
use grammar::InstructionOp::*;
use InstructionOp::*;
// force the program borrow to drop
let line = {
@@ -578,7 +456,9 @@ impl IC {
let inst = line.instruction;
match inst {
Nop => Ok(()),
Hcf => Ok(()), // TODO
Hcf => Ok(()), // TODO
Clr => Ok(()), // TODO
Label => Ok(()), // NOP
Sleep => match &operands[..] {
[a] => {
let a = a.as_value(this, inst, 1)?;
@@ -2577,31 +2457,31 @@ impl IC {
}
#[allow(dead_code)]
const CHANNEL_LOGIC_TYPES: [grammar::LogicType; 8] = [
grammar::LogicType::Channel0,
grammar::LogicType::Channel1,
grammar::LogicType::Channel2,
grammar::LogicType::Channel3,
grammar::LogicType::Channel4,
grammar::LogicType::Channel5,
grammar::LogicType::Channel6,
grammar::LogicType::Channel7,
const CHANNEL_LOGIC_TYPES: [LogicType; 8] = [
LogicType::Channel0,
LogicType::Channel1,
LogicType::Channel2,
LogicType::Channel3,
LogicType::Channel4,
LogicType::Channel5,
LogicType::Channel6,
LogicType::Channel7,
];
trait LogicTypeExt {
fn as_channel(&self) -> Option<usize>;
}
impl LogicTypeExt for grammar::LogicType {
impl LogicTypeExt for LogicType {
fn as_channel(&self) -> Option<usize> {
match self {
grammar::LogicType::Channel0 => Some(0),
grammar::LogicType::Channel1 => Some(1),
grammar::LogicType::Channel2 => Some(2),
grammar::LogicType::Channel3 => Some(3),
grammar::LogicType::Channel4 => Some(4),
grammar::LogicType::Channel5 => Some(5),
grammar::LogicType::Channel6 => Some(6),
grammar::LogicType::Channel7 => Some(7),
LogicType::Channel0 => Some(0),
LogicType::Channel1 => Some(1),
LogicType::Channel2 => Some(2),
LogicType::Channel3 => Some(3),
LogicType::Channel4 => Some(4),
LogicType::Channel5 => Some(5),
LogicType::Channel6 => Some(6),
LogicType::Channel7 => Some(7),
_ => None,
}
}

View File

@@ -1,8 +1,8 @@
pub mod device;
pub mod errors;
pub mod grammar;
pub mod interpreter;
pub mod network;
mod rand_mscorlib;
pub mod tokens;
pub mod device;
pub mod vm;
pub mod network;

View File

@@ -131,7 +131,6 @@ pub enum NetworkError {
}
impl Network {
pub fn new(id: u32) -> Self {
Network {
id,

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
pub mod basic_enums;
pub mod prefabs;
pub mod script_enums;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
pub mod enums;
pub mod operands;
pub mod traits;
use enums::InstructionOp;
use operands::Operand;
use serde::{Deserialize, Serialize};
use phf::phf_map;
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct Instruction {
pub instruction: InstructionOp,
pub operands: Vec<Operand>,
}
#[allow(clippy::approx_constant)]
pub static CONSTANTS_LOOKUP: phf::Map<&'static str, f64> = phf_map! {
"nan" => f64::NAN,
"ninf" => f64::NEG_INFINITY,
"deg2rad" => 0.0174532923847437f64,
"rad2deg" => 57.2957801818848f64,
"epsilon" => f64::EPSILON,
"pinf" => f64::INFINITY,
"pi" => 3.141592653589793f64,
};

View File

@@ -0,0 +1,302 @@
use crate::errors::ICError;
use crate::interpreter;
use crate::vm::enums::script_enums::{
LogicBatchMethod as BatchMode, LogicReagentMode as ReagentMode, LogicSlotType as SlotLogicType,
LogicType,
};
use crate::vm::instructions::enums::InstructionOp;
use serde::{Deserialize, Serialize};
use strum::EnumProperty;
#[derive(PartialEq, Eq, Debug, Clone, Copy, Serialize, Deserialize)]
pub enum Device {
Db,
Numbered(u32),
Indirect { indirection: u32, target: u32 },
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct RegisterSpec {
pub indirection: u32,
pub target: u32,
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct DeviceSpec {
pub device: Device,
pub connection: Option<usize>,
}
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
pub struct Identifier {
pub name: String,
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub enum Number {
Float(f64),
Binary(i64),
Hexadecimal(i64),
Constant(f64),
String(String),
Enum(f64),
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub enum Operand {
RegisterSpec(RegisterSpec),
DeviceSpec(DeviceSpec),
Number(Number),
Type {
logic_type: Option<LogicType>,
slot_logic_type: Option<SlotLogicType>,
batch_mode: Option<BatchMode>,
reagent_mode: Option<ReagentMode>,
identifier: Identifier,
},
Identifier(Identifier),
}
impl Operand {
pub fn as_value(
&self,
ic: &interpreter::IC,
inst: InstructionOp,
index: u32,
) -> Result<f64, ICError> {
match self.translate_alias(ic) {
Operand::RegisterSpec(RegisterSpec {
indirection,
target,
}) => ic.get_register(indirection, target),
Operand::Number(num) => Ok(num.value()),
Operand::Type {
logic_type,
slot_logic_type,
batch_mode,
reagent_mode,
identifier: _,
} => {
if let Some(lt) = logic_type {
Ok(lt
.get_str("value")
.ok_or_else(|| ICError::NoGeneratedValue(lt.to_string()))?
.parse::<u16>()
.map_err(|_| {
ICError::BadGeneratedValueParse(lt.to_string(), "u16".to_owned())
})? as f64)
} else if let Some(slt) = slot_logic_type {
Ok(slt
.get_str("value")
.ok_or_else(|| ICError::NoGeneratedValue(slt.to_string()))?
.parse::<u8>()
.map_err(|_| {
ICError::BadGeneratedValueParse(slt.to_string(), "u8".to_owned())
})? as f64)
} else if let Some(bm) = batch_mode {
Ok(bm
.get_str("value")
.ok_or_else(|| ICError::NoGeneratedValue(bm.to_string()))?
.parse::<u8>()
.map_err(|_| {
ICError::BadGeneratedValueParse(bm.to_string(), "u8".to_owned())
})? as f64)
} else if let Some(rm) = reagent_mode {
Ok(rm
.get_str("value")
.ok_or_else(|| ICError::NoGeneratedValue(rm.to_string()))?
.parse::<u8>()
.map_err(|_| {
ICError::BadGeneratedValueParse(rm.to_string(), "u8".to_owned())
})? as f64)
} else {
Err(ICError::TypeValueNotKnown)
}
}
Operand::Identifier(id) => Err(ICError::UnknownIdentifier(id.name.to_string())),
Operand::DeviceSpec { .. } => Err(ICError::IncorrectOperandType {
inst,
index,
desired: "Value".to_owned(),
}),
}
}
pub fn as_value_i64(
&self,
ic: &interpreter::IC,
signed: bool,
inst: InstructionOp,
index: u32,
) -> Result<i64, ICError> {
match self {
Self::Number(num) => Ok(num.value_i64(signed)),
_ => {
let val = self.as_value(ic, inst, index)?;
if val < -9.223_372_036_854_776E18 {
Err(ICError::ShiftUnderflowI64)
} else if val <= 9.223_372_036_854_776E18 {
Ok(interpreter::f64_to_i64(val, signed))
} else {
Err(ICError::ShiftOverflowI64)
}
}
}
}
pub fn as_value_i32(
&self,
ic: &interpreter::IC,
signed: bool,
inst: InstructionOp,
index: u32,
) -> Result<i32, ICError> {
match self {
Self::Number(num) => Ok(num.value_i64(signed) as i32),
_ => {
let val = self.as_value(ic, inst, index)?;
if val < -2147483648.0 {
Err(ICError::ShiftUnderflowI32)
} else if val <= 2147483647.0 {
Ok(val as i32)
} else {
Err(ICError::ShiftOverflowI32)
}
}
}
}
pub fn as_register(
&self,
ic: &interpreter::IC,
inst: InstructionOp,
index: u32,
) -> Result<RegisterSpec, ICError> {
match self.translate_alias(ic) {
Operand::RegisterSpec(reg) => Ok(reg),
Operand::Identifier(id) => Err(ICError::UnknownIdentifier(id.name.to_string())),
_ => Err(ICError::IncorrectOperandType {
inst,
index,
desired: "Register".to_owned(),
}),
}
}
pub fn as_device(
&self,
ic: &interpreter::IC,
inst: InstructionOp,
index: u32,
) -> Result<(Option<u32>, Option<usize>), ICError> {
match self.translate_alias(ic) {
Operand::DeviceSpec(DeviceSpec { device, connection }) => match device {
Device::Db => Ok((Some(ic.device), connection)),
Device::Numbered(p) => {
let dp = ic
.pins
.borrow()
.get(p as usize)
.ok_or(ICError::DeviceIndexOutOfRange(p as f64))
.copied()?;
Ok((dp, connection))
}
Device::Indirect {
indirection,
target,
} => {
let val = ic.get_register(indirection, target)?;
let dp = ic
.pins
.borrow()
.get(val as usize)
.ok_or(ICError::DeviceIndexOutOfRange(val))
.copied()?;
Ok((dp, connection))
}
},
Operand::Identifier(id) => Err(ICError::UnknownIdentifier(id.name.to_string())),
_ => Err(ICError::IncorrectOperandType {
inst,
index,
desired: "Value".to_owned(),
}),
}
}
pub fn as_logic_type(
&self,
ic: &interpreter::IC,
inst: InstructionOp,
index: u32,
) -> Result<LogicType, ICError> {
match &self {
Operand::Type {
logic_type: Some(lt),
..
} => Ok(*lt),
_ => LogicType::try_from(self.as_value(ic, inst, index)?),
}
}
pub fn as_slot_logic_type(
&self,
ic: &interpreter::IC,
inst: InstructionOp,
index: u32,
) -> Result<SlotLogicType, ICError> {
match &self {
Operand::Type {
slot_logic_type: Some(slt),
..
} => Ok(*slt),
_ => SlotLogicType::try_from(self.as_value(ic, inst, index)?),
}
}
pub fn as_batch_mode(
&self,
ic: &interpreter::IC,
inst: InstructionOp,
index: u32,
) -> Result<BatchMode, ICError> {
match &self {
Operand::Type {
batch_mode: Some(bm),
..
} => Ok(*bm),
_ => BatchMode::try_from(self.as_value(ic, inst, index)?),
}
}
pub fn as_reagent_mode(
&self,
ic: &interpreter::IC,
inst: InstructionOp,
index: u32,
) -> Result<ReagentMode, ICError> {
match &self {
Operand::Type {
reagent_mode: Some(rm),
..
} => Ok(*rm),
_ => ReagentMode::try_from(self.as_value(ic, inst, index)?),
}
}
pub fn translate_alias(&self, ic: &interpreter::IC) -> Self {
match &self {
Operand::Identifier(id) | Operand::Type { identifier: id, .. } => {
if let Some(alias) = ic.aliases.borrow().get(&id.name) {
alias.clone()
} else if let Some(define) = ic.defines.borrow().get(&id.name) {
Operand::Number(Number::Float(*define))
} else if let Some(label) = ic.program.borrow().labels.get(&id.name) {
Operand::Number(Number::Float(*label as f64))
} else {
self.clone()
}
}
_ => self.clone(),
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,15 @@
mod object;
pub mod enums;
pub mod instructions;
pub mod object;
use crate::{
device::{Device, DeviceTemplate, SlotOccupant, SlotOccupantTemplate},
grammar::{BatchMode, LogicType, SlotLogicType},
interpreter::{self, FrozenIC, ICError, LineError},
errors::{ICError, VMError},
interpreter::{self, FrozenIC},
network::{CableConnectionType, Connection, FrozenNetwork, Network},
vm::enums::script_enums::{
LogicBatchMethod as BatchMode, LogicSlotType as SlotLogicType, LogicType,
},
};
use std::{
cell::RefCell,
@@ -16,31 +19,6 @@ use std::{
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Error, Debug, Serialize, Deserialize)]
pub enum VMError {
#[error("device with id '{0}' does not exist")]
UnknownId(u32),
#[error("ic with id '{0}' does not exist")]
UnknownIcId(u32),
#[error("device with id '{0}' does not have a ic slot")]
NoIC(u32),
#[error("ic encountered an error: {0}")]
ICError(#[from] ICError),
#[error("ic encountered an error: {0}")]
LineError(#[from] LineError),
#[error("invalid network id {0}")]
InvalidNetwork(u32),
#[error("device {0} not visible to device {1} (not on the same networks)")]
DeviceNotVisible(u32, u32),
#[error("a device with id {0} already exists")]
IdInUse(u32),
#[error("device(s) with ids {0:?} already exist")]
IdsInUse(Vec<u32>),
#[error("atempt to use a set of id's with duplicates: id(s) {0:?} exsist more than once")]
DuplicateIds(Vec<u32>),
}
#[derive(Debug)]
pub struct VM {

View File

@@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use thiserror::Error;
use crate::grammar::{LogicType, SlotLogicType};
use crate::vm::enums::script_enums::{LogicSlotType as SlotLogicType, LogicType};
#[derive(Error, Debug, Serialize, Deserialize)]
pub enum LogicError {
@@ -14,7 +14,7 @@ pub enum LogicError {
#[error("can't write slot {1} SlotLogicType {0}")]
CantSlotWrite(SlotLogicType, usize),
#[error("slot id {0} is out of range 0..{1}")]
SlotIndexOutOfRange(usize, usize)
SlotIndexOutOfRange(usize, usize),
}
#[derive(Error, Debug, Serialize, Deserialize)]

View File

@@ -1,14 +1,14 @@
use macro_rules_attribute::derive;
use serde::{Deserialize, Serialize};
mod macros;
mod traits;
mod stationpedia;
mod errors;
pub mod errors;
pub mod macros;
pub mod stationpedia;
pub mod traits;
use traits::*;
use crate::{device::SlotType, grammar::SlotLogicType};
use crate::{device::SlotType, vm::enums::script_enums::LogicSlotType as SlotLogicType};
pub type ObjectID = u32;
pub type BoxedObject = Box<dyn Object<ID = ObjectID>>;
@@ -46,7 +46,6 @@ pub struct LogicField {
pub value: f64,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct Slot {
pub typ: SlotType,

View File

@@ -1,12 +1,8 @@
use std::str::FromStr;
use serde::{Deserialize, Serialize};
use strum::{AsRefStr, Display, EnumIter, EnumProperty, EnumString, FromRepr};
use crate::vm::enums::prefabs::StationpediaPrefab;
use crate::vm::object::BoxedObject;
include!(concat!(env!("OUT_DIR"), "/stationpedia_prefabs.rs"));
#[allow(unused)]
pub enum PrefabTemplate {
Hash(i32),
@@ -27,4 +23,4 @@ pub fn object_from_prefab_template(template: &PrefabTemplate) -> Option<BoxedObj
}
}
mod generic;
pub mod generic;

View File

@@ -1,14 +1,12 @@
use crate::{
grammar::{LogicType, SlotLogicType},
vm::{
object::{
errors::{LogicError, MemoryError},
macros::ObjectInterface,
traits::*,
FieldType, LogicField, Name, ObjectID, Slot,
},
VM,
use crate::vm::{
enums::script_enums::{LogicSlotType as SlotLogicType, LogicType},
object::{
errors::{LogicError, MemoryError},
macros::ObjectInterface,
traits::*,
FieldType, LogicField, Name, ObjectID, Slot,
},
VM,
};
use macro_rules_attribute::derive;
use std::{collections::BTreeMap, usize};
@@ -47,25 +45,9 @@ macro_rules! GWLogicable {
}
};
}
pub trait GWMemory {
fn memory_size(&self) -> usize;
}
macro_rules! GWMemory {
(
$( #[$attr:meta] )*
$viz:vis struct $struct:ident {
$($body:tt)*
}
) => {
impl GWMemory for $struct {
fn memory_size(&self) -> usize {
self.memory.len()
}
}
};
}
pub trait GWMemoryReadable: GWMemory {
pub trait GWMemoryReadable {
fn memory_size(&self) -> usize;
fn memory(&self) -> &Vec<f64>;
}
macro_rules! GWMemoryReadable {
@@ -76,13 +58,16 @@ macro_rules! GWMemoryReadable {
}
) => {
impl GWMemoryReadable for $struct {
fn memory_size(&self) -> usize {
self.memory.len()
}
fn memory(&self) -> &Vec<f64> {
&self.memory
}
}
};
}
pub trait GWMemoryWritable: GWMemory + GWMemoryReadable {
pub trait GWMemoryWritable: GWMemoryReadable {
fn memory_mut(&mut self) -> &mut Vec<f64>;
}
macro_rules! GWMemoryWritable {
@@ -202,12 +187,10 @@ impl<T: GWLogicable + Object> Logicable for T {
}
}
impl<T: GWMemory + Object> Memory for T {
impl<T: GWMemoryReadable + Object> MemoryReadable for T {
fn memory_size(&self) -> usize {
self.memory_size()
}
}
impl<T: GWMemoryReadable + Memory + Object> MemoryReadable for T {
fn get_memory(&self, index: i32) -> Result<f64, MemoryError> {
if index < 0 {
Err(MemoryError::StackUnderflow(index, self.memory().len()))
@@ -218,7 +201,7 @@ impl<T: GWMemoryReadable + Memory + Object> MemoryReadable for T {
}
}
}
impl<T: GWMemoryWritable + Memory + Object> MemoryWritable for T {
impl<T: GWMemoryWritable + MemoryReadable + Object> MemoryWritable for T {
fn set_memory(&mut self, index: i32, val: f64) -> Result<(), MemoryError> {
if index < 0 {
Err(MemoryError::StackUnderflow(index, self.memory().len()))
@@ -270,8 +253,8 @@ pub struct GenericLogicableDevice {
slots: Vec<Slot>,
}
#[derive(ObjectInterface!, GWLogicable!, GWMemory!, GWMemoryReadable!)]
#[custom(implements(Object { Logicable, Memory, MemoryReadable }))]
#[derive(ObjectInterface!, GWLogicable!, GWMemoryReadable!)]
#[custom(implements(Object { Logicable, MemoryReadable }))]
pub struct GenericLogicableMemoryReadable {
#[custom(object_id)]
id: ObjectID,
@@ -283,8 +266,8 @@ pub struct GenericLogicableMemoryReadable {
memory: Vec<f64>,
}
#[derive(ObjectInterface!, GWLogicable!, GWMemory!, GWMemoryReadable!, GWMemoryWritable!)]
#[custom(implements(Object { Logicable, Memory, MemoryReadable, MemoryWritable }))]
#[derive(ObjectInterface!, GWLogicable!, GWMemoryReadable!, GWMemoryWritable!)]
#[custom(implements(Object { Logicable, MemoryReadable, MemoryWritable }))]
pub struct GenericLogicableMemoryReadWritable {
#[custom(object_id)]
id: ObjectID,
@@ -296,8 +279,8 @@ pub struct GenericLogicableMemoryReadWritable {
memory: Vec<f64>,
}
#[derive(ObjectInterface!, GWLogicable!, GWDevice!, GWMemory!, GWMemoryReadable!, GWMemoryWritable!)]
#[custom(implements(Object { Logicable, Device, Memory, MemoryReadable }))]
#[derive(ObjectInterface!, GWLogicable!, GWDevice!, GWMemoryReadable!, GWMemoryWritable!)]
#[custom(implements(Object { Logicable, Device, MemoryReadable }))]
pub struct GenericLogicableDeviceMemoryReadable {
#[custom(object_id)]
id: ObjectID,
@@ -309,8 +292,8 @@ pub struct GenericLogicableDeviceMemoryReadable {
memory: Vec<f64>,
}
#[derive(ObjectInterface!, GWLogicable!, GWDevice!, GWMemory!, GWMemoryReadable!, GWMemoryWritable!)]
#[custom(implements(Object { Logicable, Device, Memory, MemoryReadable, MemoryWritable }))]
#[derive(ObjectInterface!, GWLogicable!, GWDevice!, GWMemoryReadable!, GWMemoryWritable!)]
#[custom(implements(Object { Logicable, Device, MemoryReadable, MemoryWritable }))]
pub struct GenericLogicableDeviceMemoryReadWriteablable {
#[custom(object_id)]
id: ObjectID,

View File

@@ -1,39 +1,55 @@
use std::fmt::Debug;
use crate::{
errors::ICError,
vm::{
enums::script_enums::{LogicSlotType, LogicType},
instructions::Instruction,
object::{
errors::{LogicError, MemoryError},
macros::tag_object_traits,
ObjectID, Slot,
},
VM,
},
};
use crate::{grammar, vm::{object::{errors::{LogicError, MemoryError}, macros::tag_object_traits, ObjectID, Slot}, VM}};
use std::fmt::Debug;
tag_object_traits! {
#![object_trait(Object: Debug)]
pub trait Memory {
pub trait MemoryReadable {
fn memory_size(&self) -> usize;
fn get_memory(&self, index: i32) -> Result<f64, MemoryError>;
}
pub trait MemoryWritable: Memory {
pub trait MemoryWritable: MemoryReadable {
fn set_memory(&mut self, index: i32, val: f64) -> Result<(), MemoryError>;
fn clear_memory(&mut self) -> Result<(), MemoryError>;
}
pub trait MemoryReadable: Memory {
fn get_memory(&self, index: i32) -> Result<f64, MemoryError>;
}
pub trait Logicable {
fn prefab_hash(&self) -> i32;
/// returns 0 if not set
fn name_hash(&self) -> i32;
fn is_logic_readable(&self) -> bool;
fn is_logic_writeable(&self) -> bool;
fn can_logic_read(&self, lt: grammar::LogicType) -> bool;
fn can_logic_write(&self, lt: grammar::LogicType) -> bool;
fn set_logic(&mut self, lt: grammar::LogicType, value: f64, force: bool) -> Result<(), LogicError>;
fn get_logic(&self, lt: grammar::LogicType) -> Result<f64, LogicError>;
fn can_logic_read(&self, lt: LogicType) -> bool;
fn can_logic_write(&self, lt: LogicType) -> bool;
fn set_logic(&mut self, lt: LogicType, value: f64, force: bool) -> Result<(), LogicError>;
fn get_logic(&self, lt: LogicType) -> Result<f64, LogicError>;
fn slots_count(&self) -> usize;
fn get_slot(&self, index: usize) -> Option<&Slot>;
fn get_slot_mut(&mut self, index: usize) -> Option<&mut Slot>;
fn can_slot_logic_read(&self, slt: grammar::SlotLogicType, index: usize) -> bool;
fn get_slot_logic(&self, slt: grammar::SlotLogicType, index: usize, vm: &VM) -> Result<f64, LogicError>;
fn can_slot_logic_read(&self, slt: LogicSlotType, index: usize) -> bool;
fn get_slot_logic(&self, slt: LogicSlotType, index: usize, vm: &VM) -> Result<f64, LogicError>;
}
pub trait SourceCode {
fn set_source_code(&mut self, code: &str) -> Result<(), ICError>;
fn set_source_code_with_invalid(&mut self, code: &str);
fn get_source_code(&self) -> String;
fn get_line(&self, line: usize) -> Result<&Instruction, ICError>;
}
pub trait CircuitHolder: Logicable {
@@ -49,17 +65,17 @@ tag_object_traits! {
fn get_batch_mut(&self) -> Vec<LogicableRefMut<Self>>;
}
pub trait SourceCode {
pub trait Programmable: crate::vm::instructions::traits::ICInstructable {
fn get_source_code(&self) -> String;
fn set_source_code(&self, code: String);
fn step(&mut self) -> Result<(), crate::errors::ICError>;
}
pub trait Instructable: Memory {
pub trait Instructable: MemoryWritable {
// fn get_instructions(&self) -> Vec<LogicInstruction>
}
pub trait LogicStack: Memory {
pub trait LogicStack: MemoryWritable {
// fn logic_stack(&self) -> LogicStack;
}
@@ -67,10 +83,17 @@ tag_object_traits! {
}
}
impl<T: Debug> Debug for dyn Object<ID = T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Object: (ID = {:?}, Type = {})", self.id(), self.type_name())
write!(
f,
"Object: (ID = {:?}, Type = {})",
self.id(),
self.type_name()
)
}
}

View File

@@ -25,7 +25,8 @@ fn main() {
ts_types.push_str(&lt_tstype);
let slt_tsunion: String = Itertools::intersperse(
ic10emu::grammar::generated::SlotLogicType::iter().map(|slt| format!("\"{}\"", slt.as_ref())),
ic10emu::grammar::generated::SlotLogicType::iter()
.map(|slt| format!("\"{}\"", slt.as_ref())),
"\n | ".to_owned(),
)
.collect();

View File

@@ -10,10 +10,8 @@ pub fn set_panic_hook() {
console_error_panic_hook::set_once();
web_sys::console::log_1(&format!("Panic hook set...").into());
}
}
extern crate web_sys;
// A macro to provide `println!(..)`-style syntax for `console.log` logging.

View File

@@ -1,6 +1,6 @@
use futures::stream::TryStreamExt;
use std::{collections::HashMap, sync::Arc};
use tokio::sync::RwLock;
use futures::stream::TryStreamExt;
use tower_lsp::{LspService, Server};
use wasm_bindgen::{prelude::*, JsCast};
use wasm_bindgen_futures::stream::JsStream;
@@ -60,7 +60,7 @@ pub async fn serve(config: ServerConfig) -> Result<(), JsValue> {
let output = wasm_streams::WritableStream::from_raw(output);
let output = output.try_into_async_write().map_err(|err| err.0)?;
let (service, messages) = LspService::new(|client| ic10lsp_lib::server::Backend{
let (service, messages) = LspService::new(|client| ic10lsp_lib::server::Backend {
client,
files: Arc::new(RwLock::new(HashMap::new())),
config: Arc::new(RwLock::new(ic10lsp_lib::server::Configuration::default())),

View File

@@ -5,4 +5,22 @@ edition.workspace = true
[dependencies]
clap = { version = "4.5.4", features = ["derive", "env"] }
color-eyre = "0.6.3"
convert_case = "0.6.0"
indexmap = { version = "2.2.6", features = ["serde"] }
# onig = "6.4.0"
phf_codegen = "0.11.2"
regex = "1.10.4"
serde = "1.0.200"
serde_derive = "1.0.200"
serde_ignored = "0.1.10"
serde_json = "1.0.116"
serde_path_to_error = "0.1.16"
serde_with = "3.8.1"
textwrap = { version = "0.16.1", default-features = false }
thiserror = "1.0.58"
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
onig = { git = "https://github.com/rust-onig/rust-onig", revision = "fa90c0e97e90a056af89f183b23cd417b59ee6a2" }

28
xtask/src/enums.rs Normal file
View File

@@ -0,0 +1,28 @@
use std::collections::BTreeMap;
use serde_derive::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename = "Enums")]
pub struct Enums {
#[serde(rename = "scriptEnums")]
pub script_enums: BTreeMap<String, EnumListing>,
#[serde(rename = "basicEnums")]
pub basic_enums: BTreeMap<String, EnumListing>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename = "EnumListing")]
pub struct EnumListing {
#[serde(rename = "enumName")]
pub enum_name: String,
pub values: BTreeMap<String, EnumEntry>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(rename = "EnumEntry")]
pub struct EnumEntry {
pub value: i64,
pub deprecated: bool,
pub description: String,
}

101
xtask/src/generate.rs Normal file
View File

@@ -0,0 +1,101 @@
use color_eyre::eyre;
use std::{collections::BTreeMap, process::Command};
use crate::{enums::Enums, stationpedia::Stationpedia};
mod database;
mod enums;
mod instructions;
mod utils;
pub fn generate(
stationpedia_path: &std::path::Path,
workspace: &std::path::Path,
) -> color_eyre::Result<()> {
let mut pedia: Stationpedia = parse_json(&mut serde_json::Deserializer::from_reader(
std::io::BufReader::new(std::fs::File::open(
stationpedia_path.join("Stationpedia.json"),
)?),
))?;
let instruction_help_patches: BTreeMap<String, String> = parse_json(
&mut serde_json::Deserializer::from_reader(std::io::BufReader::new(std::fs::File::open(
workspace.join("data").join("instruction_help_patches.json"),
)?)),
)?;
for (inst, patch) in instruction_help_patches {
if let Some(cmd) = pedia.script_commands.get_mut(&inst) {
cmd.desc = patch;
} else {
eprintln!("Warning: can find instruction '{inst}' to patch help!");
}
}
let enums: Enums = parse_json(&mut serde_json::Deserializer::from_reader(
std::io::BufReader::new(std::fs::File::open(stationpedia_path.join("Enums.json"))?),
))?;
database::generate_database(&pedia, &enums, workspace)?;
let enums_files = enums::generate_enums(&pedia, &enums, workspace)?;
let inst_files = instructions::generate_instructions(&pedia, workspace)?;
let generated_files = [enums_files.as_slice(), inst_files.as_slice()].concat();
eprintln!("Formatting generated files...");
for file in &generated_files {
prepend_genereated_comment(file)?;
}
let mut cmd = Command::new("cargo");
cmd.current_dir(workspace);
cmd.arg("fmt").arg("--");
cmd.args(&generated_files);
cmd.status()?;
Ok(())
}
pub fn parse_json<'a, T: serde::Deserialize<'a>>(
jd: impl serde::Deserializer<'a>,
) -> Result<T, color_eyre::Report> {
let mut track = serde_path_to_error::Track::new();
let path = serde_path_to_error::Deserializer::new(jd, &mut track);
let mut fun = |path: serde_ignored::Path| {
tracing::warn!(key=%path,"Found ignored key");
};
serde_ignored::deserialize(path, &mut fun).map_err(|e| {
eyre::eyre!(
"path: {track} | error = {e}",
track = track.path().to_string(),
)
})
}
fn prepend_genereated_comment(file_path: &std::path::Path) -> color_eyre::Result<()> {
use std::io::Write;
let tmp_path = file_path.with_extension("rs.tmp");
{
let mut tmp = std::fs::File::create(&tmp_path)?;
let mut src = std::fs::File::open(file_path)?;
write!(
&mut tmp,
"// ================================================= \n\
// !! <-----> DO NOT MODIFY <-----> !! \n\
// \n\
// This module was automatically generated by an
// xtask \n\
// \n\
// run `cargo xtask generate` from the workspace \n\
// to regenerate \n\
// \n\
// ================================================= \n\
\n\
\n\
"
)?;
std::io::copy(&mut src, &mut tmp)?;
}
std::fs::remove_file(file_path)?;
std::fs::rename(&tmp_path, file_path)?;
Ok(())
}

View File

@@ -0,0 +1,674 @@
use std::{collections::BTreeMap, io::Write};
use serde_derive::{Deserialize, Serialize};
use crate::{
enums,
stationpedia::{self, Page, Stationpedia},
};
pub fn generate_database(
stationpedia: &stationpedia::Stationpedia,
enums: &enums::Enums,
workspace: &std::path::Path,
) -> color_eyre::Result<()> {
let templates = generate_templates(stationpedia)?;
println!("Writing prefab database ...");
let prefabs: BTreeMap<String, ObjectTemplate> = templates
.into_iter()
.map(|obj| (obj.prefab().prefab_name.clone(), obj))
.collect();
let prefabs_by_hash: BTreeMap<i32, String> = prefabs
.iter()
.map(|(key, val)| (val.prefab().prefab_hash, key.clone()))
.collect();
let structures = prefabs
.iter()
.filter_map(|(_, val)| {
use ObjectTemplate::*;
match val {
Structure(_)
| StructureSlots(_)
| StructureLogic(_)
| StructureLogicDevice(_)
| StructureLogicDeviceMemory(_) => Some(val.prefab().prefab_name.clone()),
Item(_) | ItemSlots(_) | ItemLogic(_) | ItemLogicMemory(_) => None,
}
})
.collect();
let items = prefabs
.iter()
.filter_map(|(_, val)| {
use ObjectTemplate::*;
match val {
Structure(_)
| StructureSlots(_)
| StructureLogic(_)
| StructureLogicDevice(_)
| StructureLogicDeviceMemory(_) => None,
Item(_) | ItemSlots(_) | ItemLogic(_) | ItemLogicMemory(_) => {
Some(val.prefab().prefab_name.clone())
}
}
})
.collect();
let logicable_items = prefabs
.iter()
.filter_map(|(_, val)| {
use ObjectTemplate::*;
match val {
Structure(_)
| StructureSlots(_)
| StructureLogic(_)
| StructureLogicDevice(_)
| StructureLogicDeviceMemory(_)
| Item(_)
| ItemSlots(_) => None,
ItemLogic(_) | ItemLogicMemory(_) => Some(val.prefab().prefab_name.clone()),
}
})
.collect();
let devices = prefabs
.iter()
.filter_map(|(_, val)| {
use ObjectTemplate::*;
match val {
Structure(_) | StructureSlots(_) | StructureLogic(_) | Item(_) | ItemSlots(_)
| ItemLogic(_) | ItemLogicMemory(_) => None,
StructureLogicDevice(_) | StructureLogicDeviceMemory(_) => {
Some(val.prefab().prefab_name.clone())
}
}
})
.collect();
let db: ObjectDatabase = ObjectDatabase {
prefabs,
reagents: stationpedia.reagents.clone(),
enums: enums.clone(),
prefabs_by_hash,
structures,
devices,
items,
logicable_items,
};
let data_path = workspace.join("data");
if !data_path.exists() {
std::fs::create_dir(&data_path)?;
}
let database_path = data_path.join("database.json");
let mut database_file = std::io::BufWriter::new(std::fs::File::create(database_path)?);
serde_json::to_writer(&mut database_file, &db)?;
database_file.flush()?;
Ok(())
}
fn generate_templates(pedia: &Stationpedia) -> color_eyre::Result<Vec<ObjectTemplate>> {
println!("Generating templates ...");
let mut templates: Vec<ObjectTemplate> = Vec::new();
for page in pedia.pages.iter() {
let prefab = PrefabInfo {
prefab_name: page.prefab_name.clone(),
prefab_hash: page.prefab_hash,
desc: page.description.clone(),
name: page.title.clone(),
};
// every page should either by a item or a structure
// in theory every device is logicable
// in theory everything with memory is logicable
match page {
Page {
item: Some(item),
structure: None,
logic_info: None,
slot_inserts,
memory: None,
device: None,
transmission_receiver: None,
wireless_logic: None,
circuit_holder: None,
..
} if slot_inserts.is_empty() => {
templates.push(ObjectTemplate::Item(ItemTemplate {
prefab,
item: item.into(),
}));
}
Page {
item: Some(item),
structure: None,
logic_info: None,
slot_inserts,
memory: None,
device: None,
transmission_receiver: None,
wireless_logic: None,
circuit_holder: None,
..
} => {
templates.push(ObjectTemplate::ItemSlots(ItemSlotsTemplate {
prefab,
item: item.into(),
slots: slot_inserts_to_info(slot_inserts),
}));
}
Page {
item: Some(item),
structure: None,
logic_info: Some(logic),
slot_inserts,
memory: None,
device: None,
transmission_receiver,
wireless_logic,
circuit_holder,
..
} => {
let mut logic: LogicInfo = logic.into();
if !page.mode_insert.is_empty() {
logic.modes = Some(mode_inserts_to_info(&page.mode_insert));
}
logic.transmission_receiver = transmission_receiver.unwrap_or(false);
logic.wireless_logic = wireless_logic.unwrap_or(false);
logic.circuit_holder = circuit_holder.unwrap_or(false);
templates.push(ObjectTemplate::ItemLogic(ItemLogicTemplate {
prefab,
item: item.into(),
logic,
slots: slot_inserts_to_info(slot_inserts),
}));
}
Page {
item: Some(item),
structure: None,
logic_info: Some(logic),
slot_inserts,
memory: Some(memory),
device: None,
transmission_receiver,
wireless_logic,
circuit_holder,
..
} => {
let mut logic: LogicInfo = logic.into();
if !page.mode_insert.is_empty() {
logic.modes = Some(mode_inserts_to_info(&page.mode_insert));
}
logic.transmission_receiver = transmission_receiver.unwrap_or(false);
logic.wireless_logic = wireless_logic.unwrap_or(false);
logic.circuit_holder = circuit_holder.unwrap_or(false);
templates.push(ObjectTemplate::ItemLogicMemory(ItemLogicMemoryTemplate {
prefab,
item: item.into(),
logic,
slots: slot_inserts_to_info(slot_inserts),
memory: memory.into(),
}));
}
Page {
item: None,
structure: Some(structure),
slot_inserts,
logic_info: None,
memory: None,
device: None,
transmission_receiver: None,
wireless_logic: None,
circuit_holder: None,
..
} if slot_inserts.is_empty() => {
templates.push(ObjectTemplate::Structure(StructureTemplate {
prefab,
structure: structure.into(),
}));
// println!("Structure")
}
Page {
item: None,
structure: Some(structure),
slot_inserts,
logic_info: None,
memory: None,
device: None,
transmission_receiver: None,
wireless_logic: None,
circuit_holder: None,
..
} => {
templates.push(ObjectTemplate::StructureSlots(StructureSlotsTemplate {
prefab,
structure: structure.into(),
slots: slot_inserts_to_info(slot_inserts),
}));
// println!("Structure")
}
Page {
item: None,
structure: Some(structure),
logic_info: Some(logic),
slot_inserts,
memory: None,
device: None,
transmission_receiver,
wireless_logic,
circuit_holder,
..
} => {
let mut logic: LogicInfo = logic.into();
if !page.mode_insert.is_empty() {
logic.modes = Some(mode_inserts_to_info(&page.mode_insert));
}
logic.transmission_receiver = transmission_receiver.unwrap_or(false);
logic.wireless_logic = wireless_logic.unwrap_or(false);
logic.circuit_holder = circuit_holder.unwrap_or(false);
templates.push(ObjectTemplate::StructureLogic(StructureLogicTemplate {
prefab,
structure: structure.into(),
logic,
slots: slot_inserts_to_info(slot_inserts),
}));
// println!("Structure")
}
Page {
item: None,
structure: Some(structure),
logic_info: Some(logic),
slot_inserts,
memory: None,
device: Some(device),
transmission_receiver,
wireless_logic,
circuit_holder,
..
} => {
let mut logic: LogicInfo = logic.into();
if !page.mode_insert.is_empty() {
logic.modes = Some(mode_inserts_to_info(&page.mode_insert));
}
logic.transmission_receiver = transmission_receiver.unwrap_or(false);
logic.wireless_logic = wireless_logic.unwrap_or(false);
logic.circuit_holder = circuit_holder.unwrap_or(false);
templates.push(ObjectTemplate::StructureLogicDevice(
StructureLogicDeviceTemplate {
prefab,
structure: structure.into(),
logic,
slots: slot_inserts_to_info(slot_inserts),
device: device.into(),
},
));
// println!("Structure")
}
Page {
item: None,
structure: Some(structure),
logic_info: Some(logic),
slot_inserts,
memory: Some(memory),
device: Some(device),
transmission_receiver,
wireless_logic,
circuit_holder,
..
} => {
let mut logic: LogicInfo = logic.into();
if !page.mode_insert.is_empty() {
logic.modes = Some(mode_inserts_to_info(&page.mode_insert));
}
logic.transmission_receiver = transmission_receiver.unwrap_or(false);
logic.wireless_logic = wireless_logic.unwrap_or(false);
logic.circuit_holder = circuit_holder.unwrap_or(false);
templates.push(ObjectTemplate::StructureLogicDeviceMemory(
StructureLogicDeviceMemoryTemplate {
prefab,
structure: structure.into(),
logic,
slots: slot_inserts_to_info(slot_inserts),
device: device.into(),
memory: memory.into(),
},
));
// println!("Structure")
}
_ => panic!(
"Non conforming: {:?} \n\titem: {:?}\n\tstructure: {:?}\n\tlogic_info: {:?}\n\tslot_inserts: {:?}\n\tslot_logic: {:?}\n\tmemory: {:?}\n\tdevice: {:?}",
page.key,
page.item,
page.structure,
page.logic_info,
page.slot_inserts,
page.logic_slot_insert,
page.memory,
page.device,
),
}
}
Ok(templates)
}
fn slot_inserts_to_info(slots: &[stationpedia::SlotInsert]) -> Vec<SlotInfo> {
let mut tmp: Vec<_> = slots.into();
tmp.sort_by(|a, b| a.slot_index.cmp(&b.slot_index));
tmp.iter()
.map(|slot| SlotInfo {
name: slot.slot_name.clone(),
typ: slot.slot_type.clone(),
})
.collect()
}
fn mode_inserts_to_info(modes: &[stationpedia::ModeInsert]) -> BTreeMap<u32, String> {
modes
.iter()
.map(|mode| (mode.logic_access_types, mode.logic_name.clone()))
.collect()
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct ObjectDatabase {
pub prefabs: BTreeMap<String, ObjectTemplate>,
pub reagents: BTreeMap<String, stationpedia::Reagent>,
pub enums: enums::Enums,
pub prefabs_by_hash: BTreeMap<i32, String>,
pub structures: Vec<String>,
pub devices: Vec<String>,
pub items: Vec<String>,
pub logicable_items: Vec<String>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ObjectTemplate {
Structure(StructureTemplate),
StructureSlots(StructureSlotsTemplate),
StructureLogic(StructureLogicTemplate),
StructureLogicDevice(StructureLogicDeviceTemplate),
StructureLogicDeviceMemory(StructureLogicDeviceMemoryTemplate),
Item(ItemTemplate),
ItemSlots(ItemSlotsTemplate),
ItemLogic(ItemLogicTemplate),
ItemLogicMemory(ItemLogicMemoryTemplate),
}
impl ObjectTemplate {
fn prefab(&self) -> &PrefabInfo {
use ObjectTemplate::*;
match self {
Structure(s) => &s.prefab,
StructureSlots(s) => &s.prefab,
StructureLogic(s) => &s.prefab,
StructureLogicDevice(s) => &s.prefab,
StructureLogicDeviceMemory(s) => &s.prefab,
Item(i) => &i.prefab,
ItemSlots(i) => &i.prefab,
ItemLogic(i) => &i.prefab,
ItemLogicMemory(i) => &i.prefab,
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct PrefabInfo {
pub prefab_name: String,
pub prefab_hash: i32,
pub desc: String,
pub name: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct SlotInfo {
pub name: String,
pub typ: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct LogicInfo {
pub logic_slot_types: BTreeMap<u32, stationpedia::LogicSlotTypes>,
pub logic_types: stationpedia::LogicTypes,
#[serde(skip_serializing_if = "Option::is_none")]
pub modes: Option<BTreeMap<u32, String>>,
pub transmission_receiver: bool,
pub wireless_logic: bool,
pub circuit_holder: bool,
}
impl From<&stationpedia::LogicInfo> for LogicInfo {
fn from(value: &stationpedia::LogicInfo) -> Self {
LogicInfo {
logic_slot_types: value.logic_slot_types.clone(),
logic_types: value.logic_types.clone(),
modes: None,
transmission_receiver: false,
wireless_logic: false,
circuit_holder: false,
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct ItemInfo {
pub consumable: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub filter_type: Option<String>,
pub ingredient: bool,
pub max_quantity: f64,
#[serde(skip_serializing_if = "Option::is_none")]
pub reagents: Option<BTreeMap<String, f64>>,
pub slot_class: String,
pub sorting_class: String,
}
impl From<&stationpedia::Item> for ItemInfo {
fn from(item: &stationpedia::Item) -> Self {
ItemInfo {
consumable: item.consumable.unwrap_or(false),
filter_type: item.filter_type.clone(),
ingredient: item.ingredient.unwrap_or(false),
max_quantity: item.max_quantity.unwrap_or(1.0),
reagents: item
.reagents
.as_ref()
.map(|map| map.iter().map(|(key, val)| (key.clone(), *val)).collect()),
slot_class: item.slot_class.clone(),
sorting_class: item.sorting_class.clone(),
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct DeviceInfo {
pub connection_list: Vec<(String, String)>,
#[serde(skip_serializing_if = "Option::is_none")]
pub device_pins_length: Option<i64>,
pub has_activate_state: bool,
pub has_atmosphere: bool,
pub has_color_state: bool,
pub has_lock_state: bool,
pub has_mode_state: bool,
pub has_on_off_state: bool,
pub has_open_state: bool,
pub has_reagents: bool,
}
impl From<&stationpedia::Device> for DeviceInfo {
fn from(value: &stationpedia::Device) -> Self {
DeviceInfo {
connection_list: value.connection_list.clone(),
device_pins_length: value.devices_length,
has_activate_state: value.has_activate_state,
has_atmosphere: value.has_atmosphere,
has_color_state: value.has_color_state,
has_lock_state: value.has_lock_state,
has_mode_state: value.has_mode_state,
has_on_off_state: value.has_on_off_state,
has_open_state: value.has_open_state,
has_reagents: value.has_reagents,
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct StructureInfo {
pub small_grid: bool,
}
impl From<&stationpedia::Structure> for StructureInfo {
fn from(value: &stationpedia::Structure) -> Self {
StructureInfo {
small_grid: value.small_grid,
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct Instruction {
pub description: String,
pub typ: String,
pub value: i64,
}
impl From<&stationpedia::Instruction> for Instruction {
fn from(value: &stationpedia::Instruction) -> Self {
Instruction {
description: value.description.clone(),
typ: value.type_.clone(),
value: value.value,
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct MemoryInfo {
#[serde(skip_serializing_if = "Option::is_none")]
pub instructions: Option<BTreeMap<String, Instruction>>,
pub memory_access: String,
pub memory_size: i64,
}
impl From<&stationpedia::Memory> for MemoryInfo {
fn from(value: &stationpedia::Memory) -> Self {
MemoryInfo {
instructions: value.instructions.as_ref().map(|insts| {
insts
.iter()
.map(|(key, value)| (key.clone(), value.into()))
.collect()
}),
memory_access: value.memory_access.clone(),
memory_size: value.memory_size,
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct StructureTemplate {
pub prefab: PrefabInfo,
pub structure: StructureInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct StructureSlotsTemplate {
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct StructureLogicTemplate {
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct StructureLogicDeviceTemplate {
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
pub device: DeviceInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct StructureLogicDeviceMemoryTemplate {
pub prefab: PrefabInfo,
pub structure: StructureInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
pub device: DeviceInfo,
pub memory: MemoryInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct ItemTemplate {
pub prefab: PrefabInfo,
pub item: ItemInfo,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct ItemSlotsTemplate {
pub prefab: PrefabInfo,
pub item: ItemInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct ItemLogicTemplate {
pub prefab: PrefabInfo,
pub item: ItemInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct ItemLogicMemoryTemplate {
pub prefab: PrefabInfo,
pub item: ItemInfo,
pub logic: LogicInfo,
pub slots: Vec<SlotInfo>,
pub memory: MemoryInfo,
}

397
xtask/src/generate/enums.rs Normal file
View File

@@ -0,0 +1,397 @@
use convert_case::{Case, Casing};
use std::collections::BTreeMap;
use std::{
fmt::Display,
io::{BufWriter, Write},
path::PathBuf,
str::FromStr,
};
pub fn generate_enums(
stationpedia: &crate::stationpedia::Stationpedia,
enums: &crate::enums::Enums,
workspace: &std::path::Path,
) -> color_eyre::Result<Vec<PathBuf>> {
println!("Writing Enum Listings ...");
let enums_path = workspace
.join("ic10emu")
.join("src")
.join("vm")
.join("enums");
if !enums_path.exists() {
std::fs::create_dir(&enums_path)?;
}
let mut writer =
std::io::BufWriter::new(std::fs::File::create(enums_path.join("script_enums.rs"))?);
write_repr_enum_use_header(&mut writer)?;
for enm in enums.script_enums.values() {
write_enum_listing(&mut writer, enm)?;
}
let mut writer =
std::io::BufWriter::new(std::fs::File::create(enums_path.join("basic_enums.rs"))?);
write_repr_enum_use_header(&mut writer)?;
for enm in enums.basic_enums.values() {
write_enum_listing(&mut writer, enm)?;
}
write_enum_aggragate_mod(&mut writer, &enums.basic_enums)?;
let mut writer = std::io::BufWriter::new(std::fs::File::create(enums_path.join("prefabs.rs"))?);
write_repr_enum_use_header(&mut writer)?;
let prefabs = stationpedia
.pages
.iter()
.map(|page| {
let variant = ReprEnumVariant {
value: page.prefab_hash,
deprecated: false,
props: vec![
("name".to_owned(), page.title.clone()),
("desc".to_owned(), page.description.clone()),
],
};
(page.prefab_name.clone(), variant)
})
.collect::<Vec<_>>();
write_repr_enum(&mut writer, "StationpediaPrefab", &prefabs, true)?;
Ok(vec![
enums_path.join("script_enums.rs"),
enums_path.join("basic_enums.rs"),
enums_path.join("prefabs.rs"),
])
}
fn write_enum_aggragate_mod<T: std::io::Write>(
writer: &mut BufWriter<T>,
enums: &BTreeMap<String, crate::enums::EnumListing>,
) -> color_eyre::Result<()> {
let variant_lines = enums
.iter()
.map(|(name, listing)| {
let name = if name.is_empty() || name == "_unnamed" {
"Unnamed"
} else {
name
};
format!(
" {}({}),",
name.to_case(Case::Pascal),
listing.enum_name.to_case(Case::Pascal)
)
})
.collect::<Vec<_>>()
.join("\n");
let value_arms = enums
.keys()
.map(|name| {
let variant_name = (if name.is_empty() || name == "_unnamed" {
"Unnamed"
} else {
name
})
.to_case(Case::Pascal);
format!(" Self::{variant_name}(enm) => *enm as u32,",)
})
.collect::<Vec<_>>()
.join("\n");
let get_str_arms = enums
.keys()
.map(|name| {
let variant_name = (if name.is_empty() || name == "_unnamed" {
"Unnamed"
} else {
name
})
.to_case(Case::Pascal);
format!(" Self::{variant_name}(enm) => enm.get_str(prop),",)
})
.collect::<Vec<_>>()
.join("\n");
let iter_chain = enums
.iter()
.enumerate()
.map(|(index, (name, listing))| {
let variant_name = (if name.is_empty() || name == "_unnamed" {
"Unnamed"
} else {
name
})
.to_case(Case::Pascal);
let enum_name = listing.enum_name.to_case(Case::Pascal);
if index == 0 {
format!("{enum_name}::iter().map(|enm| Self::{variant_name}(enm))")
} else {
format!(".chain({enum_name}::iter().map(|enm| Self::{variant_name}(enm)))")
}
})
.collect::<Vec<_>>()
.join("\n");
write!(
writer,
"pub enum BasicEnum {{\n\
{variant_lines}
}}\n\
impl BasicEnum {{\n \
pub fn get_value(&self) -> u32 {{\n \
match self {{\n \
{value_arms}\n \
}}\n \
}}\n\
pub fn get_str(&self, prop: &str) -> Option<&'static str> {{\n \
match self {{\n \
{get_str_arms}\n \
}}\n \
}}\n\
pub fn iter() -> impl std::iter::Iterator<Item = Self> {{\n \
use strum::IntoEnumIterator;\n \
{iter_chain}\n \
}}
}}\n\
"
)?;
let arms = enums
.iter()
.flat_map(|(name, listing)| {
let variant_name = (if name.is_empty() || name == "_unnamed" {
"Unnamed"
} else {
name
})
.to_case(Case::Pascal);
let name = if name == "_unnamed" {
"".to_string()
} else {
name.clone()
};
let enum_name = listing.enum_name.to_case(Case::Pascal);
listing.values.keys().map(move |variant| {
let sep = if name.is_empty() { "" } else { "." };
let pat = format!("{name}{sep}{variant}").to_lowercase();
let variant = variant.to_case(Case::Pascal);
format!("\"{pat}\" => Ok(Self::{variant_name}({enum_name}::{variant})),")
})
})
.collect::<Vec<_>>()
.join("\n ");
write!(
writer,
"\
impl std::str::FromStr for BasicEnum {{\n \
type Err = crate::errors::ParseError;\n \
fn from_str(s: &str) -> Result<Self, Self::Err> {{\n \
let end = s.len();\n \
match s {{\n \
{arms}\n \
_ => Err(crate::errors::ParseError{{ line: 0, start: 0, end, msg: format!(\"Unknown enum '{{}}'\", s) }})\n \
}}\n \
}}\n\
}}\
"
)?;
let display_arms = enums
.keys()
.map(|name| {
let variant_name = (if name.is_empty() || name == "_unnamed" {
"Unnamed"
} else {
name
})
.to_case(Case::Pascal);
let name = if name == "_unnamed" {
"".to_string()
} else {
name.clone()
};
let sep = if name.is_empty() || name == "_unnamed" {
""
} else {
"."
};
let pat = format!("{name}{sep}{{}}");
format!(" Self::{variant_name}(enm) => write!(f, \"{pat}\", enm),",)
})
.collect::<Vec<_>>()
.join("\n ");
write!(
writer,
"\
impl std::fmt::Display for BasicEnum {{\n \
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {{\n \
match self {{\n \
{display_arms}\n \
}}\n \
}}\n\
}}\
"
)?;
Ok(())
}
pub fn write_enum_listing<T: std::io::Write>(
writer: &mut BufWriter<T>,
enm: &crate::enums::EnumListing,
) -> color_eyre::Result<()> {
let max = enm
.values
.values()
.map(|var| var.value)
.max()
.expect("enum should have max value");
let min = enm
.values
.values()
.map(|var| var.value)
.min()
.expect("enum should have min value");
if max < u8::MAX as i64 && min >= u8::MIN as i64 {
let variants: Vec<_> = enm
.values
.iter()
.map(|(n, var)| {
let variant = ReprEnumVariant {
value: var.value as u8,
deprecated: var.deprecated,
props: vec![("docs".to_owned(), var.description.to_owned())],
};
(n.clone(), variant)
})
.collect();
write_repr_enum(
writer,
&enm.enum_name.to_case(Case::Pascal),
&variants,
true,
)?;
} else if max < u16::MAX as i64 && min >= u16::MIN as i64 {
let variants: Vec<_> = enm
.values
.iter()
.map(|(n, var)| {
let variant = ReprEnumVariant {
value: var.value as u16,
deprecated: var.deprecated,
props: vec![("docs".to_owned(), var.description.to_owned())],
};
(n.clone(), variant)
})
.collect();
write_repr_enum(writer, &enm.enum_name, &variants, true)?;
} else if max < u32::MAX as i64 && min >= u32::MIN as i64 {
let variants: Vec<_> = enm
.values
.iter()
.map(|(n, var)| {
let variant = ReprEnumVariant {
value: var.value as u32,
deprecated: var.deprecated,
props: vec![("docs".to_owned(), var.description.to_owned())],
};
(n.clone(), variant)
})
.collect();
write_repr_enum(writer, &enm.enum_name, &variants, true)?;
} else if max < i32::MAX as i64 && min >= i32::MIN as i64 {
let variants: Vec<_> = enm
.values
.iter()
.map(|(n, var)| {
let variant = ReprEnumVariant {
value: var.value as i32,
deprecated: var.deprecated,
props: vec![("docs".to_owned(), var.description.to_owned())],
};
(n.clone(), variant)
})
.collect();
write_repr_enum(writer, &enm.enum_name, &variants, true)?;
} else {
let variants: Vec<_> = enm
.values
.iter()
.map(|(n, var)| {
let variant = ReprEnumVariant {
value: var.value as i32,
deprecated: var.deprecated,
props: vec![("docs".to_owned(), var.description.to_owned())],
};
(n.clone(), variant)
})
.collect();
write_repr_enum(writer, &enm.enum_name, &variants, true)?;
}
Ok(())
}
struct ReprEnumVariant<P>
where
P: Display + FromStr,
{
pub value: P,
pub deprecated: bool,
pub props: Vec<(String, String)>,
}
fn write_repr_enum_use_header<T: std::io::Write>(
writer: &mut BufWriter<T>,
) -> color_eyre::Result<()> {
write!(
writer,
"use serde::{{Deserialize, Serialize}};\n\
use strum::{{\n \
AsRefStr, Display, EnumIter, EnumProperty, EnumString, FromRepr,\n\
}};\n"
)?;
Ok(())
}
fn write_repr_enum<'a, T: std::io::Write, I, P>(
writer: &mut BufWriter<T>,
name: &str,
variants: I,
use_phf: bool,
) -> color_eyre::Result<()>
where
P: Display + FromStr + 'a,
I: IntoIterator<Item = &'a (String, ReprEnumVariant<P>)>,
{
let additional_strum = if use_phf { "#[strum(use_phf)]\n" } else { "" };
let repr = std::any::type_name::<P>();
write!(
writer,
"#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, EnumString, AsRefStr, EnumProperty, EnumIter, FromRepr, Serialize, Deserialize)]\n\
{additional_strum}\
#[repr({repr})]\n\
pub enum {name} {{\n"
)?;
for (name, variant) in variants {
let variant_name = name.replace('.', "").to_case(Case::Pascal);
let serialize = vec![name.clone()];
let serialize_str = serialize
.into_iter()
.map(|s| format!("serialize = \"{s}\""))
.collect::<Vec<String>>()
.join(", ");
let mut props = Vec::new();
if variant.deprecated {
props.push("deprecated = \"true\"".to_owned());
}
for (prop_name, prop_val) in &variant.props {
props.push(format!("{prop_name} = r#\"{prop_val}\"#"));
}
let val = &variant.value;
props.push(format!("value = \"{val}\""));
let props_str = if !props.is_empty() {
format!(", props( {} )", props.join(", "))
} else {
"".to_owned()
};
writeln!(
writer,
" #[strum({serialize_str}{props_str})] {variant_name} = {val}{repr},"
)?;
}
writeln!(writer, "}}")?;
Ok(())
}

View File

@@ -0,0 +1,216 @@
use convert_case::{Case, Casing};
use std::{collections::BTreeMap, path::PathBuf};
use crate::{generate::utils, stationpedia};
pub fn generate_instructions(
stationpedia: &stationpedia::Stationpedia,
workspace: &std::path::Path,
) -> color_eyre::Result<Vec<PathBuf>> {
let instructions_path = workspace
.join("ic10emu")
.join("src")
.join("vm")
.join("instructions");
if !instructions_path.exists() {
std::fs::create_dir(&instructions_path)?;
}
let mut writer =
std::io::BufWriter::new(std::fs::File::create(instructions_path.join("enums.rs"))?);
write_instructions_enum(&mut writer, &stationpedia.script_commands)?;
let mut writer =
std::io::BufWriter::new(std::fs::File::create(instructions_path.join("traits.rs"))?);
write_instruction_interface_trait(&mut writer)?;
for (typ, info) in &stationpedia.script_commands {
write_instruction_trait(&mut writer, (typ, info))?;
}
write_instruction_super_trait(&mut writer, &stationpedia.script_commands)?;
Ok(vec![
instructions_path.join("enums.rs"),
instructions_path.join("traits.rs"),
])
}
fn write_instructions_enum<T: std::io::Write>(
writer: &mut T,
instructions: &BTreeMap<String, stationpedia::Command>,
) -> color_eyre::Result<()> {
println!("Writing instruction Listings ...");
let mut instructions = instructions.clone();
for (_, ref mut info) in instructions.iter_mut() {
info.example = utils::strip_color(&info.example);
}
write!(
writer,
"use serde::{{Deserialize, Serialize}};\n\
use strum::{{\n \
Display, EnumIter, EnumProperty, EnumString, FromRepr,\n\
}};\n
use crate::vm::object::traits::Programmable;\n\
use crate::vm::instructions::traits::*;\n\
"
)?;
write!(
writer,
"#[derive(Debug, Display, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Deserialize)]\n\
#[derive(EnumIter, EnumString, EnumProperty, FromRepr)]\n\
#[strum(use_phf, serialize_all = \"lowercase\")]\n\
#[serde(rename_all = \"lowercase\")]\n\
pub enum InstructionOp {{\n\
"
)?;
writeln!(writer, " Nop,")?;
for (name, info) in &instructions {
let props_str = format!(
"props( example = \"{}\", desc = \"{}\", operands = \"{}\" )",
&info.example,
&info.desc,
count_operands(&info.example)
);
writeln!(
writer,
" #[strum({props_str})] {},",
name.to_case(Case::Pascal)
)?;
}
writeln!(writer, "}}")?;
write!(
writer,
"impl InstructionOp {{\n \
pub fn num_operands(&self) -> usize {{\n \
self.get_str(\"operands\").expect(\"instruction without operand property\").parse::<usize>().expect(\"invalid instruction operand property\")\n \
}}\n\
\n \
pub fn execute<T>(\n \
&self,\n \
ic: &mut T,\n \
vm: &crate::vm::VM,\n \
operands: &[crate::vm::instructions::operands::Operand],\n \
) -> Result<(), crate::errors::ICError>\n \
where\n \
T: Programmable,\n\
{{\n \
let num_operands = self.num_operands();\n \
if operands.len() != num_operands {{\n \
return Err(crate::errors::ICError::mismatch_operands(operands.len(), num_operands as u32));\n \
}}\n \
match self {{\n \
Self::Nop => Ok(()),\n \
"
)?;
for (name, info) in instructions {
let num_operands = count_operands(&info.example);
let operands = (0..num_operands)
.map(|i| format!("&operands[{}]", i))
.collect::<Vec<_>>()
.join(", ");
let trait_name = name.to_case(Case::Pascal);
writeln!(
writer,
" Self::{trait_name} => ic.execute_{name}(vm, {operands}),",
)?;
}
write!(
writer,
" }}\
}}\n\
}}
"
)?;
Ok(())
}
fn write_instruction_trait<T: std::io::Write>(
writer: &mut T,
instruction: (&str, &stationpedia::Command),
) -> color_eyre::Result<()> {
let (name, info) = instruction;
let trait_name = format!("{}Instruction", name.to_case(Case::Pascal));
let operands = operand_names(&info.example)
.iter()
.map(|name| {
format!(
"{}: &crate::vm::instructions::operands::Operand",
name.to_case(Case::Snake)
)
})
.collect::<Vec<_>>()
.join(", ");
let example = utils::strip_color(&info.example);
write!(
writer,
"pub trait {trait_name}: IntegratedCircuit {{\n \
/// {example} \n \
fn execute_{name}(&mut self, vm: &crate::vm::VM, {operands}) -> Result<(), crate::errors::ICError>;\n\
}}"
)?;
Ok(())
}
fn count_operands(example: &str) -> usize {
example.split(' ').count() - 1
}
fn operand_names(example: &str) -> Vec<String> {
utils::strip_color(example)
.split(' ')
.skip(1)
.map(|name| name.split(['?', '(']).next().unwrap().to_string())
.collect()
}
fn write_instruction_interface_trait<T: std::io::Write>(writer: &mut T) -> color_eyre::Result<()> {
write!(
writer,
"\
use std::collections::BTreeMap;\n\
use crate::vm::object::traits::{{Logicable, MemoryWritable, SourceCode}};\n\
use crate::errors::ICError; \n\
pub trait IntegratedCircuit: Logicable + MemoryWritable + SourceCode {{\n \
fn get_instruciton_pointer(&self) -> usize;\n \
fn set_next_instruction(&mut self, next_instruction: usize);\n \
fn reset(&mut self);\n \
fn get_real_target(&self, indirection: u32, target: u32) -> Result<f64, ICError>;\n \
fn get_register(&self, indirection: u32, target: u32) -> Result<f64, ICError>;\n \
fn set_register(&mut self, indirection: u32, target: u32, val: f64) -> Result<f64, ICError>;\n \
fn set_return_address(&mut self, addr: f64);\n \
fn push_stack(&mut self, val: f64) -> Result<f64, ICError>;\n \
fn pop_stack(&mut self) -> Result<f64, ICError>;\n \
fn peek_stack(&self) -> Result<f64, ICError>;\n \
fn get_aliases(&self) -> &BTreeMap<String, crate::vm::instructions::operands::Operand>;\n \
fn get_defines(&self) -> &BTreeMap<String, f64>;\n \
fn get_lables(&self) -> &BTreeMap<String, u32>;\n\
}}\n\
"
)?;
Ok(())
}
fn write_instruction_super_trait<T: std::io::Write>(
writer: &mut T,
instructions: &BTreeMap<String, stationpedia::Command>,
) -> color_eyre::Result<()> {
let traits = instructions
.keys()
.map(|name| format!("{}Instruction", name.to_case(Case::Pascal)))
.collect::<Vec<_>>()
.join(" + ");
write!(
writer,
"\
pub trait ICInstructable: {traits} {{}}\n\
impl <T> ICInstructable for T where T: {traits} {{}}
"
)?;
Ok(())
}

View File

@@ -0,0 +1,60 @@
use onig::{Captures, Regex, RegexOptions, Syntax};
pub fn strip_color(s: &str) -> String {
let color_regex = Regex::with_options(
r#"<color=(#?\w+)>((:?(?!<color=(?:#?\w+)>).)+?)</color>"#,
RegexOptions::REGEX_OPTION_MULTILINE | RegexOptions::REGEX_OPTION_CAPTURE_GROUP,
Syntax::default(),
)
.unwrap();
let mut new = s.to_owned();
loop {
new = color_regex.replace_all(&new, |caps: &Captures| caps.at(2).unwrap_or("").to_string());
if !color_regex.is_match(&new) {
break;
}
}
new
}
#[allow(dead_code)]
pub fn color_to_heml(s: &str) -> String {
let color_regex = Regex::with_options(
r#"<color=(#?\w+)>((:?(?!<color=(?:#?\w+)>).)+?)</color>"#,
RegexOptions::REGEX_OPTION_MULTILINE | RegexOptions::REGEX_OPTION_CAPTURE_GROUP,
Syntax::default(),
)
.unwrap();
let mut new = s.to_owned();
loop {
new = color_regex.replace_all(&new, |caps: &Captures| {
format!(
r#"<div style="color: {};">{}</div>"#,
caps.at(1).unwrap_or(""),
caps.at(2).unwrap_or("")
)
});
if !color_regex.is_match(&new) {
break;
}
}
new
}
#[allow(dead_code)]
pub fn strip_link(s: &str) -> String {
let link_regex = Regex::with_options(
r#"<link=(\w+)>(.+?)</link>"#,
RegexOptions::REGEX_OPTION_MULTILINE | RegexOptions::REGEX_OPTION_CAPTURE_GROUP,
Syntax::default(),
)
.unwrap();
let mut new = s.to_owned();
loop {
new = link_regex.replace_all(&new, |caps: &Captures| caps.at(2).unwrap_or("").to_string());
if !link_regex.is_match(&new) {
break;
}
}
new
}

View File

@@ -2,6 +2,10 @@ use std::process::{Command, ExitStatus};
use clap::{Parser, Subcommand};
mod enums;
mod generate;
mod stationpedia;
/// Helper program to start ic10emu and website.
///
/// Can be invoked as `cargo xtask <command>`
@@ -44,11 +48,19 @@ enum Task {
Deploy {},
/// bump the cargo.toml and package,json versions
Version {
#[arg(last = true, default_value = "patch", value_parser = clap::builder::PossibleValuesParser::new(VALID_VERSION_TYPE))]
#[arg(default_value = "patch", value_parser = clap::builder::PossibleValuesParser::new(VALID_VERSION_TYPE))]
version: String,
},
/// update changelog
Changelog {},
Generate {
#[arg()]
/// Path to Stationeers installation. Used to locate "Stationpedia.json" and "Enums.json"
/// generated by https://github.com/Ryex/StationeersStationpediaExtractor
/// Otherwise looks for both files in `<workspace>` or `<workspace>/data`.
/// Can also point directly at a folder containing the two files.
path: Option<std::ffi::OsString>,
},
}
#[derive(thiserror::Error)]
@@ -57,6 +69,8 @@ enum Error {
BuildFailed(String, String, std::process::ExitStatus),
#[error("failed to run command `{0}`")]
Command(String, #[source] std::io::Error),
#[error("can not find `Stationpedia.json` and/or `Enums.json` at `{0}`")]
BadStationeresPath(std::path::PathBuf),
}
impl std::fmt::Debug for Error {
@@ -75,7 +89,8 @@ impl std::fmt::Debug for Error {
}
const VERSION: Option<&str> = option_env!("CARGO_PKG_VERSION");
fn main() -> Result<(), Error> {
fn main() -> color_eyre::Result<()> {
color_eyre::install()?;
let args = Args::parse();
let workspace = {
let out = Command::new("cargo")
@@ -132,21 +147,78 @@ fn main() -> Result<(), Error> {
cmd.args(["version", &version]).status().map_err(|e| {
Error::Command(format!("{}", cmd.get_program().to_string_lossy()), e)
})?;
},
Task::Changelog { } => {
}
Task::Changelog {} => {
let mut cmd = Command::new("git-changelog");
cmd.current_dir(&workspace);
cmd.args([
"-io", "CHANGELOG.md",
"-t", "path:CHANGELOG.md.jinja",
"-c", "conventional",
"--bump", VERSION.unwrap_or("auto"),
"-io",
"CHANGELOG.md",
"-t",
"path:CHANGELOG.md.jinja",
"-c",
"conventional",
"--bump",
VERSION.unwrap_or("auto"),
"--parse-refs",
"--trailers"
]).status().map_err(|e| {
Error::Command(format!("{}", cmd.get_program().to_string_lossy()), e)
})?;
},
"--trailers",
])
.status()
.map_err(|e| Error::Command(format!("{}", cmd.get_program().to_string_lossy()), e))?;
}
Task::Generate { path } => {
let path = match path {
Some(path) => {
let mut path = std::path::PathBuf::from(path);
if path.exists()
&& path
.parent()
.and_then(|p| p.file_name())
.is_some_and(|p| p == "Stationeers")
&& path.file_name().is_some_and(|name| {
(std::env::consts::OS == "windows" && name == "rocketstation.exe")
|| (name == "rocketstation")
|| (name == "rocketstation_Data")
})
{
path = path.parent().unwrap().to_path_buf();
}
if path.is_dir()
&& path.file_name().is_some_and(|name| name == "Stationeers")
&& path.join("Stationpedia").join("Stationpedia.json").exists()
{
path = path.join("Stationpedia");
}
if path.is_file()
&& path
.file_name()
.is_some_and(|name| name == "Stationpedia.json")
{
path = path.parent().unwrap().to_path_buf();
}
path
}
None => {
let mut path = workspace.clone();
if path.join("data").join("Stationpedia.json").exists()
&& path.join("data").join("Enums.json").exists()
{
path = path.join("data")
}
path
}
};
if path.is_dir()
&& path.join("Stationpedia.json").exists()
&& path.join("Enums.json").exists()
{
generate::generate(&path, &workspace)?;
} else {
return Err(Error::BadStationeresPath(path).into());
}
}
}
Ok(())
}

346
xtask/src/stationpedia.rs Normal file
View File

@@ -0,0 +1,346 @@
use serde_derive::{Deserialize, Serialize};
use serde_with::{serde_as, DisplayFromStr};
use std::collections::BTreeMap;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename = "Stationpedia", deny_unknown_fields)]
pub struct Stationpedia {
pub pages: Vec<Page>,
pub reagents: BTreeMap<String, Reagent>,
#[serde(rename = "scriptCommands")]
pub script_commands: BTreeMap<String, Command>,
}
#[allow(dead_code)]
impl Stationpedia {
pub fn lookup_prefab_name(&self, prefab_name: &'_ str) -> Option<&Page> {
self.pages.iter().find(|p| p.prefab_name == prefab_name)
}
pub fn lookup_key(&self, key: &str) -> Option<&Page> {
self.pages.iter().find(|p| p.key == key)
}
pub fn lookup_hash(&self, hash: i32) -> Option<&Page> {
self.pages.iter().find(|p| p.prefab_hash == hash)
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Reagent {
#[serde(rename = "Hash")]
pub hash: i64,
#[serde(rename = "Unit")]
pub unit: String,
#[serde(rename = "Sources")]
pub sources: Option<BTreeMap<String, f64>>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Command {
pub desc: String,
pub example: String,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Page {
#[serde(rename = "ConnectionInsert")]
pub connection_insert: Vec<ConnectionInsert>,
#[serde(rename = "ConstructedByKits")]
pub constructs: Vec<Constructs>,
#[serde(rename = "Description")]
pub description: String,
#[serde(rename = "Device")]
pub device: Option<Device>,
/// the item , if none then deprecated
#[serde(rename = "Item")]
pub item: Option<Item>,
#[serde(rename = "Structure")]
pub structure: Option<Structure>,
#[serde(rename = "Key")]
pub key: String,
#[serde(rename = "LogicInfo")]
pub logic_info: Option<LogicInfo>,
#[serde(rename = "LogicInsert")]
pub logic_insert: Vec<LogicInsert>,
#[serde(rename = "LogicSlotInsert")]
pub logic_slot_insert: Vec<LogicSlotInsert>,
#[serde(rename = "Memory")]
pub memory: Option<Memory>,
#[serde(rename = "ModeInsert")]
pub mode_insert: Vec<ModeInsert>,
#[serde(rename = "PrefabHash")]
pub prefab_hash: i32,
#[serde(rename = "PrefabName")]
pub prefab_name: String,
#[serde(rename = "SlotInserts")]
pub slot_inserts: Vec<SlotInsert>,
#[serde(rename = "Title")]
pub title: String,
#[serde(rename = "TransmissionReceiver")]
pub transmission_receiver: Option<bool>,
#[serde(rename = "WirelessLogic")]
pub wireless_logic: Option<bool>,
#[serde(rename = "CircuitHolder")]
pub circuit_holder: Option<bool>,
#[serde(rename = "BasePowerDraw")]
pub base_power_draw: Option<String>,
#[serde(rename = "MaxPressure")]
pub max_pressure: Option<String>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Constructs {
#[serde(rename = "NameOfThing")]
pub name_of_thing: String,
#[serde(rename = "PageLink")]
pub page_link: String,
#[serde(rename = "PrefabHash")]
pub prefab_hash: i32,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Structure {
#[serde(rename = "SmallGrid")]
pub small_grid: bool,
#[serde(rename = "BuildStates")]
pub build_states: BuildStates,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct BuildStates(pub Vec<BuildState>);
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct BuildState {
#[serde(rename = "Tool")]
pub tool: Option<Vec<Tool>>,
#[serde(rename = "ToolExit")]
pub tool_exit: Option<Vec<Tool>>,
#[serde(rename = "CanManufacture", default)]
pub can_manufacture: bool,
#[serde(rename = "MachineTier")]
pub machine_tier: Option<MachineTier>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub enum MachineTier {
Undefined,
TierOne,
TierTwo,
TierThree,
Max,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Tool {
#[serde(rename = "IsTool", default)]
pub is_tool: bool,
#[serde(rename = "PrefabName")]
pub prefab_name: String,
#[serde(rename = "Quantity")]
pub quantity: Option<i64>,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct SlotInsert {
#[serde(rename = "SlotIndex")]
#[serde_as(as = "DisplayFromStr")]
pub slot_index: u32,
#[serde(rename = "SlotName")]
pub slot_name: String,
#[serde(rename = "SlotType")]
pub slot_type: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct LogicInsert {
#[serde(rename = "LogicAccessTypes")]
pub logic_access_types: String,
#[serde(rename = "LogicName")]
pub logic_name: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct LogicSlotInsert {
#[serde(rename = "LogicAccessTypes")]
pub logic_access_types: String,
#[serde(rename = "LogicName")]
pub logic_name: String,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ModeInsert {
#[serde(rename = "LogicAccessTypes")]
#[serde_as(as = "DisplayFromStr")]
pub logic_access_types: u32,
#[serde(rename = "LogicName")]
pub logic_name: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ConnectionInsert {
#[serde(rename = "LogicAccessTypes")]
pub logic_access_types: String,
#[serde(rename = "LogicName")]
pub logic_name: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct LogicInfo {
#[serde(rename = "LogicSlotTypes")]
pub logic_slot_types: BTreeMap<u32, LogicSlotTypes>,
#[serde(rename = "LogicTypes")]
pub logic_types: LogicTypes,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct LogicSlotTypes {
#[serde(flatten)]
pub slot_types: BTreeMap<String, String>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct LogicTypes {
#[serde(flatten)]
pub types: BTreeMap<String, String>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Memory {
#[serde(rename = "Instructions")]
pub instructions: Option<BTreeMap<String, Instruction>>,
#[serde(rename = "MemoryAccess")]
pub memory_access: String,
#[serde(rename = "MemorySize")]
pub memory_size: i64,
#[serde(rename = "MemorySizeReadable")]
pub memory_size_readable: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Instruction {
#[serde(rename = "Description")]
pub description: String,
#[serde(rename = "Type")]
pub type_: String,
#[serde(rename = "Value")]
pub value: i64,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Item {
#[serde(rename = "Consumable")]
pub consumable: Option<bool>,
#[serde(rename = "FilterType")]
pub filter_type: Option<String>,
#[serde(rename = "Ingredient")]
pub ingredient: Option<bool>,
#[serde(rename = "MaxQuantity")]
pub max_quantity: Option<f64>,
#[serde(rename = "Reagents")]
pub reagents: Option<indexmap::IndexMap<String, f64>>,
#[serde(rename = "SlotClass")]
pub slot_class: String,
#[serde(rename = "SortingClass")]
pub sorting_class: String,
#[serde(rename = "Recipes", default)]
pub recipes: Vec<Recipe>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Recipe {
#[serde(rename = "CreatorPrefabName")]
pub creator_prefab_name: String,
#[serde(rename = "TierName")]
pub tier_name: String,
#[serde(rename = "Time")]
pub time: f64,
#[serde(rename = "Energy")]
pub energy: f64,
#[serde(rename = "Temperature")]
pub temperature: RecipeTemperature,
#[serde(rename = "Pressure")]
pub pressure: RecipePressure,
#[serde(rename = "RequiredMix")]
pub required_mix: RecipeGasMix,
#[serde(rename = "CountTypes")]
pub count_types: i64,
#[serde(flatten)]
pub reagents: indexmap::IndexMap<String, f64>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RecipeTemperature {
#[serde(rename = "Start")]
pub start: f64,
#[serde(rename = "Stop")]
pub stop: f64,
#[serde(rename = "IsValid")]
pub is_valid: bool,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RecipePressure {
#[serde(rename = "Start")]
pub start: f64,
#[serde(rename = "Stop")]
pub stop: f64,
#[serde(rename = "IsValid")]
pub is_valid: bool,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct RecipeGasMix {
#[serde(rename = "Rule")]
pub rule: i64,
#[serde(rename = "IsAny")]
pub is_any: bool,
#[serde(rename = "IsAnyToRemove")]
pub is_any_to_remove: bool,
#[serde(flatten)]
pub reagents: BTreeMap<String, f64>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct Device {
#[serde(rename = "ConnectionList")]
pub connection_list: Vec<(String, String)>,
#[serde(rename = "DevicesLength")]
pub devices_length: Option<i64>,
#[serde(rename = "HasActivateState")]
pub has_activate_state: bool,
#[serde(rename = "HasAtmosphere")]
pub has_atmosphere: bool,
#[serde(rename = "HasColorState")]
pub has_color_state: bool,
#[serde(rename = "HasLockState")]
pub has_lock_state: bool,
#[serde(rename = "HasModeState")]
pub has_mode_state: bool,
#[serde(rename = "HasOnOffState")]
pub has_on_off_state: bool,
#[serde(rename = "HasOpenState")]
pub has_open_state: bool,
#[serde(rename = "HasReagents")]
pub has_reagents: bool,
}