refactor(vm): more ic10 instruction impls
This commit is contained in:
@@ -151,7 +151,7 @@ pub enum ICError {
|
|||||||
#[error("incorrect operand type for instruction `{inst}` operand {index}, not a {desired} ")]
|
#[error("incorrect operand type for instruction `{inst}` operand {index}, not a {desired} ")]
|
||||||
IncorrectOperandType {
|
IncorrectOperandType {
|
||||||
inst: InstructionOp,
|
inst: InstructionOp,
|
||||||
index: u32,
|
index: usize,
|
||||||
desired: String,
|
desired: String,
|
||||||
},
|
},
|
||||||
#[error("unknown identifier {0}")]
|
#[error("unknown identifier {0}")]
|
||||||
@@ -206,6 +206,8 @@ pub enum ICError {
|
|||||||
NoGeneratedValue(String),
|
NoGeneratedValue(String),
|
||||||
#[error("generated Enum {0}'s value does not parse as {1} . Report this error.")]
|
#[error("generated Enum {0}'s value does not parse as {1} . Report this error.")]
|
||||||
BadGeneratedValueParse(String, String),
|
BadGeneratedValueParse(String, String),
|
||||||
|
#[error("IC with id {0} is not sloted into a circuit holder")]
|
||||||
|
NoCircuitHolder(ObjectID),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ICError {
|
impl ICError {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
2262
ic10emu/src/interpreter/instructions.rs
Normal file
2262
ic10emu/src/interpreter/instructions.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -87,6 +87,10 @@ impl VM {
|
|||||||
vm
|
vm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn random_f64(&self) -> f64 {
|
||||||
|
self.random.borrow_mut().next_f64()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_device_from_template(
|
pub fn add_device_from_template(
|
||||||
self: &Rc<Self>,
|
self: &Rc<Self>,
|
||||||
template: ObjectTemplate,
|
template: ObjectTemplate,
|
||||||
|
|||||||
@@ -59,13 +59,55 @@ pub enum Operand {
|
|||||||
Identifier(Identifier),
|
Identifier(Identifier),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Operand {
|
pub struct InstOperand {
|
||||||
pub fn as_value<IC: IntegratedCircuit>(
|
pub operand: Operand,
|
||||||
&self,
|
pub inst: InstructionOp,
|
||||||
ic: &IC,
|
pub index: usize,
|
||||||
inst: InstructionOp,
|
}
|
||||||
index: u32,
|
|
||||||
) -> Result<f64, ICError> {
|
impl InstOperand {
|
||||||
|
pub fn new(operand: &Operand, inst: InstructionOp, index: usize) -> Self {
|
||||||
|
InstOperand {
|
||||||
|
operand: operand.clone(),
|
||||||
|
inst,
|
||||||
|
index,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_ident(&self) -> Result<Identifier, ICError> {
|
||||||
|
let &Operand::Identifier(ident) = &self.operand else {
|
||||||
|
return Err(ICError::IncorrectOperandType {
|
||||||
|
inst: self.inst,
|
||||||
|
index: self.index,
|
||||||
|
desired: "Name".to_owned(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
Ok(ident)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_number(&self) -> Result<Number, ICError> {
|
||||||
|
let &Operand::Number(num) = &self.operand else {
|
||||||
|
return Err(ICError::IncorrectOperandType {
|
||||||
|
inst: self.inst,
|
||||||
|
index: self.index,
|
||||||
|
desired: "Number".to_owned(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
Ok(num)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_aliasable(&self) -> Result<Operand, ICError> {
|
||||||
|
match &self.operand {
|
||||||
|
Operand::RegisterSpec { .. } | Operand::DeviceSpec { .. } => Ok(self.operand.clone()),
|
||||||
|
_ => Err(ICError::IncorrectOperandType {
|
||||||
|
inst: self.inst,
|
||||||
|
index: self.index,
|
||||||
|
desired: "Device Or Register".to_owned(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_value<IC: IntegratedCircuit>(&self, ic: &IC) -> Result<f64, ICError> {
|
||||||
match self.translate_alias(ic) {
|
match self.translate_alias(ic) {
|
||||||
Operand::RegisterSpec(RegisterSpec {
|
Operand::RegisterSpec(RegisterSpec {
|
||||||
indirection,
|
indirection,
|
||||||
@@ -117,8 +159,8 @@ impl Operand {
|
|||||||
}
|
}
|
||||||
Operand::Identifier(id) => Err(ICError::UnknownIdentifier(id.name.to_string())),
|
Operand::Identifier(id) => Err(ICError::UnknownIdentifier(id.name.to_string())),
|
||||||
Operand::DeviceSpec { .. } => Err(ICError::IncorrectOperandType {
|
Operand::DeviceSpec { .. } => Err(ICError::IncorrectOperandType {
|
||||||
inst,
|
inst: self.inst,
|
||||||
index,
|
index: self.index,
|
||||||
desired: "Value".to_owned(),
|
desired: "Value".to_owned(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
@@ -128,16 +170,14 @@ impl Operand {
|
|||||||
&self,
|
&self,
|
||||||
ic: &IC,
|
ic: &IC,
|
||||||
signed: bool,
|
signed: bool,
|
||||||
inst: InstructionOp,
|
|
||||||
index: u32,
|
|
||||||
) -> Result<i64, ICError> {
|
) -> Result<i64, ICError> {
|
||||||
match self {
|
match &self.operand {
|
||||||
Self::Number(num) => Ok(num.value_i64(signed)),
|
Operand::Number(num) => Ok(num.value_i64(signed)),
|
||||||
_ => {
|
_ => {
|
||||||
let val = self.as_value(ic, inst, index)?;
|
let val = self.as_value(ic)?;
|
||||||
if val < -9.223_372_036_854_776E18 {
|
if val < i64::MIN as f64 {
|
||||||
Err(ICError::ShiftUnderflowI64)
|
Err(ICError::ShiftUnderflowI64)
|
||||||
} else if val <= 9.223_372_036_854_776E18 {
|
} else if val <= i64::MAX as f64 {
|
||||||
Ok(interpreter::f64_to_i64(val, signed))
|
Ok(interpreter::f64_to_i64(val, signed))
|
||||||
} else {
|
} else {
|
||||||
Err(ICError::ShiftOverflowI64)
|
Err(ICError::ShiftOverflowI64)
|
||||||
@@ -149,13 +189,11 @@ impl Operand {
|
|||||||
&self,
|
&self,
|
||||||
ic: &IC,
|
ic: &IC,
|
||||||
signed: bool,
|
signed: bool,
|
||||||
inst: InstructionOp,
|
|
||||||
index: u32,
|
|
||||||
) -> Result<i32, ICError> {
|
) -> Result<i32, ICError> {
|
||||||
match self {
|
match &self.operand {
|
||||||
Self::Number(num) => Ok(num.value_i64(signed) as i32),
|
Operand::Number(num) => Ok(num.value_i64(signed) as i32),
|
||||||
_ => {
|
_ => {
|
||||||
let val = self.as_value(ic, inst, index)?;
|
let val = self.as_value(ic)?;
|
||||||
if val < i32::MIN as f64 {
|
if val < i32::MIN as f64 {
|
||||||
Err(ICError::ShiftUnderflowI32)
|
Err(ICError::ShiftUnderflowI32)
|
||||||
} else if val <= i32::MAX as f64 {
|
} else if val <= i32::MAX as f64 {
|
||||||
@@ -167,112 +205,89 @@ impl Operand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_register<IC: IntegratedCircuit>(
|
pub fn as_register<IC: IntegratedCircuit>(&self, ic: &IC) -> Result<RegisterSpec, ICError> {
|
||||||
&self,
|
|
||||||
ic: &IC,
|
|
||||||
inst: InstructionOp,
|
|
||||||
index: u32,
|
|
||||||
) -> Result<RegisterSpec, ICError> {
|
|
||||||
match self.translate_alias(ic) {
|
match self.translate_alias(ic) {
|
||||||
Operand::RegisterSpec(reg) => Ok(reg),
|
Operand::RegisterSpec(reg) => Ok(reg),
|
||||||
Operand::Identifier(id) => Err(ICError::UnknownIdentifier(id.name.to_string())),
|
Operand::Identifier(id) => Err(ICError::UnknownIdentifier(id.name.to_string())),
|
||||||
_ => Err(ICError::IncorrectOperandType {
|
_ => Err(ICError::IncorrectOperandType {
|
||||||
inst,
|
inst: self.inst,
|
||||||
index,
|
index: self.index,
|
||||||
desired: "Register".to_owned(),
|
desired: "Register".to_owned(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// interpret the operand as a device index, i32::MAX is db
|
||||||
pub fn as_device<IC: IntegratedCircuit>(
|
pub fn as_device<IC: IntegratedCircuit>(
|
||||||
&self,
|
&self,
|
||||||
ic: &IC,
|
ic: &IC,
|
||||||
inst: InstructionOp,
|
) -> Result<(i32, Option<usize>), ICError> {
|
||||||
index: u32,
|
|
||||||
) -> Result<(Option<u32>, Option<usize>), ICError> {
|
|
||||||
match self.translate_alias(ic) {
|
match self.translate_alias(ic) {
|
||||||
Operand::DeviceSpec(DeviceSpec { device, connection }) => match device {
|
Operand::DeviceSpec(DeviceSpec { device, connection }) => match device {
|
||||||
Device::Db => Ok((Some(0), connection)),
|
Device::Db => Ok((i32::MAX, connection)),
|
||||||
Device::Numbered(p) => Ok((Some(p), connection)),
|
Device::Numbered(p) => Ok((p as i32, connection)),
|
||||||
Device::Indirect {
|
Device::Indirect {
|
||||||
indirection,
|
indirection,
|
||||||
target,
|
target,
|
||||||
} => {
|
} => {
|
||||||
let val = ic.get_register(indirection, target)?;
|
let val = ic.get_register(indirection, target)?;
|
||||||
Ok((Some(val as u32), connection))
|
Ok((val as i32, connection))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Operand::Identifier(id) => Err(ICError::UnknownIdentifier(id.name.to_string())),
|
Operand::Identifier(id) => Err(ICError::UnknownIdentifier(id.name.to_string())),
|
||||||
_ => Err(ICError::IncorrectOperandType {
|
_ => Err(ICError::IncorrectOperandType {
|
||||||
inst,
|
inst: self.inst,
|
||||||
index,
|
index: self.index,
|
||||||
desired: "Value".to_owned(),
|
desired: "Value".to_owned(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_logic_type<IC: IntegratedCircuit>(
|
pub fn as_logic_type<IC: IntegratedCircuit>(&self, ic: &IC) -> Result<LogicType, ICError> {
|
||||||
&self,
|
match &self.operand {
|
||||||
ic: &IC,
|
|
||||||
inst: InstructionOp,
|
|
||||||
index: u32,
|
|
||||||
) -> Result<LogicType, ICError> {
|
|
||||||
match &self {
|
|
||||||
Operand::Type {
|
Operand::Type {
|
||||||
logic_type: Some(lt),
|
logic_type: Some(lt),
|
||||||
..
|
..
|
||||||
} => Ok(*lt),
|
} => Ok(*lt),
|
||||||
_ => LogicType::try_from(self.as_value(ic, inst, index)?),
|
_ => LogicType::try_from(self.as_value(ic)?),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_slot_logic_type<IC: IntegratedCircuit>(
|
pub fn as_slot_logic_type<IC: IntegratedCircuit>(
|
||||||
&self,
|
&self,
|
||||||
ic: &IC,
|
ic: &IC,
|
||||||
inst: InstructionOp,
|
|
||||||
index: u32,
|
|
||||||
) -> Result<LogicSlotType, ICError> {
|
) -> Result<LogicSlotType, ICError> {
|
||||||
match &self {
|
match &self.operand {
|
||||||
Operand::Type {
|
Operand::Type {
|
||||||
slot_logic_type: Some(slt),
|
slot_logic_type: Some(slt),
|
||||||
..
|
..
|
||||||
} => Ok(*slt),
|
} => Ok(*slt),
|
||||||
_ => LogicSlotType::try_from(self.as_value(ic, inst, index)?),
|
_ => LogicSlotType::try_from(self.as_value(ic)?),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_batch_mode<IC: IntegratedCircuit>(
|
pub fn as_batch_mode<IC: IntegratedCircuit>(&self, ic: &IC) -> Result<BatchMode, ICError> {
|
||||||
&self,
|
match &self.operand {
|
||||||
ic: &IC,
|
|
||||||
inst: InstructionOp,
|
|
||||||
index: u32,
|
|
||||||
) -> Result<BatchMode, ICError> {
|
|
||||||
match &self {
|
|
||||||
Operand::Type {
|
Operand::Type {
|
||||||
batch_mode: Some(bm),
|
batch_mode: Some(bm),
|
||||||
..
|
..
|
||||||
} => Ok(*bm),
|
} => Ok(*bm),
|
||||||
_ => BatchMode::try_from(self.as_value(ic, inst, index)?),
|
_ => BatchMode::try_from(self.as_value(ic)?),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_reagent_mode<IC: IntegratedCircuit>(
|
pub fn as_reagent_mode<IC: IntegratedCircuit>(&self, ic: &IC) -> Result<ReagentMode, ICError> {
|
||||||
&self,
|
match &self.operand {
|
||||||
ic: &IC,
|
|
||||||
inst: InstructionOp,
|
|
||||||
index: u32,
|
|
||||||
) -> Result<ReagentMode, ICError> {
|
|
||||||
match &self {
|
|
||||||
Operand::Type {
|
Operand::Type {
|
||||||
reagent_mode: Some(rm),
|
reagent_mode: Some(rm),
|
||||||
..
|
..
|
||||||
} => Ok(*rm),
|
} => Ok(*rm),
|
||||||
_ => ReagentMode::try_from(self.as_value(ic, inst, index)?),
|
_ => ReagentMode::try_from(self.as_value(ic)?),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn translate_alias<IC: IntegratedCircuit>(&self, ic: &IC) -> Self {
|
pub fn translate_alias<IC: IntegratedCircuit>(&self, ic: &IC) -> Operand {
|
||||||
match &self {
|
match self.operand {
|
||||||
Operand::Identifier(id) | Operand::Type { identifier: id, .. } => {
|
Operand::Identifier(id) | Operand::Type { identifier: id, .. } => {
|
||||||
if let Some(alias) = ic.get_aliases().get(&id.name) {
|
if let Some(alias) = ic.get_aliases().get(&id.name) {
|
||||||
alias.clone()
|
alias.clone()
|
||||||
@@ -281,7 +296,7 @@ impl Operand {
|
|||||||
} else if let Some(label) = ic.get_labels().get(&id.name) {
|
} else if let Some(label) = ic.get_labels().get(&id.name) {
|
||||||
Operand::Number(Number::Float(*label as f64))
|
Operand::Number(Number::Float(*label as f64))
|
||||||
} else {
|
} else {
|
||||||
self.clone()
|
self.operand.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => self.clone(),
|
_ => self.clone(),
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,8 @@ pub enum MemoryError {
|
|||||||
StackUnderflow(i32, usize),
|
StackUnderflow(i32, usize),
|
||||||
#[error("stack overflow: {0} > range [0..{1})")]
|
#[error("stack overflow: {0} > range [0..{1})")]
|
||||||
StackOverflow(i32, usize),
|
StackOverflow(i32, usize),
|
||||||
#[error("memory unit not present")]
|
#[error("memory not readable")]
|
||||||
NotPresent,
|
NotReadable,
|
||||||
|
#[error("memory not writeable")]
|
||||||
|
NotWriteable,
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -15,10 +15,9 @@ use crate::{
|
|||||||
macros::tag_object_traits,
|
macros::tag_object_traits,
|
||||||
ObjectID, Slot,
|
ObjectID, Slot,
|
||||||
},
|
},
|
||||||
VM,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use std::{collections::BTreeMap, fmt::Debug, rc::Rc};
|
use std::{collections::BTreeMap, fmt::Debug};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||||
pub struct ParentSlotInfo {
|
pub struct ParentSlotInfo {
|
||||||
@@ -63,7 +62,7 @@ tag_object_traits! {
|
|||||||
fn set_logic(&mut self, lt: LogicType, value: f64, force: bool) -> Result<(), LogicError>;
|
fn set_logic(&mut self, lt: LogicType, value: f64, force: bool) -> Result<(), LogicError>;
|
||||||
fn get_logic(&self, lt: LogicType) -> Result<f64, LogicError>;
|
fn get_logic(&self, lt: LogicType) -> Result<f64, LogicError>;
|
||||||
fn can_slot_logic_read(&self, slt: LogicSlotType, index: f64) -> bool;
|
fn can_slot_logic_read(&self, slt: LogicSlotType, index: f64) -> bool;
|
||||||
fn get_slot_logic(&self, slt: LogicSlotType, index: f64, vm: &VM) -> Result<f64, LogicError>;
|
fn get_slot_logic(&self, slt: LogicSlotType, index: f64) -> Result<f64, LogicError>;
|
||||||
fn valid_logic_types(&self) -> Vec<LogicType>;
|
fn valid_logic_types(&self) -> Vec<LogicType>;
|
||||||
fn known_modes(&self) -> Option<Vec<(u32, String)>>;
|
fn known_modes(&self) -> Option<Vec<(u32, String)>>;
|
||||||
}
|
}
|
||||||
@@ -78,10 +77,28 @@ tag_object_traits! {
|
|||||||
pub trait CircuitHolder: Logicable + Storage {
|
pub trait CircuitHolder: Logicable + Storage {
|
||||||
fn clear_error(&mut self);
|
fn clear_error(&mut self);
|
||||||
fn set_error(&mut self, state: i32);
|
fn set_error(&mut self, state: i32);
|
||||||
fn get_logicable_from_index(&self, device: usize, vm: &VM) -> Option<LogicableRef>;
|
/// i32::MAX is db
|
||||||
fn get_logicable_from_index_mut(&self, device: usize, vm: &VM) -> Option<LogicableRefMut>;
|
fn get_logicable_from_index(
|
||||||
fn get_logicable_from_id(&self, device: ObjectID, vm: &VM) -> Option<LogicableRef>;
|
&self,
|
||||||
fn get_logicable_from_id_mut(&self, device: ObjectID, vm: &VM) -> Option<LogicableRefMut>;
|
device: i32,
|
||||||
|
connection: Option<usize>,
|
||||||
|
) -> Option<LogicableRef>;
|
||||||
|
/// i32::MAX is db
|
||||||
|
fn get_logicable_from_index_mut(
|
||||||
|
&self,
|
||||||
|
device: i32,
|
||||||
|
connection: Option<usize>,
|
||||||
|
) -> Option<LogicableRefMut>;
|
||||||
|
fn get_logicable_from_id(
|
||||||
|
&self,
|
||||||
|
device: ObjectID,
|
||||||
|
connection: Option<usize>,
|
||||||
|
) -> Option<LogicableRef>;
|
||||||
|
fn get_logicable_from_id_mut(
|
||||||
|
&self,
|
||||||
|
device: ObjectID,
|
||||||
|
connection: Option<usize>,
|
||||||
|
) -> Option<LogicableRefMut>;
|
||||||
fn get_source_code(&self) -> String;
|
fn get_source_code(&self) -> String;
|
||||||
fn set_source_code(&self, code: String);
|
fn set_source_code(&self, code: String);
|
||||||
fn get_batch(&self) -> Vec<LogicableRef>;
|
fn get_batch(&self) -> Vec<LogicableRef>;
|
||||||
@@ -102,7 +119,7 @@ tag_object_traits! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait IntegratedCircuit: Logicable + MemoryWritable + SourceCode + Item {
|
pub trait IntegratedCircuit: Logicable + MemoryWritable + SourceCode + Item {
|
||||||
fn get_circuit_holder(&self, vm: &Rc<VM>) -> Option<CircuitHolderRef>;
|
fn get_circuit_holder(&self) -> Option<CircuitHolderRef>;
|
||||||
fn get_instruction_pointer(&self) -> f64;
|
fn get_instruction_pointer(&self) -> f64;
|
||||||
fn set_next_instruction(&mut self, next_instruction: f64);
|
fn set_next_instruction(&mut self, next_instruction: f64);
|
||||||
fn set_next_instruction_relative(&mut self, offset: f64) {
|
fn set_next_instruction_relative(&mut self, offset: f64) {
|
||||||
@@ -122,7 +139,9 @@ tag_object_traits! {
|
|||||||
fn get_stack(&self, addr: f64) -> Result<f64, ICError>;
|
fn get_stack(&self, addr: f64) -> Result<f64, ICError>;
|
||||||
fn put_stack(&self, addr: f64, val: f64) -> Result<f64, ICError>;
|
fn put_stack(&self, addr: f64, val: f64) -> Result<f64, ICError>;
|
||||||
fn get_aliases(&self) -> &BTreeMap<String, crate::vm::instructions::operands::Operand>;
|
fn get_aliases(&self) -> &BTreeMap<String, crate::vm::instructions::operands::Operand>;
|
||||||
|
fn get_aliases_mut(&mut self) -> &mut BTreeMap<String, crate::vm::instructions::operands::Operand>;
|
||||||
fn get_defines(&self) -> &BTreeMap<String, f64>;
|
fn get_defines(&self) -> &BTreeMap<String, f64>;
|
||||||
|
fn get_defines_mut(&mut self) -> &mut BTreeMap<String, f64>;
|
||||||
fn get_labels(&self) -> &BTreeMap<String, u32>;
|
fn get_labels(&self) -> &BTreeMap<String, u32>;
|
||||||
fn get_state(&self) -> ICState;
|
fn get_state(&self) -> ICState;
|
||||||
fn set_state(&mut self, state: ICState);
|
fn set_state(&mut self, state: ICState);
|
||||||
@@ -131,7 +150,7 @@ tag_object_traits! {
|
|||||||
pub trait Programmable: ICInstructable {
|
pub trait Programmable: ICInstructable {
|
||||||
fn get_source_code(&self) -> String;
|
fn get_source_code(&self) -> String;
|
||||||
fn set_source_code(&self, code: String);
|
fn set_source_code(&self, code: String);
|
||||||
fn step(&mut self, vm: &VM, advance_ip_on_err: bool) -> Result<(), crate::errors::ICError>;
|
fn step(&mut self, advance_ip_on_err: bool) -> Result<(), crate::errors::ICError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Instructable: MemoryWritable {
|
pub trait Instructable: MemoryWritable {
|
||||||
@@ -149,8 +168,7 @@ tag_object_traits! {
|
|||||||
slt: LogicSlotType,
|
slt: LogicSlotType,
|
||||||
index: f64,
|
index: f64,
|
||||||
value: f64,
|
value: f64,
|
||||||
vm: &VM,
|
force: bool,
|
||||||
force: bool
|
|
||||||
) -> Result<(), LogicError>;
|
) -> Result<(), LogicError>;
|
||||||
fn connection_list(&self) -> &[Connection];
|
fn connection_list(&self) -> &[Connection];
|
||||||
fn connection_list_mut(&mut self) -> &mut [Connection];
|
fn connection_list_mut(&mut self) -> &mut [Connection];
|
||||||
@@ -166,13 +184,9 @@ tag_object_traits! {
|
|||||||
fn has_reagents(&self) -> bool;
|
fn has_reagents(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait WirelessTransmit: Logicable {
|
pub trait WirelessTransmit: Logicable {}
|
||||||
|
|
||||||
}
|
pub trait WirelessReceive: Logicable {}
|
||||||
|
|
||||||
pub trait WirelessReceive: Logicable {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Network: Logicable {
|
pub trait Network: Logicable {
|
||||||
fn contains(&self, id: &ObjectID) -> bool;
|
fn contains(&self, id: &ObjectID) -> bool;
|
||||||
@@ -192,7 +206,6 @@ tag_object_traits! {
|
|||||||
fn get_channel_data(&self) -> &[f64; 8];
|
fn get_channel_data(&self) -> &[f64; 8];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for dyn Object {
|
impl Debug for dyn Object {
|
||||||
|
|||||||
@@ -133,7 +133,8 @@ fn write_instruction_trait<T: std::io::Write>(
|
|||||||
instruction: (&str, &stationpedia::Command),
|
instruction: (&str, &stationpedia::Command),
|
||||||
) -> color_eyre::Result<()> {
|
) -> color_eyre::Result<()> {
|
||||||
let (name, info) = instruction;
|
let (name, info) = instruction;
|
||||||
let trait_name = format!("{}Instruction", name.to_case(Case::Pascal));
|
let op_name = name.to_case(Case::Pascal);
|
||||||
|
let trait_name = format!("{op_name}Instruction");
|
||||||
let operands = operand_names(&info.example)
|
let operands = operand_names(&info.example)
|
||||||
.iter()
|
.iter()
|
||||||
.map(|name| {
|
.map(|name| {
|
||||||
@@ -148,12 +149,45 @@ fn write_instruction_trait<T: std::io::Write>(
|
|||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
let operands_inner = operand_names(&info.example)
|
||||||
|
.iter()
|
||||||
|
.map(|name| {
|
||||||
|
let mut n: &str = name;
|
||||||
|
if n == "str" {
|
||||||
|
n = "string";
|
||||||
|
}
|
||||||
|
format!(
|
||||||
|
"{}: &crate::vm::instructions::operands::InstOperand",
|
||||||
|
n.to_case(Case::Snake)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ");
|
||||||
|
let operand_call = operand_names(&info.example)
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, name)| {
|
||||||
|
let mut n: &str = name;
|
||||||
|
if n == "str" {
|
||||||
|
n = "string";
|
||||||
|
}
|
||||||
|
format!(
|
||||||
|
"&crate::vm::instructions::operands::InstOperand::new({}, InstructionOp::{op_name}, {index})",
|
||||||
|
n.to_case(Case::Snake)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ");
|
||||||
let example = utils::strip_color(&info.example);
|
let example = utils::strip_color(&info.example);
|
||||||
write!(
|
write!(
|
||||||
writer,
|
writer,
|
||||||
"pub trait {trait_name}: IntegratedCircuit {{\n \
|
"pub trait {trait_name}: IntegratedCircuit {{\n \
|
||||||
/// {example} \n \
|
/// {example} \n \
|
||||||
fn execute_{name}(&mut self, {operands}) -> Result<(), crate::errors::ICError>;\n\
|
fn execute_{name}(&mut self, {operands}) -> Result<(), crate::errors::ICError> {{\n \
|
||||||
|
{trait_name}::execute_inner(self, {operand_call})\n \
|
||||||
|
}}\n \
|
||||||
|
/// {example} \n \
|
||||||
|
fn execute_inner(&mut self, {operands_inner}) -> Result<(), crate::errors::ICError>;\n\
|
||||||
}}"
|
}}"
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -176,6 +210,7 @@ fn write_instruction_trait_use<T: std::io::Write>(writer: &mut T) -> color_eyre:
|
|||||||
writer,
|
writer,
|
||||||
"\
|
"\
|
||||||
use crate::vm::object::traits::IntegratedCircuit;\n\
|
use crate::vm::object::traits::IntegratedCircuit;\n\
|
||||||
|
use crate::vm::instructions::enums::InstructionOp;\n\
|
||||||
"
|
"
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user