diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2013-03-13 22:25:28 -0400 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2013-03-29 18:36:20 -0700 |
| commit | 6965fe4bceea836586bd8e7aa01a92a35b467f78 (patch) | |
| tree | d95089f050cd67db2a5171a799763faa09f5b0a8 /src/libsyntax/parse | |
| parent | f864934f548be9f03d2c0512de8d7e908469e2ae (diff) | |
| download | rust-6965fe4bceea836586bd8e7aa01a92a35b467f78.tar.gz rust-6965fe4bceea836586bd8e7aa01a92a35b467f78.zip | |
Add AbiSet and integrate it into the AST.
I believe this patch incorporates all expected syntax changes from extern
function reform (#3678). You can now write things like:
extern "<abi>" fn foo(s: S) -> T { ... }
extern "<abi>" mod { ... }
extern "<abi>" fn(S) -> T
The ABI for foreign functions is taken from this syntax (rather than from an
annotation). We support the full ABI specification I described on the mailing
list. The correct ABI is chosen based on the target architecture.
Calls by pointer to C functions are not yet supported, and the Rust type of
crust fns is still *u8.
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 113 |
1 files changed, 75 insertions, 38 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ac0e42fc65d..353e3014cf7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -10,7 +10,9 @@ use core::prelude::*; -use ast::{Sigil, BorrowedSigil, ManagedSigil, OwnedSigil, RustAbi}; +use abi; +use abi::AbiSet; +use ast::{Sigil, BorrowedSigil, ManagedSigil, OwnedSigil}; use ast::{CallSugar, NoSugar, DoSugar, ForSugar}; use ast::{TyBareFn, TyClosure}; use ast::{RegionTyParamBound, TraitTyParamBound}; @@ -361,11 +363,13 @@ pub impl Parser { */ + let opt_abis = self.parse_opt_abis(); + let abis = opt_abis.get_or_default(AbiSet::Rust()); let purity = self.parse_purity(); self.expect_keyword(&~"fn"); let (decl, lifetimes) = self.parse_ty_fn_decl(); return ty_bare_fn(@TyBareFn { - abi: RustAbi, + abis: abis, purity: purity, lifetimes: lifetimes, decl: decl @@ -3041,11 +3045,13 @@ pub impl Parser { span: mk_sp(lo, hi) } } - fn parse_item_fn(&self, purity: purity) -> item_info { + fn parse_item_fn(&self, purity: purity, abis: AbiSet) -> item_info { let (ident, generics) = self.parse_fn_header(); let decl = self.parse_fn_decl(|p| p.parse_arg()); let (inner_attrs, body) = self.parse_inner_attrs_and_block(true); - (ident, item_fn(decl, purity, generics, body), Some(inner_attrs)) + (ident, + item_fn(decl, purity, abis, generics, body), + Some(inner_attrs)) } fn parse_method(&self) -> @method { @@ -3607,7 +3613,7 @@ pub impl Parser { } fn parse_foreign_mod_items(&self, sort: ast::foreign_mod_sort, - +abi: ast::ident, + +abis: AbiSet, +first_item_attrs: ~[attribute]) -> foreign_mod { // Shouldn't be any view items since we've already parsed an item attr @@ -3630,30 +3636,20 @@ pub impl Parser { } ast::foreign_mod { sort: sort, - abi: abi, + abis: abis, view_items: view_items, items: items } } - fn parse_item_foreign_mod(&self, lo: BytePos, + fn parse_item_foreign_mod(&self, + lo: BytePos, + opt_abis: Option<AbiSet>, visibility: visibility, attrs: ~[attribute], items_allowed: bool) - -> item_or_view_item { - - // Parse the ABI. - let abi_opt; - match *self.token { - token::LIT_STR(copy found_abi) => { - self.bump(); - abi_opt = Some(found_abi); - } - _ => { - abi_opt = None; - } - } - + -> item_or_view_item + { let mut must_be_named_mod = false; if self.is_keyword(&~"mod") { must_be_named_mod = true; @@ -3688,14 +3684,10 @@ pub impl Parser { // extern mod { ... } if items_allowed && self.eat(&token::LBRACE) { - let abi; - match abi_opt { - Some(found_abi) => abi = found_abi, - None => abi = special_idents::c_abi, - } + let abis = opt_abis.get_or_default(AbiSet::C()); let (inner, next) = self.parse_inner_attrs_and_next(); - let m = self.parse_foreign_mod_items(sort, abi, next); + let m = self.parse_foreign_mod_items(sort, abis, next); self.expect(&token::RBRACE); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, @@ -3704,12 +3696,8 @@ pub impl Parser { Some(inner)))); } - match abi_opt { - None => {} // OK. - Some(_) => { - self.span_err(*self.span, ~"an ABI may not be specified \ - here"); - } + if opt_abis.is_some() { + self.span_err(*self.span, ~"an ABI may not be specified here"); } // extern mod foo; @@ -3913,6 +3901,49 @@ pub impl Parser { } } + fn parse_opt_abis(&self) -> Option<AbiSet> { + match *self.token { + token::LIT_STR(s) => { + self.bump(); + let the_string = self.id_to_str(s); + let mut words = ~[]; + for str::each_word(*the_string) |s| { words.push(s) } + let mut abis = AbiSet::empty(); + for words.each |word| { + match abi::lookup(*word) { + Some(abi) => { + if abis.contains(abi) { + self.span_err( + *self.span, + fmt!("ABI `%s` appears twice", + *word)); + } else { + abis.add(abi); + } + } + + None => { + self.span_err( + *self.span, + fmt!("illegal ABI: \ + expected one of [%s], \ + found `%s`", + str::connect_slices( + abi::all_names(), + ", "), + *word)); + } + } + } + Some(abis) + } + + _ => { + None + } + } + } + // parse one of the items or view items allowed by the // flags; on failure, return iovi_none. fn parse_item_or_view_item( @@ -3961,7 +3992,8 @@ pub impl Parser { self.is_keyword(&~"fn") && !self.fn_expr_lookahead(self.look_ahead(1u)) { self.bump(); - let (ident, item_, extra_attrs) = self.parse_item_fn(impure_fn); + let (ident, item_, extra_attrs) = + self.parse_item_fn(impure_fn, AbiSet::Rust()); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); @@ -3970,7 +4002,8 @@ pub impl Parser { // PURE FUNCTION ITEM self.obsolete(*self.last_span, ObsoletePurity); self.expect_keyword(&~"fn"); - let (ident, item_, extra_attrs) = self.parse_item_fn(impure_fn); + let (ident, item_, extra_attrs) = + self.parse_item_fn(impure_fn, AbiSet::Rust()); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); @@ -3987,16 +4020,20 @@ pub impl Parser { // UNSAFE FUNCTION ITEM (where items are allowed) self.bump(); self.expect_keyword(&~"fn"); - let (ident, item_, extra_attrs) = self.parse_item_fn(unsafe_fn); + let (ident, item_, extra_attrs) = + self.parse_item_fn(unsafe_fn, AbiSet::Rust()); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); } if self.eat_keyword(&~"extern") { + let opt_abis = self.parse_opt_abis(); + if items_allowed && self.eat_keyword(&~"fn") { // EXTERN FUNCTION ITEM + let abis = opt_abis.get_or_default(AbiSet::C()); let (ident, item_, extra_attrs) = - self.parse_item_fn(extern_fn); + self.parse_item_fn(extern_fn, abis); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, @@ -4004,7 +4041,7 @@ pub impl Parser { } if !foreign_items_allowed { // EXTERN MODULE ITEM - return self.parse_item_foreign_mod(lo, visibility, attrs, + return self.parse_item_foreign_mod(lo, opt_abis, visibility, attrs, items_allowed); } } |
