added MTWT functions
This commit is contained in:
parent
1083ae6b06
commit
7e4cd09e2e
5 changed files with 461 additions and 65 deletions
|
@ -27,32 +27,48 @@ use std::serialize::{Encodable, Decodable, Encoder, Decoder};
|
||||||
// macro expansion per Flatt et al., "Macros
|
// macro expansion per Flatt et al., "Macros
|
||||||
// That Work Together"
|
// That Work Together"
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq)]
|
||||||
pub struct ident { repr: Name }
|
pub struct ident { repr: Name, ctxt: SyntaxContext }
|
||||||
|
|
||||||
// a SyntaxContext represents a chain of macro-expandings
|
// a SyntaxContext represents a chain of macro-expandings
|
||||||
// and renamings. Each macro expansion corresponds to
|
// and renamings. Each macro expansion corresponds to
|
||||||
// a fresh uint
|
// 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 = uint;
|
||||||
|
|
||||||
|
pub type SCTable = ~[SyntaxContext_];
|
||||||
|
pub static empty_ctxt : uint = 0;
|
||||||
|
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq)]
|
||||||
pub enum SyntaxContext {
|
#[auto_encode]
|
||||||
MT,
|
#[auto_decode]
|
||||||
Mark (Mrk,~SyntaxContext),
|
pub enum SyntaxContext_ {
|
||||||
Rename (~ident,Name,~SyntaxContext)
|
EmptyCtxt,
|
||||||
|
Mark (Mrk,SyntaxContext),
|
||||||
|
// flattening the name and syntaxcontext into the rename...
|
||||||
|
// HIDDEN INVARIANTS:
|
||||||
|
// 1) the first name in a Rename node
|
||||||
|
// can only be a programmer-supplied name.
|
||||||
|
// 2) Every Rename node with a given Name in the
|
||||||
|
// "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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// a name represents an identifier
|
||||||
// ** this is going to have to apply to paths, not to idents.
|
pub type Name = uint;
|
||||||
// Returns true if these two identifiers access the same
|
|
||||||
// local binding or top-level binding... that's what it
|
|
||||||
// should do. For now, it just compares the names.
|
|
||||||
pub fn free_ident_eq (a : ident, b: ident) -> bool{
|
|
||||||
a.repr == b.repr
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// a name represents a string, interned
|
|
||||||
type Name = uint;
|
|
||||||
// a mark represents a unique id associated
|
// a mark represents a unique id associated
|
||||||
// with a macro expansion
|
// with a macro expansion
|
||||||
type Mrk = uint;
|
pub type Mrk = uint;
|
||||||
|
|
||||||
impl<S:Encoder> Encodable<S> for ident {
|
impl<S:Encoder> Encodable<S> for ident {
|
||||||
fn encode(&self, s: &S) {
|
fn encode(&self, s: &S) {
|
||||||
|
@ -1302,22 +1318,77 @@ pub enum inlined_item {
|
||||||
ii_dtor(struct_dtor, ident, Generics, def_id /* parent id */)
|
ii_dtor(struct_dtor, ident, Generics, def_id /* parent id */)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* hold off on tests ... they appear in a later merge.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
//are asts encodable?
|
use core::option::{None, Option, Some};
|
||||||
|
use core::uint;
|
||||||
// it looks like this *will* be a compiler bug, after
|
|
||||||
// I get deriving_eq for crates into incoming :)
|
|
||||||
/*
|
|
||||||
use std;
|
use std;
|
||||||
use codemap::*;
|
use codemap::*;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|
||||||
|
#[test] fn xorpush_test () {
|
||||||
|
let mut s = ~[];
|
||||||
|
xorPush(&mut s,14);
|
||||||
|
assert_eq!(s,~[14]);
|
||||||
|
xorPush(&mut s,14);
|
||||||
|
assert_eq!(s,~[]);
|
||||||
|
xorPush(&mut s,14);
|
||||||
|
assert_eq!(s,~[14]);
|
||||||
|
xorPush(&mut s,15);
|
||||||
|
assert_eq!(s,~[14,15]);
|
||||||
|
xorPush (&mut s,16);
|
||||||
|
assert_eq! (s,~[14,15,16]);
|
||||||
|
xorPush (&mut s,16);
|
||||||
|
assert_eq! (s,~[14,15]);
|
||||||
|
xorPush (&mut s,15);
|
||||||
|
assert_eq! (s,~[14]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test] fn test_marksof () {
|
||||||
|
let stopname = uints_to_name(&~[12,14,78]);
|
||||||
|
let name1 = uints_to_name(&~[4,9,7]);
|
||||||
|
assert_eq!(marksof (MT,stopname),~[]);
|
||||||
|
assert_eq! (marksof (Mark (4,@Mark(98,@MT)),stopname),~[4,98]);
|
||||||
|
// does xoring work?
|
||||||
|
assert_eq! (marksof (Mark (5, @Mark (5, @Mark (16,@MT))),stopname),
|
||||||
|
~[16]);
|
||||||
|
// does nested xoring work?
|
||||||
|
assert_eq! (marksof (Mark (5,
|
||||||
|
@Mark (10,
|
||||||
|
@Mark (10,
|
||||||
|
@Mark (5,
|
||||||
|
@Mark (16,@MT))))),
|
||||||
|
stopname),
|
||||||
|
~[16]);
|
||||||
|
// stop has no effect on marks
|
||||||
|
assert_eq! (marksof (Mark (9, @Mark (14, @Mark (12, @MT))),stopname),
|
||||||
|
~[9,14,12]);
|
||||||
|
// rename where stop doesn't match:
|
||||||
|
assert_eq! (marksof (Mark (9, @Rename
|
||||||
|
(name1,
|
||||||
|
@Mark (4, @MT),
|
||||||
|
uints_to_name(&~[100,101,102]),
|
||||||
|
@Mark (14, @MT))),
|
||||||
|
stopname),
|
||||||
|
~[9,14]);
|
||||||
|
// rename where stop does match
|
||||||
|
;
|
||||||
|
assert_eq! (marksof (Mark(9, @Rename (name1,
|
||||||
|
@Mark (4, @MT),
|
||||||
|
stopname,
|
||||||
|
@Mark (14, @MT))),
|
||||||
|
stopname),
|
||||||
|
~[9]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// are ASTs encodable?
|
||||||
#[test] fn check_asts_encodable() {
|
#[test] fn check_asts_encodable() {
|
||||||
let bogus_span = span {lo:BytePos(10),
|
let bogus_span = span {lo:BytePos(10),
|
||||||
hi:BytePos(20),
|
hi:BytePos(20),
|
||||||
expn_info:None};
|
expn_info:None};
|
||||||
let _e : crate =
|
let e : crate =
|
||||||
spanned{
|
spanned{
|
||||||
node: crate_{
|
node: crate_{
|
||||||
module: _mod {view_items: ~[], items: ~[]},
|
module: _mod {view_items: ~[], items: ~[]},
|
||||||
|
@ -1326,10 +1397,13 @@ mod test {
|
||||||
},
|
},
|
||||||
span: bogus_span};
|
span: bogus_span};
|
||||||
// doesn't matter which encoder we use....
|
// doesn't matter which encoder we use....
|
||||||
let _f = (_e as std::serialize::Encodable::<std::json::Encoder>);
|
let _f = (@e as @std::serialize::Encodable<std::json::Encoder>);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
//
|
//
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
// mode: rust
|
// mode: rust
|
||||||
|
|
|
@ -24,6 +24,7 @@ use core::str;
|
||||||
use core::to_bytes;
|
use core::to_bytes;
|
||||||
use core::vec;
|
use core::vec;
|
||||||
|
|
||||||
|
|
||||||
pub fn path_name_i(idents: &[ident], intr: @token::ident_interner) -> ~str {
|
pub fn path_name_i(idents: &[ident], intr: @token::ident_interner) -> ~str {
|
||||||
// FIXME: Bad copies (#2543 -- same for everything else that says "bad")
|
// FIXME: Bad copies (#2543 -- same for everything else that says "bad")
|
||||||
str::connect(idents.map(|i| copy *intr.get(*i)), ~"::")
|
str::connect(idents.map(|i| copy *intr.get(*i)), ~"::")
|
||||||
|
@ -587,6 +588,280 @@ pub enum Privacy {
|
||||||
Public
|
Public
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HYGIENE FUNCTIONS
|
||||||
|
|
||||||
|
/// Construct an identifier with the given repr and an empty context:
|
||||||
|
pub fn mk_ident(repr: uint) -> ident { ident {repr: repr, ctxt: 0}}
|
||||||
|
|
||||||
|
/// Extend a syntax context with a given mark
|
||||||
|
pub fn mk_mark (m:Mrk,ctxt:SyntaxContext,table:&mut SCTable)
|
||||||
|
-> SyntaxContext {
|
||||||
|
idx_push(table,Mark(m,ctxt))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extend a syntax context with a given rename
|
||||||
|
pub fn mk_rename (id:ident, to:Name, tail:SyntaxContext, table: &mut SCTable)
|
||||||
|
-> SyntaxContext {
|
||||||
|
idx_push(table,Rename(id,to,tail))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Make a fresh syntax context table with EmptyCtxt in slot zero
|
||||||
|
pub fn mk_sctable() -> SCTable { ~[EmptyCtxt] }
|
||||||
|
|
||||||
|
/// Add a value to the end of a vec, return its index
|
||||||
|
fn idx_push<T>(vec: &mut ~[T], +val: T) -> uint {
|
||||||
|
vec.push(val);
|
||||||
|
vec.len() - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolve a syntax object to a name, per MTWT.
|
||||||
|
pub fn resolve (id : ident, table : &SCTable) -> Name {
|
||||||
|
match table[id.ctxt] {
|
||||||
|
EmptyCtxt => id.repr,
|
||||||
|
// ignore marks here:
|
||||||
|
Mark(_,subctxt) => resolve (ident{repr:id.repr, ctxt: subctxt},table),
|
||||||
|
// do the rename if necessary:
|
||||||
|
Rename(ident{repr,ctxt},toname,subctxt) => {
|
||||||
|
// this could be cached or computed eagerly:
|
||||||
|
let resolvedfrom = resolve(ident{repr:repr,ctxt:ctxt},table);
|
||||||
|
let resolvedthis = resolve(ident{repr:id.repr,ctxt:subctxt},table);
|
||||||
|
if ((resolvedthis == resolvedfrom)
|
||||||
|
&& (marksof (ctxt,resolvedthis,table)
|
||||||
|
== marksof (subctxt,resolvedthis,table))) {
|
||||||
|
toname
|
||||||
|
} else {
|
||||||
|
resolvedthis
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compute the marks associated with a syntax context.
|
||||||
|
// it's not clear to me whether it's better to use a [] mutable
|
||||||
|
// vector or a cons-list for this.
|
||||||
|
pub fn marksof(ctxt: SyntaxContext, stopname: Name, table: &SCTable) -> ~[Mrk] {
|
||||||
|
let mut result = ~[];
|
||||||
|
let mut loopvar = ctxt;
|
||||||
|
loop {
|
||||||
|
match table[loopvar] {
|
||||||
|
EmptyCtxt => {return result;},
|
||||||
|
Mark(mark,tl) => {
|
||||||
|
xorPush(&mut result,mark);
|
||||||
|
loopvar = tl;
|
||||||
|
},
|
||||||
|
Rename(_,name,tl) => {
|
||||||
|
// see MTWT for details on the purpose of the stopname.
|
||||||
|
// short version: it prevents duplication of effort.
|
||||||
|
if (name == stopname) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
loopvar = tl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Push a name... unless it matches the one on top, in which
|
||||||
|
/// case pop and discard (so two of the same marks cancel)
|
||||||
|
pub fn xorPush(marks: &mut ~[uint], mark: uint) {
|
||||||
|
if ((marks.len() > 0) && (getLast(marks) == mark)) {
|
||||||
|
marks.pop();
|
||||||
|
} else {
|
||||||
|
marks.push(mark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the last element of a mutable array.
|
||||||
|
// FIXME #4903: , must be a separate procedure for now.
|
||||||
|
pub fn getLast(arr: &~[Mrk]) -> uint {
|
||||||
|
*arr.last()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use ast::*;
|
||||||
|
use super::*;
|
||||||
|
use core::io;
|
||||||
|
|
||||||
|
#[test] fn xorpush_test () {
|
||||||
|
let mut s = ~[];
|
||||||
|
xorPush(&mut s,14);
|
||||||
|
assert_eq!(s,~[14]);
|
||||||
|
xorPush(&mut s,14);
|
||||||
|
assert_eq!(s,~[]);
|
||||||
|
xorPush(&mut s,14);
|
||||||
|
assert_eq!(s,~[14]);
|
||||||
|
xorPush(&mut s,15);
|
||||||
|
assert_eq!(s,~[14,15]);
|
||||||
|
xorPush (&mut s,16);
|
||||||
|
assert_eq! (s,~[14,15,16]);
|
||||||
|
xorPush (&mut s,16);
|
||||||
|
assert_eq! (s,~[14,15]);
|
||||||
|
xorPush (&mut s,15);
|
||||||
|
assert_eq! (s,~[14]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert a list of uints to an @~[ident]
|
||||||
|
// (ignores the interner completely)
|
||||||
|
fn uints_to_idents (uints: &~[uint]) -> @~[ident] {
|
||||||
|
@uints.map(|u|{ ident {repr:*u, ctxt: empty_ctxt} })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn id (u : uint, s: SyntaxContext) -> ident {
|
||||||
|
ident{repr:u, ctxt: s}
|
||||||
|
}
|
||||||
|
|
||||||
|
// because of the SCTable, I now need a tidy way of
|
||||||
|
// creating syntax objects. Sigh.
|
||||||
|
#[deriving(Eq)]
|
||||||
|
enum TestSC {
|
||||||
|
M(Mrk),
|
||||||
|
R(ident,Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// unfold a vector of TestSC values into a SCTable,
|
||||||
|
// returning the resulting index
|
||||||
|
fn unfold_test_sc(tscs : ~[TestSC], tail: SyntaxContext, table : &mut SCTable)
|
||||||
|
-> SyntaxContext {
|
||||||
|
tscs.foldr(tail, |tsc : &TestSC,tail : SyntaxContext|
|
||||||
|
{match *tsc {
|
||||||
|
M(mrk) => mk_mark(mrk,tail,table),
|
||||||
|
R(ident,name) => mk_rename(ident,name,tail,table)}})
|
||||||
|
}
|
||||||
|
|
||||||
|
// gather a SyntaxContext back into a vector of TestSCs
|
||||||
|
fn refold_test_sc(mut sc: SyntaxContext, table : &SCTable) -> ~[TestSC] {
|
||||||
|
let mut result = ~[];
|
||||||
|
loop {
|
||||||
|
match table[sc] {
|
||||||
|
EmptyCtxt => {return result;},
|
||||||
|
Mark(mrk,tail) => {
|
||||||
|
result.push(M(mrk));
|
||||||
|
sc = tail;
|
||||||
|
loop;
|
||||||
|
},
|
||||||
|
Rename(id,name,tail) => {
|
||||||
|
result.push(R(id,name));
|
||||||
|
sc = tail;
|
||||||
|
loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test] fn test_unfold_refold(){
|
||||||
|
let mut t = mk_sctable();
|
||||||
|
|
||||||
|
let test_sc = ~[M(3),R(id(101,0),14),M(9)];
|
||||||
|
assert_eq!(unfold_test_sc(test_sc,empty_ctxt,&mut t),3);
|
||||||
|
assert_eq!(t[1],Mark(9,0));
|
||||||
|
assert_eq!(t[2],Rename(id(101,0),14,1));
|
||||||
|
assert_eq!(t[3],Mark(3,2));
|
||||||
|
assert_eq!(refold_test_sc(3,&t),test_sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// extend a syntax context with a sequence of marks given
|
||||||
|
// in a vector. v[0] will be the outermost mark.
|
||||||
|
fn unfold_marks(mrks:~[Mrk],tail:SyntaxContext,table: &mut SCTable) -> SyntaxContext {
|
||||||
|
mrks.foldr(tail, |mrk:&Mrk,tail:SyntaxContext|
|
||||||
|
{mk_mark(*mrk,tail,table)})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test] fn unfold_marks_test() {
|
||||||
|
let mut t = ~[EmptyCtxt];
|
||||||
|
|
||||||
|
assert_eq!(unfold_marks(~[3,7],empty_ctxt,&mut t),2);
|
||||||
|
assert_eq!(t[1],Mark(7,0));
|
||||||
|
assert_eq!(t[2],Mark(3,1));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test] fn test_marksof () {
|
||||||
|
let stopname = 242;
|
||||||
|
let name1 = 243;
|
||||||
|
let mut t = mk_sctable();
|
||||||
|
assert_eq!(marksof (empty_ctxt,stopname,&t),~[]);
|
||||||
|
// FIXME #5074: ANF'd to dodge nested calls
|
||||||
|
{ let ans = unfold_marks(~[4,98],empty_ctxt,&mut t);
|
||||||
|
assert_eq! (marksof (ans,stopname,&t),~[4,98]);}
|
||||||
|
// does xoring work?
|
||||||
|
{ let ans = unfold_marks(~[5,5,16],empty_ctxt,&mut t);
|
||||||
|
assert_eq! (marksof (ans,stopname,&t), ~[16]);}
|
||||||
|
// does nested xoring work?
|
||||||
|
{ let ans = unfold_marks(~[5,10,10,5,16],empty_ctxt,&mut t);
|
||||||
|
assert_eq! (marksof (ans, stopname,&t), ~[16]);}
|
||||||
|
// rename where stop doesn't match:
|
||||||
|
{ let chain = ~[M(9),
|
||||||
|
R(id(name1,
|
||||||
|
mk_mark (4, empty_ctxt,&mut t)),
|
||||||
|
100101102),
|
||||||
|
M(14)];
|
||||||
|
let ans = unfold_test_sc(chain,empty_ctxt,&mut t);
|
||||||
|
assert_eq! (marksof (ans, stopname, &t), ~[9,14]);}
|
||||||
|
// rename where stop does match
|
||||||
|
{ let name1sc = mk_mark(4, empty_ctxt, &mut t);
|
||||||
|
let chain = ~[M(9),
|
||||||
|
R(id(name1, name1sc),
|
||||||
|
stopname),
|
||||||
|
M(14)];
|
||||||
|
let ans = unfold_test_sc(chain,empty_ctxt,&mut t);
|
||||||
|
assert_eq! (marksof (ans, stopname, &t), ~[9]); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test] fn resolve_tests () {
|
||||||
|
let a = 40;
|
||||||
|
let mut t = mk_sctable();
|
||||||
|
// - ctxt is MT
|
||||||
|
assert_eq!(resolve(id(a,empty_ctxt),&t),a);
|
||||||
|
// - simple ignored marks
|
||||||
|
{ let sc = unfold_marks(~[1,2,3],empty_ctxt,&mut t);
|
||||||
|
assert_eq!(resolve(id(a,sc),&t),a);}
|
||||||
|
// - orthogonal rename where names don't match
|
||||||
|
{ let sc = unfold_test_sc(~[R(id(50,empty_ctxt),51),M(12)],empty_ctxt,&mut t);
|
||||||
|
assert_eq!(resolve(id(a,sc),&t),a);}
|
||||||
|
// - rename where names do match, but marks don't
|
||||||
|
{ let sc1 = mk_mark(1,empty_ctxt,&mut t);
|
||||||
|
let sc = unfold_test_sc(~[R(id(a,sc1),50),
|
||||||
|
M(1),
|
||||||
|
M(2)],
|
||||||
|
empty_ctxt,&mut t);
|
||||||
|
assert_eq!(resolve(id(a,sc),&t), a);}
|
||||||
|
// - rename where names and marks match
|
||||||
|
{ let sc1 = unfold_test_sc(~[M(1),M(2)],empty_ctxt,&mut t);
|
||||||
|
let sc = unfold_test_sc(~[R(id(a,sc1),50),M(1),M(2)],empty_ctxt,&mut t);
|
||||||
|
assert_eq!(resolve(id(a,sc),&t), 50); }
|
||||||
|
// - rename where names and marks match by literal sharing
|
||||||
|
{ let sc1 = unfold_test_sc(~[M(1),M(2)],empty_ctxt,&mut t);
|
||||||
|
let sc = unfold_test_sc(~[R(id(a,sc1),50)],sc1,&mut t);
|
||||||
|
assert_eq!(resolve(id(a,sc),&t), 50); }
|
||||||
|
// - two renames of the same var.. can only happen if you use
|
||||||
|
// local-expand to prevent the inner binding from being renamed
|
||||||
|
// during the rename-pass caused by the first:
|
||||||
|
io::println("about to run bad test");
|
||||||
|
{ let sc = unfold_test_sc(~[R(id(a,empty_ctxt),50),
|
||||||
|
R(id(a,empty_ctxt),51)],
|
||||||
|
empty_ctxt,&mut t);
|
||||||
|
assert_eq!(resolve(id(a,sc),&t), 51); }
|
||||||
|
// the simplest double-rename:
|
||||||
|
{ let a_to_a50 = mk_rename(id(a,empty_ctxt),50,empty_ctxt,&mut t);
|
||||||
|
let a50_to_a51 = mk_rename(id(a,a_to_a50),51,a_to_a50,&mut t);
|
||||||
|
assert_eq!(resolve(id(a,a50_to_a51),&t),51);
|
||||||
|
// mark on the outside doesn't stop rename:
|
||||||
|
let sc = mk_mark(9,a50_to_a51,&mut t);
|
||||||
|
assert_eq!(resolve(id(a,sc),&t),51);
|
||||||
|
// but mark on the inside does:
|
||||||
|
let a50_to_a51_b = unfold_test_sc(~[R(id(a,a_to_a50),51),
|
||||||
|
M(9)],
|
||||||
|
a_to_a50,
|
||||||
|
&mut t);
|
||||||
|
assert_eq!(resolve(id(a,a50_to_a51_b),&t),50);}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
// mode: rust
|
// mode: rust
|
||||||
// fill-column: 78;
|
// fill-column: 78;
|
||||||
|
|
|
@ -547,6 +547,53 @@ pub fn expand_crate(parse_sess: @mut parse::ParseSess,
|
||||||
@f.fold_crate(&*c)
|
@f.fold_crate(&*c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// given a function from paths to paths, produce
|
||||||
|
// an ast_fold that applies that function:
|
||||||
|
fn fun_to_path_folder(f: @fn(&ast::Path)->ast::Path) -> @ast_fold{
|
||||||
|
let afp = default_ast_fold();
|
||||||
|
let f_pre = @AstFoldFns{
|
||||||
|
fold_path : |p, _| f(p),
|
||||||
|
.. *afp
|
||||||
|
};
|
||||||
|
make_fold(f_pre)
|
||||||
|
}
|
||||||
|
/* going to have to figure out whether the table is passed in or
|
||||||
|
extracted from TLS...
|
||||||
|
// update the ctxts in a path to get a rename node
|
||||||
|
fn ctxt_update_rename(from: ast::Name,
|
||||||
|
fromctx: ast::SyntaxContext, to: ast::Name) ->
|
||||||
|
@fn(&ast::Path,@ast_fold)->ast::Path {
|
||||||
|
return |p:&ast::Path,_|
|
||||||
|
ast::Path {span: p.span,
|
||||||
|
global: p.global,
|
||||||
|
idents: p.idents.map(|id|
|
||||||
|
ast::ident{
|
||||||
|
repr: id.repr,
|
||||||
|
// this needs to be cached....
|
||||||
|
ctxt: Some(@ast::Rename(from,fromctx,
|
||||||
|
to,id.ctxt))
|
||||||
|
}),
|
||||||
|
rp: p.rp,
|
||||||
|
types: p.types};
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the ctxts in a path to get a mark node
|
||||||
|
fn ctxt_update_mark(mark: uint) ->
|
||||||
|
@fn(&ast::Path,@ast_fold)->ast::Path {
|
||||||
|
return |p:&ast::Path,_|
|
||||||
|
ast::Path {span: p.span,
|
||||||
|
global: p.global,
|
||||||
|
idents: p.idents.map(|id|
|
||||||
|
ast::ident{
|
||||||
|
repr: id.repr,
|
||||||
|
// this needs to be cached....
|
||||||
|
ctxt: Some(@ast::Mark(mark,id.ctxt))
|
||||||
|
}),
|
||||||
|
rp: p.rp,
|
||||||
|
types: p.types};
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -4280,7 +4280,7 @@ pub impl Parser {
|
||||||
rp: None,
|
rp: None,
|
||||||
types: ~[] };
|
types: ~[] };
|
||||||
return @spanned(lo, self.span.hi,
|
return @spanned(lo, self.span.hi,
|
||||||
view_path_glob(path, self.get_id()));
|
view_path_glob(path, self.get_id()));
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => break
|
_ => break
|
||||||
|
|
|
@ -309,50 +309,50 @@ pub fn is_bar(t: &Token) -> bool {
|
||||||
pub mod special_idents {
|
pub mod special_idents {
|
||||||
use ast::ident;
|
use ast::ident;
|
||||||
|
|
||||||
pub static underscore : ident = ident { repr: 0u };
|
pub static underscore : ident = ident { repr: 0u, ctxt: 0};
|
||||||
pub static anon : ident = ident { repr: 1u };
|
pub static anon : ident = ident { repr: 1u, ctxt: 0};
|
||||||
pub static dtor : ident = ident { repr: 2u }; // 'drop', but that's
|
pub static dtor : ident = ident { repr: 2u, ctxt: 0}; // 'drop', but that's
|
||||||
// reserved
|
// reserved
|
||||||
pub static invalid : ident = ident { repr: 3u }; // ''
|
pub static invalid : ident = ident { repr: 3u, ctxt: 0}; // ''
|
||||||
pub static unary : ident = ident { repr: 4u };
|
pub static unary : ident = ident { repr: 4u, ctxt: 0};
|
||||||
pub static not_fn : ident = ident { repr: 5u };
|
pub static not_fn : ident = ident { repr: 5u, ctxt: 0};
|
||||||
pub static idx_fn : ident = ident { repr: 6u };
|
pub static idx_fn : ident = ident { repr: 6u, ctxt: 0};
|
||||||
pub static unary_minus_fn : ident = ident { repr: 7u };
|
pub static unary_minus_fn : ident = ident { repr: 7u, ctxt: 0};
|
||||||
pub static clownshoes_extensions : ident = ident { repr: 8u };
|
pub static clownshoes_extensions : ident = ident { repr: 8u, ctxt: 0};
|
||||||
|
|
||||||
pub static self_ : ident = ident { repr: 9u }; // 'self'
|
pub static self_ : ident = ident { repr: 9u, ctxt: 0}; // 'self'
|
||||||
|
|
||||||
/* for matcher NTs */
|
/* for matcher NTs */
|
||||||
pub static item : ident = ident { repr: 10u };
|
pub static item : ident = ident { repr: 10u, ctxt: 0};
|
||||||
pub static block : ident = ident { repr: 11u };
|
pub static block : ident = ident { repr: 11u, ctxt: 0};
|
||||||
pub static stmt : ident = ident { repr: 12u };
|
pub static stmt : ident = ident { repr: 12u, ctxt: 0};
|
||||||
pub static pat : ident = ident { repr: 13u };
|
pub static pat : ident = ident { repr: 13u, ctxt: 0};
|
||||||
pub static expr : ident = ident { repr: 14u };
|
pub static expr : ident = ident { repr: 14u, ctxt: 0};
|
||||||
pub static ty : ident = ident { repr: 15u };
|
pub static ty : ident = ident { repr: 15u, ctxt: 0};
|
||||||
pub static ident : ident = ident { repr: 16u };
|
pub static ident : ident = ident { repr: 16u, ctxt: 0};
|
||||||
pub static path : ident = ident { repr: 17u };
|
pub static path : ident = ident { repr: 17u, ctxt: 0};
|
||||||
pub static tt : ident = ident { repr: 18u };
|
pub static tt : ident = ident { repr: 18u, ctxt: 0};
|
||||||
pub static matchers : ident = ident { repr: 19u };
|
pub static matchers : ident = ident { repr: 19u, ctxt: 0};
|
||||||
|
|
||||||
pub static str : ident = ident { repr: 20u }; // for the type
|
pub static str : ident = ident { repr: 20u, ctxt: 0}; // for the type
|
||||||
|
|
||||||
/* outside of libsyntax */
|
/* outside of libsyntax */
|
||||||
pub static ty_visitor : ident = ident { repr: 21u };
|
pub static ty_visitor : ident = ident { repr: 21u, ctxt: 0};
|
||||||
pub static arg : ident = ident { repr: 22u };
|
pub static arg : ident = ident { repr: 22u, ctxt: 0};
|
||||||
pub static descrim : ident = ident { repr: 23u };
|
pub static descrim : ident = ident { repr: 23u, ctxt: 0};
|
||||||
pub static clownshoe_abi : ident = ident { repr: 24u };
|
pub static clownshoe_abi : ident = ident { repr: 24u, ctxt: 0};
|
||||||
pub static clownshoe_stack_shim : ident = ident { repr: 25u };
|
pub static clownshoe_stack_shim : ident = ident { repr: 25u, ctxt: 0};
|
||||||
pub static tydesc : ident = ident { repr: 26u };
|
pub static tydesc : ident = ident { repr: 26u, ctxt: 0};
|
||||||
pub static literally_dtor : ident = ident { repr: 27u };
|
pub static literally_dtor : ident = ident { repr: 27u, ctxt: 0};
|
||||||
pub static main : ident = ident { repr: 28u };
|
pub static main : ident = ident { repr: 28u, ctxt: 0};
|
||||||
pub static opaque : ident = ident { repr: 29u };
|
pub static opaque : ident = ident { repr: 29u, ctxt: 0};
|
||||||
pub static blk : ident = ident { repr: 30u };
|
pub static blk : ident = ident { repr: 30u, ctxt: 0};
|
||||||
pub static static : ident = ident { repr: 31u };
|
pub static static : ident = ident { repr: 31u, ctxt: 0};
|
||||||
pub static intrinsic : ident = ident { repr: 32u };
|
pub static intrinsic : ident = ident { repr: 32u, ctxt: 0};
|
||||||
pub static clownshoes_foreign_mod: ident = ident { repr: 33 };
|
pub static clownshoes_foreign_mod: ident = ident { repr: 33u, ctxt: 0};
|
||||||
pub static unnamed_field: ident = ident { repr: 34 };
|
pub static unnamed_field: ident = ident { repr: 34u, ctxt: 0};
|
||||||
pub static c_abi: ident = ident { repr: 35 };
|
pub static c_abi: ident = ident { repr: 35u, ctxt: 0};
|
||||||
pub static type_self: ident = ident { repr: 36 }; // `Self`
|
pub static type_self: ident = ident { repr: 36u, ctxt: 0}; // `Self`
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ident_interner {
|
pub struct ident_interner {
|
||||||
|
@ -361,10 +361,10 @@ pub struct ident_interner {
|
||||||
|
|
||||||
pub impl ident_interner {
|
pub impl ident_interner {
|
||||||
fn intern(&self, val: @~str) -> ast::ident {
|
fn intern(&self, val: @~str) -> ast::ident {
|
||||||
ast::ident { repr: self.interner.intern(val) }
|
ast::ident { repr: self.interner.intern(val), ctxt: 0}
|
||||||
}
|
}
|
||||||
fn gensym(&self, val: @~str) -> ast::ident {
|
fn gensym(&self, val: @~str) -> ast::ident {
|
||||||
ast::ident { repr: self.interner.gensym(val) }
|
ast::ident { repr: self.interner.gensym(val), ctxt: 0}
|
||||||
}
|
}
|
||||||
fn get(&self, idx: ast::ident) -> @~str {
|
fn get(&self, idx: ast::ident) -> @~str {
|
||||||
self.interner.get(idx.repr)
|
self.interner.get(idx.repr)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue