summaryrefslogtreecommitdiff
path: root/src/tokens/assembler.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tokens/assembler.rs')
-rw-r--r--src/tokens/assembler.rs140
1 files changed, 140 insertions, 0 deletions
diff --git a/src/tokens/assembler.rs b/src/tokens/assembler.rs
new file mode 100644
index 0000000..04ecd38
--- /dev/null
+++ b/src/tokens/assembler.rs
@@ -0,0 +1,140 @@
+use crate::*;
+
+
+#[derive(Clone)]
+pub enum AssembledToken {
+ Word(AssembledWord),
+ LabelDefinition(LabelDefinition),
+ PinnedAddress(PinnedAddress),
+ Error(AssemblerError),
+}
+
+#[derive(Clone)]
+pub struct AssembledWord {
+ pub source: SourceSpan,
+ pub value: usize,
+ pub bits: usize,
+ pub fields: Vec<AssembledField>,
+ pub errors: Vec<AssemblerError>,
+}
+
+#[derive(Clone)]
+pub struct AssembledField {
+ pub source: SourceSpan,
+ pub value: IntegerArgument,
+ /// Length of field in bits
+ pub bits: usize,
+ /// Distance to left-shift field in value
+ pub shift: usize,
+}
+
+#[derive(Clone)]
+pub struct AssembledExpression {
+ pub source: SourceSpan,
+ pub tokens: Vec<AssembledExpressionToken>,
+}
+
+#[derive(Clone)]
+pub enum AssembledExpressionToken {
+ Integer(TrackedInteger),
+ LabelReference(Tracked<String>),
+ Operator(Operator),
+ Expression(Box<AssembledExpression>),
+}
+
+#[derive(Clone)]
+pub enum Argument {
+ Integer(IntegerArgument),
+ Block(Vec<AssembledToken>),
+}
+
+#[derive(Clone)]
+pub enum IntegerArgument {
+ LabelReference(Tracked<String>),
+ Integer(TrackedInteger),
+ Expression(AssembledExpression),
+}
+
+#[derive(Clone)]
+pub struct AssemblerError {
+ pub source: SourceSpan,
+ pub variant: AssemblerErrorVariant,
+}
+
+#[derive(Clone, Debug)]
+pub enum AssemblerErrorVariant {
+ DefinitionNotFound(String),
+ NotAnInteger,
+ NotABlock,
+ IntegerInBlock,
+ /// expected, received
+ IncorrectArgumentCount(usize, usize),
+ /// expected, received, index
+ IncorrectArgumentType(ArgumentVariant, ArgumentVariant),
+}
+
+// ------------------------------------------------------------------------ //
+
+macro_rules! indent {
+ ($indent:expr => $($tokens:tt)*) => {{
+ for _ in 0..$indent { print!(" "); }
+ println!($($tokens)*);
+ }};
+}
+
+pub fn print_assembled_tokens(tokens: &[AssembledToken]) {
+ println!();
+ println!("--------------------------------------------------------------");
+ println!();
+ for token in tokens {
+ match token {
+ AssembledToken::LabelDefinition(definition) => {
+ println!("LABEL {}", definition.name)
+ }
+ AssembledToken::PinnedAddress(address) => {
+ println!("PINNED {}", address.address)
+ }
+ AssembledToken::Word(word) => {
+ println!("WORD {:b}", word.value);
+ for field in &word.fields {
+ print!(" FIELD ({} << {}) ", field.bits, field.shift);
+ match &field.value {
+ IntegerArgument::LabelReference(name) => {
+ println!("LABEL '{name}'");
+ }
+ IntegerArgument::Integer(integer) => {
+ println!("INTEGER '{}'", integer.value);
+ }
+ IntegerArgument::Expression(expr) => {
+ println!("EXPRESSION");
+ print_assembled_expression(2, expr);
+ }
+ }
+ }
+ }
+ AssembledToken::Error(error) => {
+ println!("ERROR {:?}", error.variant)
+ }
+ }
+ }
+}
+
+fn print_assembled_expression(indent: usize, expr: &AssembledExpression) {
+ for token in &expr.tokens {
+ match token {
+ AssembledExpressionToken::Integer(integer) => {
+ indent!(indent => "INTEGER {}", integer.value)
+ }
+ AssembledExpressionToken::LabelReference(name) => {
+ indent!(indent => "LABEL '{name}'")
+ }
+ AssembledExpressionToken::Operator(operator) => {
+ indent!(indent => "OPERATOR {operator:?}")
+ }
+ AssembledExpressionToken::Expression(expr) => {
+ indent!(indent => "EXPRESSION");
+ print_assembled_expression(indent+1, expr);
+ }
+ }
+ }
+}