Labels
This commit is contained in:
parent
51e0db9c7d
commit
c648bf0b24
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -35,6 +35,12 @@ version = "0.5.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
|
@ -101,6 +107,7 @@ name = "hbasm"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ariadne",
|
||||
"bytemuck",
|
||||
"hashbrown 0.14.0",
|
||||
"hbbytecode",
|
||||
"lasso",
|
||||
|
|
|
@ -9,6 +9,7 @@ hbbytecode = { path = "../hbbytecode" }
|
|||
literify = "0.1"
|
||||
paste = "1.0"
|
||||
hashbrown = "0.14.0"
|
||||
bytemuck = "1.13.1"
|
||||
|
||||
[dependencies.lasso]
|
||||
version = "0.7"
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
#![no_std]
|
||||
#![feature(error_in_core)]
|
||||
|
||||
use lasso::Key;
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
pub mod text_r;
|
||||
|
||||
mod macros;
|
||||
|
||||
use {alloc::vec::Vec, hashbrown::HashSet};
|
||||
use {alloc::vec::Vec, hashbrown::HashSet, lasso::Spur};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Assembler {
|
||||
pub buf: Vec<u8>,
|
||||
sub: HashSet<usize>,
|
||||
pub sub: HashSet<usize>,
|
||||
}
|
||||
|
||||
macros::impl_both!(
|
||||
|
@ -53,11 +55,11 @@ macro_rules! impl_imm_le_bytes {
|
|||
impl_imm_le_bytes!(u64, i64, f64);
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct Symbol(pub u64);
|
||||
struct Symbol(pub Spur);
|
||||
impl Imm for Symbol {
|
||||
#[inline(always)]
|
||||
fn insert(&self, asm: &mut Assembler) {
|
||||
asm.sub.insert(asm.buf.len());
|
||||
asm.buf.extend(self.0.to_le_bytes());
|
||||
asm.buf.extend((self.0.into_usize() as u64).to_le_bytes());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@ macro_rules! gen_text {
|
|||
Assembler,
|
||||
macros::text::*,
|
||||
},
|
||||
lasso::{Rodeo, Spur},
|
||||
hashbrown::HashMap,
|
||||
lasso::{Key, Rodeo, Spur},
|
||||
logos::{Lexer, Logos, Span},
|
||||
};
|
||||
|
||||
|
@ -72,75 +73,124 @@ macro_rules! gen_text {
|
|||
}
|
||||
|
||||
pub fn assemble(asm: &mut Assembler, code: &str) -> Result<(), Error> {
|
||||
fn next(lexer: &mut Lexer<Token>) -> Result<Token, ErrorKind> {
|
||||
match lexer.next() {
|
||||
Some(Ok(t)) => Ok(t),
|
||||
Some(Err(())) => Err(ErrorKind::InvalidToken),
|
||||
None => Err(ErrorKind::UnexpectedEnd),
|
||||
}
|
||||
pub struct TextAsm<'a> {
|
||||
asm: &'a mut Assembler,
|
||||
lexer: Lexer<'a, Token>,
|
||||
symloc: HashMap<Spur, usize>,
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn inner(asm: &mut Assembler, lexer: &mut Lexer<Token>) -> Result<(), ErrorKind> {
|
||||
loop {
|
||||
match lexer.next() {
|
||||
Some(Ok(Token::Opcode(op))) => {
|
||||
match op {
|
||||
$(
|
||||
$(hbbytecode::opcode::$opcode)|* => paste::paste!({
|
||||
param_extract_itm!(lexer, $($param_i: $param_ty),*);
|
||||
asm.[<i_param_ $ityn>](op, $($param_i),*);
|
||||
}),
|
||||
)*
|
||||
_ => unreachable!(),
|
||||
impl<'a> TextAsm<'a> {
|
||||
fn next(&mut self) -> Result<Token, ErrorKind> {
|
||||
match self.lexer.next() {
|
||||
Some(Ok(t)) => Ok(t),
|
||||
Some(Err(())) => Err(ErrorKind::InvalidToken),
|
||||
None => Err(ErrorKind::UnexpectedEnd),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn run(&mut self) -> Result<(), ErrorKind> {
|
||||
loop {
|
||||
match self.lexer.next() {
|
||||
Some(Ok(Token::Opcode(op))) => {
|
||||
match op {
|
||||
$(
|
||||
$(hbbytecode::opcode::$opcode)|* => paste::paste!({
|
||||
param_extract_itm!(self, $($param_i: $param_ty),*);
|
||||
self.asm.[<i_param_ $ityn>](op, $($param_i),*);
|
||||
}),
|
||||
)*
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
Some(Ok(Token::Label(lbl))) => {
|
||||
self.symloc.insert(lbl, self.asm.buf.len());
|
||||
}
|
||||
Some(Ok(Token::ISep)) => (),
|
||||
Some(Ok(_)) => return Err(ErrorKind::UnexpectedToken),
|
||||
Some(Err(())) => return Err(ErrorKind::InvalidToken),
|
||||
None => return Ok(()),
|
||||
}
|
||||
Some(Ok(Token::Label(_))) => {
|
||||
todo!("Labels");
|
||||
}
|
||||
Some(Ok(Token::ISep)) => (),
|
||||
Some(Ok(_)) => return Err(ErrorKind::UnexpectedToken),
|
||||
Some(Err(())) => return Err(ErrorKind::InvalidToken),
|
||||
None => return Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut lexer = Token::lexer(code);
|
||||
inner(asm, &mut lexer)
|
||||
.map_err(|kind| Error { kind, span: lexer.span() })
|
||||
let mut asm = TextAsm {
|
||||
asm,
|
||||
lexer: Token::lexer(code),
|
||||
symloc: HashMap::default(),
|
||||
};
|
||||
|
||||
asm.run()
|
||||
.map_err(|kind| Error { kind, span: asm.lexer.span() })?;
|
||||
for &loc in &asm.asm.sub {
|
||||
let val = asm.symloc
|
||||
.get(
|
||||
&Spur::try_from_usize(bytemuck::pod_read_unaligned::<u64>(&asm.asm.buf[loc..loc+core::mem::size_of::<u64>()]) as _)
|
||||
.unwrap()
|
||||
)
|
||||
.ok_or(Error { kind: ErrorKind::InvalidSymbol, span: 0..0 })?
|
||||
.to_le_bytes();
|
||||
|
||||
asm.asm.buf[loc..]
|
||||
.iter_mut()
|
||||
.zip(val)
|
||||
.for_each(|(dst, src)| *dst = src);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
enum InternalImm {
|
||||
Const(u64),
|
||||
Named(Spur),
|
||||
}
|
||||
|
||||
impl $crate::Imm for InternalImm {
|
||||
#[inline]
|
||||
fn insert(&self, asm: &mut Assembler) {
|
||||
match self {
|
||||
Self::Const(a) => a.insert(asm),
|
||||
Self::Named(a) => $crate::Symbol(*a).insert(asm),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! extract_pat {
|
||||
($lexer:expr, $pat:pat) => {
|
||||
let $pat = next($lexer)?
|
||||
else { return Err(ErrorKind::UnexpectedToken) };
|
||||
($self:expr, $pat:pat) => {
|
||||
let $pat = $self.next()?
|
||||
else { return Err(ErrorKind::UnexpectedToken) };
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! extract {
|
||||
($lexer:expr, R, $id:ident) => {
|
||||
extract_pat!($lexer, Token::Register($id));
|
||||
($self:expr, R, $id:ident) => {
|
||||
extract_pat!($self, Token::Register($id));
|
||||
};
|
||||
($lexer:expr, I, $id:ident) => {
|
||||
extract_pat!($lexer, Token::Integer($id));
|
||||
|
||||
($self:expr, I, $id:ident) => {
|
||||
let $id = match $self.next()? {
|
||||
Token::Integer(a) => InternalImm::Const(a),
|
||||
Token::Symbol(a) => InternalImm::Named(a),
|
||||
_ => return Err(ErrorKind::UnexpectedToken),
|
||||
};
|
||||
};
|
||||
($lexer:expr, u16, $id:ident) => {
|
||||
extract_pat!($lexer, Token::Integer($id));
|
||||
let $id = u16::try_from($id)
|
||||
.map_err(|_| ErrorKind::InvalidToken)?;
|
||||
|
||||
($self:expr, u16, $id:ident) => {
|
||||
extract_pat!($self, Token::Integer($id));
|
||||
let $id = u16::try_from($id).map_err(|_| ErrorKind::InvalidToken)?;
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! param_extract_itm {
|
||||
($lexer:expr, $($id:ident: $ty:ident)? $(, $($tt:tt)*)?) => {
|
||||
$(extract!($lexer, $ty, $id);)?
|
||||
($self:expr, $($id:ident: $ty:ident)? $(, $($tt:tt)*)?) => {
|
||||
$(extract!($self, $ty, $id);)?
|
||||
$(
|
||||
extract_pat!($lexer, Token::PSep);
|
||||
param_extract_itm!($lexer, $($tt)*);
|
||||
extract_pat!($self, Token::PSep);
|
||||
param_extract_itm!($self, $($tt)*);
|
||||
)?
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::io::Write;
|
||||
|
||||
use hbasm::Assembler;
|
||||
|
||||
use {
|
||||
|
@ -25,22 +27,28 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||
let message = match e.kind {
|
||||
hbasm::text::ErrorKind::UnexpectedToken => "This token is not expected!",
|
||||
hbasm::text::ErrorKind::InvalidToken => "The token is not valid!",
|
||||
hbasm::text::ErrorKind::UnexpectedEnd => "The assembler reached the end of input unexpectedly!",
|
||||
hbasm::text::ErrorKind::InvalidSymbol => "This referenced symbol doesn't have a corresponding label!",
|
||||
hbasm::text::ErrorKind::UnexpectedEnd => {
|
||||
"The assembler reached the end of input unexpectedly!"
|
||||
}
|
||||
hbasm::text::ErrorKind::InvalidSymbol => {
|
||||
"This referenced symbol doesn't have a corresponding label!"
|
||||
}
|
||||
};
|
||||
let a = colors.next();
|
||||
|
||||
Report::build(ReportKind::Error, "engine_internal", e.span.clone().start)
|
||||
.with_code(e_code)
|
||||
.with_message(format!("{:?}", e.kind))
|
||||
.with_label(
|
||||
Label::new(("engine_internal", e.span.clone()))
|
||||
.with_message(message)
|
||||
.with_color(a),
|
||||
)
|
||||
.finish()
|
||||
.eprint(("engine_internal", Source::from(&code)))
|
||||
.unwrap();
|
||||
.with_code(e_code)
|
||||
.with_message(format!("{:?}", e.kind))
|
||||
.with_label(
|
||||
Label::new(("engine_internal", e.span.clone()))
|
||||
.with_message(message)
|
||||
.with_color(a),
|
||||
)
|
||||
.finish()
|
||||
.eprint(("engine_internal", Source::from(&code)))
|
||||
.unwrap();
|
||||
} else {
|
||||
std::io::stdout().lock().write_all(&assembler.buf).unwrap();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
Loading…
Reference in a new issue