merge Object and Expression

This commit is contained in:
Alain Zscheile 2023-05-22 21:04:00 +02:00
parent 599721de7c
commit 3703b65e41

View File

@ -27,13 +27,13 @@ pub struct Entry {
// technically this is a set, but that would just waste space here...
pub args: Box<[Atom]>,
// might be a dummy
pub obj: Option<Object>,
pub obj: Option<Expression>,
// we use a bitflag here to conserve memory
pub flags: EntryFlags,
}
#[derive(Clone, Debug)]
pub enum Object {
pub enum Expression {
Code {
cfe: bool,
data: Box<[Expression]>,
@ -42,6 +42,11 @@ pub enum Object {
Module(Module),
Alias(FullIdentifier),
Integer(i64),
InvocationSingle(Box<(Expression, Expression)>),
InvocationMulti {
obj: Box<Expression>,
args: BTreeMap<Box<[Atom]>, (Location, Expression)>,
},
}
#[derive(Clone, Debug)]
@ -57,18 +62,6 @@ pub struct Path {
pub idents: Box<[Atom]>,
}
#[derive(Clone, Debug)]
pub enum Expression {
InvocationSingle {
obj: Object,
arg: Object,
},
InvocationMulti {
obj: Object,
args: BTreeMap<Box<[Atom]>, (Location, Object)>,
},
}
pub struct Error {
pub loc: Location,
pub kind: ErrorKind,
@ -182,40 +175,6 @@ impl FullIdentifier {
}
impl Expression {
fn parse_high(ctx: &mut ParserContext<'_>) -> Result<Self, Error> {
let obj = Object::parse_high(ctx)?;
Ok(if let Some(&(_, Token::Comma)) = ctx.pklx.peek() {
let mut args = BTreeMap::new();
while ctx.maybe_eat_token(Token::Comma).is_some() {
let Path { loc, idents } = Path::parse_high(ctx)?;
ctx.expect_token(Token::Assign, "=")?;
let obj = Object::parse_high(ctx)?;
if args.insert(idents, (loc, obj)).is_some() {
return Err(Error {
loc,
kind: ErrorKind::DuplicateIdentifier,
});
}
}
Expression::InvocationMulti { obj, args }
} else if matches!(ctx.pklx.peek(), Some(&(_, Token::SemiColon)) | None) {
// do nothing, there won't be an argument
// this escape hatch is a bit ugly, idk...
Expression::InvocationMulti {
obj,
args: BTreeMap::new(),
}
} else {
Expression::InvocationSingle {
obj,
arg: Object::parse_high(ctx)?,
}
})
}
}
impl Object {
fn parse_high(ctx: &mut ParserContext<'_>) -> Result<Self, Error> {
let mut cfe = false;
for (_, i) in ctx.pklx.peeking_take_while(|(_, t)| t.is_cobj_attr()) {
@ -225,7 +184,7 @@ impl Object {
}
}
match ctx.pklx.peek() {
let obj = match ctx.pklx.peek() {
None => Err(ctx.make_eof()),
Some((_, Token::OpenBrace)) => {
ctx.pklx.next();
@ -242,7 +201,7 @@ impl Object {
break;
}
}
Ok(Object::Code {
Ok(Expression::Code {
cfe,
data: codata.into_boxed_slice(),
ret,
@ -257,17 +216,40 @@ impl Object {
// expect a single code object descriptor => alias, or number.
Some(&(_, Token::Integer(i))) => {
ctx.pklx.next();
Ok(Object::Integer(i))
Ok(Expression::Integer(i))
}
Some((_, Token::Module)) => {
ctx.pklx.next();
ctx.expect_token(Token::OpenBrace, "{")?;
let m = Module::parse_high(ctx)?;
ctx.expect_token(Token::CloseBrace, "}")?;
Ok(Object::Module(m))
Ok(Expression::Module(m))
}
_ => FullIdentifier::parse_high(ctx).map(Object::Alias),
}
_ => FullIdentifier::parse_high(ctx).map(Expression::Alias),
}?;
Ok(if let Some(&(_, Token::Comma)) = ctx.pklx.peek() {
let mut args = BTreeMap::new();
while ctx.maybe_eat_token(Token::Comma).is_some() {
let Path { loc, idents } = Path::parse_high(ctx)?;
ctx.expect_token(Token::Assign, "=")?;
let obj = Expression::parse_high(ctx)?;
if args.insert(idents, (loc, obj)).is_some() {
return Err(Error {
loc,
kind: ErrorKind::DuplicateIdentifier,
});
}
}
Expression::InvocationMulti {
obj: Box::new(obj),
args,
}
} else if matches!(ctx.pklx.peek(), Some(&(_, Token::SemiColon)) | None) {
obj
} else {
Expression::InvocationSingle(Box::new((obj, Expression::parse_high(ctx)?)))
})
}
}
@ -346,8 +328,8 @@ impl Module {
}
let obj = if ctx.maybe_eat_token(Token::Assign).is_some() {
let obj = Object::parse_high(ctx)?;
if let Object::Code { cfe: true, .. } = obj {
let obj = Expression::parse_high(ctx)?;
if let Expression::Code { cfe: true, .. } = obj {
flags |= EntryFlags::CTRLFE;
}
Some(obj)
@ -355,7 +337,6 @@ impl Module {
None
};
// code object
ret.entries.insert(
name,
Entry {