Merge pull request #4 from Emilgardis/fixes

Some small changes and fixes
This commit is contained in:
Rachel Powers
2024-03-29 15:04:29 -07:00
committed by GitHub
6 changed files with 489 additions and 1448 deletions

View File

@@ -29,7 +29,7 @@ where
{
pub aliases: Vec<String>,
pub value: Option<P>,
pub depricated: bool,
pub deprecated: bool,
}
fn write_repr_enum<T: std::io::Write, I, P>(
@@ -49,7 +49,7 @@ fn write_repr_enum<T: std::io::Write, I, P>(
pub enum {name} {{\n"
)
.unwrap();
for (name, variant) in variants.into_iter() {
for (name, variant) in variants {
let variant_name = name.to_case(Case::Pascal);
let mut serialize = vec![name.clone()];
serialize.extend(variant.aliases.iter().cloned());
@@ -58,23 +58,23 @@ fn write_repr_enum<T: std::io::Write, I, P>(
.map(|s| format!("serialize = \"{s}\""))
.collect::<Vec<String>>()
.join(", ");
let depricated_str = if variant.depricated {
", depricated = \"true\"".to_string()
let deprecated_str = if variant.deprecated {
", deprecated = \"true\"".to_owned()
} else {
"".to_string()
"".to_owned()
};
let props_str = if let Some(val) = &variant.value {
format!(", props( value = \"{val}\"{depricated_str})")
format!(", props( value = \"{val}\"{deprecated_str})")
} else {
"".to_string()
"".to_owned()
};
write!(
writeln!(
writer,
" #[strum({serialize_str}{props_str})] {variant_name},\n"
" #[strum({serialize_str}{props_str})] {variant_name},"
)
.unwrap();
}
write!(writer, "}}\n").unwrap();
writeln!(writer, "}}").unwrap();
}
fn write_logictypes() {
@@ -94,7 +94,7 @@ fn write_logictypes() {
let val_str = it.next().unwrap();
let val: Option<u8> = val_str.parse().ok();
let docs = it.next();
let depricated = docs
let deprecated = docs
.map(|docs| docs.trim().to_uppercase() == "DEPRECATED")
.unwrap_or(false);
@@ -104,14 +104,14 @@ fn write_logictypes() {
.find(|(_, variant)| variant.value == Some(val))
{
variant.aliases.push(name.to_string());
variant.depricated = depricated;
variant.deprecated = deprecated;
} else {
logictypes.insert(
name.to_string(),
EnumVariant {
aliases: Vec::new(),
value: Some(val),
depricated,
deprecated,
},
);
}
@@ -121,7 +121,7 @@ fn write_logictypes() {
EnumVariant {
aliases: Vec::new(),
value: val,
depricated,
deprecated,
},
);
}
@@ -137,7 +137,7 @@ fn write_logictypes() {
let val_str = it.next().unwrap();
let val: Option<u8> = val_str.parse().ok();
let docs = it.next();
let depricated = docs
let deprecated = docs
.map(|docs| docs.trim().to_uppercase() == "DEPRECATED")
.unwrap_or(false);
@@ -147,14 +147,14 @@ fn write_logictypes() {
.find(|(_, variant)| variant.value == Some(val))
{
variant.aliases.push(name.to_string());
variant.depricated = depricated;
variant.deprecated = deprecated;
} else {
slotlogictypes.insert(
name.to_string(),
EnumVariant {
aliases: Vec::new(),
value: Some(val),
depricated,
deprecated,
},
);
}
@@ -164,7 +164,7 @@ fn write_logictypes() {
EnumVariant {
aliases: Vec::new(),
value: val,
depricated,
deprecated,
},
);
}
@@ -192,9 +192,8 @@ fn write_enums() {
let e_contents = fs::read_to_string(e_infile).unwrap();
for line in e_contents.lines().filter(|l| !l.trim().is_empty()) {
let mut it = line.splitn(2, ' ');
let name = it.next().unwrap();
let val_str = it.next().unwrap();
let (name, val_str) = line.split_once(' ').unwrap();
let val: Option<u8> = val_str.parse().ok();
if !check_set.contains(name) {
@@ -206,9 +205,9 @@ fn write_enums() {
}
}
write!(
writeln!(
&mut writer,
"pub(crate) const ENUM_LOOKUP: phf::Map<&'static str, u8> = {};\n",
"pub(crate) const ENUM_LOOKUP: phf::Map<&'static str, u8> = {};",
enums_lookup_map_builder.build()
)
.unwrap();
@@ -245,7 +244,7 @@ fn write_modes() {
EnumVariant {
aliases: Vec::new(),
value: Some(val),
depricated: false,
deprecated: false,
},
);
}
@@ -255,7 +254,7 @@ fn write_modes() {
EnumVariant {
aliases: Vec::new(),
value: val,
depricated: false,
deprecated: false,
},
);
}
@@ -283,7 +282,7 @@ fn write_modes() {
EnumVariant {
aliases: Vec::new(),
value: Some(val),
depricated: false,
deprecated: false,
},
);
}
@@ -293,7 +292,7 @@ fn write_modes() {
EnumVariant {
aliases: Vec::new(),
value: val,
depricated: false,
deprecated: false,
},
);
}
@@ -327,9 +326,9 @@ fn write_constants() {
constants_lookup_map_builder.entry(name, constant);
}
write!(
writeln!(
&mut writer,
"pub(crate) const CONSTANTS_LOOKUP: phf::Map<&'static str, f64> = {};\n",
"pub(crate) const CONSTANTS_LOOKUP: phf::Map<&'static str, f64> = {};",
constants_lookup_map_builder.build()
)
.unwrap();
@@ -355,18 +354,18 @@ fn write_instructions_enum() {
write!(
&mut writer,
"#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]\n\
"#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]\n\
pub enum InstructionOp {{\n\
"
)
.unwrap();
write!(&mut writer, " Nop,\n").unwrap();
writeln!(&mut writer, " Nop,").unwrap();
for typ in &instructions {
write!(&mut writer, " {},\n", typ.to_case(Case::Pascal)).unwrap();
writeln!(&mut writer, " {},", typ.to_case(Case::Pascal)).unwrap();
}
write!(&mut writer, "}}\n").unwrap();
writeln!(&mut writer, "}}").unwrap();
write!(
&mut writer,
@@ -380,7 +379,7 @@ fn write_instructions_enum() {
for typ in &instructions {
let name = typ.to_case(Case::Pascal);
write!(&mut writer, " \"{typ}\" => Ok(Self::{name}),\n").unwrap();
writeln!(&mut writer, " \"{typ}\" => Ok(Self::{name}),").unwrap();
}
write!(
&mut writer,

View File

@@ -9,6 +9,7 @@ use strum::EnumProperty;
pub mod generated {
use super::ParseError;
use crate::interpreter::ICError;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use strum::AsRefStr;
use strum::Display;
@@ -16,7 +17,6 @@ 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"));
@@ -110,32 +110,32 @@ impl Error for ParseError {}
impl ParseError {
/// Offset the ParseError in it's line, adding the passed values to it's `start` and `end`
#[must_use]
pub fn offset(self, offset: usize) -> Self {
ParseError {
line: self.line,
start: self.start + offset,
end: self.end + offset,
msg: self.msg,
..self
}
}
/// Offset the ParseError line, adding the passed value to it's `line`
#[must_use]
pub fn offset_line(self, offset: usize) -> Self {
ParseError {
line: self.line + offset,
start: self.start,
end: self.end,
msg: self.msg,
..self
}
}
/// Mark the parse error as extending 'length' bytes from `start`
#[must_use]
pub fn span(self, length: usize) -> Self {
ParseError {
line: self.line,
start: self.start,
end: self.start + length,
msg: self.msg,
..self
}
}
}
@@ -156,10 +156,10 @@ pub struct Line {
impl FromStr for Line {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut parts = s.splitn(2, "#");
let mut parts = s.splitn(2, '#');
let code = parts
.next()
.map(|s| {
.and_then(|s| {
let s = s.trim_end();
if s.is_empty() {
None
@@ -167,7 +167,6 @@ impl FromStr for Line {
Some(s.parse::<Code>())
}
})
.flatten()
.transpose()?;
let comment = parts.next().map(|s| s.parse()).transpose()?;
Ok(Line { code, comment })
@@ -196,7 +195,7 @@ impl FromStr for Code {
}
}
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Eq, Debug)]
pub struct Comment {
pub comment: String,
}
@@ -231,11 +230,11 @@ impl FromStr for Instruction {
line: 0,
start: 0,
end: 0,
msg: format!("Missing instruction"),
msg: "Missing instruction".to_owned(),
})
}
}?;
let operands = get_operand_tokens(s, tokens_iter)
.iter()
.map(|(index, token)| {
@@ -251,7 +250,10 @@ impl FromStr for Instruction {
}
}
fn get_operand_tokens<'a>(s: &'a str, tokens_iter: SplitConsecutiveWithIndices<'a>) -> Vec<(usize, &'a str)> {
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 {
@@ -270,7 +272,7 @@ fn get_operand_tokens<'a>(s: &'a str, tokens_iter: SplitConsecutiveWithIndices<'
operand_tokens
}
#[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize)]
#[derive(PartialEq, Eq, Debug, Clone, Copy, Serialize, Deserialize)]
pub enum Device {
Db,
Numbered(u32),
@@ -298,29 +300,29 @@ pub enum Operand {
impl Operand {
pub fn get_value(&self, ic: &interpreter::IC) -> Result<f64, interpreter::ICError> {
match &self {
&Operand::RegisterSpec {
Operand::RegisterSpec {
indirection,
target,
} => ic.get_register(*indirection, *target),
&Operand::Number(num) => Ok(num.value()),
&Operand::LogicType(lt) => lt
Operand::Number(num) => Ok(num.value()),
Operand::LogicType(lt) => lt
.get_str("value")
.map(|val| val.parse::<u8>().unwrap() as f64)
.ok_or(interpreter::ICError::TypeValueNotKnown),
&Operand::SlotLogicType(slt) => slt
Operand::SlotLogicType(slt) => slt
.get_str("value")
.map(|val| val.parse::<u8>().unwrap() as f64)
.ok_or(interpreter::ICError::TypeValueNotKnown),
&Operand::BatchMode(bm) => bm
Operand::BatchMode(bm) => bm
.get_str("value")
.map(|val| val.parse::<u8>().unwrap() as f64)
.ok_or(interpreter::ICError::TypeValueNotKnown),
&Operand::ReagentMode(rm) => rm
Operand::ReagentMode(rm) => rm
.get_str("value")
.map(|val| val.parse::<u8>().unwrap() as f64)
.ok_or(interpreter::ICError::TypeValueNotKnown),
&Operand::Identifier(ident) => ic.get_ident_value(&ident.name),
&Operand::DeviceSpec { .. } => Err(interpreter::ICError::DeviceNotValue),
Operand::Identifier(ident) => ic.get_ident_value(&ident.name),
Operand::DeviceSpec { .. } => Err(interpreter::ICError::DeviceNotValue),
}
}
@@ -330,9 +332,9 @@ impl Operand {
signed: bool,
) -> Result<i64, interpreter::ICError> {
let val = self.get_value(ic)?;
if val < -9.223372036854776E+18 {
if val < -9.223_372_036_854_776E18 {
Err(interpreter::ICError::ShiftUnderflowI64)
} else if val <= 9.223372036854776E+18 {
} else if val <= 9.223_372_036_854_776E18 {
Ok(interpreter::f64_to_i64(val, signed))
} else {
Err(interpreter::ICError::ShiftOverflowI64)
@@ -355,7 +357,7 @@ impl Operand {
ic: &interpreter::IC,
) -> Result<(Option<u16>, Option<u32>), interpreter::ICError> {
match &self {
&Operand::DeviceSpec { device, connection } => match device {
Operand::DeviceSpec { device, connection } => match device {
Device::Db => Ok((Some(ic.device), *connection)),
Device::Numbered(p) => {
let dp = ic
@@ -378,7 +380,7 @@ impl Operand {
Ok((dp, *connection))
}
},
&Operand::Identifier(id) => ic.get_ident_device_id(&id.name),
Operand::Identifier(id) => ic.get_ident_device_id(&id.name),
_ => Err(interpreter::ICError::ValueNotDevice),
}
}
@@ -402,13 +404,12 @@ impl FromStr for Operand {
let mut rest_iter = rest.iter();
let indirection = rest_iter.take_while_ref(|c| *c == &'r').count();
let target = rest_iter
.take_while_ref(|c| c.is_digit(10))
.take_while_ref(|c| c.is_ascii_digit())
.collect::<String>()
.parse::<u32>()
.ok();
let trailing = rest_iter.count();
if let Some(target) = target {
if trailing == 0 {
if rest_iter.next().is_none() {
return Ok(Operand::RegisterSpec {
indirection: indirection as u32,
target,
@@ -419,7 +420,7 @@ impl FromStr for Operand {
line: 0,
start: 0,
end: 0,
msg: format!("Invalid register specifier"),
msg: "Invalid register specifier".to_owned(),
})
}
['d', rest @ ..] => match rest {
@@ -428,7 +429,7 @@ impl FromStr for Operand {
connection: None,
}),
['b', ':', chan @ ..] => {
if chan.into_iter().all(|c| c.is_digit(10)) {
if chan.iter().all(|c| c.is_ascii_digit()) {
Ok(Operand::DeviceSpec {
device: Device::Db,
connection: Some(String::from_iter(chan).parse().unwrap()),
@@ -438,15 +439,15 @@ impl FromStr for Operand {
line: 0,
start: 3,
end: 3,
msg: format!("Invalid device connection specifier"),
msg: "Invalid device connection specifier".to_owned(),
})
}
}
['r', rest @ ..] => {
let mut rest_iter = rest.into_iter().peekable();
let mut rest_iter = rest.iter().peekable();
let indirection = rest_iter.take_while_ref(|c| *c == &'r').count();
let target_str = rest_iter
.take_while_ref(|c| c.is_digit(10))
.take_while_ref(|c| c.is_ascii_digit())
.collect::<String>();
let target = target_str.parse::<u32>().ok();
let connection = {
@@ -454,11 +455,10 @@ impl FromStr for Operand {
// take off ':'
rest_iter.next();
let connection_str = rest_iter
.take_while_ref(|c| c.is_digit(10))
.take_while_ref(|c| c.is_ascii_digit())
.collect::<String>();
let connection = connection_str.parse::<u32>().unwrap();
let trailing = rest_iter.clone().collect::<Vec<_>>();
if trailing.len() == 0 {
if rest_iter.next().is_none() {
Ok(Some(connection))
} else {
let start =
@@ -467,39 +467,38 @@ impl FromStr for Operand {
line: 0,
start,
end: start,
msg: format!("Invalid device connection specifier"),
msg: "Invalid device connection specifier".to_owned(),
})
}
} else {
Ok(None)
}
}?;
let trailing = rest_iter.collect::<Vec<_>>();
if let Some(target) = target {
if trailing.len() == 0 {
if rest_iter.next().is_none() {
Ok(Operand::DeviceSpec {
device: Device::Indirect {
indirection: indirection as u32,
target,
},
connection: connection,
connection,
})
} else {
Err(ParseError {
line: 0,
start: 0,
end: 0,
msg: format!("Invalid register specifier"),
msg: "Invalid register specifier".to_owned(),
})
}
} else {
Ok(Operand::Identifier(s.parse::<Identifier>()?))
}
}
[rest @ ..] => {
let mut rest_iter = rest.into_iter().peekable();
rest => {
let mut rest_iter = rest.iter().peekable();
let target_str = rest_iter
.take_while_ref(|c| c.is_digit(10))
.take_while_ref(|c| c.is_ascii_digit())
.collect::<String>();
let target = target_str.parse::<u32>().ok();
let connection = {
@@ -507,11 +506,10 @@ impl FromStr for Operand {
// take off ':'
rest_iter.next();
let connection_str = rest_iter
.take_while_ref(|c| c.is_digit(10))
.take_while_ref(|c| c.is_ascii_digit())
.collect::<String>();
let connection = connection_str.parse::<u32>().unwrap();
let trailing = rest_iter.clone().collect::<Vec<_>>();
if trailing.len() == 0 {
if rest_iter.next().is_none() {
Ok(Some(connection))
} else {
let start = 1 + target_str.len() + 1 + connection_str.len();
@@ -519,26 +517,25 @@ impl FromStr for Operand {
line: 0,
start,
end: start,
msg: format!("Invalid device connection specifier"),
msg: "Invalid device connection specifier".to_owned(),
})
}
} else {
Ok(None)
}
}?;
let trailing = rest_iter.collect::<Vec<_>>();
if let Some(target) = target {
if trailing.len() == 0 {
if rest_iter.next().is_none() {
Ok(Operand::DeviceSpec {
device: Device::Numbered(target),
connection: connection,
connection,
})
} else {
Err(ParseError {
line: 0,
start: 0,
end: 0,
msg: format!("Invalid device specifier"),
msg: "Invalid device specifier".to_owned(),
})
}
} else {
@@ -554,60 +551,58 @@ impl FromStr for Operand {
line: 0,
start: 0,
end: 0,
msg: format!("Invalid hash string: Can not contain '\"'"),
msg: "Invalid hash string: Can not contain '\"'".to_owned(),
})
}
}
['$', rest @ ..] => {
let mut rest_iter = rest.into_iter();
let mut rest_iter = rest.iter();
let num_str = rest_iter
.take_while_ref(|c| c.is_digit(16))
.take_while_ref(|c| c.is_ascii_hexdigit())
.collect::<String>();
let num = i64::from_str_radix(&num_str, 16).unwrap() as f64;
let trailing = rest_iter.count();
if trailing == 0 {
if rest_iter.next().is_none() {
Ok(Operand::Number(Number::Hexadecimal(num)))
} else {
Err(ParseError {
line: 0,
start: 0,
end: 0,
msg: format!("Invalid Hexadecimal Number"),
msg: "Invalid Hexadecimal Number".to_owned(),
})
}
}
['%', rest @ ..] => {
let mut rest_iter = rest.into_iter();
let mut rest_iter = rest.iter();
let num_str = rest_iter
.take_while_ref(|c| c.is_digit(2))
.collect::<String>();
let num = i64::from_str_radix(&num_str, 2).unwrap() as f64;
let trailing = rest_iter.count();
if trailing == 0 {
if rest_iter.next().is_none() {
Ok(Operand::Number(Number::Binary(num)))
} else {
Err(ParseError {
line: 0,
start: 0,
end: 0,
msg: format!("Invalid Binary Number"),
msg: "Invalid Binary Number".to_owned(),
})
}
}
[rest @ ..] => {
let mut rest_iter = rest.into_iter().peekable();
rest => {
let mut rest_iter = rest.iter().peekable();
let float_str = if rest_iter.peek() == Some(&&'-') {
format!("{}", rest_iter.next().unwrap())
} else {
"".to_string()
"".to_owned()
} + &rest_iter
.take_while_ref(|c| c.is_digit(10))
.take_while_ref(|c| c.is_ascii_digit())
.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))
.take_while_ref(|c| c.is_ascii_digit())
.collect::<String>();
if !decimal_str.is_empty() {
let float_str = float_str + "." + &decimal_str;
@@ -619,23 +614,20 @@ impl FromStr for Operand {
line: 0,
start,
end: start,
msg: format!("Invalid Decimal Number"),
msg: "Invalid Decimal Number".to_owned(),
})
}
} else if rest_iter.next().is_none() {
let num = f64::from_str(&float_str).unwrap();
Ok(Operand::Number(Number::Float(num)))
} else {
let trailing = rest_iter.count();
if trailing == 0 {
let num = f64::from_str(&float_str).unwrap();
Ok(Operand::Number(Number::Float(num)))
} else {
let start = float_str.len();
Err(ParseError {
line: 0,
start,
end: start,
msg: format!("Invalid Integer Number"),
})
}
let start = float_str.len();
Err(ParseError {
line: 0,
start,
end: start,
msg: "Invalid Integer Number".to_owned(),
})
}
} else if let Some(val) = CONSTANTS_LOOKUP.get(s) {
Ok(Operand::Number(Number::Constant(*val)))
@@ -663,7 +655,7 @@ impl FromStr for Operand {
// pub value: f64,
// }
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Eq, Debug)]
pub struct Label {
pub id: Identifier,
// #[rust_sitter::leaf(text = r":")] pub ());
@@ -680,19 +672,19 @@ impl FromStr for Label {
line: 0,
start: index,
end: index,
msg: "Missing ':' at end of label".to_string(),
msg: "Missing ':' at end of label".to_owned(),
}),
None => Err(ParseError {
line: 0,
start: 0,
end: 0,
msg: "empty string for label? parse miscalled".to_string(),
msg: "empty string for label? parse miscalled".to_owned(),
}),
}
}
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
#[derive(PartialEq, Eq, 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,
@@ -703,10 +695,7 @@ impl FromStr for Identifier {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut iter = s.chars();
if let Some(c) = iter.next() {
if match c {
'a'..='z' | 'A'..='Z' | '_' | '.' => true,
_ => false,
} {
if matches!(c, 'a'..='z' | 'A'..='Z' | '_' | '.') {
for (index, cc) in iter.enumerate() {
match cc {
'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' => continue,
@@ -734,7 +723,7 @@ impl FromStr for Identifier {
line: 0,
start: 0,
end: 0,
msg: format!("Empty Identifier"),
msg: "Empty Identifier".to_owned(),
})
}
}
@@ -753,11 +742,11 @@ pub enum Number {
impl Number {
pub fn value(&self) -> f64 {
match self {
Number::Enum(val) => *val,
Number::Float(val) => *val,
Number::Binary(val) => *val,
Number::Constant(val) => *val,
Number::Hexadecimal(val) => *val,
Number::Enum(val)
| Number::Float(val)
| Number::Binary(val)
| Number::Constant(val)
| Number::Hexadecimal(val) => *val,
Number::String(s) => const_crc32::crc32(s.as_bytes()) as i32 as f64,
}
}
@@ -786,7 +775,7 @@ mod tests {
],
},),),
comment: Some(Comment {
comment: " This is a comment".to_string(),
comment: " This is a comment".to_owned(),
},),
},],
);
@@ -838,7 +827,7 @@ mod tests {
Line {
code: None,
comment: Some(Comment {
comment: " This is a comment".to_string(),
comment: " This is a comment".to_owned(),
},),
},
Line {
@@ -846,7 +835,7 @@ mod tests {
instruction: InstructionOp::Define,
operands: vec![
Operand::Identifier(Identifier {
name: "a_def".to_string(),
name: "a_def".to_owned(),
},),
Operand::Number(Number::Float(10.0,),),
],
@@ -858,9 +847,9 @@ mod tests {
instruction: InstructionOp::Define,
operands: vec![
Operand::Identifier(Identifier {
name: "a_hash".to_string(),
name: "a_hash".to_owned(),
},),
Operand::Number(Number::String("This is a String".to_string()),),
Operand::Number(Number::String("This is a String".to_owned()),),
],
},),),
comment: None,
@@ -870,7 +859,7 @@ mod tests {
instruction: InstructionOp::Alias,
operands: vec![
Operand::Identifier(Identifier {
name: "a_var".to_string(),
name: "a_var".to_owned(),
},),
Operand::RegisterSpec {
indirection: 0,
@@ -885,7 +874,7 @@ mod tests {
instruction: InstructionOp::Alias,
operands: vec![
Operand::Identifier(Identifier {
name: "a_device".to_string(),
name: "a_device".to_owned(),
},),
Operand::DeviceSpec {
device: Device::Numbered(0),
@@ -938,7 +927,7 @@ mod tests {
Line {
code: Some(Code::Label(Label {
id: Identifier {
name: "main".to_string(),
name: "main".to_owned(),
},
},),),
comment: None,
@@ -975,7 +964,7 @@ mod tests {
indirection: 0,
target: 0,
},
Operand::Number(Number::String("AccessCardBlack".to_string()),),
Operand::Number(Number::String("AccessCardBlack".to_owned()),),
],
},),),
comment: None,
@@ -1043,7 +1032,7 @@ mod tests {
code: Some(Code::Instruction(Instruction {
instruction: InstructionOp::J,
operands: vec![Operand::Identifier(Identifier {
name: "main".to_string(),
name: "main".to_owned(),
},),],
},),),
comment: None,

File diff suppressed because it is too large Load Diff

View File

@@ -76,17 +76,11 @@ pub struct Network {
pub channels: [f64; 8],
}
#[derive(Debug)]
#[derive(Debug, Default)]
struct IdSequenceGenerator {
next: u16,
}
impl Default for IdSequenceGenerator {
fn default() -> Self {
IdSequenceGenerator { next: 0 }
}
}
impl IdSequenceGenerator {
pub fn next(&mut self) -> u16 {
let val = self.next;
@@ -201,16 +195,14 @@ impl Device {
pub fn get_network_id(&self, connection: usize) -> Result<u16, ICError> {
if connection >= 8 {
Err(ICError::ConnecitonIndexOutOFRange(connection as u32))
} else {
if let Connection::CableNetwork(network_id) = self.connections[connection] {
if let Some(network_id) = network_id {
Ok(network_id)
} else {
Err(ICError::NetworkNotConnected(connection as u32))
}
} else if let Connection::CableNetwork(network_id) = self.connections[connection] {
if let Some(network_id) = network_id {
Ok(network_id)
} else {
Err(ICError::NotDataConnection(connection as u32))
Err(ICError::NetworkNotConnected(connection as u32))
}
} else {
Err(ICError::NotDataConnection(connection as u32))
}
}
@@ -291,6 +283,12 @@ impl Device {
}
}
impl Default for VM {
fn default() -> Self {
Self::new()
}
}
impl VM {
pub fn new() -> Self {
let id_gen = IdSequenceGenerator::default();
@@ -331,18 +329,13 @@ impl VM {
}
}
let mut device = self.new_device();
if let Some(first_network) = device
.connections
.iter_mut()
.filter_map(|c| {
if let Connection::CableNetwork(c) = c {
Some(c)
} else {
None
}
})
.next()
{
if let Some(first_network) = device.connections.iter_mut().find_map(|c| {
if let Connection::CableNetwork(c) = c {
Some(c)
} else {
None
}
}) {
first_network.replace(if let Some(network) = network {
network
} else {
@@ -369,18 +362,13 @@ impl VM {
}
}
let (mut device, ic) = self.new_ic();
if let Some(first_network) = device
.connections
.iter_mut()
.filter_map(|c| {
if let Connection::CableNetwork(c) = c {
Some(c)
} else {
None
}
})
.next()
{
if let Some(first_network) = device.connections.iter_mut().find_map(|c| {
if let Connection::CableNetwork(c) = c {
Some(c)
} else {
None
}
}) {
first_network.replace(if let Some(network) = network {
network
} else {
@@ -524,7 +512,7 @@ impl VM {
}
pub fn devices_on_same_network(&self, ids: &[u16]) -> bool {
for (_id, net) in self.networks.iter() {
for net in self.networks.values() {
if net.borrow().contains(ids) {
return true;
}
@@ -656,17 +644,14 @@ impl VM {
.iter()
.any(|(_net_id, net)| net.borrow().contains(&[source, *id]))
{
device.borrow_mut().get_field(typ).map(|val| Some(val))
device.borrow_mut().get_field(typ).map(Some)
} else {
Ok(None)
}
})
.collect::<Result<Vec<_>, ICError>>()?
.into_iter()
.filter_map(|val| {
val.map(|val| if val.is_nan() { None } else { Some(val) })
.flatten()
})
.filter_map(|val| val.and_then(|val| if val.is_nan() { None } else { Some(val) }))
.collect_vec();
match mode {
BatchMode::Sum => Ok(samples.iter().sum()),
@@ -706,17 +691,14 @@ impl VM {
.iter()
.any(|(_net_id, net)| net.borrow().contains(&[source, *id]))
{
device.borrow().get_field(typ).map(|val| Some(val))
device.borrow().get_field(typ).map(Some)
} else {
Ok(None)
}
})
.collect::<Result<Vec<_>, ICError>>()?
.into_iter()
.filter_map(|val| {
val.map(|val| if val.is_nan() { None } else { Some(val) })
.flatten()
})
.filter_map(|val| val.and_then(|val| if val.is_nan() { None } else { Some(val) }))
.collect_vec();
match mode {
BatchMode::Sum => Ok(samples.iter().sum()),
@@ -757,20 +739,14 @@ impl VM {
.iter()
.any(|(_net_id, net)| net.borrow().contains(&[source, *id]))
{
device
.borrow()
.get_slot_field(index, typ)
.map(|val| Some(val))
device.borrow().get_slot_field(index, typ).map(Some)
} else {
Ok(None)
}
})
.collect::<Result<Vec<_>, ICError>>()?
.into_iter()
.filter_map(|val| {
val.map(|val| if val.is_nan() { None } else { Some(val) })
.flatten()
})
.filter_map(|val| val.and_then(|val| if val.is_nan() { None } else { Some(val) }))
.collect_vec();
match mode {
BatchMode::Sum => Ok(samples.iter().sum()),
@@ -809,20 +785,14 @@ impl VM {
.iter()
.any(|(_net_id, net)| net.borrow().contains(&[source, *id]))
{
device
.borrow()
.get_slot_field(index, typ)
.map(|val| Some(val))
device.borrow().get_slot_field(index, typ).map(Some)
} else {
Ok(None)
}
})
.collect::<Result<Vec<_>, ICError>>()?
.into_iter()
.filter_map(|val| {
val.map(|val| if val.is_nan() { None } else { Some(val) })
.flatten()
})
.filter_map(|val| val.and_then(|val| if val.is_nan() { None } else { Some(val) }))
.collect_vec();
match mode {
BatchMode::Sum => Ok(samples.iter().sum()),

View File

@@ -11,7 +11,7 @@ pub struct Random {
}
/// Partial implementation of mscorlib System.Random
/// https://github.com/microsoft/referencesource/blob/master/mscorlib/system/random.cs#L94
/// <https://github.com/microsoft/referencesource/blob/master/mscorlib/system/random.cs#L94>
impl Random {
pub fn new() -> Self {
Self::with_seed(rand::random::<i32>())
@@ -73,8 +73,7 @@ impl Random {
inextp = 1;
}
let mut retval =
self.seed_array[inext as usize].wrapping_sub(self.seed_array[inextp as usize]);
let mut retval = self.seed_array[inext].wrapping_sub(self.seed_array[inextp]);
if retval == i32::MAX {
retval -= 1;
@@ -82,7 +81,7 @@ impl Random {
if retval < 0 {
retval = retval.wrapping_add(i32::MAX);
}
self.seed_array[inext as usize] = retval;
self.seed_array[inext] = retval;
self.inext = inext;
self.inextp = inextp;

View File

@@ -15,49 +15,45 @@ impl<'a> Iterator for SplitConsecutiveWithIndices<'a> {
let tail = &self.haystack[self.start..];
match tail.find(self.chars) {
Some(start) => {
let end = self.start
+ start
+ 'find_end: {
let mut last = start;
for (index, c) in (&tail[start..]).chars().enumerate() {
if !self.chars.contains(&c) {
break 'find_end index;
}
last = index + c.len_utf8();
}
last
};
let start = self.start + start;
if self.start == start {
//consecutive delim matches, skip to next match
let start = end;
let end = match &self.haystack[start..].find(self.chars) {
Some(i) => start + i,
None => self.haystack.len(),
};
let s = &self.haystack[start..end];
self.start = end;
if s.is_empty() {
None
} else {
Some((start, s))
let Some(start) = tail.find(self.chars) else {
let s = &self.haystack[self.start..];
let index = self.start;
self.start = self.haystack.len();
return Some((index, s));
};
let end = self.start
+ start
+ 'find_end: {
let mut last = start;
for (index, c) in tail[start..].chars().enumerate() {
if !self.chars.contains(&c) {
break 'find_end index;
}
} else {
let s = &self.haystack[self.start..start];
let index = self.start;
self.start = start;
Some((index, s))
last = index + c.len_utf8();
}
last
};
let start = self.start + start;
if self.start == start {
//consecutive delim matches, skip to next match
let start = end;
let end = match &self.haystack[start..].find(self.chars) {
Some(i) => start + i,
None => self.haystack.len(),
};
let s = &self.haystack[start..end];
self.start = end;
if s.is_empty() {
None
} else {
Some((start, s))
}
None => {
let s = &self.haystack[self.start..];
let index = self.start;
self.start = self.haystack.len();
Some((index, s))
}
} else {
let s = &self.haystack[self.start..start];
let index = self.start;
self.start = start;
Some((index, s))
}
}
}
@@ -71,7 +67,7 @@ pub trait SplitConsecutiveIndicesExt:
) -> SplitConsecutiveWithIndices<'p> {
SplitConsecutiveWithIndices {
haystack: &self[..],
chars: chars,
chars,
start: 0,
}
}