use std::borrow::{Borrow, Cow};
use std::collections::HashMap;
use std::fmt::Display;
use std::ops::Deref;
use std::sync::Arc;
use cpclib_common::itertools::Itertools;
#[cfg(all(not(target_arch = "wasm32"), feature = "rayon"))]
use cpclib_common::rayon::prelude::*;
use cpclib_common::smallvec::SmallVec;
use cpclib_common::winnow::combinator::cut_err;
use cpclib_common::winnow::error::ErrMode;
use cpclib_common::winnow::stream::{AsBStr, AsBytes, Offset, Stream, UpdateSlice};
use cpclib_common::winnow::token::take;
use cpclib_common::winnow::{BStr, PResult, Parser};
use cpclib_sna::{FlagValue, SnapshotFlag, SnapshotVersion};
use cpclib_tokens::ordered_float::OrderedFloat;
use cpclib_tokens::{
data_access_impl_most_methods, data_access_is_any_indexregister16,
data_access_is_any_indexregister8, data_access_is_any_register16, data_access_is_any_register8,
AssemblerControlCommand, AssemblerFlavor, BaseListing, BinaryFunction, BinaryOperation,
CharsetFormat, CrunchType, DataAccess, DataAccessElem, Expr, ExprResult, FlagTest,
FormattedExpr, IndexRegister16, IndexRegister8, LabelPrefix, ListingElement, MacroParam,
MacroParamElement, Mnemonic, Register16, Register8, SaveType, StableTickerAction, TestKind,
TestKindElement, ToSimpleToken, Token, UnaryFunction, UnaryOperation, UnaryTokenOperation
};
use ouroboros::self_referencing;
use super::{
build_span, my_many0_nocollect, parse_lines, parse_single_token, parse_z80_line_complete,
InnerZ80Span, ParserContext, SourceString, Z80ParserError, Z80Span
};
use crate::assembler::Env;
use crate::error::AssemblerError;
use crate::error::ExpressionError;
use crate::implementation::expression::ExprEvaluationExt;
use crate::implementation::listing::ListingExt;
use crate::implementation::tokens::TokenExt;
use crate::preamble::parse_z80_str;
use crate::{
ensure_orgams_type, resolve_impl, BinaryTransformation, ExprElement, ParserContextBuilder,
ParsingState, SymbolFor
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LocatedExpr {
RelativeDelta(i8, Z80Span),
Value(i32, Z80Span),
Float(OrderedFloat<f64>, Z80Span),
Char(char, Z80Span),
Bool(bool, Z80Span),
String(UnescapedString),
Label(Z80Span),
List(Vec<LocatedExpr>, Z80Span),
PrefixedLabel(LabelPrefix, Z80Span, Z80Span),
Paren(Box<LocatedExpr>, Z80Span),
UnaryFunction(UnaryFunction, Box<LocatedExpr>, Z80Span),
UnaryOperation(UnaryOperation, Box<LocatedExpr>, Z80Span),
UnaryTokenOperation(UnaryTokenOperation, Box<LocatedToken>, Z80Span),
BinaryFunction(BinaryFunction, Box<LocatedExpr>, Box<LocatedExpr>, Z80Span),
BinaryOperation(BinaryOperation, Box<LocatedExpr>, Box<LocatedExpr>, Z80Span),
AnyFunction(Z80Span, Vec<LocatedExpr>, Z80Span),
Rnd(Z80Span)
}
impl std::fmt::Display for LocatedExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.span())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UnescapedString(pub(crate) String, pub(crate) Z80Span);
impl AsRef<str> for UnescapedString {
fn as_ref(&self) -> &str {
self.0.as_str()
}
}
impl Display for UnescapedString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_ref())
}
}
impl SourceString for &UnescapedString {
fn as_str(&self) -> &str {
self.as_ref()
}
}
impl ExprElement for LocatedExpr {
type ResultExpr = Expr;
type Token = LocatedToken;
fn to_expr(&self) -> Cow<Expr> {
let expr = match self {
LocatedExpr::RelativeDelta(d, _) => Expr::RelativeDelta(*d),
LocatedExpr::Value(v, _) => Expr::Value(*v),
LocatedExpr::Float(f, _) => Expr::Float(*f),
LocatedExpr::Char(c, _) => Expr::Char(*c),
LocatedExpr::Bool(b, _) => Expr::Bool(*b),
LocatedExpr::String(s) => Expr::String(s.as_ref().into()),
LocatedExpr::Label(l) => Expr::Label(l.into()),
LocatedExpr::List(l, _) => {
Expr::List(l.iter().map(|e| e.to_expr().into_owned()).collect_vec())
},
LocatedExpr::PrefixedLabel(p, l, _) => Expr::PrefixedLabel(*p, l.into()),
LocatedExpr::Paren(box p, _) => Expr::Paren(Box::new(p.to_expr().into_owned())),
LocatedExpr::UnaryFunction(f, box e, _) => {
Expr::UnaryFunction(*f, Box::new(e.to_expr().into_owned()))
},
LocatedExpr::UnaryOperation(o, box e, _) => {
Expr::UnaryOperation(*o, Box::new(e.to_expr().into_owned()))
},
LocatedExpr::UnaryTokenOperation(o, box t, _) => {
Expr::UnaryTokenOperation(*o, Box::new(t.to_token().into_owned()))
},
LocatedExpr::BinaryFunction(f, box e1, box e2, _) => {
Expr::BinaryFunction(
*f,
Box::new(e1.to_expr().into_owned()),
Box::new(e2.to_expr().into_owned())
)
},
LocatedExpr::BinaryOperation(o, box e1, box e2, _) => {
Expr::BinaryOperation(
*o,
Box::new(e1.to_expr().into_owned()),
Box::new(e2.to_expr().into_owned())
)
},
LocatedExpr::AnyFunction(n, a, _) => {
Expr::AnyFunction(
n.into(),
a.iter().map(|e| e.to_expr().into_owned()).collect_vec()
)
},
LocatedExpr::Rnd(_) => Expr::Rnd
};
Cow::Owned(expr)
}
fn is_negated(&self) -> bool {
match self {
Self::UnaryOperation(UnaryOperation::Neg, ..) => true,
_ => false
}
}
fn is_relative(&self) -> bool {
match self {
Self::RelativeDelta(..) => true,
_ => false
}
}
fn relative_delta(&self) -> i8 {
match self {
Self::RelativeDelta(val, _) => *val,
_ => unreachable!()
}
}
fn neg(&self) -> Self::ResultExpr {
Expr::UnaryOperation(UnaryOperation::Neg, Box::new(self.to_expr().into_owned()))
}
fn add<E: Into<Expr>>(&self, v: E) -> Self::ResultExpr {
Self::ResultExpr::BinaryOperation(
BinaryOperation::Add,
Box::new(self.to_expr().into_owned()),
v.into().into()
)
}
fn is_context_independant(&self) -> bool {
match self {
Self::Label(..) => false,
_ => true
}
}
fn fix_relative_value(&mut self) {
if let Self::Value(val, span) = self {
let mut new_expr = Self::RelativeDelta(*val as i8, span.clone());
std::mem::swap(self, &mut new_expr);
}
}
fn not(&self) -> Self::ResultExpr {
todo!()
}
fn is_value(&self) -> bool {
match self {
Self::Value(..) => true,
_ => false
}
}
fn value(&self) -> i32 {
match self {
Self::Value(v, _) => *v,
_ => unreachable!()
}
}
fn is_char(&self) -> bool {
match self {
Self::Char(..) => true,
_ => false
}
}
fn char(&self) -> char {
match self {
Self::Char(v, _) => *v,
_ => unreachable!()
}
}
fn is_bool(&self) -> bool {
match self {
Self::Bool(..) => true,
_ => false
}
}
fn bool(&self) -> bool {
match self {
Self::Bool(v, _) => *v,
_ => unreachable!()
}
}
fn is_string(&self) -> bool {
match self {
Self::String(..) => true,
_ => false
}
}
fn string(&self) -> &str {
match self {
Self::String(v) => &v.0,
_ => unreachable!()
}
}
fn is_float(&self) -> bool {
match self {
Self::Float(..) => true,
_ => false
}
}
fn float(&self) -> OrderedFloat<f64> {
match self {
Self::Float(v, _) => *v,
_ => unreachable!()
}
}
fn is_list(&self) -> bool {
match self {
Self::List(..) => true,
_ => false
}
}
fn list(&self) -> &[Self] {
match self {
Self::List(v, _) => v.as_slice(),
_ => unreachable!()
}
}
fn is_label(&self) -> bool {
match self {
Self::Label(..) => true,
_ => false
}
}
fn label(&self) -> &str {
match self {
Self::Label(v) => v.as_str(),
Self::PrefixedLabel(_, v, _) => v.as_str(),
_ => unreachable!()
}
}
fn is_token_operation(&self) -> bool {
match self {
Self::UnaryTokenOperation(..) => true,
_ => false
}
}
fn token_operation(&self) -> &UnaryTokenOperation {
match self {
Self::UnaryTokenOperation(op, __, _) => op,
_ => unreachable!()
}
}
fn token(&self) -> &Self::Token {
match self {
Self::UnaryTokenOperation(_, box token, _) => token,
_ => unreachable!()
}
}
fn is_prefix_label(&self) -> bool {
match self {
Self::PrefixedLabel(..) => true,
_ => false
}
}
fn prefix(&self) -> &LabelPrefix {
match self {
Self::PrefixedLabel(prefix, ..) => prefix,
_ => unreachable!()
}
}
fn is_binary_operation(&self) -> bool {
match self {
Self::BinaryOperation(..) => true,
_ => false
}
}
fn binary_operation(&self) -> BinaryOperation {
match self {
Self::BinaryOperation(op, ..) => *op,
_ => unreachable!()
}
}
fn is_unary_operation(&self) -> bool {
match self {
Self::UnaryOperation(..) => true,
_ => false
}
}
fn unary_operation(&self) -> UnaryOperation {
match self {
Self::UnaryOperation(op, ..) => *op,
_ => unreachable!()
}
}
fn is_unary_function(&self) -> bool {
match self {
Self::UnaryFunction(..) => true,
_ => false
}
}
fn unary_function(&self) -> UnaryFunction {
match self {
Self::UnaryFunction(f, ..) => *f,
_ => unreachable!()
}
}
fn is_binary_function(&self) -> bool {
match self {
Self::BinaryFunction(..) => true,
_ => false
}
}
fn binary_function(&self) -> BinaryFunction {
match self {
Self::BinaryFunction(f, ..) => *f,
_ => unreachable!()
}
}
fn is_paren(&self) -> bool {
match self {
Self::Paren(..) => true,
_ => false
}
}
fn is_rnd(&self) -> bool {
match self {
Self::Rnd(_) => true,
_ => false
}
}
fn is_any_function(&self) -> bool {
match self {
Self::AnyFunction(..) => true,
_ => false
}
}
fn function_name(&self) -> &str {
match self {
Self::AnyFunction(n, ..) => n.as_str(),
Self::UnaryFunction(_f, ..) => todo!(),
Self::BinaryFunction(_f, ..) => todo!(),
_ => unreachable!()
}
}
fn function_args(&self) -> &[Self] {
match self {
Self::AnyFunction(_, args, _) => args.as_slice(),
_ => unreachable!()
}
}
fn arg1(&self) -> &Self {
match self {
Self::BinaryOperation(_, box arg1, ..) => arg1,
Self::UnaryOperation(_, box arg, _) => arg,
Self::UnaryFunction(_, box arg, _) => arg,
Self::BinaryFunction(_, box arg1, ..) => arg1,
Self::Paren(box p, _) => p,
_ => unreachable!()
}
}
fn arg2(&self) -> &Self {
match self {
Self::BinaryOperation(_, _, box arg2, _) => arg2,
Self::BinaryFunction(_, _, box arg2, _) => arg2,
_ => unreachable!()
}
}
}
impl ExprEvaluationExt for LocatedExpr {
fn resolve(&self, env: &Env) -> Result<ExprResult, AssemblerError> {
let res = resolve_impl!(self, env).map_err(|e| e.locate(self.span().clone()))?;
let res = ensure_orgams_type(res, env);
res
}
fn symbols_used(&self) -> Vec<&str> {
match self {
LocatedExpr::RelativeDelta(..)
| LocatedExpr::Value(..)
| LocatedExpr::Float(..)
| LocatedExpr::Char(..)
| LocatedExpr::Bool(..)
| LocatedExpr::String(..)
| LocatedExpr::Rnd(_) => Vec::new(),
LocatedExpr::Label(label) | LocatedExpr::PrefixedLabel(_, label, _) => {
vec![label.as_str()]
},
LocatedExpr::BinaryFunction(_, box a, box b, _)
| LocatedExpr::BinaryOperation(_, box a, box b, _) => {
a.symbols_used()
.into_iter()
.chain(b.symbols_used().into_iter())
.collect_vec()
},
LocatedExpr::Paren(a, _)
| LocatedExpr::UnaryFunction(_, a, _)
| LocatedExpr::UnaryOperation(_, a, _) => a.symbols_used(),
LocatedExpr::AnyFunction(_, l, _) | LocatedExpr::List(l, _) => {
l.iter().map(|e| e.symbols_used()).flatten().collect_vec()
},
LocatedExpr::UnaryTokenOperation(_, box _t, _) => {
unimplemented!("Need to retreive the symbols from the operation")
}
}
}
}
impl MayHaveSpan for LocatedExpr {
fn has_span(&self) -> bool {
true
}
fn possible_span(&self) -> Option<&Z80Span> {
Some(self.span())
}
fn span(&self) -> &Z80Span {
match self {
LocatedExpr::RelativeDelta(_, span)
| LocatedExpr::Value(_, span)
| LocatedExpr::Float(_, span)
| LocatedExpr::Char(_, span)
| LocatedExpr::Bool(_, span)
| LocatedExpr::String(UnescapedString(_, span))
| LocatedExpr::Label(span)
| LocatedExpr::List(_, span)
| LocatedExpr::PrefixedLabel(_, _, span)
| LocatedExpr::Paren(_, span)
| LocatedExpr::UnaryFunction(_, _, span)
| LocatedExpr::UnaryOperation(_, _, span)
| LocatedExpr::UnaryTokenOperation(_, _, span)
| LocatedExpr::BinaryFunction(_, _, _, span)
| LocatedExpr::BinaryOperation(_, _, _, span)
| LocatedExpr::AnyFunction(_, _, span)
| LocatedExpr::Rnd(span) => span
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum LocatedDataAccess {
IndexRegister16WithIndex(IndexRegister16, BinaryOperation, LocatedExpr, Z80Span),
IndexRegister16(IndexRegister16, Z80Span),
IndexRegister8(IndexRegister8, Z80Span),
Register16(Register16, Z80Span),
Register8(Register8, Z80Span),
MemoryRegister16(Register16, Z80Span),
MemoryIndexRegister16(IndexRegister16, Z80Span),
Expression(LocatedExpr),
Memory(LocatedExpr),
FlagTest(FlagTest, Z80Span),
SpecialRegisterI(Z80Span),
SpecialRegisterR(Z80Span),
PortC(Z80Span),
PortN(LocatedExpr, Z80Span)
}
impl From<LocatedExpr> for LocatedDataAccess {
fn from(value: LocatedExpr) -> Self {
Self::Expression(value)
}
}
impl Into<DataAccess> for LocatedDataAccess {
fn into(self) -> DataAccess {
self.to_data_access()
}
}
impl LocatedDataAccess {
pub fn to_data_access(self) -> DataAccess {
match self {
LocatedDataAccess::IndexRegister16WithIndex(r, b, e, _) => {
DataAccess::IndexRegister16WithIndex(r, b, e.to_expr().into_owned())
},
LocatedDataAccess::IndexRegister16(i, _) => DataAccess::IndexRegister16(i),
LocatedDataAccess::IndexRegister8(i, _) => DataAccess::IndexRegister8(i),
LocatedDataAccess::Register16(r, _) => DataAccess::Register16(r),
LocatedDataAccess::Register8(r, _) => DataAccess::Register8(r),
LocatedDataAccess::MemoryRegister16(r, _) => DataAccess::MemoryRegister16(r),
LocatedDataAccess::MemoryIndexRegister16(i, _) => DataAccess::MemoryIndexRegister16(i),
LocatedDataAccess::Expression(e) => DataAccess::Expression(e.to_expr().into_owned()),
LocatedDataAccess::Memory(a) => DataAccess::Memory(a.to_expr().into_owned()),
LocatedDataAccess::FlagTest(f, _) => DataAccess::FlagTest(f),
LocatedDataAccess::SpecialRegisterI(_) => DataAccess::SpecialRegisterI,
LocatedDataAccess::SpecialRegisterR(_) => DataAccess::SpecialRegisterI,
LocatedDataAccess::PortC(_) => DataAccess::PortC,
LocatedDataAccess::PortN(p, _) => DataAccess::PortN(p.to_expr().into_owned())
}
}
}
impl LocatedDataAccess {
pub fn span(&self) -> &Z80Span {
match self {
LocatedDataAccess::IndexRegister16WithIndex(_, _, _, span)
| LocatedDataAccess::IndexRegister16(_, span)
| LocatedDataAccess::IndexRegister8(_, span)
| LocatedDataAccess::Register16(_, span)
| LocatedDataAccess::Register8(_, span)
| LocatedDataAccess::MemoryRegister16(_, span)
| LocatedDataAccess::MemoryIndexRegister16(_, span)
| LocatedDataAccess::FlagTest(_, span)
| LocatedDataAccess::SpecialRegisterI(span)
| LocatedDataAccess::SpecialRegisterR(span)
| LocatedDataAccess::PortC(span)
| LocatedDataAccess::PortN(_, span) => span,
LocatedDataAccess::Memory(e) | LocatedDataAccess::Expression(e) => e.span()
}
}
}
impl Display for LocatedDataAccess {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.span())
}
}
impl Into<Expr> for LocatedExpr {
fn into(self) -> Expr {
self.to_expr().into_owned()
}
}
impl DataAccessElem for LocatedDataAccess {
type Expr = LocatedExpr;
data_access_impl_most_methods!();
fn to_data_access_for_low_register(&self) -> Option<Self> {
match self {
Self::IndexRegister16(reg, span) => {
Some(LocatedDataAccess::IndexRegister8(reg.low(), span.clone()))
},
Self::Register16(reg, span) => {
reg.low()
.map(|reg| LocatedDataAccess::Register8(reg, span.clone()))
},
_ => None
}
}
fn to_data_access_for_high_register(&self) -> Option<Self> {
match self {
Self::IndexRegister16(reg, span) => {
Some(LocatedDataAccess::IndexRegister8(reg.high(), span.clone()))
},
Self::Register16(reg, span) => {
reg.high()
.map(|reg| LocatedDataAccess::Register8(reg, span.clone()))
},
_ => None
}
}
fn is_port_c(&self) -> bool {
match self {
Self::PortC(..) => true,
_ => false
}
}
fn is_register_i(&self) -> bool {
match self {
Self::SpecialRegisterI(..) => true,
_ => false
}
}
fn is_register_r(&self) -> bool {
match self {
Self::SpecialRegisterR(..) => true,
_ => false
}
}
fn to_data_access(&self) -> Cow<DataAccess> {
Cow::Owned(match self {
LocatedDataAccess::IndexRegister16WithIndex(a, b, c, _) => {
DataAccess::IndexRegister16WithIndex(*a, *b, c.to_expr().into_owned())
},
LocatedDataAccess::IndexRegister16(a, _) => DataAccess::IndexRegister16(*a),
LocatedDataAccess::IndexRegister8(a, _) => DataAccess::IndexRegister8(*a),
LocatedDataAccess::Register16(a, _) => DataAccess::Register16(*a),
LocatedDataAccess::Register8(a, _) => DataAccess::Register8(*a),
LocatedDataAccess::MemoryRegister16(a, _) => DataAccess::MemoryRegister16(*a),
LocatedDataAccess::MemoryIndexRegister16(a, _) => DataAccess::MemoryIndexRegister16(*a),
LocatedDataAccess::Expression(e) => DataAccess::Expression(e.to_expr().into_owned()),
LocatedDataAccess::Memory(a) => DataAccess::Memory(a.to_expr().into_owned()),
LocatedDataAccess::FlagTest(a, _) => DataAccess::FlagTest(*a),
LocatedDataAccess::SpecialRegisterI(_) => DataAccess::SpecialRegisterI,
LocatedDataAccess::SpecialRegisterR(_) => DataAccess::SpecialRegisterR,
LocatedDataAccess::PortC(_) => DataAccess::PortC,
LocatedDataAccess::PortN(e, _) => DataAccess::PortN(e.to_expr().into_owned())
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LocatedMacroParam {
Empty,
Single(Z80Span),
List(Vec<Box<LocatedMacroParam>>)
}
impl MacroParamElement for LocatedMacroParam {
fn empty() -> Self {
Self::Empty
}
fn is_single(&self) -> bool {
matches!(self, LocatedMacroParam::Single(..))
}
fn is_list(&self) -> bool {
matches!(self, LocatedMacroParam::List(..))
}
fn single_argument(&self) -> beef::lean::Cow<str> {
match &self {
LocatedMacroParam::Empty => beef::lean::Cow::borrowed(""),
LocatedMacroParam::Single(ref s) => beef::lean::Cow::borrowed(s.as_str()),
LocatedMacroParam::List(_) => unreachable!()
}
}
fn list_argument(&self) -> &[Box<Self>] {
match self {
LocatedMacroParam::List(l) => l,
_ => unreachable!()
}
}
}
impl LocatedMacroParam {
pub fn to_macro_param(&self) -> MacroParam {
match self {
LocatedMacroParam::Empty | LocatedMacroParam::Single(_) => {
MacroParam::Single(self.single_argument().to_string())
},
LocatedMacroParam::List(params) => {
MacroParam::List(
params
.iter()
.map(|p| p.to_macro_param())
.map(|p| Box::new(p))
.collect_vec()
)
},
}
}
pub fn is_empty(&self) -> bool {
match self {
LocatedMacroParam::Empty => true,
LocatedMacroParam::Single(text) => text.is_empty(),
_ => false
}
}
pub fn span(&self) -> Z80Span {
match self {
LocatedMacroParam::Single(span) => span.clone(),
LocatedMacroParam::List(_) => todo!(),
LocatedMacroParam::Empty => panic!()
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LocatedTestKind {
True(LocatedExpr),
False(LocatedExpr),
LabelExists(Z80Span),
LabelDoesNotExist(Z80Span),
LabelUsed(Z80Span),
LabelNused(Z80Span)
}
impl LocatedTestKind {
pub fn to_test_kind(&self) -> TestKind {
match self {
LocatedTestKind::True(e) => TestKind::True(e.to_expr().into_owned()),
LocatedTestKind::False(e) => TestKind::False(e.to_expr().into_owned()),
LocatedTestKind::LabelExists(l) => TestKind::LabelExists(l.into()),
LocatedTestKind::LabelDoesNotExist(l) => TestKind::LabelDoesNotExist(l.into()),
LocatedTestKind::LabelUsed(l) => TestKind::LabelUsed(l.into()),
LocatedTestKind::LabelNused(l) => TestKind::LabelNused(l.into())
}
}
}
impl TestKindElement for LocatedTestKind {
type Expr = LocatedExpr;
fn is_true_test(&self) -> bool {
matches!(self, LocatedTestKind::True(_))
}
fn is_false_test(&self) -> bool {
matches!(self, LocatedTestKind::False(_))
}
fn is_label_used_test(&self) -> bool {
matches!(self, LocatedTestKind::LabelUsed(_))
}
fn is_label_nused_test(&self) -> bool {
matches!(self, LocatedTestKind::LabelNused(_))
}
fn is_label_exists_test(&self) -> bool {
matches!(self, LocatedTestKind::LabelExists(_))
}
fn is_label_nexists_test(&self) -> bool {
matches!(self, LocatedTestKind::LabelDoesNotExist(_))
}
fn expr_unchecked(&self) -> &Self::Expr {
match self {
LocatedTestKind::True(exp) | LocatedTestKind::False(exp) => exp,
_ => panic!()
}
}
fn label_unchecked(&self) -> &str {
match self {
LocatedTestKind::LabelExists(l)
| LocatedTestKind::LabelDoesNotExist(l)
| LocatedTestKind::LabelUsed(l)
| LocatedTestKind::LabelNused(l) => l.as_str(),
_ => panic!()
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum LocatedAssemblerControlCommand {
RestrictedAssemblingEnvironment {
passes: Option<LocatedExpr>,
lst: LocatedListing
},
PrintAtParsingState(Vec<FormattedExpr>), PrintAtAssemblingState(Vec<FormattedExpr>)
}
impl AssemblerControlCommand for LocatedAssemblerControlCommand {
type Expr = LocatedExpr;
type T = LocatedToken;
fn is_restricted_assembling_environment(&self) -> bool {
matches!(
self,
LocatedAssemblerControlCommand::RestrictedAssemblingEnvironment { .. }
)
}
fn is_print_at_parse_state(&self) -> bool {
matches!(self, LocatedAssemblerControlCommand::PrintAtParsingState(_))
}
fn is_print_at_assembling_state(&self) -> bool {
matches!(
self,
LocatedAssemblerControlCommand::PrintAtAssemblingState(_)
)
}
fn get_max_nb_passes(&self) -> Option<&Self::Expr> {
match self {
LocatedAssemblerControlCommand::RestrictedAssemblingEnvironment { passes, .. } => {
passes.as_ref()
},
_ => unreachable!()
}
}
fn get_listing(&self) -> &[Self::T] {
match self {
LocatedAssemblerControlCommand::RestrictedAssemblingEnvironment { lst, .. } => lst,
_ => unreachable!()
}
}
fn get_formatted_expr(&self) -> &[FormattedExpr] {
match self {
LocatedAssemblerControlCommand::PrintAtAssemblingState(e)
| LocatedAssemblerControlCommand::PrintAtParsingState(e) => e,
_ => unreachable!()
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum LocatedTokenInner {
Align(LocatedExpr, Option<LocatedExpr>),
Assert(LocatedExpr, Option<Vec<FormattedExpr>>),
AssemblerControl(LocatedAssemblerControlCommand),
Assign {
label: Z80Span,
expr: LocatedExpr,
op: Option<BinaryOperation>
},
Bank(Option<LocatedExpr>),
Bankset(LocatedExpr),
Basic(Option<Vec<Z80Span>>, Option<Vec<LocatedExpr>>, Z80Span),
Break,
Breakpoint(Option<LocatedExpr>),
BuildCpr,
BuildSna(Option<SnapshotVersion>),
Charset(CharsetFormat),
Comment(Z80Span),
Confined(LocatedListing),
CrunchedSection(CrunchType, LocatedListing),
Defb(Vec<LocatedExpr>),
Defs(Vec<(LocatedExpr, Option<LocatedExpr>)>),
Defw(Vec<LocatedExpr>),
End,
Equ {
label: Z80Span,
expr: LocatedExpr
},
Export(Vec<Z80Span>),
Fail(Option<Vec<FormattedExpr>>),
Field {
label: Z80Span,
expr: LocatedExpr
},
For {
label: Z80Span,
start: LocatedExpr,
stop: LocatedExpr,
step: Option<LocatedExpr>,
listing: LocatedListing
},
Function(Z80Span, Vec<Z80Span>, LocatedListing),
If(
Vec<(LocatedTestKind, LocatedListing)>,
Option<LocatedListing>
),
Incbin {
fname: UnescapedString,
offset: Option<LocatedExpr>,
length: Option<LocatedExpr>,
extended_offset: Option<LocatedExpr>,
off: bool,
transformation: BinaryTransformation
},
Include(UnescapedString, Option<Z80Span>, bool),
Iterate(
Z80Span,
either::Either<Vec<LocatedExpr>, LocatedExpr>,
LocatedListing
),
Label(Z80Span),
Let(Z80Span, Expr),
Limit(LocatedExpr),
List,
Macro {
name: Z80Span,
params: Vec<Z80Span>,
content: Z80Span,
flavor: AssemblerFlavor
},
MacroCall(Z80Span, Vec<LocatedMacroParam>),
Map(LocatedExpr),
Module(Z80Span, LocatedListing),
MultiPop(Vec<LocatedDataAccess>),
MultiPush(Vec<LocatedDataAccess>),
Next {
label: Z80Span,
source: Z80Span,
expr: Option<LocatedExpr>
},
NoExport(Vec<Z80Span>),
NoList,
OpCode(
Mnemonic,
Option<LocatedDataAccess>,
Option<LocatedDataAccess>,
Option<Register8>
),
Org {
val1: LocatedExpr,
val2: Option<LocatedExpr>
},
Pause,
Print(Vec<FormattedExpr>),
Protect(LocatedExpr, LocatedExpr),
Range(Z80Span, LocatedExpr, LocatedExpr),
Repeat(
LocatedExpr, LocatedListing, Option<Z80Span>, Option<LocatedExpr>, Option<LocatedExpr> ),
RepeatUntil(LocatedExpr, LocatedListing),
Return(LocatedExpr),
Rorg(LocatedExpr, LocatedListing),
Run(LocatedExpr, Option<LocatedExpr>),
Save {
filename: UnescapedString,
address: Option<LocatedExpr>,
size: Option<LocatedExpr>,
save_type: Option<SaveType>,
dsk_filename: Option<UnescapedString>,
side: Option<LocatedExpr>
},
Section(Z80Span),
SetN {
label: Z80Span,
source: Z80Span,
expr: Option<LocatedExpr>
},
Skip(LocatedExpr),
SnaInit(UnescapedString),
SnaSet(SnapshotFlag, FlagValue),
StableTicker(StableTickerAction<Z80Span>),
StartingIndex {
start: Option<LocatedExpr>,
step: Option<LocatedExpr>
},
Str(Vec<LocatedExpr>),
Struct(Z80Span, Vec<(Z80Span, LocatedToken)>),
Switch(
LocatedExpr,
Vec<(LocatedExpr, LocatedListing, bool)>,
Option<LocatedListing>
),
Undef(Z80Span),
WaitNops(LocatedExpr),
WarningWrapper(Box<Self>, String),
While(LocatedExpr, LocatedListing)
}
impl LocatedTokenInner {
pub fn new_opcode(
mne: Mnemonic,
arg1: Option<LocatedDataAccess>,
arg2: Option<LocatedDataAccess>
) -> Self {
LocatedTokenInner::OpCode(mne, arg1, arg2, None)
}
pub fn into_located_token_direct(self) -> LocatedToken {
let span = match &self {
Self::Label(span) | Self::Comment(span) => span.clone(),
_ => todo!("not coded yet or impossible {:?}", self)
};
LocatedToken {
inner: either::Either::Left(self),
span
}
}
pub fn into_located_token_at(self, span: InnerZ80Span) -> LocatedToken {
match self {
Self::WarningWrapper(token, msg) => {
let warned = Box::new(token.into_located_token_at(span));
LocatedToken {
inner: either::Right((warned, msg)),
span: span.into()
}
},
_ => {
LocatedToken {
inner: either::Either::Left(self),
span: span.into()
}
},
}
}
#[inline]
pub fn into_located_token_between(
self,
start_checkpoint: &<InnerZ80Span as Stream>::Checkpoint,
mut i: InnerZ80Span
) -> LocatedToken {
let input = i.clone();
i.reset(start_checkpoint);
let start_eof_offset: usize = i.eof_offset();
let span = build_span(start_eof_offset, start_checkpoint, input);
self.into_located_token_at(span)
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct LocatedToken {
pub(crate) inner: either::Either<LocatedTokenInner, (Box<LocatedToken>, String)>,
pub(crate) span: Z80Span
}
impl ListingElement for LocatedToken {
type AssemblerControlCommand = LocatedAssemblerControlCommand;
type DataAccess = LocatedDataAccess;
type Expr = LocatedExpr;
type MacroParam = LocatedMacroParam;
type TestKind = LocatedTestKind;
fn to_token(&self) -> Cow<cpclib_tokens::Token> {
match &self.inner {
either::Either::Left(inner) => inner.to_token(),
either::Either::Right((_inner, _msg)) => {
unimplemented!("is it necessary to implement it ?")
}
}
}
fn is_buildcpr(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::BuildCpr) => true,
_ => false
}
}
fn is_equ(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Equ { .. }) => true,
_ => false
}
}
fn equ_symbol(&self) -> &str {
match &self.inner {
either::Left(LocatedTokenInner::Equ { label, .. }) => label.as_str(),
_ => unreachable!()
}
}
fn equ_value(&self) -> &Self::Expr {
match &self.inner {
either::Left(LocatedTokenInner::Equ { expr, .. }) => expr,
_ => unreachable!()
}
}
fn is_warning(&self) -> bool {
self.inner.is_right()
}
fn warning_message(&self) -> &str {
match &self.inner {
either::Right((_inner, msg)) => msg.as_str(),
_ => unreachable!()
}
}
fn is_module(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Module(..)) => true,
_ => false
}
}
fn module_listing(&self) -> &[Self] {
match &self.inner {
either::Left(LocatedTokenInner::Module(_, lst, ..)) => lst,
_ => unreachable!()
}
}
fn module_name(&self) -> &str {
match &self.inner {
either::Left(LocatedTokenInner::Module(name, ..)) => name.as_str(),
_ => unreachable!()
}
}
fn is_while(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::While(..)) => true,
_ => false
}
}
fn while_expr(&self) -> &Self::Expr {
match &self.inner {
either::Left(LocatedTokenInner::While(expr, ..)) => expr,
_ => unreachable!()
}
}
fn while_listing(&self) -> &[Self] {
match &self.inner {
either::Left(LocatedTokenInner::While(_, lst, ..)) => lst,
_ => unreachable!()
}
}
fn mnemonic(&self) -> Option<&Mnemonic> {
match &self.inner {
either::Left(LocatedTokenInner::OpCode(mne, ..)) => Some(mne),
_ => None
}
}
fn mnemonic_arg1(&self) -> Option<&Self::DataAccess> {
match &self.inner {
either::Left(LocatedTokenInner::OpCode(_, arg1, ..)) => arg1.as_ref(),
_ => None
}
}
fn mnemonic_arg2(&self) -> Option<&Self::DataAccess> {
match &self.inner {
either::Left(LocatedTokenInner::OpCode(_, _, arg2, _)) => arg2.as_ref(),
_ => None
}
}
fn mnemonic_arg1_mut(&mut self) -> Option<&mut Self::DataAccess> {
match &mut self.inner {
either::Left(LocatedTokenInner::OpCode(_, arg1, ..)) => arg1.as_mut(),
_ => None
}
}
fn mnemonic_arg2_mut(&mut self) -> Option<&mut Self::DataAccess> {
match &mut self.inner {
either::Left(LocatedTokenInner::OpCode(_, _, arg2, _)) => arg2.as_mut(),
_ => None
}
}
fn is_directive(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::OpCode(..)) => false,
_ => true
}
}
fn is_rorg(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Rorg(..)) => true,
_ => false
}
}
fn rorg_listing(&self) -> &[Self] {
match &self.inner {
either::Left(LocatedTokenInner::Rorg(_, lst)) => lst,
_ => unreachable!()
}
}
fn rorg_expr(&self) -> &Self::Expr {
match &self.inner {
either::Left(LocatedTokenInner::Rorg(exp, ..)) => exp,
_ => unreachable!()
}
}
fn is_iterate(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Iterate(..)) => true,
_ => false
}
}
fn iterate_listing(&self) -> &[Self] {
match &self.inner {
either::Left(LocatedTokenInner::Iterate(_, _, listing, ..)) => listing,
_ => unreachable!()
}
}
fn iterate_counter_name(&self) -> &str {
match &self.inner {
either::Left(LocatedTokenInner::Iterate(name, ..)) => name.as_str(),
_ => unreachable!()
}
}
fn iterate_values(&self) -> either::Either<&Vec<Self::Expr>, &Self::Expr> {
match &self.inner {
either::Left(LocatedTokenInner::Iterate(_, values, ..)) => values.as_ref(),
_ => unreachable!()
}
}
fn is_for(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::For { .. }) => true,
_ => false
}
}
fn for_listing(&self) -> &[Self] {
match &self.inner {
either::Left(LocatedTokenInner::For { listing, .. }) => listing,
_ => unreachable!()
}
}
fn for_label(&self) -> &str {
match &self.inner {
either::Left(LocatedTokenInner::For { label, .. }) => label.as_ref(),
_ => unreachable!()
}
}
fn for_start(&self) -> &Self::Expr {
match &self.inner {
either::Left(LocatedTokenInner::For { start, .. }) => start,
_ => unreachable!()
}
}
fn for_stop(&self) -> &Self::Expr {
match &self.inner {
either::Left(LocatedTokenInner::For { stop, .. }) => stop,
_ => unreachable!()
}
}
fn for_step(&self) -> Option<&Self::Expr> {
match &self.inner {
either::Left(LocatedTokenInner::For { step, .. }) => step.as_ref(),
_ => unreachable!()
}
}
fn is_repeat_until(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::RepeatUntil(..)) => true,
_ => false
}
}
fn repeat_until_listing(&self) -> &[Self] {
match &self.inner {
either::Left(LocatedTokenInner::RepeatUntil(_, code, ..)) => code,
_ => unreachable!()
}
}
fn repeat_until_condition(&self) -> &Self::Expr {
match &self.inner {
either::Left(LocatedTokenInner::RepeatUntil(cond, ..)) => cond,
_ => unreachable!()
}
}
fn is_repeat(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Repeat(..)) => true,
_ => false
}
}
fn repeat_listing(&self) -> &[Self] {
match &self.inner {
either::Left(LocatedTokenInner::Repeat(_, listing, ..)) => listing,
_ => unreachable!()
}
}
fn repeat_count(&self) -> &Self::Expr {
match &self.inner {
either::Left(LocatedTokenInner::Repeat(e, ..)) => e,
_ => unreachable!()
}
}
fn repeat_counter_name(&self) -> Option<&str> {
match &self.inner {
either::Left(LocatedTokenInner::Repeat(_, _, counter_name, ..)) => {
counter_name.as_ref().map(|c| c.as_str())
},
_ => unreachable!()
}
}
fn repeat_counter_start(&self) -> Option<&Self::Expr> {
match &self.inner {
either::Left(LocatedTokenInner::Repeat(_, _, _, start, ..)) => start.as_ref(),
_ => unreachable!()
}
}
fn repeat_counter_step(&self) -> Option<&Self::Expr> {
match &self.inner {
either::Left(LocatedTokenInner::Repeat(_, _, _, _, step)) => step.as_ref(),
_ => unreachable!()
}
}
fn is_macro_definition(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Macro { .. }) => true,
_ => false
}
}
fn macro_definition_name(&self) -> &str {
match &self.inner {
either::Left(LocatedTokenInner::Macro { name, .. }) => name.as_str(),
_ => unreachable!()
}
}
fn macro_definition_arguments(&self) -> SmallVec<[&str; 4]> {
match &self.inner {
either::Left(LocatedTokenInner::Macro { params, .. }) => {
params.iter().map(|a| a.as_str()).collect()
},
_ => unreachable!()
}
}
fn macro_definition_code(&self) -> &str {
match &self.inner {
either::Left(LocatedTokenInner::Macro { content, .. }) => content.as_str(),
_ => unreachable!()
}
}
fn macro_call_name(&self) -> &str {
match &self.inner {
either::Left(LocatedTokenInner::MacroCall(name, ..)) => name.as_str(),
_ => panic!()
}
}
fn macro_call_arguments(&self) -> &[Self::MacroParam] {
match &self.inner {
either::Left(LocatedTokenInner::MacroCall(_, args)) => args,
_ => panic!()
}
}
fn is_if(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::If(..)) => true,
_ => false
}
}
fn if_nb_tests(&self) -> usize {
match &self.inner {
either::Left(LocatedTokenInner::If(tests, ..)) => tests.len(),
_ => panic!()
}
}
fn if_test(&self, idx: usize) -> (&Self::TestKind, &[Self]) {
match &self.inner {
either::Left(LocatedTokenInner::If(tests, ..)) => {
let data = &tests[idx];
(&data.0, &data.1)
},
_ => panic!()
}
}
fn if_else(&self) -> Option<&[Self]> {
match &self.inner {
either::Left(LocatedTokenInner::If(_, r#else)) => r#else.as_ref().map(|l| l.as_slice()),
_ => panic!()
}
}
fn is_include(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Include(..)) => true,
_ => false
}
}
fn is_incbin(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Incbin { .. }) => true,
_ => false
}
}
fn incbin_fname(&self) -> &str {
match &self.inner {
either::Left(LocatedTokenInner::Incbin { fname, .. }) => fname.as_ref(),
_ => unimplemented!()
}
}
fn incbin_offset(&self) -> Option<&Self::Expr> {
match &self.inner {
either::Left(LocatedTokenInner::Incbin { offset, .. }) => offset.as_ref(),
_ => unimplemented!()
}
}
fn incbin_length(&self) -> Option<&Self::Expr> {
match &self.inner {
either::Left(LocatedTokenInner::Incbin { length, .. }) => length.as_ref(),
_ => unimplemented!()
}
}
fn incbin_transformation(&self) -> &cpclib_tokens::BinaryTransformation {
match &self.inner {
either::Left(LocatedTokenInner::Incbin { transformation, .. }) => transformation,
_ => unimplemented!()
}
}
fn include_fname(&self) -> &str {
match &self.inner {
either::Left(LocatedTokenInner::Include(fname, ..)) => fname.as_ref(),
_ => unreachable!()
}
}
fn include_namespace(&self) -> Option<&str> {
match &self.inner {
either::Left(LocatedTokenInner::Include(_, module, ..)) => {
module.as_ref().map(|s| s.as_str())
},
_ => unreachable!()
}
}
fn include_once(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Include(_, _, once)) => *once,
_ => unreachable!()
}
}
fn is_call_macro_or_build_struct(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::MacroCall(..)) => true,
_ => false
}
}
fn is_function_definition(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Function(..)) => true,
_ => false
}
}
fn function_definition_name(&self) -> &str {
match &self.inner {
either::Left(LocatedTokenInner::Function(name, ..)) => name.as_str(),
_ => unreachable!()
}
}
fn function_definition_params(&self) -> SmallVec<[&str; 4]> {
match &self.inner {
either::Left(LocatedTokenInner::Function(_name, params, ..)) => {
params.iter().map(|v| v.as_str()).collect()
},
_ => unreachable!()
}
}
fn function_definition_inner(&self) -> &[Self] {
match &self.inner {
either::Left(LocatedTokenInner::Function(_, _, inner)) => inner,
_ => unreachable!()
}
}
fn is_crunched_section(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::CrunchedSection(..)) => true,
_ => false
}
}
fn crunched_section_listing(&self) -> &[Self] {
match &self.inner {
either::Left(LocatedTokenInner::CrunchedSection(_, lst)) => lst,
_ => unreachable!()
}
}
fn crunched_section_kind(&self) -> &CrunchType {
match &self.inner {
either::Left(LocatedTokenInner::CrunchedSection(kind, ..)) => kind,
_ => unreachable!()
}
}
fn is_confined(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Confined(..)) => true,
_ => false
}
}
fn confined_listing(&self) -> &[Self] {
match &self.inner {
either::Left(LocatedTokenInner::Confined(lst)) => lst,
_ => unreachable!()
}
}
fn is_switch(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Switch(..)) => true,
_ => false
}
}
fn switch_expr(&self) -> &Self::Expr {
match &self.inner {
either::Left(LocatedTokenInner::Switch(expr, ..)) => expr,
_ => unreachable!()
}
}
fn switch_cases(&self) -> Box<dyn Iterator<Item = (&Self::Expr, &[Self], bool)> + '_> {
match &self.inner {
either::Left(LocatedTokenInner::Switch(_, cases, ..)) => {
Box::new(cases.iter().map(|c| (&c.0, c.1.as_slice(), c.2)))
},
_ => unreachable!()
}
}
fn switch_default(&self) -> Option<&[Self]> {
match &self.inner {
either::Left(LocatedTokenInner::Switch(_, _, default, ..)) => {
default.as_ref().map(|l| l.as_slice())
},
_ => unreachable!()
}
}
fn is_db(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Defb(..)) => true,
_ => false
}
}
fn is_dw(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Defw(..)) => true,
_ => false
}
}
fn is_str(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Str(..)) => true,
_ => false
}
}
fn data_exprs(&self) -> &[Self::Expr] {
match &self.inner {
either::Left(LocatedTokenInner::Defb(e, ..))
| either::Left(LocatedTokenInner::Defw(e, ..))
| either::Left(LocatedTokenInner::Str(e, ..)) => e,
_ => unreachable!()
}
}
fn is_set(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Assign { .. }) => true,
_ => false
}
}
fn is_comment(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Comment(..)) => true,
_ => false
}
}
fn warning_token(&self) -> &Self {
match &self.inner {
either::Either::Left(_) => unreachable!(),
either::Either::Right((inner, _msg)) => inner
}
}
fn is_assign(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::Assign { .. }) => true,
_ => false
}
}
fn is_org(&self) -> bool {
todo!()
}
fn is_assembler_control(&self) -> bool {
match &self.inner {
either::Left(LocatedTokenInner::AssemblerControl(_)) => true,
_ => false
}
}
fn assembler_control_command(&self) -> &Self::AssemblerControlCommand {
match &self.inner {
either::Left(LocatedTokenInner::AssemblerControl(cmd)) => cmd,
_ => unreachable!()
}
}
fn assembler_control_get_max_passes(&self) -> Option<&Self::Expr> {
self.assembler_control_command().get_max_nb_passes()
}
fn assembler_control_get_listing(&self) -> &[Self] {
self.assembler_control_command().get_listing()
}
fn macro_flavor(&self) -> AssemblerFlavor {
match &self.inner {
either::Left(LocatedTokenInner::Macro { flavor, .. }) => *flavor,
_ => unreachable!()
}
}
}
impl ListingElement for LocatedTokenInner {
type AssemblerControlCommand = LocatedAssemblerControlCommand;
type DataAccess = LocatedDataAccess;
type Expr = LocatedExpr;
type MacroParam = LocatedMacroParam;
type TestKind = LocatedTestKind;
fn to_token(&self) -> Cow<Token> {
match self {
Self::OpCode(mne, arg1, arg2, arg3) => {
Cow::Owned(Token::OpCode(
*mne,
arg1.as_ref().map(|d| d.to_data_access().into_owned()),
arg2.as_ref().map(|d| d.to_data_access().into_owned()),
arg3.clone()
))
},
Self::Comment(cmt) => Cow::Owned(Token::Comment(cmt.to_string())),
Self::Org { val1, val2 } => {
Cow::Owned(Token::Org {
val1: val1.to_expr().into_owned(),
val2: val2.as_ref().map(|val2| val2.to_expr().into_owned())
})
},
Self::CrunchedSection(c, l) => Cow::Owned(Token::CrunchedSection(*c, l.as_listing())),
Self::Function(name, params, inner) => {
Cow::Owned(Token::Function(
name.into(),
params.iter().map(|p| p.into()).collect_vec(),
inner.as_listing()
))
},
Self::If(v, e) => {
Cow::Owned(Token::If(
v.iter()
.map(|(k, l)| (k.to_test_kind(), l.as_listing()))
.collect_vec(),
e.as_ref().map(|l| l.as_listing())
))
},
Self::Repeat(e, l, s, start, step) => {
unimplemented!("step");
Cow::Owned(Token::Repeat(
e.to_expr().into_owned(),
l.as_listing(),
s.as_ref().map(|s| s.into()),
start.as_ref().map(|e| e.to_expr().into_owned())
))
},
Self::RepeatUntil(e, l) => {
Cow::Owned(Token::RepeatUntil(e.to_expr().into_owned(), l.as_listing()))
},
Self::Rorg(e, l) => Cow::Owned(Token::Rorg(e.to_expr().into_owned(), l.as_listing())),
Self::Switch(v, c, d) => {
Cow::Owned(Token::Switch(
v.to_expr().into_owned(),
c.iter()
.map(|(e, l, b)| (e.to_expr().into_owned(), l.as_listing(), b.clone()))
.collect_vec(),
d.as_ref().map(|d| d.as_listing())
))
},
Self::While(e, l) => Cow::Owned(Token::While(e.to_expr().into_owned(), l.as_listing())),
Self::Iterate(_name, _values, _code) => {
todo!()
},
Self::Module(..) => todo!(),
Self::For {
label,
start,
stop,
step,
listing
} => {
Cow::Owned(Token::For {
label: label.into(),
start: start.to_expr().into_owned(),
stop: stop.to_expr().into_owned(),
step: step.as_ref().map(|e| e.to_expr().into_owned()),
listing: listing.as_listing()
})
},
Self::Label(label) => Cow::Owned(Token::Label(label.into())),
Self::MacroCall(name, params) => {
Cow::Owned(Token::MacroCall(
name.into(),
params.iter().map(|p| p.to_macro_param()).collect_vec()
))
},
Self::Struct(name, params) => {
Cow::Owned(Token::Struct(
name.into(),
params
.iter()
.map(|(label, p)| (label.into(), p.as_simple_token().into_owned()))
.collect_vec()
))
},
Self::Defb(exprs) => {
Cow::Owned(Token::Defb(
exprs.iter().map(|e| e.to_expr().into_owned()).collect_vec()
))
},
Self::Defw(exprs) => {
Cow::Owned(Token::Defw(
exprs.iter().map(|e| e.to_expr().into_owned()).collect_vec()
))
},
Self::Str(exprs) => {
Cow::Owned(Token::Str(
exprs.iter().map(|e| e.to_expr().into_owned()).collect_vec()
))
},
Self::Include(..) => todo!(),
Self::Incbin {
fname: _,
offset: _,
length: _,
extended_offset: _,
off: _,
transformation: _
} => todo!(),
Self::Macro {
name,
params,
content,
flavor
} => {
Cow::Owned(Token::Macro {
name: name.into(),
params: params.iter().map(|p| p.into()).collect_vec(),
content: content.as_str().to_owned(),
flavor: *flavor
})
},
Self::Confined(..) => todo!(),
Self::WarningWrapper(..) => todo!(),
Self::Assign {
label: _,
expr: _,
op: _
} => todo!(),
Self::Equ { label, expr } => {
Cow::Owned(Token::Equ {
label: label.as_str().into(),
expr: expr.to_expr().into_owned()
})
},
Self::SetN {
label: _,
source: _,
expr: _
} => todo!(),
Self::Next {
label: _,
source: _,
expr: _
} => todo!(),
_ => todo!()
}
}
fn is_buildcpr(&self) -> bool {
match &self {
LocatedTokenInner::BuildCpr => true,
_ => false
}
}
fn is_equ(&self) -> bool {
match &self {
LocatedTokenInner::Equ { .. } => true,
_ => false
}
}
fn is_assign(&self) -> bool {
match &self {
LocatedTokenInner::Assign { .. } => true,
_ => false
}
}
fn equ_symbol(&self) -> &str {
match &self {
LocatedTokenInner::Equ { label, .. } => label.as_str(),
_ => unreachable!()
}
}
fn equ_value(&self) -> &Self::Expr {
match &self {
LocatedTokenInner::Equ { expr, .. } => expr,
_ => unreachable!()
}
}
fn is_warning(&self) -> bool {
todo!()
}
fn warning_token(&self) -> &Self {
todo!()
}
fn warning_message(&self) -> &str {
match &self {
LocatedTokenInner::WarningWrapper(_token, message) => message.as_str(),
_ => unreachable!()
}
}
fn is_module(&self) -> bool {
match &self {
LocatedTokenInner::Module(..) => true,
_ => false
}
}
fn module_listing(&self) -> &[Self] {
todo!()
}
fn module_name(&self) -> &str {
match &self {
LocatedTokenInner::Module(name, ..) => name.as_str(),
_ => unreachable!()
}
}
fn is_while(&self) -> bool {
match &self {
LocatedTokenInner::While(..) => true,
_ => false
}
}
fn while_expr(&self) -> &Self::Expr {
match &self {
LocatedTokenInner::While(expr, ..) => expr,
_ => unreachable!()
}
}
fn while_listing(&self) -> &[Self] {
todo!()
}
fn mnemonic(&self) -> Option<&Mnemonic> {
match &self {
LocatedTokenInner::OpCode(mne, ..) => Some(mne),
_ => None
}
}
fn mnemonic_arg1(&self) -> Option<&Self::DataAccess> {
match &self {
LocatedTokenInner::OpCode(_, arg1, ..) => arg1.as_ref(),
_ => None
}
}
fn mnemonic_arg2(&self) -> Option<&Self::DataAccess> {
match &self {
LocatedTokenInner::OpCode(_, _, arg2, _) => arg2.as_ref(),
_ => None
}
}
fn mnemonic_arg1_mut(&mut self) -> Option<&mut Self::DataAccess> {
match self {
LocatedTokenInner::OpCode(_, arg1, ..) => arg1.as_mut(),
_ => None
}
}
fn mnemonic_arg2_mut(&mut self) -> Option<&mut Self::DataAccess> {
match self {
LocatedTokenInner::OpCode(_, _, arg2, _) => arg2.as_mut(),
_ => None
}
}
fn is_directive(&self) -> bool {
match &self {
LocatedTokenInner::OpCode(..) => false,
_ => true
}
}
fn is_rorg(&self) -> bool {
match &self {
LocatedTokenInner::Rorg(..) => true,
_ => false
}
}
fn rorg_listing(&self) -> &[Self] {
todo!()
}
fn rorg_expr(&self) -> &Self::Expr {
match &self {
LocatedTokenInner::Rorg(exp, ..) => exp,
_ => unreachable!()
}
}
fn is_iterate(&self) -> bool {
match &self {
LocatedTokenInner::Iterate(..) => true,
_ => false
}
}
fn iterate_listing(&self) -> &[Self] {
todo!()
}
fn iterate_counter_name(&self) -> &str {
match &self {
LocatedTokenInner::Iterate(name, ..) => name.as_str(),
_ => unreachable!()
}
}
fn iterate_values(&self) -> either::Either<&Vec<Self::Expr>, &Self::Expr> {
match &self {
LocatedTokenInner::Iterate(_, values, ..) => values.as_ref(),
_ => unreachable!()
}
}
fn is_for(&self) -> bool {
match &self {
LocatedTokenInner::For { .. } => true,
_ => false
}
}
fn for_listing(&self) -> &[Self] {
todo!()
}
fn for_label(&self) -> &str {
match &self {
LocatedTokenInner::For { label, .. } => label.as_ref(),
_ => unreachable!()
}
}
fn for_start(&self) -> &Self::Expr {
match &self {
LocatedTokenInner::For { start, .. } => start,
_ => unreachable!()
}
}
fn for_stop(&self) -> &Self::Expr {
match &self {
LocatedTokenInner::For { stop, .. } => stop,
_ => unreachable!()
}
}
fn for_step(&self) -> Option<&Self::Expr> {
match &self {
LocatedTokenInner::For { step, .. } => step.as_ref(),
_ => unreachable!()
}
}
fn is_repeat_until(&self) -> bool {
match &self {
LocatedTokenInner::RepeatUntil(..) => true,
_ => false
}
}
fn repeat_until_listing(&self) -> &[Self] {
todo!()
}
fn repeat_until_condition(&self) -> &Self::Expr {
match &self {
LocatedTokenInner::RepeatUntil(cond, ..) => cond,
_ => unreachable!()
}
}
fn is_repeat(&self) -> bool {
match &self {
LocatedTokenInner::Repeat(..) => true,
_ => false
}
}
fn repeat_listing(&self) -> &[Self] {
todo!()
}
fn repeat_count(&self) -> &Self::Expr {
match &self {
LocatedTokenInner::Repeat(e, ..) => e,
_ => unreachable!()
}
}
fn repeat_counter_name(&self) -> Option<&str> {
match &self {
LocatedTokenInner::Repeat(_, _, counter_name, ..) => {
counter_name.as_ref().map(|c| c.as_str())
},
_ => unreachable!()
}
}
fn repeat_counter_start(&self) -> Option<&Self::Expr> {
match &self {
LocatedTokenInner::Repeat(_, _, _, start, ..) => start.as_ref(),
_ => unreachable!()
}
}
fn is_macro_definition(&self) -> bool {
match &self {
LocatedTokenInner::Macro { .. } => true,
_ => false
}
}
fn macro_definition_name(&self) -> &str {
match &self {
LocatedTokenInner::Macro { name, .. } => name.as_str(),
_ => unreachable!()
}
}
fn macro_definition_arguments(&self) -> SmallVec<[&str; 4]> {
match &self {
LocatedTokenInner::Macro { params, .. } => params.iter().map(|a| a.as_str()).collect(),
_ => unreachable!()
}
}
fn macro_definition_code(&self) -> &str {
match &self {
LocatedTokenInner::Macro { content, .. } => content.as_str(),
_ => unreachable!()
}
}
fn macro_call_name(&self) -> &str {
match &self {
LocatedTokenInner::MacroCall(name, ..) => name.as_str(),
_ => panic!()
}
}
fn macro_call_arguments(&self) -> &[Self::MacroParam] {
match &self {
LocatedTokenInner::MacroCall(_, args) => args,
_ => panic!()
}
}
fn is_if(&self) -> bool {
match &self {
LocatedTokenInner::If(..) => true,
_ => false
}
}
fn if_nb_tests(&self) -> usize {
match &self {
LocatedTokenInner::If(tests, ..) => tests.len(),
_ => panic!()
}
}
fn if_test(&self, _idx: usize) -> (&Self::TestKind, &[Self]) {
todo!()
}
fn if_else(&self) -> Option<&[Self]> {
todo!()
}
fn is_include(&self) -> bool {
match &self {
LocatedTokenInner::Include(..) => true,
_ => false
}
}
fn is_incbin(&self) -> bool {
match &self {
LocatedTokenInner::Incbin { .. } => true,
_ => false
}
}
fn incbin_fname(&self) -> &str {
match &self {
LocatedTokenInner::Incbin { fname, .. } => fname.as_ref(),
_ => unimplemented!()
}
}
fn incbin_offset(&self) -> Option<&Self::Expr> {
match &self {
LocatedTokenInner::Incbin { offset, .. } => offset.as_ref(),
_ => unimplemented!()
}
}
fn incbin_length(&self) -> Option<&Self::Expr> {
match &self {
LocatedTokenInner::Incbin { length, .. } => length.as_ref(),
_ => unimplemented!()
}
}
fn incbin_transformation(&self) -> &cpclib_tokens::BinaryTransformation {
match &self {
LocatedTokenInner::Incbin { transformation, .. } => transformation,
_ => unimplemented!()
}
}
fn include_fname(&self) -> &str {
match &self {
LocatedTokenInner::Include(fname, ..) => fname.as_ref(),
_ => unreachable!()
}
}
fn include_namespace(&self) -> Option<&str> {
match &self {
LocatedTokenInner::Include(_, module, ..) => module.as_ref().map(|s| s.as_str()),
_ => unreachable!()
}
}
fn include_once(&self) -> bool {
match &self {
LocatedTokenInner::Include(_, _, once) => *once,
_ => unreachable!()
}
}
fn is_call_macro_or_build_struct(&self) -> bool {
match &self {
LocatedTokenInner::MacroCall(..) => true,
_ => false
}
}
fn is_function_definition(&self) -> bool {
match &self {
LocatedTokenInner::Function(..) => true,
_ => false
}
}
fn function_definition_name(&self) -> &str {
match &self {
LocatedTokenInner::Function(name, ..) => name.as_str(),
_ => unreachable!()
}
}
fn function_definition_params(&self) -> SmallVec<[&str; 4]> {
match &self {
LocatedTokenInner::Function(_name, params, ..) => {
params.iter().map(|v| v.as_str()).collect()
},
_ => unreachable!()
}
}
fn function_definition_inner(&self) -> &[Self] {
todo!()
}
fn is_crunched_section(&self) -> bool {
match &self {
LocatedTokenInner::CrunchedSection(..) => true,
_ => false
}
}
fn crunched_section_listing(&self) -> &[Self] {
todo!()
}
fn crunched_section_kind(&self) -> &CrunchType {
match &self {
LocatedTokenInner::CrunchedSection(kind, ..) => kind,
_ => unreachable!()
}
}
fn is_confined(&self) -> bool {
match &self {
LocatedTokenInner::Confined(..) => true,
_ => false
}
}
fn confined_listing(&self) -> &[Self] {
todo!()
}
fn is_switch(&self) -> bool {
match &self {
LocatedTokenInner::Switch(..) => true,
_ => false
}
}
fn switch_expr(&self) -> &Self::Expr {
match &self {
LocatedTokenInner::Switch(expr, ..) => expr,
_ => unreachable!()
}
}
fn switch_cases(&self) -> Box<dyn Iterator<Item = (&Self::Expr, &[Self], bool)> + '_> {
todo!()
}
fn switch_default(&self) -> Option<&[Self]> {
todo!()
}
fn is_db(&self) -> bool {
match &self {
LocatedTokenInner::Defb(..) => true,
_ => false
}
}
fn is_dw(&self) -> bool {
match &self {
LocatedTokenInner::Defw(..) => true,
_ => false
}
}
fn is_str(&self) -> bool {
match &self {
LocatedTokenInner::Str(..) => true,
_ => false
}
}
fn data_exprs(&self) -> &[Self::Expr] {
match &self {
LocatedTokenInner::Defb(e, ..)
| LocatedTokenInner::Defw(e, ..)
| LocatedTokenInner::Str(e, ..) => e,
_ => unreachable!()
}
}
fn is_set(&self) -> bool {
match &self {
LocatedTokenInner::Assign { .. } => true,
_ => false
}
}
fn is_comment(&self) -> bool {
match &self {
LocatedTokenInner::Comment(..) => true,
_ => false
}
}
fn is_org(&self) -> bool {
todo!()
}
fn repeat_counter_step(&self) -> Option<&Self::Expr> {
todo!()
}
fn is_assembler_control(&self) -> bool {
todo!()
}
fn assembler_control_command(&self) -> &Self::AssemblerControlCommand {
todo!()
}
fn defer_listing_output(&self) -> bool {
false }
fn include_is_standard_include(&self) -> bool {
self.is_include() &&
!self.include_fname().contains('{') && !self.include_once()
}
fn assembler_control_get_max_passes(&self) -> Option<&Self::Expr> {
self.assembler_control_command().get_max_nb_passes()
}
fn assembler_control_get_listing(&self) -> &[Self] {
todo!()
}
fn macro_flavor(&self) -> AssemblerFlavor {
todo!()
}
}
impl std::fmt::Display for LocatedToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.span())
}
}
impl ToSimpleToken for LocatedToken {
fn as_simple_token(&self) -> Cow<Token> {
self.to_token()
}
}
pub trait MayHaveSpan {
fn possible_span(&self) -> Option<&Z80Span>;
fn span(&self) -> &Z80Span;
fn has_span(&self) -> bool;
}
impl MayHaveSpan for Token {
fn possible_span(&self) -> Option<&Z80Span> {
None
}
fn span(&self) -> &Z80Span {
panic!()
}
fn has_span(&self) -> bool {
false
}
}
impl MayHaveSpan for Expr {
fn possible_span(&self) -> Option<&Z80Span> {
None
}
fn has_span(&self) -> bool {
false
}
fn span(&self) -> &Z80Span {
panic!()
}
}
impl MayHaveSpan for LocatedToken {
fn has_span(&self) -> bool {
true
}
fn possible_span(&self) -> Option<&Z80Span> {
Some(self.span())
}
fn span(&self) -> &Z80Span {
&self.span
}
}
impl Clone for LocatedToken {
fn clone(&self) -> Self {
unimplemented!()
}
}
impl LocatedToken {
pub fn context(&self) -> &ParserContext {
&self.span().context()
}
}
impl LocatedToken {
pub fn parse_token(_value: &str) -> Result<(), String> {
unimplemented!("Should return a LocatedToken reference + its LocatedListing")
}
}
pub trait Locate {
type Output;
fn locate(self, span: Z80Span, size: usize) -> Self::Output;
}
impl TokenExt for LocatedToken {
fn estimated_duration(&self) -> Result<usize, AssemblerError> {
self.to_token().estimated_duration()
}
fn unroll(&self, _env: &crate::Env) -> Option<Result<Vec<&Self>, AssemblerError>> {
todo!()
}
fn disassemble_data(&self) -> Result<cpclib_tokens::Listing, String> {
todo!()
}
}
impl Deref for LocatedToken {
type Target = LocatedTokenInner;
fn deref(&self) -> &Self::Target {
match &self.inner {
either::Either::Left(inner) => inner,
either::Either::Right((inner, _)) => inner.deref()
}
}
}
pub type InnerLocatedListing = BaseListing<LocatedToken>;
#[derive(Eq)]
#[self_referencing]
pub struct LocatedListing {
src: Option<std::sync::Arc<String>>,
#[borrows(src)]
ctx: ParserContext,
#[borrows(src, ctx)]
pub(crate) parse_result: ParseResult
}
impl PartialEq for LocatedListing {
fn eq(&self, other: &Self) -> bool {
self.borrow_src() == other.borrow_src()
}
}
impl std::fmt::Debug for LocatedListing {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.with_parse_result(|p| {
f.debug_struct("LocatedListing")
.field("parse_result", p)
.finish()
})
}
}
#[derive(Debug, PartialEq, Eq)]
pub(crate) enum ParseResult {
SuccessComplete(InnerLocatedListing),
SuccessInner {
listing: InnerLocatedListing,
inner_span: Z80Span
},
FailureInner(ErrMode<Z80ParserError>),
FailureComplete(AssemblerError) }
#[derive(Debug)]
pub(crate) enum ParseResultFirstStage {
Success {
listing: Option<InnerLocatedListing>,
remaining_span: Option<Z80Span>
},
Failure(Z80ParserError)
}
impl LocatedListing {
#[inline]
pub fn new_complete_source<S: Into<String>>(
code: S,
builder: ParserContextBuilder
) -> Result<LocatedListing, LocatedListing> {
let listing = LocatedListingBuilder {
src: Some(code.into().into()),
ctx_builder: move |src: &Option<Arc<String>>| {
let source = src
.as_ref()
.map(|arc| arc.deref())
.map(|s| s.as_str())
.map(|s| unsafe { &*(s as *const str) as &'static str })
.unwrap();
builder.build(source)
},
parse_result_builder: |_, ctx| {
let src: &BStr = ctx.source;
let input_start = Z80Span::new_extra(src, ctx);
let res: Result<
Vec<LocatedToken>,
cpclib_common::winnow::error::ParseError<
cpclib_common::winnow::Stateful<
cpclib_common::winnow::Located<&BStr>,
&ParserContext
>,
Z80ParserError
>
> = parse_lines.parse(input_start.0);
let res: Result<InnerLocatedListing, Z80ParserError> = match res {
Ok(tokens) => {
Ok(InnerLocatedListing::from(tokens))
},
Err(e) => {
let e = e.into_inner();
std::result::Result::Err(e)
}
};
let res = match res {
Ok(listing) => ParseResult::SuccessComplete(listing),
Err(e) => ParseResult::FailureComplete(AssemblerError::SyntaxError { error: e })
};
return res;
}
}
.build();
match listing.borrow_parse_result() {
ParseResult::SuccessComplete(_) => Ok(listing),
ParseResult::FailureComplete(_) => Err(listing),
_ => unreachable!()
}
}
#[inline]
pub fn parse_inner(
input_code: &mut InnerZ80Span,
new_state: ParsingState,
only_one_instruction: bool
) -> PResult<Arc<LocatedListing>, Z80ParserError> {
let mut tokens = Vec::with_capacity(20);
let ctx_moved_in_builder = input_code.state.clone_with_state(new_state);
let inner_listing = LocatedListingBuilder {
src: None,
ctx_builder: move |_src| {
ctx_moved_in_builder
},
parse_result_builder: |_src, lst_ctx| {
let lst_ctx =
unsafe { &*(lst_ctx as *const ParserContext) as &'static ParserContext }; let src = unsafe { &*( std::str::from_utf8_unchecked(input_code.as_bstr()) as *const str) } as &'static str;
let mut inner_span = Z80Span::new_extra(
src,
lst_ctx
);
let inner_code_ptr = &mut inner_span;
let inner_start = inner_code_ptr.checkpoint();
let res = if only_one_instruction {
match parse_single_token.parse_next(inner_code_ptr) {
Ok(token) => {
tokens.push(token);
Ok(())
}
Err(e) => {
Err(e)
}
}
} else {
cut_err(my_many0_nocollect(parse_z80_line_complete(&mut tokens))).parse_next(
inner_code_ptr
)
};
match res {
Ok(_) => {
let inner_length = inner_code_ptr.offset_from(&inner_start);
let inner_span: &'static BStr = unsafe{std::mem::transmute(&input_code.as_bstr().as_bytes()[..inner_length])}; let inner_span = input_code.clone().update_slice(inner_span);
take::<_,_, Z80ParserError>(inner_length).parse_next(input_code).expect("BUG in parser"); ParseResult::SuccessInner {
inner_span: inner_span.into(),
listing: InnerLocatedListing::from(tokens)
}
},
Err(e) => ParseResult::FailureInner(e)
}
}
}
.build();
let inner_listing = Arc::new(inner_listing);
if let ParseResult::SuccessInner { .. } = inner_listing.borrow_parse_result() {
return Ok(inner_listing);
}
if let ParseResult::FailureInner(e) = inner_listing.borrow_parse_result() {
match e {
ErrMode::Incomplete(e) => {
return Err(ErrMode::Incomplete(e.clone()));
},
ErrMode::Backtrack(e) => {
return Err(ErrMode::Backtrack(Z80ParserError::from_inner_error(
input_code,
inner_listing.clone(),
Box::new(e.clone())
)));
},
ErrMode::Cut(e) => {
return Err(ErrMode::Cut(Z80ParserError::from_inner_error(
input_code,
inner_listing.clone(),
Box::new(e.clone())
)));
}
}
}
unreachable!();
}
}
impl LocatedListing {
pub fn src(&self) -> &str {
self.with_src(|src| src.as_ref().map(|s| s.as_str()))
.unwrap_or_else(|| {
self.with_parse_result(|parse_result| {
match parse_result {
ParseResult::SuccessInner { inner_span, .. } => inner_span.as_str(),
_ => unreachable!()
}
})
})
}
pub fn ctx(&self) -> &ParserContext {
self.with_ctx(|ctx| ctx)
}
pub fn span(&self) -> Z80Span {
self.with_parse_result(|parse_result| {
match parse_result {
ParseResult::SuccessComplete(_) => {
let src = self.src();
let ctx = self.ctx();
Z80Span::new_extra(src, ctx)
},
ParseResult::SuccessInner { inner_span, .. } => inner_span.clone(),
_ => panic!("No listing available")
}
})
}
pub fn cpclib_error_unchecked(&self) -> &AssemblerError {
self.with_parse_result(|parse_result| {
match parse_result {
ParseResult::FailureComplete(e) => e,
_ => unreachable!()
}
})
}
pub fn parse_ok(&self) -> bool {
self.with_parse_result(|parse_result| {
match parse_result {
ParseResult::SuccessComplete(_) | ParseResult::SuccessInner { .. } => true,
ParseResult::FailureInner(_) | ParseResult::FailureComplete(_) => false
}
})
}
}
impl Deref for LocatedListing {
type Target = InnerLocatedListing;
fn deref(&self) -> &Self::Target {
self.with_parse_result(|parse_result| {
match parse_result {
ParseResult::SuccessComplete(listing) => listing,
ParseResult::SuccessInner { listing, .. } => listing,
_ => panic!("No listing available.")
}
})
}
}
impl LocatedListing {
pub fn as_listing(&self) -> BaseListing<Token> {
#[cfg(all(not(target_arch = "wasm32"), feature = "rayon"))]
let iter = self.deref().par_iter();
#[cfg(any(target_arch = "wasm32", not(feature = "rayon")))]
let iter = self.deref().iter();
iter.map(|lt| lt.to_token())
.map(|c| -> Token { c.into_owned() })
.collect::<Vec<Token>>()
.into()
}
}
pub trait ParseToken {
type Output: ListingElement;
fn parse_token(src: &str) -> Result<Self::Output, String>;
}
impl ParseToken for Token {
type Output = Token;
fn parse_token(src: &str) -> Result<Self::Output, String> {
let tokens = {
let res = parse_z80_str(src);
match res {
Ok(tokens) => tokens,
Err(_e) => {
return Err("ERROR -- need to code why ...".to_owned());
}
}
};
match tokens.len() {
0 => Err("No ASM found.".to_owned()),
1 => Ok(tokens[0].to_token().into_owned()),
_ => {
Err(format!(
"{} tokens are present instead of one",
tokens.len()
))
},
}
}
}
impl ListingExt for LocatedListing {
fn add_code<S: AsRef<str> + core::fmt::Display>(
&mut self,
code: S
) -> Result<(), AssemblerError> {
panic!("Cannot be used in this context");
}
fn to_bytes_with_options(
&self,
options: crate::assembler::EnvOptions
) -> Result<Vec<u8>, AssemblerError> {
let (_, env) =
crate::assembler::visit_tokens_all_passes_with_options(&self.listing(), options)
.map_err(|(_, _, e)| AssemblerError::AlreadyRenderedError(e.to_string()))?;
Ok(env.produced_bytes())
}
fn estimated_duration(&self) -> Result<usize, AssemblerError> {
todo!()
}
fn to_string(&self) -> String {
todo!()
}
fn to_enhanced_string(&self) -> String {
todo!()
}
fn inject_labels<S: Borrow<str>>(&mut self, labels: HashMap<u16, S>) {
todo!()
}
}