Compare commits

..

No commits in common. "de741448e0825bf32a4119270e0ae910a889239d" and "1c6545fb7451210caaf73e00c4e9f193b60b6074" have entirely different histories.

9 changed files with 1089 additions and 1199 deletions

View File

@ -196,7 +196,6 @@ pub enum ExpressionKind {
WhileExpression { condition: Option<Box<Expression>>, body: Block }, WhileExpression { condition: Option<Box<Expression>>, body: Block },
ForExpression { enumerators: Vec<Enumerator>, body: Box<ForBody> }, ForExpression { enumerators: Vec<Enumerator>, body: Box<ForBody> },
Lambda { params: Vec<FormalParam>, type_anno: Option<TypeIdentifier>, body: Block }, Lambda { params: Vec<FormalParam>, type_anno: Option<TypeIdentifier>, body: Block },
Access { name: Rc<String>, expr: Box<Expression> },
ListLiteral(Vec<Expression>), ListLiteral(Vec<Expression>),
} }

View File

@ -128,9 +128,6 @@ pub fn walk_expression<V: ASTVisitor>(v: &mut V, expr: &Expression) {
Lambda { params: _, type_anno: _, body } => { Lambda { params: _, type_anno: _, body } => {
walk_block(v, body); walk_block(v, body);
} }
Access { name: _, expr } => {
walk_expression(v, expr);
}
ListLiteral(exprs) => ListLiteral(exprs) =>
for expr in exprs { for expr in exprs {
walk_expression(v, expr); walk_expression(v, expr);

View File

@ -120,7 +120,6 @@ fn render_expression(expr: &Expression, indent: usize, buf: &mut String) {
newline(buf); newline(buf);
do_indent(indent, buf); do_indent(indent, buf);
} }
Access { .. } => buf.push_str("<access-expr>"),
ListLiteral(..) => buf.push_str("<list-literal>"), ListLiteral(..) => buf.push_str("<list-literal>"),
} }
buf.push(')'); buf.push(')');

View File

@ -166,28 +166,29 @@
//! //!
//! module := 'module' IDENTIFIER '{' statement* '}' //! module := 'module' IDENTIFIER '{' statement* '}'
//! ``` //! ```
mod new_tests;
mod test; mod test;
mod new_tests;
use std::rc::Rc; use std::rc::Rc;
use crate::{ use crate::tokenizing::*;
ast::*, use crate::tokenizing::Kw::*;
identifier::IdStore, use crate::tokenizing::TokenKind::*;
tokenizing::{Kw::*, Location, TokenKind::*, *}, use crate::tokenizing::Location;
};
use crate::ast::*;
use crate::identifier::IdStore;
/// Represents a parsing error /// Represents a parsing error
#[derive(Debug)] #[derive(Debug)]
pub struct ParseError { pub struct ParseError {
pub production_name: Option<String>, pub production_name: Option<String>,
pub msg: String, pub msg: String,
pub token: Token, pub token: Token
} }
impl ParseError { impl ParseError {
fn new_with_token<T, M>(msg: M, token: Token) -> ParseResult<T> fn new_with_token<T, M>(msg: M, token: Token) -> ParseResult<T> where M: Into<String> {
where M: Into<String> {
Err(ParseError { msg: msg.into(), token, production_name: None }) Err(ParseError { msg: msg.into(), token, production_name: None })
} }
} }
@ -211,20 +212,21 @@ pub struct Parser {
id_store: IdStore<ASTItem>, id_store: IdStore<ASTItem>,
} }
struct ParserRestrictions { struct ParserRestrictions {
no_struct_literal: bool, no_struct_literal: bool
} }
struct TokenHandler { struct TokenHandler {
tokens: Vec<Token>, tokens: Vec<Token>,
idx: usize, idx: usize,
end_of_file: Location, end_of_file: Location
} }
impl TokenHandler { impl TokenHandler {
fn new(tokens: Vec<Token>) -> TokenHandler { fn new(tokens: Vec<Token>) -> TokenHandler {
let end_of_file = match tokens.last() { let end_of_file = match tokens.last() {
None => Location { line_num: 0, char_num: 0 }, None => Location { line_num: 0, char_num : 0 },
Some(t) => t.location, Some(t) => t.location,
}; };
TokenHandler { idx: 0, tokens, end_of_file } TokenHandler { idx: 0, tokens, end_of_file }
@ -238,24 +240,15 @@ impl TokenHandler {
self.peek_n(n).kind self.peek_n(n).kind
} }
fn peek(&mut self) -> Token { fn peek(&mut self) -> Token {
self.tokens self.tokens.get(self.idx).cloned().unwrap_or(Token { kind: TokenKind::EOF, location: self.end_of_file })
.get(self.idx)
.cloned()
.unwrap_or(Token { kind: TokenKind::EOF, location: self.end_of_file })
} }
/// calling peek_n(0) is the same thing as peek() /// calling peek_n(0) is the same thing as peek()
fn peek_n(&mut self, n: usize) -> Token { fn peek_n(&mut self, n: usize) -> Token {
self.tokens self.tokens.get(self.idx + n).cloned().unwrap_or(Token { kind: TokenKind::EOF, location: self.end_of_file })
.get(self.idx + n)
.cloned()
.unwrap_or(Token { kind: TokenKind::EOF, location: self.end_of_file })
} }
fn next(&mut self) -> Token { fn next(&mut self) -> Token {
self.idx += 1; self.idx += 1;
self.tokens self.tokens.get(self.idx - 1).cloned().unwrap_or(Token { kind: TokenKind::EOF, location: self.end_of_file })
.get(self.idx - 1)
.cloned()
.unwrap_or(Token { kind: TokenKind::EOF, location: self.end_of_file })
} }
} }
@ -303,9 +296,7 @@ impl Parser {
} }
macro_rules! print_token_pattern { macro_rules! print_token_pattern {
($tokenpattern:pat) => { ($tokenpattern:pat) => { stringify!($tokenpattern) }
stringify!($tokenpattern)
};
} }
macro_rules! expect { macro_rules! expect {
@ -331,7 +322,8 @@ macro_rules! delimited {
($self:expr, $start:pat, $parse_fn:ident, $delim:pat, $end:pat) => { ($self:expr, $start:pat, $parse_fn:ident, $delim:pat, $end:pat) => {
delimited!($self, $start, $parse_fn, $delim, $end, true) delimited!($self, $start, $parse_fn, $delim, $end, true)
}; };
($self:expr, $start:pat, $parse_fn:ident, $delim:pat, $end:pat, $strictness:expr) => {{ ($self:expr, $start:pat, $parse_fn:ident, $delim:pat, $end:pat, $strictness:expr) => {
{
expect!($self, $start); expect!($self, $start);
let mut acc = vec![]; let mut acc = vec![];
loop { loop {
@ -339,35 +331,30 @@ macro_rules! delimited {
match peek.get_kind() { match peek.get_kind() {
$end | EOF => break, $end | EOF => break,
Newline | Semicolon => { Newline | Semicolon => {
$self.token_handler.next(); $self.token_handler.next(); continue;
continue; },
}
_ => (), _ => (),
} }
if !$strictness { if !$strictness {
match peek.get_kind() { match peek.get_kind() {
$delim => { $delim => { $self.token_handler.next(); continue },
$self.token_handler.next(); _ => ()
continue;
}
_ => (),
} }
} }
acc.push($self.$parse_fn()?); acc.push($self.$parse_fn()?);
match $self.token_handler.peek().get_kind() { match $self.token_handler.peek().get_kind() {
$delim => { $delim => { $self.token_handler.next(); continue },
$self.token_handler.next();
continue;
}
_ if $strictness => break, _ if $strictness => break,
_ => continue, _ => continue,
}; };
} }
expect!($self, $end); expect!($self, $end);
acc acc
}}; }
};
} }
impl Parser { impl Parser {
/// `program := (statement delimiter)* EOF` /// `program := (statement delimiter)* EOF`
/// `delimiter := NEWLINE | ';'` /// `delimiter := NEWLINE | ';'`
@ -380,8 +367,10 @@ impl Parser {
Newline | Semicolon => { Newline | Semicolon => {
self.token_handler.next(); self.token_handler.next();
continue; continue;
} },
_ => statements.push(self.statement()?), _ => statements.push(
self.statement()?
),
} }
} }
Ok(AST { id: self.id_store.fresh(), statements: statements.into() }) Ok(AST { id: self.id_store.fresh(), statements: statements.into() })
@ -394,19 +383,20 @@ impl Parser {
let tok = self.token_handler.peek(); let tok = self.token_handler.peek();
let kind = match tok.get_kind() { let kind = match tok.get_kind() {
AtSign => self.annotation().map(StatementKind::Declaration), AtSign => self.annotation().map(StatementKind::Declaration),
Keyword(Type) => self.type_declaration().map(|decl| StatementKind::Declaration(decl)), Keyword(Type) => self.type_declaration().map(|decl| { StatementKind::Declaration(decl) }),
Keyword(Func) => self.func_declaration().map(|func| StatementKind::Declaration(func)), Keyword(Func)=> self.func_declaration().map(|func| { StatementKind::Declaration(func) }),
Keyword(Let) => self.binding_declaration().map(StatementKind::Declaration), Keyword(Let) => self.binding_declaration().map(StatementKind::Declaration),
Keyword(Interface) => self.interface_declaration().map(StatementKind::Declaration), Keyword(Interface) => self.interface_declaration().map(StatementKind::Declaration),
Keyword(Impl) => self.impl_declaration().map(StatementKind::Declaration), Keyword(Impl) => self.impl_declaration().map(StatementKind::Declaration),
Keyword(Import) => self.import_declaration().map(StatementKind::Import), Keyword(Import) => self.import_declaration().map(StatementKind::Import),
Keyword(Module) => self.module_declaration().map(StatementKind::Module), Keyword(Module) => self.module_declaration().map(StatementKind::Module),
_ => self.expression().map(|expr| StatementKind::Expression(expr)), _ => self.expression().map(|expr| { StatementKind::Expression(expr) } ),
}?; }?;
let id = self.id_store.fresh(); let id = self.id_store.fresh();
Ok(Statement { kind, id, location: tok.location }) Ok(Statement { kind, id, location: tok.location })
} }
#[recursive_descent_method] #[recursive_descent_method]
fn annotation(&mut self) -> ParseResult<Declaration> { fn annotation(&mut self) -> ParseResult<Declaration> {
expect!(self, AtSign); expect!(self, AtSign);
@ -417,7 +407,10 @@ impl Parser {
vec![] vec![]
}; };
Ok(Declaration::Annotation { name, arguments }) Ok(Declaration::Annotation {
name,
arguments,
})
} }
#[recursive_descent_method] #[recursive_descent_method]
@ -440,7 +433,7 @@ impl Parser {
let name = self.type_singleton_name()?; let name = self.type_singleton_name()?;
expect!(self, Equals); expect!(self, Equals);
let body = self.type_body()?; let body = self.type_body()?;
Ok(Declaration::TypeDecl { name, body, mutable }) Ok(Declaration::TypeDecl { name, body, mutable})
} }
} }
@ -470,16 +463,19 @@ impl Parser {
LParen => { LParen => {
let tuple_members = delimited!(self, LParen, type_name, Comma, RParen); let tuple_members = delimited!(self, LParen, type_name, Comma, RParen);
VariantKind::TupleStruct(tuple_members) VariantKind::TupleStruct(tuple_members)
} },
LCurlyBrace => { LCurlyBrace => {
println!("ARAH"); println!("ARAH");
let typed_identifier_list = let typed_identifier_list = delimited!(self, LCurlyBrace, typed_identifier, Comma, RCurlyBrace);
delimited!(self, LCurlyBrace, typed_identifier, Comma, RCurlyBrace);
VariantKind::Record(typed_identifier_list) VariantKind::Record(typed_identifier_list)
} },
_ => VariantKind::UnitStruct, _ => VariantKind::UnitStruct
}; };
Ok(Variant { id: self.id_store.fresh(), name, kind }) Ok(Variant {
id: self.id_store.fresh(),
name,
kind
})
} }
#[recursive_descent_method] #[recursive_descent_method]
@ -509,8 +505,8 @@ impl Parser {
let name = s; let name = s;
self.token_handler.next(); self.token_handler.next();
(name, true) (name, true)
} },
_ => (self.identifier()?, false), _ => (self.identifier()?, false)
}; };
let params = self.formal_param_list()?; let params = self.formal_param_list()?;
let type_anno = match self.token_handler.peek_kind() { let type_anno = match self.token_handler.peek_kind() {
@ -522,8 +518,7 @@ impl Parser {
#[recursive_descent_method] #[recursive_descent_method]
fn nonempty_func_body(&mut self) -> ParseResult<Vec<Statement>> { fn nonempty_func_body(&mut self) -> ParseResult<Vec<Statement>> {
let statements = let statements = delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict);
delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict);
Ok(statements) Ok(statements)
} }
@ -537,14 +532,14 @@ impl Parser {
let name = self.identifier()?; let name = self.identifier()?;
let anno = match self.token_handler.peek_kind() { let anno = match self.token_handler.peek_kind() {
Colon => Some(self.type_anno()?), Colon => Some(self.type_anno()?),
_ => None, _ => None
}; };
let default = match self.token_handler.peek_kind() { let default = match self.token_handler.peek_kind() {
Equals => { Equals => {
self.token_handler.next(); self.token_handler.next();
Some(self.expression()?) Some(self.expression()?)
} },
_ => None, _ => None
}; };
Ok(FormalParam { name, anno, default }) Ok(FormalParam { name, anno, default })
} }
@ -557,11 +552,14 @@ impl Parser {
self.token_handler.next(); self.token_handler.next();
false false
} }
_ => true, _ => true
}; };
let name = self.identifier()?; let name = self.identifier()?;
let type_anno = let type_anno = if let Colon = self.token_handler.peek_kind() {
if let Colon = self.token_handler.peek_kind() { Some(self.type_anno()?) } else { None }; Some(self.type_anno()?)
} else {
None
};
expect!(self, Equals); expect!(self, Equals);
let expr = self.expression()?; let expr = self.expression()?;
@ -597,11 +595,8 @@ impl Parser {
Ok(match (first, second) { Ok(match (first, second) {
(interface_name, Some(type_name)) => (interface_name, Some(type_name)) =>
Declaration::Impl { type_name, interface_name: Some(interface_name), block }, Declaration::Impl { type_name, interface_name: Some(interface_name), block },
(type_singleton_name, None) => Declaration::Impl { (type_singleton_name, None) =>
type_name: TypeIdentifier::Singleton(type_singleton_name), Declaration::Impl { type_name: TypeIdentifier::Singleton(type_singleton_name), interface_name: None, block }
interface_name: None,
block,
},
}) })
} }
@ -615,7 +610,7 @@ impl Parser {
let mut expr_body = self.precedence_expr(BinOp::min_precedence())?; let mut expr_body = self.precedence_expr(BinOp::min_precedence())?;
let type_anno = match self.token_handler.peek_kind() { let type_anno = match self.token_handler.peek_kind() {
Colon => Some(self.type_anno()?), Colon => Some(self.type_anno()?),
_ => None, _ => None
}; };
if expr_body.type_anno.is_some() { if expr_body.type_anno.is_some() {
return ParseError::new_with_token("Bad parse state encountered", self.token_handler.peek()); return ParseError::new_with_token("Bad parse state encountered", self.token_handler.peek());
@ -646,7 +641,7 @@ impl Parser {
params: match self.token_handler.peek_kind() { params: match self.token_handler.peek_kind() {
LAngleBracket => delimited!(self, LAngleBracket, type_name, Comma, RAngleBracket), LAngleBracket => delimited!(self, LAngleBracket, type_name, Comma, RAngleBracket),
_ => vec![], _ => vec![],
}, }
}) })
} }
@ -675,13 +670,10 @@ impl Parser {
let operation = match BinOp::from_sigil_token(&next_tok.kind) { let operation = match BinOp::from_sigil_token(&next_tok.kind) {
Some(sigil) => sigil, Some(sigil) => sigil,
//TODO I think I can fix this unreachable //TODO I think I can fix this unreachable
None => unreachable!(), None => unreachable!()
}; };
let rhs = self.precedence_expr(new_precedence)?; let rhs = self.precedence_expr(new_precedence)?;
lhs = Expression::new( lhs = Expression::new(self.id_store.fresh(), ExpressionKind::BinExp(operation, Box::new(lhs), Box::new(rhs)));
self.id_store.fresh(),
ExpressionKind::BinExp(operation, Box::new(lhs), Box::new(rhs)),
);
} }
self.parse_level -= 1; self.parse_level -= 1;
Ok(lhs) Ok(lhs)
@ -699,10 +691,10 @@ impl Parser {
let prefix_op = PrefixOp::from_sigil(sigil.as_str()); let prefix_op = PrefixOp::from_sigil(sigil.as_str());
Ok(Expression::new( Ok(Expression::new(
self.id_store.fresh(), self.id_store.fresh(),
ExpressionKind::PrefixExp(prefix_op, Box::new(expr)), ExpressionKind::PrefixExp(prefix_op, Box::new(expr))
)) ))
} },
_ => self.extended_expr(), _ => self.extended_expr()
} }
} }
@ -713,34 +705,24 @@ impl Parser {
//TODO need a next non whitespace //TODO need a next non whitespace
let next = self.token_handler.peek_kind(); let next = self.token_handler.peek_kind();
match next { match next {
Period => { Period => unimplemented!(),
self.token_handler.next();
let name = self.identifier()?;
expression = Expression::new(
self.id_store.fresh(),
ExpressionKind::Access { name, expr: Box::new(expression) },
);
}
LSquareBracket => { LSquareBracket => {
let indexers = delimited!(self, LSquareBracket, expression, Comma, RSquareBracket); let indexers = delimited!(self, LSquareBracket, expression, Comma, RSquareBracket);
if indexers.is_empty() { if indexers.is_empty() {
return ParseError::new_with_token( return ParseError::new_with_token("Empty index expressions are not allowed", self.token_handler.peek());
"Empty index expressions are not allowed",
self.token_handler.peek(),
);
}
expression = Expression::new(
self.id_store.fresh(),
ExpressionKind::Index { indexee: Box::new(expression), indexers },
);
} }
expression = Expression::new(self.id_store.fresh(), ExpressionKind::Index {
indexee: Box::new(expression),
indexers,
});
},
LParen => { LParen => {
let arguments = delimited!(self, LParen, invocation_argument, Comma, RParen); let arguments = delimited!(self, LParen, invocation_argument, Comma, RParen);
expression = Expression::new( expression = Expression::new(self.id_store.fresh(), ExpressionKind::Call {
self.id_store.fresh(), f: Box::new(expression),
ExpressionKind::Call { f: Box::new(expression), arguments }, arguments,
); });
} },
_ => break, _ => break,
} }
} }
@ -753,20 +735,22 @@ impl Parser {
Underscore => { Underscore => {
self.token_handler.next(); self.token_handler.next();
InvocationArgument::Ignored InvocationArgument::Ignored
} },
Identifier(s) => match self.token_handler.peek_kind_n(1) { Identifier(s) => {
match self.token_handler.peek_kind_n(1) {
Equals => { Equals => {
self.token_handler.next(); self.token_handler.next();
self.token_handler.next(); self.token_handler.next();
let expr = self.expression()?; let expr = self.expression()?;
InvocationArgument::Keyword { name: s, expr } InvocationArgument::Keyword { name: s, expr }
} },
_ => { _ => {
let expr = self.expression()?; let expr = self.expression()?;
InvocationArgument::Positional(expr) InvocationArgument::Positional(expr)
} }
}
}, },
_ => InvocationArgument::Positional(self.expression()?), _ => InvocationArgument::Positional(self.expression()?)
}) })
} }
@ -776,18 +760,12 @@ impl Parser {
Ok(if let LSquareBracket = self.token_handler.peek_kind() { Ok(if let LSquareBracket = self.token_handler.peek_kind() {
let indexers = delimited!(self, LSquareBracket, expression, Comma, RSquareBracket); let indexers = delimited!(self, LSquareBracket, expression, Comma, RSquareBracket);
if indexers.is_empty() { if indexers.is_empty() {
return ParseError::new_with_token( return ParseError::new_with_token("Empty index expressions are not allowed", self.token_handler.peek());
"Empty index expressions are not allowed",
self.token_handler.peek(),
);
} }
Expression::new( Expression::new(self.id_store.fresh(), ExpressionKind::Index {
self.id_store.fresh(),
ExpressionKind::Index {
indexee: Box::new(Expression::new(self.id_store.fresh(), primary.kind)), indexee: Box::new(Expression::new(self.id_store.fresh(), primary.kind)),
indexers, indexers,
}, })
)
} else { } else {
primary primary
}) })
@ -828,8 +806,7 @@ impl Parser {
_ => None, _ => None,
}; };
let body = self.nonempty_func_body()?.into(); let body = self.nonempty_func_body()?.into();
Ok(Expression::new(self.id_store.fresh(), ExpressionKind::Lambda { params, type_anno, body })) Ok(Expression::new(self.id_store.fresh(), ExpressionKind::Lambda { params, type_anno, body })) //TODO need to handle types somehow
//TODO need to handle types somehow
} }
#[recursive_descent_method] #[recursive_descent_method]
@ -852,7 +829,7 @@ impl Parser {
match inner.len() { match inner.len() {
0 => Ok(Expression::new(self.id_store.fresh(), TupleLiteral(vec![]))), 0 => Ok(Expression::new(self.id_store.fresh(), TupleLiteral(vec![]))),
1 => Ok(inner.pop().unwrap()), 1 => Ok(inner.pop().unwrap()),
_ => Ok(Expression::new(self.id_store.fresh(), TupleLiteral(inner))), _ => Ok(Expression::new(self.id_store.fresh(), TupleLiteral(inner)))
} }
}; };
self.restrictions.no_struct_literal = old_struct_value; self.restrictions.no_struct_literal = old_struct_value;
@ -868,8 +845,8 @@ impl Parser {
LCurlyBrace if !self.restrictions.no_struct_literal => { LCurlyBrace if !self.restrictions.no_struct_literal => {
let fields = self.record_block()?; let fields = self.record_block()?;
Expression::new(self.id_store.fresh(), NamedStruct { name: qualified_identifier, fields }) Expression::new(self.id_store.fresh(), NamedStruct { name: qualified_identifier, fields })
} },
_ => Expression::new(self.id_store.fresh(), Value(qualified_identifier)), _ => Expression::new(self.id_store.fresh(), Value(qualified_identifier))
}) })
} }
@ -927,7 +904,7 @@ impl Parser {
expect!(self, Keyword(Kw::Then)); expect!(self, Keyword(Kw::Then));
let then_case = self.expr_or_block()?; let then_case = self.expr_or_block()?;
let else_case = self.else_case()?; let else_case = self.else_case()?;
Ok(IfExpressionBody::SimpleConditional { then_case, else_case }) Ok(IfExpressionBody::SimpleConditional {then_case, else_case })
} }
#[recursive_descent_method] #[recursive_descent_method]
@ -957,17 +934,11 @@ impl Parser {
loop { loop {
match self.token_handler.peek_kind() { match self.token_handler.peek_kind() {
RCurlyBrace | EOF => break, RCurlyBrace | EOF => break,
Semicolon | Newline => { Semicolon | Newline => { self.token_handler.next(); continue},
self.token_handler.next();
continue;
}
_ => { _ => {
cond_arms.push(self.cond_arm()?); cond_arms.push(self.cond_arm()?);
match self.token_handler.peek_kind() { match self.token_handler.peek_kind() {
Comma | Semicolon | Newline => { Comma | Semicolon | Newline => { self.token_handler.next(); continue; },
self.token_handler.next();
continue;
}
_ => break, _ => break,
} }
} }
@ -998,13 +969,15 @@ impl Parser {
Keyword(Kw::Is) => { Keyword(Kw::Is) => {
self.token_handler.next(); self.token_handler.next();
Condition::Pattern(self.pattern()?) Condition::Pattern(self.pattern()?)
} },
ref tok if BinOp::from_sigil_token(tok).is_some() => { ref tok if BinOp::from_sigil_token(tok).is_some() => {
let op = BinOp::from_sigil_token(&self.token_handler.next().kind).unwrap(); let op = BinOp::from_sigil_token(&self.token_handler.next().kind).unwrap();
let expr = self.expression()?; let expr = self.expression()?;
Condition::TruncatedOp(op, expr) Condition::TruncatedOp(op, expr)
} },
_ => Condition::Expression(self.expression()?), _ => {
Condition::Expression(self.expression()?)
},
}) })
} }
@ -1014,8 +987,8 @@ impl Parser {
Keyword(Kw::If) => { Keyword(Kw::If) => {
self.token_handler.next(); self.token_handler.next();
Some(self.expression()?) Some(self.expression()?)
} },
_ => None, _ => None
}) })
} }
@ -1039,15 +1012,17 @@ impl Parser {
LCurlyBrace => { LCurlyBrace => {
let members = delimited!(self, LCurlyBrace, record_pattern_entry, Comma, RCurlyBrace); let members = delimited!(self, LCurlyBrace, record_pattern_entry, Comma, RCurlyBrace);
Pattern::Record(qualified_identifier, members) Pattern::Record(qualified_identifier, members)
} },
LParen => { LParen => {
let members = delimited!(self, LParen, pattern, Comma, RParen); let members = delimited!(self, LParen, pattern, Comma, RParen);
Pattern::TupleStruct(qualified_identifier, members) Pattern::TupleStruct(qualified_identifier, members)
},
_ => {
Pattern::VarOrName(qualified_identifier)
},
} }
_ => Pattern::VarOrName(qualified_identifier), },
} _ => self.pattern_literal()?
}
_ => self.pattern_literal()?,
}) })
} }
@ -1058,22 +1033,22 @@ impl Parser {
Keyword(Kw::True) => { Keyword(Kw::True) => {
self.token_handler.next(); self.token_handler.next();
Pattern::Literal(PatternLiteral::BoolPattern(true)) Pattern::Literal(PatternLiteral::BoolPattern(true))
} },
Keyword(Kw::False) => { Keyword(Kw::False) => {
self.token_handler.next(); self.token_handler.next();
Pattern::Literal(PatternLiteral::BoolPattern(false)) Pattern::Literal(PatternLiteral::BoolPattern(false))
} },
StrLiteral { s, .. } => { StrLiteral { s, .. } => {
self.token_handler.next(); self.token_handler.next();
Pattern::Literal(PatternLiteral::StringPattern(s)) Pattern::Literal(PatternLiteral::StringPattern(s))
} },
DigitGroup(_) | HexLiteral(_) | BinNumberSigil | Period => self.signed_number_literal()?, DigitGroup(_) | HexLiteral(_) | BinNumberSigil | Period => self.signed_number_literal()?,
Operator(ref op) if **op == "-" => self.signed_number_literal()?, Operator(ref op) if **op == "-" => self.signed_number_literal()?,
Underscore => { Underscore => {
self.token_handler.next(); self.token_handler.next();
Pattern::Ignored Pattern::Ignored
} },
other => return ParseError::new_with_token(format!("{:?} is not a valid Pattern", other), tok), other => return ParseError::new_with_token(format!("{:?} is not a valid Pattern", other), tok)
}) })
} }
@ -1083,8 +1058,8 @@ impl Parser {
Operator(ref op) if **op == "-" => { Operator(ref op) if **op == "-" => {
self.token_handler.next(); self.token_handler.next();
true true
} },
_ => false, _ => false
}; };
let Expression { kind, .. } = self.number_literal()?; let Expression { kind, .. } = self.number_literal()?;
Ok(Pattern::Literal(PatternLiteral::NumPattern { neg, num: kind })) Ok(Pattern::Literal(PatternLiteral::NumPattern { neg, num: kind }))
@ -1098,8 +1073,8 @@ impl Parser {
expect!(self, Colon); expect!(self, Colon);
let pat = self.pattern()?; let pat = self.pattern()?;
(name, pat) (name, pat)
} },
_ => (name.clone(), Pattern::Literal(PatternLiteral::StringPattern(name))), _ => (name.clone(), Pattern::Literal(PatternLiteral::StringPattern(name)))
}) })
} }
@ -1116,11 +1091,7 @@ impl Parser {
LCurlyBrace => self.block(), LCurlyBrace => self.block(),
_ => { _ => {
let expr = self.expression()?; let expr = self.expression()?;
let s = Statement { let s = Statement { id: self.id_store.fresh(), location: tok.location, kind: StatementKind::Expression(expr) };
id: self.id_store.fresh(),
location: tok.location,
kind: StatementKind::Expression(expr),
};
Ok(s.into()) Ok(s.into())
} }
} }
@ -1137,7 +1108,7 @@ impl Parser {
x?.map(Box::new) x?.map(Box::new)
}; };
let body = self.block()?; let body = self.block()?;
Ok(Expression::new(self.id_store.fresh(), WhileExpression { condition, body })) Ok(Expression::new(self.id_store.fresh(), WhileExpression {condition, body}))
} }
#[recursive_descent_method] #[recursive_descent_method]
@ -1180,14 +1151,13 @@ impl Parser {
let tok = self.token_handler.peek(); let tok = self.token_handler.peek();
Ok(match tok.get_kind() { Ok(match tok.get_kind() {
LCurlyBrace => { LCurlyBrace => {
let statements = let statements = delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict);
delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict);
StatementBlock(statements.into()) StatementBlock(statements.into())
} },
Keyword(Kw::Return) => { Keyword(Kw::Return) => {
self.token_handler.next(); self.token_handler.next();
MonadicReturn(self.expression()?) MonadicReturn(self.expression()?)
} },
_ => return ParseError::new_with_token("for expressions must end in a block or 'return'", tok), _ => return ParseError::new_with_token("for expressions must end in a block or 'return'", tok),
}) })
} }
@ -1212,13 +1182,13 @@ impl Parser {
self.token_handler.next(); self.token_handler.next();
let id = self.id_store.fresh(); let id = self.id_store.fresh();
Ok(Expression::new(id, BoolLiteral(true))) Ok(Expression::new(id, BoolLiteral(true)))
} },
Keyword(Kw::False) => { Keyword(Kw::False) => {
self.token_handler.next(); self.token_handler.next();
let id = self.id_store.fresh(); let id = self.id_store.fresh();
Ok(Expression::new(id, BoolLiteral(false))) Ok(Expression::new(id, BoolLiteral(false)))
} },
StrLiteral { s, .. } => { StrLiteral {s, ..} => {
self.token_handler.next(); self.token_handler.next();
let id = self.id_store.fresh(); let id = self.id_store.fresh();
Ok(Expression::new(id, StringLiteral(s))) Ok(Expression::new(id, StringLiteral(s)))
@ -1244,12 +1214,12 @@ impl Parser {
let digits = self.digits()?; let digits = self.digits()?;
let n = parse_binary(digits, tok)?; let n = parse_binary(digits, tok)?;
Ok(Expression::new(self.id_store.fresh(), NatLiteral(n))) Ok(Expression::new(self.id_store.fresh(), NatLiteral(n)))
} },
HexLiteral(text) => { HexLiteral(text) => {
let digits: String = text.chars().filter(|c| c.is_digit(16)).collect(); let digits: String = text.chars().filter(|c| c.is_digit(16)).collect();
let n = parse_hex(digits, tok)?; let n = parse_hex(digits, tok)?;
Ok(Expression::new(self.id_store.fresh(), NatLiteral(n))) Ok(Expression::new(self.id_store.fresh(), NatLiteral(n)))
} },
_ => return ParseError::new_with_token("Expected '0x' or '0b'", tok), _ => return ParseError::new_with_token("Expected '0x' or '0b'", tok),
} }
} }
@ -1266,12 +1236,12 @@ impl Parser {
match digits.parse::<f64>() { match digits.parse::<f64>() {
Ok(f) => Ok(Expression::new(self.id_store.fresh(), FloatLiteral(f))), Ok(f) => Ok(Expression::new(self.id_store.fresh(), FloatLiteral(f))),
Err(e) => ParseError::new_with_token(format!("Float failed to parse with error: {}", e), tok), Err(e) => ParseError::new_with_token(format!("Float failed to parse with error: {}", e), tok),
} }
} else { } else {
match digits.parse::<u64>() { match digits.parse::<u64>() {
Ok(d) => Ok(Expression::new(self.id_store.fresh(), NatLiteral(d))), Ok(d) => Ok(Expression::new(self.id_store.fresh(), NatLiteral(d))),
Err(e) => Err(e) => ParseError::new_with_token(format!("Integer failed to parse with error: {}", e), tok),
ParseError::new_with_token(format!("Integer failed to parse with error: {}", e), tok),
} }
} }
} }
@ -1281,14 +1251,8 @@ impl Parser {
let mut ds = String::new(); let mut ds = String::new();
loop { loop {
match self.token_handler.peek_kind() { match self.token_handler.peek_kind() {
Underscore => { Underscore => { self.token_handler.next(); continue; },
self.token_handler.next(); DigitGroup(ref s) => { self.token_handler.next(); ds.push_str(s)},
continue;
}
DigitGroup(ref s) => {
self.token_handler.next();
ds.push_str(s)
}
_ => break, _ => break,
} }
} }
@ -1314,15 +1278,19 @@ impl Parser {
LCurlyBrace => { LCurlyBrace => {
let names = delimited!(self, LCurlyBrace, identifier, Comma, RCurlyBrace); let names = delimited!(self, LCurlyBrace, identifier, Comma, RCurlyBrace);
ImportedNames::List(names) ImportedNames::List(names)
} },
Operator(ref s) if **s == "*" => { Operator(ref s) if **s == "*" => {
self.token_handler.next(); self.token_handler.next();
ImportedNames::All ImportedNames::All
} },
_ => ImportedNames::LastOfPath, _ => ImportedNames::LastOfPath
}; };
Ok(ImportSpecifier { id: self.id_store.fresh(), path_components, imported_names }) Ok(ImportSpecifier {
id: self.id_store.fresh(),
path_components,
imported_names
})
} }
#[recursive_descent_method] #[recursive_descent_method]
@ -1331,11 +1299,11 @@ impl Parser {
Operator(ref s) if **s == "*" => { Operator(ref s) if **s == "*" => {
self.token_handler.next(); self.token_handler.next();
ImportedNames::All ImportedNames::All
} },
LCurlyBrace => { LCurlyBrace => {
let names = delimited!(self, LCurlyBrace, identifier, Comma, RCurlyBrace); let names = delimited!(self, LCurlyBrace, identifier, Comma, RCurlyBrace);
ImportedNames::List(names) ImportedNames::List(names)
} },
_ => return ParseError::new_with_token("Expected '{{' or '*'", self.token_handler.peek()), _ => return ParseError::new_with_token("Expected '{{' or '*'", self.token_handler.peek()),
}) })
} }
@ -1356,15 +1324,11 @@ fn parse_binary(digits: String, tok: Token) -> ParseResult<u64> {
match d { match d {
'1' => result += multiplier, '1' => result += multiplier,
'0' => (), '0' => (),
_ => _ => return ParseError::new_with_token("Encountered a character not '1' or '0 while parsing a binary literal", tok),
return ParseError::new_with_token(
"Encountered a character not '1' or '0 while parsing a binary literal",
tok,
),
} }
multiplier = match multiplier.checked_mul(2) { multiplier = match multiplier.checked_mul(2) {
Some(m) => m, Some(m) => m,
None => return ParseError::new_with_token("This binary expression will overflow", tok), None => return ParseError::new_with_token("This binary expression will overflow", tok)
} }
} }
Ok(result) Ok(result)
@ -1380,8 +1344,9 @@ fn parse_hex(digits: String, tok: Token) -> ParseResult<u64> {
} }
multiplier = match multiplier.checked_mul(16) { multiplier = match multiplier.checked_mul(16) {
Some(m) => m, Some(m) => m,
None => return ParseError::new_with_token("This hex expression will overflow", tok), None => return ParseError::new_with_token("This hex expression will overflow", tok)
} }
} }
Ok(result) Ok(result)
} }

View File

@ -203,36 +203,11 @@ fn operators() {
#[test] #[test]
fn accessors() { fn accessors() {
use ExpressionKind::*; /*
assert_expr!("a.b");
assert_expr!("a.b", expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) })); assert_expr!("a.b.c.d()");
assert_expr!( assert_expr!("a.b().c.d()");
"a.b.c", */
expr(Access {
name: rc("c"),
expr: bx(expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }))
})
);
assert_expr!(
"a.b.c(3)",
expr(Call {
f: bx(expr(Access {
name: rc("c"),
expr: bx(expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }))
})),
arguments: vec![InvocationArgument::Positional(expr(NatLiteral(3)))],
})
);
assert_expr!(
"a.b().c",
expr(Access {
name: rc("c"),
expr: bx(expr(Call {
f: bx(expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) })),
arguments: vec![]
}))
})
);
} }
#[test] #[test]

View File

@ -4,7 +4,7 @@ use crate::{
ast, ast,
builtin::Builtin, builtin::Builtin,
symbol_table::{DefId, SymbolSpec, SymbolTable}, symbol_table::{DefId, SymbolSpec, SymbolTable},
type_inference::{TypeContext, TypeId}, type_inference::TypeContext,
}; };
mod test; mod test;
@ -135,14 +135,23 @@ impl<'a, 'b> Reducer<'a, 'b> {
}), }),
NamedStruct { name, fields } => { NamedStruct { name, fields } => {
self.symbol_table.debug(); self.symbol_table.debug();
println!("Namedstruct name {} id: {}", name, name.id);
let symbol = self.symbol_table.lookup_symbol(&name.id).unwrap(); let symbol = self.symbol_table.lookup_symbol(&name.id).unwrap();
let (tag, type_id) = match symbol.spec() { let (tag, type_id) = match symbol.spec() {
SymbolSpec::RecordConstructor { tag, members: _, type_id } => (tag, type_id), SymbolSpec::RecordConstructor { tag, members: _, type_id } => (tag, type_id),
e => return Expression::ReductionError(format!("Bad symbol for NamedStruct: {:?}", e)), e => return Expression::ReductionError(format!("Bad symbol for NamedStruct: {:?}", e)),
}; };
let field_order = compute_field_orderings(&self.type_context, &type_id, tag).unwrap(); // Eventually, the ReducedIR should decide what field ordering is optimal.
// For now, just do it alphabetically.
let mut field_order: Vec<String> = self
.type_context
.lookup_record_members(&type_id, tag)
.unwrap()
.iter()
.map(|(field, _type_id)| field)
.cloned()
.collect();
field_order.sort_unstable();
let mut field_map = HashMap::new(); let mut field_map = HashMap::new();
for (name, expr) in fields.iter() { for (name, expr) in fields.iter() {
@ -170,8 +179,6 @@ impl<'a, 'b> Reducer<'a, 'b> {
WhileExpression { .. } => Expression::ReductionError("While expr not implemented".to_string()), WhileExpression { .. } => Expression::ReductionError("While expr not implemented".to_string()),
ForExpression { .. } => Expression::ReductionError("For expr not implemented".to_string()), ForExpression { .. } => Expression::ReductionError("For expr not implemented".to_string()),
ListLiteral { .. } => Expression::ReductionError("ListLiteral expr not implemented".to_string()), ListLiteral { .. } => Expression::ReductionError("ListLiteral expr not implemented".to_string()),
Access { name, expr } =>
Expression::Access { name: name.as_ref().to_string(), expr: Box::new(self.expression(expr)) },
} }
} }
@ -381,21 +388,3 @@ impl ast::Pattern {
}) })
} }
} }
/// Given the type context and a variant, compute what order the fields on it were stored.
/// This needs to be public until type-checking is fully implemented because the type information
/// is only available at runtime.
pub fn compute_field_orderings(
type_context: &TypeContext,
type_id: &TypeId,
tag: u32,
) -> Option<Vec<String>> {
// Eventually, the ReducedIR should decide what field ordering is optimal.
// For now, just do it alphabetically.
let record_members = type_context.lookup_record_members(type_id, tag)?;
let mut field_order: Vec<String> =
record_members.iter().map(|(field, _type_id)| field).cloned().collect();
field_order.sort_unstable();
Some(field_order)
}

View File

@ -50,7 +50,6 @@ pub enum Expression {
Tuple(Vec<Expression>), Tuple(Vec<Expression>),
Lookup(Lookup), Lookup(Lookup),
Assign { lval: DefId, rval: Box<Expression> }, Assign { lval: DefId, rval: Box<Expression> },
Access { name: String, expr: Box<Expression> },
Callable(Callable), Callable(Callable),
Call { f: Box<Expression>, args: Vec<Expression> }, Call { f: Box<Expression>, args: Vec<Expression> },
Conditional { cond: Box<Expression>, then_clause: Vec<Statement>, else_clause: Vec<Statement> }, Conditional { cond: Box<Expression>, then_clause: Vec<Statement>, else_clause: Vec<Statement> },

View File

@ -126,28 +126,6 @@ impl<'a, 'b> Evaluator<'a, 'b> {
Expression::CaseMatch { box cond, alternatives } => Expression::CaseMatch { box cond, alternatives } =>
self.case_match_expression(cond, alternatives)?, self.case_match_expression(cond, alternatives)?,
Expression::ReductionError(e) => return Err(e.into()), Expression::ReductionError(e) => return Err(e.into()),
Expression::Access { name, box expr } => {
let expr = self.expression(expr)?;
match expr {
Primitive::Object { items, ordered_fields: Some(ordered_fields), .. } => {
let idx = match ordered_fields.iter().position(|s| s == &name) {
Some(idx) => idx,
None => return Err(format!("Field `{}` not found", name).into()),
};
let item = match items.get(idx) {
Some(item) => item,
None => return Err(format!("Field lookup `{}` failed", name).into()),
};
item.clone()
}
e =>
return Err(
format!("Trying to do a field lookup on a non-object value: {:?}", e).into()
),
}
}
}) })
} }

View File

@ -1,6 +1,6 @@
#![cfg(test)] #![cfg(test)]
use pretty_assertions::assert_eq;
use test_case::test_case; use test_case::test_case;
use pretty_assertions::assert_eq;
use crate::{ use crate::{
symbol_table::SymbolTable, symbol_table::SymbolTable,
@ -367,14 +367,3 @@ import Option::*
let x = Some(9); if x is Some(q) then { q } else { 0 }"#; let x = Some(9); if x is Some(q) then { q } else { 0 }"#;
eval_assert(source, "9"); eval_assert(source, "9");
} }
#[test]
fn accessors() {
let source = r#"
type Klewos = Klewos { a: Int, b: String }
let value = Klewos::Klewos { a: 50, b: "nah" }
(value.a, value.b)
"#;
eval_assert(source, r#"(50, "nah")"#);
}