gbas 0.1.0

An assembler for Game Boy
Documentation
use backend;
use codebase::CodebaseError;
use diagnostics;
use diagnostics::InternalDiagnostic;
use frontend;
use frontend::{Downstream, Token};
use span;
use std::borrow::BorrowMut;
use std::fmt::Debug;
use std::marker;

pub trait Session {
    type Ident: Into<String> + Debug + PartialEq;
    type Span: span::Span;
    fn analyze_file(&mut self, path: Self::Ident) -> Result<(), CodebaseError>;
    fn invoke_macro(
        &mut self,
        name: (Self::Ident, Self::Span),
        args: MacroArgs<Self::Ident, Self::Span>,
    );
    fn emit_diagnostic(&mut self, diagnostic: InternalDiagnostic<Self::Span>);
    fn emit_item(&mut self, item: backend::Item<Self::Span>);
    fn define_label(&mut self, label: (String, Self::Span));
    fn define_macro(
        &mut self,
        name: (impl Into<Self::Ident>, Self::Span),
        params: Vec<(Self::Ident, Self::Span)>,
        tokens: Vec<(Token<Self::Ident>, Self::Span)>,
    );
    fn set_origin(&mut self, origin: backend::RelocExpr<Self::Span>);
}

pub type MacroArgs<I, S> = Vec<Vec<(Token<I>, S)>>;

pub struct Components<F, B, D, BMF, BMB, BMD>
where
    F: frontend::Frontend,
    B: backend::Backend<F::Span>,
    D: diagnostics::DiagnosticsListener<F::Span>,
    BMF: BorrowMut<F>,
    BMB: BorrowMut<B>,
    BMD: BorrowMut<D>,
{
    frontend: BMF,
    backend: BMB,
    diagnostics: BMD,
    phantom: marker::PhantomData<(F, B, D)>,
}

pub type BorrowedComponents<'a, F, B, D> = Components<F, B, D, &'a mut F, &'a mut B, &'a mut D>;

impl<F, B, D, BMF, BMB, BMD> Components<F, B, D, BMF, BMB, BMD>
where
    F: frontend::Frontend,
    B: backend::Backend<F::Span>,
    D: diagnostics::DiagnosticsListener<F::Span>,
    BMF: BorrowMut<F>,
    BMB: BorrowMut<B>,
    BMD: BorrowMut<D>,
{
    pub fn new(
        frontend: BMF,
        backend: BMB,
        diagnostics: BMD,
    ) -> Components<F, B, D, BMF, BMB, BMD> {
        Components {
            frontend,
            backend,
            diagnostics,
            phantom: marker::PhantomData,
        }
    }

    pub fn build_object(self) -> B::Object
    where
        BMB: Into<B>,
    {
        self.backend.into().into_object()
    }
}

impl<F, B, D, BMF, BMB, BMD> Session for Components<F, B, D, BMF, BMB, BMD>
where
    F: frontend::Frontend,
    B: backend::Backend<F::Span>,
    D: diagnostics::DiagnosticsListener<F::Span>,
    BMF: BorrowMut<F>,
    BMB: BorrowMut<B>,
    BMD: BorrowMut<D>,
{
    type Ident = F::Ident;
    type Span = F::Span;

    fn analyze_file(&mut self, path: Self::Ident) -> Result<(), CodebaseError> {
        self.frontend.borrow_mut().analyze_file(
            path,
            Downstream {
                backend: self.backend.borrow_mut(),
                diagnostics: self.diagnostics.borrow_mut(),
            },
        )
    }

    fn invoke_macro(
        &mut self,
        name: (Self::Ident, Self::Span),
        args: MacroArgs<Self::Ident, Self::Span>,
    ) {
        self.frontend.borrow_mut().invoke_macro(
            name,
            args,
            Downstream {
                backend: self.backend.borrow_mut(),
                diagnostics: self.diagnostics.borrow_mut(),
            },
        )
    }

    fn emit_diagnostic(&mut self, diagnostic: InternalDiagnostic<Self::Span>) {
        self.diagnostics.borrow_mut().emit_diagnostic(diagnostic)
    }

    fn emit_item(&mut self, item: backend::Item<Self::Span>) {
        self.backend.borrow_mut().emit_item(item)
    }

    fn define_label(&mut self, label: (String, Self::Span)) {
        self.backend.borrow_mut().add_label(label)
    }

    fn define_macro(
        &mut self,
        name: (impl Into<Self::Ident>, Self::Span),
        params: Vec<(Self::Ident, Self::Span)>,
        tokens: Vec<(Token<Self::Ident>, Self::Span)>,
    ) {
        self.frontend
            .borrow_mut()
            .define_macro(name, params, tokens)
    }

    fn set_origin(&mut self, origin: backend::RelocExpr<Self::Span>) {
        self.backend.borrow_mut().set_origin(origin)
    }
}