Make a distinct Block type

This commit is contained in:
Greg Shuflin 2021-10-26 14:05:27 -07:00
parent 3402cfe326
commit 851fd9885f
6 changed files with 85 additions and 62 deletions

View File

@ -3,6 +3,7 @@
use std::rc::Rc;
use std::fmt;
use std::convert::{AsRef, From};
mod visitor;
mod operators;
@ -53,7 +54,7 @@ impl ItemIdStore {
pub struct AST {
#[derivative(PartialEq="ignore")]
pub id: ItemId,
pub statements: Vec<Statement>
pub statements: Block,
}
#[derive(Derivative, Debug, Clone)]
@ -74,7 +75,29 @@ pub enum StatementKind {
Module(ModuleSpecifier),
}
pub type Block = Vec<Statement>;
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Block {
pub statements: Vec<Statement>
}
impl From<Vec<Statement>> for Block {
fn from(statements: Vec<Statement>) -> Self {
Self { statements }
}
}
impl From<Statement> for Block {
fn from(statement: Statement) -> Self {
Self { statements: vec![statement] }
}
}
impl AsRef<[Statement]> for Block {
fn as_ref(&self) -> &[Statement] {
self.statements.as_ref()
}
}
pub type ParamName = Rc<String>;
#[derive(Debug, Derivative, Clone)]
@ -319,6 +342,6 @@ pub enum ImportedNames {
#[derive(Debug, PartialEq, Clone)]
pub struct ModuleSpecifier {
pub name: Rc<String>,
pub contents: Vec<Statement>,
pub contents: Block,
}

View File

@ -22,7 +22,7 @@ pub fn walk_ast<V: ASTVisitor>(v: &mut V, ast: &AST) {
pub fn walk_block<V: ASTVisitor>(v: &mut V, block: &Block) {
use StatementKind::*;
for statement in block.iter() {
for statement in block.statements.iter() {
match statement.kind {
StatementKind::Expression(ref expr) => {
walk_expression(v, expr);

View File

@ -362,7 +362,7 @@ impl Parser {
),
}
}
Ok(AST { id: self.id_store.fresh(), statements })
Ok(AST { id: self.id_store.fresh(), statements: statements.into() })
}
/// `statement := expression | declaration`
@ -478,7 +478,7 @@ impl Parser {
fn func_declaration(&mut self) -> ParseResult<Declaration> {
let signature = self.func_signature()?;
if let LCurlyBrace = self.token_handler.peek_kind() {
let statements = self.nonempty_func_body()?;
let statements = self.nonempty_func_body()?.into();
Ok(Declaration::FuncDecl(signature, statements))
} else {
Ok(Declaration::FuncSig(signature))
@ -771,7 +771,7 @@ impl Parser {
Colon => Some(self.type_anno()?),
_ => None,
};
let body = self.nonempty_func_body()?;
let body = self.nonempty_func_body()?.into();
Ok(Expression::new(self.id_store.fresh(), ExpressionKind::Lambda { params, type_anno, body })) //TODO need to handle types somehow
}
@ -1047,7 +1047,7 @@ impl Parser {
#[recursive_descent_method]
fn block(&mut self) -> ParseResult<Block> {
let block = delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict);
Ok(block)
Ok(block.into())
}
#[recursive_descent_method]
@ -1058,7 +1058,7 @@ impl Parser {
_ => {
let expr = self.expression()?;
let s = Statement { id: self.id_store.fresh(), location: tok.location, kind: StatementKind::Expression(expr) };
Ok(vec![s])
Ok(s.into())
}
}
}
@ -1118,7 +1118,7 @@ impl Parser {
Ok(match tok.get_kind() {
LCurlyBrace => {
let statements = delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict);
StatementBlock(statements)
StatementBlock(statements.into())
},
Keyword(Kw::Return) => {
self.token_handler.next();
@ -1279,7 +1279,7 @@ impl Parser {
expect!(self, Keyword(Kw::Module));
let name = self.identifier()?;
let contents = delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict);
Ok(ModuleSpecifier { name, contents })
Ok(ModuleSpecifier { name, contents: contents.into() })
}
}

View File

@ -48,7 +48,7 @@ macro_rules! parse_test {
};
}
macro_rules! parse_test_wrap_ast {
($string:expr, $correct:expr) => { parse_test!($string, AST { id: Default::default(), statements: vec![$correct] }) }
($string:expr, $correct:expr) => { parse_test!($string, AST { id: Default::default(), statements: vec![$correct].into() }) }
}
macro_rules! parse_error {
($string:expr) => { assert!(parse($string).is_err()) }
@ -142,7 +142,7 @@ fn parsing_number_literals_and_binexps() {
AST {
id: Default::default(),
statements: vec![exst!(NatLiteral(3)), exst!(NatLiteral(4)),
exst!(FloatLiteral(4.3))]
exst!(FloatLiteral(4.3))].into()
}
};
@ -271,10 +271,10 @@ fn parsing_functions() {
parse_test_wrap_ast!("fn a(x) { x() }", decl!(
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), anno: None, default: None }], type_anno: None },
vec![exst!(Call { f: bx!(ex!(val!("x"))), arguments: vec![] })])));
vec![exst!(Call { f: bx!(ex!(val!("x"))), arguments: vec![] })].into())));
parse_test_wrap_ast!("fn a(x) {\n x() }", decl!(
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), anno: None, default: None }], type_anno: None },
vec![exst!(Call { f: bx!(ex!(val!("x"))), arguments: vec![] })])));
vec![exst!(Call { f: bx!(ex!(val!("x"))), arguments: vec![] })].into())));
let multiline = r#"
fn a(x) {
@ -283,7 +283,7 @@ x()
"#;
parse_test_wrap_ast!(multiline, decl!(
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), default: None, anno: None }], type_anno: None },
vec![exst!(Call { f: bx!(ex!(val!("x"))), arguments: vec![] })])));
vec![exst!(Call { f: bx!(ex!(val!("x"))), arguments: vec![] })].into())));
let multiline2 = r#"
fn a(x) {
@ -293,7 +293,7 @@ x()
"#;
parse_test_wrap_ast!(multiline2, decl!(
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), default: None, anno: None }], type_anno: None },
vec![exst!(s "x()")])));
exst!(s "x()").into())));
}
#[test]
@ -304,7 +304,7 @@ fn functions_with_default_args() {
FuncDecl(Signature { name: rc!(func), operator: false, type_anno: None, params: vec![
FormalParam { name: rc!(x), default: None, anno: Some(ty!("Int")) },
FormalParam { name: rc!(y), default: Some(ex!(s "4")), anno: Some(ty!("Int")) }
]}, vec![])
]}, vec![].into())
)
};
}
@ -383,7 +383,7 @@ fn parsing_block_expressions() {
}),
body: bx! {
IfExpressionBody::SimpleConditional {
then_case: vec![exst!(Call { f: bx!(ex!(val!("b"))), arguments: vec![]}), exst!(Call { f: bx!(ex!(val!("c"))), arguments: vec![] })],
then_case: vec![exst!(Call { f: bx!(ex!(val!("b"))), arguments: vec![]}), exst!(Call { f: bx!(ex!(val!("c"))), arguments: vec![] })].into(),
else_case: None,
}
}
@ -399,8 +399,8 @@ fn parsing_block_expressions() {
}),
body: bx! {
IfExpressionBody::SimpleConditional {
then_case: vec![exst!(Call { f: bx!(ex!(val!("b"))), arguments: vec![]}), exst!(Call { f: bx!(ex!(val!("c"))), arguments: vec![] })],
else_case: Some(vec![exst!(val!("q"))]),
then_case: vec![exst!(Call { f: bx!(ex!(val!("b"))), arguments: vec![]}), exst!(Call { f: bx!(ex!(val!("c"))), arguments: vec![] })].into(),
else_case: Some(vec![exst!(val!("q"))].into()),
}
}
}
@ -527,7 +527,7 @@ fn parsing_type_annotations() {
#[test]
fn parsing_lambdas() {
parse_test_wrap_ast! { r#"\(x) { x + 1}"#, exst!(
Lambda { params: vec![FormalParam { name: rc!(x), anno: None, default: None } ], type_anno: None, body: vec![exst!(s "x + 1")] }
Lambda { params: vec![FormalParam { name: rc!(x), anno: None, default: None } ], type_anno: None, body: exst!(s "x + 1").into() }
)
}
@ -538,7 +538,7 @@ fn parsing_lambdas() {
FormalParam { name: rc!(y), anno: None, default: None }
],
type_anno: None,
body: vec![exst!(s "a"), exst!(s "b"), exst!(s "c")]
body: vec![exst!(s "a"), exst!(s "b"), exst!(s "c")].into()
})
);
@ -549,7 +549,7 @@ fn parsing_lambdas() {
FormalParam { name: rc!(x), anno: None, default: None }
],
type_anno: None,
body: vec![exst!(s "y")] }
body: exst!(s "y").into() }
)),
arguments: vec![inv!(ex!(NatLiteral(1)))] })
};
@ -561,7 +561,7 @@ fn parsing_lambdas() {
FormalParam { name: rc!(x), anno: Some(ty!("Int")), default: None },
],
type_anno: Some(ty!("String")),
body: vec![exst!(s r#""q""#)]
body: exst!(s r#""q""#).into()
})
}
}
@ -573,7 +573,7 @@ fn single_param_lambda() {
exst!(Lambda {
params: vec![FormalParam { name: rc!(x), anno: None, default: None }],
type_anno: None,
body: vec![exst!(s r"x + 10")]
body: exst!(s r"x + 10").into()
})
}
@ -582,7 +582,7 @@ fn single_param_lambda() {
exst!(Lambda {
params: vec![FormalParam { name: rc!(x), anno: Some(ty!("Nat")), default: None }],
type_anno: None,
body: vec![exst!(s r"x + 10")]
body: exst!(s r"x + 10").into()
})
}
}
@ -602,7 +602,7 @@ fn more_advanced_lambdas() {
arguments: vec![inv!(ex!(NatLiteral(3)))],
}
}
]
].into()
}
}
}
@ -619,12 +619,12 @@ fn more_advanced_lambdas() {
fn while_expr() {
parse_test_wrap_ast! {
"while { }",
exst!(WhileExpression { condition: None, body: vec![] })
exst!(WhileExpression { condition: None, body: Block::default() })
}
parse_test_wrap_ast! {
"while a == b { }",
exst!(WhileExpression { condition: Some(bx![ex![binexp!("==", val!("a"), val!("b"))]]), body: vec![] })
exst!(WhileExpression { condition: Some(bx![ex![binexp!("==", val!("a"), val!("b"))]]), body: Block::default() })
}
}
@ -641,7 +641,7 @@ fn for_expr() {
parse_test_wrap_ast! {
"for n <- someRange { f(n); }",
exst!(ForExpression { enumerators: vec![Enumerator { id: rc!(n), generator: ex!(val!("someRange"))}],
body: bx!(ForBody::StatementBlock(vec![exst!(s "f(n)")]))
body: bx!(ForBody::StatementBlock(vec![exst!(s "f(n)")].into()))
})
}
}
@ -654,8 +654,8 @@ fn patterns() {
discriminator: Some(bx!(ex!(s "x"))),
body: bx!(IfExpressionBody::SimplePatternMatch {
pattern: Pattern::TupleStruct(qname!(Some), vec![Pattern::VarOrName(qname!(a))]),
then_case: vec![exst!(s "4")],
else_case: Some(vec![exst!(s "9")]) })
then_case: vec![exst!(s "4")].into(),
else_case: Some(vec![exst!(s "9")].into()) })
}
)
}
@ -666,8 +666,8 @@ fn patterns() {
discriminator: Some(bx!(ex!(s "x"))),
body: bx!(IfExpressionBody::SimplePatternMatch {
pattern: Pattern::TupleStruct(qname!(Some), vec![Pattern::VarOrName(qname!(a))]),
then_case: vec![exst!(s "4")],
else_case: Some(vec![exst!(s "9")]) }
then_case: vec![exst!(s "4")].into(),
else_case: Some(vec![exst!(s "9")].into()) }
)
}
)
@ -682,8 +682,8 @@ fn patterns() {
(rc!(a),Pattern::Literal(PatternLiteral::StringPattern(rc!(a)))),
(rc!(b),Pattern::VarOrName(qname!(x)))
]),
then_case: vec![exst!(s "4")],
else_case: Some(vec![exst!(s "9")])
then_case: vec![exst!(s "4")].into(),
else_case: Some(vec![exst!(s "9")].into())
}
)
}
@ -700,8 +700,8 @@ fn pattern_literals() {
discriminator: Some(bx!(ex!(s "x"))),
body: bx!(IfExpressionBody::SimplePatternMatch {
pattern: Pattern::Literal(PatternLiteral::NumPattern { neg: true, num: NatLiteral(1) }),
then_case: vec![exst!(NatLiteral(1))],
else_case: Some(vec![exst!(NatLiteral(2))]),
then_case: vec![exst!(NatLiteral(1))].into(),
else_case: Some(vec![exst!(NatLiteral(2))].into()),
})
}
)
@ -714,8 +714,8 @@ fn pattern_literals() {
discriminator: Some(bx!(ex!(s "x"))),
body: bx!(IfExpressionBody::SimplePatternMatch {
pattern: Pattern::Literal(PatternLiteral::NumPattern { neg: false, num: NatLiteral(1) }),
then_case: vec![exst!(s "1")],
else_case: Some(vec![exst!(s "2")]),
then_case: vec![exst!(s "1")].into(),
else_case: Some(vec![exst!(s "2")].into()),
})
}
)
@ -729,8 +729,8 @@ fn pattern_literals() {
body: bx!(
IfExpressionBody::SimplePatternMatch {
pattern: Pattern::Literal(PatternLiteral::BoolPattern(true)),
then_case: vec![exst!(NatLiteral(1))],
else_case: Some(vec![exst!(NatLiteral(2))]),
then_case: vec![exst!(NatLiteral(1))].into(),
else_case: Some(vec![exst!(NatLiteral(2))].into()),
})
}
)
@ -743,8 +743,8 @@ fn pattern_literals() {
discriminator: Some(bx!(ex!(s "x"))),
body: bx!(IfExpressionBody::SimplePatternMatch {
pattern: Pattern::Literal(PatternLiteral::StringPattern(rc!(gnosticism))),
then_case: vec![exst!(s "1")],
else_case: Some(vec![exst!(s "2")]),
then_case: vec![exst!(s "1")].into(),
else_case: Some(vec![exst!(s "2")].into()),
})
}
)
@ -816,12 +816,12 @@ fn if_expr() {
ConditionArm {
condition: Condition::Pattern(Pattern::Literal(PatternLiteral::NumPattern { neg: false, num: NatLiteral(1)})),
guard: None,
body: vec![exst!(s "5")],
body: vec![exst!(s "5")].into(),
},
ConditionArm {
condition: Condition::Else,
guard: None,
body: vec![exst!(s "20")],
body: vec![exst!(s "20")].into(),
},
]
))
@ -854,7 +854,7 @@ if (45, "panda", false, 2.2) {
]
)),
guard: None,
body: vec![exst!(s r#""no""#)],
body: vec![exst!(s r#""no""#)].into(),
},
ConditionArm {
condition: Condition::Pattern(Pattern::TuplePattern(
@ -866,12 +866,12 @@ if (45, "panda", false, 2.2) {
]
)),
guard: None,
body: vec![exst!(s r#""yes""#)],
body: vec![exst!(s r#""yes""#)].into(),
},
ConditionArm {
condition: Condition::Pattern(Pattern::Ignored),
guard: None,
body: vec![exst!(s r#""maybe""#)],
body: vec![exst!(s r#""maybe""#)].into(),
},
]))
}
@ -891,8 +891,8 @@ r#"
module!(
ModuleSpecifier { name: rc!(ephraim), contents: vec![
decl!(Binding { name: rc!(a), constant: true, type_anno: None, expr: ex!(s "10") }),
decl!(FuncDecl(Signature { name: rc!(nah), operator: false, params: vec![], type_anno: None }, vec![exst!(NatLiteral(33))])),
] }
decl!(FuncDecl(Signature { name: rc!(nah), operator: false, params: vec![], type_anno: None }, vec![exst!(NatLiteral(33))].into())),
].into() }
)
}
}
@ -911,10 +911,10 @@ fn annotations() {
decl!(Annotation { name: rc!(test_annotation), arguments: vec![] }),
decl!(FuncDecl(
Signature { name: rc!(some_function), operator: false, params: vec![], type_anno: None }
, vec![]
, vec![].into()
)
)
]
].into()
}
};
parse_test! {
@ -932,10 +932,10 @@ fn annotations() {
] }),
decl!(FuncDecl(
Signature { name: rc!(some_function), operator: false, params: vec![], type_anno: None }
, vec![]
, vec![].into()
)
)
]
].into()
}
};
}

View File

@ -31,14 +31,14 @@ impl<'a> Reducer<'a> {
fn reduce(mut self, ast: &ast::AST) -> ReducedIR {
// First reduce all functions
// TODO once this works, maybe rewrite it using the Visitor
for statement in ast.statements.iter() {
for statement in ast.statements.statements.iter() {
self.top_level_statement(statement);
}
// Then compute the entrypoint statements (which may reference previously-computed
// functions by ID)
let mut entrypoint = vec![];
for statement in ast.statements.iter() {
for statement in ast.statements.statements.iter() {
let ast::Statement { id: item_id, kind, .. } = statement;
match &kind {
ast::StatementKind::Expression(expr) => {
@ -224,8 +224,8 @@ impl<'a> Reducer<'a> {
}
}
fn function_internal_block(&mut self, statements: &ast::Block) -> Vec<Statement> {
statements.iter().filter_map(|stmt| self.function_internal_statement(stmt)).collect()
fn function_internal_block(&mut self, block: &ast::Block) -> Vec<Statement> {
block.statements.iter().filter_map(|stmt| self.function_internal_statement(stmt)).collect()
}
fn prefix(&mut self, prefix: &ast::PrefixOp, arg: &ast::Expression) -> Expression {

View File

@ -298,7 +298,7 @@ impl<'a> TypeContext<'a> {
/// the AST to ReducedAST
pub fn typecheck(&mut self, ast: &AST) -> Result<Type, TypeError> {
let mut returned_type = Type::Const(TypeConst::Unit);
for statement in ast.statements.iter() {
for statement in ast.statements.statements.iter() {
returned_type = self.statement(statement)?;
}
Ok(returned_type)
@ -444,7 +444,7 @@ impl<'a> TypeContext<'a> {
#[allow(clippy::ptr_arg)]
fn block(&mut self, block: &Block) -> InferResult<Type> {
let mut output = ty!(Unit);
for statement in block.iter() {
for statement in block.statements.iter() {
output = self.statement(statement)?;
}
Ok(output)