getting rid of interner_key! macro
This commit is contained in:
parent
fc4f304ef9
commit
999f692645
9 changed files with 60 additions and 125 deletions
|
@ -17,24 +17,18 @@ use doc;
|
||||||
use core::local_data::local_data_get;
|
use core::local_data::local_data_get;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax;
|
use syntax;
|
||||||
|
use syntax::parse::token::{ident_interner};
|
||||||
/* can't import macros yet, so this is copied from token.rs. See its comment
|
use syntax::parse::token;
|
||||||
* there. */
|
|
||||||
macro_rules! interner_key (
|
|
||||||
() => (cast::transmute::<(uint, uint),
|
|
||||||
&fn(v: @@syntax::parse::token::ident_interner)>((-3 as uint, 0u)))
|
|
||||||
)
|
|
||||||
|
|
||||||
// Hack; rather than thread an interner through everywhere, rely on
|
// Hack; rather than thread an interner through everywhere, rely on
|
||||||
// thread-local data
|
// thread-local data
|
||||||
pub fn to_str(id: ast::ident) -> ~str {
|
pub fn to_str(id: ast::ident) -> ~str {
|
||||||
let intr = unsafe{ local_data_get(interner_key!()) };
|
let intr = token::get_ident_interner();
|
||||||
|
return copy *(*intr).get(id);
|
||||||
return copy *(*intr.get()).get(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interner() -> @syntax::parse::token::ident_interner {
|
pub fn interner() -> @ident_interner {
|
||||||
return *(unsafe{ local_data_get(interner_key!()) }).get();
|
return token::get_ident_interner();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_srv(
|
pub fn from_srv(
|
||||||
|
|
|
@ -13,9 +13,10 @@
|
||||||
use codemap::{span, spanned};
|
use codemap::{span, spanned};
|
||||||
use abi::AbiSet;
|
use abi::AbiSet;
|
||||||
use opt_vec::OptVec;
|
use opt_vec::OptVec;
|
||||||
|
use parse::token::get_ident_interner;
|
||||||
|
|
||||||
use core::cast;
|
use core::cast;
|
||||||
use core::option::{None, Option, Some};
|
use core::option::{Option};
|
||||||
use core::to_bytes;
|
use core::to_bytes;
|
||||||
use core::to_bytes::IterBytes;
|
use core::to_bytes::IterBytes;
|
||||||
use core::to_str::ToStr;
|
use core::to_str::ToStr;
|
||||||
|
@ -78,27 +79,14 @@ pub type Mrk = uint;
|
||||||
|
|
||||||
impl<S:Encoder> Encodable<S> for ident {
|
impl<S:Encoder> Encodable<S> for ident {
|
||||||
fn encode(&self, s: &mut S) {
|
fn encode(&self, s: &mut S) {
|
||||||
unsafe {
|
let intr = get_ident_interner();
|
||||||
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));
|
s.emit_str(*(*intr).get(*self));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D:Decoder> Decodable<D> for ident {
|
impl<D:Decoder> Decodable<D> for ident {
|
||||||
fn decode(d: &mut D) -> ident {
|
fn decode(d: &mut D) -> ident {
|
||||||
let intr = match unsafe {
|
let intr = get_ident_interner();
|
||||||
local_data::local_data_get(interner_key!())
|
|
||||||
} {
|
|
||||||
None => fail!("decode: TLS interner not set up"),
|
|
||||||
Some(intr) => intr
|
|
||||||
};
|
|
||||||
|
|
||||||
(*intr).intern(d.read_str())
|
(*intr).intern(d.read_str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -806,7 +806,7 @@ mod test {
|
||||||
};
|
};
|
||||||
let table = @mut new_sctable();
|
let table = @mut new_sctable();
|
||||||
let a_name = 100; // enforced by testing_interner
|
let a_name = 100; // enforced by testing_interner
|
||||||
let a2_name = sess.interner.gensym(@~"a2").repr;
|
let a2_name = sess.interner.gensym("a2").repr;
|
||||||
let renamer = new_ident_renamer(ast::ident{repr:a_name,ctxt:empty_ctxt},
|
let renamer = new_ident_renamer(ast::ident{repr:a_name,ctxt:empty_ctxt},
|
||||||
a2_name,table);
|
a2_name,table);
|
||||||
let renamed_ast = fun_to_ident_folder(renamer).fold_item(item_ast).get();
|
let renamed_ast = fun_to_ident_folder(renamer).fold_item(item_ast).get();
|
||||||
|
|
|
@ -786,7 +786,7 @@ mod test {
|
||||||
fn setup(teststr: ~str) -> Env {
|
fn setup(teststr: ~str) -> Env {
|
||||||
let cm = CodeMap::new();
|
let cm = CodeMap::new();
|
||||||
let fm = cm.new_filemap(~"zebra.rs", @teststr);
|
let fm = cm.new_filemap(~"zebra.rs", @teststr);
|
||||||
let ident_interner = token::mk_ident_interner(); // interner::mk();
|
let ident_interner = token::get_ident_interner();
|
||||||
let span_handler =
|
let span_handler =
|
||||||
diagnostic::mk_span_handler(diagnostic::mk_handler(None),@cm);
|
diagnostic::mk_span_handler(diagnostic::mk_handler(None),@cm);
|
||||||
Env {
|
Env {
|
||||||
|
|
|
@ -19,7 +19,7 @@ use diagnostic::{span_handler, mk_span_handler, mk_handler, Emitter};
|
||||||
use parse::attr::parser_attr;
|
use parse::attr::parser_attr;
|
||||||
use parse::lexer::reader;
|
use parse::lexer::reader;
|
||||||
use parse::parser::Parser;
|
use parse::parser::Parser;
|
||||||
use parse::token::{ident_interner, mk_ident_interner};
|
use parse::token::{ident_interner, get_ident_interner};
|
||||||
|
|
||||||
use core::io;
|
use core::io;
|
||||||
use core::option::{None, Option, Some};
|
use core::option::{None, Option, Some};
|
||||||
|
@ -59,7 +59,7 @@ pub fn new_parse_sess(demitter: Option<Emitter>) -> @mut ParseSess {
|
||||||
cm: cm,
|
cm: cm,
|
||||||
next_id: 1,
|
next_id: 1,
|
||||||
span_diagnostic: mk_span_handler(mk_handler(demitter), cm),
|
span_diagnostic: mk_span_handler(mk_handler(demitter), cm),
|
||||||
interner: mk_ident_interner(),
|
interner: get_ident_interner(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ pub fn new_parse_sess_special_handler(sh: @span_handler,
|
||||||
cm: cm,
|
cm: cm,
|
||||||
next_id: 1,
|
next_id: 1,
|
||||||
span_diagnostic: sh,
|
span_diagnostic: sh,
|
||||||
interner: mk_ident_interner(),
|
interner: get_ident_interner(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,8 +352,8 @@ mod test {
|
||||||
use opt_vec;
|
use opt_vec;
|
||||||
use ast;
|
use ast;
|
||||||
use abi;
|
use abi;
|
||||||
use ast_util::new_ident;
|
|
||||||
use parse::parser::Parser;
|
use parse::parser::Parser;
|
||||||
|
use parse::token::intern;
|
||||||
use util::parser_testing::{string_to_tts_and_sess,string_to_parser};
|
use util::parser_testing::{string_to_tts_and_sess,string_to_parser};
|
||||||
use util::parser_testing::{string_to_expr, string_to_item};
|
use util::parser_testing::{string_to_expr, string_to_item};
|
||||||
use util::parser_testing::{string_to_stmt};
|
use util::parser_testing::{string_to_stmt};
|
||||||
|
@ -378,8 +378,8 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert a vector of uints to a vector of ast::idents
|
// convert a vector of uints to a vector of ast::idents
|
||||||
fn ints_to_idents(ids: ~[uint]) -> ~[ast::ident] {
|
fn ints_to_idents(ids: ~[~str]) -> ~[ast::ident] {
|
||||||
ids.map(|u| new_ident(*u))
|
ids.map(|u| intern(*u))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test] fn path_exprs_1 () {
|
#[test] fn path_exprs_1 () {
|
||||||
|
@ -388,7 +388,7 @@ mod test {
|
||||||
callee_id:2,
|
callee_id:2,
|
||||||
node:ast::expr_path(@ast::Path {span:sp(0,1),
|
node:ast::expr_path(@ast::Path {span:sp(0,1),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[new_ident(100)],
|
idents:~[intern("a")],
|
||||||
rp:None,
|
rp:None,
|
||||||
types:~[]}),
|
types:~[]}),
|
||||||
span:sp(0,1)})
|
span:sp(0,1)})
|
||||||
|
@ -398,9 +398,10 @@ mod test {
|
||||||
assert_eq!(string_to_expr(@~"::a::b"),
|
assert_eq!(string_to_expr(@~"::a::b"),
|
||||||
@ast::expr{id:1,
|
@ast::expr{id:1,
|
||||||
callee_id:2,
|
callee_id:2,
|
||||||
node:ast::expr_path(@ast::Path {span:sp(0,6),
|
node:ast::expr_path(
|
||||||
|
@ast::Path {span:sp(0,6),
|
||||||
global:true,
|
global:true,
|
||||||
idents:ints_to_idents(~[100,101]),
|
idents:ints_to_idents(~[~"a",~"b"]),
|
||||||
rp:None,
|
rp:None,
|
||||||
types:~[]}),
|
types:~[]}),
|
||||||
span:sp(0,6)})
|
span:sp(0,6)})
|
||||||
|
@ -451,7 +452,7 @@ mod test {
|
||||||
node:ast::expr_path(
|
node:ast::expr_path(
|
||||||
@ast::Path{span:sp(7,8),
|
@ast::Path{span:sp(7,8),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[new_ident(103)],
|
idents:~[intern("d")],
|
||||||
rp:None,
|
rp:None,
|
||||||
types:~[]
|
types:~[]
|
||||||
}),
|
}),
|
||||||
|
@ -469,7 +470,7 @@ mod test {
|
||||||
@ast::Path{
|
@ast::Path{
|
||||||
span:sp(0,1),
|
span:sp(0,1),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[new_ident(101)],
|
idents:~[intern("b")],
|
||||||
rp:None,
|
rp:None,
|
||||||
types: ~[]}),
|
types: ~[]}),
|
||||||
span: sp(0,1)},
|
span: sp(0,1)},
|
||||||
|
@ -490,7 +491,7 @@ mod test {
|
||||||
@ast::Path{
|
@ast::Path{
|
||||||
span:sp(0,1),
|
span:sp(0,1),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[new_ident(101)],
|
idents:~[intern("b")],
|
||||||
rp: None,
|
rp: None,
|
||||||
types: ~[]},
|
types: ~[]},
|
||||||
None // no idea
|
None // no idea
|
||||||
|
@ -509,7 +510,7 @@ mod test {
|
||||||
span:sp(4,4), // this is bizarre...
|
span:sp(4,4), // this is bizarre...
|
||||||
// check this in the original parser?
|
// check this in the original parser?
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[new_ident(105)],
|
idents:~[intern("int")],
|
||||||
rp: None,
|
rp: None,
|
||||||
types: ~[]},
|
types: ~[]},
|
||||||
2),
|
2),
|
||||||
|
@ -519,7 +520,7 @@ mod test {
|
||||||
@ast::Path{
|
@ast::Path{
|
||||||
span:sp(0,1),
|
span:sp(0,1),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[new_ident(101)],
|
idents:~[intern("b")],
|
||||||
rp: None,
|
rp: None,
|
||||||
types: ~[]},
|
types: ~[]},
|
||||||
None // no idea
|
None // no idea
|
||||||
|
@ -535,7 +536,7 @@ mod test {
|
||||||
// assignment order of the node_ids.
|
// assignment order of the node_ids.
|
||||||
assert_eq!(string_to_item(@~"fn a (b : int) { b; }"),
|
assert_eq!(string_to_item(@~"fn a (b : int) { b; }"),
|
||||||
Some(
|
Some(
|
||||||
@ast::item{ident:new_ident(100),
|
@ast::item{ident:intern("a"),
|
||||||
attrs:~[],
|
attrs:~[],
|
||||||
id: 10, // fixme
|
id: 10, // fixme
|
||||||
node: ast::item_fn(ast::fn_decl{
|
node: ast::item_fn(ast::fn_decl{
|
||||||
|
@ -545,7 +546,7 @@ mod test {
|
||||||
node: ast::ty_path(@ast::Path{
|
node: ast::ty_path(@ast::Path{
|
||||||
span:sp(10,13),
|
span:sp(10,13),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[new_ident(106)],
|
idents:~[intern("int")],
|
||||||
rp: None,
|
rp: None,
|
||||||
types: ~[]},
|
types: ~[]},
|
||||||
2),
|
2),
|
||||||
|
@ -556,7 +557,7 @@ mod test {
|
||||||
@ast::Path{
|
@ast::Path{
|
||||||
span:sp(6,7),
|
span:sp(6,7),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[new_ident(101)],
|
idents:~[intern("b")],
|
||||||
rp: None,
|
rp: None,
|
||||||
types: ~[]},
|
types: ~[]},
|
||||||
None // no idea
|
None // no idea
|
||||||
|
@ -587,7 +588,7 @@ mod test {
|
||||||
@ast::Path{
|
@ast::Path{
|
||||||
span:sp(17,18),
|
span:sp(17,18),
|
||||||
global:false,
|
global:false,
|
||||||
idents:~[new_ident(101)],
|
idents:~[intern("b")],
|
||||||
rp:None,
|
rp:None,
|
||||||
types: ~[]}),
|
types: ~[]}),
|
||||||
span: sp(17,18)},
|
span: sp(17,18)},
|
||||||
|
|
|
@ -411,8 +411,7 @@ pub impl ident_interner {
|
||||||
}
|
}
|
||||||
|
|
||||||
// return a fresh interner, preloaded with special identifiers.
|
// return a fresh interner, preloaded with special identifiers.
|
||||||
// EFFECT: stores this interner in TLS
|
fn mk_fresh_ident_interner() -> @ident_interner {
|
||||||
pub fn mk_fresh_ident_interner() -> @ident_interner {
|
|
||||||
// the indices here must correspond to the numbers in
|
// the indices here must correspond to the numbers in
|
||||||
// special_idents.
|
// special_idents.
|
||||||
let init_vec = ~[
|
let init_vec = ~[
|
||||||
|
@ -453,23 +452,27 @@ pub fn mk_fresh_ident_interner() -> @ident_interner {
|
||||||
"Self", // 34
|
"Self", // 34
|
||||||
];
|
];
|
||||||
|
|
||||||
let rv = @ident_interner {
|
@ident_interner {
|
||||||
interner: interner::StrInterner::prefill(init_vec)
|
interner: interner::StrInterner::prefill(init_vec)
|
||||||
};
|
|
||||||
unsafe {
|
|
||||||
local_data::local_data_set(interner_key!(), @rv);
|
|
||||||
}
|
}
|
||||||
rv
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if an interner exists in TLS, return it. Otherwise, prepare a
|
// if an interner exists in TLS, return it. Otherwise, prepare a
|
||||||
// fresh one.
|
// fresh one.
|
||||||
pub fn mk_ident_interner() -> @ident_interner {
|
pub fn get_ident_interner() -> @ident_interner {
|
||||||
unsafe {
|
unsafe {
|
||||||
match local_data::local_data_get(interner_key!()) {
|
let key =
|
||||||
|
(cast::transmute::<(uint, uint),
|
||||||
|
&fn(v: @@::parse::token::ident_interner)>(
|
||||||
|
(-3 as uint, 0u)));
|
||||||
|
match local_data::local_data_get(key) {
|
||||||
Some(interner) => *interner,
|
Some(interner) => *interner,
|
||||||
None => {
|
None => {
|
||||||
mk_fresh_ident_interner()
|
let interner = mk_fresh_ident_interner();
|
||||||
|
unsafe {
|
||||||
|
local_data::local_data_set(key, @interner);
|
||||||
|
}
|
||||||
|
interner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -481,6 +484,12 @@ pub fn mk_fake_ident_interner() -> @ident_interner {
|
||||||
@ident_interner { interner: interner::StrInterner::new() }
|
@ident_interner { interner: interner::StrInterner::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// maps a string to its interned representation
|
||||||
|
pub fn intern(str : &str) -> ast::ident {
|
||||||
|
let interner = get_ident_interner();
|
||||||
|
interner.intern(str)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All the valid words that have meaning in the Rust language.
|
* All the valid words that have meaning in the Rust language.
|
||||||
*
|
*
|
||||||
|
|
|
@ -25,9 +25,6 @@
|
||||||
|
|
||||||
extern mod std;
|
extern mod std;
|
||||||
|
|
||||||
// allow the interner_key macro
|
|
||||||
// to escape this module:
|
|
||||||
#[macro_escape]
|
|
||||||
pub mod util {
|
pub mod util {
|
||||||
pub mod interner;
|
pub mod interner;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -12,9 +12,6 @@
|
||||||
// allows bidirectional lookup; i.e. given a value, one can easily find the
|
// allows bidirectional lookup; i.e. given a value, one can easily find the
|
||||||
// type, and vice versa.
|
// type, and vice versa.
|
||||||
|
|
||||||
// allow the interner_key macro to escape this module:
|
|
||||||
#[macro_escape];
|
|
||||||
|
|
||||||
use core::cmp::Equiv;
|
use core::cmp::Equiv;
|
||||||
use core::hashmap::HashMap;
|
use core::hashmap::HashMap;
|
||||||
use syntax::parse::token::StringRef;
|
use syntax::parse::token::StringRef;
|
||||||
|
@ -78,6 +75,8 @@ pub impl<T:Eq + IterBytes + Hash + Const + Copy> Interner<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A StrInterner differs from Interner<String> in that it accepts
|
||||||
|
// borrowed pointers rather than @ ones, resulting in less allocation.
|
||||||
pub struct StrInterner {
|
pub struct StrInterner {
|
||||||
priv map: @mut HashMap<@~str, uint>,
|
priv map: @mut HashMap<@~str, uint>,
|
||||||
priv vect: @mut ~[@~str],
|
priv vect: @mut ~[@~str],
|
||||||
|
@ -133,17 +132,6 @@ pub impl StrInterner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Key for thread-local data for sneaking interner information to the
|
|
||||||
* encoder/decoder. It sounds like a hack because it is one.
|
|
||||||
* Bonus ultra-hack: functions as keys don't work across crates,
|
|
||||||
* so we have to use a unique number. See taskgroup_key! in task.rs
|
|
||||||
* for another case of this. */
|
|
||||||
macro_rules! interner_key (
|
|
||||||
() => (cast::transmute::<(uint, uint),
|
|
||||||
&fn(v: @@::parse::token::ident_interner)>(
|
|
||||||
(-3 as uint, 0u)))
|
|
||||||
)
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -9,64 +9,22 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use core::option::{Option,None};
|
use core::option::{Option,None};
|
||||||
use core::int;
|
|
||||||
use core::num::NumCast;
|
|
||||||
use codemap::CodeMap;
|
|
||||||
use ast;
|
use ast;
|
||||||
use parse::parser::Parser;
|
use parse::parser::Parser;
|
||||||
use parse::token::{ident_interner, mk_fresh_ident_interner};
|
use parse::{new_parse_sess};
|
||||||
use diagnostic::{mk_handler, mk_span_handler};
|
|
||||||
|
|
||||||
use syntax::parse::{ParseSess,string_to_filemap,filemap_to_tts};
|
use syntax::parse::{ParseSess,string_to_filemap,filemap_to_tts};
|
||||||
use syntax::parse::{new_parser_from_source_str};
|
use syntax::parse::{new_parser_from_source_str};
|
||||||
|
|
||||||
// add known names to interner for testing
|
|
||||||
fn mk_testing_interner() -> @ident_interner {
|
|
||||||
let i = mk_fresh_ident_interner();
|
|
||||||
// baby hack; in order to put the identifiers
|
|
||||||
// 'a' and 'b' at known locations, we're going
|
|
||||||
// to fill up the interner to length 100. If
|
|
||||||
// the # of preloaded items on the interner
|
|
||||||
// ever gets larger than 100, we'll have to
|
|
||||||
// adjust this number (say, to 200) and
|
|
||||||
// change the numbers in the identifier
|
|
||||||
// test cases below.
|
|
||||||
|
|
||||||
assert!(i.len() < 100);
|
|
||||||
for int::range(0,100-((i.len()).to_int())) |_dc| {
|
|
||||||
i.gensym(~"dontcare");
|
|
||||||
}
|
|
||||||
i.intern("a");
|
|
||||||
i.intern("b");
|
|
||||||
i.intern("c");
|
|
||||||
i.intern("d");
|
|
||||||
i.intern("return");
|
|
||||||
assert!(i.get(ast::ident{repr:101,ctxt:0}) == @~"b");
|
|
||||||
i
|
|
||||||
}
|
|
||||||
|
|
||||||
// make a parse_sess that's closed over a
|
|
||||||
// testing interner (where a -> 100, b -> 101)
|
|
||||||
fn mk_testing_parse_sess() -> @mut ParseSess {
|
|
||||||
let interner = mk_testing_interner();
|
|
||||||
let cm = @CodeMap::new();
|
|
||||||
@mut ParseSess {
|
|
||||||
cm: cm,
|
|
||||||
next_id: 1,
|
|
||||||
span_diagnostic: mk_span_handler(mk_handler(None), cm),
|
|
||||||
interner: interner,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// map a string to tts, using a made-up filename: return both the token_trees
|
// map a string to tts, using a made-up filename: return both the token_trees
|
||||||
// and the ParseSess
|
// and the ParseSess
|
||||||
pub fn string_to_tts_and_sess (source_str : @~str) -> (~[ast::token_tree],@mut ParseSess) {
|
pub fn string_to_tts_and_sess (source_str : @~str) -> (~[ast::token_tree],@mut ParseSess) {
|
||||||
let ps = mk_testing_parse_sess();
|
let ps = new_parse_sess(None);
|
||||||
(filemap_to_tts(ps,string_to_filemap(ps,source_str,~"bogofile")),ps)
|
(filemap_to_tts(ps,string_to_filemap(ps,source_str,~"bogofile")),ps)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_to_parser_and_sess(source_str: @~str) -> (Parser,@mut ParseSess) {
|
pub fn string_to_parser_and_sess(source_str: @~str) -> (Parser,@mut ParseSess) {
|
||||||
let ps = mk_testing_parse_sess();
|
let ps = new_parse_sess(None);
|
||||||
(new_parser_from_source_str(ps,~[],~"bogofile",source_str),ps)
|
(new_parser_from_source_str(ps,~[],~"bogofile",source_str),ps)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue