summaryrefslogtreecommitdiff
path: root/src/parsers/bytecode.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/parsers/bytecode.rs')
-rw-r--r--src/parsers/bytecode.rs191
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 });
- }
- }
-}