Skip to content

Hygiene fns and cleanup #6559

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 16 additions & 12 deletions doc/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -2250,6 +2250,14 @@ do_expr : "do" expr [ '|' ident_list '|' ] ? '{' block '}' ;
A _do expression_ provides a more-familiar block-syntax for a [lambda expression](#lambda-expressions),
including a special translation of [return expressions](#return-expressions) inside the supplied block.

Any occurrence of a [return expression](#return-expressions)
inside this `block` expression is rewritten
as a reference to an (anonymous) flag set in the caller's environment,
which is checked on return from the `expr` and, if set,
causes a corresponding return from the caller.
In this way, the meaning of `return` statements in language built-in control blocks is preserved,
if they are rewritten using lambda functions and `do` expressions as abstractions.

The optional `ident_list` and `block` provided in a `do` expression are parsed as though they constitute a lambda expression;
if the `ident_list` is missing, an empty `ident_list` is implied.

Expand Down Expand Up @@ -2296,19 +2304,15 @@ A _for expression_ is similar to a [`do` expression](#do-expressions),
in that it provides a special block-form of lambda expression,
suited to passing the `block` function to a higher-order function implementing a loop.

Like a `do` expression, a `return` expression inside a `for` expresison is rewritten,
to access a local flag that causes an early return in the caller.

Additionally, any occurrence of a [return expression](#return-expressions)
inside the `block` of a `for` expression is rewritten
as a reference to an (anonymous) flag set in the caller's environment,
which is checked on return from the `expr` and, if set,
causes a corresponding return from the caller.
In this way, the meaning of `return` statements in language built-in control blocks is preserved,
if they are rewritten using lambda functions and `do` expressions as abstractions.
In contrast to a `do` expression, a `for` expression is designed to work
with methods such as `each` and `times`, that require the body block to
return a boolean. The `for` expression accommodates this by implicitly
returning `true` at the end of each block, unless a `break` expression
is evaluated.

Like `return` expressions, any [`break`](#break-expressions) and [`loop`](#loop-expressions) expressions
are rewritten inside `for` expressions, with a combination of local flag variables,
In addition, [`break`](#break-expressions) and [`loop`](#loop-expressions) expressions
are rewritten inside `for` expressions in the same way that `return` expressions are,
with a combination of local flag variables,
and early boolean-valued returns from the `block` function,
such that the meaning of `break` and `loop` is preserved in a primitive loop
when rewritten as a `for` loop controlled by a higher order function.
Expand Down
18 changes: 6 additions & 12 deletions src/librustdoc/extract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,18 @@ use doc;
use core::local_data::local_data_get;
use syntax::ast;
use syntax;

/* can't import macros yet, so this is copied from token.rs. See its comment
* there. */
macro_rules! interner_key (
() => (cast::transmute::<(uint, uint),
&fn(v: @@syntax::parse::token::ident_interner)>((-3 as uint, 0u)))
)
use syntax::parse::token::{ident_interner};
use syntax::parse::token;

// Hack; rather than thread an interner through everywhere, rely on
// thread-local data
pub fn to_str(id: ast::ident) -> ~str {
let intr = unsafe{ local_data_get(interner_key!()) };

return copy *(*intr.get()).get(id);
let intr = token::get_ident_interner();
return copy *(*intr).get(id);
}

pub fn interner() -> @syntax::parse::token::ident_interner {
return *(unsafe{ local_data_get(interner_key!()) }).get();
pub fn interner() -> @ident_interner {
return token::get_ident_interner();
}

pub fn from_srv(
Expand Down
36 changes: 16 additions & 20 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
use codemap::{span, spanned};
use abi::AbiSet;
use opt_vec::OptVec;
use parse::token::get_ident_interner;

use core::cast;
use core::option::{None, Option, Some};
use core::option::{Option};
use core::to_bytes;
use core::to_bytes::IterBytes;
use core::to_str::ToStr;
use core::hashmap::HashMap;
use std::serialize::{Encodable, Decodable, Encoder, Decoder};


Expand All @@ -38,14 +40,20 @@ pub struct ident { repr: Name, ctxt: SyntaxContext }
// 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
// syntax context.

// this uint is a reference to a table stored in thread-local
// storage.
pub type SyntaxContext = uint;

pub type SCTable = ~[SyntaxContext_];
pub struct SCTable {
table : ~[SyntaxContext_],
mark_memo : HashMap<(SyntaxContext,Mrk),SyntaxContext>,
rename_memo : HashMap<(SyntaxContext,ident,Name),SyntaxContext>
}
// NB: these must be placed in any SCTable...
pub static empty_ctxt : uint = 0;
pub static illegal_ctxt : uint = 1;

#[deriving(Eq, Encodable, Decodable)]
pub enum SyntaxContext_ {
Expand All @@ -59,7 +67,8 @@ pub enum SyntaxContext_ {
// "to" slot must have the same name and context
// in the "from" slot. In essence, they're all
// pointers to a single "rename" event node.
Rename (ident,Name,SyntaxContext)
Rename (ident,Name,SyntaxContext),
IllegalCtxt()
}

// a name represents an identifier
Expand All @@ -70,27 +79,14 @@ pub type Mrk = uint;

impl<S:Encoder> Encodable<S> for ident {
fn encode(&self, s: &mut S) {
unsafe {
let intr =
match local_data::local_data_get(interner_key!()) {
None => fail!("encode: TLS interner not set up"),
Some(intr) => intr
};

s.emit_str(*(*intr).get(*self));
}
let intr = get_ident_interner();
s.emit_str(*(*intr).get(*self));
}
}

impl<D:Decoder> Decodable<D> for ident {
fn decode(d: &mut D) -> ident {
let intr = match unsafe {
local_data::local_data_get(interner_key!())
} {
None => fail!("decode: TLS interner not set up"),
Some(intr) => intr
};

let intr = get_ident_interner();
(*intr).intern(d.read_str())
}
}
Expand Down
Loading