Type decl stuff

This commit is contained in:
Greg Shuflin 2021-11-18 17:16:39 -08:00
parent 7f3b4a727f
commit 12a7fe3e3e
3 changed files with 155 additions and 107 deletions

View File

@ -2,11 +2,12 @@ use std::{cell::RefCell, rc::Rc};
use nom::{ use nom::{
branch::alt, branch::alt,
bytes::complete::{tag, escaped_transform, take_while, take_till}, bytes::complete::{escaped_transform, tag, take_till, take_while},
character::is_alphanumeric, character::{
character::complete::{ complete::{
alpha1, alphanumeric0, char, line_ending, none_of, not_line_ending, one_of, space0, alpha1, alphanumeric0, char, line_ending, none_of, not_line_ending, one_of, space0, space1,
space1, },
is_alphanumeric,
}, },
combinator::{map, not, opt, peek, recognize, value}, combinator::{map, not, opt, peek, recognize, value},
error::{context, ParseError, VerboseError}, error::{context, ParseError, VerboseError},
@ -82,13 +83,16 @@ fn statement_delimiter(input: Span) -> ParseResult<()> {
pub fn program(input: Span) -> ParseResult<AST> { pub fn program(input: Span) -> ParseResult<AST> {
let id = fresh_id(&input); let id = fresh_id(&input);
//TODO `rest` should be empty //TODO `rest` should be empty
let (rest, statements) = context("AST", let (rest, statements) = context(
"AST",
map( map(
tuple(( tuple((
many0(statement_delimiter), many0(statement_delimiter),
separated_list0(statement_delimiter, statement), separated_list0(statement_delimiter, statement),
many0(statement_delimiter), many0(statement_delimiter),
)), |(_, items, _)| items.into()) )),
|(_, items, _)| items.into(),
),
)(input)?; )(input)?;
println!("REST: {}", rest.fragment()); println!("REST: {}", rest.fragment());
@ -119,34 +123,96 @@ fn statement(input: Span) -> ParseResult<Statement> {
let id = fresh_id(&input); let id = fresh_id(&input);
let (rest, kind) = context( let (rest, kind) = context(
"Parsing-statement", "Parsing-statement",
alt(( alt((map(declaration, StatementKind::Declaration), map(expression, StatementKind::Expression))),
map(declaration, StatementKind::Declaration),
map(expression, StatementKind::Expression),
))
)(input)?; )(input)?;
Ok((rest, Statement { id, location, kind })) Ok((rest, Statement { id, location, kind }))
} }
fn declaration(input: Span) -> ParseResult<Declaration> { fn declaration(input: Span) -> ParseResult<Declaration> {
alt((binding, module))(input) alt((binding, type_decl, module))(input)
}
fn type_decl(input: Span) -> ParseResult<Declaration> {
alt((
map(
tuple((kw("type"), kw("alias"), tok(identifier), tok(char('=')), tok(identifier))),
|(_, _, alias, _, name)| Declaration::TypeAlias {
alias: rc_string(alias.fragment()),
original: rc_string(name.fragment()),
},
),
map(
tuple((kw("type"), opt(kw("mut")), type_singleton_name, tok(char('=')), type_body)),
|(_, mutable, name, _, body)| Declaration::TypeDecl { name, body, mutable: mutable.is_some() },
),
))(input)
}
fn type_body(input: Span) -> ParseResult<TypeBody> {
let id = fresh_id(&input);
alt((
map(
delimited(tok(char('{')), separated_list1(tok(char(',')), record_variant_item), tok(char('}'))),
move |items| TypeBody::ImmediateRecord(id, items),
),
map(separated_list0(tok(char('|')), variant_spec), TypeBody::Variants),
))(input)
}
fn variant_spec(input: Span) -> ParseResult<Variant> {
fn record_variant(input: Span) -> ParseResult<VariantKind> {
map(
delimited(tok(char('{')), separated_list1(tok(char(',')), record_variant_item), tok(char('}'))),
VariantKind::Record,
)(input)
}
fn tuple_variant(input: Span) -> ParseResult<VariantKind> {
map(
delimited(tok(char('(')), separated_list1(tok(char(',')), type_identifier), tok(char(')'))),
VariantKind::TupleStruct,
)(input)
}
let id = fresh_id(&input);
let (rest, (name, kind)) = alt((
pair(tok(identifier), record_variant),
pair(tok(identifier), tuple_variant),
map(tok(identifier), |ident| (ident, VariantKind::UnitStruct)),
))(input)?;
Ok((rest, Variant { id, name: rc_string(name.fragment()), kind }))
}
fn record_variant_item(input: Span) -> ParseResult<(Rc<String>, TypeIdentifier)> {
map(tuple((tok(identifier), tok(char(':')), type_identifier)), |(name, _, ty)| {
(rc_string(name.fragment()), ty)
})(input)
} }
fn binding(input: Span) -> ParseResult<Declaration> { fn binding(input: Span) -> ParseResult<Declaration> {
let parser = let parser =
tuple((kw("let"), opt(kw("mut")), tok(identifier), opt(type_anno), tok(char('=')), expression)); tuple((kw("let"), opt(kw("mut")), tok(identifier), opt(type_anno), tok(char('=')), expression));
map(parser, |(_, maybe_mut, ident, type_anno, _, expr)| map(parser, |(_, maybe_mut, ident, type_anno, _, expr)| Declaration::Binding {
Declaration::Binding { name: rc_string(ident.fragment()), constant: maybe_mut.is_none(), name: rc_string(ident.fragment()),
type_anno, expr })(input) constant: maybe_mut.is_none(),
type_anno,
expr,
})(input)
} }
fn module(input: Span) -> ParseResult<Declaration> { fn module(input: Span) -> ParseResult<Declaration> {
map(tuple((kw("module"), tok(identifier), block)), map(tuple((kw("module"), tok(identifier), block)), |(_, name, items)| Declaration::Module {
|(_, name, items)| Declaration::Module { name: rc_string(name.fragment()), items })(input) name: rc_string(name.fragment()),
items,
})(input)
} }
pub fn expression(input: Span) -> ParseResult<Expression> { pub fn expression(input: Span) -> ParseResult<Expression> {
let id = fresh_id(&input); let id = fresh_id(&input);
map(pair(expression_kind, opt(type_anno)), move |(kind, type_anno)| Expression { id, type_anno, kind })(input) map(pair(expression_kind, opt(type_anno)), move |(kind, type_anno)| Expression { id, type_anno, kind })(
input,
)
} }
fn type_anno(input: Span) -> ParseResult<TypeIdentifier> { fn type_anno(input: Span) -> ParseResult<TypeIdentifier> {
@ -155,24 +221,23 @@ fn type_anno(input: Span) -> ParseResult<TypeIdentifier> {
fn type_identifier(input: Span) -> ParseResult<TypeIdentifier> { fn type_identifier(input: Span) -> ParseResult<TypeIdentifier> {
alt(( alt((
map(delimited(tok(char('(')), separated_list0(tok(char(',')), type_identifier), tok(char(')'))), map(
TypeIdentifier::Tuple), delimited(tok(char('(')), separated_list0(tok(char(',')), type_identifier), tok(char(')'))),
TypeIdentifier::Tuple,
),
map(type_singleton_name, TypeIdentifier::Singleton), map(type_singleton_name, TypeIdentifier::Singleton),
))(input) ))(input)
} }
fn type_singleton_name(input: Span) -> ParseResult<TypeSingletonName> { fn type_singleton_name(input: Span) -> ParseResult<TypeSingletonName> {
map(pair(tok(identifier), opt(type_params)), |(name, params)| TypeSingletonName { map(pair(tok(identifier), opt(type_params)), |(name, params)| TypeSingletonName {
name: rc_string(name.fragment()), params: if let Some(params) = params { params } else { vec![] } name: rc_string(name.fragment()),
params: if let Some(params) = params { params } else { vec![] },
})(input) })(input)
} }
fn type_params(input: Span) -> ParseResult<Vec<TypeIdentifier>> { fn type_params(input: Span) -> ParseResult<Vec<TypeIdentifier>> {
delimited( delimited(tok(char('<')), separated_list1(tok(char(',')), type_identifier), tok(char('>')))(input)
tok(char('<')),
separated_list1(tok(char(',')), type_identifier),
tok(char('>'))
)(input)
} }
pub fn expression_kind(input: Span) -> ParseResult<ExpressionKind> { pub fn expression_kind(input: Span) -> ParseResult<ExpressionKind> {
@ -186,7 +251,8 @@ fn precedence_expr(input: Span) -> ParseResult<ExpressionKind> {
move |(first, rest): (ExpressionKind, Vec<(BinOp, ExpressionKind)>)| { move |(first, rest): (ExpressionKind, Vec<(BinOp, ExpressionKind)>)| {
let mut handle_ref = handle.borrow_mut(); let mut handle_ref = handle.borrow_mut();
BinopSequence { first, rest }.do_precedence(&mut handle_ref) BinopSequence { first, rest }.do_precedence(&mut handle_ref)
})(input) },
)(input)
} }
fn precedence_continuation(input: Span) -> ParseResult<(BinOp, ExpressionKind)> { fn precedence_continuation(input: Span) -> ParseResult<(BinOp, ExpressionKind)> {
@ -227,22 +293,19 @@ enum ExtendedPart<'a> {
} }
fn extended_expr(input: Span) -> ParseResult<ExpressionKind> { fn extended_expr(input: Span) -> ParseResult<ExpressionKind> {
let (s, (primary, parts)) = context("extended-expr", let (s, (primary, parts)) =
pair(primary_expr, many0(extended_expr_part)))(input)?; context("extended-expr", pair(primary_expr, many0(extended_expr_part)))(input)?;
let mut expression = Expression::new(fresh_id(&s), primary); let mut expression = Expression::new(fresh_id(&s), primary);
for part in parts.into_iter() { for part in parts.into_iter() {
let kind = match part { let kind = match part {
ExtendedPart::Index(indexers) => { ExtendedPart::Index(indexers) =>
ExpressionKind::Index { indexee: Box::new(expression), indexers } ExpressionKind::Index { indexee: Box::new(expression), indexers },
}, ExtendedPart::Call(arguments) => ExpressionKind::Call { f: Box::new(expression), arguments },
ExtendedPart::Call(arguments) => {
ExpressionKind::Call { f: Box::new(expression), arguments }
}
ExtendedPart::Accessor(name) => { ExtendedPart::Accessor(name) => {
let name = rc_string(name); let name = rc_string(name);
ExpressionKind::Access { name, expr: Box::new(expression) } ExpressionKind::Access { name, expr: Box::new(expression) }
}, }
}; };
expression = Expression::new(fresh_id(&s), kind); expression = Expression::new(fresh_id(&s), kind);
} }
@ -252,104 +315,90 @@ fn extended_expr(input: Span) -> ParseResult<ExpressionKind> {
fn extended_expr_part(input: Span) -> ParseResult<ExtendedPart> { fn extended_expr_part(input: Span) -> ParseResult<ExtendedPart> {
fn index_part(input: Span) -> ParseResult<Vec<Expression>> { fn index_part(input: Span) -> ParseResult<Vec<Expression>> {
delimited( delimited(tok(char('[')), separated_list1(tok(char(',')), expression), tok(char(']')))(input)
tok(char('[')),
separated_list1(tok(char(',')), expression),
tok(char(']')),
)(input)
} }
fn call_part(input: Span) -> ParseResult<Vec<InvocationArgument>> { fn call_part(input: Span) -> ParseResult<Vec<InvocationArgument>> {
delimited( delimited(tok(char('(')), separated_list0(tok(char(',')), invocation_argument), tok(char(')')))(input)
tok(char('(')),
separated_list0(tok(char(',')), invocation_argument),
tok(char(')')),
)(input)
} }
fn access_part(input: Span) -> ParseResult<&str> { fn access_part(input: Span) -> ParseResult<&str> {
preceded( preceded(tok(char('.')), map(identifier, |item| *item.fragment()))(input)
tok(char('.')),
map(identifier, |item| *item.fragment())
)(input)
} }
alt(( alt((
map(index_part, ExtendedPart::Index), map(index_part, ExtendedPart::Index),
map(call_part, ExtendedPart::Call), map(call_part, ExtendedPart::Call),
map(access_part, ExtendedPart::Accessor) map(access_part, ExtendedPart::Accessor),
))(input) ))(input)
} }
//TODO this shouldn't be an expression b/c type annotations disallowed here //TODO this shouldn't be an expression b/c type annotations disallowed here
fn invocation_argument(input: Span) -> ParseResult<InvocationArgument> { fn invocation_argument(input: Span) -> ParseResult<InvocationArgument> {
alt(( alt((
map(tok(char('_')), |_| InvocationArgument::Ignored), map(tok(char('_')), |_| InvocationArgument::Ignored),
map(tuple(( map(tuple((tok(identifier), tok(char('=')), expression)), |(name, _, expr)| {
tok(identifier), InvocationArgument::Keyword { name: rc_string(name.fragment()), expr }
tok(char('=')), }),
expression,
)), |(name, _, expr)| InvocationArgument::Keyword { name: rc_string(name.fragment()), expr }),
map(expression, InvocationArgument::Positional), map(expression, InvocationArgument::Positional),
))(input) ))(input)
} }
fn primary_expr(input: Span) -> ParseResult<ExpressionKind> { fn primary_expr(input: Span) -> ParseResult<ExpressionKind> {
context("primary-expr", alt(( context(
list_expr, paren_expr, "primary-expr",
string_literal, float_literal, number_literal, bool_literal, identifier_expr alt((
)) list_expr,
paren_expr,
string_literal,
float_literal,
number_literal,
bool_literal,
identifier_expr,
)),
)(input) )(input)
} }
fn paren_expr(input: Span) -> ParseResult<ExpressionKind> { fn paren_expr(input: Span) -> ParseResult<ExpressionKind> {
delimited( delimited(
tok(char('(')), tok(char('(')),
map(separated_list0(tok(char(',')), expression), map(separated_list0(tok(char(',')), expression), |mut exprs| match exprs.len() {
|mut exprs| match exprs.len() {
1 => exprs.pop().unwrap().kind, 1 => exprs.pop().unwrap().kind,
_ => ExpressionKind::TupleLiteral(exprs), _ => ExpressionKind::TupleLiteral(exprs),
}), }),
tok(char(')')) tok(char(')')),
)(input) )(input)
} }
fn list_expr(input: Span) -> ParseResult<ExpressionKind> { fn list_expr(input: Span) -> ParseResult<ExpressionKind> {
map( map(delimited(tok(char('[')), separated_list0(tok(char(',')), expression), tok(char(']'))), |items| {
delimited( ExpressionKind::ListLiteral(items)
tok(char('[')), })(input)
separated_list0(tok(char(',')), expression),
tok(char(']')),
), |items| ExpressionKind::ListLiteral(items))(input)
} }
//TODO need to do something with prefix in the AST //TODO need to do something with prefix in the AST
fn string_literal(input: Span) -> ParseResult<ExpressionKind> { fn string_literal(input: Span) -> ParseResult<ExpressionKind> {
tok( tok(map(pair(opt(identifier), bare_string_literal), |(_maybe_prefix, s)| {
map(pair(opt(identifier), bare_string_literal), ExpressionKind::StringLiteral(Rc::new(s))
|(_maybe_prefix, s)| ExpressionKind::StringLiteral(Rc::new(s))) }))(input)
)(input)
} }
fn bare_string_literal(input: Span) -> ParseResult<String> { fn bare_string_literal(input: Span) -> ParseResult<String> {
let string_escape_transforms = alt(( let string_escape_transforms =
value("\\", tag("\\")), alt((value("\\", tag("\\")), value("\"", tag("\"")), value("\n", tag("n")), value("\t", tag("t"))));
value("\"", tag("\"")), alt((
value("\n", tag("n")), map(tag(r#""""#), |_| String::new()),
value("\t", tag("t")), map(
)); tuple((
alt((map(tag(r#""""#), |_| String::new()), char('"'),
map( escaped_transform(none_of(r#""\"#), '\\', string_escape_transforms),
tuple(( char('"'),
char('"'), )),
escaped_transform(none_of(r#""\"#), '\\', string_escape_transforms), |(_, s, _)| s,
char('"'), ),
)), |(_, s, _)| s)))(input) ))(input)
} }
fn identifier_expr(input: Span) -> ParseResult<ExpressionKind> { fn identifier_expr(input: Span) -> ParseResult<ExpressionKind> {
context("identifier-expr", map(qualified_identifier, ExpressionKind::Value))(input) context("identifier-expr", map(qualified_identifier, ExpressionKind::Value))(input)
} }
@ -362,7 +411,9 @@ fn qualified_identifier(input: Span) -> ParseResult<QualifiedName> {
} }
fn identifier(input: Span) -> ParseResult<Span> { fn identifier(input: Span) -> ParseResult<Span> {
recognize(pair(alt((tag("_"), alpha1)), take_while(|ch: char| { is_alphanumeric(ch as u8) || ch == '_'})))(input) recognize(pair(alt((tag("_"), alpha1)), take_while(|ch: char| is_alphanumeric(ch as u8) || ch == '_')))(
input,
)
} }
fn bool_literal(input: Span) -> ParseResult<ExpressionKind> { fn bool_literal(input: Span) -> ParseResult<ExpressionKind> {

View File

@ -44,9 +44,7 @@ impl Parser {
let id_store: IdStore<ASTItem> = IdStore::new(); let id_store: IdStore<ASTItem> = IdStore::new();
let span = Span::new_extra(input, Rc::new(RefCell::new(id_store))); let span = Span::new_extra(input, Rc::new(RefCell::new(id_store)));
combinator::expression(span).map_err(|err| convert_err(input, err)).map(|(rest, output)| { combinator::expression(span).map_err(|err| convert_err(input, err)).map(|(rest, output)| output)
output
})
} }
#[cfg(test)] #[cfg(test)]

View File

@ -98,7 +98,6 @@ macro_rules! assert_ast {
}; };
} }
macro_rules! assert_ast_comb { macro_rules! assert_ast_comb {
($input:expr, $statements:expr) => { ($input:expr, $statements:expr) => {
let mut parser = Parser::new(); let mut parser = Parser::new();
@ -692,12 +691,12 @@ fn type_declarations() {
})] })]
); );
assert_ast!( assert_ast_comb!(
"type alias Alpha = Beta", "type alias Alpha = Beta",
decl(Declaration::TypeAlias { alias: rc("Alpha"), original: rc("Beta") }) decl(Declaration::TypeAlias { alias: rc("Alpha"), original: rc("Beta") })
); );
assert_ast!("type Complex<T, U> = Unit | Record { field: AnotherType<Bool>, field2: (Nat, Int), field3: T } | Tuple(Int, (String, T))", assert_ast_comb!("type Complex<T, U> = Unit | Record { field: AnotherType<Bool>, field2: (Nat, Int), field3: T } | Tuple(Int, (String, T))",
decl(TypeDecl { decl(TypeDecl {
name: TypeSingletonName { name: rc("Complex"), params: vec![ name: TypeSingletonName { name: rc("Complex"), params: vec![
TypeIdentifier::Singleton(TypeSingletonName { name: rc("T"), params: vec![] }), TypeIdentifier::Singleton(TypeSingletonName { name: rc("T"), params: vec![] }),
@ -734,7 +733,7 @@ fn type_declarations() {
fn declarations() { fn declarations() {
use ExpressionKind::*; use ExpressionKind::*;
assert_ast!( assert_ast_comb!(
"let q_q = Yolo::Swaggins", "let q_q = Yolo::Swaggins",
vec![decl(Declaration::Binding { vec![decl(Declaration::Binding {
name: rc("q_q"), name: rc("q_q"),
@ -749,7 +748,7 @@ fn declarations() {
fn bindings() { fn bindings() {
use ExpressionKind::*; use ExpressionKind::*;
assert_ast!( assert_ast_comb!(
"let mut a = 10", "let mut a = 10",
vec![decl(Declaration::Binding { vec![decl(Declaration::Binding {
name: rc("a"), name: rc("a"),
@ -759,7 +758,7 @@ fn bindings() {
})] })]
); );
assert_ast!( assert_ast_comb!(
"let a = 2 + a", "let a = 2 + a",
vec![stmt(StatementKind::Declaration(Declaration::Binding { vec![stmt(StatementKind::Declaration(Declaration::Binding {
name: rc("a"), name: rc("a"),
@ -769,7 +768,7 @@ fn bindings() {
}))] }))]
); );
assert_ast!( assert_ast_comb!(
"let a: Nat = 2", "let a: Nat = 2",
vec![stmt(StatementKind::Declaration(Declaration::Binding { vec![stmt(StatementKind::Declaration(Declaration::Binding {
name: rc("a"), name: rc("a"),