Skip to content

Commit

Permalink
Replace DelimItem Vectors with SepList
Browse files Browse the repository at this point in the history
Introduces a new type for managing lists of seprated items. Instead of
having a `Vec<DelimItem<Expression>>` we can now just have a
`SepList<Expression>`. The plan is that later tranformations can more
easily index in and find separators and items.
  • Loading branch information
iwillspeak committed Aug 16, 2020
1 parent c1fef2f commit e957db5
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 151 deletions.
4 changes: 2 additions & 2 deletions spec/fail/badcalls.ulg
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ foo(100, '', 100) # !> Too many arguments to call
foo(false, '', 100) # !> Too many arguments to call
foo(100, '', '', false) # !> Too many arguments to call

foo(100, 100) # !> 12:7:error: Invalid argument. Expected 'String' but found 'Number'
foo(100, 100) # !> 12:9:error: Invalid argument. Expected 'String' but found 'Number'

# !> 16:4:error: Invalid argument. Expected 'Number' but found 'String'
# !> 16:11:error: Invalid argument. Expected 'String' but found 'Bool'
# !> 16:13:error: Invalid argument. Expected 'String' but found 'Bool'
foo('hello', false)

let bar = 100
Expand Down
8 changes: 6 additions & 2 deletions spec/malformed/invalid_calls.ulg
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,9 @@ end
# !> 6:4:error: unexpected token: expected expression but found ','
foo(,)

# !> 9:15:error: unexpected token: expected expression but found ')'
foo(100, false,)
# it's OK to have a trailing `,`
foo(100, false,)

# don't go nuts though...
# !> 13:15:error: unexpected token: expected expression but found ','
foo(969, true, ,)
4 changes: 1 addition & 3 deletions src/sem/binder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,6 @@ impl Binder {
.iter()
.map(|param| {
param
.as_inner()
.typ
.as_ref()
.map(|t| self.bind_type(&t.type_ref))
Expand Down Expand Up @@ -501,7 +500,7 @@ impl Binder {
.iter()
.zip(param_tys)
.map(|(arg, param)| {
let bound_arg = self.bind_expression(arg.as_inner(), source);
let bound_arg = self.bind_expression(arg, source);
if bound_arg.typ != param {
self.diagnostics.push(Diagnostic::new(
format!(
Expand Down Expand Up @@ -616,7 +615,6 @@ impl Binder {
.params
.iter()
.map(|p| {
let p = p.as_inner();
let ty = match p.typ.as_ref() {
Some(anno) => self.bind_type(&anno.type_ref),
None => {
Expand Down
25 changes: 12 additions & 13 deletions src/syntax/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ mod tokeniser;
mod checkparse_tests;

use super::text::{Ident, SourceText, DUMMY_SPAN};
use super::tree::{Literal, SyntaxTree, Token, TokenKind};
use super::{
BlockBody, DelimItem, Expression, InfixOp, PrefixOp, TypeAnno, TypeRef, TypedId, VarStyle,
};
use super::tree::{Literal, SepList, SyntaxTree, Token, TokenKind};
use super::{BlockBody, Expression, InfixOp, PrefixOp, TypeAnno, TypeRef, TypedId, VarStyle};
use crate::diag::Diagnostic;
use std::iter::Iterator;
use tokeniser::{TokenStream, Tokeniser};
Expand Down Expand Up @@ -401,27 +399,28 @@ impl<'a> Parser<'a> {
/// Returns a list of zero or more elemnets delimited by the given
/// tokens. Used to parse the parameter list for a function and
/// the argument list for a call site.
fn delimited<P, T>(&mut self, p: P, delimiter: TokenKind, close: TokenKind) -> Vec<DelimItem<T>>
fn delimited<P, T>(&mut self, p: P, delimiter: TokenKind, close: TokenKind) -> SepList<T>
where
P: Fn(&mut Parser) -> T,
{
let mut res = Vec::new();
if !self.current_is(&close) {
res.push(DelimItem::First(p(self)));
}
let mut builder = SepList::builder();
let mut last_span = self.current.as_ref().map(|t| t.span());
while !self.current_is(&close) {
let delim = self.expect(&delimiter);
res.push(DelimItem::Follow(delim, p(self)));
let with_item = builder.push_item(p(self));
if !self.current_is(&close) {
builder = with_item.push_sep(self.expect(&delimiter));
} else {
return with_item.build();
}

let cur_span = self.current.as_ref().map(|t| t.span());
let cur_span = self.current.as_ref().map(|t| t.span());
if cur_span.is_some() && last_span == cur_span {
break;
} else {
last_span = cur_span;
}
}
res
builder.build()
}

/// Parse Null Denotation
Expand Down
143 changes: 68 additions & 75 deletions src/syntax/parse/checkparse_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ fn parse_simple_call() {
check_parse!("foo()", |s| Expression::call(
mk_ident(&s, "foo"),
Token::new(TokenKind::OpenBracket),
Vec::new(),
SepList::empty(),
Token::new(TokenKind::CloseBracket)
));
}
Expand All @@ -225,32 +225,25 @@ fn parse_complex_call() {
check_parse!("hello(1, 1 + 23, -world)", |s| Expression::call(
mk_ident(&s, "hello"),
Token::new(TokenKind::OpenBracket),
vec![
DelimItem::First(Expression::constant_num(
SepList::builder()
.push_item(Expression::constant_num(
Token::new(TokenKind::Literal(Literal::Number(1))),
1
)),
DelimItem::Follow(
Token::new(TokenKind::Comma),
Expression::infix(
Expression::constant_num(Token::new(TokenKind::Literal(Literal::Number(1))), 1),
Token::new(TokenKind::Plus),
InfixOp::Add,
Expression::constant_num(
Token::new(TokenKind::Literal(Literal::Number(23))),
23
),
)
),
DelimItem::Follow(
Token::new(TokenKind::Comma),
Expression::prefix(
Token::new(TokenKind::Minus),
PrefixOp::Negate,
mk_ident(&s, "world"),
)
),
],
))
.push_sep(Token::new(TokenKind::Comma))
.push_item(Expression::infix(
Expression::constant_num(Token::new(TokenKind::Literal(Literal::Number(1))), 1),
Token::new(TokenKind::Plus),
InfixOp::Add,
Expression::constant_num(Token::new(TokenKind::Literal(Literal::Number(23))), 23),
))
.push_sep(Token::new(TokenKind::Comma))
.push_item(Expression::prefix(
Token::new(TokenKind::Minus),
PrefixOp::Negate,
mk_ident(&s, "world"),
))
.build(),
Token::new(TokenKind::CloseBracket),
));
}
Expand Down Expand Up @@ -287,21 +280,19 @@ fn parse_indexing() {
Token::new(TokenKind::CloseSqBracket)
),
Token::new(TokenKind::OpenBracket),
vec![
DelimItem::First(Expression::constant_num(
SepList::builder()
.push_item(Expression::constant_num(
Token::new(TokenKind::Literal(Literal::Number(1))),
1
)),
DelimItem::Follow(
Token::new(TokenKind::Comma),
Expression::index(
Expression::constant_num(Token::new(TokenKind::Literal(Literal::Number(2))), 2),
Token::new(TokenKind::OpenSqBracket),
Expression::constant_num(Token::new(TokenKind::Literal(Literal::Number(3))), 3),
Token::new(TokenKind::CloseSqBracket)
)
),
],
))
.push_sep(Token::new(TokenKind::Comma))
.push_item(Expression::index(
Expression::constant_num(Token::new(TokenKind::Literal(Literal::Number(2))), 2),
Token::new(TokenKind::OpenSqBracket),
Expression::constant_num(Token::new(TokenKind::Literal(Literal::Number(3))), 3),
Token::new(TokenKind::CloseSqBracket)
))
.build(),
Token::new(TokenKind::CloseBracket),
));
}
Expand All @@ -327,10 +318,12 @@ fn parse_ternary_if() {
Expression::call(
mk_ident(&s, "hello"),
Token::new(TokenKind::OpenBracket),
vec![DelimItem::First(Expression::constant_num(
Token::new(TokenKind::Literal(Literal::Number(1))),
1,
))],
SepList::builder()
.push_item(Expression::constant_num(
Token::new(TokenKind::Literal(Literal::Number(1))),
1,
))
.build(),
Token::new(TokenKind::CloseBracket),
),
Token::new(TokenKind::Word(s.intern("else"))),
Expand Down Expand Up @@ -376,7 +369,7 @@ fn parse_function_def() {
Token::new(TokenKind::Word(s.intern("fn"))),
s.intern("test"),
Token::new(TokenKind::OpenBracket),
Vec::new(),
SepList::empty(),
Token::new(TokenKind::CloseBracket),
mk_simple_ty_anno(&s, "Num"),
blockify(vec![Expression::constant_num(
Expand All @@ -392,7 +385,7 @@ fn parse_function_def() {
Token::new(TokenKind::Word(s.intern("fn"))),
s.intern("ünécød3"),
Token::new(TokenKind::OpenBracket),
Vec::new(),
SepList::empty(),
Token::new(TokenKind::CloseBracket),
mk_simple_ty_anno(&s, "Num"),
blockify(vec![Expression::if_then_else(
Expand Down Expand Up @@ -429,10 +422,12 @@ fn parse_function_with_args() {
Token::new(TokenKind::Word(s.intern("fn"))),
s.intern("neg"),
Token::new(TokenKind::OpenBracket),
vec![DelimItem::First(TypedId::new(
Token::new(TokenKind::Word(s.intern("i"))),
mk_simple_ty_anno(&s, "Num")
))],
SepList::builder()
.push_item(TypedId::new(
Token::new(TokenKind::Word(s.intern("i"))),
mk_simple_ty_anno(&s, "Num")
))
.build(),
Token::new(TokenKind::CloseBracket),
mk_simple_ty_anno(&s, "Num"),
blockify(vec![Expression::prefix(
Expand All @@ -447,23 +442,21 @@ fn parse_function_with_args() {
Token::new(TokenKind::Word(s.intern("fn"))),
s.intern("test"),
Token::new(TokenKind::OpenBracket),
vec![
DelimItem::First(TypedId::new(
SepList::builder()
.push_item(TypedId::new(
Token::new(TokenKind::Word(s.intern("i"))),
mk_simple_ty_anno(&s, "Num"),
)),
DelimItem::Follow(
Token::new(TokenKind::Comma),
TypedId::new_without_type(Token::new(TokenKind::Word(s.intern("j")))),
),
DelimItem::Follow(
Token::new(TokenKind::Comma),
TypedId::new(
Token::new(TokenKind::Word(s.intern("k"))),
mk_simple_ty_anno(&s, "String"),
),
),
],
))
.push_sep(Token::new(TokenKind::Comma))
.push_item(TypedId::new_without_type(Token::new(TokenKind::Word(
s.intern("j"),
))))
.push_sep(Token::new(TokenKind::Comma))
.push_item(TypedId::new(
Token::new(TokenKind::Word(s.intern("k"))),
mk_simple_ty_anno(&s, "String"),
))
.build(),
Token::new(TokenKind::CloseBracket),
mk_simple_ty_anno(&s, "String"),
blockify(vec![Expression::infix(
Expand Down Expand Up @@ -523,7 +516,9 @@ fn parse_simple_tuple() {
Token::new(TokenKind::Colon),
TypeRef::tuple(
Token::new(TokenKind::OpenBracket),
vec![DelimItem::First(mk_simple_ty(&s, "Num"))],
SepList::builder()
.push_item(mk_simple_ty(&s, "Num"))
.build(),
Token::new(TokenKind::CloseBracket)
)
)),
Expand All @@ -540,17 +535,15 @@ fn parse_simple_tuple() {
Token::new(TokenKind::Colon),
TypeRef::tuple(
Token::new(TokenKind::OpenBracket),
vec![
DelimItem::First(mk_simple_ty(&s, "Num")),
DelimItem::Follow(
Token::new(TokenKind::Comma),
TypeRef::array(
Token::new(TokenKind::OpenSqBracket),
mk_simple_ty(&s, "String"),
Token::new(TokenKind::CloseSqBracket)
)
),
],
SepList::builder()
.push_item(mk_simple_ty(&s, "Num"))
.push_sep(Token::new(TokenKind::Comma))
.push_item(TypeRef::array(
Token::new(TokenKind::OpenSqBracket),
mk_simple_ty(&s, "String"),
Token::new(TokenKind::CloseSqBracket)
))
.build(),
Token::new(TokenKind::CloseBracket)
)
)),
Expand Down
14 changes: 8 additions & 6 deletions src/syntax/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
pub mod expression;
pub mod operators;
mod seplist;
mod token;
mod trivia;
pub mod types;
Expand All @@ -16,11 +17,12 @@ use crate::diag::Diagnostic;
use crate::parse::Parser;
use crate::text::SourceText;

pub use self::seplist::{SepList, SepListBuilder};
pub use self::token::{Literal, Token, TokenKind};
pub use self::trivia::{TriviaToken, TriviaTokenKind};

use self::expression::Expression;
use super::SyntaxNode;
use expression::Expression;

/// Syntax tree
///
Expand All @@ -46,12 +48,12 @@ impl<'a> SyntaxTree<'a> {
/// # Parameters
///
/// * `root`: The body of the file. This could be an empty
/// sequence if the file is empty
/// sequence if the file is empty
/// * `diagnostics`: Diagnostics raised in the parsing of the
/// source.
/// source.
/// * `end`: The closing EOF token. This may have some leading
/// trivia attached and is therefore required for a full-fidelity
/// tree.
/// trivia attached and is therefore required for a
/// full-fidelity tree.
pub fn new(
source: &'a SourceText,
root: Expression,
Expand Down Expand Up @@ -144,7 +146,7 @@ where
Expression::Prefix(p) => vec![&p.inner],
Expression::Infix(i) => vec![&i.left, &i.right],
Expression::Call(c) => std::iter::once(&*c.callee)
.chain(c.arguments.iter().map(|a| a.as_inner()))
.chain(c.arguments.iter())
.collect(),
Expression::Index(i) => vec![&i.index, &i.indexee],
Expression::IfThenElse(i) => vec![&i.cond, &i.if_true, &i.if_false],
Expand Down
Loading

0 comments on commit e957db5

Please sign in to comment.