diff options
Diffstat (limited to 'src/parsers/bytecode.rs')
-rw-r--r-- | src/parsers/bytecode.rs | 191 |
1 files changed, 0 insertions, 191 deletions
diff --git a/src/parsers/bytecode.rs b/src/parsers/bytecode.rs deleted file mode 100644 index ed16e22..0000000 --- a/src/parsers/bytecode.rs +++ /dev/null @@ -1,191 +0,0 @@ -use crate::*; - -use std::collections::HashMap; - - -pub struct BytecodeGenerator<'a> { - tokens: &'a [AssembledToken], - addresses: HashMap<String, Tracked<usize>>, - words: Vec<Word>, - errors: Vec<BytecodeError>, -} - -impl<'a> BytecodeGenerator<'a> { - pub fn new(tokens: &'a [AssembledToken]) -> Self { - Self { - tokens, - addresses: HashMap::new(), - words: Vec::new(), - errors: Vec::new(), - } - } - - pub fn generate(mut self) -> Bytecode { - self.calculate_addresses(); - for token in self.tokens { - match token { - AssembledToken::Word(assembled_word) => { - self.assemble_word(assembled_word); - } - AssembledToken::PinnedAddress(pinned) => { - if self.words.len() > pinned.address { - let variant = BytecodeErrorVariant::PinnedAddressBacktrack( - pinned.address, self.words.len()); - let source = pinned.source.clone(); - self.errors.push(BytecodeError { source, variant }); - } else { - self.words.resize(pinned.address, Word { bits: 0, value: 0}); - } - } - AssembledToken::LabelDefinition(_) => (), - AssembledToken::Error(_) => (), - } - } - - return Bytecode { - words: self.words, - errors: self.errors, - } - } - - fn calculate_addresses(&mut self) { - let mut i = 0; - for token in self.tokens { - match token { - AssembledToken::LabelDefinition(definition) => { - let address = Tracked::from(i, definition.source.clone()); - if let Some(_) = self.addresses.insert(definition.name.clone(), address) { - let name = definition.name.clone(); - let variant = BytecodeErrorVariant::DuplicateLabelDefinition(name); - let source = definition.source.clone(); - self.errors.push(BytecodeError { source, variant }); - } - } - AssembledToken::Word(word) => { - i += word.count(); - } - AssembledToken::PinnedAddress(pinned) => { - i = pinned.address; - } - AssembledToken::Error(_) => (), - } - } - } - - fn resolve_expression(&mut self, expr: &AssembledExpression) -> isize { - let mut stack = Vec::new(); - macro_rules! push { - ($value:expr) => { stack.push($value) }; - } - macro_rules! pop { - ($name:ident) => { let $name = match stack.pop() { - Some(value) => value, - None => { - let variant = BytecodeErrorVariant::StackUnderflow; - self.errors.push(BytecodeError { source: expr.source.clone(), variant }); - return 0; - }, - }; }; - } - macro_rules! truth { - ($bool:expr) => { match $bool { true => 1, false => 0 } }; - } - - for token in &expr.tokens { - match &token { - AssembledExpressionToken::Integer(value) => { - push!(value.value) - } - AssembledExpressionToken::LabelReference(name) => { - push!(self.resolve_label_reference(name)) - } - AssembledExpressionToken::Expression(expr) => { - push!(self.resolve_expression(expr)) - } - AssembledExpressionToken::Operator(operator) => match operator { - Operator::Equal => { pop!(b); pop!(a); push!(truth!(a==b)) }, - Operator::NotEqual => { pop!(b); pop!(a); push!(truth!(a!=b)) }, - Operator::LessThan => { pop!(b); pop!(a); push!(truth!(a < b)) }, - Operator::GreaterThan => { pop!(b); pop!(a); push!(truth!(a > b)) }, - Operator::LessThanEqual => { pop!(b); pop!(a); push!(truth!(a <= b)) }, - Operator::GreaterThanEqual => { pop!(b); pop!(a); push!(truth!(a >= b)) }, - Operator::Add => { pop!(b); pop!(a); push!(a + b) }, - Operator::Subtract => { pop!(b); pop!(a); push!(a - b) }, - Operator::LeftShift => { pop!(b); pop!(a); push!(a << b) }, - Operator::RightShift => { pop!(b); pop!(a); push!(a >> b) }, - Operator::And => { pop!(b); pop!(a); push!(a & b) }, - Operator::Or => { pop!(b); pop!(a); push!(a | b) }, - Operator::Xor => { pop!(b); pop!(a); push!(a ^ b) }, - Operator::Not => { pop!(a); push!(!a) }, - } - } - } - - let variant = match stack.len() { - 0 => BytecodeErrorVariant::NoReturnValue, - 1 => return stack[0], - _ => BytecodeErrorVariant::MultipleReturnValues, - }; - self.errors.push(BytecodeError { source: expr.source.clone(), variant}); - 0 - } - - fn resolve_label_reference(&mut self, name: &Tracked<String>) -> isize { - if let Some(address) = self.addresses.get(&name.value) { - address.value as isize - } else { - let variant = BytecodeErrorVariant::DefinitionNotFound(name.value.clone()); - self.errors.push(BytecodeError { source: name.source.clone(), variant }); - 0 - } - } - - fn assemble_word(&mut self, assembled_word: &AssembledWord) { - let mut field_values = Vec::new(); - for field in &assembled_word.fields { - match &field.value { - IntegerArgument::Expression(expr) => { - let source = expr.source.clone(); - let value = self.resolve_expression(expr); - field_values.push(vec![Tracked::from(value, source)]) - } - IntegerArgument::LabelReference(name) => { - let source = name.source.clone(); - let value = self.resolve_label_reference(name); - field_values.push(vec![Tracked::from(value, source)]) - } - IntegerArgument::Integer(integer) => { - let source = integer.source.clone(); - let value = integer.value; - field_values.push(vec![Tracked::from(value, source)]) - } - IntegerArgument::String(string) => { - let values = string.chars.iter() - .map(|c| Tracked::from(c.value as isize, c.source.clone())) - .collect(); - field_values.push(values); - } - }; - } - for i in 0..assembled_word.count() { - let mut value = assembled_word.value; - for (f, field) in assembled_word.fields.iter().enumerate() { - let (field_value, source) = match field_values[f].get(i) { - Some(tracked) => (tracked.value, Some(tracked.source.clone())), - None => (0, None), - }; - let bitcount = match field_value { - 0 => 0, - _ => (field_value.ilog2() + 1) as usize, - }; - if field.bits < bitcount { - let variant = BytecodeErrorVariant::ValueTooLarge(field.bits, bitcount); - self.errors.push(BytecodeError { source: source.unwrap(), variant }); - } else { - value |= (field_value << field.shift) as usize; - } - } - self.words.push(Word { bits: assembled_word.bits, value }); - } - } -} |