Compare commits

..

4 Commits

Author SHA1 Message Date
Greg Shuflin
60ddac9774 Rest of clippy lints 2021-10-19 22:29:41 -07:00
Greg Shuflin
ae6a79077f more clippy lints 2021-10-19 22:24:27 -07:00
Greg Shuflin
36f06b38de Automatically apply clippy to various util modules 2021-10-19 21:57:14 -07:00
Greg Shuflin
c9c65b050c Clippy for parsing 2021-10-19 21:55:51 -07:00
11 changed files with 115 additions and 111 deletions

View File

@ -15,7 +15,7 @@ struct RecursiveDescentFn {
impl Fold for RecursiveDescentFn {
fn fold_item_fn(&mut self, mut i: syn::ItemFn) -> syn::ItemFn {
let box block = i.block;
let ref ident = i.ident;
let ident = &i.ident;
let new_block: syn::Block = parse_quote! {
{

View File

@ -1,5 +1,7 @@
use std::rc::Rc;
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::enum_variant_names)]
use std::rc::Rc;
use crate::derivative::Derivative;
mod walker;

View File

@ -6,26 +6,28 @@ use crate::ast::*;
pub trait ASTVisitor: Sized {
fn ast(&mut self, _ast: &AST) {}
fn block(&mut self, _statements: &Vec<Statement>) {}
fn block(&mut self, _statements: &[ Statement ]) {}
fn statement(&mut self, _statement: &Statement) {}
fn declaration(&mut self, _declaration: &Declaration) {}
fn signature(&mut self, _signature: &Signature) {}
fn type_declaration(&mut self, _name: &TypeSingletonName, _body: &TypeBody, _mutable: bool) {}
fn type_alias(&mut self, _alias: &Rc<String>, _original: &Rc<String>) {}
fn binding(&mut self, _name: &Rc<String>, _constant: bool, _type_anno: Option<&TypeIdentifier>, _expr: &Expression) {}
fn implemention(&mut self, _type_name: &TypeIdentifier, _interface_name: Option<&TypeSingletonName>, _block: &Vec<Declaration>) {}
fn interface(&mut self, _name: &Rc<String>, _signatures: &Vec<Signature>) {}
fn implemention(&mut self, _type_name: &TypeIdentifier, _interface_name: Option<&TypeSingletonName>, _block: &[ Declaration ]) {}
fn interface(&mut self, _name: &Rc<String>, _signatures: &[ Signature ]) {}
fn expression(&mut self, _expression: &Expression) {}
fn expression_kind(&mut self, _kind: &ExpressionKind) {}
fn type_annotation(&mut self, _type_anno: Option<&TypeIdentifier>) {}
fn named_struct(&mut self, _name: &QualifiedName, _fields: &Vec<(Rc<String>, Expression)>) {}
fn call(&mut self, _f: &Expression, _arguments: &Vec<InvocationArgument>) {}
fn index(&mut self, _indexee: &Expression, _indexers: &Vec<Expression>) {}
fn named_struct(&mut self, _name: &QualifiedName, _fields: &[ (Rc<String>, Expression) ]) {}
fn call(&mut self, _f: &Expression, _arguments: &[ InvocationArgument ]) {}
fn index(&mut self, _indexee: &Expression, _indexers: &[ Expression ]) {}
fn if_expression(&mut self, _discrim: Option<&Expression>, _body: &IfExpressionBody) {}
fn condition_arm(&mut self, _arm: &ConditionArm) {}
#[allow(clippy::ptr_arg)]
fn while_expression(&mut self, _condition: Option<&Expression>, _body: &Block) {}
fn for_expression(&mut self, _enumerators: &Vec<Enumerator>, _body: &ForBody) {}
fn lambda(&mut self, _params: &Vec<FormalParam>, _type_anno: Option<&TypeIdentifier>, _body: &Block) {}
fn for_expression(&mut self, _enumerators: &[ Enumerator ], _body: &ForBody) {}
#[allow(clippy::ptr_arg)]
fn lambda(&mut self, _params: &[ FormalParam ], _type_anno: Option<&TypeIdentifier>, _body: &Block) {}
fn invocation_argument(&mut self, _arg: &InvocationArgument) {}
fn formal_param(&mut self, _param: &FormalParam) {}
fn import(&mut self, _import: &ImportSpecifier) {}

View File

@ -9,6 +9,7 @@ pub fn walk_ast<V: ASTVisitor>(v: &mut V, ast: &AST) {
walk_block(v, &ast.statements);
}
#[allow(clippy::ptr_arg)]
fn walk_block<V: ASTVisitor>(v: &mut V, block: &Vec<Statement>) {
for s in block {
v.statement(s);
@ -39,12 +40,12 @@ fn declaration<V: ASTVisitor>(v: &mut V, decl: &Declaration) {
use Declaration::*;
match decl {
FuncSig(sig) => {
v.signature(&sig);
signature(v, &sig);
v.signature(sig);
signature(v, sig);
},
FuncDecl(sig, block) => {
v.signature(&sig);
v.block(&block);
v.signature(sig);
v.block(block);
walk_block(v, block);
},
TypeDecl { name, body, mutable } => v.type_declaration(name, body, *mutable),
@ -52,8 +53,8 @@ fn declaration<V: ASTVisitor>(v: &mut V, decl: &Declaration) {
Binding { name, constant, type_anno, expr } => {
v.binding(name, *constant, type_anno.as_ref(), expr);
v.type_annotation(type_anno.as_ref());
v.expression(&expr);
expression(v, &expr);
v.expression(expr);
expression(v, expr);
},
Impl { type_name, interface_name, block } => {
v.implemention(type_name, interface_name.as_ref(), block);
@ -79,7 +80,7 @@ fn expression<V: ASTVisitor>(v: &mut V, expression: &Expression) {
}
fn call<V: ASTVisitor>(v: &mut V, f: &Expression, args: &Vec<InvocationArgument>) {
fn call<V: ASTVisitor>(v: &mut V, f: &Expression, args: &[ InvocationArgument ]) {
v.expression(f);
expression(v, f);
for arg in args.iter() {
@ -103,20 +104,21 @@ fn invocation_argument<V: ASTVisitor>(v: &mut V, arg: &InvocationArgument) {
}
}
fn index<V: ASTVisitor>(v: &mut V, indexee: &Expression, indexers: &Vec<Expression>) {
fn index<V: ASTVisitor>(v: &mut V, indexee: &Expression, indexers: &[ Expression ]) {
v.expression(indexee);
for i in indexers.iter() {
v.expression(i);
}
}
fn named_struct<V: ASTVisitor>(v: &mut V, n: &QualifiedName, fields: &Vec<(Rc<String>, Expression)>) {
fn named_struct<V: ASTVisitor>(v: &mut V, n: &QualifiedName, fields: &[ (Rc<String>, Expression) ]) {
v.qualified_name(n);
for (_, expr) in fields.iter() {
v.expression(expr);
}
}
#[allow(clippy::ptr_arg)]
fn lambda<V: ASTVisitor>(v: &mut V, params: &Vec<FormalParam>, type_anno: Option<&TypeIdentifier>, body: &Block) {
for param in params {
v.formal_param(param);
@ -128,11 +130,11 @@ fn lambda<V: ASTVisitor>(v: &mut V, params: &Vec<FormalParam>, type_anno: Option
}
fn formal_param<V: ASTVisitor>(v: &mut V, param: &FormalParam) {
param.default.as_ref().map(|p| {
v.expression(p);
expression(v, p);
});
v.type_annotation(param.anno.as_ref());
if let Some(p) = param.default.as_ref() {
v.expression(p);
expression(v, p);
};
v.type_annotation(param.anno.as_ref());
}
fn expression_kind<V: ASTVisitor>(v: &mut V, expression_kind: &ExpressionKind) {
@ -172,7 +174,7 @@ fn expression_kind<V: ASTVisitor>(v: &mut V, expression_kind: &ExpressionKind) {
},
IfExpression { discriminator, body } => {
v.if_expression(deref_optional_box(discriminator), body);
discriminator.as_ref().map(|d| expression(v, d));
if let Some(d) = discriminator.as_ref() { expression(v, d) }
if_expression_body(v, body);
},
WhileExpression { condition, body } => v.while_expression(deref_optional_box(condition), body),
@ -195,13 +197,13 @@ fn if_expression_body<V: ASTVisitor>(v: &mut V, body: &IfExpressionBody) {
match body {
SimpleConditional { then_case, else_case } => {
walk_block(v, then_case);
else_case.as_ref().map(|block| walk_block(v, block));
if let Some(block) = else_case.as_ref() { walk_block(v, block) }
},
SimplePatternMatch { pattern, then_case, else_case } => {
v.pattern(pattern);
walk_pattern(v, pattern);
walk_block(v, then_case);
else_case.as_ref().map(|block| walk_block(v, block));
if let Some(block) = else_case.as_ref() { walk_block(v, block) }
},
CondList(arms) => {
for arm in arms {
@ -230,10 +232,10 @@ fn condition_arm<V: ASTVisitor>(v: &mut V, arm: &ConditionArm) {
},
_ => ()
}
arm.guard.as_ref().map(|guard| {
v.expression(guard);
expression(v, guard);
});
if let Some(guard) = arm.guard.as_ref() {
v.expression(guard);
expression(v, guard);
};
v.block(&arm.body);
walk_block(v, &arm.body);
}

View File

@ -13,15 +13,15 @@ fn evaluate_all_outputs(input: &str) -> Vec<Result<String, String>> {
let reduced = reduce(&ast, &symbol_table);
let mut state = State::new();
let all_output = state.evaluate(reduced, true);
all_output
state.evaluate(reduced, true)
}
macro_rules! test_in_fresh_env {
($string:expr, $correct:expr) => {
{
let all_output = evaluate_all_outputs($string);
let ref output = all_output.last().unwrap();
let output = &all_output.last().unwrap();
assert_eq!(**output, Ok($correct.to_string()));
}
}

View File

@ -1,3 +1,5 @@
#![allow(clippy::upper_case_acronyms)]
//! # Parsing
//! This module is where the recursive-descent parsing methods live.
//!
@ -230,15 +232,15 @@ impl TokenHandler {
self.peek_n(n).kind
}
fn peek(&mut self) -> Token {
self.tokens.get(self.idx).map(|t: &Token| { t.clone()}).unwrap_or(Token { kind: TokenKind::EOF, location: self.end_of_file })
self.tokens.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()
fn peek_n(&mut self, n: usize) -> Token {
self.tokens.get(self.idx + n).map(|t: &Token| { t.clone()}).unwrap_or(Token { kind: TokenKind::EOF, location: self.end_of_file })
self.tokens.get(self.idx + n).cloned().unwrap_or(Token { kind: TokenKind::EOF, location: self.end_of_file })
}
fn next(&mut self) -> Token {
self.idx += 1;
self.tokens.get(self.idx - 1).map(|t: &Token| { t.clone() }).unwrap_or(Token { kind: TokenKind::EOF, location: self.end_of_file })
self.tokens.get(self.idx - 1).cloned().unwrap_or(Token { kind: TokenKind::EOF, location: self.end_of_file })
}
}
@ -371,11 +373,11 @@ impl Parser {
let kind = match tok.get_kind() {
Keyword(Type) => self.type_declaration().map(|decl| { StatementKind::Declaration(decl) }),
Keyword(Func)=> self.func_declaration().map(|func| { StatementKind::Declaration(func) }),
Keyword(Let) => self.binding_declaration().map(|decl| StatementKind::Declaration(decl)),
Keyword(Interface) => self.interface_declaration().map(|decl| StatementKind::Declaration(decl)),
Keyword(Impl) => self.impl_declaration().map(|decl| StatementKind::Declaration(decl)),
Keyword(Import) => self.import_declaration().map(|spec| StatementKind::Import(spec)),
Keyword(Module) => self.module_declaration().map(|spec| StatementKind::Module(spec)),
Keyword(Let) => self.binding_declaration().map(StatementKind::Declaration),
Keyword(Interface) => self.interface_declaration().map(StatementKind::Declaration),
Keyword(Impl) => self.impl_declaration().map(StatementKind::Declaration),
Keyword(Import) => self.import_declaration().map(StatementKind::Import),
Keyword(Module) => self.module_declaration().map(StatementKind::Module),
_ => self.expression().map(|expr| { StatementKind::Expression(expr) } ),
}?;
let id = self.id_store.fresh();
@ -417,15 +419,10 @@ impl Parser {
#[recursive_descent_method]
fn type_body(&mut self) -> ParseResult<TypeBody> {
let mut variants = Vec::new();
variants.push(self.variant_specifier()?);
loop {
if let Pipe = self.token_handler.peek_kind() {
let mut variants = vec![self.variant_specifier()?];
while let Pipe = self.token_handler.peek_kind() {
self.token_handler.next();
variants.push(self.variant_specifier()?);
} else {
break;
}
}
Ok(TypeBody(variants))
}
@ -472,7 +469,7 @@ impl Parser {
expect!(self, Keyword(Func));
let (name, operator) = match self.token_handler.peek_kind() {
Operator(s) => {
let name = s.clone();
let name = s;
self.token_handler.next();
(name, true)
},
@ -582,7 +579,7 @@ impl Parser {
Colon => Some(self.type_anno()?),
_ => None
};
if let Some(_) = expr_body.type_anno {
if expr_body.type_anno.is_some() {
return ParseError::new_with_token("Bad parse state encountered", self.token_handler.peek());
}
expr_body.type_anno = type_anno;
@ -616,10 +613,11 @@ impl Parser {
}
// this implements Pratt parsing, see http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
#[allow(clippy::while_let_loop)]
fn precedence_expr(&mut self, precedence: i32) -> ParseResult<Expression> {
let record = ParseRecord {
production_name: "precedence_expr".to_string(),
next_token: format!("{}", self.token_handler.peek().to_string_with_metadata()),
next_token: self.token_handler.peek().to_string_with_metadata(),
level: self.parse_level,
};
self.parse_level += 1;
@ -691,7 +689,7 @@ impl Parser {
self.token_handler.next();
self.token_handler.next();
let expr = self.expression()?;
InvocationArgument::Keyword { name: s.clone(), expr }
InvocationArgument::Keyword { name: s, expr }
},
_ => {
let expr = self.expression()?;
@ -799,14 +797,11 @@ impl Parser {
#[recursive_descent_method]
fn qualified_identifier(&mut self) -> ParseResult<Vec<Rc<String>>> {
let mut components = vec![self.identifier()?];
loop {
match (self.token_handler.peek_kind(), self.token_handler.peek_kind_n(1)) {
(Colon, Colon) => {
self.token_handler.next(); self.token_handler.next();
components.push(self.identifier()?);
},
_ => break,
}
while let (Colon, Colon) = (self.token_handler.peek_kind(), self.token_handler.peek_kind_n(1)) {
self.token_handler.next();
self.token_handler.next();
components.push(self.identifier()?);
}
Ok(components)
}
@ -1023,7 +1018,7 @@ impl Parser {
let pat = self.pattern()?;
(name, pat)
},
_ => (name.clone(), Pattern::Literal(PatternLiteral::StringPattern(name.clone())))
_ => (name.clone(), Pattern::Literal(PatternLiteral::StringPattern(name)))
})
}
@ -1054,7 +1049,7 @@ impl Parser {
self.restrictions.no_struct_literal = true;
let x = self.while_cond();
self.restrictions.no_struct_literal = false;
x?.map(|expr| Box::new(expr))
x?.map(Box::new)
};
let body = self.block()?;
Ok(Expression::new(self.id_store.fresh(), WhileExpression {condition, body}))
@ -1140,7 +1135,7 @@ impl Parser {
StrLiteral {s, ..} => {
self.token_handler.next();
let id = self.id_store.fresh();
Ok(Expression::new(id, StringLiteral(s.clone())))
Ok(Expression::new(id, StringLiteral(s)))
}
e => ParseError::new_with_token(format!("Expected a literal expression, got {:?}", e), tok),
}
@ -1180,7 +1175,7 @@ impl Parser {
let mut digits = self.digits()?;
if let Period = self.token_handler.peek_kind() {
self.token_handler.next();
digits.push_str(".");
digits.push('.');
digits.push_str(&self.digits()?);
match digits.parse::<f64>() {
Ok(f) => Ok(Expression::new(self.id_store.fresh(), FloatLiteral(f))),
@ -1211,20 +1206,16 @@ impl Parser {
#[recursive_descent_method]
fn import_declaration(&mut self) -> ParseResult<ImportSpecifier> {
expect!(self, Keyword(Import));
let mut path_components = vec![];
path_components.push(self.identifier()?);
loop {
match (self.token_handler.peek_kind(), self.token_handler.peek_kind_n(1)) {
(Colon, Colon) => {
self.token_handler.next(); self.token_handler.next();
if let Identifier(_) = self.token_handler.peek_kind() {
let mut path_components = vec![self.identifier()?];
while let (Colon, Colon) = (self.token_handler.peek_kind(), self.token_handler.peek_kind_n(1)) {
self.token_handler.next();
self.token_handler.next();
if let Identifier(_) = self.token_handler.peek_kind() {
path_components.push(self.identifier()?);
} else {
} else {
break;
}
},
_ => break,
}
}
}
let imported_names = match self.token_handler.peek_kind() {

View File

@ -1,4 +1,7 @@
#![cfg(test)]
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::vec_init_then_push)]
use std::rc::Rc;
use crate::tokenizing::Location;
@ -170,12 +173,12 @@ fn parsing_tuples() {
parse_test_wrap_ast!("()", exst!(TupleLiteral(vec![])));
parse_test_wrap_ast!("(\"hella\", 34)", exst!(
TupleLiteral(
vec![ex!(s r#""hella""#).into(), ex!(s "34").into()]
vec![ex!(s r#""hella""#), ex!(s "34")]
)
));
parse_test_wrap_ast!("((1+2), \"slough\")", exst!(TupleLiteral(vec![
ex!(binexp!("+", NatLiteral(1), NatLiteral(2))).into(),
ex!(StringLiteral(rc!(slough))).into(),
ex!(binexp!("+", NatLiteral(1), NatLiteral(2))),
ex!(StringLiteral(rc!(slough))),
])))
}
@ -255,7 +258,7 @@ fn parsing_functions() {
parse_test_wrap_ast!("oi()", exst!(Call { f: bx!(ex!(val!("oi"))), arguments: vec![] }));
parse_test_wrap_ast!("oi(a, 2 + 2)", exst!(Call
{ f: bx!(ex!(val!("oi"))),
arguments: vec![inv!(ex!(val!("a"))), inv!(ex!(binexp!("+", NatLiteral(2), NatLiteral(2)))).into()]
arguments: vec![inv!(ex!(val!("a"))), inv!(ex!(binexp!("+", NatLiteral(2), NatLiteral(2))))]
}));
parse_error!("a(b,,c)");
@ -541,7 +544,7 @@ fn parsing_lambdas() {
type_anno: None,
body: vec![exst!(s "y")] }
)),
arguments: vec![inv!(ex!(NatLiteral(1))).into()] })
arguments: vec![inv!(ex!(NatLiteral(1)))] })
};
parse_test_wrap_ast! {
@ -589,7 +592,7 @@ fn more_advanced_lambdas() {
exst! {
Call {
f: bx!(ex!(Call { f: bx!(ex!(val!("wahoo"))), arguments: vec![] })),
arguments: vec![inv!(ex!(NatLiteral(3))).into()],
arguments: vec![inv!(ex!(NatLiteral(3)))],
}
}
]

View File

@ -92,7 +92,7 @@ impl<'a> ASTVisitor for Resolver<'a> {
self.symbol_table.id_to_fqsn.insert(qualified_name.id.clone(), fqsn);
}
fn named_struct(&mut self, qualified_name: &QualifiedName, _fields: &Vec<(Rc<String>, Expression)>) {
fn named_struct(&mut self, qualified_name: &QualifiedName, _fields: &[ (Rc<String>, Expression) ]) {
let fqsn = self.lookup_name_in_scope(qualified_name);
self.symbol_table.id_to_fqsn.insert(qualified_name.id.clone(), fqsn);
}

View File

@ -1,8 +1,9 @@
#![allow(clippy::upper_case_acronyms)]
use itertools::Itertools;
use std::{iter::{Iterator, Peekable}, convert::TryFrom, rc::Rc, fmt};
use std::convert::TryInto;
/// A location in a particular source file. Note that the
/// sizes of the internal unsigned integer types limit
/// the size of a source file to 2^32 lines of

View File

@ -1,5 +1,4 @@
use std::rc::Rc;
use std::fmt::Write;
use std::convert::TryFrom;
use ena::unify::{UnifyKey, InPlaceUnificationTable, UnificationTable, EqUnifyValue};
@ -79,19 +78,21 @@ pub enum TypeConst {
}
impl TypeConst {
/*
#[allow(dead_code)]
pub fn to_string(&self) -> String {
use self::TypeConst::*;
match self {
Unit => format!("()"),
Nat => format!("Nat"),
Int => format!("Int"),
Float => format!("Float"),
StringT => format!("String"),
Bool => format!("Bool"),
Ordering => format!("Ordering"),
Unit => "()".to_string(),
Nat => "Nat".to_string(),
Int => "Int".to_string(),
Float => "Float".to_string(),
StringT => "String".to_string(),
Bool => "Bool".to_string(),
Ordering => "Ordering".to_string(),
}
}
*/
}
impl EqUnifyValue for TypeConst { }
@ -110,6 +111,7 @@ macro_rules! ty {
//TODO find a better way to capture the to/from string logic
impl Type {
/*
#[allow(dead_code)]
pub fn to_string(&self) -> String {
use self::Type::*;
@ -117,7 +119,7 @@ impl Type {
Const(c) => c.to_string(),
Var(v) => format!("t_{}", v.0),
Arrow { params, box ref ret } => {
if params.len() == 0 {
if params.is_empty() {
format!("-> {}", ret.to_string())
} else {
let mut buf = String::new();
@ -128,9 +130,10 @@ impl Type {
buf
}
},
Compound { .. } => format!("<some compound type>")
Compound { .. } => "<some compound type>".to_string()
}
}
*/
fn from_string(string: &str) -> Option<Type> {
Some(match string {
@ -256,7 +259,7 @@ impl<'a> TypeContext<'a> {
use self::TypeIdentifier::*;
Ok(match name {
Singleton(TypeSingletonName { name,.. }) => {
match Type::from_string(&name) {
match Type::from_string(name) {
Some(ty) => ty,
None => return TypeError::new(format!("Unknown type name: {}", name))
}
@ -279,7 +282,7 @@ impl<'a> TypeContext<'a> {
fn statement(&mut self, statement: &Statement) -> InferResult<Type> {
match &statement.kind {
StatementKind::Expression(e) => self.expr(e),
StatementKind::Declaration(decl) => self.decl(&decl),
StatementKind::Declaration(decl) => self.decl(decl),
StatementKind::Import(_) => Ok(ty!(Unit)),
StatementKind::Module(_) => Ok(ty!(Unit)),
}
@ -287,12 +290,9 @@ impl<'a> TypeContext<'a> {
fn decl(&mut self, decl: &Declaration) -> InferResult<Type> {
use self::Declaration::*;
match decl {
Binding { name, expr, .. } => {
if let Binding { name, expr, .. } = decl {
let ty = self.expr(expr)?;
self.variable_map.insert(name.clone(), ty);
},
_ => (),
}
Ok(ty!(Unit))
}
@ -361,10 +361,11 @@ impl<'a> TypeContext<'a> {
use self::IfExpressionBody::*;
match (discriminator, body) {
(Some(expr), SimpleConditional{ then_case, else_case }) => self.handle_simple_if(expr, then_case, else_case),
_ => TypeError::new(format!("Complex conditionals not supported"))
_ => TypeError::new("Complex conditionals not supported".to_string())
}
}
#[allow(clippy::ptr_arg)]
fn handle_simple_if(&mut self, expr: &Expression, then_clause: &Block, else_clause: &Option<Block>) -> InferResult<Type> {
let t1 = self.expr(expr)?;
let t2 = self.block(then_clause)?;
@ -377,6 +378,7 @@ impl<'a> TypeContext<'a> {
self.unify(t2, t3)
}
#[allow(clippy::ptr_arg)]
fn lambda(&mut self, params: &Vec<FormalParam>, type_anno: &Option<TypeIdentifier>, _body: &Block) -> InferResult<Type> {
let argument_types: InferResult<Vec<Type>> = params.iter().map(|param: &FormalParam| {
if let FormalParam { anno: Some(type_identifier), .. } = param {
@ -394,7 +396,7 @@ impl<'a> TypeContext<'a> {
Ok(ty!(argument_types, ret_type))
}
fn call(&mut self, f: &Expression, args: &Vec<InvocationArgument>) -> InferResult<Type> {
fn call(&mut self, f: &Expression, args: &[ InvocationArgument ]) -> InferResult<Type> {
let tf = self.expr(f)?;
let arg_types: InferResult<Vec<Type>> = args.iter().map(|ex| self.invoc(ex)).collect();
let arg_types = arg_types?;
@ -410,10 +412,11 @@ impl<'a> TypeContext<'a> {
t_ret.clone()
},
Type::Arrow { .. } => return TypeError::new("Wrong length"),
_ => return TypeError::new(format!("Not a function"))
_ => return TypeError::new("Not a function".to_string())
})
}
#[allow(clippy::ptr_arg)]
fn block(&mut self, block: &Block) -> InferResult<Type> {
let mut output = ty!(Unit);
for statement in block.iter() {
@ -438,26 +441,26 @@ impl<'a> TypeContext<'a> {
(Const(ref c1), Const(ref c2)) if c1 == c2 => Ok(Const(c1.clone())), //choice of c1 is arbitrary I *think*
(a @ Var(_), b @ Const(_)) => self.unify(b, a),
(Const(ref c1), Var(ref v2)) => {
self.unification_table.unify_var_value(v2.clone(), Some(c1.clone()))
self.unification_table.unify_var_value(*v2, Some(c1.clone()))
.or_else(|_| TypeError::new(format!("Couldn't unify {:?} and {:?}", Const(c1.clone()), Var(*v2))))?;
Ok(Const(c1.clone()))
},
(Var(v1), Var(v2)) => {
//TODO add occurs check
self.unification_table.unify_var_var(v1.clone(), v2.clone())
self.unification_table.unify_var_var(v1, v2)
.or_else(|e| {
println!("Unify error: {:?}", e);
TypeError::new(format!("Two type variables {:?} and {:?} couldn't unify", v1, v2))
})?;
Ok(Var(v1.clone())) //arbitrary decision I think
Ok(Var(v1)) //arbitrary decision I think
},
(a, b) => TypeError::new(format!("{:?} and {:?} do not unify", a, b)),
}
}
fn fresh_type_variable(&mut self) -> TypeVar {
let new_type_var = self.unification_table.new_key(None);
new_type_var
self.unification_table.new_key(None)
}
}
@ -468,7 +471,7 @@ mod typechecking_tests {
macro_rules! assert_type_in_fresh_context {
($string:expr, $type:expr) => {
let mut tc = TypeContext::new();
let ref ast = crate::util::quick_ast($string);
let ast = &crate::util::quick_ast($string);
let ty = tc.typecheck(ast).unwrap();
assert_eq!(ty, $type)
}

View File

@ -4,7 +4,7 @@ use std::cmp::Eq;
use std::ops::Deref;
pub fn deref_optional_box<T>(x: &Option<Box<T>>) -> Option<&T> {
x.as_ref().map(|b: &Box<T>| Deref::deref(b))
x.as_ref().map(Deref::deref)
}
#[derive(Default, Debug)]