var decls
This commit is contained in:
parent
0ee6bbad61
commit
51ef019fd1
|
|
@ -240,7 +240,7 @@ pub enum AstNode {
|
||||||
VarDecl {
|
VarDecl {
|
||||||
mutable: bool,
|
mutable: bool,
|
||||||
name: String,
|
name: String,
|
||||||
var_type: Type,
|
var_type: Option<Type>,
|
||||||
},
|
},
|
||||||
Assignment {
|
Assignment {
|
||||||
dest: Index,
|
dest: Index,
|
||||||
|
|
@ -414,6 +414,14 @@ impl PlaceOrValue {
|
||||||
PlaceOrValue::Value(_) => PlaceOrValue::Value(index),
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
||||||
|
|
@ -603,9 +611,48 @@ where
|
||||||
self.function.clone()
|
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((
|
choice((
|
||||||
self.function.clone(),
|
self.function.clone(),
|
||||||
|
self.var_decl(),
|
||||||
self.expr
|
self.expr
|
||||||
.clone()
|
.clone()
|
||||||
.then_ignore(just(Token::Semi))
|
.then_ignore(just(Token::Semi))
|
||||||
|
|
@ -718,10 +765,7 @@ where
|
||||||
&self,
|
&self,
|
||||||
) -> impl Parser<'src, TokenInput<'src>, PlaceOrValue, ParserExtra> + Clone + use<'src, 'b>
|
) -> impl Parser<'src, TokenInput<'src>, PlaceOrValue, ParserExtra> + Clone + use<'src, 'b>
|
||||||
{
|
{
|
||||||
self.expr
|
self.stmt()
|
||||||
.clone()
|
|
||||||
.then_ignore(just(Token::Semi))
|
|
||||||
.map(PlaceOrValue::index)
|
|
||||||
.repeated()
|
.repeated()
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.then(self.expr.clone().or_not())
|
.then(self.expr.clone().or_not())
|
||||||
|
|
@ -1022,13 +1066,20 @@ where
|
||||||
.then(self.expr())
|
.then(self.expr())
|
||||||
.then(else_expr.or_not())
|
.then(else_expr.or_not())
|
||||||
.map_with(|((condition, then), or), e: &mut E| {
|
.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 {
|
let node = AstNode::If {
|
||||||
condition,
|
condition,
|
||||||
then: then.index(),
|
then: then.index(),
|
||||||
r#else: or.map(PlaceOrValue::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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
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};
|
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 mut state = SimpleState(Ast::new());
|
||||||
let out = parser.parse_with_state(tokens, &mut state);
|
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 ast = state.0;
|
||||||
let mut pretty = pretty::PrettyPrint::new();
|
let mut pretty = pretty::PrettyPrint::new();
|
||||||
pretty.print(&ast);
|
pretty.print(&ast);
|
||||||
|
|
@ -1184,6 +1239,7 @@ mod tests {
|
||||||
r#"
|
r#"
|
||||||
/// docs!
|
/// docs!
|
||||||
fn my_function(a: i32, b: *const u8) -> i32 {
|
fn my_function(a: i32, b: *const u8) -> i32 {
|
||||||
|
let mut x: i32;
|
||||||
x = a + 1;
|
x = a + 1;
|
||||||
x
|
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]
|
#[test]
|
||||||
fn parse_if_expr() {
|
fn parse_if_expr() {
|
||||||
let ctx = crate::ParserCtx::new();
|
let ctx = crate::ParserCtx::new();
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,15 @@ impl PrettyPrint {
|
||||||
mutable,
|
mutable,
|
||||||
name,
|
name,
|
||||||
var_type,
|
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 } => {
|
AstNode::Assignment { dest, expr } => {
|
||||||
self.push_line(format!("{}", node_name(node),));
|
self.push_line(format!("{}", node_name(node),));
|
||||||
self.indents.push(Indent::Vertical);
|
self.indents.push(Indent::Vertical);
|
||||||
|
|
@ -174,7 +182,7 @@ impl PrettyPrint {
|
||||||
});
|
});
|
||||||
*self.indents.last_mut().unwrap() = Indent::End;
|
*self.indents.last_mut().unwrap() = Indent::End;
|
||||||
self.push_line("EXPR".to_string());
|
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);
|
this.stuff(ast, idx);
|
||||||
});
|
});
|
||||||
self.indents.pop();
|
self.indents.pop();
|
||||||
|
|
@ -182,8 +190,13 @@ impl PrettyPrint {
|
||||||
AstNode::GlobalDecl {
|
AstNode::GlobalDecl {
|
||||||
name,
|
name,
|
||||||
var_type,
|
var_type,
|
||||||
expr: value,
|
expr,
|
||||||
} => todo!(),
|
} => {
|
||||||
|
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::StructDecl { name, fields } => todo!(),
|
||||||
AstNode::FieldDecl { name, field_type } => todo!(),
|
AstNode::FieldDecl { name, field_type } => todo!(),
|
||||||
AstNode::FieldAccess { expr, field } => todo!(),
|
AstNode::FieldAccess { expr, field } => todo!(),
|
||||||
|
|
@ -350,8 +363,8 @@ fn node_name(node: &AstNode) -> &'static str {
|
||||||
AstNode::ExplicitCast { .. } => "AS",
|
AstNode::ExplicitCast { .. } => "AS",
|
||||||
AstNode::Deref { .. } => "DEREF",
|
AstNode::Deref { .. } => "DEREF",
|
||||||
AstNode::AddressOf { .. } => "ADDR_OF",
|
AstNode::AddressOf { .. } => "ADDR_OF",
|
||||||
AstNode::PlaceToValue { .. } => "INTO_PLACE",
|
AstNode::PlaceToValue { .. } => "INTO_VALUE",
|
||||||
AstNode::ValueToPlace { .. } => "INTO_VALUE",
|
AstNode::ValueToPlace { .. } => "INTO_PLACE",
|
||||||
AstNode::CallExpr { .. } => "CALL",
|
AstNode::CallExpr { .. } => "CALL",
|
||||||
AstNode::Argument { .. } => "ARG",
|
AstNode::Argument { .. } => "ARG",
|
||||||
AstNode::Not(_) => "NOT",
|
AstNode::Not(_) => "NOT",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue