// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // The Rust abstract syntax tree. use codemap::{Span, Spanned, DUMMY_SP}; use abi::Abi; use ast_util; use owned_slice::OwnedSlice; use parse::token::{InternedString, str_to_ident}; use parse::token; use std::fmt; use std::fmt::Show; use std::option::Option; use std::rc::Rc; use std::gc::{Gc, GC}; use serialize::{Encodable, Decodable, Encoder, Decoder}; /// A pointer abstraction. // FIXME(eddyb) #10676 use Rc in the future. pub type P = Gc; #[allow(non_snake_case_functions)] /// Construct a P from a T value. pub fn P(value: T) -> P { box(GC) value } // FIXME #6993: in librustc, uses of "ident" should be replaced // by just "Name". /// An identifier contains a Name (index into the interner /// table) and a SyntaxContext to track renaming and /// macro expansion per Flatt et al., "Macros /// That Work Together" #[deriving(Clone, Hash, PartialOrd, Eq, Ord)] pub struct Ident { pub name: Name, pub ctxt: SyntaxContext } impl Ident { /// Construct an identifier with the given name and an empty context: pub fn new(name: Name) -> Ident { Ident {name: name, ctxt: EMPTY_CTXT}} pub fn as_str<'a>(&'a self) -> &'a str { self.name.as_str() } } impl Show for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "\"{}\"#{}", token::get_ident(*self).get(), self.ctxt) } } impl PartialEq for Ident { fn eq(&self, other: &Ident) -> bool { if self.ctxt == other.ctxt { self.name == other.name } else { // IF YOU SEE ONE OF THESE FAILS: it means that you're comparing // idents that have different contexts. You can't fix this without // knowing whether the comparison should be hygienic or non-hygienic. // if it should be non-hygienic (most things are), just compare the // 'name' fields of the idents. Or, even better, replace the idents // with Name's. // // On the other hand, if the comparison does need to be hygienic, // one example and its non-hygienic counterpart would be: // syntax::parse::token::mtwt_token_eq // syntax::ext::tt::macro_parser::token_name_eq fail!("not allowed to compare these idents: {:?}, {:?}. \ Probably related to issue \\#6993", self, other); } } fn ne(&self, other: &Ident) -> bool { ! self.eq(other) } } /// A SyntaxContext represents a chain of macro-expandings /// and renamings. Each macro expansion corresponds to /// a fresh uint // I'm representing this syntax context as an index into // a table, in order to work around a compiler bug // that's causing unreleased memory to cause core dumps // and also perhaps to save some work in destructor checks. // the special uint '0' will be used to indicate an empty // syntax context. // this uint is a reference to a table stored in thread-local // storage. pub type SyntaxContext = u32; pub static EMPTY_CTXT : SyntaxContext = 0; pub static ILLEGAL_CTXT : SyntaxContext = 1; /// A name is a part of an identifier, representing a string or gensym. It's /// the result of interning. #[deriving(Eq, Ord, PartialEq, PartialOrd, Hash, Encodable, Decodable, Clone, Show)] pub struct Name(pub u32); impl Name { pub fn as_str<'a>(&'a self) -> &'a str { unsafe { // FIXME #12938: can't use copy_lifetime since &str isn't a &T ::std::mem::transmute(token::get_name(*self).get()) } } pub fn uint(&self) -> uint { let Name(nm) = *self; nm as uint } pub fn ident(&self) -> Ident { Ident { name: *self, ctxt: 0 } } } /// A mark represents a unique id associated with a macro expansion pub type Mrk = u32; impl, E> Encodable for Ident { fn encode(&self, s: &mut S) -> Result<(), E> { s.emit_str(token::get_ident(*self).get()) } } impl, E> Decodable for Ident { fn decode(d: &mut D) -> Result { Ok(str_to_ident(try!(d.read_str()).as_slice())) } } /// Function name (not all functions have names) pub type FnIdent = Option; #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Lifetime { pub id: NodeId, pub span: Span, pub name: Name } /// A "Path" is essentially Rust's notion of a name; for instance: /// std::cmp::PartialEq . It's represented as a sequence of identifiers, /// along with a bunch of supporting information. #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Path { pub span: Span, /// A `::foo` path, is relative to the crate root rather than current /// module (like paths in an import). pub global: bool, /// The segments in the path: the things separated by `::`. pub segments: Vec , } /// A segment of a path: an identifier, an optional lifetime, and a set of /// types. #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct PathSegment { /// The identifier portion of this path segment. pub identifier: Ident, /// The lifetime parameters for this path segment. pub lifetimes: Vec, /// The type parameters for this path segment, if present. pub types: OwnedSlice>, } pub type CrateNum = u32; pub type NodeId = u32; #[deriving(Clone, Eq, Ord, PartialOrd, PartialEq, Encodable, Decodable, Hash, Show)] pub struct DefId { pub krate: CrateNum, pub node: NodeId, } /// Item definitions in the currently-compiled crate would have the CrateNum /// LOCAL_CRATE in their DefId. pub static LOCAL_CRATE: CrateNum = 0; pub static CRATE_NODE_ID: NodeId = 0; /// When parsing and doing expansions, we initially give all AST nodes this AST /// node value. Then later, in the renumber pass, we renumber them to have /// small, positive ids. pub static DUMMY_NODE_ID: NodeId = -1; /// The AST represents all type param bounds as types. /// typeck::collect::compute_bounds matches these against /// the "special" built-in traits (see middle::lang_items) and /// detects Copy, Send and Share. #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum TyParamBound { TraitTyParamBound(TraitRef), StaticRegionTyParamBound, UnboxedFnTyParamBound(UnboxedFnTy), OtherRegionTyParamBound(Span) // FIXME -- just here until work for #5723 lands } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct TyParam { pub ident: Ident, pub id: NodeId, pub bounds: OwnedSlice, pub unbound: Option, pub default: Option>, pub span: Span } /// Represents lifetimes and type parameters attached to a declaration /// of a function, enum, trait, etc. #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Generics { pub lifetimes: Vec, pub ty_params: OwnedSlice, } impl Generics { pub fn is_parameterized(&self) -> bool { self.lifetimes.len() + self.ty_params.len() > 0 } pub fn is_lt_parameterized(&self) -> bool { self.lifetimes.len() > 0 } pub fn is_type_parameterized(&self) -> bool { self.ty_params.len() > 0 } } /// The set of MetaItems that define the compilation environment of the crate, /// used to drive conditional compilation pub type CrateConfig = Vec> ; #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Crate { pub module: Mod, pub attrs: Vec, pub config: CrateConfig, pub span: Span, pub exported_macros: Vec } pub type MetaItem = Spanned; #[deriving(Clone, Encodable, Decodable, Eq, Hash)] pub enum MetaItem_ { MetaWord(InternedString), MetaList(InternedString, Vec>), MetaNameValue(InternedString, Lit), } // can't be derived because the MetaList requires an unordered comparison impl PartialEq for MetaItem_ { fn eq(&self, other: &MetaItem_) -> bool { match *self { MetaWord(ref ns) => match *other { MetaWord(ref no) => (*ns) == (*no), _ => false }, MetaNameValue(ref ns, ref vs) => match *other { MetaNameValue(ref no, ref vo) => { (*ns) == (*no) && vs.node == vo.node } _ => false }, MetaList(ref ns, ref miss) => match *other { MetaList(ref no, ref miso) => { ns == no && miss.iter().all(|mi| miso.iter().any(|x| x.node == mi.node)) } _ => false } } } } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Block { pub view_items: Vec, pub stmts: Vec>, pub expr: Option>, pub id: NodeId, pub rules: BlockCheckMode, pub span: Span, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Pat { pub id: NodeId, pub node: Pat_, pub span: Span, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct FieldPat { pub ident: Ident, pub pat: Gc, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum BindingMode { BindByRef(Mutability), BindByValue(Mutability), } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum Pat_ { PatWild, PatWildMulti, /// A PatIdent may either be a new bound variable, /// or a nullary enum (in which case the third field /// is None). /// In the nullary enum case, the parser can't determine /// which it is. The resolver determines this, and /// records this pattern's NodeId in an auxiliary /// set (of "PatIdents that refer to nullary enums") PatIdent(BindingMode, SpannedIdent, Option>), PatEnum(Path, Option>>), /* "none" means a * pattern where * we don't bind the fields to names */ PatStruct(Path, Vec, bool), PatTup(Vec>), PatBox(Gc), PatRegion(Gc), // reference pattern PatLit(Gc), PatRange(Gc, Gc), /// [a, b, ..i, y, z] is represented as: /// PatVec(~[a, b], Some(i), ~[y, z]) PatVec(Vec>, Option>, Vec>), PatMac(Mac), } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum Mutability { MutMutable, MutImmutable, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum ExprVstore { /// ~[1, 2, 3, 4] ExprVstoreUniq, /// &[1, 2, 3, 4] ExprVstoreSlice, /// &mut [1, 2, 3, 4] ExprVstoreMutSlice, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum BinOp { BiAdd, BiSub, BiMul, BiDiv, BiRem, BiAnd, BiOr, BiBitXor, BiBitAnd, BiBitOr, BiShl, BiShr, BiEq, BiLt, BiLe, BiNe, BiGe, BiGt, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum UnOp { UnBox, UnUniq, UnDeref, UnNot, UnNeg } pub type Stmt = Spanned; #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum Stmt_ { /// Could be an item or a local (let) binding: StmtDecl(Gc, NodeId), /// Expr without trailing semi-colon (must have unit type): StmtExpr(Gc, NodeId), /// Expr with trailing semi-colon (may have any type): StmtSemi(Gc, NodeId), /// bool: is there a trailing sem-colon? StmtMac(Mac, bool), } /// Where a local declaration came from: either a true `let ... = /// ...;`, or one desugared from the pattern of a for loop. #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum LocalSource { LocalLet, LocalFor, } // FIXME (pending discussion of #1697, #2178...): local should really be // a refinement on pat. /// Local represents a `let` statement, e.g., `let : = ;` #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Local { pub ty: P, pub pat: Gc, pub init: Option>, pub id: NodeId, pub span: Span, pub source: LocalSource, } pub type Decl = Spanned; #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)] pub enum Decl_ { /// A local (let) binding: DeclLocal(Gc), /// An item binding: DeclItem(Gc), } /// represents one arm of a 'match' #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Arm { pub attrs: Vec, pub pats: Vec>, pub guard: Option>, pub body: Gc, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Field { pub ident: SpannedIdent, pub expr: Gc, pub span: Span, } pub type SpannedIdent = Spanned; #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum BlockCheckMode { DefaultBlock, UnsafeBlock(UnsafeSource), } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum UnsafeSource { CompilerGenerated, UserProvided, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Expr { pub id: NodeId, pub node: Expr_, pub span: Span, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum Expr_ { ExprVstore(Gc, ExprVstore), /// First expr is the place; second expr is the value. ExprBox(Gc, Gc), ExprVec(Vec>), ExprCall(Gc, Vec>), ExprMethodCall(SpannedIdent, Vec>, Vec>), ExprTup(Vec>), ExprBinary(BinOp, Gc, Gc), ExprUnary(UnOp, Gc), ExprLit(Gc), ExprCast(Gc, P), ExprIf(Gc, P, Option>), ExprWhile(Gc, P), // FIXME #6993: change to Option ... or not, if these are hygienic. ExprForLoop(Gc, Gc, P, Option), // Conditionless loop (can be exited with break, cont, or ret) // FIXME #6993: change to Option ... or not, if these are hygienic. ExprLoop(P, Option), ExprMatch(Gc, Vec), ExprFnBlock(P, P), ExprProc(P, P), ExprBlock(P), ExprAssign(Gc, Gc), ExprAssignOp(BinOp, Gc, Gc), ExprField(Gc, SpannedIdent, Vec>), ExprIndex(Gc, Gc), /// Variable reference, possibly containing `::` and/or /// type parameters, e.g. foo::bar:: ExprPath(Path), ExprAddrOf(Mutability, Gc), ExprBreak(Option), ExprAgain(Option), ExprRet(Option>), ExprInlineAsm(InlineAsm), ExprMac(Mac), /// A struct literal expression. ExprStruct(Path, Vec , Option> /* base */), /// A vector literal constructed from one repeated element. ExprRepeat(Gc /* element */, Gc /* count */), /// No-op: used solely so we can pretty-print faithfully ExprParen(Gc) } /// When the main rust parser encounters a syntax-extension invocation, it /// parses the arguments to the invocation as a token-tree. This is a very /// loose structure, such that all sorts of different AST-fragments can /// be passed to syntax extensions using a uniform type. /// /// If the syntax extension is an MBE macro, it will attempt to match its /// LHS "matchers" against the provided token tree, and if it finds a /// match, will transcribe the RHS token tree, splicing in any captured /// macro_parser::matched_nonterminals into the TTNonterminals it finds. /// /// The RHS of an MBE macro is the only place a TTNonterminal or TTSeq /// makes any real sense. You could write them elsewhere but nothing /// else knows what to do with them, so you'll probably get a syntax /// error. #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] #[doc="For macro invocations; parsing is delegated to the macro"] pub enum TokenTree { /// A single token TTTok(Span, ::parse::token::Token), /// A delimited sequence (the delimiters appear as the first /// and last elements of the vector) // FIXME(eddyb) #6308 Use Rc<[TokenTree]> after DST. TTDelim(Rc>), // These only make sense for right-hand-sides of MBE macros: /// A kleene-style repetition sequence with a span, a TTForest, /// an optional separator, and a boolean where true indicates /// zero or more (..), and false indicates one or more (+). // FIXME(eddyb) #6308 Use Rc<[TokenTree]> after DST. TTSeq(Span, Rc>, Option<::parse::token::Token>, bool), /// A syntactic variable that will be filled in by macro expansion. TTNonterminal(Span, Ident) } // Matchers are nodes defined-by and recognized-by the main rust parser and // language, but they're only ever found inside syntax-extension invocations; // indeed, the only thing that ever _activates_ the rules in the rust parser // for parsing a matcher is a matcher looking for the 'matchers' nonterminal // itself. Matchers represent a small sub-language for pattern-matching // token-trees, and are thus primarily used by the macro-defining extension // itself. // // MatchTok // -------- // // A matcher that matches a single token, denoted by the token itself. So // long as there's no $ involved. // // // MatchSeq // -------- // // A matcher that matches a sequence of sub-matchers, denoted various // possible ways: // // $(M)* zero or more Ms // $(M)+ one or more Ms // $(M),+ one or more comma-separated Ms // $(A B C);* zero or more semi-separated 'A B C' seqs // // // MatchNonterminal // ----------------- // // A matcher that matches one of a few interesting named rust // nonterminals, such as types, expressions, items, or raw token-trees. A // black-box matcher on expr, for example, binds an expr to a given ident, // and that ident can re-occur as an interpolation in the RHS of a // macro-by-example rule. For example: // // $foo:expr => 1 + $foo // interpolate an expr // $foo:tt => $foo // interpolate a token-tree // $foo:tt => bar! $foo // only other valid interpolation // // is in arg position for another // // macro // // As a final, horrifying aside, note that macro-by-example's input is // also matched by one of these matchers. Holy self-referential! It is matched // by a MatchSeq, specifically this one: // // $( $lhs:matchers => $rhs:tt );+ // // If you understand that, you have closed the loop and understand the whole // macro system. Congratulations. pub type Matcher = Spanned; #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum Matcher_ { /// Match one token MatchTok(::parse::token::Token), /// Match repetitions of a sequence: body, separator, zero ok?, /// lo, hi position-in-match-array used: MatchSeq(Vec , Option<::parse::token::Token>, bool, uint, uint), /// Parse a Rust NT: name to bind, name of NT, position in match array: MatchNonterminal(Ident, Ident, uint) } pub type Mac = Spanned; /// Represents a macro invocation. The Path indicates which macro /// is being invoked, and the vector of token-trees contains the source /// of the macro invocation. /// There's only one flavor, now, so this could presumably be simplified. #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum Mac_ { // NB: the additional ident for a macro_rules-style macro is actually // stored in the enclosing item. Oog. MacInvocTT(Path, Vec , SyntaxContext), // new macro-invocation } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum StrStyle { CookedStr, RawStr(uint) } pub type Lit = Spanned; #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum Lit_ { LitStr(InternedString, StrStyle), LitBinary(Rc >), LitByte(u8), LitChar(char), LitInt(i64, IntTy), LitUint(u64, UintTy), LitIntUnsuffixed(i64), LitFloat(InternedString, FloatTy), LitFloatUnsuffixed(InternedString), LitNil, LitBool(bool), } // NB: If you change this, you'll probably want to change the corresponding // type structure in middle/ty.rs as well. #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct MutTy { pub ty: P, pub mutbl: Mutability, } #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)] pub struct TypeField { pub ident: Ident, pub mt: MutTy, pub span: Span, } /// Represents a required method in a trait declaration, /// one without a default implementation #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct TypeMethod { pub ident: Ident, pub attrs: Vec, pub fn_style: FnStyle, pub decl: P, pub generics: Generics, pub explicit_self: ExplicitSelf, pub id: NodeId, pub span: Span, pub vis: Visibility, } /// Represents a method declaration in a trait declaration, possibly including /// a default implementation A trait method is either required (meaning it /// doesn't have an implementation, just a signature) or provided (meaning it /// has a default implementation). #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum TraitMethod { Required(TypeMethod), Provided(Gc), } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum IntTy { TyI, TyI8, TyI16, TyI32, TyI64, } impl fmt::Show for IntTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", ast_util::int_ty_to_string(*self, None)) } } impl IntTy { pub fn suffix_len(&self) -> uint { match *self { TyI => 1, TyI8 => 2, TyI16 | TyI32 | TyI64 => 3, } } } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum UintTy { TyU, TyU8, TyU16, TyU32, TyU64, } impl UintTy { pub fn suffix_len(&self) -> uint { match *self { TyU => 1, TyU8 => 2, TyU16 | TyU32 | TyU64 => 3, } } } impl fmt::Show for UintTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", ast_util::uint_ty_to_string(*self, None)) } } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum FloatTy { TyF32, TyF64, } impl fmt::Show for FloatTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", ast_util::float_ty_to_string(*self)) } } impl FloatTy { pub fn suffix_len(&self) -> uint { match *self { TyF32 | TyF64 => 3, // add F128 handling here } } } // NB PartialEq method appears below. #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Ty { pub id: NodeId, pub node: Ty_, pub span: Span, } /// Not represented directly in the AST, referred to by name through a ty_path. #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum PrimTy { TyInt(IntTy), TyUint(UintTy), TyFloat(FloatTy), TyStr, TyBool, TyChar } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum Onceness { Once, Many } impl fmt::Show for Onceness { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Once => "once".fmt(f), Many => "many".fmt(f), } } } /// Represents the type of a closure #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)] pub struct ClosureTy { pub lifetimes: Vec, pub fn_style: FnStyle, pub onceness: Onceness, pub decl: P, /// Optional optvec distinguishes between "fn()" and "fn:()" so we can /// implement issue #7264. None means "fn()", which means infer a default /// bound based on pointer sigil during typeck. Some(Empty) means "fn:()", /// which means use no bounds (e.g., not even Owned on a ~fn()). pub bounds: Option>, } #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)] pub struct BareFnTy { pub fn_style: FnStyle, pub abi: Abi, pub lifetimes: Vec, pub decl: P } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct UnboxedFnTy { pub decl: P, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum Ty_ { TyNil, TyBot, /* bottom type */ TyBox(P), TyUniq(P), TyVec(P), TyFixedLengthVec(P, Gc), TyPtr(MutTy), TyRptr(Option, MutTy), TyClosure(Gc, Option), TyProc(Gc), TyBareFn(Gc), TyUnboxedFn(Gc), TyTup(Vec> ), TyPath(Path, Option>, NodeId), // for #7264; see above /// No-op; kept solely so that we can pretty-print faithfully TyParen(P), TyTypeof(Gc), /// TyInfer means the type should be inferred instead of it having been /// specified. This can appear anywhere in a type. TyInfer, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum AsmDialect { AsmAtt, AsmIntel } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct InlineAsm { pub asm: InternedString, pub asm_str_style: StrStyle, pub clobbers: InternedString, pub inputs: Vec<(InternedString, Gc)>, pub outputs: Vec<(InternedString, Gc)>, pub volatile: bool, pub alignstack: bool, pub dialect: AsmDialect } /// represents an argument in a function header #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Arg { pub ty: P, pub pat: Gc, pub id: NodeId, } impl Arg { pub fn new_self(span: Span, mutability: Mutability, self_ident: Ident) -> Arg { let path = Spanned{span:span,node:self_ident}; Arg { // HACK(eddyb) fake type for the self argument. ty: P(Ty { id: DUMMY_NODE_ID, node: TyInfer, span: DUMMY_SP, }), pat: box(GC) Pat { id: DUMMY_NODE_ID, node: PatIdent(BindByValue(mutability), path, None), span: span }, id: DUMMY_NODE_ID } } } /// represents the header (not the body) of a function declaration #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct FnDecl { pub inputs: Vec, pub output: P, pub cf: RetStyle, pub variadic: bool } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum FnStyle { /// Declared with "unsafe fn" UnsafeFn, /// Declared with "fn" NormalFn, } impl fmt::Show for FnStyle { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { NormalFn => "normal".fmt(f), UnsafeFn => "unsafe".fmt(f), } } } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum RetStyle { /// Functions with return type ! that always /// raise an error or exit (i.e. never return to the caller) NoReturn, /// Everything else Return, } /// Represents the kind of 'self' associated with a method #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum ExplicitSelf_ { /// No self SelfStatic, /// `self SelfValue(Ident), /// `&'lt self`, `&'lt mut self` SelfRegion(Option, Mutability, Ident), /// `~self` SelfUniq(Ident) } pub type ExplicitSelf = Spanned; #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Method { pub attrs: Vec, pub id: NodeId, pub span: Span, pub node: Method_ } #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)] pub enum Method_ { /// Represents a method declaration MethDecl(Ident, Generics, ExplicitSelf, FnStyle, P, P, Visibility), /// Represents a macro in method position MethMac(Mac), } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Mod { /// A span from the first token past `{` to the last token until `}`. /// For `mod foo;`, the inner span ranges from the first token /// to the last token in the external file. pub inner: Span, pub view_items: Vec, pub items: Vec>, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct ForeignMod { pub abi: Abi, pub view_items: Vec, pub items: Vec>, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct VariantArg { pub ty: P, pub id: NodeId, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum VariantKind { TupleVariantKind(Vec), StructVariantKind(Gc), } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct EnumDef { pub variants: Vec>, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Variant_ { pub name: Ident, pub attrs: Vec, pub kind: VariantKind, pub id: NodeId, pub disr_expr: Option>, pub vis: Visibility, } pub type Variant = Spanned; #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct PathListIdent_ { pub name: Ident, pub id: NodeId, } pub type PathListIdent = Spanned; pub type ViewPath = Spanned; #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)] pub enum ViewPath_ { /// `quux = foo::bar::baz` /// /// or just /// /// `foo::bar::baz ` (with 'baz =' implicitly on the left) ViewPathSimple(Ident, Path, NodeId), /// `foo::bar::*` ViewPathGlob(Path, NodeId), /// `foo::bar::{a,b,c}` ViewPathList(Path, Vec , NodeId) } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct ViewItem { pub node: ViewItem_, pub attrs: Vec, pub vis: Visibility, pub span: Span, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum ViewItem_ { /// Ident: name used to refer to this crate in the code /// optional (InternedString,StrStyle): if present, this is a location /// (containing arbitrary characters) from which to fetch the crate sources /// For example, extern crate whatever = "github.com/rust-lang/rust" ViewItemExternCrate(Ident, Option<(InternedString,StrStyle)>, NodeId), ViewItemUse(Gc), } /// Meta-data associated with an item pub type Attribute = Spanned; /// Distinguishes between Attributes that decorate items and Attributes that /// are contained as statements within items. These two cases need to be /// distinguished for pretty-printing. #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum AttrStyle { AttrOuter, AttrInner, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct AttrId(pub uint); /// Doc-comments are promoted to attributes that have is_sugared_doc = true #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Attribute_ { pub id: AttrId, pub style: AttrStyle, pub value: Gc, pub is_sugared_doc: bool, } /// TraitRef's appear in impls. /// resolve maps each TraitRef's ref_id to its defining trait; that's all /// that the ref_id is for. The impl_id maps to the "self type" of this impl. /// If this impl is an ItemImpl, the impl_id is redundant (it could be the /// same as the impl's node id). #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct TraitRef { pub path: Path, pub ref_id: NodeId, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum Visibility { Public, Inherited, } impl Visibility { pub fn inherit_from(&self, parent_visibility: Visibility) -> Visibility { match self { &Inherited => parent_visibility, &Public => *self } } } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct StructField_ { pub kind: StructFieldKind, pub id: NodeId, pub ty: P, pub attrs: Vec, } impl StructField_ { pub fn ident(&self) -> Option { match self.kind { NamedField(ref ident, _) => Some(ident.clone()), UnnamedField(_) => None } } } pub type StructField = Spanned; #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum StructFieldKind { NamedField(Ident, Visibility), /// Element of a tuple-like struct UnnamedField(Visibility), } impl StructFieldKind { pub fn is_unnamed(&self) -> bool { match *self { UnnamedField(..) => true, NamedField(..) => false, } } } #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)] pub struct StructDef { /// Fields, not including ctor pub fields: Vec, /// ID of the constructor. This is only used for tuple- or enum-like /// structs. pub ctor_id: Option, /// Super struct, if specified. pub super_struct: Option>, /// True iff the struct may be inherited from. pub is_virtual: bool, } /* FIXME (#3300): Should allow items to be anonymous. Right now we just use dummy names for anon items. */ #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct Item { pub ident: Ident, pub attrs: Vec, pub id: NodeId, pub node: Item_, pub vis: Visibility, pub span: Span, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum Item_ { ItemStatic(P, Mutability, Gc), ItemFn(P, FnStyle, Abi, Generics, P), ItemMod(Mod), ItemForeignMod(ForeignMod), ItemTy(P, Generics), ItemEnum(EnumDef, Generics), ItemStruct(Gc, Generics), /// Represents a Trait Declaration ItemTrait(Generics, Option, // (optional) default bound not required for Self. // Currently, only Sized makes sense here. Vec , Vec), ItemImpl(Generics, Option, // (optional) trait this impl implements P, // self Vec>), /// A macro invocation (which includes macro definition) ItemMac(Mac), } #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)] pub struct ForeignItem { pub ident: Ident, pub attrs: Vec, pub node: ForeignItem_, pub id: NodeId, pub span: Span, pub vis: Visibility, } #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)] pub enum ForeignItem_ { ForeignItemFn(P, Generics), ForeignItemStatic(P, /* is_mutbl */ bool), } /// The data we save and restore about an inlined item or method. This is not /// part of the AST that we parse from a file, but it becomes part of the tree /// that we trans. #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)] pub enum InlinedItem { IIItem(Gc), IIMethod(DefId /* impl id */, bool /* is provided */, Gc), IIForeign(Gc), } #[cfg(test)] mod test { use serialize::json; use serialize; use codemap::*; use super::*; // are ASTs encodable? #[test] fn check_asts_encodable() { use std::io; let e = Crate { module: Mod { inner: Span { lo: BytePos(11), hi: BytePos(19), expn_info: None, }, view_items: Vec::new(), items: Vec::new(), }, attrs: Vec::new(), config: Vec::new(), span: Span { lo: BytePos(10), hi: BytePos(20), expn_info: None, }, exported_macros: Vec::new(), }; // doesn't matter which encoder we use.... let _f = &e as &serialize::Encodable; } }