diff --git a/.gitignore b/.gitignore index 63c0e00..35b6a68 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ dist/ mode_modules/ target/ Session.vim +*.pyc diff --git a/cspell.json b/cspell.json index 994b35f..c56bbe8 100644 --- a/cspell.json +++ b/cspell.json @@ -58,6 +58,7 @@ "brnez", "Circuitboard", "codegen", + "conv", "cstyle", "endpos", "getd", @@ -123,6 +124,7 @@ "thiserror", "tokentype", "trunc", + "Tsify", "whos" ] } diff --git a/ic10emu/src/grammar.rs b/ic10emu/src/grammar.rs index a887211..c0a910b 100644 --- a/ic10emu/src/grammar.rs +++ b/ic10emu/src/grammar.rs @@ -17,7 +17,7 @@ pub mod generated { use strum::EnumProperty; use strum::EnumString; use strum::IntoEnumIterator; - + include!(concat!(env!("OUT_DIR"), "/instructions.rs")); include!(concat!(env!("OUT_DIR"), "/logictypes.rs")); include!(concat!(env!("OUT_DIR"), "/modes.rs")); diff --git a/ic10emu_wasm/Cargo.lock b/ic10emu_wasm/Cargo.lock index 21ec29c..54a0ab2 100644 --- a/ic10emu_wasm/Cargo.lock +++ b/ic10emu_wasm/Cargo.lock @@ -228,6 +228,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gloo-utils" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -303,8 +316,10 @@ dependencies = [ "itertools", "js-sys", "serde", - "serde-wasm-bindgen", + "serde-wasm-bindgen 0.6.5", "serde_with", + "thiserror", + "tsify", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", @@ -621,6 +636,17 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde-wasm-bindgen" version = "0.6.5" @@ -643,6 +669,17 @@ dependencies = [ "syn 2.0.55", ] +[[package]] +name = "serde_derive_internals" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e578a843d40b4189a4d66bba51d7684f57da5bd7c304c64e14bd63efbef49509" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + [[package]] name = "serde_json" version = "1.0.115" @@ -804,6 +841,32 @@ dependencies = [ "time-core", ] +[[package]] +name = "tsify" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b26cf145f2f3b9ff84e182c448eaf05468e247f148cf3d2a7d67d78ff023a0" +dependencies = [ + "gloo-utils", + "serde", + "serde-wasm-bindgen 0.5.0", + "serde_json", + "tsify-macros", + "wasm-bindgen", +] + +[[package]] +name = "tsify-macros" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a94b0f0954b3e59bfc2c246b4c8574390d94a4ad4ad246aaf2fb07d7dfd3b47" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.55", +] + [[package]] name = "unicode-ident" version = "1.0.12" diff --git a/ic10emu_wasm/Cargo.toml b/ic10emu_wasm/Cargo.toml index 9ec1615..9675f31 100644 --- a/ic10emu_wasm/Cargo.toml +++ b/ic10emu_wasm/Cargo.toml @@ -18,6 +18,8 @@ serde-wasm-bindgen = "0.6.5" itertools = "0.12.1" serde = { version = "1.0.197", features = ["derive"] } serde_with = "3.7.0" +tsify = { version = "0.4.5", default-Vfeatures = false, features = ["js", "wasm-bindgen"] } +thiserror = "1.0.58" [features] default = ["console_error_panic_hook"] diff --git a/ic10emu_wasm/build.rs b/ic10emu_wasm/build.rs new file mode 100644 index 0000000..55a368f --- /dev/null +++ b/ic10emu_wasm/build.rs @@ -0,0 +1,23 @@ +use std::{ + env, + fs::{self, File}, + io::{BufWriter, Write}, + path::Path, +}; + +fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + let dest_path = Path::new(&out_dir).join("ts_types.rs"); + let output_file = File::create(dest_path).unwrap(); + let mut writer = BufWriter::new(&output_file); + + let infile = Path::new("src/types.ts"); + let contents = fs::read_to_string(infile).unwrap(); + write!( + &mut writer, + "#[wasm_bindgen(typescript_custom_section)]\n\ + const TYPES: &'static str = r#\"{contents}\"#; + " + ) + .unwrap(); +} diff --git a/ic10emu_wasm/src/lib.rs b/ic10emu_wasm/src/lib.rs index 4154fb4..c984eac 100644 --- a/ic10emu_wasm/src/lib.rs +++ b/ic10emu_wasm/src/lib.rs @@ -1,18 +1,15 @@ #[macro_use] mod utils; +mod types; + +use types::{Stack, Registers}; use std::{cell::RefCell, rc::Rc}; use itertools::Itertools; // use itertools::Itertools; -use serde::{Deserialize, Serialize}; use wasm_bindgen::prelude::*; -use serde_with::serde_as; - -#[serde_as] -#[derive(Serialize, Deserialize)] -struct Stack(#[serde_as(as = "[_; 512]")] [f64; 512]); #[wasm_bindgen] extern "C" { @@ -46,22 +43,22 @@ impl DeviceRef { self.device.borrow().name_hash } - #[wasm_bindgen(getter)] + #[wasm_bindgen(getter, skip_typescript)] pub fn fields(&self) -> JsValue { serde_wasm_bindgen::to_value(&self.device.borrow().fields).unwrap() } - #[wasm_bindgen(getter)] + #[wasm_bindgen(getter, skip_typescript)] pub fn slots(&self) -> JsValue { serde_wasm_bindgen::to_value(&self.device.borrow().slots).unwrap() } - #[wasm_bindgen(getter)] + #[wasm_bindgen(getter, skip_typescript)] pub fn reagents(&self) -> JsValue { serde_wasm_bindgen::to_value(&self.device.borrow().reagents).unwrap() } - #[wasm_bindgen(getter)] + #[wasm_bindgen(getter, skip_typescript)] pub fn connections(&self) -> JsValue { serde_wasm_bindgen::to_value(&self.device.borrow().connections).unwrap() } @@ -99,46 +96,38 @@ impl DeviceRef { } #[wasm_bindgen(getter, js_name = "stack")] - pub fn ic_stack(&self) -> JsValue { - serde_wasm_bindgen::to_value( - &self - .device - .borrow() - .ic - .as_ref() - .map(|ic| { - self.vm - .borrow() - .ics - .get(ic) - .map(|ic| Stack(ic.as_ref().borrow().stack)) - }) - .flatten(), - ) - .unwrap() + pub fn ic_stack(&self) -> Option { + self.device + .borrow() + .ic + .as_ref() + .map(|ic| { + self.vm + .borrow() + .ics + .get(ic) + .map(|ic| Stack(ic.as_ref().borrow().stack)) + }) + .flatten() } #[wasm_bindgen(getter, js_name = "registers")] - pub fn ic_registers(&self) -> JsValue { - serde_wasm_bindgen::to_value( - &self - .device - .borrow() - .ic - .as_ref() - .map(|ic| { - self.vm - .borrow() - .ics - .get(ic) - .map(|ic| ic.as_ref().borrow().registers) - }) - .flatten(), - ) - .unwrap() + pub fn ic_registers(&self) -> Option { + self.device + .borrow() + .ic + .as_ref() + .map(|ic| { + self.vm + .borrow() + .ics + .get(ic) + .map(|ic| Registers(ic.as_ref().borrow().registers)) + }) + .flatten() } - #[wasm_bindgen(getter, js_name = "aliases")] + #[wasm_bindgen(getter, js_name = "aliases", skip_typescript)] pub fn ic_aliases(&self) -> JsValue { serde_wasm_bindgen::to_value( &self @@ -158,7 +147,7 @@ impl DeviceRef { .unwrap() } - #[wasm_bindgen(getter, js_name = "defines")] + #[wasm_bindgen(getter, js_name = "defines", skip_typescript)] pub fn ic_defines(&self) -> JsValue { serde_wasm_bindgen::to_value( &self @@ -178,7 +167,7 @@ impl DeviceRef { .unwrap() } - #[wasm_bindgen(getter, js_name = "pins")] + #[wasm_bindgen(getter, js_name = "pins", skip_typescript)] pub fn ic_pins(&self) -> JsValue { serde_wasm_bindgen::to_value( &self @@ -268,7 +257,7 @@ impl DeviceRef { .as_ref() .ok_or(ic10emu::VMError::NoIC(self.device.borrow().id))?; let vm_borrow = self.vm.borrow(); - let ic = vm_borrow + let ic = vm_borrow .ics .get(&ic_id) .ok_or(ic10emu::VMError::NoIC(self.device.borrow().id))?; @@ -285,7 +274,7 @@ impl DeviceRef { .as_ref() .ok_or(ic10emu::VMError::NoIC(self.device.borrow().id))?; let vm_borrow = self.vm.borrow(); - let ic = vm_borrow + let ic = vm_borrow .ics .get(&ic_id) .ok_or(ic10emu::VMError::NoIC(self.device.borrow().id))?; diff --git a/ic10emu_wasm/src/types.rs b/ic10emu_wasm/src/types.rs new file mode 100644 index 0000000..c659553 --- /dev/null +++ b/ic10emu_wasm/src/types.rs @@ -0,0 +1,17 @@ + +use serde::{Deserialize, Serialize}; +use serde_with::serde_as; +use tsify::Tsify; +use wasm_bindgen::prelude::*; + +#[serde_as] +#[derive(Tsify, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +pub struct Stack(#[serde_as(as = "[_; 512]")] pub [f64; 512]); + +#[serde_as] +#[derive(Tsify, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +pub struct Registers(#[serde_as(as = "[_; 18]")] pub [f64; 18]); + +include!(concat!(env!("OUT_DIR"), "/ts_types.rs")); \ No newline at end of file diff --git a/ic10emu_wasm/src/types.ts b/ic10emu_wasm/src/types.ts new file mode 100644 index 0000000..8230ba8 --- /dev/null +++ b/ic10emu_wasm/src/types.ts @@ -0,0 +1,36 @@ +type FieldType = 'Read' | 'Write' | 'ReadWrite'; + +interface LogicField { + field_type: FieldType, + value: number, +} +type Fields = Map; + +type SlotType = 'AccessCard' | 'Appliance' | 'Back' | 'Battery' | 'Blocked' | 'Bottle' | 'Cartridge' | 'Circuitboard' | 'CreditCard' | 'DataDisk' | 'DrillHead' | 'Egg' | 'Entity' | 'Flare' | 'GasCanister' | 'GasFilter' | 'Helmet' | 'Ingot' | 'LiquidBottle' | 'LiquidCanister' | 'Magazine' | 'Ore' | 'Organ' | 'Plant' | 'ProgramableChip' | 'ScanningHead' | 'SensorProcessingUnit' | 'SoundCartridge' | 'Suit' | 'Tool' | 'Torpedo' | 'None'; + +interface Slot { + typ: SlotType, + fields: Fields, +} + +type Reagents = Map>; + +type Connection = { CableNetwork: number } | 'Other' ; + +type Alias = { RegisterSpec: {indirection: number, target: number} } | { DeviceSpec: { device: "Db" | { Numbered: number } | { Indirect: { indirection: number, target: number } } }, connection: number | undefined }; + +type Aliases = Map; + +type Defines = Map; + +type Pins = (number | undefined)[] + +export interface DeviceRef { + readonly fields: Fields | undefined; + readonly slots: Slot[] | undefined; + readonly reagents: Reagents | undefined; + readonly connections: Connection[] | undefined; + readonly aliases: Aliases | undefined; + readonly defines: Defines | undefined; + readonly pins: Pins; +} diff --git a/ic10lsp_wasm/Cargo.toml b/ic10lsp_wasm/Cargo.toml index ad3f47e..2212d95 100644 --- a/ic10lsp_wasm/Cargo.toml +++ b/ic10lsp_wasm/Cargo.toml @@ -30,4 +30,4 @@ opt-level = "s" lto = true [build] -target = "wasm32-unknown-unknown" \ No newline at end of file +target = "wasm32-unknown-unknown" diff --git a/www/cspell.json b/www/cspell.json index e28adb3..196686c 100644 --- a/www/cspell.json +++ b/www/cspell.json @@ -54,6 +54,7 @@ "brnez", "Circuitboard", "codegen", + "Depressurising", "endpos", "getd", "Hardsuit", @@ -64,22 +65,28 @@ "Keybind", "lbns", "logicable", + "logicslottypes", "logictype", "logictypes", + "lparen", "Mineables", "modelist", "ninf", + "noconflict", "offcanvas", "overcolumn", "Overlength", "pedia", + "pinf", "popperjs", "preproc", + "Pressurising", "putd", "QUICKFIX", "reagentmode", "reagentmodes", "rocketstation", + "rparen", "sapz", "sattellite", "sdns", diff --git a/www/package.json b/www/package.json index f155e92..c4e15ec 100644 --- a/www/package.json +++ b/www/package.json @@ -25,6 +25,9 @@ "homepage": "https://github.com/ryex/ic10emu#readme", "devDependencies": { "@oneidentity/zstd-js": "^1.0.3", + "@types/ace": "^0.0.52", + "@types/bootstrap": "^5.2.10", + "@types/wicg-file-system-access": "^2023.10.5", "autoprefixer": "^10.4.19", "copy-webpack-plugin": "^12.0.2", "css-loader": "^6.10.0", @@ -49,7 +52,7 @@ }, "dependencies": { "@popperjs/core": "^2.11.8", - "ace-code": "^1.32.9", + "ace-builds": "^1.32.9", "ace-linters": "^1.1.2", "bootstrap": "^5.3.3", "bson": "^6.5.0", diff --git a/www/pnpm-lock.yaml b/www/pnpm-lock.yaml index 4e36dee..368f8fd 100644 --- a/www/pnpm-lock.yaml +++ b/www/pnpm-lock.yaml @@ -8,7 +8,7 @@ dependencies: '@popperjs/core': specifier: ^2.11.8 version: 2.11.8 - ace-code: + ace-builds: specifier: ^1.32.9 version: 1.32.9 ace-linters: @@ -52,6 +52,15 @@ devDependencies: '@oneidentity/zstd-js': specifier: ^1.0.3 version: 1.0.3 + '@types/ace': + specifier: ^0.0.52 + version: 0.0.52 + '@types/bootstrap': + specifier: ^5.2.10 + version: 5.2.10 + '@types/wicg-file-system-access': + specifier: ^2023.10.5 + version: 2023.10.5 autoprefixer: specifier: ^10.4.19 version: 10.4.19(postcss@8.4.38) @@ -235,7 +244,6 @@ packages: /@popperjs/core@2.11.8: resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} - dev: false /@sindresorhus/is@0.7.0: resolution: {integrity: sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==} @@ -256,6 +264,10 @@ packages: engines: {node: '>=10.13.0'} dev: true + /@types/ace@0.0.52: + resolution: {integrity: sha512-YPF9S7fzpuyrxru+sG/rrTpZkC6gpHBPF14W3x70kqVOD+ks6jkYLapk4yceh36xej7K4HYxcyz9ZDQ2lTvwgQ==} + dev: true + /@types/body-parser@1.19.5: resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} dependencies: @@ -269,6 +281,12 @@ packages: '@types/node': 20.11.30 dev: true + /@types/bootstrap@5.2.10: + resolution: {integrity: sha512-F2X+cd6551tep0MvVZ6nM8v7XgGN/twpdNDjqS1TUM7YFNEtQYWk+dKAnH+T1gr6QgCoGMPl487xw/9hXooa2g==} + dependencies: + '@popperjs/core': 2.11.8 + dev: true + /@types/connect-history-api-fallback@1.5.4: resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} dependencies: @@ -411,6 +429,10 @@ packages: '@types/node': 20.11.30 dev: true + /@types/wicg-file-system-access@2023.10.5: + resolution: {integrity: sha512-e9kZO9kCdLqT2h9Tw38oGv9UNzBBWaR1MzuAavxPcsV/7FJ3tWbU6RI3uB+yKIDPGLkGVbplS52ub0AcRLvrhA==} + dev: true + /@types/ws@8.5.10: resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} dependencies: @@ -631,9 +653,8 @@ packages: negotiator: 0.6.3 dev: true - /ace-code@1.32.9: - resolution: {integrity: sha512-MgjfSoJ8tV72v9NZntxM/z9txHizagzNczrb1zMtPOKzmGkJChm+ywDQV8INAKRla1vt9gmbAJMSTPpUZHrlew==} - engines: {node: '>= 0.6.0'} + /ace-builds@1.32.9: + resolution: {integrity: sha512-dqBLPj//Gq0b92YUtRIsdWsORf4J+4xW3r8/4Wr2Vqid7O1j7YBV/ZsVvWBjZFy+EnvMCRFCFOEIM1cbt4BQ/g==} dev: false /ace-linters@1.1.2: diff --git a/www/src/js/editor/ace.ts b/www/src/js/editor/ace.js similarity index 100% rename from www/src/js/editor/ace.ts rename to www/src/js/editor/ace.js diff --git a/www/src/js/editor/ic10_highlight_rules.ts b/www/src/js/editor/ic10_highlight_rules.ts index 193f353..5af79ed 100644 --- a/www/src/js/editor/ic10_highlight_rules.ts +++ b/www/src/js/editor/ic10_highlight_rules.ts @@ -1,316 +1,401 @@ -"use strict"; -var oop = require("ace-code/src/lib/oop"); -var TextHighlightRules = require("ace-code/src/mode/text_highlight_rules").TextHighlightRules; -var IC10HighlightRules = function() { - // regexp must not have capturing parentheses. Use (?:) instead. - // regexps are ordered -> the first match is used +var ops = ( + "abs|acos|add|alias|and|asin|atan|atan2|bap|bapal|bapz|bapzal|bdns|" + + "bdnsal|bdse|bdseal|beq|beqal|beqz|beqzal|bge|bgeal|bgez|bgezal|bgt|" + + "bgtal|bgtz|bgtzal|ble|bleal|blez|blezal|blt|bltal|bltz|bltzal|bna|" + + "bnaal|bnan|bnaz|bnazal|bne|bneal|bnez|bnezal|brap|brapz|brdns|brdse|" + + "breq|breqz|brge|brgez|brgt|brgtz|brle|brlez|brlt|brltz|brna|brnan|" + + "brnaz|brne|brnez|ceil|cos|define|div|exp|floor|get|getd|hcf|j|jal|jr|" + + "l|label|lb|lbn|lbns|lbs|ld|log|lr|ls|max|min|mod|move|mul|nor|not|or|" + + "peek|poke|pop|push|put|putd|rand|round|s|sap|sapz|sb|sbn|sbs|sd|sdns|" + + "sdse|select|seq|seqz|sge|sgez|sgt|sgtz|sin|sla|sle|sleep|slez|sll|" + + "slt|sltz|sna|snan|snanz|snaz|sne|snez|sqrt|sra|srl|ss|sub|tan|trunc|" + + "xor|yield" +); - var ops = ( - "abs|acos|add|alias|and|asin|atan|atan2|bap|bapal|bapz|bapzal|bdns|"+ - "bdnsal|bdse|bdseal|beq|beqal|beqz|beqzal|bge|bgeal|bgez|bgezal|bgt|"+ - "bgtal|bgtz|bgtzal|ble|bleal|blez|blezal|blt|bltal|bltz|bltzal|bna|"+ - "bnaal|bnan|bnaz|bnazal|bne|bneal|bnez|bnezal|brap|brapz|brdns|brdse|"+ - "breq|breqz|brge|brgez|brgt|brgtz|brle|brlez|brlt|brltz|brna|brnan|"+ - "brnaz|brne|brnez|ceil|cos|define|div|exp|floor|get|getd|hcf|j|jal|jr|"+ - "l|label|lb|lbn|lbns|lbs|ld|log|lr|ls|max|min|mod|move|mul|nor|not|or|"+ - "peek|poke|pop|push|put|putd|rand|round|s|sap|sapz|sb|sbn|sbs|sd|sdns|"+ - "sdse|select|seq|seqz|sge|sgez|sgt|sgtz|sin|sla|sle|sleep|slez|sll|"+ - "slt|sltz|sna|snan|snanz|snaz|sne|snez|sqrt|sra|srl|ss|sub|tan|trunc|"+ - "xor|yield" - ); - - var enums = ( - "LogicType\\.Power|LogicType\\.Open|LogicType\\.Mode|LogicType\\.Error|"+ - "LogicType\\.Pressure|LogicType\\.Temperature|LogicType\\.PressureExternal|"+ - "LogicType\\.PressureInternal|LogicType\\.Activate|LogicType\\.Lock|"+ - "LogicType\\.Charge|LogicType\\.Setting|LogicType\\.Reagents|"+ - "LogicType\\.RatioOxygen|LogicType\\.RatioCarbonDioxide|"+ - "LogicType\\.RatioNitrogen|LogicType\\.RatioPollutant|"+ - "LogicType\\.RatioVolatiles|LogicType\\.RatioWater|LogicType\\.Horizontal|"+ - "LogicType\\.Vertical|LogicType\\.SolarAngle|LogicType\\.Maximum|"+ - "LogicType\\.Ratio|LogicType\\.PowerPotential|LogicType\\.PowerActual|"+ - "LogicType\\.Quantity|LogicType\\.On|LogicType\\.RequiredPower|"+ - "LogicType\\.HorizontalRatio|LogicType\\.VerticalRatio|"+ - "LogicType\\.PowerRequired|LogicType\\.Idle|LogicType\\.Color|"+ - "LogicType\\.ElevatorSpeed|LogicType\\.ElevatorLevel|"+ - "LogicType\\.RecipeHash|LogicType\\.RequestHash|LogicType\\.CompletionRatio|"+ - "LogicType\\.ClearMemory|LogicType\\.ExportCount|LogicType\\.ImportCount|"+ - "LogicType\\.PowerGeneration|LogicType\\.TotalMoles|LogicType\\.Volume|"+ - "LogicType\\.Plant|LogicType\\.Harvest|LogicType\\.Output|"+ - "LogicType\\.PressureSetting|LogicType\\.TemperatureSetting|"+ - "LogicType\\.TemperatureExternal|LogicType\\.Filtration|"+ - "LogicType\\.AirRelease|LogicType\\.PositionX|LogicType\\.PositionZ|"+ - "LogicType\\.VelocityMagnitude|LogicType\\.VelocityRelativeX|"+ - "LogicType\\.VelocityRelativeY|LogicType\\.VelocityRelativeZ|"+ - "LogicType\\.RatioNitrousOxide|LogicType\\.PrefabHash|"+ - "LogicType\\.ForceWrite|LogicType\\.SignalStrength|LogicType\\.SignalID|"+ - "LogicType\\.TargetX|LogicType\\.TargetY|LogicType\\.TargetZ|"+ - "LogicType\\.SettingInput|LogicType\\.SettingOutput|"+ - "LogicType\\.CurrentResearchPodType|LogicType\\.ManualResearchRequiredPod|"+ - "LogicType\\.MineablesInVicinity|LogicType\\.MineablesInQueue|"+ - "LogicType\\.NextWeatherEventTime|LogicType\\.Combustion|LogicType\\.Fuel|"+ - "LogicType\\.ReturnFuelCost|LogicType\\.CollectableGoods|LogicType\\.Time|"+ - "LogicType\\.Bpm|LogicType\\.EnvironmentEfficiency|"+ - "LogicType\\.WorkingGasEfficiency|LogicType\\.PressureInput|"+ - "LogicType\\.TemperatureInput|LogicType\\.RatioOxygenInput|"+ - "LogicType\\.RatioCarbonDioxideInput|LogicType\\.RatioNitrogenInput|"+ - "LogicType\\.RatioPollutantInput|LogicType\\.RatioVolatilesInput|"+ - "LogicType\\.RatioWaterInput|LogicType\\.RatioNitrousOxideInput|"+ - "LogicType\\.TotalMolesInput|LogicType\\.PressureInput2|"+ - "LogicType\\.TemperatureInput2|LogicType\\.RatioOxygenInput2|"+ - "LogicType\\.RatioCarbonDioxideInput2|"+ - "LogicType\\.RatioLiquidCarbonDioxide|LogicType\\.RatioNitrogenInput2|"+ - "LogicType\\.RatioPollutantInput2|LogicType\\.RatioVolatilesInput2|"+ - "LogicType\\.RatioWaterInput2|LogicType\\.RatioNitrousOxideInput2|"+ - "LogicType\\.TotalMolesInput2|LogicType\\.PressureOutput|"+ - "LogicType\\.TemperatureOutput|LogicType\\.RatioOxygenOutput|"+ - "LogicType\\.RatioCarbonDioxideOutput|LogicType\\.RatioNitrogenOutput|"+ - "LogicType\\.RatioPollutantOutput|LogicType\\.RatioVolatilesOutput|"+ - "LogicType\\.RatioWaterOutput|LogicType\\.RatioNitrousOxideOutput|"+ - "LogicType\\.TotalMolesOutput|LogicType\\.PressureOutput2|"+ - "LogicType\\.TemperatureOutput2|LogicType\\.RatioOxygenOutput2|"+ - "LogicType\\.RatioCarbonDioxideOutput2|LogicType\\.RatioNitrogenOutput2|"+ - "LogicType\\.RatioPollutantOutput2|LogicType\\.RatioVolatilesOutput2|"+ - "LogicType\\.RatioWaterOutput2|LogicType\\.RatioNitrousOxideOutput2|"+ - "LogicType\\.TotalMolesOutput2|LogicType\\.CombustionInput|"+ - "LogicType\\.CombustionInput2|LogicType\\.CombustionOutput|"+ - "LogicType\\.CombustionOutput2|"+ - "LogicType\\.OperationalTemperatureEfficiency|"+ - "LogicType\\.TemperatureDifferentialEfficiency|"+ - "LogicType\\.PressureEfficiency|LogicType\\.CombustionLimiter|"+ - "LogicType\\.Throttle|LogicType\\.Rpm|LogicType\\.Stress|"+ - "LogicType\\.InterrogationProgress|LogicType\\.TargetPadIndex|"+ - "LogicType\\.SizeX|LogicType\\.SizeY|LogicType\\.SizeZ|"+ - "LogicType\\.MinimumWattsToContact|LogicType\\.WattsReachingContact|"+ - "LogicType\\.Channel0|LogicType\\.Channel1|LogicType\\.Channel2|"+ - "LogicType\\.Channel3|LogicType\\.Channel4|LogicType\\.Channel5|"+ - "LogicType\\.Channel6|LogicType\\.LineNumber|LogicType\\.Flush|"+ - "LogicType\\.Channel7|LogicType\\.SoundAlert|LogicType\\.SolarIrradiance|"+ - "LogicType\\.RatioLiquidNitrogen|LogicType\\.RatioLiquidNitrogenInput|"+ - "LogicType\\.RatioLiquidNitrogenInput2|"+ - "LogicType\\.RatioLiquidNitrogenOutput|"+ - "LogicType\\.RatioLiquidNitrogenOutput2|"+ - "LogicType\\.VolumeOfLiquid|LogicType\\.RatioLiquidOxygen|"+ - "LogicType\\.RatioLiquidOxygenInput|LogicType\\.RatioLiquidOxygenInput2|"+ - "LogicType\\.RatioLiquidOxygenOutput|"+ - "LogicType\\.RatioLiquidOxygenOutput2|LogicType\\.RatioLiquidVolatiles|"+ - "LogicType\\.RatioLiquidVolatilesInput|"+ - "LogicType\\.RatioLiquidVolatilesInput2|"+ - "LogicType\\.RatioLiquidVolatilesOutput|"+ - "LogicType\\.RatioLiquidVolatilesOutput2|LogicType\\.RatioSteam|"+ - "LogicType\\.RatioSteamInput|LogicType\\.RatioSteamInput2|"+ - "LogicType\\.RatioSteamOutput|LogicType\\.RatioSteamOutput2|"+ - "LogicType\\.ContactTypeId|LogicType\\.RatioLiquidCarbonDioxideInput|"+ - "LogicType\\.RatioLiquidCarbonDioxideInput2|"+ - "LogicType\\.RatioLiquidCarbonDioxideOutput|"+ - "LogicType\\.RatioLiquidCarbonDioxideOutput2|"+ - "LogicType\\.RatioLiquidPollutant|LogicType\\.RatioLiquidPollutantInput|"+ - "LogicType\\.RatioLiquidPollutantInput2|"+ - "LogicType\\.RatioLiquidPollutantOutput|"+ - "LogicType\\.RatioLiquidPollutantOutput2|"+ - "LogicType\\.RatioLiquidNitrousOxide|"+ - "LogicType\\.RatioLiquidNitrousOxideInput|"+ - "LogicType\\.RatioLiquidNitrousOxideInput2|"+ - "LogicType\\.RatioLiquidNitrousOxideOutput|"+ - "LogicType\\.RatioLiquidNitrousOxideOutput2|"+ - "LogicType\\.Progress|LogicType\\.DestinationCode|"+ - "LogicType\\.Acceleration|LogicType\\.ReferenceId|"+ - "LogicType\\.AutoShutOff|LogicType\\.Mass|LogicType\\.DryMass|"+ - "LogicType\\.Thrust|LogicType\\.Weight|LogicType\\.ThrustToWeight|"+ - "LogicType\\.TimeToDestination|LogicType\\.BurnTimeRemaining|"+ - "LogicType\\.AutoLand|LogicType\\.ForwardX|LogicType\\.ForwardY|"+ - "LogicType\\.ForwardZ|LogicType\\.Orientation|LogicType\\.VelocityX|"+ - "LogicType\\.VelocityY|LogicType\\.VelocityZ|LogicType\\.PassedMoles|"+ - "LogicType\\.ExhaustVelocity|LogicType\\.FlightControlRule|"+ - "LogicType\\.ReEntryAltitude|LogicType\\.Apex|LogicType\\.EntityState|"+ - "LogicType\\.DrillCondition|LogicType\\.Index|LogicType\\.CelestialHash|"+ - "LogicType\\.AlignmentError|LogicType\\.DistanceAu|LogicType\\.OrbitPeriod|"+ - "LogicType\\.Inclination|LogicType\\.Eccentricity|LogicType\\.SemiMajorAxis|"+ - "LogicType\\.DistanceKm|LogicType\\.CelestialParentHash|"+ - "LogicType\\.TrueAnomaly|"+ - "LogicSlotType\\.None|LogicSlotType\\.Occupied|LogicSlotType\\.OccupantHash|"+ - "LogicSlotType\\.Quantity|LogicSlotType\\.Damage|LogicSlotType\\.Efficiency|"+ - "LogicSlotType\\.Health|LogicSlotType\\.Growth|LogicSlotType\\.Pressure|"+ - "LogicSlotType\\.Temperature|LogicSlotType\\.Charge|"+ - "LogicSlotType\\.ChargeRatio|LogicSlotType\\.Class|"+ - "LogicSlotType\\.PressureWaste|LogicSlotType\\.PressureAir|"+ - "LogicSlotType\\.MaxQuantity|LogicSlotType\\.Mature|"+ - "LogicSlotType\\.PrefabHash|LogicSlotType\\.Seeding|"+ - "LogicSlotType\\.LineNumber|LogicSlotType\\.Volume|"+ - "LogicSlotType\\.Open|LogicSlotType\\.On|LogicSlotType\\.Lock|"+ - "LogicSlotType\\.SortingClass|LogicSlotType\\.FilterType|"+ - "LogicSlotType\\.ReferenceId|"+ - "SlotClass\\.None|SlotClass\\.Helmet|SlotClass\\.Suit|SlotClass\\.Back|"+ - "SlotClass\\.GasFilter|SlotClass\\.Motherboard|SlotClass\\.Circuitboard|"+ - "SlotClass\\.DataDisk|SlotClass\\.Organ|SlotClass\\.Ore|SlotClass\\.Plant|"+ - "SlotClass\\.Uniform|SlotClass\\.Battery|SlotClass\\.Egg|SlotClass\\.Belt|"+ - "SlotClass\\.Tool|SlotClass\\.Appliance|SlotClass\\.Ingot|SlotClass\\.Torpedo|"+ - "SlotClass\\.Cartridge|SlotClass\\.AccessCard|SlotClass\\.Magazine|"+ - "SlotClass\\.Circuit|SlotClass\\.Bottle|SlotClass\\.ProgrammableChip|"+ - "SlotClass\\.Glasses|SlotClass\\.CreditCard|SlotClass\\.DirtCanister|"+ - "SlotClass\\.SensorProcessingUnit|SlotClass\\.LiquidCanister|"+ - "SlotClass\\.LiquidBottle|SlotClass\\.Wreckage|SlotClass\\.SoundCartridge|"+ - "SlotClass\\.DrillHead|SlotClass\\.ScanningHead|SlotClass\\.Flare|"+ - "SlotClass\\.Blocked|GasType\\.Undefined|GasType\\.Oxygen|GasType\\.Nitrogen|"+ - "GasType\\.CarbonDioxide|GasType\\.Volatiles|GasType\\.Pollutant|"+ - "GasType\\.Water|GasType\\.NitrousOxide|GasType\\.LiquidNitrogen|"+ - "GasType\\.LiquidVolatiles|GasType\\.Steam|GasType\\.LiquidCarbonDioxide|"+ - "GasType\\.LiquidPollutant|GasType\\.LiquidNitrousOxide|"+ - "Equals|Greater|Less|NotEquals|"+ - "AirCon\\.Cold|AirCon\\.Hot|AirControl\\.None|AirControl\\.Offline|"+ - "AirControl\\.Pressure|AirControl\\.Draught|"+ - "Color\\.Blue|Color\\.Gray|Color\\.Green|Color\\.Orange|Color\\.Red|Color\\.Yellow|"+ - "Color\\.White|Color\\.Black|Color\\.Brown|Color\\.Khaki|Color\\.Pink|"+ - "Color\\.Purple|"+ - "DaylightSensorMode\\.Default|DaylightSensorMode\\.Horizontal|"+ - "DaylightSensorMode\\.Vertical|"+ - "ElevatorMode\\.Stationary|ElevatorMode\\.Upward|ElevatorMode\\.Downward|"+ - "EntityState\\.Alive|EntityState\\.Dead|EntityState\\.Unconscious"+ - "|EntityState\\.Decay|"+ - "PowerMode\\.Idle|PowerMode\\.Discharged|PowerMode\\.Discharging|"+ - "PowerMode\\.Charging|PowerMode\\.Charged|"+ - "RobotMode\\.None|RobotMode\\.Follow|RobotMode\\.MoveToTarget|"+ - "RobotMode\\.Roam|RobotMode\\.Unload|RobotMode\\.PathToTarget|"+ - "RobotMode\\.StorageFull|"+ - "SortingClass\\.Default|SortingClass\\.Kits|SortingClass\\.Tools|"+ - "SortingClass\\.Resources|SortingClass\\.Food|SortingClass\\.Clothing|"+ - "SortingClass\\.Appliances|SortingClass\\.Atmospherics|"+ - "SortingClass\\.Storage|SortingClass\\.Ores|SortingClass\\.Ices|"+ - "TransmitterMode\\.Passive|TransmitterMode\\.Active|"+ - "Vent\\.Outward|Vent\\.Inward" - ); - - var logictypes = ( - "Acceleration|Activate|AirRelease|AlignmentError|Apex|AutoLand|"+ - "AutoShutOff|Average|Bpm|BurnTimeRemaining|Bypass|CelestialHash|"+ - "CelestialParentHash|Channel|Channel0|Channel1|Channel2|Channel3|"+ - "Channel4|Channel5|Channel6|Channel7|Charge|ChargeRatio|Class|"+ - "ClearMemory|CollectableGoods|Color|Combustion|CombustionInput|"+ - "CombustionInput2|CombustionLimiter|CombustionOutput|CombustionOutput2|"+ - "CompletionRatio|ContactTypeId|Contents|CurrentResearchPodType|Damage|"+ - "DestinationCode|DistanceAu|DistanceKm|DrillCondition|DryMass|"+ - "Eccentricity|Efficiency|ElevatorLevel|ElevatorSpeed|EntityState|"+ - "EnvironmentEfficiency|Error|ExhaustVelocity|ExportCount|"+ - "ExportQuantity|ExportSlotHash|ExportSlotOccupant|FilterType|"+ - "Filtration|FlightControlRule|Flush|ForceWrite|ForwardX|ForwardY|"+ - "ForwardZ|Fuel|Growth|Harvest|Health|Horizontal|HorizontalRatio|"+ - "Idle|ImportCount|ImportQuantity|ImportSlotHash|ImportSlotOccupant|"+ - "Inclination|Index|InterrogationProgress|LineNumber|Lock|"+ - "ManualResearchRequiredPod|Mass|Mature|MaxQuantity|Maximum|"+ - "MinWattsToContact|MineablesInQueue|MineablesInVicinity|Minimum|"+ - "MinimumWattsToContact|Mode|NextWeatherEventTime|None|OccupantHash|"+ - "Occupied|On|Open|OperationalTemperatureEfficiency|OrbitPeriod|"+ - "Orientation|Output|OverShootTarget|PassedMoles|Plant|"+ - "PlantEfficiency1|PlantEfficiency2|PlantEfficiency3|PlantEfficiency4|"+ - "PlantGrowth1|PlantGrowth2|PlantGrowth3|PlantGrowth4|PlantHash1|"+ - "PlantHash2|PlantHash3|PlantHash4|PlantHealth1|PlantHealth2|"+ - "PlantHealth3|PlantHealth4|PositionX|PositionY|PositionZ|Power|"+ - "PowerActual|PowerGeneration|PowerPotential|PowerRequired|"+ - "PrefabHash|Pressure|PressureAir|PressureEfficiency|PressureExternal|"+ - "PressureInput|PressureInput2|PressureInternal|PressureOutput|"+ - "PressureOutput2|PressureSetting|PressureWaste|Progress|Quantity|"+ - "Ratio|RatioCarbonDioxide|RatioCarbonDioxideInput|"+ - "RatioCarbonDioxideInput2|RatioCarbonDioxideOutput|"+ - "RatioCarbonDioxideOutput2|RatioLiquidCarbonDioxide|"+ - "RatioLiquidCarbonDioxideInput|RatioLiquidCarbonDioxideInput2|"+ - "RatioLiquidCarbonDioxideOutput|RatioLiquidCarbonDioxideOutput2|"+ - "RatioLiquidNitrogen|RatioLiquidNitrogenInput|"+ - "RatioLiquidNitrogenInput2|RatioLiquidNitrogenOutput|"+ - "RatioLiquidNitrogenOutput2|RatioLiquidNitrousOxide|"+ - "RatioLiquidNitrousOxideInput|RatioLiquidNitrousOxideInput2|"+ - "RatioLiquidNitrousOxideOutput|RatioLiquidNitrousOxideOutput2|"+ - "RatioLiquidOxygen|RatioLiquidOxygenInput|RatioLiquidOxygenInput2|"+ - "RatioLiquidOxygenOutput|RatioLiquidOxygenOutput2|"+ - "RatioLiquidPollutant|RatioLiquidPollutantInput|"+ - "RatioLiquidPollutantInput2|RatioLiquidPollutantOutput|"+ - "RatioLiquidPollutantOutput2|RatioLiquidVolatiles|"+ - "RatioLiquidVolatilesInput|RatioLiquidVolatilesInput2|"+ - "RatioLiquidVolatilesOutput|RatioLiquidVolatilesOutput2|"+ - "RatioNitrogen|RatioNitrogenInput|RatioNitrogenInput2|"+ - "RatioNitrogenOutput|RatioNitrogenOutput2|RatioNitrousOxide|"+ - "RatioNitrousOxideInput|RatioNitrousOxideInput2|"+ - "RatioNitrousOxideOutput|RatioNitrousOxideOutput2|RatioOxygen|"+ - "RatioOxygenInput|RatioOxygenInput2|RatioOxygenOutput|"+ - "RatioOxygenOutput2|RatioPollutant|RatioPollutantInput|"+ - "RatioPollutantInput2|RatioPollutantOutput|RatioPollutantOutput2|"+ - "RatioSteam|RatioSteamInput|RatioSteamInput2|RatioSteamOutput|"+ - "RatioSteamOutput2|RatioVolatiles|RatioVolatilesInput|"+ - "RatioVolatilesInput2|RatioVolatilesOutput|RatioVolatilesOutput2|"+ - "RatioWater|RatioWaterInput|RatioWaterInput2|RatioWaterOutput|"+ - "RatioWaterOutput2|ReEntryAltitude|Reagents|Recipe|RecipeHash|"+ - "ReferenceId|RequestHash|Required|RequiredPower|ReturnFuelCost|Rpm|"+ - "Seeding|SemiMajorAxis|Setting|SettingInput|SettingInputHash|"+ - "SettingOutput|SettingOutputHash|SignalID|SignalStrength|SizeX|SizeY|"+ - "SizeZ|SolarAngle|SolarConstant|SolarIrradiance|SortingClass|"+ - "SoundAlert|Stress|Sum|TargetPadIndex|TargetX|TargetY|TargetZ|"+ - "Temperature|TemperatureDifferentialEfficiency|TemperatureExternal|"+ - "TemperatureInput|TemperatureInput2|TemperatureOutput|"+ - "TemperatureOutput2|TemperatureSetting|Throttle|Thrust|ThrustToWeight|"+ - "Time|TimeToDestination|TotalMoles|TotalMolesInput|TotalMolesInput2|"+ - "TotalMolesOutput|TotalMolesOutput2|TrueAnomaly|Unknown|"+ - "VelocityMagnitude|VelocityRelativeX|VelocityRelativeY|"+ - "VelocityRelativeZ|VelocityX|VelocityY|VelocityZ|Vertical|"+ - "VerticalRatio|Volume|VolumeOfLiquid|WattsReachingContact|Weight"+ - "|WorkingGasEfficiency" - ); - - var constants = ("nan|pinf|ninf|pi|deg2rad|rad2deg|epsilon") +var enums = ( + "AirCon\\.Cold|AirCon\\.Hot|AirControl\\.Draught|AirControl\\.None|" + + "AirControl\\.Offline|AirControl\\.Pressure|Color\\.Black|Color\\.Blue|" + + "Color\\.Brown|Color\\.Gray|Color\\.Green|Color\\.Khaki|Color\\.Orange|" + + "Color\\.Pink|Color\\.Purple|Color\\.Red|Color\\.White|Color\\.Yellow|" + + "DaylightSensorMode\\.Default|DaylightSensorMode\\.Horizontal|" + + "DaylightSensorMode\\.Vertical|ElevatorMode\\.Downward|" + + "ElevatorMode\\.Stationary|ElevatorMode\\.Upward|EntityState\\.Alive|" + + "EntityState\\.Dead|EntityState\\.Decay|EntityState\\.Unconscious|" + + "Equals|GasType\\.CarbonDioxide|GasType\\.Hydrogen|GasType\\.LiquidCarbonDioxide|" + + "GasType\\.LiquidHydrogen|GasType\\.LiquidNitrogen|GasType\\.LiquidNitrousOxide|" + + "GasType\\.LiquidOxygen|GasType\\.LiquidPollutant|GasType\\.LiquidVolatiles|" + + "GasType\\.Nitrogen|GasType\\.NitrousOxide|GasType\\.Oxygen|" + + "GasType\\.Pollutant|GasType\\.PollutedWater|GasType\\.Steam|" + + "GasType\\.Undefined|GasType\\.Volatiles|GasType\\.Water|" + + "Greater|Less|LogicSlotType\\.Charge|LogicSlotType\\.ChargeRatio|" + + "LogicSlotType\\.Class|LogicSlotType\\.Damage|LogicSlotType\\.Efficiency|" + + "LogicSlotType\\.FilterType|LogicSlotType\\.Growth|LogicSlotType\\.Health|" + + "LogicSlotType\\.LineNumber|LogicSlotType\\.Lock|LogicSlotType\\.Mature|" + + "LogicSlotType\\.MaxQuantity|LogicSlotType\\.None|LogicSlotType\\.OccupantHash|" + + "LogicSlotType\\.Occupied|LogicSlotType\\.On|LogicSlotType\\.Open|" + + "LogicSlotType\\.PrefabHash|LogicSlotType\\.Pressure|" + + "LogicSlotType\\.PressureAir|LogicSlotType\\.PressureWaste|" + + "LogicSlotType\\.Quantity|LogicSlotType\\.ReferenceId|" + + "LogicSlotType\\.Seeding|LogicSlotType\\.SortingClass|" + + "LogicSlotType\\.Temperature|LogicSlotType\\.Volume|" + + "LogicType\\.Acceleration|LogicType\\.Activate|LogicType\\.AirRelease|" + + "LogicType\\.AlignmentError|LogicType\\.Apex|LogicType\\.AutoLand|" + + "LogicType\\.AutoShutOff|LogicType\\.Bpm|LogicType\\.BurnTimeRemaining|" + + "LogicType\\.CelestialHash|LogicType\\.CelestialParentHash|" + + "LogicType\\.Channel1|LogicType\\.Channel1|LogicType\\.Channel2|" + + "LogicType\\.Channel3|LogicType\\.Channel4|LogicType\\.Channel5|" + + "LogicType\\.Channel6|LogicType\\.Channel7|LogicType\\.Charge|" + + "LogicType\\.Chart|LogicType\\.ChartedNavPoints|LogicType\\.ClearMemory|" + + "LogicType\\.CollectableGoods|LogicType\\.Color|LogicType\\.Combustion|" + + "LogicType\\.CombustionInput|LogicType\\.CombustionInput2|" + + "LogicType\\.CombustionLimiter|LogicType\\.CombustionOutput|" + + "LogicType\\.CombustionOutput2|LogicType\\.CompletionRatio|" + + "LogicType\\.ContactTypeId|LogicType\\.CurrentCode|LogicType\\.CurrentResearchPodType|" + + "LogicType\\.Density|LogicType\\.DestinationCode|LogicType\\.Discover|" + + "LogicType\\.DistanceAu|LogicType\\.DistanceKm|LogicType\\.DrillCondition|" + + "LogicType\\.DryMass|LogicType\\.Eccentricity|LogicType\\.ElevatorLevel|" + + "LogicType\\.ElevatorSpeed|LogicType\\.EntityState|LogicType\\.EnvironmentEfficiency|" + + "LogicType\\.Error|LogicType\\.ExhaustVelocity|LogicType\\.ExportCount|" + + "LogicType\\.ExportQuantity|LogicType\\.ExportSlotHash|" + + "LogicType\\.ExportSlotOccupant|LogicType\\.Filtration|" + + "LogicType\\.FlightControlRule|LogicType\\.Flush|LogicType\\.ForceWrite|" + + "LogicType\\.ForwardX|LogicType\\.ForwardY|LogicType\\.ForwardZ|" + + "LogicType\\.Fuel|LogicType\\.Harvest|LogicType\\.Horizontal|" + + "LogicType\\.HorizontalRatio|LogicType\\.Idle|LogicType\\.ImportCount|" + + "LogicType\\.ImportQuantity|LogicType\\.ImportSlotHash|" + + "LogicType\\.ImportSlotOccupant|LogicType\\.Inclination|" + + "LogicType\\.Index|LogicType\\.InterrogationProgress|" + + "LogicType\\.LineNumber|LogicType\\.Lock|LogicType\\.ManualResearchRequiredPod|" + + "LogicType\\.Mass|LogicType\\.Maximum|LogicType\\.MineablesInQueue|" + + "LogicType\\.MineablesInVicinity|LogicType\\.MinedQuantity|" + + "LogicType\\.MinimumWattsToContact|LogicType\\.Mode|" + + "LogicType\\.NavPoints|LogicType\\.NextWeatherEventTime|" + + "LogicType\\.None|LogicType\\.On|LogicType\\.Open|LogicType\\.OperationalTemperatureEfficiency|" + + "LogicType\\.OrbitPeriod|LogicType\\.Orientation|LogicType\\.Output|" + + "LogicType\\.PassedMoles|LogicType\\.Plant|LogicType\\.PlantEfficiency1|" + + "LogicType\\.PlantEfficiency2|LogicType\\.PlantEfficiency3|" + + "LogicType\\.PlantEfficiency4|LogicType\\.PlantGrowth1|" + + "LogicType\\.PlantGrowth2|LogicType\\.PlantGrowth3|LogicType\\.PlantGrowth4|" + + "LogicType\\.PlantHash1|LogicType\\.PlantHash2|LogicType\\.PlantHash3|" + + "LogicType\\.PlantHash4|LogicType\\.PlantHealth1|LogicType\\.PlantHealth2|" + + "LogicType\\.PlantHealth3|LogicType\\.PlantHealth4|LogicType\\.PositionX|" + + "LogicType\\.PositionY|LogicType\\.PositionZ|LogicType\\.Power|" + + "LogicType\\.PowerActual|LogicType\\.PowerGeneration|" + + "LogicType\\.PowerPotential|LogicType\\.PowerRequired|" + + "LogicType\\.PrefabHash|LogicType\\.Pressure|LogicType\\.PressureEfficiency|" + + "LogicType\\.PressureExternal|LogicType\\.PressureInput|" + + "LogicType\\.PressureInput2|LogicType\\.PressureInternal|" + + "LogicType\\.PressureOutput|LogicType\\.PressureOutput2|" + + "LogicType\\.PressureSetting|LogicType\\.Progress|LogicType\\.Quantity|" + + "LogicType\\.Ratio|LogicType\\.RatioCarbonDioxide|LogicType\\.RatioCarbonDioxideInput|" + + "LogicType\\.RatioCarbonDioxideInput2|LogicType\\.RatioCarbonDioxideOutput|" + + "LogicType\\.RatioCarbonDioxideOutput2|LogicType\\.RatioHydrogen|" + + "LogicType\\.RatioLiquidCarbonDioxide|LogicType\\.RatioLiquidCarbonDioxideInput|" + + "LogicType\\.RatioLiquidCarbonDioxideInput2|LogicType\\.RatioLiquidCarbonDioxideOutput|" + + "LogicType\\.RatioLiquidCarbonDioxideOutput2|LogicType\\.RatioLiquidHydrogen|" + + "LogicType\\.RatioLiquidNitrogen|LogicType\\.RatioLiquidNitrogenInput|" + + "LogicType\\.RatioLiquidNitrogenInput2|LogicType\\.RatioLiquidNitrogenOutput|" + + "LogicType\\.RatioLiquidNitrogenOutput2|LogicType\\.RatioLiquidNitrousOxide|" + + "LogicType\\.RatioLiquidNitrousOxideInput|LogicType\\.RatioLiquidNitrousOxideInput2|" + + "LogicType\\.RatioLiquidNitrousOxideOutput|LogicType\\.RatioLiquidNitrousOxideOutput2|" + + "LogicType\\.RatioLiquidOxygen|LogicType\\.RatioLiquidOxygenInput|" + + "LogicType\\.RatioLiquidOxygenInput2|LogicType\\.RatioLiquidOxygenOutput|" + + "LogicType\\.RatioLiquidOxygenOutput2|LogicType\\.RatioLiquidPollutant|" + + "LogicType\\.RatioLiquidPollutantInput|LogicType\\.RatioLiquidPollutantInput2|" + + "LogicType\\.RatioLiquidPollutantOutput|LogicType\\.RatioLiquidPollutantOutput2|" + + "LogicType\\.RatioLiquidVolatiles|LogicType\\.RatioLiquidVolatilesInput|" + + "LogicType\\.RatioLiquidVolatilesInput2|LogicType\\.RatioLiquidVolatilesOutput|" + + "LogicType\\.RatioLiquidVolatilesOutput2|LogicType\\.RatioNitrogen|" + + "LogicType\\.RatioNitrogenInput|LogicType\\.RatioNitrogenInput2|" + + "LogicType\\.RatioNitrogenOutput|LogicType\\.RatioNitrogenOutput2|" + + "LogicType\\.RatioNitrousOxide|LogicType\\.RatioNitrousOxideInput|" + + "LogicType\\.RatioNitrousOxideInput2|LogicType\\.RatioNitrousOxideOutput|" + + "LogicType\\.RatioNitrousOxideOutput2|LogicType\\.RatioOxygen|" + + "LogicType\\.RatioOxygenInput|LogicType\\.RatioOxygenInput2|" + + "LogicType\\.RatioOxygenOutput|LogicType\\.RatioOxygenOutput2|" + + "LogicType\\.RatioPollutant|LogicType\\.RatioPollutantInput|" + + "LogicType\\.RatioPollutantInput2|LogicType\\.RatioPollutantOutput|" + + "LogicType\\.RatioPollutantOutput2|LogicType\\.RatioPollutedWater|" + + "LogicType\\.RatioSteam|LogicType\\.RatioSteamInput|" + + "LogicType\\.RatioSteamInput2|LogicType\\.RatioSteamOutput|" + + "LogicType\\.RatioSteamOutput2|LogicType\\.RatioVolatiles|" + + "LogicType\\.RatioVolatilesInput|LogicType\\.RatioVolatilesInput2|" + + "LogicType\\.RatioVolatilesOutput|LogicType\\.RatioVolatilesOutput2|" + + "LogicType\\.RatioWater|LogicType\\.RatioWaterInput|" + + "LogicType\\.RatioWaterInput2|LogicType\\.RatioWaterOutput|" + + "LogicType\\.RatioWaterOutput2|LogicType\\.ReEntryAltitude|" + + "LogicType\\.Reagents|LogicType\\.RecipeHash|LogicType\\.ReferenceId|" + + "LogicType\\.RequestHash|LogicType\\.RequiredPower|LogicType\\.ReturnFuelCost|" + + "LogicType\\.Richness|LogicType\\.Rpm|LogicType\\.SemiMajorAxis|" + + "LogicType\\.Setting|LogicType\\.SettingInput|LogicType\\.SettingOutput|" + + "LogicType\\.SignalID|LogicType\\.SignalStrength|LogicType\\.Sites|" + + "LogicType\\.Size|LogicType\\.SizeX|LogicType\\.SizeY|" + + "LogicType\\.SizeZ|LogicType\\.SolarAngle|LogicType\\.SolarIrradiance|" + + "LogicType\\.SoundAlert|LogicType\\.Stress|LogicType\\.Survey|" + + "LogicType\\.TargetPadIndex|LogicType\\.TargetX|LogicType\\.TargetY|" + + "LogicType\\.TargetZ|LogicType\\.Temperature|LogicType\\.TemperatureDifferentialEfficiency|" + + "LogicType\\.TemperatureExternal|LogicType\\.TemperatureInput|" + + "LogicType\\.TemperatureInput2|LogicType\\.TemperatureOutput|" + + "LogicType\\.TemperatureOutput2|LogicType\\.TemperatureSetting|" + + "LogicType\\.Throttle|LogicType\\.Thrust|LogicType\\.ThrustToWeight|" + + "LogicType\\.Time|LogicType\\.TimeToDestination|LogicType\\.TotalMoles|" + + "LogicType\\.TotalMolesInput|LogicType\\.TotalMolesInput2|" + + "LogicType\\.TotalMolesOutput|LogicType\\.TotalMolesOutput2|" + + "LogicType\\.TotalQuantity|LogicType\\.TrueAnomaly|LogicType\\.VelocityMagnitude|" + + "LogicType\\.VelocityRelativeX|LogicType\\.VelocityRelativeY|" + + "LogicType\\.VelocityRelativeZ|LogicType\\.VelocityX|" + + "LogicType\\.VelocityY|LogicType\\.VelocityZ|LogicType\\.Vertical|" + + "LogicType\\.VerticalRatio|LogicType\\.Volume|LogicType\\.VolumeOfLiquid|" + + "LogicType\\.WattsReachingContact|LogicType\\.Weight|" + + "LogicType\\.WorkingGasEfficiency|NotEquals|PowerMode\\.Charged|" + + "PowerMode\\.Charging|PowerMode\\.Discharged|PowerMode\\.Discharging|" + + "PowerMode\\.Idle|RobotMode\\.Follow|RobotMode\\.MoveToTarget|" + + "RobotMode\\.None|RobotMode\\.PathToTarget|RobotMode\\.Roam|" + + "RobotMode\\.StorageFull|RobotMode\\.Unload|SlotClass\\.AccessCard|" + + "SlotClass\\.Appliance|SlotClass\\.Back|SlotClass\\.Battery|" + + "SlotClass\\.Belt|SlotClass\\.Blocked|SlotClass\\.Bottle|" + + "SlotClass\\.Cartridge|SlotClass\\.Circuit|SlotClass\\.Circuitboard|" + + "SlotClass\\.CreditCard|SlotClass\\.DataDisk|SlotClass\\.DirtCanister|" + + "SlotClass\\.DrillHead|SlotClass\\.Egg|SlotClass\\.Entity|" + + "SlotClass\\.Flare|SlotClass\\.GasCanister|SlotClass\\.GasFilter|" + + "SlotClass\\.Glasses|SlotClass\\.Helmet|SlotClass\\.Ingot|" + + "SlotClass\\.LiquidBottle|SlotClass\\.LiquidCanister|" + + "SlotClass\\.Magazine|SlotClass\\.Motherboard|SlotClass\\.None|" + + "SlotClass\\.Ore|SlotClass\\.Organ|SlotClass\\.Plant|" + + "SlotClass\\.ProgrammableChip|SlotClass\\.ScanningHead|" + + "SlotClass\\.SensorProcessingUnit|SlotClass\\.SoundCartridge|" + + "SlotClass\\.Suit|SlotClass\\.Tool|SlotClass\\.Torpedo|" + + "SlotClass\\.Uniform|SlotClass\\.Wreckage|SortingClass\\.Appliances|" + + "SortingClass\\.Atmospherics|SortingClass\\.Clothing|" + + "SortingClass\\.Default|SortingClass\\.Food|SortingClass\\.Ices|" + + "SortingClass\\.Kits|SortingClass\\.Ores|SortingClass\\.Resources|" + + "SortingClass\\.Storage|SortingClass\\.Tools|Sound\\.AirlockCycling|" + + "Sound\\.Alarm1|Sound\\.Alarm10|Sound\\.Alarm11|Sound\\.Alarm12|" + + "Sound\\.Alarm2|Sound\\.Alarm3|Sound\\.Alarm4|Sound\\.Alarm5|" + + "Sound\\.Alarm6|Sound\\.Alarm7|Sound\\.Alarm8|Sound\\.Alarm9|" + + "Sound\\.Alert|Sound\\.Danger|Sound\\.Depressurising|" + + "Sound\\.FireFireFire|Sound\\.Five|Sound\\.Floor|Sound\\.Four|" + + "Sound\\.HaltWhoGoesThere|Sound\\.HighCarbonDioxide|" + + "Sound\\.IntruderAlert|Sound\\.LiftOff|Sound\\.MalfunctionDetected|" + + "Sound\\.Music1|Sound\\.Music2|Sound\\.Music3|Sound\\.None|" + + "Sound\\.One|Sound\\.PollutantsDetected|Sound\\.PowerLow|" + + "Sound\\.PressureHigh|Sound\\.PressureLow|Sound\\.Pressurising|" + + "Sound\\.RocketLaunching|Sound\\.StormIncoming|Sound\\.SystemFailure|" + + "Sound\\.TemperatureHigh|Sound\\.TemperatureLow|Sound\\.Three|" + + "Sound\\.TraderIncoming|Sound\\.TraderLanded|Sound\\.Two|" + + "Sound\\.Warning|Sound\\.Welcome|TransmitterMode\\.Active|" + + "TransmitterMode\\.Passive|Vent\\.Inward|Vent\\.Outward"); - this.$rules = { - start: [{ - token : "comment.line.number-sign", - regex: /#.*$/, - }, { - token: ["text", "keyword", "text", "entity.name.tag"], - regex: /^(\s*)(j(?:al)?)(\s+)([a-zA-Z_.][a-zA-Z0-9_.]*)/, - comment: "absolute jumps | branches with a label" - }, { - token: "keyword", - regex: "^\\s*(?:" + ops + ")\\b", - }, { - token: "entity.name.tag", - regex: /^\s*[a-zA-Z_.][a-zA-Z0-9_.]*\b:/, - comment: "Labels at line start: begin_repeat: add ..." - }, { - token: "variable.parameter", - regex: /\b(?:sp|r(?:a|r*)(?:[0-9]|1[0-7]))\b/, - }, { - token: "variable.language", - regex: /\b(?:d(?:b|[0-5]|r*(?:[0-9]|1[0-7]))(?::[0-9]+)?)\b/, - }, { - token: "support.type", - regex: "\\b(?:" + logictypes + ")\\b", - }, { - token: "constant.language", - regex: "\\b(?:" + constants + ")\\b", - }, { - token: "variable.language", - regex: "\\b(?:" + enums + ")\\b", - }, { - token: "constant.numeric.ic10", - regex: /\-?[0-9]+(?:\.[0-9]+)?|\$[a-fA-F0-9_]+|%[01_]+/, - comment: "Numbers like 12, -3.0, 55, $3F, %1000" - }, { - token: ["support.function", "paren.lparen", "string.quoted", "paren.rparen"], - regex: /\b(HASH)(\()(\".*\")(\))/, - }, { - token: "entity.name", - regex: /\b[a-zA-Z_.][a-zA-Z0-9_.]*\b/, - }] - }; +var logictypes = ( + "Acceleration|Activate|AirRelease|AlignmentError|Apex|AutoLand|" + + "AutoShutOff|Bpm|BurnTimeRemaining|CelestialHash|CelestialParentHash|" + + "Channel0|Channel1|Channel2|Channel3|Channel4|Channel5|Channel6|" + + "Channel7|Charge|Chart|ChartedNavPoints|ClearMemory|CollectableGoods|" + + "Color|Combustion|CombustionInput|CombustionInput2|CombustionLimiter|" + + "CombustionOutput|CombustionOutput2|CompletionRatio|ContactTypeId|" + + "CurrentCode|CurrentResearchPodType|Density|DestinationCode|Discover|" + + "DistanceAu|DistanceKm|DrillCondition|DryMass|Eccentricity|ElevatorLevel|" + + "ElevatorSpeed|EntityState|EnvironmentEfficiency|Error|ExhaustVelocity|" + + "ExportCount|ExportQuantity|ExportSlotHash|ExportSlotOccupant|" + + "Filtration|FlightControlRule|Flush|ForceWrite|ForwardX|ForwardY|" + + "ForwardZ|Fuel|Harvest|Horizontal|HorizontalRatio|Idle|ImportCount|" + + "ImportQuantity|ImportSlotHash|ImportSlotOccupant|Inclination|" + + "Index|InterrogationProgress|LineNumber|Lock|ManualResearchRequiredPod|" + + "Mass|Maximum|MineablesInQueue|MineablesInVicinity|MinedQuantity|" + + "MinimumWattsToContact|Mode|NavPoints|NextWeatherEventTime|None|" + + "On|Open|OperationalTemperatureEfficiency|OrbitPeriod|Orientation|" + + "Output|PassedMoles|Plant|PlantEfficiency1|PlantEfficiency2|PlantEfficiency3|" + + "PlantEfficiency4|PlantGrowth1|PlantGrowth2|PlantGrowth3|PlantGrowth4|" + + "PlantHash1|PlantHash2|PlantHash3|PlantHash4|PlantHealth1|PlantHealth2|" + + "PlantHealth3|PlantHealth4|PositionX|PositionY|PositionZ|Power|" + + "PowerActual|PowerGeneration|PowerPotential|PowerRequired|PrefabHash|" + + "Pressure|PressureEfficiency|PressureExternal|PressureInput|PressureInput2|" + + "PressureInternal|PressureOutput|PressureOutput2|PressureSetting|" + + "Progress|Quantity|Ratio|RatioCarbonDioxide|RatioCarbonDioxideInput|" + + "RatioCarbonDioxideInput2|RatioCarbonDioxideOutput|RatioCarbonDioxideOutput2|" + + "RatioHydrogen|RatioLiquidCarbonDioxide|RatioLiquidCarbonDioxideInput|" + + "RatioLiquidCarbonDioxideInput2|RatioLiquidCarbonDioxideOutput|" + + "RatioLiquidCarbonDioxideOutput2|RatioLiquidHydrogen|RatioLiquidNitrogen|" + + "RatioLiquidNitrogenInput|RatioLiquidNitrogenInput2|RatioLiquidNitrogenOutput|" + + "RatioLiquidNitrogenOutput2|RatioLiquidNitrousOxide|RatioLiquidNitrousOxideInput|" + + "RatioLiquidNitrousOxideInput2|RatioLiquidNitrousOxideOutput|RatioLiquidNitrousOxideOutput2|" + + "RatioLiquidOxygen|RatioLiquidOxygenInput|RatioLiquidOxygenInput2|" + + "RatioLiquidOxygenOutput|RatioLiquidOxygenOutput2|RatioLiquidPollutant|" + + "RatioLiquidPollutantInput|RatioLiquidPollutantInput2|RatioLiquidPollutantOutput|" + + "RatioLiquidPollutantOutput2|RatioLiquidVolatiles|RatioLiquidVolatilesInput|" + + "RatioLiquidVolatilesInput2|RatioLiquidVolatilesOutput|RatioLiquidVolatilesOutput2|" + + "RatioNitrogen|RatioNitrogenInput|RatioNitrogenInput2|RatioNitrogenOutput|" + + "RatioNitrogenOutput2|RatioNitrousOxide|RatioNitrousOxideInput|" + + "RatioNitrousOxideInput2|RatioNitrousOxideOutput|RatioNitrousOxideOutput2|" + + "RatioOxygen|RatioOxygenInput|RatioOxygenInput2|RatioOxygenOutput|" + + "RatioOxygenOutput2|RatioPollutant|RatioPollutantInput|RatioPollutantInput2|" + + "RatioPollutantOutput|RatioPollutantOutput2|RatioPollutedWater|" + + "RatioSteam|RatioSteamInput|RatioSteamInput2|RatioSteamOutput|" + + "RatioSteamOutput2|RatioVolatiles|RatioVolatilesInput|RatioVolatilesInput2|" + + "RatioVolatilesOutput|RatioVolatilesOutput2|RatioWater|RatioWaterInput|" + + "RatioWaterInput2|RatioWaterOutput|RatioWaterOutput2|ReEntryAltitude|" + + "Reagents|RecipeHash|ReferenceId|RequestHash|RequiredPower|ReturnFuelCost|" + + "Richness|Rpm|SemiMajorAxis|Setting|SettingInput|SettingOutput|" + + "SignalID|SignalStrength|Sites|Size|SizeX|SizeY|SizeZ|SolarAngle|" + + "SolarIrradiance|SoundAlert|Stress|Survey|TargetPadIndex|TargetX|" + + "TargetY|TargetZ|Temperature|TemperatureDifferentialEfficiency|" + + "TemperatureExternal|TemperatureInput|TemperatureInput2|TemperatureOutput|" + + "TemperatureOutput2|TemperatureSetting|Throttle|Thrust|ThrustToWeight|" + + "Time|TimeToDestination|TotalMoles|TotalMolesInput|TotalMolesInput2|" + + "TotalMolesOutput|TotalMolesOutput2|TotalQuantity|TrueAnomaly|" + + "VelocityMagnitude|VelocityRelativeX|VelocityRelativeY|VelocityRelativeZ|" + + "VelocityX|VelocityY|VelocityZ|Vertical|VerticalRatio|Volume|VolumeOfLiquid|" + + "WattsReachingContact|Weight|WorkingGasEfficiency"); - this.normalizeRules(); +var logictypes = ( + "Acceleration|Activate|AirRelease|AlignmentError|Apex|AutoLand|" + + "AutoShutOff|Average|Bpm|BurnTimeRemaining|Bypass|CelestialHash|" + + "CelestialParentHash|Channel|Channel0|Channel1|Channel2|Channel3|" + + "Channel4|Channel5|Channel6|Channel7|Charge|ChargeRatio|Class|" + + "ClearMemory|CollectableGoods|Color|Combustion|CombustionInput|" + + "CombustionInput2|CombustionLimiter|CombustionOutput|CombustionOutput2|" + + "CompletionRatio|ContactTypeId|Contents|CurrentResearchPodType|Damage|" + + "DestinationCode|DistanceAu|DistanceKm|DrillCondition|DryMass|" + + "Eccentricity|Efficiency|ElevatorLevel|ElevatorSpeed|EntityState|" + + "EnvironmentEfficiency|Error|ExhaustVelocity|ExportCount|" + + "ExportQuantity|ExportSlotHash|ExportSlotOccupant|FilterType|" + + "Filtration|FlightControlRule|Flush|ForceWrite|ForwardX|ForwardY|" + + "ForwardZ|Fuel|Growth|Harvest|Health|Horizontal|HorizontalRatio|" + + "Idle|ImportCount|ImportQuantity|ImportSlotHash|ImportSlotOccupant|" + + "Inclination|Index|InterrogationProgress|LineNumber|Lock|" + + "ManualResearchRequiredPod|Mass|Mature|MaxQuantity|Maximum|" + + "MinWattsToContact|MineablesInQueue|MineablesInVicinity|Minimum|" + + "MinimumWattsToContact|Mode|NextWeatherEventTime|None|OccupantHash|" + + "Occupied|On|Open|OperationalTemperatureEfficiency|OrbitPeriod|" + + "Orientation|Output|OverShootTarget|PassedMoles|Plant|" + + "PlantEfficiency1|PlantEfficiency2|PlantEfficiency3|PlantEfficiency4|" + + "PlantGrowth1|PlantGrowth2|PlantGrowth3|PlantGrowth4|PlantHash1|" + + "PlantHash2|PlantHash3|PlantHash4|PlantHealth1|PlantHealth2|" + + "PlantHealth3|PlantHealth4|PositionX|PositionY|PositionZ|Power|" + + "PowerActual|PowerGeneration|PowerPotential|PowerRequired|" + + "PrefabHash|Pressure|PressureAir|PressureEfficiency|PressureExternal|" + + "PressureInput|PressureInput2|PressureInternal|PressureOutput|" + + "PressureOutput2|PressureSetting|PressureWaste|Progress|Quantity|" + + "Ratio|RatioCarbonDioxide|RatioCarbonDioxideInput|" + + "RatioCarbonDioxideInput2|RatioCarbonDioxideOutput|" + + "RatioCarbonDioxideOutput2|RatioLiquidCarbonDioxide|" + + "RatioLiquidCarbonDioxideInput|RatioLiquidCarbonDioxideInput2|" + + "RatioLiquidCarbonDioxideOutput|RatioLiquidCarbonDioxideOutput2|" + + "RatioLiquidNitrogen|RatioLiquidNitrogenInput|" + + "RatioLiquidNitrogenInput2|RatioLiquidNitrogenOutput|" + + "RatioLiquidNitrogenOutput2|RatioLiquidNitrousOxide|" + + "RatioLiquidNitrousOxideInput|RatioLiquidNitrousOxideInput2|" + + "RatioLiquidNitrousOxideOutput|RatioLiquidNitrousOxideOutput2|" + + "RatioLiquidOxygen|RatioLiquidOxygenInput|RatioLiquidOxygenInput2|" + + "RatioLiquidOxygenOutput|RatioLiquidOxygenOutput2|" + + "RatioLiquidPollutant|RatioLiquidPollutantInput|" + + "RatioLiquidPollutantInput2|RatioLiquidPollutantOutput|" + + "RatioLiquidPollutantOutput2|RatioLiquidVolatiles|" + + "RatioLiquidVolatilesInput|RatioLiquidVolatilesInput2|" + + "RatioLiquidVolatilesOutput|RatioLiquidVolatilesOutput2|" + + "RatioNitrogen|RatioNitrogenInput|RatioNitrogenInput2|" + + "RatioNitrogenOutput|RatioNitrogenOutput2|RatioNitrousOxide|" + + "RatioNitrousOxideInput|RatioNitrousOxideInput2|" + + "RatioNitrousOxideOutput|RatioNitrousOxideOutput2|RatioOxygen|" + + "RatioOxygenInput|RatioOxygenInput2|RatioOxygenOutput|" + + "RatioOxygenOutput2|RatioPollutant|RatioPollutantInput|" + + "RatioPollutantInput2|RatioPollutantOutput|RatioPollutantOutput2|" + + "RatioSteam|RatioSteamInput|RatioSteamInput2|RatioSteamOutput|" + + "RatioSteamOutput2|RatioVolatiles|RatioVolatilesInput|" + + "RatioVolatilesInput2|RatioVolatilesOutput|RatioVolatilesOutput2|" + + "RatioWater|RatioWaterInput|RatioWaterInput2|RatioWaterOutput|" + + "RatioWaterOutput2|ReEntryAltitude|Reagents|Recipe|RecipeHash|" + + "ReferenceId|RequestHash|Required|RequiredPower|ReturnFuelCost|Rpm|" + + "Seeding|SemiMajorAxis|Setting|SettingInput|SettingInputHash|" + + "SettingOutput|SettingOutputHash|SignalID|SignalStrength|SizeX|SizeY|" + + "SizeZ|SolarAngle|SolarConstant|SolarIrradiance|SortingClass|" + + "SoundAlert|Stress|Sum|TargetPadIndex|TargetX|TargetY|TargetZ|" + + "Temperature|TemperatureDifferentialEfficiency|TemperatureExternal|" + + "TemperatureInput|TemperatureInput2|TemperatureOutput|" + + "TemperatureOutput2|TemperatureSetting|Throttle|Thrust|ThrustToWeight|" + + "Time|TimeToDestination|TotalMoles|TotalMolesInput|TotalMolesInput2|" + + "TotalMolesOutput|TotalMolesOutput2|TrueAnomaly|Unknown|" + + "VelocityMagnitude|VelocityRelativeX|VelocityRelativeY|" + + "VelocityRelativeZ|VelocityX|VelocityY|VelocityZ|Vertical|" + + "VerticalRatio|Volume|VolumeOfLiquid|WattsReachingContact|Weight" + + "|WorkingGasEfficiency" +); + +var logicslottypes = ( + "Charge|ChargeRatio|Class|Damage|Efficiency|FilterType|Growth|" + + "Health|LineNumber|Lock|Mature|MaxQuantity|None|OccupantHash|" + + "Occupied|On|Open|PrefabHash|Pressure|PressureAir|PressureWaste|" + + "Quantity|ReferenceId|Seeding|SortingClass|Temperature|Volume" +); + +var batchmodes = ("Average|Maximum|Minimum|Sum"); + +var reagentmodes = ("Contents|Recipe|Required|TotalContents"); + +var constants = ("nan|pinf|ninf|pi|deg2rad|rad2deg|epsilon"); + +var deprecated = ( + "ExportSlotHash|ExportSlotOccupant|ImportSlotHash|ImportSlotOccupant|" + + "LogicType.ExportSlotHash|LogicType.ExportSlotOccupant|LogicType.ImportSlotHash|" + + "LogicType.ImportSlotOccupant|LogicType.PlantEfficiency1|LogicType.PlantEfficiency2|" + + "LogicType.PlantEfficiency3|LogicType.PlantEfficiency4|LogicType.PlantGrowth1|" + + "LogicType.PlantGrowth2|LogicType.PlantGrowth3|LogicType.PlantGrowth4|" + + "LogicType.PlantHash1|LogicType.PlantHash2|LogicType.PlantHash3|LogicType.PlantHash4|" + + "LogicType.PlantHealth1|LogicType.PlantHealth2|LogicType.PlantHealth3|LogicType.PlantHealth4|" + + "PlantEfficiency1|PlantEfficiency2|PlantEfficiency3|PlantEfficiency4|" + + "PlantGrowth1|PlantGrowth2|PlantGrowth3|PlantGrowth4|PlantHash1|PlantHash2|" + + "PlantHash3|PlantHash4|PlantHealth1|PlantHealth2|PlantHealth3|PlantHealth4" +); + +// regexp must not have capturing parentheses. Use (?:) instead. +// regexps are ordered -> the first match is used +var rules = { + start: [{ + token: "comment.line.number-sign", + regex: /#.*$/, + }, { + token: ["text", "keyword", "text", "entity.name.tag"], + regex: /^(\s*)(j(?:al)?)(\s+)([a-zA-Z_.][a-zA-Z0-9_.]*)/, + comment: "absolute jumps | branches with a label" + }, { + token: "keyword", + regex: "^\\s*(?:" + ops + ")\\b", + }, { + token: "entity.name.tag", + regex: /^\s*[a-zA-Z_.][a-zA-Z0-9_.]*\b:/, + comment: "Labels at line start: begin_repeat: add ..." + }, { + token: "variable.parameter", + regex: /\b(?:sp|r(?:a|r*)(?:[0-9]|1[0-7]))\b/, + }, { + token: "variable.language", + regex: /\b(?:d(?:b|[0-5]|r*(?:[0-9]|1[0-7]))(?::[0-9]+)?)\b/, + }, { + token: "support.type", + regex: "\\b(?:" + logictypes + "|" + logicslottypes + "|" + batchmodes + "|" + reagentmodes + ")\\b", + }, { + token: "invalid.deprecated", + regex: "\\b(?:" + deprecated + ")\\b", + }, + { + token: "constant.language", + regex: "\\b(?:" + constants + ")\\b", + }, { + token: "variable.language", + regex: "\\b(?:" + enums + ")\\b", + }, { + token: "constant.numeric.ic10", + regex: /\-?[0-9]+(?:\.[0-9]+)?|\$[a-fA-F0-9_]+|%[01_]+/, + comment: "Numbers like 12, -3.0, 55, $3F, %1000" + }, { + token: ["support.function", "paren.lparen", "string.quoted", "paren.rparen"], + regex: /\b(HASH)(\()(\".*\")(\))/, + }, { + token: "entity.name", + regex: /\b[a-zA-Z_.][a-zA-Z0-9_.]*\b/, + }] }; -IC10HighlightRules.metaData = { - fileTypes: ["ic10"], - name: "ic10", - scopeName: "source.ic10" -}; - - -oop.inherits(IC10HighlightRules, TextHighlightRules); - -exports.IC10HighlightRules = IC10HighlightRules; +export { rules }; \ No newline at end of file diff --git a/www/src/js/editor/ic10_mode.ts b/www/src/js/editor/ic10_mode.ts index b055600..6977e05 100644 --- a/www/src/js/editor/ic10_mode.ts +++ b/www/src/js/editor/ic10_mode.ts @@ -1,22 +1,51 @@ -"use strict"; +import ace from 'ace-builds'; +import { rules as highlightRules } from "./ic10_highlight_rules"; -var oop = require("ace-code/src/lib/oop"); -var TextMode = require("ace-code/src/mode/text").Mode; -var FoldMode = require("ace-code/src/mode/folding/cstyle").FoldMode; -var IC10HighlightRules = require("./ic10_highlight_rules.js").IC10HighlightRules; +//Support function to create Ace mode +function createAceMode(modeName: string, highlighterObj: ace.Ace.HighlightRulesMap) { + (ace as any).define(modeName, ["require", "exports", "module"], function (require: any, exports: any, module: any) { + console.log(require); + var oop = require("ace/lib/oop"); + var TextMode = require("ace/mode/text").Mode; + var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules; + var WorkerClient = require("ace/worker/worker_client").WorkerClient; -var Mode = function() { - this.HighlightRules = IC10HighlightRules; - this.foldingRules = new FoldMode(); + var HighlightRules = function () { + this.$rules = highlighterObj; + this.normalizeRules(); + }; + oop.inherits(HighlightRules, TextHighlightRules); + (HighlightRules as any).metaData = { + fileTypes: [modeName], + name: modeName, + scopeName: `source.${modeName}` + }; + var CustomMode = function () { + this.HighlightRules = HighlightRules; + }; + oop.inherits(CustomMode, TextMode); + + (function () { + //Create worker for live syntax checking + this.createWorker = function (session: ace.Ace.EditSession) { + session.on("change", function () { + session.clearAnnotations(); + let annotations: ace.Ace.Annotation[] = []; + for (let row = 0; row < session.getLength(); row++) { + let tokens = session.getTokens(row); + if (!tokens || tokens.length == 0) continue; + tokens.forEach(token => { + if (token.type === "invalid") annotations.push({ row: row, column: 0, text: "This need to be fixed!", type: "error" }); + }); + } + session.setAnnotations(annotations); + }); + } + this.lineCommentStart = ["#"]; + this.$id = modeName; + }).call(CustomMode.prototype); + exports.Mode = CustomMode; + }); } -oop.inherits(Mode, TextMode); - -(function() { - // configure comment start/end characters - this.lineCommentStart = ["#"]; - this.$id = "ace/mode/ic10"; - -}).call(Mode.prototype); - -exports.Mode = Mode; +createAceMode("ace/mode/ic10", highlightRules); diff --git a/www/src/js/editor/index.ts b/www/src/js/editor/index.ts index 9702baa..d4f0d66 100644 --- a/www/src/js/editor/index.ts +++ b/www/src/js/editor/index.ts @@ -1,18 +1,35 @@ -import { ace } from "./ace.js" -import { Mode as IC10Mode } from "./ic10_mode.js"; -import * as one_dark from "ace-code/src/theme/one_dark"; +// import { ace } from "./ace.js" +import ace from "ace-builds"; +import "ace-builds/esm-resolver"; + +// patch prompt ext +ace.config.setModuleLoader('ace/ext/prompt', () => import('./prompt_patch')); +ace.config.setDefaultValue("session", "theme", "ace/theme/one_dark"); + + +import "ace-builds/src-noconflict/ext-language_tools"; +ace.require("ace/ext/language_tools"); + +import "./ic10_mode"; import { AceLanguageClient } from "ace-linters/build/ace-language-client"; -import { IC10EditorUI } from './ui.js'; -import { Range } from 'ace-code/src/range.js'; +import { IC10EditorUI } from './ui'; +import { Range } from 'ace-builds'; + +import { App } from "../index"; +import { Session } from "../session"; + +// import { Mode as TextMode } from 'ace-code/src/mode/text'; // to make sure language tools are loaded -import _ace_ext_langue_tools from "ace-code/src/ext/language_tools"; +ace.config.loadModule("ace/ext/language_tools"); + +import { Mode as TextMode } from "ace-builds/src-noconflict/mode-text"; async function setupLspWorker() { // Create a web worker - let worker = new Worker(new URL('./lspWorker.js', import.meta.url)); + let worker = new Worker(new URL('./lspWorker.ts', import.meta.url)); - const loaded = w => + const loaded = (w: Worker) => new Promise(r => w.addEventListener("message", r, { once: true })); await Promise.all([loaded(worker)]); @@ -20,11 +37,22 @@ async function setupLspWorker() { return worker; } +declare global { + interface Window { Editor: IC10Editor } +} class IC10Editor { - constructor(session_id) { + mode: string; + settings: { keyboard: string; cursor: string; fontSize: number; relativeLineNumbers: boolean; }; + aceEditor: ace.Ace.Editor; + sessions: Map; + active_session: number; + active_line_markers: Map; + languageProvider: null | AceLanguageClient; + ui: IC10EditorUI; + constructor(session_id: number) { window.Editor = this; - this.mode = new IC10Mode(); + this.mode = "ace/mode/ic10"; this.settings = { keyboard: "ace", @@ -39,19 +67,19 @@ class IC10Editor { enableLiveAutocompletion: true, enableSnippets: true, theme: "ace/theme/one_dark", - fontSize: "16px", + fontSize: 16, customScrollbar: false, firstLineNumber: 0, printMarginColumn: 52, placeholder: "Your code goes here ...", }); - this.sessions = {}; - this.sessions[session_id] = this.aceEditor.getSession(); + this.sessions = new Map(); + this.sessions.set(session_id, this.aceEditor.getSession()); this.active_session = session_id; - this.bindSession(session_id, this.sessions[session_id]); - this.active_line_markers = {}; - this.active_line_markers[session_id] = null; + this.bindSession(session_id, this.sessions.get(session_id)); + this.active_line_markers = new Map(); + this.active_line_markers.set(session_id, null); this.languageProvider = null; @@ -59,35 +87,37 @@ class IC10Editor { const that = this; - App.session.onLoad((session) => { + App.session.onLoad((session: Session ) => { const updated_ids = []; - for (const id in session.programs) { + for (const [id, _] of session.programs) { updated_ids.push(id); - that.createOrSetSession(id, session.programs[id]); + that.createOrSetSession(id, session.programs.get(id)); } - for (const id in that.sessions) { + that.activateSession(that.active_session); + for (const [id, _] of that.sessions) { if (!updated_ids.includes(id)) { that.destroySession(id); } } + }); App.session.loadFromFragment(); - App.session.onActiveLine(session => { - for (const id in Object.keys(session.programs)) { + App.session.onActiveLine((session: Session) => { + for (const id of session.programs.keys()) { const active_line = session.getActiveLine(id); if (typeof active_line !== "undefined") { - const marker = that.active_line_markers[id]; + const marker = that.active_line_markers.get(id); if (marker) { - that.sessions[id].removeMarker(marker); - that.active_line_markers[id] = null; + that.sessions.get(id).removeMarker(marker); + that.active_line_markers.set(id, null); } - const session = that.sessions[id]; + const session = that.sessions.get(id); if (session) { - that.active_line_markers[id] = session.addMarker(new Range(active_line, 0, active_line, 1), "vm_ic_active_line", "fullLine", true); + that.active_line_markers.set(id, session.addMarker(new Range(active_line, 0, active_line, 1), "vm_ic_active_line", "fullLine", true)); if (that.active_session == id) { // editor.resize(true); - that.aceEditor.scrollToLine(active_line, true, true) + that.aceEditor.scrollToLine(active_line, true, true, ()=>{}) } } } @@ -96,34 +126,26 @@ class IC10Editor { } - createOrSetSession(session_id, content) { + createOrSetSession(session_id: number, content: any) { if (!this.sessions.hasOwnProperty(session_id)) { this.newSession(session_id); } - this.sessions[session_id].setValue(content); + this.sessions.get(session_id).setValue(content); } - newSession(session_id) { + newSession(session_id: number) { if (this.sessions.hasOwnProperty(session_id)) { return false; } - const session = ace.createEditSession("", this.mode); + const session = ace.createEditSession("", this.mode as any); session.setOptions({ - enableBasicAutocompletion: true, - enableLiveAutocompletion: true, - enableSnippets: true, - theme: "ace/theme/one_dark", - fontSize: "16px", - customScrollbar: false, firstLineNumber: 0, - printMarginColumn: 52, - placeholder: "Your code goes here ...", }) - this.sessions[session_id] = session; + this.sessions.set(session_id, session); this.bindSession(session_id, session); } - setupLsp(lsp_worker) { + setupLsp(lsp_worker: Worker) { const serverData = { module: () => import("ace-linters/build/language-client"), modes: "ic10", @@ -131,26 +153,22 @@ class IC10Editor { worker: lsp_worker, }; // Create a language provider for web worker - this.languageProvider = AceLanguageClient.for(serverData); - this.languageProvider.registerEditor(this.aceEditor); + this.languageProvider = AceLanguageClient.for(serverData as any); + (this.languageProvider as any).registerEditor(this.aceEditor); - for (const session_id in this.sessions) { - let options = this.mode.options ?? {}; - this.languageProvider.setSessionOptions(this.sessions[session_id], options); - } + // for (const session_id of this.sessions.keys()) { + // let options = {}; + // (this.languageProvider as any).setSessionOptions(this.sessions.get(session_id), options); + // } } - activateSession(session_id) { - if (!this.sessions.hasOwnProperty(session_id)) { + activateSession(session_id: number) { + if (!this.sessions.get(session_id)) { return false; } - this.aceEditor.setSession(this.sessions[session_id]); + this.aceEditor.setSession(this.sessions.get(session_id)); this.active_session = session_id; - let options = this.mode.options ?? {}; - if (this.languageProvider !== null) { - this.languageProvider.setSessionOptions(this.sessions[session_id], options); - } return true; } @@ -172,23 +190,23 @@ class IC10Editor { window.localStorage.setItem("editorSettings", toSave); } - destroySession(session_id) { + destroySession(session_id: number) { if (!this.sessions.hasOwnProperty(session_id)) { return false; } if (!(Object.keys(this.sessions).length > 1)) { return false; } - const session = this.sessions[session_id]; - delete this.sessions[session_id]; + const session = this.sessions.get(session_id); + this.sessions.delete(session_id); if (this.active_session = session_id) { - this.activateSession(Object.keys(this.sessions)[0]); + this.activateSession(this.sessions.entries().next().value); } session.destroy(); return true; } - bindSession(session_id, session) { + bindSession(session_id: number, session: ace.Ace.EditSession) { session.on('change', () => { var val = session.getValue(); window.App.session.setProgramCode(session_id, val); diff --git a/www/src/js/editor/lspWorker.ts b/www/src/js/editor/lspWorker.ts index 0d93a76..60afa33 100644 --- a/www/src/js/editor/lspWorker.ts +++ b/www/src/js/editor/lspWorker.ts @@ -1,21 +1,20 @@ import { ServerConfig, serve } from "ic10lsp_wasm"; -import { v4 as uuidv4 } from 'uuid'; export const encoder = new TextEncoder(); export const decoder = new TextDecoder(); export default class Bytes { - static encode(input) { + static encode(input: string) { return encoder.encode(input); } - static decode(input) { + static decode(input: Uint8Array) { return decoder.decode(input); } static append( - constructor, - ...arrays + constructor: Uint8ArrayConstructor, + ...arrays: Uint8Array[] ) { let totalLength = 0; for (const arr of arrays) { @@ -31,23 +30,23 @@ export default class Bytes { } } -export class AsyncStreamQueue { +export class AsyncStreamQueue implements AsyncIterator { - promises = []; - resolvers = []; - observers = []; + promises: Promise[] = []; + resolvers: Promise[] = []; + observers: any = []; closed = false; - locked = false; tag = ""; + stream: WritableStream; - static __add(promises, resolvers) { + static __add(promises: any[], resolvers: any[]) { promises.push(new Promise((resolve) => { resolvers.push(resolve); })) } - static __enqueue(closed, promises, resolvers, item) { + static __enqueue(closed: boolean, promises: any[], resolvers: any[], item: any) { if (!closed) { if (!resolvers.length) AsyncStreamQueue.__add(promises, resolvers); const resolve = resolvers.shift(); @@ -55,7 +54,7 @@ export class AsyncStreamQueue { } } - constructor(tag) { + constructor(tag: string) { this.tag = tag; const closed = this.closed; // invariant: at least one of the arrays is empty @@ -72,7 +71,7 @@ export class AsyncStreamQueue { return AsyncStreamQueue.__add(this.promises, this.resolvers); } - enqueue(item) { + enqueue(item: Uint8Array) { return AsyncStreamQueue.__enqueue(this.closed, this.promises, this.resolvers, item); } @@ -95,17 +94,17 @@ export class AsyncStreamQueue { return this.promises.length - this.resolvers.length; } - return() { + /* return() { return new Promise(() => { }) } - throw(err) { + throw(err: any) { return new Promise((_resolve, reject) => { reject(err); }) - } + } */ - async next() { + async next(): Promise> { const done = false; // console.log(`AsyncStream(${this.tag}) waiting for message`) const value = await this.dequeue(); @@ -117,11 +116,11 @@ export class AsyncStreamQueue { return this; } - locked() { + get locked() { return this.stream.locked; } - abort(reason) { + abort(reason: any) { return this.stream.abort(reason); } @@ -142,8 +141,7 @@ async function start() { await serve(config); } -function fixup(data) { - // data.id = uuidv4(); +function fixup(data: { hasOwnProperty: (arg0: string) => any; params: { hasOwnProperty: (arg0: string) => any; rootUri: string; textDocument: { hasOwnProperty: (arg0: string) => any; uri: string; }; }; }) { if (data.hasOwnProperty("params") && data.params.hasOwnProperty("rootUri") && data.params.rootUri === "") { data.params.rootUri = null } @@ -159,7 +157,7 @@ function fixup(data) { return data } -function sendClient(data) { +function sendClient(data: any) { data = fixup(data); const data_j = JSON.stringify(data); const msg = `Content-Length: ${data_j.length}\r\n\r\n${data_j}` @@ -212,7 +210,7 @@ listen(); postMessage("ready"); -onmessage = function(e) { +onmessage = function (e) { console.log("Client Message:", e.data); sendClient(e.data) } diff --git a/www/src/js/editor/prompt_patch.ts b/www/src/js/editor/prompt_patch.ts index d2975ef..7cd4262 100644 --- a/www/src/js/editor/prompt_patch.ts +++ b/www/src/js/editor/prompt_patch.ts @@ -1,11 +1,12 @@ -const ace_prompt = require('ace-code/src/ext/prompt.js').prompt; +import { prompt as ace_prompt } from "ace-builds/src-noconflict/ext-prompt" + console.log(ace_prompt); -function prompt(editor, message, options, callback) { +function prompt(editor: { cmdLine: { setTheme: (arg0: string) => void; }; }, message: any, options: any, callback: any) { ace_prompt(editor, message, options, callback); if (editor.cmdLine) { editor.cmdLine.setTheme("ace/theme/one_dark"); } } -exports.prompt = prompt; +export { prompt }; diff --git a/www/src/js/editor/ui.ts b/www/src/js/editor/ui.ts index f5049f1..4968470 100644 --- a/www/src/js/editor/ui.ts +++ b/www/src/js/editor/ui.ts @@ -1,9 +1,11 @@ -import { ace } from "./ace"; +import { IC10Editor } from "."; +import * as ace from "ace-builds"; import { Offcanvas } from 'bootstrap'; class IC10EditorUI { + ic10editor: IC10Editor; - constructor(ic10editor) { + constructor(ic10editor: IC10Editor) { const that = this; @@ -13,11 +15,11 @@ class IC10EditorUI { name: "showSettingsMenu", description: "Show settings menu", bindKey: { win: "Ctrl-,", mac: "Command-," }, - exec: (_editor) => { + exec: (_editor: ace.Ace.Editor) => { const offCanvas = new Offcanvas(document.getElementById("editorSettings")); offCanvas.toggle(); } - }); + } as any); ace.config.loadModule("ace/ext/keyboard_menu", function (module) { console.log("keybinding_menu loaded"); @@ -32,7 +34,7 @@ class IC10EditorUI { document.getElementsByName("editorKeybindRadio").forEach((el) => { el.addEventListener('change', (e) => { - that.ic10editor.settings.keyboard = e.target.value; + that.ic10editor.settings.keyboard = (e.target as any).value; that.ic10editor.saveEditorSettings(); that.updateEditorSettings(); }); @@ -40,18 +42,18 @@ class IC10EditorUI { document.getElementsByName("editorCursorRadio").forEach((el) => { el.addEventListener('change', (e) => { - that.ic10editor.settings.cursor = e.target.value; + that.ic10editor.settings.cursor = (e.target as any).value; that.ic10editor.saveEditorSettings(); that.updateEditorSettings(); }); }); document.getElementById("editorSettingsFontSize").addEventListener('change', (e) => { - window.App.editorSettings.fontSize = e.target.value; + window.App.editorSettings.fontSize = parseInt((e.target as any).value); that.ic10editor.saveEditorSettings(); that.updateEditorSettings(); }); document.getElementById("editorSettingsRelativeLineNumbers").addEventListener('change', (e) => { - window.App.editorSettings.relativeLineNumbers = e.target.checked; + window.App.editorSettings.relativeLineNumbers = (e.target as any).checked; that.ic10editor.saveEditorSettings(); that.updateEditorSettings(); }); @@ -76,21 +78,21 @@ class IC10EditorUI { } else { editor.setOption('keyboardHandler', `ace/keyboard/${settings.keyboard}`); } - editor.setOption('cursorStyle', settings.cursor); - editor.setOption('fontSize', `${settings.fontSize}px`); + editor.setOption('cursorStyle', settings.cursor as any); + editor.setOption('fontSize', settings.fontSize); editor.setOption('relativeLineNumbers', settings.relativeLineNumbers); } displayEditorSettings() { const settings = this.ic10editor.settings; - document.getElementsByName("editorKeybindRadio").forEach((el) => { + document.getElementsByName("editorKeybindRadio").forEach((el: any) => { el.checked = el.value === settings.keyboard; }); - document.getElementsByName("editorCursorRadio").forEach((el) => { + document.getElementsByName("editorCursorRadio").forEach((el: any) => { el.checked = el.value === settings.cursor; }); - document.getElementById("editorSettingsFontSize").value = settings.fontSize; - document.getElementById("editorSettingsRelativeLineNumbers").checked = settings.relativeLineNumbers; + (document.getElementById("editorSettingsFontSize") as any).value = settings.fontSize; + (document.getElementById("editorSettingsRelativeLineNumbers") as any).checked = settings.relativeLineNumbers; } reCalcEditorSize() { diff --git a/www/src/js/index.ts b/www/src/js/index.ts index 7790f64..7fcea87 100644 --- a/www/src/js/index.ts +++ b/www/src/js/index.ts @@ -3,25 +3,35 @@ import { Session } from './session'; import { VirtualMachine } from "./virtual_machine"; import { docReady, openFile, saveFile } from "./utils"; // import { makeRequest } from "./utils"; +declare global { + interface Window { App: App } +} -const App = { +type App = { + editorSettings: { fontSize: number, relativeLineNumbers: boolean }; editor: IC10Editor, vm: VirtualMachine, session: Session +} + + +export const App: App = { editor: null, vm: null, - session: new Session() + session: new Session(), + editorSettings: { fontSize: 16, relativeLineNumbers: false } }; window.App = App; // const dbPromise = makeRequest({ method: "GET", url: "/data/database.json"}); -const dbPromise = fetch("/data/database.json").then(resp => resp.json()); +// const dbPromise = fetch("/data/database.json").then(resp => resp.json()); +const dbPromise = import("../../data/database.json") -docReady(() => { +docReady(() => { App.vm = new VirtualMachine(); dbPromise.then(db => App.vm.setupDeviceDatabase(db)) - const init_session_id = App.vm.devices[0]; + const init_session_id = App.vm.devices.get(0).id; App.editor = new IC10Editor(init_session_id); @@ -32,26 +42,26 @@ docReady(() => { // Menu document.getElementById("mainMenuShare").addEventListener('click', (_event) => { - const link = document.getElementById("shareLinkText"); - link.setAttribute('value', window.location); + const link = document.getElementById("shareLinkText") as HTMLInputElement; + link.setAttribute('value', window.location.href); link.setSelectionRange(0, 0); }, { capture: true }); document.getElementById("shareLinkCopyButton").addEventListener('click', (event) => { event.preventDefault(); - const link = document.getElementById("shareLinkText"); + const link = document.getElementById("shareLinkText") as HTMLInputElement; link.select(); link.setSelectionRange(0, 99999); navigator.clipboard.writeText(link.value); }, { capture: true }); document.getElementById("mainMenuOpenFile").addEventListener('click', (_event) => { - openFile(editor); + openFile(App.editor.aceEditor); }, { capture: true }); document.getElementById("mainMenuSaveAs").addEventListener('click', (_event) => { - saveFile(editor.getSession().getValue()) + saveFile(App.editor.aceEditor.getSession().getValue()) }, { capture: true }); document.getElementById("mainMenuKeyboardShortcuts").addEventListener('click', (_event) => { - App.editor.editor.execCommand("showKeyboardShortcuts"); + App.editor.aceEditor.execCommand("showKeyboardShortcuts"); }, { capture: true }); }); diff --git a/www/src/js/main.ts b/www/src/js/main.ts index a340001..84b6acc 100644 --- a/www/src/js/main.ts +++ b/www/src/js/main.ts @@ -1,10 +1,10 @@ import '@popperjs/core'; import '../scss/styles.scss'; -import { Dropdown, Model, ButtonGroup } from 'bootstrap'; +import { Dropdown, Modal } from 'bootstrap'; // A dependency graph that contains any wasm must all be imported -// asynchronously. This `bootstrap.js` file does the single async import, so +// asynchronously. This `main.js` file does the single async import, so // that no one else needs to worry about it again. -import("./index.js") - .catch(e => console.error("Error importing `index.js`:", e)); +import("./index") + .catch(e => console.error("Error importing `index.ts`:", e)); diff --git a/www/src/js/session.ts b/www/src/js/session.ts index 54bd962..652ad5b 100644 --- a/www/src/js/session.ts +++ b/www/src/js/session.ts @@ -61,10 +61,21 @@ j ra ` +interface SessionCbFn { + (param: Session): void; +} + class Session { + _programs: Map; + _onLoadCallbacks: SessionCbFn[]; + _activeSession: number; + _activeLines: Map; + _onActiveLineCallbacks: SessionCbFn[]; + _activeLine: number; + private _save_timeout: ReturnType; constructor() { this._programs = new Map(); - this._save_timeout = 0; + this._save_timeout = null; this._onLoadCallbacks = []; this._activeSession = 0; this._activeLines = new Map(); @@ -89,25 +100,25 @@ class Session { return this._activeSession; } - getActiveLine(id) { + getActiveLine(id: number) { return this._activeLines.get(id); } - setActiveLine(id, line) { + setActiveLine(id: number, line: number) { this._activeLines.set(id, line); this._fireOnActiveLine(); } - set activeLine(line) { + set activeLine(line: number) { this._activeLine = line; } - setProgramCode(id, code) { + setProgramCode(id: number, code: string) { this._programs.set(id, code); this.save(); } - onLoad(callback) { + onLoad(callback: SessionCbFn) { this._onLoadCallbacks.push(callback); } @@ -117,7 +128,7 @@ class Session { } } - onActiveLine(callback) { + onActiveLine(callback: SessionCbFn) { this._onActiveLineCallbacks.push(callback); } @@ -134,7 +145,7 @@ class Session { if (window.App.vm) { window.App.vm.updateCode(); } - + this._save_timeout = null; }, 1000); } @@ -182,7 +193,7 @@ class Session { } } -async function decompressFragment(c_bytes) { +async function decompressFragment(c_bytes: ArrayBuffer) { try { const bytes = await decompress(c_bytes); return bytes; @@ -192,7 +203,7 @@ async function decompressFragment(c_bytes) { } } -function getJson(value) { +function getJson(value: any) { try { return JSON.parse(value); } catch (_) { @@ -200,7 +211,7 @@ function getJson(value) { } } -async function* streamAsyncIterator(stream) { +async function* streamAsyncIterator(stream: ReadableStream) { // Get a lock on the stream const reader = stream.getReader(); @@ -217,14 +228,14 @@ async function* streamAsyncIterator(stream) { } } -function base64url_encode(buffer) { +function base64url_encode(buffer: ArrayBuffer) { return btoa(Array.from(new Uint8Array(buffer), b => String.fromCharCode(b)).join('')) .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/, ''); } -function base64url_decode(value) { +function base64url_decode(value: string): ArrayBuffer { const m = value.length % 4; return Uint8Array.from(atob( value.replace(/-/g, '+') @@ -233,13 +244,13 @@ function base64url_decode(value) { ), c => c.charCodeAt(0)).buffer } -async function concatUintArrays(arrays) { +async function concatUintArrays(arrays: Uint8Array[]) { const blob = new Blob(arrays); const buffer = await blob.arrayBuffer(); return new Uint8Array(buffer); } -async function compress(bytes) { +async function compress(bytes: ArrayBuffer) { const s = new Blob([bytes]).stream(); const cs = s.pipeThrough( new CompressionStream('deflate-raw') @@ -251,7 +262,7 @@ async function compress(bytes) { return await concatUintArrays(chunks); } -async function decompress(bytes) { +async function decompress(bytes: ArrayBuffer) { const s = new Blob([bytes]).stream(); const ds = s.pipeThrough( new DecompressionStream('deflate-raw') @@ -263,4 +274,4 @@ async function decompress(bytes) { return await concatUintArrays(chunks); } -export { Session }; +export { Session, SessionCbFn }; diff --git a/www/src/js/utils.ts b/www/src/js/utils.ts index bd5e680..3e864a6 100644 --- a/www/src/js/utils.ts +++ b/www/src/js/utils.ts @@ -1,6 +1,7 @@ +import { Ace } from "ace-builds"; -function docReady(fn) { +function docReady(fn: ()=> void) { // see if DOM is already available if (document.readyState === "complete" || document.readyState === "interactive") { setTimeout(fn, 1); @@ -10,8 +11,7 @@ function docReady(fn) { } // probably not needed, fetch() exists now -function makeRequest (opts) { - const req = new Request() +function makeRequest(opts: { method: string, url: string, headers: { [key: string]: string }, params: any }) { return new Promise(function (resolve, reject) { var xhr = new XMLHttpRequest(); xhr.open(opts.method, opts.url); @@ -46,22 +46,21 @@ function makeRequest (opts) { }); } -async function saveFile(content) { +async function saveFile(content: BlobPart) { const blob = new Blob([content], { type: "text/plain" }); if (typeof window.showSaveFilePicker !== "undefined") { console.log("Saving via FileSystem API") - const options = { + const saveHandle = await window.showSaveFilePicker({ types: [ { - suggestedName: "code.ic10", + // suggestedName: "code.ic10", description: 'Text Files', accept: { 'text/plain': ['.txt', '.ic10'], }, }, ], - }; - const saveHandle = await window.showSaveFilePicker(options); + }); const ws = await saveHandle.createWritable(); await ws.write(blob); await ws.close(); @@ -74,7 +73,7 @@ async function saveFile(content) { } } -async function openFile(editor) { +async function openFile(editor: Ace.Editor) { if (typeof window.showOpenFilePicker !== "undefined") { console.log("opening file via FileSystem Api"); const [fileHandle] = await window.showOpenFilePicker(); @@ -93,7 +92,7 @@ async function openFile(editor) { const file = files[0]; var reader = new FileReader(); reader.onload = (e) => { - const contents = e.target.result; + const contents = e.target.result as string; const session = editor.getSession(); // session.id = file.name; session.setValue(contents); diff --git a/www/src/js/virtual_machine/device.ts b/www/src/js/virtual_machine/device.ts index 1ba9398..b80d743 100644 --- a/www/src/js/virtual_machine/device.ts +++ b/www/src/js/virtual_machine/device.ts @@ -1,9 +1,16 @@ import { Offcanvas } from 'bootstrap'; +import { VirtualMachine, VirtualMachineUI } from '.'; +import { DeviceRef } from 'ic10emu_wasm'; class VMDeviceUI { + ui: VirtualMachineUI; + root: HTMLDivElement; + canvasEl: HTMLElement; + deviceCountEl: HTMLElement; + canvas: Offcanvas; - constructor(ui) { + constructor(ui: VirtualMachineUI) { const that = this; that.ui = ui; this.root = document.createElement('div'); @@ -13,7 +20,7 @@ class VMDeviceUI { } - update(active_ic) { + update(active_ic: DeviceRef) { const devices = window.VM.devices; @@ -22,7 +29,11 @@ class VMDeviceUI { } class VMDeviceCard { - constructor(deviceUI, device) { + root: HTMLDivElement; + viewBtn: HTMLButtonElement; + deviceUI: VMDeviceUI; + device: DeviceRef; + constructor(deviceUI: VMDeviceUI, device: DeviceRef) { const that = this; this.deviceUI = deviceUI; this.device = device; diff --git a/www/src/js/virtual_machine/index.ts b/www/src/js/virtual_machine/index.ts index 39a1c3a..2a4f845 100644 --- a/www/src/js/virtual_machine/index.ts +++ b/www/src/js/virtual_machine/index.ts @@ -1,8 +1,34 @@ -import { init } from "ic10emu_wasm"; +import { DeviceRef, VM, init } from "ic10emu_wasm"; import { VMDeviceUI } from "./device"; // import { Card } from 'bootstrap'; +declare global { + interface Window { VM: VirtualMachine } +} + +type DeviceDB = { + logic_enabled: string[]; + slot_logic_enabled: string[]; + devices: string[]; + items: { + [key: string]: { + name: string, + hash: number, + desc: string, + logic?: { [key: string]: string }, + slots?: { name: string, type: string }[], + modes?: { [key: string]: string }, + conn?: { [key: string]: string[] }, + } + } +} + class VirtualMachine { + ic10vm: VM; + ui: VirtualMachineUI; + _devices: Map; + _ics: Map; + db: any; constructor() { const vm = init(); @@ -21,27 +47,27 @@ class VirtualMachine { } - get devices () { + get devices() { return this._devices; } - get ics () { + get ics() { return this._ics; } - get activeIC () { + get activeIC() { return this._ics.get(window.App.session.activeSession); } updateDevices() { - + const device_ids = this.ic10vm.devices; for (const id of device_ids) { - if (!this._devices.has(id)){ + if (!this._devices.has(id)) { this._devices.set(id, this.ic10vm.getDevice(id)); } } - for(const id of this._devices) { + for (const id of this._devices.keys()) { if (!device_ids.includes(id)) { this._devices.delete(id); } @@ -49,11 +75,11 @@ class VirtualMachine { const ics = this.ic10vm.ics; for (const id of ics) { - if (!this._ics.has(id)){ + if (!this._ics.has(id)) { this._ics.set(id, this._devices.get(id)); } } - for(const id of this._ics) { + for (const id of this._ics.keys()) { if (!ics.includes(id)) { this._ics.delete(id); } @@ -63,17 +89,17 @@ class VirtualMachine { updateCode() { const progs = window.App.session.programs; - for (const id of Object.keys(progs)) { + for (const id of progs.keys()) { const attempt = Date.now().toString(16) const ic = this._ics.get(id); - const prog = progs[id]; + const prog = progs.get(id); if (ic && prog) { console.time(`CompileProgram_${id}_${attempt}`); try { - this.ics[id].setCode(progs[id]); + this.ics.get(id).setCode(progs.get(id)); } catch (e) { console.log(e); - } + } console.timeEnd(`CompileProgram_${id}_${attempt}`); } } @@ -119,7 +145,7 @@ class VirtualMachine { this.ui.update(ic); } - setRegister(index, val) { + setRegister(index: number, val: number) { const ic = this.activeIC; try { ic.setRegister(index, val); @@ -128,7 +154,7 @@ class VirtualMachine { } } - setStack(addr, val) { + setStack(addr: number, val: number) { const ic = this.activeIC; try { ic.setStack(addr, val); @@ -137,7 +163,7 @@ class VirtualMachine { } } - setupDeviceDatabase(db) { + setupDeviceDatabase(db: DeviceDB) { this.db = db; console.log("Loaded Device Database", this.db); } @@ -145,7 +171,13 @@ class VirtualMachine { class VirtualMachineUI { - constructor(vm) { + vm: VirtualMachine; + state: VMStateUI; + registers: VMRegistersUI; + stack: VMStackUI; + devices: VMDeviceUI; + + constructor(vm: VirtualMachine) { this.vm = vm this.state = new VMStateUI(this); this.registers = new VMRegistersUI(this); @@ -166,7 +198,7 @@ class VirtualMachineUI { } - update(ic) { + update(ic: DeviceRef) { this.state.update(ic); this.registers.update(ic); this.stack.update(ic); @@ -176,7 +208,11 @@ class VirtualMachineUI { } class VMStateUI { - constructor(ui) { + ui: VirtualMachineUI; + instructionPointer: HTMLElement; + instructionCounter: HTMLElement; + lastState: HTMLElement; + constructor(ui: VirtualMachineUI) { this.ui = ui; this.instructionPointer = document.getElementById("vmActiveICStateIP"); @@ -184,7 +220,7 @@ class VMStateUI { this.lastState = document.getElementById("vmActiveICStateLastRun"); } - update(ic) { + update(ic: { ip: { toString: () => string; }; instructionCount: { toString: () => string; }; state: { toString: () => string; }; }) { if (ic) { this.instructionPointer.innerText = ic.ip.toString(); this.instructionCounter.innerText = ic.instructionCount.toString(); @@ -194,7 +230,18 @@ class VMStateUI { } class VMRegistersUI { - constructor(ui) { + ui: VirtualMachineUI; + tbl: HTMLDivElement; + regCells: { + cell: HTMLDivElement, + nameLabel: HTMLSpanElement, + aliasesLabel: HTMLSpanElement, + input: HTMLInputElement + }[]; + default_aliases: Map; + ic_aliases: Map; + constructor(ui: VirtualMachineUI) { + const that = this; this.ui = ui; const regDom = document.getElementById("vmActiveRegisters"); this.tbl = document.createElement("div"); @@ -212,8 +259,8 @@ class VMRegistersUI { cell.appendChild(nameLabel); const input = document.createElement("input"); input.type = "text" - input.value = 0; - input.dataset.index = i; + input.value = (0).toString(); + input.dataset.index = i.toString(); cell.appendChild(input); const aliasesLabel = document.createElement("span"); aliasesLabel.classList.add("input-group-text", "reg_label") @@ -228,72 +275,74 @@ class VMRegistersUI { this.tbl.appendChild(container); } this.regCells.forEach(cell => { - cell.input.addEventListener('change', this.onCellUpdate); + cell.input.addEventListener('change', that.onCellUpdate); }); - this.default_aliases = { "sp": 16, "ra": 17 } - this.ic_aliases = {} + this.default_aliases = new Map([["sp", 16], ["ra", 17]]); + this.ic_aliases = new Map(); regDom.appendChild(this.tbl); } - onCellUpdate(e) { + onCellUpdate(e: Event) { let index; let val; + let target = (e.target as HTMLInputElement); try { - index = parseInt(e.target.dataset.index); - val = parseFloat(e.target.value); + index = parseInt(target.dataset.index); + val = parseFloat(target.value); } catch (e) { // reset the edit console.log(e); - VM.update(); + window.VM.update(); return; } - VM.setRegister(index, val); + window.VM.setRegister(index, val); } - update(ic) { + update(ic: DeviceRef) { const that = this; if (ic) { const registers = ic.registers; if (registers) { for (var i = 0; i < registers.length; i++) { - this.regCells[i].input.value = registers[i]; + this.regCells[i].input.value = registers[i].toString(); } } const aliases = ic.aliases; if (aliases) { - this.ic_aliases = {}; - aliases.forEach( (target, alias, _map) => { - // const target = aliases.get(alias); - if (target.RegisterSpec && target.RegisterSpec.indirection == 0) { + this.ic_aliases = new Map(); + aliases.forEach((target, alias, _map) => { + if (("RegisterSpec" in target) && target.RegisterSpec.indirection == 0) { const index = target.RegisterSpec.target; - this.ic_aliases[alias] = index; + this.ic_aliases.set(alias, index); } }) } - console.log(aliases); } this.updateAliases(); } - updateAliases () { - const aliases = Object.assign({}, this.default_aliases, this.ic_aliases); - const labels = {} - for (const [alias, target] of Object.entries(aliases)) { + updateAliases() { + const aliases = new Map([...Array.from(this.default_aliases), ...Array.from(this.ic_aliases)]); + const labels = new Map(); + for (const [alias, target] of aliases) { if (labels.hasOwnProperty(target)) { - labels[target].push(alias) + labels.get(target).push(alias) } else { - labels[target] = [alias] + labels.set(target, [alias]); } } - for(const [index, label] of Object.entries(labels)) { - this.regCells[index].aliasesLabel.innerText = label.join(", ") + for (const [index, label_list] of labels) { + this.regCells[index].aliasesLabel.innerText = label_list.join(", ") } } } class VMStackUI { - constructor(ui) { + ui: VirtualMachineUI; + tbl: HTMLDivElement; + stackCells: { cell: HTMLDivElement, nameLabel: HTMLSpanElement, input: HTMLInputElement }[]; + constructor(ui: VirtualMachineUI) { this.ui = ui; const stackDom = document.getElementById("vmActiveStack"); this.tbl = document.createElement("div"); @@ -310,10 +359,10 @@ class VMStackUI { cell.appendChild(nameLabel); const input = document.createElement("input"); input.type = "text" - input.value = 0; - input.dataset.index = i; + input.value = (0).toString(); + input.dataset.index = i.toString(); cell.appendChild(input); - + this.stackCells.push({ cell, nameLabel, @@ -328,22 +377,22 @@ class VMStackUI { stackDom.appendChild(this.tbl); } - onCellUpdate(e) { + onCellUpdate(e: Event) { let index; let val; + let target = e.target as HTMLInputElement; try { - index = parseInt(e.target.dataset.index); - val = parseFloat(e.target.value); + index = parseInt(target.dataset.index); + val = parseFloat(target.value); } catch (e) { // reset the edit - console.log(e); - VM.update(); + window.VM.update(); return; } - VM.setStack(index, val); + window.VM.setStack(index, val); } - update(ic) { + update(ic: { stack: any; registers: any[]; }) { const that = this; if (ic) { const stack = ic.stack; @@ -363,4 +412,4 @@ class VMStackUI { } -export { VirtualMachine } \ No newline at end of file +export { VirtualMachine, VirtualMachineUI , DeviceDB }; \ No newline at end of file diff --git a/www/tsconfig.json b/www/tsconfig.json index 4cda1c5..e91f392 100644 --- a/www/tsconfig.json +++ b/www/tsconfig.json @@ -3,10 +3,11 @@ "outDir": "./dist/", "sourceMap": true, "noImplicitAny": true, - "module": "es6", - "target": "es6", - "jsx": "react", + "module": "es2022", + "target": "es2020", "allowJs": true, - "moduleResolution": "node" + "moduleResolution": "bundler", + "resolveJsonModule": true, + "types": ["@types/wicg-file-system-access", "@types/ace"] } } diff --git a/www/webpack.config.js b/www/webpack.config.js index 1dbacb0..016dbf7 100644 --- a/www/webpack.config.js +++ b/www/webpack.config.js @@ -6,10 +6,11 @@ const miniCssExtractPlugin = require('mini-css-extract-plugin'); const path = require('path'); module.exports = { - entry: "./src/js/main.js", + entry: "./src/js/main.ts", output: { path: path.resolve(__dirname, "dist"), filename: "main.js", + clean: true, }, devServer: { static: path.resolve(__dirname, 'dist'), @@ -79,9 +80,4 @@ module.exports = { asyncWebAssembly: true, syncWebAssembly: true, }, - output: { - path: path.resolve(__dirname, 'dist'), - - clean: true, - }, }; diff --git a/www/webpack.config.prod.js b/www/webpack.config.prod.js index 8a76c1c..47f55a0 100644 --- a/www/webpack.config.prod.js +++ b/www/webpack.config.prod.js @@ -6,10 +6,11 @@ const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin"); const path = require('path'); module.exports = { - entry: "./src/js/main.js", + entry: "./src/js/main.ts", output: { path: path.resolve(__dirname, "dist"), filename: "main.js", + clean: true }, devServer: { static: path.resolve(__dirname, 'dist'), @@ -120,9 +121,4 @@ module.exports = { }) ] }, - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, 'dist'), - clean: true - }, };