Type decl stuff
This commit is contained in:
parent
7f3b4a727f
commit
12a7fe3e3e
@ -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,32 +315,21 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,71 +337,68 @@ fn extended_expr_part(input: Span) -> ParseResult<ExtendedPart> {
|
|||||||
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")),
|
|
||||||
));
|
|
||||||
alt((map(tag(r#""""#), |_| String::new()),
|
|
||||||
map(
|
map(
|
||||||
tuple((
|
tuple((
|
||||||
char('"'),
|
char('"'),
|
||||||
escaped_transform(none_of(r#""\"#), '\\', string_escape_transforms),
|
escaped_transform(none_of(r#""\"#), '\\', string_escape_transforms),
|
||||||
char('"'),
|
char('"'),
|
||||||
)), |(_, s, _)| s)))(input)
|
)),
|
||||||
|
|(_, s, _)| s,
|
||||||
|
),
|
||||||
|
))(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> {
|
||||||
|
@ -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)]
|
||||||
|
@ -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"),
|
||||||
|
Loading…
Reference in New Issue
Block a user