Merge pull request #4 from Emilgardis/fixes
Some small changes and fixes
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
@@ -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()),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user