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