diff --git a/src/schala_lang/parsing.rs b/src/schala_lang/parsing.rs index 153e94d..f71cc38 100644 --- a/src/schala_lang/parsing.rs +++ b/src/schala_lang/parsing.rs @@ -403,7 +403,6 @@ pub enum Statement { } type ParamName = Rc; -type TypeName = Rc; //TODO change TypeName to TypeAnno everywhere type TraitName = Rc; type FormalParamList = Vec<(ParamName, Option)>; @@ -433,19 +432,19 @@ pub struct TypeBody(pub Vec); #[derive(Debug, PartialEq, Clone)] pub enum Variant { UnitStruct(Rc), - TupleStruct(Rc, Vec), - Record(Rc, Vec<(Rc, TypeAnno)>), + TupleStruct(Rc, Vec), + Record(Rc, Vec<(Rc, TypeName)>), } #[derive(Debug, PartialEq, Clone)] -pub struct Expression(pub ExpressionType, pub Option); +pub struct Expression(pub ExpressionType, pub Option); #[derive(Debug, PartialEq, Clone)] -pub enum TypeAnno { - Tuple(Vec), +pub enum TypeName { + Tuple(Vec), Singleton { name: Rc, - params: Vec, + params: Vec, } } @@ -636,7 +635,7 @@ impl Parser { } }); - parse_method!(typed_identifier(&mut self) -> ParseResult<(Rc, TypeAnno)> { + parse_method!(typed_identifier(&mut self) -> ParseResult<(Rc, TypeName)> { let identifier = self.identifier()?; expect!(self, Colon, "':'"); let type_name = self.type_name()?; @@ -679,10 +678,10 @@ impl Parser { parse_method!(impl_declaration(&mut self) -> ParseResult { expect!(self, Keyword(Impl), "'impl'"); - let first = self.identifier()?; + let first = self.type_name()?; let second = if let Keyword(For) = self.peek() { self.next(); - Some(self.identifier()?) + Some(self.type_name()?) } else { None }; @@ -690,7 +689,13 @@ impl Parser { let block = self.decl_block()?; let result = match (first, second) { - (first, Some(second)) => Declaration::Impl { type_name: second, trait_name: Some(first), block }, + (first, Some(second)) => { + match first { + TypeName::Singleton { ref name, ref params } if params.len() == 0 => + Declaration::Impl { type_name: second, trait_name: Some(name.clone()), block }, + _ => return ParseError::new(&format!("Invalid name for a trait")), + } + }, (first, None) => Declaration::Impl { type_name: first, trait_name: None, block } }; Ok(result) @@ -713,15 +718,16 @@ impl Parser { Ok(expr_body) }); - parse_method!(type_anno(&mut self) -> ParseResult { + parse_method!(type_anno(&mut self) -> ParseResult { expect!(self, Colon, "':'"); self.type_name() }); - parse_method!(type_name(&mut self) -> ParseResult { + parse_method!(type_name(&mut self) -> ParseResult { + use self::TypeName::*; Ok(match self.peek() { - LParen => TypeAnno::Tuple(delimited!(self, LParen, '(', type_name, Comma, RParen, ')')), - _ => TypeAnno::Singleton { + LParen => Tuple(delimited!(self, LParen, '(', type_name, Comma, RParen, ')')), + _ => Singleton { name: self.identifier()?, params: match self.peek() { LAngleBracket => delimited!(self, LAngleBracket, '<', type_name, Comma, RAngleBracket, '>'), @@ -988,7 +994,7 @@ mod parse_tests { use super::{AST, Expression, Statement, Operation, TypeBody, Variant, parse, tokenize}; use super::Statement::*; use super::Declaration::*; - use super::TypeAnno::*; + use super::TypeName::*; use super::ExpressionType::*; use super::Variant::*; diff --git a/src/schala_lang/type_check.rs b/src/schala_lang/type_check.rs index ead7464..befab13 100644 --- a/src/schala_lang/type_check.rs +++ b/src/schala_lang/type_check.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use std::rc::Rc; -use schala_lang::parsing::{AST, Statement, Declaration, Expression, ExpressionType, Operation, TypeAnno}; +use schala_lang::parsing::{AST, Statement, Declaration, Expression, ExpressionType, Operation, TypeName}; #[derive(Debug, PartialEq, Eq, Hash)] struct PathSpecifier { @@ -103,7 +103,7 @@ impl TypeContext { match (&expr.0, &expr.1) { (&IntLiteral(_), &Some(ref t)) => { match t { - &TypeAnno::Singleton { ref name, ref params } if **name == "Int" && params.len() == 0 => (), + &TypeName::Singleton { ref name, ref params } if **name == "Int" && params.len() == 0 => (), t => return Err(format!("Bad type {:?} for int literal", t)), } },