Vm working. simple interface built
- still need stack view - still ned to work with devices
This commit is contained in:
104
ic10emu/Cargo.lock
generated
104
ic10emu/Cargo.lock
generated
@@ -38,6 +38,16 @@ dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.10.0"
|
||||
@@ -75,10 +85,11 @@ dependencies = [
|
||||
"phf_codegen",
|
||||
"rand",
|
||||
"regex",
|
||||
"serde",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"thiserror",
|
||||
"web-time",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -90,6 +101,12 @@ dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.69"
|
||||
@@ -117,6 +134,21 @@ version = "2.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
@@ -205,6 +237,12 @@ dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
@@ -300,6 +338,26 @@ version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.11"
|
||||
@@ -371,6 +429,40 @@ dependencies = [
|
||||
"syn 2.0.53",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"num-conv",
|
||||
"num_threads",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
@@ -442,13 +534,3 @@ name = "wasm-bindgen-shared"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||
|
||||
[[package]]
|
||||
name = "web-time"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
@@ -9,21 +9,30 @@ edition = "2021"
|
||||
crate-type = ["lib"]
|
||||
|
||||
|
||||
|
||||
|
||||
[dependencies]
|
||||
const-crc32 = "1.3.0"
|
||||
itertools = "0.12.1"
|
||||
phf = "0.11.2"
|
||||
rand = "0.8.5"
|
||||
regex = "1.10.3"
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
strum = { version = "0.26.2", features = ["derive", "phf", "strum_macros"] }
|
||||
strum_macros = "0.26.2"
|
||||
thiserror = "1.0.58"
|
||||
time = { version = "0.3.34", features = [
|
||||
"formatting",
|
||||
"serde",
|
||||
"local-offset",
|
||||
] }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
web-time = "1.1.0"
|
||||
getrandom = { version = "0.2", features = ["js"] }
|
||||
time = { version = "0.3.34", features = [
|
||||
"formatting",
|
||||
"serde",
|
||||
"local-offset",
|
||||
"wasm-bindgen",
|
||||
] }
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
|
||||
@@ -44,7 +44,7 @@ fn write_repr_enum<T: std::io::Write, I, P>(
|
||||
let additional_strum = if use_phf { "#[strum(use_phf)]\n" } else { "" };
|
||||
write!(
|
||||
writer,
|
||||
"#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash, EnumString, AsRefStr, EnumProperty, EnumIter)]\n\
|
||||
"#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash, EnumString, AsRefStr, EnumProperty, EnumIter, Serialize, Deserialize)]\n\
|
||||
{additional_strum}\
|
||||
pub enum {name} {{\n"
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::interpreter;
|
||||
use crate::tokens::SplitConsecutiveIndicesExt;
|
||||
use crate::tokens::{SplitConsecutiveIndicesExt, SplitConsecutiveWithIndices};
|
||||
use itertools::Itertools;
|
||||
use std::error::Error;
|
||||
use std::fmt::Display;
|
||||
@@ -16,6 +16,7 @@ pub mod generated {
|
||||
use strum::EnumProperty;
|
||||
use strum::EnumString;
|
||||
use strum::IntoEnumIterator;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/instructions.rs"));
|
||||
include!(concat!(env!("OUT_DIR"), "/logictypes.rs"));
|
||||
@@ -85,8 +86,9 @@ pub mod generated {
|
||||
}
|
||||
|
||||
pub use generated::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ParseError {
|
||||
pub line: usize,
|
||||
pub start: usize,
|
||||
@@ -233,29 +235,15 @@ impl FromStr for Instruction {
|
||||
})
|
||||
}
|
||||
}?;
|
||||
let mut operand_tokens = Vec::new();
|
||||
let mut string_start = None;
|
||||
for (index, token) in tokens_iter {
|
||||
if token.starts_with("HASH(\"") {
|
||||
string_start = Some(index);
|
||||
}
|
||||
if let Some(start) = string_start {
|
||||
if token.ends_with("\")") {
|
||||
operand_tokens.push((start, &s[start..(index + token.len())]));
|
||||
string_start = None;
|
||||
}
|
||||
} else {
|
||||
operand_tokens.push((index, token));
|
||||
}
|
||||
}
|
||||
let operands = operand_tokens
|
||||
.into_iter()
|
||||
|
||||
let operands = get_operand_tokens(s, tokens_iter)
|
||||
.iter()
|
||||
.map(|(index, token)| {
|
||||
token
|
||||
.parse::<Operand>()
|
||||
.map_err(|e| e.offset(index).span(token.len()))
|
||||
.map_err(|e| e.offset(*index).span(token.len()))
|
||||
})
|
||||
.collect::<Result<Vec<_>, ParseError>>()?;
|
||||
.try_collect()?;
|
||||
Ok(Instruction {
|
||||
instruction,
|
||||
operands,
|
||||
@@ -263,14 +251,33 @@ impl FromStr for Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
fn get_operand_tokens<'a>(s: &'a str, tokens_iter: SplitConsecutiveWithIndices<'a>) -> Vec<(usize, &'a str)> {
|
||||
let mut operand_tokens = Vec::with_capacity(8);
|
||||
let mut string_start = None;
|
||||
for (index, token) in tokens_iter {
|
||||
if token.starts_with("HASH(\"") {
|
||||
string_start = Some(index);
|
||||
}
|
||||
if let Some(start) = string_start {
|
||||
if token.ends_with("\")") {
|
||||
operand_tokens.push((start, &s[start..(index + token.len())]));
|
||||
string_start = None;
|
||||
}
|
||||
} else {
|
||||
operand_tokens.push((index, token));
|
||||
}
|
||||
}
|
||||
operand_tokens
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
pub enum Device {
|
||||
Db,
|
||||
Numbered(u32),
|
||||
Indirect { indirection: u32, target: u32 },
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum Operand {
|
||||
RegisterSpec {
|
||||
indirection: u32,
|
||||
@@ -349,7 +356,7 @@ impl Operand {
|
||||
) -> Result<(Option<u16>, Option<u32>), interpreter::ICError> {
|
||||
match &self {
|
||||
&Operand::DeviceSpec { device, connection } => match device {
|
||||
Device::Db => Ok((Some(ic.id), *connection)),
|
||||
Device::Db => Ok((Some(ic.device), *connection)),
|
||||
Device::Numbered(p) => {
|
||||
let dp = ic
|
||||
.pins
|
||||
@@ -598,6 +605,7 @@ impl FromStr for Operand {
|
||||
.collect::<String>();
|
||||
if !float_str.is_empty() {
|
||||
if rest_iter.peek() == Some(&&'.') {
|
||||
rest_iter.next();
|
||||
let decimal_str = rest_iter
|
||||
.take_while_ref(|c| c.is_digit(10))
|
||||
.collect::<String>();
|
||||
@@ -684,7 +692,7 @@ impl FromStr for Label {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Identifier {
|
||||
// #[rust_sitter::leaf(pattern = r"[a-zA-Z_.][\w\d.]*", transform = |id| id.to_string())]
|
||||
pub name: String,
|
||||
@@ -732,7 +740,7 @@ impl FromStr for Identifier {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum Number {
|
||||
Float(f64),
|
||||
Binary(f64),
|
||||
@@ -757,7 +765,6 @@ impl Number {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::generated::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,47 +1,56 @@
|
||||
use core::f64;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
collections::{HashMap, HashSet},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
mod grammar;
|
||||
mod interpreter;
|
||||
pub mod grammar;
|
||||
pub mod interpreter;
|
||||
mod rand_mscorlib;
|
||||
mod tokens;
|
||||
pub mod tokens;
|
||||
|
||||
use grammar::{BatchMode, LogicType, ReagentMode, SlotLogicType};
|
||||
use interpreter::ICError;
|
||||
use interpreter::{ICError, LineError};
|
||||
use itertools::Itertools;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[derive(Error, Debug, Serialize, Deserialize)]
|
||||
pub enum VMError {
|
||||
#[error("Device with id '{0}' does not exist")]
|
||||
UnknownId(u16),
|
||||
#[error("IC with id '{0}' does not exist")]
|
||||
UnknownIcId(u16),
|
||||
#[error("Device with id '{0}' does not have a IC Slot")]
|
||||
NoIC(u16),
|
||||
#[error("IC encoutered an error: {0}")]
|
||||
ICError(#[from] ICError),
|
||||
#[error("IC encoutered an error: {0}")]
|
||||
LineError(#[from] LineError),
|
||||
#[error("Invalid network ID {0}")]
|
||||
InvalidNetwork(u16),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum FieldType {
|
||||
Read,
|
||||
Write,
|
||||
ReadWrite,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct LogicField {
|
||||
pub field_type: FieldType,
|
||||
pub value: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
pub struct Slot {
|
||||
pub fields: HashMap<grammar::SlotLogicType, LogicField>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
|
||||
pub enum Connection {
|
||||
CableNetwork(Option<u16>),
|
||||
#[default]
|
||||
@@ -56,12 +65,12 @@ pub struct Device {
|
||||
pub fields: HashMap<grammar::LogicType, LogicField>,
|
||||
pub slots: Vec<Slot>,
|
||||
pub reagents: HashMap<ReagentMode, HashMap<i32, f64>>,
|
||||
pub ic: Option<interpreter::IC>,
|
||||
pub ic: Option<u16>,
|
||||
pub connections: [Connection; 8],
|
||||
pub prefab_hash: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Network {
|
||||
pub devices: HashSet<u16>,
|
||||
pub channels: [f64; 8],
|
||||
@@ -74,7 +83,7 @@ struct IdSequenceGenerator {
|
||||
|
||||
impl Default for IdSequenceGenerator {
|
||||
fn default() -> Self {
|
||||
IdSequenceGenerator { next: 1 }
|
||||
IdSequenceGenerator { next: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,13 +97,13 @@ impl IdSequenceGenerator {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VM {
|
||||
pub ics: HashSet<u16>,
|
||||
pub devices: HashMap<u16, Device>,
|
||||
pub networks: HashMap<u16, Network>,
|
||||
pub ics: HashMap<u16, Rc<RefCell<interpreter::IC>>>,
|
||||
pub devices: HashMap<u16, Rc<RefCell<Device>>>,
|
||||
pub networks: HashMap<u16, Rc<RefCell<Network>>>,
|
||||
pub default_network: u16,
|
||||
id_gen: IdSequenceGenerator,
|
||||
network_id_gen: IdSequenceGenerator,
|
||||
random: crate::rand_mscorlib::Random,
|
||||
random: Rc<RefCell<crate::rand_mscorlib::Random>>,
|
||||
}
|
||||
|
||||
impl Default for Network {
|
||||
@@ -146,7 +155,7 @@ impl Network {
|
||||
|
||||
impl Device {
|
||||
pub fn new(id: u16) -> Self {
|
||||
Device {
|
||||
let mut device = Device {
|
||||
id,
|
||||
name: None,
|
||||
name_hash: None,
|
||||
@@ -156,12 +165,36 @@ impl Device {
|
||||
ic: None,
|
||||
connections: [Connection::default(); 8],
|
||||
prefab_hash: None,
|
||||
}
|
||||
};
|
||||
device.connections[0] = Connection::CableNetwork(None);
|
||||
device
|
||||
}
|
||||
|
||||
pub fn with_ic(id: u16) -> Self {
|
||||
pub fn with_ic(id: u16, ic: u16) -> Self {
|
||||
let mut device = Device::new(id);
|
||||
device.ic = Some(interpreter::IC::new(id));
|
||||
device.ic = Some(ic);
|
||||
device.fields.insert(
|
||||
LogicType::Setting,
|
||||
LogicField {
|
||||
field_type: FieldType::ReadWrite,
|
||||
value: 0.0,
|
||||
},
|
||||
);
|
||||
device.fields.insert(
|
||||
LogicType::Error,
|
||||
LogicField {
|
||||
field_type: FieldType::ReadWrite,
|
||||
value: 0.0,
|
||||
},
|
||||
);
|
||||
device.fields.insert(
|
||||
LogicType::PrefabHash,
|
||||
LogicField {
|
||||
field_type: FieldType::Read,
|
||||
value: -128473777.0,
|
||||
},
|
||||
);
|
||||
device.prefab_hash = Some(-128473777);
|
||||
device
|
||||
}
|
||||
|
||||
@@ -262,19 +295,19 @@ impl VM {
|
||||
pub fn new() -> Self {
|
||||
let id_gen = IdSequenceGenerator::default();
|
||||
let mut network_id_gen = IdSequenceGenerator::default();
|
||||
let default_network = Network::default();
|
||||
let default_network = Rc::new(RefCell::new(Network::default()));
|
||||
let mut networks = HashMap::new();
|
||||
let default_network_key = network_id_gen.next();
|
||||
networks.insert(default_network_key, default_network);
|
||||
|
||||
let mut vm = VM {
|
||||
ics: HashSet::new(),
|
||||
ics: HashMap::new(),
|
||||
devices: HashMap::new(),
|
||||
networks,
|
||||
default_network: default_network_key,
|
||||
id_gen,
|
||||
network_id_gen,
|
||||
random: crate::rand_mscorlib::Random::new(),
|
||||
random: Rc::new(RefCell::new(crate::rand_mscorlib::Random::new())),
|
||||
};
|
||||
let _ = vm.add_ic(None);
|
||||
vm
|
||||
@@ -284,8 +317,11 @@ impl VM {
|
||||
Device::new(self.id_gen.next())
|
||||
}
|
||||
|
||||
fn new_ic(&mut self) -> Device {
|
||||
Device::with_ic(self.id_gen.next())
|
||||
fn new_ic(&mut self) -> (Device, interpreter::IC) {
|
||||
let id = self.id_gen.next();
|
||||
let ic = interpreter::IC::new(id, id);
|
||||
let device = Device::with_ic(id, id);
|
||||
(device, ic)
|
||||
}
|
||||
|
||||
pub fn add_device(&mut self, network: Option<u16>) -> Result<u16, VMError> {
|
||||
@@ -314,7 +350,15 @@ impl VM {
|
||||
});
|
||||
}
|
||||
let id = device.id;
|
||||
self.devices.insert(id, device);
|
||||
self.devices.insert(id, Rc::new(RefCell::new(device)));
|
||||
let _ = self.add_device_to_network(
|
||||
id,
|
||||
if let Some(network) = network {
|
||||
network
|
||||
} else {
|
||||
self.default_network
|
||||
},
|
||||
);
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
@@ -324,7 +368,7 @@ impl VM {
|
||||
return Err(VMError::InvalidNetwork(*n));
|
||||
}
|
||||
}
|
||||
let mut device = self.new_ic();
|
||||
let (mut device, ic) = self.new_ic();
|
||||
if let Some(first_network) = device
|
||||
.connections
|
||||
.iter_mut()
|
||||
@@ -344,45 +388,117 @@ impl VM {
|
||||
});
|
||||
}
|
||||
let id = device.id;
|
||||
self.devices.insert(id, device);
|
||||
self.ics.insert(id);
|
||||
let ic_id = ic.id;
|
||||
self.devices.insert(id, Rc::new(RefCell::new(device)));
|
||||
self.ics.insert(ic_id, Rc::new(RefCell::new(ic)));
|
||||
let _ = self.add_device_to_network(
|
||||
id,
|
||||
if let Some(network) = network {
|
||||
network
|
||||
} else {
|
||||
self.default_network
|
||||
},
|
||||
);
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
pub fn add_network(&mut self) -> u16 {
|
||||
let next_id = self.network_id_gen.next();
|
||||
self.networks.insert(next_id, Network::default());
|
||||
self.networks
|
||||
.insert(next_id, Rc::new(RefCell::new(Network::default())));
|
||||
next_id
|
||||
}
|
||||
|
||||
pub fn get_default_network(&mut self) -> &mut Network {
|
||||
self.networks.get_mut(&self.default_network).unwrap()
|
||||
pub fn get_default_network(&self) -> Rc<RefCell<Network>> {
|
||||
self.networks.get(&self.default_network).cloned().unwrap()
|
||||
}
|
||||
|
||||
pub fn get_network(&mut self, id: u16) -> Option<&mut Network> {
|
||||
self.networks.get_mut(&id)
|
||||
pub fn get_network(&self, id: u16) -> Option<Rc<RefCell<Network>>> {
|
||||
self.networks.get(&id).cloned()
|
||||
}
|
||||
|
||||
pub fn remove_ic(&mut self, id: u16) {
|
||||
if self.ics.remove(&id) {
|
||||
if self.ics.remove(&id).is_some() {
|
||||
self.devices.remove(&id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_code(&mut self, id: u16, code: &str) -> Result<bool, VMError> {
|
||||
let device = self.devices.get_mut(&id).ok_or(VMError::UnknownId(id))?;
|
||||
let ic = device.ic.as_mut().ok_or(VMError::NoIC(id))?;
|
||||
pub fn set_code(&self, id: u16, code: &str) -> Result<bool, VMError> {
|
||||
let device = self
|
||||
.devices
|
||||
.get(&id)
|
||||
.ok_or(VMError::UnknownId(id))?
|
||||
.borrow();
|
||||
let ic_id = *device.ic.as_ref().ok_or(VMError::NoIC(id))?;
|
||||
let mut ic = self
|
||||
.ics
|
||||
.get(&ic_id)
|
||||
.ok_or(VMError::UnknownIcId(ic_id))?
|
||||
.borrow_mut();
|
||||
let new_prog = interpreter::Program::try_from_code(code)?;
|
||||
ic.program = new_prog;
|
||||
ic.ip = 0;
|
||||
ic.code = code.to_string();
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub fn get_device(&mut self, id: u16) -> Option<&mut Device> {
|
||||
self.devices.get_mut(&id)
|
||||
pub fn step_ic(&self, id: u16) -> Result<bool, VMError> {
|
||||
let device = self.devices.get(&id).ok_or(VMError::UnknownId(id))?.clone();
|
||||
let ic_id = *device.borrow().ic.as_ref().ok_or(VMError::NoIC(id))?;
|
||||
let ic = self
|
||||
.ics
|
||||
.get(&ic_id)
|
||||
.ok_or(VMError::UnknownIcId(ic_id))?
|
||||
.clone();
|
||||
ic.borrow_mut().ic = 0;
|
||||
let result = ic.borrow_mut().step(self)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn get_device_same_network(&mut self, source: u16, other: u16) -> Option<&mut Device> {
|
||||
/// returns true if exacuted 128 lines, false if returned early.
|
||||
pub fn run_ic(&self, id: u16, ignore_errors: bool) -> Result<bool, VMError> {
|
||||
let device = self.devices.get(&id).ok_or(VMError::UnknownId(id))?.clone();
|
||||
let ic_id = *device.borrow().ic.as_ref().ok_or(VMError::NoIC(id))?;
|
||||
let ic = self
|
||||
.ics
|
||||
.get(&ic_id)
|
||||
.ok_or(VMError::UnknownIcId(ic_id))?
|
||||
.clone();
|
||||
ic.borrow_mut().ic = 0;
|
||||
for _i in 0..128 {
|
||||
if let Err(err) = ic.borrow_mut().step(self) {
|
||||
if !ignore_errors {
|
||||
return Err(err.into());
|
||||
}
|
||||
}
|
||||
if let interpreter::ICState::Yield = ic.borrow().state {
|
||||
return Ok(false);
|
||||
} else if let interpreter::ICState::Sleep(_then, _sleep_for) = ic.borrow().state {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
ic.borrow_mut().state = interpreter::ICState::Yield;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub fn reset_ic(&self, id: u16) -> Result<bool, VMError> {
|
||||
let device = self.devices.get(&id).ok_or(VMError::UnknownId(id))?.clone();
|
||||
let ic_id = *device.borrow().ic.as_ref().ok_or(VMError::NoIC(id))?;
|
||||
let ic = self
|
||||
.ics
|
||||
.get(&ic_id)
|
||||
.ok_or(VMError::UnknownIcId(ic_id))?
|
||||
.clone();
|
||||
ic.borrow_mut().ic = 0;
|
||||
ic.borrow_mut().reset();
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub fn get_device(&self, id: u16) -> Option<Rc<RefCell<Device>>> {
|
||||
self.devices.get(&id).cloned()
|
||||
}
|
||||
|
||||
pub fn get_device_same_network(&self, source: u16, other: u16) -> Option<Rc<RefCell<Device>>> {
|
||||
if self.devices_on_same_network(&[source, other]) {
|
||||
self.get_device(other)
|
||||
} else {
|
||||
@@ -395,29 +511,41 @@ impl VM {
|
||||
.networks
|
||||
.get(&(id as u16))
|
||||
.ok_or(ICError::BadNetworkId(id as u32))?;
|
||||
Ok(network.channels[channel])
|
||||
Ok(network.borrow().channels[channel])
|
||||
}
|
||||
|
||||
pub fn set_network_channel(&mut self, id: usize, channel: usize, val: f64) -> Result<(), ICError> {
|
||||
pub fn set_network_channel(&self, id: usize, channel: usize, val: f64) -> Result<(), ICError> {
|
||||
let network = self
|
||||
.networks
|
||||
.get_mut(&(id as u16))
|
||||
.get(&(id as u16))
|
||||
.ok_or(ICError::BadNetworkId(id as u32))?;
|
||||
network.channels[channel] = val;
|
||||
network.borrow_mut().channels[channel] = val;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn devices_on_same_network(&self, ids: &[u16]) -> bool {
|
||||
for (_id, net) in self.networks.iter() {
|
||||
if net.contains(ids) {
|
||||
if net.borrow().contains(ids) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn add_device_to_network(&self, id: u16, network_id: u16) -> Result<bool, VMError> {
|
||||
if !self.devices.contains_key(&id) {
|
||||
return Err(VMError::UnknownId(id));
|
||||
};
|
||||
if let Some(network) = self.networks.get(&network_id) {
|
||||
network.borrow_mut().add(id);
|
||||
Ok(true)
|
||||
} else {
|
||||
Err(VMError::InvalidNetwork(network_id))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_batch_device_field(
|
||||
&mut self,
|
||||
&self,
|
||||
source: u16,
|
||||
prefab: f64,
|
||||
typ: LogicType,
|
||||
@@ -425,14 +553,19 @@ impl VM {
|
||||
) -> Result<(), ICError> {
|
||||
let networks = &self.networks;
|
||||
self.devices
|
||||
.iter_mut()
|
||||
.iter()
|
||||
.map(|(id, device)| {
|
||||
if device.fields.get(&LogicType::PrefabHash).map(|f| f.value) == Some(prefab)
|
||||
if device
|
||||
.borrow()
|
||||
.fields
|
||||
.get(&LogicType::PrefabHash)
|
||||
.map(|f| f.value)
|
||||
== Some(prefab)
|
||||
&& networks
|
||||
.iter()
|
||||
.any(|(_net_id, net)| net.contains(&[source, *id]))
|
||||
.any(|(_net_id, net)| net.borrow().contains(&[source, *id]))
|
||||
{
|
||||
device.set_field(typ, val)
|
||||
device.clone().borrow_mut().set_field(typ, val)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@@ -441,7 +574,7 @@ impl VM {
|
||||
}
|
||||
|
||||
pub fn set_batch_device_slot_field(
|
||||
&mut self,
|
||||
&self,
|
||||
source: u16,
|
||||
prefab: f64,
|
||||
index: f64,
|
||||
@@ -450,14 +583,19 @@ impl VM {
|
||||
) -> Result<(), ICError> {
|
||||
let networks = &self.networks;
|
||||
self.devices
|
||||
.iter_mut()
|
||||
.iter()
|
||||
.map(|(id, device)| {
|
||||
if device.fields.get(&LogicType::PrefabHash).map(|f| f.value) == Some(prefab)
|
||||
if device
|
||||
.borrow()
|
||||
.fields
|
||||
.get(&LogicType::PrefabHash)
|
||||
.map(|f| f.value)
|
||||
== Some(prefab)
|
||||
&& networks
|
||||
.iter()
|
||||
.any(|(_net_id, net)| net.contains(&[source, *id]))
|
||||
.any(|(_net_id, net)| net.borrow().contains(&[source, *id]))
|
||||
{
|
||||
device.set_slot_field(index, typ, val)
|
||||
device.borrow_mut().set_slot_field(index, typ, val)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@@ -466,7 +604,7 @@ impl VM {
|
||||
}
|
||||
|
||||
pub fn set_batch_name_device_field(
|
||||
&mut self,
|
||||
&self,
|
||||
source: u16,
|
||||
prefab: f64,
|
||||
name: f64,
|
||||
@@ -475,15 +613,20 @@ impl VM {
|
||||
) -> Result<(), ICError> {
|
||||
let networks = &self.networks;
|
||||
self.devices
|
||||
.iter_mut()
|
||||
.iter()
|
||||
.map(|(id, device)| {
|
||||
if device.fields.get(&LogicType::PrefabHash).map(|f| f.value) == Some(prefab)
|
||||
&& Some(name) == device.name_hash
|
||||
if device
|
||||
.borrow()
|
||||
.fields
|
||||
.get(&LogicType::PrefabHash)
|
||||
.map(|f| f.value)
|
||||
== Some(prefab)
|
||||
&& Some(name) == device.borrow().name_hash
|
||||
&& networks
|
||||
.iter()
|
||||
.any(|(_net_id, net)| net.contains(&[source, *id]))
|
||||
.any(|(_net_id, net)| net.borrow().contains(&[source, *id]))
|
||||
{
|
||||
device.set_field(typ, val)
|
||||
device.borrow_mut().set_field(typ, val)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@@ -492,7 +635,7 @@ impl VM {
|
||||
}
|
||||
|
||||
pub fn get_batch_device_field(
|
||||
&mut self,
|
||||
&self,
|
||||
source: u16,
|
||||
prefab: f64,
|
||||
typ: LogicType,
|
||||
@@ -501,14 +644,19 @@ impl VM {
|
||||
let networks = &self.networks;
|
||||
let samples = self
|
||||
.devices
|
||||
.iter_mut()
|
||||
.iter()
|
||||
.map(|(id, device)| {
|
||||
if device.fields.get(&LogicType::PrefabHash).map(|f| f.value) == Some(prefab)
|
||||
if device
|
||||
.borrow()
|
||||
.fields
|
||||
.get(&LogicType::PrefabHash)
|
||||
.map(|f| f.value)
|
||||
== Some(prefab)
|
||||
&& networks
|
||||
.iter()
|
||||
.any(|(_net_id, net)| net.contains(&[source, *id]))
|
||||
.any(|(_net_id, net)| net.borrow().contains(&[source, *id]))
|
||||
{
|
||||
device.get_field(typ).map(|val| Some(val))
|
||||
device.borrow_mut().get_field(typ).map(|val| Some(val))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
@@ -535,7 +683,7 @@ impl VM {
|
||||
}
|
||||
|
||||
pub fn get_batch_name_device_field(
|
||||
&mut self,
|
||||
&self,
|
||||
source: u16,
|
||||
prefab: f64,
|
||||
name: f64,
|
||||
@@ -545,15 +693,20 @@ impl VM {
|
||||
let networks = &self.networks;
|
||||
let samples = self
|
||||
.devices
|
||||
.iter_mut()
|
||||
.iter()
|
||||
.map(|(id, device)| {
|
||||
if device.fields.get(&LogicType::PrefabHash).map(|f| f.value) == Some(prefab)
|
||||
&& Some(name) == device.name_hash
|
||||
if device
|
||||
.borrow()
|
||||
.fields
|
||||
.get(&LogicType::PrefabHash)
|
||||
.map(|f| f.value)
|
||||
== Some(prefab)
|
||||
&& Some(name) == device.borrow().name_hash
|
||||
&& networks
|
||||
.iter()
|
||||
.any(|(_net_id, net)| net.contains(&[source, *id]))
|
||||
.any(|(_net_id, net)| net.borrow().contains(&[source, *id]))
|
||||
{
|
||||
device.get_field(typ).map(|val| Some(val))
|
||||
device.borrow().get_field(typ).map(|val| Some(val))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
@@ -580,7 +733,7 @@ impl VM {
|
||||
}
|
||||
|
||||
pub fn get_batch_name_device_slot_field(
|
||||
&mut self,
|
||||
&self,
|
||||
source: u16,
|
||||
prefab: f64,
|
||||
name: f64,
|
||||
@@ -591,15 +744,23 @@ impl VM {
|
||||
let networks = &self.networks;
|
||||
let samples = self
|
||||
.devices
|
||||
.iter_mut()
|
||||
.iter()
|
||||
.map(|(id, device)| {
|
||||
if device.fields.get(&LogicType::PrefabHash).map(|f| f.value) == Some(prefab)
|
||||
&& Some(name) == device.name_hash
|
||||
if device
|
||||
.borrow()
|
||||
.fields
|
||||
.get(&LogicType::PrefabHash)
|
||||
.map(|f| f.value)
|
||||
== Some(prefab)
|
||||
&& Some(name) == device.borrow().name_hash
|
||||
&& networks
|
||||
.iter()
|
||||
.any(|(_net_id, net)| net.contains(&[source, *id]))
|
||||
.any(|(_net_id, net)| net.borrow().contains(&[source, *id]))
|
||||
{
|
||||
device.get_slot_field(index, typ).map(|val| Some(val))
|
||||
device
|
||||
.borrow()
|
||||
.get_slot_field(index, typ)
|
||||
.map(|val| Some(val))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
@@ -626,7 +787,7 @@ impl VM {
|
||||
}
|
||||
|
||||
pub fn get_batch_device_slot_field(
|
||||
&mut self,
|
||||
&self,
|
||||
source: u16,
|
||||
prefab: f64,
|
||||
index: f64,
|
||||
@@ -636,14 +797,22 @@ impl VM {
|
||||
let networks = &self.networks;
|
||||
let samples = self
|
||||
.devices
|
||||
.iter_mut()
|
||||
.iter()
|
||||
.map(|(id, device)| {
|
||||
if device.fields.get(&LogicType::PrefabHash).map(|f| f.value) == Some(prefab)
|
||||
if device
|
||||
.borrow()
|
||||
.fields
|
||||
.get(&LogicType::PrefabHash)
|
||||
.map(|f| f.value)
|
||||
== Some(prefab)
|
||||
&& networks
|
||||
.iter()
|
||||
.any(|(_net_id, net)| net.contains(&[source, *id]))
|
||||
.any(|(_net_id, net)| net.borrow().contains(&[source, *id]))
|
||||
{
|
||||
device.get_slot_field(index, typ).map(|val| Some(val))
|
||||
device
|
||||
.borrow()
|
||||
.get_slot_field(index, typ)
|
||||
.map(|val| Some(val))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
use std::usize;
|
||||
|
||||
const MSEED: i32 = 161803398;
|
||||
// const MZ: i32 = 0;
|
||||
// const MZ: i32 = 0;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Random {
|
||||
inext: i32,
|
||||
inextp: i32,
|
||||
inext: usize,
|
||||
inextp: usize,
|
||||
seed_array: [i32; 56],
|
||||
}
|
||||
|
||||
|
||||
/// Partial implementation of mscorlib System.Random
|
||||
/// https://github.com/microsoft/referencesource/blob/master/mscorlib/system/random.cs#L94
|
||||
impl Random {
|
||||
@@ -29,20 +28,20 @@ impl Random {
|
||||
seed_array[55] = mj;
|
||||
let mut mk: i32 = 1;
|
||||
|
||||
for i in 1_usize..55 {
|
||||
let ii = (21 * i) % 55;
|
||||
for i in 1..55 {
|
||||
let ii = 21 * i % 55;
|
||||
seed_array[ii] = mk;
|
||||
mk = mj - mk;
|
||||
mk = mj.wrapping_sub(mk);
|
||||
if mk < 0 {
|
||||
mk += i32::MAX;
|
||||
mk = mk.wrapping_add(i32::MAX);
|
||||
}
|
||||
mj = seed_array[ii];
|
||||
}
|
||||
for _k in 1_usize..5 {
|
||||
for i in 1_usize..56 {
|
||||
seed_array[i] -= seed_array[1 + (i + 30) % 55];
|
||||
seed_array[i] = seed_array[i].wrapping_sub(seed_array[1 + (i + 30) % 55]);
|
||||
if seed_array[i] < 0 {
|
||||
seed_array[i] += i32::MAX;
|
||||
seed_array[i] = seed_array[i].wrapping_add(i32::MAX);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,28 +63,24 @@ impl Random {
|
||||
let mut inext = self.inext;
|
||||
let mut inextp = self.inextp;
|
||||
|
||||
if {
|
||||
inext += 1;
|
||||
inext
|
||||
} >= 56
|
||||
{
|
||||
inext += 1;
|
||||
|
||||
if inext >= 56 {
|
||||
inext = 1;
|
||||
}
|
||||
if {
|
||||
inextp += 1;
|
||||
inextp
|
||||
} >= 56
|
||||
{
|
||||
inextp += 1;
|
||||
if inextp >= 56 {
|
||||
inextp = 1;
|
||||
}
|
||||
|
||||
let mut retval = self.seed_array[inext as usize] - self.seed_array[inextp as usize];
|
||||
let mut retval =
|
||||
self.seed_array[inext as usize].wrapping_sub(self.seed_array[inextp as usize]);
|
||||
|
||||
if retval == i32::MAX {
|
||||
retval -= 1;
|
||||
}
|
||||
if retval < 0 {
|
||||
retval += i32::MAX;
|
||||
retval = retval.wrapping_add(i32::MAX);
|
||||
}
|
||||
self.seed_array[inext as usize] = retval;
|
||||
|
||||
@@ -103,6 +98,26 @@ impl Random {
|
||||
pub fn next_f64(&mut self) -> f64 {
|
||||
self.sample()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn create() {
|
||||
let mut rand = Random::with_seed(0);
|
||||
assert_eq!(rand.next(), 1559595546);
|
||||
assert_eq!(rand.next(), 1755192844);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify() {
|
||||
let mut rand = Random::with_seed(1919810);
|
||||
assert_eq!(rand.next(), 147482110);
|
||||
assert_eq!(rand.next(), 1747108798);
|
||||
assert_eq!(rand.next(), 1937076328);
|
||||
assert_eq!(rand.next(), 924982271);
|
||||
assert_eq!(rand.next_f64(), 0.044092261252967765);
|
||||
assert_eq!(rand.next(), 659561101);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,14 +47,16 @@ impl<'a> Iterator for SplitConsecutiveWithIndices<'a> {
|
||||
}
|
||||
} else {
|
||||
let s = &self.haystack[self.start..start];
|
||||
let index = self.start;
|
||||
self.start = start;
|
||||
Some((self.start, s))
|
||||
Some((index, s))
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let s = &self.haystack[self.start..];
|
||||
let index = self.start;
|
||||
self.start = self.haystack.len();
|
||||
Some((self.start, s))
|
||||
Some((index, s))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
147
ic10emu/verify_mscorlib_rand.ipynb
Normal file
147
ic10emu/verify_mscorlib_rand.ipynb
Normal file
@@ -0,0 +1,147 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div class=\"dni-plaintext\"><pre>[ 1559595546, 1755192844 ]</pre></div><style>\r\n",
|
||||
".dni-code-hint {\r\n",
|
||||
" font-style: italic;\r\n",
|
||||
" overflow: hidden;\r\n",
|
||||
" white-space: nowrap;\r\n",
|
||||
"}\r\n",
|
||||
".dni-treeview {\r\n",
|
||||
" white-space: nowrap;\r\n",
|
||||
"}\r\n",
|
||||
".dni-treeview td {\r\n",
|
||||
" vertical-align: top;\r\n",
|
||||
" text-align: start;\r\n",
|
||||
"}\r\n",
|
||||
"details.dni-treeview {\r\n",
|
||||
" padding-left: 1em;\r\n",
|
||||
"}\r\n",
|
||||
"table td {\r\n",
|
||||
" text-align: start;\r\n",
|
||||
"}\r\n",
|
||||
"table tr { \r\n",
|
||||
" vertical-align: top; \r\n",
|
||||
" margin: 0em 0px;\r\n",
|
||||
"}\r\n",
|
||||
"table tr td pre \r\n",
|
||||
"{ \r\n",
|
||||
" vertical-align: top !important; \r\n",
|
||||
" margin: 0em 0px !important;\r\n",
|
||||
"} \r\n",
|
||||
"table th {\r\n",
|
||||
" text-align: start;\r\n",
|
||||
"}\r\n",
|
||||
"</style>"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"var rand = new System.Random(0);\n",
|
||||
"int[] two_rands = [rand.Next(), rand.Next()];\n",
|
||||
"\n",
|
||||
"two_rands"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"dotnet_interactive": {
|
||||
"language": "csharp"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelName": "csharp"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div class=\"dni-plaintext\"><pre>[ 147482110, 1747108798, 1937076328, 924982271, 0.044092261252967765, 659561101 ]</pre></div><style>\r\n",
|
||||
".dni-code-hint {\r\n",
|
||||
" font-style: italic;\r\n",
|
||||
" overflow: hidden;\r\n",
|
||||
" white-space: nowrap;\r\n",
|
||||
"}\r\n",
|
||||
".dni-treeview {\r\n",
|
||||
" white-space: nowrap;\r\n",
|
||||
"}\r\n",
|
||||
".dni-treeview td {\r\n",
|
||||
" vertical-align: top;\r\n",
|
||||
" text-align: start;\r\n",
|
||||
"}\r\n",
|
||||
"details.dni-treeview {\r\n",
|
||||
" padding-left: 1em;\r\n",
|
||||
"}\r\n",
|
||||
"table td {\r\n",
|
||||
" text-align: start;\r\n",
|
||||
"}\r\n",
|
||||
"table tr { \r\n",
|
||||
" vertical-align: top; \r\n",
|
||||
" margin: 0em 0px;\r\n",
|
||||
"}\r\n",
|
||||
"table tr td pre \r\n",
|
||||
"{ \r\n",
|
||||
" vertical-align: top !important; \r\n",
|
||||
" margin: 0em 0px !important;\r\n",
|
||||
"} \r\n",
|
||||
"table th {\r\n",
|
||||
" text-align: start;\r\n",
|
||||
"}\r\n",
|
||||
"</style>"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"var rand = new System.Random(1919810);\n",
|
||||
"double[] samples = [rand.Next(), rand.Next(), rand.Next(), rand.Next(), rand.NextDouble(), rand.Next()];\n",
|
||||
"\n",
|
||||
"samples"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".NET (C#)",
|
||||
"language": "C#",
|
||||
"name": ".net-csharp"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "polyglot-notebook"
|
||||
},
|
||||
"polyglot_notebook": {
|
||||
"kernelInfo": {
|
||||
"defaultKernelName": "csharp",
|
||||
"items": [
|
||||
{
|
||||
"aliases": [],
|
||||
"name": "csharp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
427
ic10emu_wasm/Cargo.lock
generated
427
ic10emu_wasm/Cargo.lock
generated
@@ -12,10 +12,31 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
@@ -23,12 +44,31 @@ version = "3.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.90"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console_error_panic_hook"
|
||||
version = "0.1.7"
|
||||
@@ -54,12 +94,75 @@ dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.55",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.30"
|
||||
@@ -80,7 +183,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.55",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -125,12 +228,53 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ic10emu"
|
||||
version = "0.1.0"
|
||||
@@ -143,10 +287,11 @@ dependencies = [
|
||||
"phf_codegen",
|
||||
"rand",
|
||||
"regex",
|
||||
"serde",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"thiserror",
|
||||
"web-time",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -155,13 +300,45 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"ic10emu",
|
||||
"itertools",
|
||||
"js-sys",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"serde_with",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-streams",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown 0.12.3",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.3",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.1"
|
||||
@@ -171,6 +348,12 @@ dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.69"
|
||||
@@ -198,6 +381,30 @@ version = "2.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
@@ -298,6 +505,12 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
@@ -383,9 +596,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.2"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
@@ -393,6 +606,84 @@ version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-wasm-bindgen"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.115"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"chrono",
|
||||
"hex",
|
||||
"indexmap 1.9.3",
|
||||
"indexmap 2.2.6",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"serde_with_macros",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "3.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.11"
|
||||
@@ -408,6 +699,12 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.26.2"
|
||||
@@ -428,7 +725,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.55",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -444,9 +741,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.53"
|
||||
version = "2.0.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
|
||||
checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -470,7 +767,41 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.55",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"num-conv",
|
||||
"num_threads",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -512,7 +843,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.55",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -547,7 +878,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.53",
|
||||
"syn 2.0.55",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@@ -560,9 +891,9 @@ checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-streams"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7"
|
||||
checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"js-sys",
|
||||
@@ -582,11 +913,67 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-time"
|
||||
version = "1.1.0"
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||
|
||||
@@ -6,17 +6,27 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
ic10emu = { path = "../ic10emu" }
|
||||
console_error_panic_hook = "0.1.7"
|
||||
console_error_panic_hook = {version = "0.1.7", optional = true}
|
||||
js-sys = "0.3.69"
|
||||
web-sys = { version = "0.3.69", features = ["WritableStream", "console"] }
|
||||
wasm-bindgen = "0.2.81"
|
||||
wasm-bindgen-futures = { version = "0.4.30", features = [
|
||||
"futures-core-03-stream",
|
||||
] }
|
||||
wasm-streams = "0.3"
|
||||
wasm-streams = "0.4"
|
||||
serde-wasm-bindgen = "0.6.5"
|
||||
itertools = "0.12.1"
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
serde_with = "3.7.0"
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
console_error_panic_hook = ["dep:console_error_panic_hook"]
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[profile.release]
|
||||
# Tell `rustc` to optimize for small code size.
|
||||
opt-level = "s"
|
||||
lto = true
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
|
||||
#[macro_use]
|
||||
mod utils;
|
||||
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use itertools::Itertools;
|
||||
// use itertools::Itertools;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use wasm_bindgen::prelude::*;
|
||||
use ic10emu::VM;
|
||||
|
||||
use serde_with::serde_as;
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Stack(#[serde_as(as = "[_; 512]")] [f64; 512]);
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
@@ -11,8 +20,302 @@ extern "C" {
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn init() {
|
||||
utils::set_panic_hook();
|
||||
let _vm = VM::new();
|
||||
log!("Hello from ic10emu!");
|
||||
pub struct DeviceRef {
|
||||
device: Rc<RefCell<ic10emu::Device>>,
|
||||
vm: Rc<RefCell<ic10emu::VM>>,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl DeviceRef {
|
||||
fn from_device(device: Rc<RefCell<ic10emu::Device>>, vm: Rc<RefCell<ic10emu::VM>>) -> Self {
|
||||
DeviceRef { device, vm }
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn id(&self) -> u16 {
|
||||
self.device.borrow().id
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn name(&self) -> Option<String> {
|
||||
self.device.borrow().name.clone()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "nameHash")]
|
||||
pub fn name_hash(&self) -> Option<f64> {
|
||||
self.device.borrow().name_hash
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn fields(&self) -> JsValue {
|
||||
serde_wasm_bindgen::to_value(&self.device.borrow().fields).unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn slots(&self) -> JsValue {
|
||||
serde_wasm_bindgen::to_value(&self.device.borrow().slots).unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn reagents(&self) -> JsValue {
|
||||
serde_wasm_bindgen::to_value(&self.device.borrow().reagents).unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn connections(&self) -> JsValue {
|
||||
serde_wasm_bindgen::to_value(&self.device.borrow().connections).unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "prefabHash")]
|
||||
pub fn prefab_hash(&self) -> Option<i32> {
|
||||
self.device.borrow().prefab_hash
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "ip")]
|
||||
pub fn ic_ip(&self) -> Option<u32> {
|
||||
self.device
|
||||
.borrow()
|
||||
.ic
|
||||
.as_ref()
|
||||
.map(|ic| {
|
||||
self.vm
|
||||
.borrow()
|
||||
.ics
|
||||
.get(ic)
|
||||
.map(|ic| ic.as_ref().borrow().ip)
|
||||
})
|
||||
.flatten()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "instructionCount")]
|
||||
pub fn ic_instruction_count(&self) -> Option<u16> {
|
||||
self.device
|
||||
.borrow()
|
||||
.ic
|
||||
.as_ref()
|
||||
.map(|ic| {
|
||||
self.vm
|
||||
.borrow()
|
||||
.ics
|
||||
.get(ic)
|
||||
.map(|ic| ic.as_ref().borrow().ic)
|
||||
})
|
||||
.flatten()
|
||||
}
|
||||
|
||||
#[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()
|
||||
}
|
||||
|
||||
#[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()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "aliases")]
|
||||
pub fn ic_aliases(&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().aliases.clone())
|
||||
})
|
||||
.flatten(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "defines")]
|
||||
pub fn ic_defines(&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().defines.clone())
|
||||
})
|
||||
.flatten(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "pins")]
|
||||
pub fn ic_pins(&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().pins)
|
||||
})
|
||||
.flatten(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "state")]
|
||||
pub fn ic_state(&self) -> Option<String> {
|
||||
self
|
||||
.device
|
||||
.borrow()
|
||||
.ic
|
||||
.as_ref()
|
||||
.map(|ic| {
|
||||
self.vm
|
||||
.borrow()
|
||||
.ics
|
||||
.get(ic)
|
||||
.map(|ic| ic.borrow().state.clone())
|
||||
})
|
||||
.flatten()
|
||||
.map(|state| state.to_string())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "step")]
|
||||
pub fn step_ic(&self) -> Result<bool, JsError> {
|
||||
let id = self.device.borrow().id;
|
||||
Ok(self.vm.borrow().step_ic(id)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "run")]
|
||||
pub fn run_ic(&self, ignore_errors: bool) -> Result<bool, JsError> {
|
||||
let id = self.device.borrow().id;
|
||||
Ok(self.vm.borrow().run_ic(id, ignore_errors)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "reset")]
|
||||
pub fn reset_ic(&self) -> Result<bool, JsError> {
|
||||
let id = self.device.borrow().id;
|
||||
Ok(self.vm.borrow().reset_ic(id)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "setCode")]
|
||||
pub fn set_code(&self, code: &str) -> Result<bool, JsError> {
|
||||
let id = self.device.borrow().id;
|
||||
Ok(self.vm.borrow().set_code(id, code)?)
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[derive(Debug)]
|
||||
pub struct VM {
|
||||
vm: Rc<RefCell<ic10emu::VM>>,
|
||||
}
|
||||
#[wasm_bindgen]
|
||||
impl VM {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new() -> Self {
|
||||
VM {
|
||||
vm: Rc::new(RefCell::new(ic10emu::VM::new())),
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "addDevice")]
|
||||
pub fn add_device(&self, network: Option<u16>) -> Result<u16, JsError> {
|
||||
Ok(self.vm.borrow_mut().add_device(network)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getDevice")]
|
||||
pub fn get_device(&self, id: u16) -> Option<DeviceRef> {
|
||||
let device = self.vm.borrow().get_device(id);
|
||||
device.map(|d| DeviceRef::from_device(d.clone(), self.vm.clone()))
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "setCode")]
|
||||
pub fn set_code(&self, id: u16, code: &str) -> Result<bool, JsError> {
|
||||
Ok(self.vm.borrow().set_code(id, code)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "stepIC")]
|
||||
pub fn step_ic(&self, id: u16) -> Result<bool, JsError> {
|
||||
Ok(self.vm.borrow().step_ic(id)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "runIC")]
|
||||
pub fn run_ic(&self, id: u16, ignore_errors: bool) -> Result<bool, JsError> {
|
||||
Ok(self.vm.borrow().run_ic(id, ignore_errors)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "resetIC")]
|
||||
pub fn reset_ic(&self, id: u16) -> Result<bool, JsError> {
|
||||
Ok(self.vm.borrow().reset_ic(id)?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter, js_name = "defaultNetwork")]
|
||||
pub fn defualt_network(&self) -> u16 {
|
||||
self.vm.borrow().default_network
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn devices(&self) -> Vec<u16> {
|
||||
self.vm.borrow().devices.keys().copied().collect_vec()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn networks(&self) -> Vec<u16> {
|
||||
self.vm.borrow().networks.keys().copied().collect_vec()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn ics(&self) -> Vec<u16> {
|
||||
self.vm.borrow().ics.keys().copied().collect_vec()
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn init() -> VM {
|
||||
utils::set_panic_hook();
|
||||
let vm = VM::new();
|
||||
log!("Hello from ic10emu!");
|
||||
vm
|
||||
}
|
||||
|
||||
@@ -6,7 +6,11 @@ pub fn set_panic_hook() {
|
||||
// For more details see
|
||||
// https://github.com/rustwasm/console_error_panic_hook#readme
|
||||
#[cfg(feature = "console_error_panic_hook")]
|
||||
console_error_panic_hook::set_once();
|
||||
{
|
||||
console_error_panic_hook::set_once();
|
||||
web_sys::console::log_1(&format!("Panic hook set...").into());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
4
ic10lsp_wasm/Cargo.lock
generated
4
ic10lsp_wasm/Cargo.lock
generated
@@ -1174,9 +1174,9 @@ checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-streams"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7"
|
||||
checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"js-sys",
|
||||
|
||||
@@ -19,11 +19,12 @@ tower-lsp = { version = "0.20.0", default-features = false, features = ["runtime
|
||||
# tree-sitter = { version = "0.9.0", package = "tree-sitter-facade" }
|
||||
wasm-bindgen = "0.2.81"
|
||||
wasm-bindgen-futures = { version = "0.4.30", features = ["futures-core-03-stream"] }
|
||||
wasm-streams = "0.3"
|
||||
wasm-streams = "0.4"
|
||||
# web-tree-sitter-sys = "1.3"
|
||||
ic10lsp = { git = "https://github.com/Ryex/ic10lsp.git", branch = "wasm" }
|
||||
|
||||
[profile.release]
|
||||
# Tell `rustc` to optimize for small code size.
|
||||
opt-level = "s"
|
||||
lto = true
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
<body class="">
|
||||
<noscript>This page contains webassembly and javascript content, please enable javascript in your browser.</noscript>
|
||||
<div class="App" >
|
||||
<div class="App">
|
||||
<div id="modelShareLink" class="modal fade" tabindex="-1" aria-hidden="true" data-bs-theme="dark">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
@@ -153,62 +153,78 @@
|
||||
<ul class="nav navbar-nav navbar-right flex-row d-sm-none d-none d-md-flex">
|
||||
<p class="navbar-text mt-auto mb-auto align-self-center" style="">Official Stationeers:</p>
|
||||
<li role="presentation" class="">
|
||||
<a href="https://store.steampowered.com/app/544550/Stationeers/"><svg aria-hidden="true" focusable="false"
|
||||
data-prefix="fab" data-icon="steam" class="svg-inline--fa fa-steam fa-w-16 " role="img"
|
||||
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512">
|
||||
<path fill="currentColor"
|
||||
d="M496 256c0 137-111.2 248-248.4 248-113.8 0-209.6-76.3-239-180.4l95.2 39.3c6.4 32.1 34.9 56.4 68.9 56.4 39.2 0 71.9-32.4 70.2-73.5l84.5-60.2c52.1 1.3 95.8-40.9 95.8-93.5 0-51.6-42-93.5-93.7-93.5s-93.7 42-93.7 93.5v1.2L176.6 279c-15.5-.9-30.7 3.4-43.5 12.1L0 236.1C10.2 108.4 117.1 8 247.6 8 384.8 8 496 119 496 256zM155.7 384.3l-30.5-12.6a52.79 52.79 0 0 0 27.2 25.8c26.9 11.2 57.8-1.6 69-28.4 5.4-13 5.5-27.3.1-40.3-5.4-13-15.5-23.2-28.5-28.6-12.9-5.4-26.7-5.2-38.9-.6l31.5 13c19.8 8.2 29.2 30.9 20.9 50.7-8.3 19.9-31 29.2-50.8 21zm173.8-129.9c-34.4 0-62.4-28-62.4-62.3s28-62.3 62.4-62.3 62.4 28 62.4 62.3-27.9 62.3-62.4 62.3zm.1-15.6c25.9 0 46.9-21 46.9-46.8 0-25.9-21-46.8-46.9-46.8s-46.9 21-46.9 46.8c.1 25.8 21.1 46.8 46.9 46.8z">
|
||||
</path>
|
||||
</svg>
|
||||
<a href="https://store.steampowered.com/app/544550/Stationeers/">
|
||||
<i class="fa-brands fa-steam fa-w-16"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation" class="">
|
||||
<a href="https://stationeers.com/">
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fa" data-icon="globe"
|
||||
class="svg-inline--fa fa-globe fa-w-16 " role="img" xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 496 512">
|
||||
<path fill="currentColor"
|
||||
d="M336.5 160C322 70.7 287.8 8 248 8s-74 62.7-88.5 152h177zM152 256c0 22.2 1.2 43.5 3.3 64h185.3c2.1-20.5 3.3-41.8 3.3-64s-1.2-43.5-3.3-64H155.3c-2.1 20.5-3.3 41.8-3.3 64zm324.7-96c-28.6-67.9-86.5-120.4-158-141.6 24.4 33.8 41.2 84.7 50 141.6h108zM177.2 18.4C105.8 39.6 47.8 92.1 19.3 160h108c8.7-56.9 25.5-107.8 49.9-141.6zM487.4 192H372.7c2.1 21 3.3 42.5 3.3 64s-1.2 43-3.3 64h114.6c5.5-20.5 8.6-41.8 8.6-64s-3.1-43.5-8.5-64zM120 256c0-21.5 1.2-43 3.3-64H8.6C3.2 212.5 0 233.8 0 256s3.2 43.5 8.6 64h114.6c-2-21-3.2-42.5-3.2-64zm39.5 96c14.5 89.3 48.7 152 88.5 152s74-62.7 88.5-152h-177zm159.3 141.6c71.4-21.2 129.4-73.7 158-141.6h-108c-8.8 56.9-25.6 107.8-50 141.6zM19.3 352c28.6 67.9 86.5 120.4 158 141.6-24.4-33.8-41.2-84.7-50-141.6h-108z">
|
||||
</path>
|
||||
</svg>
|
||||
<i class="fa-solid fa-globe fa-w-16"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation" class="">
|
||||
<a href="https://twitter.com/stationeers">
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="twitter"
|
||||
class="svg-inline--fa fa-twitter fa-w-16 " role="img" xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 512 512">
|
||||
<path fill="currentColor"
|
||||
d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z">
|
||||
</path>
|
||||
</svg>
|
||||
<i class="fa-brands fa-x-twitter"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation" class="">
|
||||
<a href="https://discordapp.com/invite/CxR3mRy">
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="discord"
|
||||
class="svg-inline--fa fa-discord fa-w-14 " role="img" xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 448 512">
|
||||
<path fill="currentColor"
|
||||
d="M297.216 243.2c0 15.616-11.52 28.416-26.112 28.416-14.336 0-26.112-12.8-26.112-28.416s11.52-28.416 26.112-28.416c14.592 0 26.112 12.8 26.112 28.416zm-119.552-28.416c-14.592 0-26.112 12.8-26.112 28.416s11.776 28.416 26.112 28.416c14.592 0 26.112-12.8 26.112-28.416.256-15.616-11.52-28.416-26.112-28.416zM448 52.736V512c-64.494-56.994-43.868-38.128-118.784-107.776l13.568 47.36H52.48C23.552 451.584 0 428.032 0 398.848V52.736C0 23.552 23.552 0 52.48 0h343.04C424.448 0 448 23.552 448 52.736zm-72.96 242.688c0-82.432-36.864-149.248-36.864-149.248-36.864-27.648-71.936-26.88-71.936-26.88l-3.584 4.096c43.52 13.312 63.744 32.512 63.744 32.512-60.811-33.329-132.244-33.335-191.232-7.424-9.472 4.352-15.104 7.424-15.104 7.424s21.248-20.224 67.328-33.536l-2.56-3.072s-35.072-.768-71.936 26.88c0 0-36.864 66.816-36.864 149.248 0 0 21.504 37.12 78.08 38.912 0 0 9.472-11.52 17.152-21.248-32.512-9.728-44.8-30.208-44.8-30.208 3.766 2.636 9.976 6.053 10.496 6.4 43.21 24.198 104.588 32.126 159.744 8.96 8.96-3.328 18.944-8.192 29.44-15.104 0 0-12.8 20.992-46.336 30.464 7.68 9.728 16.896 20.736 16.896 20.736 56.576-1.792 78.336-38.912 78.336-38.912z">
|
||||
</path>
|
||||
</svg>
|
||||
<i class="fa-brands fa-discord"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="d-flex flex-column">
|
||||
<div id="editorContainer" class="p-1 h-100">
|
||||
<div id="editor" class="w-100"></div>
|
||||
|
||||
<div class="d-flex flex-row">
|
||||
<div class="d-flex flex-column w-100">
|
||||
<div id="editorContainer" class="p-1 h-100">
|
||||
<div id="editor" class="w-100"></div>
|
||||
</div>
|
||||
<div id="statusBarContainer" class="p-1 mt-auto">
|
||||
<div id="statusBar" class="w-100 text-body">IC10 editor!</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="statusBarContainer" class="p-1 mt-auto">
|
||||
<div id="statusBar" class="w-100 text-body">IC10 editor!</div>
|
||||
<div class="d-flex flex-column flex-shrink-1">
|
||||
<div id="virtualMachine" >
|
||||
<div id="vmActiveIC">
|
||||
<div class="p-2 d-flex flex-row justify-content-center">
|
||||
<div class="d-flex flex-column">
|
||||
<div id="vmControls" class="btn-group-vertical btn-group-sm " role="group"
|
||||
aria-label="Virtual Machine Controls">
|
||||
<button id="vmControlRun" type="button" class="btn btn-primary">Run</button>
|
||||
<button id="vmControlStep" type="button" class="btn btn-secondary">Step</button>
|
||||
<button id="vmControlReset" type="button" class="btn btn-warning">Reset</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card ms-2">
|
||||
<div class="card-header">State</div>
|
||||
<div id="vmActiveICState" class="card-body">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-2 ms-2 d-flex flex-row">
|
||||
<div class="card ms-2">
|
||||
<div class="card-header">Registers</div>
|
||||
<div id="vmActiveRegisters" class="vm_reg">
|
||||
</div>
|
||||
</div>
|
||||
<div id="vmActiveStack">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.7/ace.js" type="text/javascript" charset="utf-8"></script> -->
|
||||
<script>
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
@@ -36,6 +36,8 @@ ace.config.setModuleLoader('ace/keyboard/sublime', () => import('ace-code/src/ke
|
||||
ace.config.setModuleLoader('ace/keyboard/vim', () => import('ace-code/src/keyboard/vim.js'));
|
||||
ace.config.setModuleLoader('ace/keyboard/vscode', () => import('ace-code/src/keyboard/vscode.js'));
|
||||
|
||||
ace.config.setModuleLoader('ace/range', () => import('ace-code/src/range'));
|
||||
|
||||
console.log("ace module loaders patched");
|
||||
|
||||
export { ace };
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Mode as IC10Mode } from "./ic10_mode.js";
|
||||
import * as one_dark from "ace-code/src/theme/one_dark";
|
||||
import { AceLanguageClient } from "ace-linters/build/ace-language-client";
|
||||
import { IC10EditorUI } from './ui.js';
|
||||
|
||||
import { Range } from 'ace-code/src/range.js';
|
||||
// to make sure language tools are loaded
|
||||
import _ace_ext_langue_tools from "ace-code/src/ext/language_tools";
|
||||
|
||||
@@ -21,139 +21,173 @@ async function setupLspWorker() {
|
||||
}
|
||||
|
||||
|
||||
function IC10Editor(session_id) {
|
||||
this.mode = new IC10Mode()
|
||||
class IC10Editor {
|
||||
constructor(session_id) {
|
||||
window.Editor = this;
|
||||
this.mode = new IC10Mode();
|
||||
|
||||
this.settings = {
|
||||
keyboard: "ace",
|
||||
cursor: "ace",
|
||||
fontSize: 16,
|
||||
relativeLineNumbers: false,
|
||||
};
|
||||
this.settings = {
|
||||
keyboard: "ace",
|
||||
cursor: "ace",
|
||||
fontSize: 16,
|
||||
relativeLineNumbers: false,
|
||||
};
|
||||
|
||||
this.editor = ace.edit('editor', {
|
||||
mode: this.mode,
|
||||
enableBasicAutocompletion: true,
|
||||
enableLiveAutocompletion: true,
|
||||
enableSnippets: true,
|
||||
theme: "ace/theme/one_dark",
|
||||
fontSize: "16px",
|
||||
customScrollbar: true,
|
||||
firstLineNumber: 0,
|
||||
printMarginColumn: 52,
|
||||
});
|
||||
this.aceEditor = ace.edit('editor', {
|
||||
mode: this.mode,
|
||||
enableBasicAutocompletion: true,
|
||||
enableLiveAutocompletion: true,
|
||||
enableSnippets: true,
|
||||
theme: "ace/theme/one_dark",
|
||||
fontSize: "16px",
|
||||
customScrollbar: false,
|
||||
firstLineNumber: 0,
|
||||
printMarginColumn: 52,
|
||||
});
|
||||
|
||||
this.sessions = {};
|
||||
this.sessions[session_id] = this.editor.getSession();
|
||||
this.active_session = session_id;
|
||||
this.bindSession(session_id, this.sessions[session_id]);
|
||||
this.sessions = {};
|
||||
this.sessions[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.languageProvider = null;
|
||||
this.languageProvider = null;
|
||||
|
||||
this.ui = new IC10EditorUI(this);
|
||||
this.ui = new IC10EditorUI(this);
|
||||
|
||||
const self = this;
|
||||
const self = this;
|
||||
|
||||
App.session.onLoad((session) => {
|
||||
const updated_ids = [];
|
||||
for (const id in session.programs) {
|
||||
updated_ids.push(id);
|
||||
self.createOrSetSession(id, session.programs[id]);
|
||||
App.session.onLoad((session) => {
|
||||
const updated_ids = [];
|
||||
for (const id in session.programs) {
|
||||
updated_ids.push(id);
|
||||
self.createOrSetSession(id, session.programs[id]);
|
||||
}
|
||||
for (const id in self.sessions) {
|
||||
if (!updated_ids.includes(id)) {
|
||||
self.destroySession(id);
|
||||
}
|
||||
}
|
||||
});
|
||||
App.session.loadFromFragment();
|
||||
|
||||
App.session.onActiveLine(session => {
|
||||
for (const id in Object.keys(session.programs)) {
|
||||
const active_line = session.getActiveLine(id);
|
||||
if (typeof active_line !== "undefined") {
|
||||
const marker = self.active_line_markers[id];
|
||||
if (marker) {
|
||||
self.sessions[id].removeMarker(marker);
|
||||
self.active_line_markers[id] = null;
|
||||
|
||||
}
|
||||
self.active_line_markers[id] = self.sessions[id].addMarker(new Range(active_line, 0, active_line, 1), "vm_ic_active_line", "fullLine", true);
|
||||
if (self.active_session == id) {
|
||||
// editor.resize(true);
|
||||
self.aceEditor.scrollToLine(active_line, true, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
createOrSetSession(session_id, content) {
|
||||
if (!this.sessions.hasOwnProperty(session_id)) {
|
||||
this.newSession(session_id);
|
||||
}
|
||||
for (const id in self.sessions) {
|
||||
if (!updated_ids.includes(id)) {
|
||||
self.destroySession(id);
|
||||
this.sessions[session_id].setValue(content);
|
||||
}
|
||||
|
||||
newSession(session_id) {
|
||||
if (this.sessions.hasOwnProperty(session_id)) {
|
||||
return false;
|
||||
}
|
||||
this.sessions[session_id] = ace.createEditSession("", this.mode);
|
||||
this.bindSession(session_id, this.sessions[session_id]);
|
||||
}
|
||||
|
||||
setupLsp(lsp_worker) {
|
||||
const serverData = {
|
||||
module: () => import("ace-linters/build/language-client"),
|
||||
modes: "ic10",
|
||||
type: "webworker",
|
||||
worker: lsp_worker,
|
||||
};
|
||||
// Create a language provider for web worker
|
||||
this.languageProvider = AceLanguageClient.for(serverData);
|
||||
this.languageProvider.registerEditor(this.aceEditor);
|
||||
|
||||
for (const session_id in this.sessions) {
|
||||
let options = this.mode.options ?? {};
|
||||
this.languageProvider.setSessionOptions(this.sessions[session_id], options);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
activateSession(session_id) {
|
||||
if (!this.sessions.hasOwnProperty(session_id)) {
|
||||
return false;
|
||||
}
|
||||
this.aceEditor.setSession(this.sessions[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;
|
||||
}
|
||||
|
||||
loadEditorSettings() {
|
||||
const saved_settings = window.localStorage.getItem("editorSettings");
|
||||
if (saved_settings !== null && saved_settings.length > 0) {
|
||||
try {
|
||||
const saved = JSON.parse(saved_settings);
|
||||
const temp = Object.assign({}, this.settings, saved);
|
||||
Object.assign(this.settings, temp);
|
||||
} catch (e) {
|
||||
console.log("error loading editor settings", e);
|
||||
}
|
||||
}
|
||||
})
|
||||
App.session.loadFromFragment();
|
||||
|
||||
}
|
||||
|
||||
IC10Editor.prototype.createOrSetSession = function(session_id, content) {
|
||||
if (!this.sessions.hasOwnProperty(session_id)) {
|
||||
this.newSession(session_id);
|
||||
}
|
||||
this.sessions[session_id].setValue(content);
|
||||
}
|
||||
|
||||
IC10Editor.prototype.newSession = function(session_id) {
|
||||
if (this.sessions.hasOwnProperty(session_id)) {
|
||||
return false;
|
||||
}
|
||||
this.sessions[session_id] = ace.createEditSession("", this.mode);
|
||||
this.bindSession(session_id, this.sessions[session_id]);
|
||||
}
|
||||
|
||||
IC10Editor.prototype.setupLsp = function(lsp_worker) {
|
||||
const serverData = {
|
||||
module: () => import("ace-linters/build/language-client"),
|
||||
modes: "ic10",
|
||||
type: "webworker",
|
||||
worker: lsp_worker,
|
||||
};
|
||||
// Create a language provider for web worker
|
||||
this.languageProvider = AceLanguageClient.for(serverData);
|
||||
this.languageProvider.registerEditor(this.editor);
|
||||
|
||||
for (const session_id in this.sessions) {
|
||||
let options = this.mode.options ?? {};
|
||||
this.languageProvider.setSessionOptions(this.sessions[session_id], options);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
IC10Editor.prototype.activateSession = function(session_id) {
|
||||
if (!this.sessions.hasOwnProperty(session_id)) {
|
||||
return false;
|
||||
saveEditorSettings() {
|
||||
const toSave = JSON.stringify(this.settings);
|
||||
window.localStorage.setItem("editorSettings", toSave);
|
||||
}
|
||||
this.editor.setSession(this.sessions[session_id]);
|
||||
let options = this.mode.options ?? {};
|
||||
if (this.languageProvider !== null) {
|
||||
this.languageProvider.setSessionOptions(this.sessions[session_id], options);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
IC10Editor.prototype.loadEditorSettings = function() {
|
||||
const saved_settings = window.localStorage.getItem("editorSettings");
|
||||
if (saved_settings !== null && saved_settings.length > 0) {
|
||||
try {
|
||||
const saved = JSON.parse(saved_settings);
|
||||
const temp = Object.assign({}, this.settings, saved);
|
||||
Object.assign(this.settings, temp);
|
||||
} catch (e) {
|
||||
console.log("error loading editor settings", e);
|
||||
destroySession(session_id) {
|
||||
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];
|
||||
if (this.active_session = session_id) {
|
||||
this.activateSession(Object.keys(this.sessions)[0]);
|
||||
}
|
||||
session.destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
bindSession(session_id, session) {
|
||||
session.on('change', () => {
|
||||
var val = session.getValue();
|
||||
window.App.session.setProgramCode(session_id, val);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
IC10Editor.prototype.saveEditorSettings = function() {
|
||||
const toSave = JSON.stringify(this.settings);
|
||||
window.localStorage.setItem("editorSettings", toSave);
|
||||
}
|
||||
|
||||
IC10Editor.prototype.destroySession = function(session_id) {
|
||||
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];
|
||||
if (this.active_session = session_id) {
|
||||
this.activateSession(Object.keys(this.sessions)[0]);
|
||||
}
|
||||
session.destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
IC10Editor.prototype.bindSession = function(session_id, session) {
|
||||
session.on('change', () => {
|
||||
var val = session.getValue();
|
||||
window.App.session.setProgramCode(session_id, val);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export { IC10Editor, setupLspWorker };
|
||||
|
||||
@@ -107,9 +107,9 @@ export class AsyncStreamQueue {
|
||||
|
||||
async next() {
|
||||
const done = false;
|
||||
console.log(`AsyncStream(${this.tag}) waiting for message`)
|
||||
// console.log(`AsyncStream(${this.tag}) waiting for message`)
|
||||
const value = await this.dequeue();
|
||||
console.log(`AsyncStream(${this.tag}) got message`, decoder.decode(value))
|
||||
// console.log(`AsyncStream(${this.tag}) got message`, decoder.decode(value))
|
||||
return { done, value };
|
||||
}
|
||||
|
||||
|
||||
@@ -1,104 +1,111 @@
|
||||
import { ace } from "./ace";
|
||||
import { Offcanvas } from 'bootstrap';
|
||||
|
||||
function IC10EditorUI(ic10editor) {
|
||||
class IC10EditorUI {
|
||||
|
||||
const self = this;
|
||||
constructor(ic10editor) {
|
||||
|
||||
self.ic10editor = ic10editor;
|
||||
const self = this;
|
||||
|
||||
self.ic10editor.editor.commands.addCommand({
|
||||
name: "showSettingsMenu",
|
||||
description: "Show settings menu",
|
||||
bindKey: { win: "Ctrl-,", mac: "Command-," },
|
||||
exec: (_editor) => {
|
||||
const offCanvas = new Offcanvas(document.getElementById("editorSettings"));
|
||||
offCanvas.toggle();
|
||||
}
|
||||
});
|
||||
self.ic10editor = ic10editor;
|
||||
|
||||
ace.config.loadModule("ace/ext/keyboard_menu", function(module) {
|
||||
console.log("keybinding_menu loaded");
|
||||
module.init(self.ic10editor.editor);
|
||||
})
|
||||
self.ic10editor.aceEditor.commands.addCommand({
|
||||
name: "showSettingsMenu",
|
||||
description: "Show settings menu",
|
||||
bindKey: { win: "Ctrl-,", mac: "Command-," },
|
||||
exec: (_editor) => {
|
||||
const offCanvas = new Offcanvas(document.getElementById("editorSettings"));
|
||||
offCanvas.toggle();
|
||||
}
|
||||
});
|
||||
|
||||
self.ic10editor.loadEditorSettings();
|
||||
self.displayEditorSettings();
|
||||
self.updateEditorSettings();
|
||||
self.reCalcEditorSize();
|
||||
window.addEventListener('resize', (e) => { self.reCalcEditorSize() });
|
||||
ace.config.loadModule("ace/ext/keyboard_menu", function (module) {
|
||||
console.log("keybinding_menu loaded");
|
||||
module.init(self.ic10editor.aceEditor);
|
||||
});
|
||||
|
||||
document.getElementsByName("editorKeybindRadio").forEach((el) => {
|
||||
el.addEventListener('change', (e) => {
|
||||
self.ic10editor.settings.keyboard = e.target.value;
|
||||
self.ic10editor.loadEditorSettings();
|
||||
self.displayEditorSettings();
|
||||
self.updateEditorSettings();
|
||||
self.reCalcEditorSize();
|
||||
window.addEventListener('resize', (e) => { self.reCalcEditorSize(); });
|
||||
|
||||
document.getElementsByName("editorKeybindRadio").forEach((el) => {
|
||||
el.addEventListener('change', (e) => {
|
||||
self.ic10editor.settings.keyboard = e.target.value;
|
||||
self.ic10editor.saveEditorSettings();
|
||||
self.updateEditorSettings();
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementsByName("editorCursorRadio").forEach((el) => {
|
||||
el.addEventListener('change', (e) => {
|
||||
self.ic10editor.settings.cursor = e.target.value;
|
||||
self.ic10editor.saveEditorSettings();
|
||||
self.updateEditorSettings();
|
||||
});
|
||||
});
|
||||
document.getElementById("editorSettingsFontSize").addEventListener('change', (e) => {
|
||||
window.App.editorSettings.fontSize = e.target.value;
|
||||
self.ic10editor.saveEditorSettings();
|
||||
self.updateEditorSettings();
|
||||
})
|
||||
});
|
||||
|
||||
document.getElementsByName("editorCursorRadio").forEach((el) => {
|
||||
el.addEventListener('change', (e) => {
|
||||
self.ic10editor.settings.cursor = e.target.value;
|
||||
});
|
||||
document.getElementById("editorSettingsRelativeLineNumbers").addEventListener('change', (e) => {
|
||||
window.App.editorSettings.relativeLineNumbers = e.target.checked;
|
||||
self.ic10editor.saveEditorSettings();
|
||||
self.updateEditorSettings();
|
||||
})
|
||||
});
|
||||
document.getElementById("editorSettingsFontSize").addEventListener('change', (e) => {
|
||||
window.App.editorSettings.fontSize = e.target.value;
|
||||
self.ic10editor.saveEditorSettings();
|
||||
self.updateEditorSettings();
|
||||
});
|
||||
document.getElementById("editorSettingsRelativeLineNumbers").addEventListener('change', (e) => {
|
||||
window.App.editorSettings.relativeLineNumbers = e.target.checked;
|
||||
self.ic10editor.saveEditorSettings();
|
||||
self.updateEditorSettings();
|
||||
})
|
||||
});
|
||||
|
||||
console.log(self.ic10editor.editor.getOption('keyboardHandler'));
|
||||
console.log(self.ic10editor.aceEditor.getOption('keyboardHandler'));
|
||||
|
||||
self.ic10editor.editor.setTheme("ace/theme/one_dark");
|
||||
ace.config.loadModule("ace/ext/statusbar", function(module) {
|
||||
const statusBar = new module.StatusBar(self.ic10editor.editor, document.getElementById("statusBar"));
|
||||
statusBar.updateStatus(self.ic10editor.editor);
|
||||
})
|
||||
self.ic10editor.aceEditor.setTheme("ace/theme/one_dark");
|
||||
ace.config.loadModule("ace/ext/statusbar", function (module) {
|
||||
const statusBar = new module.StatusBar(self.ic10editor.aceEditor, document.getElementById("statusBar"));
|
||||
statusBar.updateStatus(self.ic10editor.aceEditor);
|
||||
});
|
||||
|
||||
self.ic10editor.editor.setAutoScrollEditorIntoView(true);
|
||||
}
|
||||
self.ic10editor.aceEditor.setAutoScrollEditorIntoView(true);
|
||||
|
||||
IC10EditorUI.prototype.updateEditorSettings = function() {
|
||||
const settings = this.ic10editor.settings;
|
||||
const editor = this.ic10editor.editor;
|
||||
if (settings.keyboard === 'ace') {
|
||||
editor.setOption('keyboardHandler', null);
|
||||
} else {
|
||||
editor.setOption('keyboardHandler', `ace/keyboard/${settings.keyboard}`);
|
||||
}
|
||||
editor.setOption('cursorStyle', settings.cursor);
|
||||
editor.setOption('fontSize', `${settings.fontSize}px`);
|
||||
editor.setOption('relativeLineNumbers', settings.relativeLineNumbers);
|
||||
|
||||
updateEditorSettings() {
|
||||
const settings = this.ic10editor.settings;
|
||||
const editor = this.ic10editor.aceEditor;
|
||||
if (settings.keyboard === 'ace') {
|
||||
editor.setOption('keyboardHandler', null);
|
||||
} else {
|
||||
editor.setOption('keyboardHandler', `ace/keyboard/${settings.keyboard}`);
|
||||
}
|
||||
editor.setOption('cursorStyle', settings.cursor);
|
||||
editor.setOption('fontSize', `${settings.fontSize}px`);
|
||||
editor.setOption('relativeLineNumbers', settings.relativeLineNumbers);
|
||||
}
|
||||
|
||||
displayEditorSettings() {
|
||||
const settings = this.ic10editor.settings;
|
||||
document.getElementsByName("editorKeybindRadio").forEach((el) => {
|
||||
el.checked = el.value === settings.keyboard;
|
||||
});
|
||||
document.getElementsByName("editorCursorRadio").forEach((el) => {
|
||||
el.checked = el.value === settings.cursor;
|
||||
});
|
||||
document.getElementById("editorSettingsFontSize").value = settings.fontSize;
|
||||
document.getElementById("editorSettingsRelativeLineNumbers").checked = settings.relativeLineNumbers;
|
||||
}
|
||||
|
||||
reCalcEditorSize() {
|
||||
const editor = this.ic10editor.aceEditor;
|
||||
const navBar = document.getElementById("navBar");
|
||||
const statusBarContainer = document.getElementById("statusBarContainer");
|
||||
|
||||
const correction = navBar.offsetHeight + statusBarContainer.offsetHeight;
|
||||
const editorContainer = document.getElementById("editor");
|
||||
editorContainer.style.height = `calc( 100vh - ${correction}px - 0.5rem)`;
|
||||
editor.resize(true);
|
||||
}
|
||||
}
|
||||
|
||||
IC10EditorUI.prototype.displayEditorSettings = function() {
|
||||
const settings = this.ic10editor.settings;
|
||||
document.getElementsByName("editorKeybindRadio").forEach((el) => {
|
||||
el.checked = el.value === settings.keyboard;
|
||||
});
|
||||
document.getElementsByName("editorCursorRadio").forEach((el) => {
|
||||
el.checked = el.value === settings.cursor;
|
||||
});
|
||||
document.getElementById("editorSettingsFontSize").value = settings.fontSize;
|
||||
document.getElementById("editorSettingsRelativeLineNumbers").checked = settings.relativeLineNumbers;
|
||||
}
|
||||
|
||||
IC10EditorUI.prototype.reCalcEditorSize = function() {
|
||||
const editor = this.ic10editor.editor;
|
||||
const navBar = document.getElementById("navBar");
|
||||
const statusBarContainer = document.getElementById("statusBarContainer");
|
||||
|
||||
const correction = navBar.offsetHeight + statusBarContainer.offsetHeight;
|
||||
const editorContainer = document.getElementById("editor");
|
||||
editorContainer.style.height = `calc( 100vh - ${correction}px - 0.5rem)`;
|
||||
editor.resize(true);
|
||||
}
|
||||
|
||||
export { IC10EditorUI };
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { init } from "ic10emu_wasm";
|
||||
|
||||
import { IC10Editor, setupLspWorker } from "./editor";
|
||||
import { Session } from './session';
|
||||
import { VirtualMachine } from "./virtual_machine";
|
||||
|
||||
const App = {
|
||||
editor: null,
|
||||
vm: null,
|
||||
session: new Session()
|
||||
};
|
||||
|
||||
@@ -20,10 +20,10 @@ function docReady(fn) {
|
||||
}
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
docReady(() => {
|
||||
|
||||
App.vm = new VirtualMachine();
|
||||
|
||||
App.editor = new IC10Editor();
|
||||
|
||||
setupLspWorker().then((worker) => {
|
||||
|
||||
@@ -37,7 +37,7 @@ move r2 100000.001
|
||||
# to get their documentation
|
||||
# vvvvvvvvvvvvvvv
|
||||
move r0 HASH("AccessCardBlack")
|
||||
beqz r1 test
|
||||
beqzal r1 test
|
||||
|
||||
# -2045627372 is the crc32 hash of a SolarPanel,
|
||||
# hover it to see the documentation!
|
||||
@@ -45,7 +45,7 @@ beqz r1 test
|
||||
move r1 -2045627372
|
||||
jal test
|
||||
move r1 $FF
|
||||
beqz 0 test
|
||||
beqzal 0 test
|
||||
move r1 %1000
|
||||
yield
|
||||
j main
|
||||
@@ -61,6 +61,9 @@ class Session {
|
||||
this._programs = {};
|
||||
this._save_timeout = 0;
|
||||
this._onLoadCallbacks = [];
|
||||
this._activeSession = 0;
|
||||
this._activeLines = {};
|
||||
this._onActiveLineCallbacks = [];
|
||||
this.loadFromFragment();
|
||||
|
||||
const self = this;
|
||||
@@ -77,6 +80,23 @@ class Session {
|
||||
Object.assign(this._programs, programs);
|
||||
}
|
||||
|
||||
get activeSession() {
|
||||
return this._activeSession;
|
||||
}
|
||||
|
||||
getActiveLine(id) {
|
||||
return this._activeLines[id];
|
||||
}
|
||||
|
||||
setActiveLine(id, line) {
|
||||
this._activeLines[id] = line;
|
||||
this._fireOnActiveLine();
|
||||
}
|
||||
|
||||
set activeLine(line) {
|
||||
this._activeLine = line;
|
||||
}
|
||||
|
||||
setProgramCode(id, code) {
|
||||
this._programs[id] = code;
|
||||
this.save();
|
||||
@@ -93,10 +113,25 @@ class Session {
|
||||
}
|
||||
}
|
||||
|
||||
onActiveLine(callback) {
|
||||
this._onActiveLineCallbacks.push(callback);
|
||||
}
|
||||
|
||||
_fireOnActiveLine() {
|
||||
for (const i in this._onActiveLineCallbacks) {
|
||||
const callback = this._onActiveLineCallbacks[i];
|
||||
callback(this);
|
||||
}
|
||||
}
|
||||
|
||||
save() {
|
||||
if (this._save_timeout) clearTimeout(this._save_timeout);
|
||||
this._save_timeout = setTimeout(() => {
|
||||
this.saveToFragment();
|
||||
if (window.App.vm) {
|
||||
window.App.vm.updateCode();
|
||||
}
|
||||
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
|
||||
201
www/src/js/virtual_machine/index.js
Normal file
201
www/src/js/virtual_machine/index.js
Normal file
@@ -0,0 +1,201 @@
|
||||
import { init } from "ic10emu_wasm";
|
||||
// import { Card } from 'bootstrap';
|
||||
|
||||
class VirtualMachine {
|
||||
|
||||
constructor() {
|
||||
const vm = init();
|
||||
|
||||
window.VM = this;
|
||||
|
||||
this.ic10vm = vm;
|
||||
this.ui = new VirtualMachineUI(this);
|
||||
|
||||
this.ics = {}
|
||||
const ics = this.ic10vm.ics;
|
||||
for (const id of Object.keys(ics)) {
|
||||
this.ics[id] = this.ic10vm.getDevice(parseInt(id));
|
||||
}
|
||||
this.updateCode()
|
||||
|
||||
|
||||
}
|
||||
|
||||
updateCode() {
|
||||
const progs = window.App.session.programs;
|
||||
for (const id of Object.keys(progs)) {
|
||||
const ic = this.ics[id];
|
||||
const prog = progs[id];
|
||||
if (ic && prog) {
|
||||
console.time(`CompileProgram_${id}`);
|
||||
this.ics[id].setCode(progs[id]);
|
||||
console.timeEnd(`CompileProgram_${id}`);
|
||||
}
|
||||
}
|
||||
this.update();
|
||||
}
|
||||
|
||||
step() {
|
||||
const ic = this.ics[window.App.session.activeSession];
|
||||
if (ic) {
|
||||
try {
|
||||
ic.step();
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
run() {
|
||||
const ic = this.ics[window.App.session.activeSession];
|
||||
if (ic) {
|
||||
try {
|
||||
ic.run(false);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
reset() {
|
||||
const ic = this.ics[window.App.session.activeSession];
|
||||
if (ic) {
|
||||
ic.reset();
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
update() {
|
||||
const ic = this.ics[window.App.session.activeSession];
|
||||
window.App.session.setActiveLine(window.App.session.activeSession, ic.ip);
|
||||
this.ui.update(ic);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class VirtualMachineUI {
|
||||
constructor(vm) {
|
||||
this.vm = vm
|
||||
this.state = new VMStateUI();
|
||||
this.registers = new VMRegistersUI();
|
||||
this.buildStackDisplay();
|
||||
|
||||
const self = this;
|
||||
|
||||
|
||||
document.getElementById("vmControlRun").addEventListener('click', (_event) => {
|
||||
self.vm.run();
|
||||
}, { capture: true });
|
||||
document.getElementById("vmControlStep").addEventListener('click', (_event) => {
|
||||
self.vm.step();
|
||||
}, { capture: true });
|
||||
document.getElementById("vmControlReset").addEventListener('click', (_event) => {
|
||||
self.vm.reset();
|
||||
}, { capture: true });
|
||||
|
||||
}
|
||||
|
||||
update(ic) {
|
||||
this.state.update(ic);
|
||||
this.registers.update(ic);
|
||||
}
|
||||
|
||||
|
||||
buildStackDisplay() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class VMStateUI {
|
||||
constructor() {
|
||||
const stateDom = document.getElementById("vmActiveICState");
|
||||
|
||||
this.tbl = document.createElement("table");
|
||||
this.tbl.classList.add("table");
|
||||
this.ipRow = this.tbl.insertRow();
|
||||
this.counterRow = this.tbl.insertRow()
|
||||
this.stateRow = this.tbl.insertRow()
|
||||
const ipTh = document.createElement("th");
|
||||
ipTh.appendChild(document.createTextNode("Instruction Pointer"));
|
||||
this.ipRow.appendChild(ipTh);
|
||||
this.instructionPointer = this.ipRow.insertCell();
|
||||
const conuterTh = document.createElement("th");
|
||||
conuterTh.appendChild(document.createTextNode("Last Run Operations"));
|
||||
this.counterRow.appendChild(conuterTh);
|
||||
this.instructionCounter = this.counterRow.insertCell();
|
||||
const stateTh = document.createElement("th");
|
||||
stateTh.appendChild(document.createTextNode("Last State"));
|
||||
this.stateRow.appendChild(stateTh);
|
||||
this.lastState = this.stateRow.insertCell();
|
||||
|
||||
stateDom.appendChild(this.tbl);
|
||||
}
|
||||
|
||||
update(ic) {
|
||||
if (ic) {
|
||||
this.instructionPointer.innerText = ic.ip.toString();
|
||||
this.instructionCounter.innerText = ic.instructionCount.toString();
|
||||
this.lastState.innerText = ic.state.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VMRegistersUI {
|
||||
constructor() {
|
||||
const regDom = document.getElementById("vmActiveRegisters");
|
||||
this.tbl = document.createElement("div");
|
||||
this.tbl.classList.add("d-flex", "flex-wrap", "justify-content-start", "align-items-start", "align-self-center");
|
||||
this.regCels = [];
|
||||
for (var i = 0; i < 18; i++) {
|
||||
const container = document.createElement("div");
|
||||
container.classList.add("vm_reg_cel");
|
||||
const cell = document.createElement("div");
|
||||
cell.classList.add("input-group", "input-group-sm")
|
||||
// cell.style.width = "30%";
|
||||
const nameLabel = document.createElement("span");
|
||||
nameLabel.innerText = `r${i}`;
|
||||
nameLabel.classList.add("input-group-text")
|
||||
cell.appendChild(nameLabel);
|
||||
const input = document.createElement("input");
|
||||
input.type = "text"
|
||||
input.value = 0;
|
||||
// input.size = 3;
|
||||
// input.style.width = 40;
|
||||
cell.appendChild(input);
|
||||
const aliasesLabel = document.createElement("span");
|
||||
aliasesLabel.classList.add("input-group-text")
|
||||
aliasesLabel.innerText = "\xa0";
|
||||
cell.appendChild(aliasesLabel);
|
||||
if (i == 16 ) {
|
||||
aliasesLabel.innerText = "sp";
|
||||
} else if (i == 17) {
|
||||
aliasesLabel.innerText = "ra";
|
||||
}
|
||||
this.regCels.push({
|
||||
cell,
|
||||
nameLabel,
|
||||
aliasesLabel,
|
||||
input,
|
||||
});
|
||||
container.appendChild(cell);
|
||||
this.tbl.appendChild(container);
|
||||
}
|
||||
regDom.appendChild(this.tbl);
|
||||
}
|
||||
|
||||
update(ic) {
|
||||
if (ic) {
|
||||
const registers = ic.registers;
|
||||
if (registers) {
|
||||
console.log(registers)
|
||||
for (var i = 0; i < registers.length; i++) {
|
||||
this.regCels[i].input.value = registers[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { VirtualMachine }
|
||||
@@ -409,3 +409,33 @@ code {
|
||||
border: 1px solid rgba(8, 121, 144, 0.5);
|
||||
background: rgba(76, 87, 103, .19);
|
||||
}
|
||||
|
||||
.vm_ic_active_line {
|
||||
position: absolute;
|
||||
background: rgba(121, 82, 179, 0.4);
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.vm_reg {
|
||||
overflow-x: auto;
|
||||
overflow-y: auto;
|
||||
max-width: 1200px;
|
||||
max-height: 400px;
|
||||
}
|
||||
|
||||
// .vm_unset_reg .input-group {
|
||||
// width: inherit;
|
||||
// }
|
||||
|
||||
.vm_reg_cel {
|
||||
max-width: 300px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.vm_reg_cel span {
|
||||
min-width: 2.5rem;
|
||||
}
|
||||
|
||||
.vm_reg_cel input {
|
||||
width: 6rem;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ $offcanvas-box-shadow: 0 1rem 3rem rgba(0, 0, 0, .175);
|
||||
$body-color: #333;
|
||||
$body-bg: #fff;
|
||||
$border-radius: .4rem;
|
||||
$success: #7952b3;
|
||||
$success: rgb(121, 82, 179);
|
||||
|
||||
// Required
|
||||
@import "bootstrap/scss/variables";
|
||||
|
||||
Reference in New Issue
Block a user