var decls
This commit is contained in:
parent
0ee6bbad61
commit
51ef019fd1
|
|
@ -240,7 +240,7 @@ pub enum AstNode {
|
|||
VarDecl {
|
||||
mutable: bool,
|
||||
name: String,
|
||||
var_type: Type,
|
||||
var_type: Option<Type>,
|
||||
},
|
||||
Assignment {
|
||||
dest: Index,
|
||||
|
|
@ -414,6 +414,14 @@ impl PlaceOrValue {
|
|||
PlaceOrValue::Value(_) => PlaceOrValue::Value(index),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eq_placeness(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(PlaceOrValue::Place(_), PlaceOrValue::Place(_))
|
||||
| (PlaceOrValue::Value(_), PlaceOrValue::Value(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
||||
|
|
@ -603,9 +611,48 @@ where
|
|||
self.function.clone()
|
||||
}
|
||||
|
||||
fn stmt(&self) -> impl Parser<'src, TokenInput<'src>, Index, ParserExtra> + Clone {
|
||||
fn var_decl(
|
||||
&self,
|
||||
) -> impl Parser<'src, TokenInput<'src>, Index, ParserExtra> + Clone + use<'src, 'b> {
|
||||
let ident = select! {Token::Ident(ident) => ident};
|
||||
just(Token::Let)
|
||||
.ignored()
|
||||
.then(select! {Token::Mutable => ()}.or_not())
|
||||
.then(ident)
|
||||
.then(
|
||||
just(Token::Colon)
|
||||
.ignore_then(type_parser::<ParserExtra>())
|
||||
.or_not(),
|
||||
)
|
||||
.then(
|
||||
just(Token::Equal)
|
||||
.ignore_then(self.expr().map_with(Self::into_value))
|
||||
.or_not(),
|
||||
)
|
||||
.then_ignore(just(Token::Semi))
|
||||
.map_with(|((((_, mutable), ident), var_type), val), e: &mut E| {
|
||||
let decl = e.state().push(AstNode::VarDecl {
|
||||
mutable: mutable.is_some(),
|
||||
name: ident.to_string(),
|
||||
var_type,
|
||||
});
|
||||
if let Some(expr) = val {
|
||||
e.state().push(AstNode::Assignment {
|
||||
dest: decl,
|
||||
expr: expr.index(),
|
||||
})
|
||||
} else {
|
||||
decl
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn stmt(
|
||||
&self,
|
||||
) -> impl Parser<'src, TokenInput<'src>, Index, ParserExtra> + Clone + use<'src, 'b> {
|
||||
choice((
|
||||
self.function.clone(),
|
||||
self.var_decl(),
|
||||
self.expr
|
||||
.clone()
|
||||
.then_ignore(just(Token::Semi))
|
||||
|
|
@ -718,10 +765,7 @@ where
|
|||
&self,
|
||||
) -> impl Parser<'src, TokenInput<'src>, PlaceOrValue, ParserExtra> + Clone + use<'src, 'b>
|
||||
{
|
||||
self.expr
|
||||
.clone()
|
||||
.then_ignore(just(Token::Semi))
|
||||
.map(PlaceOrValue::index)
|
||||
self.stmt()
|
||||
.repeated()
|
||||
.collect::<Vec<_>>()
|
||||
.then(self.expr.clone().or_not())
|
||||
|
|
@ -1022,13 +1066,20 @@ where
|
|||
.then(self.expr())
|
||||
.then(else_expr.or_not())
|
||||
.map_with(|((condition, then), or), e: &mut E| {
|
||||
// TODO: determine placeness from branches
|
||||
use PlaceOrValue::*;
|
||||
let (then, or) = match (then, or) {
|
||||
(Place(then), Some(Place(or))) => (Place(then), Some(Place(or))),
|
||||
_ => (
|
||||
Self::into_value(then, e),
|
||||
or.map(|or| Self::into_value(or, e)),
|
||||
),
|
||||
};
|
||||
let node = AstNode::If {
|
||||
condition,
|
||||
then: then.index(),
|
||||
r#else: or.map(PlaceOrValue::index),
|
||||
};
|
||||
e.state().push(node).as_value()
|
||||
then.with_index(e.state().push(node))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1095,7 +1146,7 @@ mod symbols;
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use chumsky::{Parser, extra::SimpleState};
|
||||
use chumsky::{ParseResult, Parser, extra::SimpleState};
|
||||
|
||||
use crate::{Ast, AstNode, ParserCtx, ParserExtra, new_token_input, pretty, type_parser};
|
||||
|
||||
|
|
@ -1163,6 +1214,10 @@ mod tests {
|
|||
) {
|
||||
let mut state = SimpleState(Ast::new());
|
||||
let out = parser.parse_with_state(tokens, &mut state);
|
||||
for e in out.errors() {
|
||||
eprintln!("Error: {}", e);
|
||||
panic!("errors occured while parsing.")
|
||||
}
|
||||
let ast = state.0;
|
||||
let mut pretty = pretty::PrettyPrint::new();
|
||||
pretty.print(&ast);
|
||||
|
|
@ -1184,6 +1239,7 @@ mod tests {
|
|||
r#"
|
||||
/// docs!
|
||||
fn my_function(a: i32, b: *const u8) -> i32 {
|
||||
let mut x: i32;
|
||||
x = a + 1;
|
||||
x
|
||||
}
|
||||
|
|
@ -1193,6 +1249,40 @@ fn my_function(a: i32, b: *const u8) -> i32 {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_var_decl() {
|
||||
let ctx = crate::ParserCtx::new();
|
||||
print_ast(
|
||||
new_token_input(
|
||||
r#"
|
||||
let mut x: i32 = 10;
|
||||
"#,
|
||||
),
|
||||
ctx.var_decl(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_stmts() {
|
||||
let ctx = crate::ParserCtx::new();
|
||||
print_ast(
|
||||
new_token_input(
|
||||
r#"
|
||||
let mut x: i32 = 10;
|
||||
"#,
|
||||
),
|
||||
ctx.stmt(),
|
||||
);
|
||||
print_ast(
|
||||
new_token_input(
|
||||
r#"
|
||||
(if (true) {x} else {y}) = x + x;
|
||||
"#,
|
||||
),
|
||||
ctx.stmt(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_if_expr() {
|
||||
let ctx = crate::ParserCtx::new();
|
||||
|
|
|
|||
|
|
@ -164,7 +164,15 @@ impl PrettyPrint {
|
|||
mutable,
|
||||
name,
|
||||
var_type,
|
||||
} => todo!(),
|
||||
} => {
|
||||
self.push_line(format!(
|
||||
"{} [{} {}: {}]",
|
||||
node_name(node),
|
||||
name,
|
||||
mutable.then_some(" mut").unwrap_or(""),
|
||||
var_type.map_or("?".to_string(), |ty| format!("{ty}"))
|
||||
));
|
||||
}
|
||||
AstNode::Assignment { dest, expr } => {
|
||||
self.push_line(format!("{}", node_name(node),));
|
||||
self.indents.push(Indent::Vertical);
|
||||
|
|
@ -174,7 +182,7 @@ impl PrettyPrint {
|
|||
});
|
||||
*self.indents.last_mut().unwrap() = Indent::End;
|
||||
self.push_line("EXPR".to_string());
|
||||
self.with_indent(core::iter::once(*dest), |this, idx| {
|
||||
self.with_indent(core::iter::once(*expr), |this, idx| {
|
||||
this.stuff(ast, idx);
|
||||
});
|
||||
self.indents.pop();
|
||||
|
|
@ -182,8 +190,13 @@ impl PrettyPrint {
|
|||
AstNode::GlobalDecl {
|
||||
name,
|
||||
var_type,
|
||||
expr: value,
|
||||
} => todo!(),
|
||||
expr,
|
||||
} => {
|
||||
self.push_line(format!("{} [{}: {}]", node_name(node), name, var_type));
|
||||
self.with_indent(core::iter::once(*expr), |this, idx| {
|
||||
this.stuff(ast, idx);
|
||||
});
|
||||
}
|
||||
AstNode::StructDecl { name, fields } => todo!(),
|
||||
AstNode::FieldDecl { name, field_type } => todo!(),
|
||||
AstNode::FieldAccess { expr, field } => todo!(),
|
||||
|
|
@ -350,8 +363,8 @@ fn node_name(node: &AstNode) -> &'static str {
|
|||
AstNode::ExplicitCast { .. } => "AS",
|
||||
AstNode::Deref { .. } => "DEREF",
|
||||
AstNode::AddressOf { .. } => "ADDR_OF",
|
||||
AstNode::PlaceToValue { .. } => "INTO_PLACE",
|
||||
AstNode::ValueToPlace { .. } => "INTO_VALUE",
|
||||
AstNode::PlaceToValue { .. } => "INTO_VALUE",
|
||||
AstNode::ValueToPlace { .. } => "INTO_PLACE",
|
||||
AstNode::CallExpr { .. } => "CALL",
|
||||
AstNode::Argument { .. } => "ARG",
|
||||
AstNode::Not(_) => "NOT",
|
||||
|
|
|
|||
Loading…
Reference in a new issue