From 9267002670e0a9a5b63deb88c43c294c92f9b1f6 Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Sat, 20 Sep 2014 16:32:33 -0700 Subject: [PATCH] Enable the parsing of higher kinded types --- src/libsyntax/ast.rs | 9 ++++++++- src/libsyntax/ext/build.rs | 9 ++++++--- src/libsyntax/ext/deriving/decodable.rs | 6 +++--- src/libsyntax/ext/deriving/encodable.rs | 6 +++--- src/libsyntax/ext/deriving/generic/mod.rs | 3 ++- src/libsyntax/ext/deriving/generic/ty.rs | 11 ++++++----- src/libsyntax/ext/deriving/hash.rs | 4 ++-- src/libsyntax/ext/deriving/rand.rs | 3 ++- src/libsyntax/fold.rs | 5 +++-- src/libsyntax/parse/parser.rs | 20 +++++++++++++++++--- 10 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 5c84745c20c6f..6d1a8ba9a38a3 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -233,7 +233,14 @@ pub struct TyParam { pub bounds: TyParamBounds, pub unbound: Option, pub default: Option>, - pub span: Span + pub span: Span, + pub kind: TyKind +} + +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub enum TyKind { + Star, + Arrow(Box, Box) } /// Represents lifetimes and type parameters attached to a declaration diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 16ecd83180ed1..57005d4c4f11a 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -69,7 +69,8 @@ pub trait AstBuilder { id: ast::Ident, bounds: OwnedSlice, unbound: Option, - default: Option>) -> ast::TyParam; + default: Option>, + kind: ast::TyKind) -> ast::TyParam; fn trait_ref(&self, path: ast::Path) -> ast::TraitRef; fn typarambound(&self, path: ast::Path) -> ast::TyParamBound; @@ -409,14 +410,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> { id: ast::Ident, bounds: OwnedSlice, unbound: Option, - default: Option>) -> ast::TyParam { + default: Option>, + kind: ast::TyKind) -> ast::TyParam { ast::TyParam { ident: id, id: ast::DUMMY_NODE_ID, bounds: bounds, unbound: unbound, default: default, - span: span + span: span, + kind: kind } } diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index fd24f5e35a446..c4fd980de34ed 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -13,7 +13,7 @@ The compiler code necessary for `#[deriving(Decodable)]`. See encodable.rs for more. */ -use ast::{MetaItem, Item, Expr, MutMutable, Ident}; +use ast::{MetaItem, Item, Expr, MutMutable, Ident, Star}; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -37,10 +37,10 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt, additional_bounds: Vec::new(), generics: LifetimeBounds { lifetimes: Vec::new(), - bounds: vec!(("__D", None, vec!(Path::new_( + bounds: vec!(("__D", Star, None, vec!(Path::new_( vec!("serialize", "Decoder"), None, vec!(box Literal(Path::new_local("__E"))), true))), - ("__E", None, vec!())) + ("__E", Star, None, vec!())) }, methods: vec!( MethodDef { diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 103253560df65..e31b8ed283fda 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -79,7 +79,7 @@ //! } //! ``` -use ast::{MetaItem, Item, Expr, ExprRet, MutMutable, LitNil}; +use ast::{MetaItem, Item, Expr, ExprRet, MutMutable, LitNil, Star}; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -102,10 +102,10 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt, additional_bounds: Vec::new(), generics: LifetimeBounds { lifetimes: Vec::new(), - bounds: vec!(("__S", None, vec!(Path::new_( + bounds: vec!(("__S", Star, None, vec!(Path::new_( vec!("serialize", "Encoder"), None, vec!(box Literal(Path::new_local("__E"))), true))), - ("__E", None, vec!())) + ("__E", Star, None, vec!())) }, methods: vec!( MethodDef { diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 142adc9b721e0..d0dd7d54d00cd 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -422,7 +422,8 @@ impl<'a> TraitDef<'a> { ty_param.ident, OwnedSlice::from_vec(bounds), ty_param.unbound.clone(), - None) + None, + ty_param.kind.clone()) })); let trait_generics = Generics { lifetimes: lifetimes, diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs index a90618a30b6eb..bc15d1f2c0bf3 100644 --- a/src/libsyntax/ext/deriving/generic/ty.rs +++ b/src/libsyntax/ext/deriving/generic/ty.rs @@ -195,13 +195,13 @@ impl<'a> Ty<'a> { fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str, bounds: &[Path], unbound: Option, - self_ident: Ident, self_generics: &Generics) -> ast::TyParam { + self_ident: Ident, self_generics: &Generics, kind: ast::TyKind) -> ast::TyParam { let bounds = bounds.iter().map(|b| { let path = b.to_path(cx, span, self_ident, self_generics); cx.typarambound(path) }).collect(); - cx.typaram(span, cx.ident_of(name), bounds, unbound, None) + cx.typaram(span, cx.ident_of(name), bounds, unbound, None, kind) } fn mk_generics(lifetimes: Vec, ty_params: Vec) @@ -220,7 +220,7 @@ fn mk_generics(lifetimes: Vec, ty_params: Vec) #[deriving(Clone)] pub struct LifetimeBounds<'a> { pub lifetimes: Vec<(&'a str, Vec<&'a str>)>, - pub bounds: Vec<(&'a str, Option, Vec>)>, + pub bounds: Vec<(&'a str, ast::TyKind, Option, Vec>)>, } impl<'a> LifetimeBounds<'a> { @@ -243,14 +243,15 @@ impl<'a> LifetimeBounds<'a> { }).collect(); let ty_params = self.bounds.iter().map(|t| { match t { - &(ref name, ref unbound, ref bounds) => { + &(ref name, ref kind, ref unbound, ref bounds) => { mk_ty_param(cx, span, *name, bounds.as_slice(), unbound.clone(), self_ty, - self_generics) + self_generics, + kind.clone()) } } }).collect(); diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index b7f11c2582548..79cc38d4c69ab 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{MetaItem, Item, Expr, MutMutable}; +use ast::{MetaItem, Item, Expr, MutMutable, Star}; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -28,7 +28,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, vec!(box Literal(Path::new_local("__S"))), true), LifetimeBounds { lifetimes: Vec::new(), - bounds: vec!(("__S", None, + bounds: vec!(("__S", Star, None, vec!(Path::new(vec!("std", "hash", "Writer"))))), }, Path::new_local("__S")) diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index 584645bb30639..29b472d87a70d 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -34,8 +34,9 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt, generics: LifetimeBounds { lifetimes: Vec::new(), bounds: vec!(("R", + ast::Star, None, - vec!( Path::new(vec!("std", "rand", "Rng")) ))) + vec!( Path::new(vec!("std", "rand", "Rng")) ))), }, explicit_self: None, args: vec!( diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 7ebb11c148bd2..cc5c95f28617b 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -682,14 +682,15 @@ pub fn noop_fold_ty_param_bound(tpb: TyParamBound, fld: &mut T) } pub fn noop_fold_ty_param(tp: TyParam, fld: &mut T) -> TyParam { - let TyParam {id, ident, bounds, unbound, default, span} = tp; + let TyParam {id, ident, bounds, unbound, default, span, kind} = tp; TyParam { id: fld.new_id(id), ident: ident, bounds: fld.fold_bounds(bounds), unbound: unbound.map(|x| fld.fold_ty_param_bound(x)), default: default.map(|x| fld.fold_ty(x)), - span: span + span: span, + kind: kind.clone() } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 069d30cbd8354..2f4546eac2356 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -52,7 +52,7 @@ use ast::{TokenTree, TraitItem, TraitRef, TTDelim, TTSeq, TTTok}; use ast::{TTNonterminal, TupleVariantKind, Ty, Ty_, TyBot, TyBox}; use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn}; use ast::{TyTypeof, TyInfer, TypeMethod}; -use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPtr, TyQPath}; +use ast::{TyNil, TyParam, TyParamBound, TyKind, TyParen, TyPath, TyPtr, TyQPath}; use ast::{TyRptr, TyTup, TyU32, TyUnboxedFn, TyUniq, TyVec, UnUniq}; use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind}; use ast::{UnboxedFnBound, UnboxedFnTy, UnboxedFnTyParamBound}; @@ -3839,7 +3839,7 @@ impl<'a> Parser<'a> { } } - /// Matches typaram = (unbound`?`)? IDENT optbounds ( EQ ty )? + /// Matches typaram = (unbound`?`)? IDENT optkind optbounds ( EQ ty )? fn parse_ty_param(&mut self) -> TyParam { // This is a bit hacky. Currently we are only interested in a single // unbound, and it may only be `Sized`. To avoid backtracking and other @@ -3856,6 +3856,8 @@ impl<'a> Parser<'a> { ident = self.parse_ident(); } + let kind = self.parse_ty_kind(); + let bounds = self.parse_colon_then_ty_param_bounds(); let default = if self.token == token::EQ { @@ -3871,9 +3873,22 @@ impl<'a> Parser<'a> { unbound: unbound, default: default, span: span, + kind: kind } } + fn parse_ty_kind(&mut self) -> ast::TyKind { + if self.eat(&token::LT) { + println!("Inside parse_ty_kind!") + let placeholders = self.parse_seq_to_gt(Some(token::COMMA), |p| { + p.eat(&token::UNDERSCORE) + }); + placeholders + .iter() + .skip(1) + .fold(ast::Star, |accum, _| ast::Arrow(box ast::Star, box accum)) + } else { ast::Star } + } /// Parse a set of optional generic type parameter declarations. Where /// clauses are not parsed here, and must be added later via /// `parse_where_clause()`. @@ -5781,4 +5796,3 @@ impl<'a> Parser<'a> { } } } -