1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use std::fmt::Display;

use crate::{
    interface::parser::{ParserInstSet, ParserResult},
    types::middleware_types::AssemblerConfig,
};

pub trait Assembler<IS>: Send + Sync
where
    IS: ParserInstSet + InstructionSetTrait,
{
    fn assemble(&mut self, ast: ParserResult<IS>)
        -> Result<AssembleResult<IS>, Vec<AssemblyError>>;
    fn update_config(&mut self, config: &AssemblerConfig);
    fn dump(&mut self, ast: ParserResult<IS>) -> Result<Memory, Vec<AssemblyError>>;
}

pub trait InstructionSetTrait {
    type Register: Clone;
    type Immediate: Clone;
}

#[derive(Clone)]
pub struct AssembleResult<IS: ParserInstSet + InstructionSetTrait> {
    pub data: Vec<u8>,
    pub instruction: Vec<InstructionSet<IS>>,
}

#[derive(Clone)]
pub struct InstructionSet<IS: ParserInstSet + InstructionSetTrait> {
    pub line_number: u64,
    pub instruction: Instruction<IS>,
    pub address: u32,
    pub code: u32,
    pub basic: String,
}

#[derive(Clone)]
pub struct Instruction<IS: ParserInstSet + InstructionSetTrait> {
    pub operation: IS::Operator,
    pub operands: Vec<Operand<IS>>,
}

#[allow(type_alias_bounds)]
pub type Operand<IS: ParserInstSet + InstructionSetTrait> = IS::Immediate;

pub struct Memory {
    pub data: String,
    pub text: String,
}

#[derive(Debug)]
pub struct AssemblyError {
    pub line: usize,
    pub msg: String,
}

impl Display for AssemblyError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "line:{} {}", self.line, self.msg)
    }
}

impl<IS: ParserInstSet + InstructionSetTrait> Instruction<IS> {
    pub fn new(operation: IS::Operator) -> Self {
        Instruction {
            operation,
            operands: vec![],
        }
    }
}

impl<IS: ParserInstSet + InstructionSetTrait> InstructionSet<IS> {
    pub fn new(instruction: Instruction<IS>) -> Self {
        InstructionSet {
            line_number: 0,
            instruction,
            address: 0,
            code: 0,
            basic: String::new(),
        }
    }
}