Added Assignable support in parser / AST
This commit is contained in:
parent
e47e739e02
commit
4c6dd311a7
|
@ -38,6 +38,18 @@ impl Hash for Ident {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone, Hash)]
|
||||||
|
pub struct Assignable {
|
||||||
|
pub ident: Ident,
|
||||||
|
pub kind: AssignableKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone, Hash)]
|
||||||
|
pub enum AssignableKind {
|
||||||
|
Variable,
|
||||||
|
Cart { indices: Vec<Expr> },
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Hash)]
|
#[derive(Debug, PartialEq, Clone, Hash)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
pub block: Vec<Stmt>,
|
pub block: Vec<Stmt>,
|
||||||
|
@ -80,7 +92,7 @@ pub enum StmtKind {
|
||||||
init: Option<Expr>,
|
init: Option<Expr>,
|
||||||
},
|
},
|
||||||
Assign {
|
Assign {
|
||||||
ident: Ident,
|
assignable: Assignable,
|
||||||
value: Expr,
|
value: Expr,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -197,7 +197,11 @@ impl ExecEnv {
|
||||||
|
|
||||||
self.decl_var(&ident.ident, init);
|
self.decl_var(&ident.ident, init);
|
||||||
}
|
}
|
||||||
StmtKind::Functio { ident, params, body } => {
|
StmtKind::Functio {
|
||||||
|
ident,
|
||||||
|
params,
|
||||||
|
body,
|
||||||
|
} => {
|
||||||
self.decl_var(
|
self.decl_var(
|
||||||
&ident.ident,
|
&ident.ident,
|
||||||
Value::Functio(Functio::AbleFunctio {
|
Value::Functio(Functio::AbleFunctio {
|
||||||
|
@ -240,9 +244,10 @@ impl ExecEnv {
|
||||||
HaltStatus::Hopback(_) => continue,
|
HaltStatus::Hopback(_) => continue,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
StmtKind::Assign { ident, value } => {
|
StmtKind::Assign { assignable, value } => {
|
||||||
|
// TODO: Assigning to carts
|
||||||
let value = self.eval_expr(value)?;
|
let value = self.eval_expr(value)?;
|
||||||
self.get_var_mut(ident)?.value.replace(value);
|
self.get_var_mut(&assignable.ident)?.value.replace(value);
|
||||||
}
|
}
|
||||||
StmtKind::Break => {
|
StmtKind::Break => {
|
||||||
return Ok(HaltStatus::Break(stmt.span.clone()));
|
return Ok(HaltStatus::Break(stmt.span.clone()));
|
||||||
|
|
|
@ -355,15 +355,25 @@ impl<'source> Parser<'source> {
|
||||||
|
|
||||||
// Variable Assignment
|
// Variable Assignment
|
||||||
Token::Equal => {
|
Token::Equal => {
|
||||||
if let Some(Expr {
|
let assignable = buf.take().and_then(|buf| match buf.kind {
|
||||||
kind: ExprKind::Variable(ident),
|
ExprKind::Variable(ident) => Some(Assignable {
|
||||||
span,
|
ident: Ident::new(ident, buf.span),
|
||||||
}) = buf
|
kind: AssignableKind::Variable,
|
||||||
{
|
}),
|
||||||
|
ExprKind::Index { expr, index } => self.cart_assignable_flow(*expr, *index),
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(assignable) = assignable {
|
||||||
break StmtKind::Assign {
|
break StmtKind::Assign {
|
||||||
ident: Ident::new(ident, span),
|
assignable,
|
||||||
value: self.expr_flow(Token::Semicolon)?,
|
value: self.expr_flow(Token::Semicolon)?,
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
return Err(Error::new(
|
||||||
|
ErrorKind::UnexpectedToken(Token::Equal),
|
||||||
|
self.lexer.span(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,6 +395,27 @@ impl<'source> Parser<'source> {
|
||||||
Ok(r)
|
Ok(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse Cart Assignable flow
|
||||||
|
fn cart_assignable_flow(&mut self, mut buf: Expr, index: Expr) -> Option<Assignable> {
|
||||||
|
let mut indices = vec![index];
|
||||||
|
let ident = loop {
|
||||||
|
match buf.kind {
|
||||||
|
ExprKind::Variable(ident) => break ident,
|
||||||
|
ExprKind::Index { expr, index } => {
|
||||||
|
indices.push(*index);
|
||||||
|
buf = *expr;
|
||||||
|
}
|
||||||
|
_ => return None,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
indices.reverse();
|
||||||
|
Some(Assignable {
|
||||||
|
ident: Ident::new(ident, buf.span),
|
||||||
|
kind: AssignableKind::Cart { indices },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse If flow
|
/// Parse If flow
|
||||||
///
|
///
|
||||||
/// Consists of condition and block, there is no else
|
/// Consists of condition and block, there is no else
|
||||||
|
@ -431,7 +462,11 @@ impl<'source> Parser<'source> {
|
||||||
|
|
||||||
let body = self.get_block()?;
|
let body = self.get_block()?;
|
||||||
|
|
||||||
Ok(StmtKind::Functio { ident, params, body })
|
Ok(StmtKind::Functio {
|
||||||
|
ident,
|
||||||
|
params,
|
||||||
|
body,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse BF function declaration
|
/// Parse BF function declaration
|
||||||
|
|
Loading…
Reference in a new issue