auto merge of #9026 : jbclements/rust/let-var-hygiene, r=jbclements
This is a rebase of my approved pull request from ... the end of June? It introduces hygiene for let-bound variables.
This commit is contained in:
commit
124eb2119c
38 changed files with 1623 additions and 634 deletions
|
|
@ -14,28 +14,8 @@ use cryptoutil::{write_u64_be, write_u32_be, read_u64v_be, read_u32v_be, add_byt
|
|||
add_bytes_to_bits_tuple, FixedBuffer, FixedBuffer128, FixedBuffer64, StandardPadding};
|
||||
use digest::Digest;
|
||||
|
||||
|
||||
// Sha-512 and Sha-256 use basically the same calculations which are implemented by these macros.
|
||||
// Inlining the calculations seems to result in better generated code.
|
||||
macro_rules! schedule_round( ($t:expr) => (
|
||||
W[$t] = sigma1(W[$t - 2]) + W[$t - 7] + sigma0(W[$t - 15]) + W[$t - 16];
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! sha2_round(
|
||||
($A:ident, $B:ident, $C:ident, $D:ident,
|
||||
$E:ident, $F:ident, $G:ident, $H:ident, $K:ident, $t:expr) => (
|
||||
{
|
||||
$H += sum1($E) + ch($E, $F, $G) + $K[$t] + W[$t];
|
||||
$D += $H;
|
||||
$H += sum0($A) + maj($A, $B, $C);
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
// A structure that represents that state of a digest computation for the SHA-2 512 family of digest
|
||||
// functions
|
||||
// A structure that represents that state of a digest computation for the SHA-2 512 family
|
||||
// of digest functions
|
||||
struct Engine512State {
|
||||
H0: u64,
|
||||
H1: u64,
|
||||
|
|
@ -108,6 +88,25 @@ impl Engine512State {
|
|||
|
||||
let mut W = [0u64, ..80];
|
||||
|
||||
// Sha-512 and Sha-256 use basically the same calculations which are implemented by
|
||||
// these macros. Inlining the calculations seems to result in better generated code.
|
||||
macro_rules! schedule_round( ($t:expr) => (
|
||||
W[$t] = sigma1(W[$t - 2]) + W[$t - 7] + sigma0(W[$t - 15]) + W[$t - 16];
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! sha2_round(
|
||||
($A:ident, $B:ident, $C:ident, $D:ident,
|
||||
$E:ident, $F:ident, $G:ident, $H:ident, $K:ident, $t:expr) => (
|
||||
{
|
||||
$H += sum1($E) + ch($E, $F, $G) + $K[$t] + W[$t];
|
||||
$D += $H;
|
||||
$H += sum0($A) + maj($A, $B, $C);
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
read_u64v_be(W.mut_slice(0, 16), data);
|
||||
|
||||
// Putting the message schedule inside the same loop as the round calculations allows for
|
||||
|
|
@ -505,6 +504,25 @@ impl Engine256State {
|
|||
|
||||
let mut W = [0u32, ..64];
|
||||
|
||||
// Sha-512 and Sha-256 use basically the same calculations which are implemented
|
||||
// by these macros. Inlining the calculations seems to result in better generated code.
|
||||
macro_rules! schedule_round( ($t:expr) => (
|
||||
W[$t] = sigma1(W[$t - 2]) + W[$t - 7] + sigma0(W[$t - 15]) + W[$t - 16];
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! sha2_round(
|
||||
($A:ident, $B:ident, $C:ident, $D:ident,
|
||||
$E:ident, $F:ident, $G:ident, $H:ident, $K:ident, $t:expr) => (
|
||||
{
|
||||
$H += sum1($E) + ch($E, $F, $G) + $K[$t] + W[$t];
|
||||
$D += $H;
|
||||
$H += sum0($A) + maj($A, $B, $C);
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
read_u32v_be(W.mut_slice(0, 16), data);
|
||||
|
||||
// Putting the message schedule inside the same loop as the round calculations allows for
|
||||
|
|
|
|||
|
|
@ -788,7 +788,7 @@ impl BorrowckCtxt {
|
|||
match fname {
|
||||
mc::NamedField(ref fname) => {
|
||||
out.push_char('.');
|
||||
out.push_str(token::ident_to_str(fname));
|
||||
out.push_str(token::interner_get(*fname));
|
||||
}
|
||||
mc::PositionalField(idx) => {
|
||||
out.push_char('#'); // invent a notation here
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ pub fn find_entry_point(session: Session, crate: &Crate, ast_map: ast_map::map)
|
|||
fn find_item(item: @item, ctxt: @mut EntryContext, visitor: &mut EntryVisitor) {
|
||||
match item.node {
|
||||
item_fn(*) => {
|
||||
if item.ident == special_idents::main {
|
||||
if item.ident.name == special_idents::main.name {
|
||||
match ctxt.ast_map.find(&item.id) {
|
||||
Some(&ast_map::node_item(_, path)) => {
|
||||
if path.len() == 0 {
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ use syntax::ast::{MutImmutable, MutMutable};
|
|||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::print::pprust;
|
||||
use syntax::parse::token;
|
||||
|
||||
#[deriving(Eq)]
|
||||
pub enum categorization {
|
||||
|
|
@ -99,7 +100,7 @@ pub enum InteriorKind {
|
|||
|
||||
#[deriving(Eq, IterBytes)]
|
||||
pub enum FieldName {
|
||||
NamedField(ast::Ident),
|
||||
NamedField(ast::Name),
|
||||
PositionalField(uint)
|
||||
}
|
||||
|
||||
|
|
@ -619,7 +620,7 @@ impl mem_categorization_ctxt {
|
|||
@cmt_ {
|
||||
id: node.id(),
|
||||
span: node.span(),
|
||||
cat: cat_interior(base_cmt, InteriorField(NamedField(f_name))),
|
||||
cat: cat_interior(base_cmt, InteriorField(NamedField(f_name.name))),
|
||||
mutbl: base_cmt.mutbl.inherit(),
|
||||
ty: f_ty
|
||||
}
|
||||
|
|
@ -1224,9 +1225,9 @@ pub fn ptr_sigil(ptr: PointerKind) -> ~str {
|
|||
}
|
||||
|
||||
impl Repr for InteriorKind {
|
||||
fn repr(&self, tcx: ty::ctxt) -> ~str {
|
||||
fn repr(&self, _tcx: ty::ctxt) -> ~str {
|
||||
match *self {
|
||||
InteriorField(NamedField(fld)) => tcx.sess.str_of(fld).to_owned(),
|
||||
InteriorField(NamedField(fld)) => token::interner_get(fld).to_owned(),
|
||||
InteriorField(PositionalField(i)) => fmt!("#%?", i),
|
||||
InteriorElement(_) => ~"[]",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -429,7 +429,7 @@ impl VisitContext {
|
|||
// specified and (2) have a type that
|
||||
// moves-by-default:
|
||||
let consume_with = with_fields.iter().any(|tf| {
|
||||
!fields.iter().any(|f| f.ident == tf.ident) &&
|
||||
!fields.iter().any(|f| f.ident.name == tf.ident.name) &&
|
||||
ty::type_moves_by_default(self.tcx, tf.mt.ty)
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ impl PrivacyVisitor {
|
|||
fn check_field(&mut self, span: Span, id: ast::DefId, ident: ast::Ident) {
|
||||
let fields = ty::lookup_struct_fields(self.tcx, id);
|
||||
for field in fields.iter() {
|
||||
if field.ident != ident { loop; }
|
||||
if field.ident.name != ident.name { loop; }
|
||||
if field.vis == private {
|
||||
self.tcx.sess.span_err(span, fmt!("field `%s` is private",
|
||||
token::ident_to_str(&ident)));
|
||||
|
|
|
|||
|
|
@ -23,13 +23,13 @@ use middle::pat_util::pat_bindings;
|
|||
|
||||
use syntax::ast::*;
|
||||
use syntax::ast;
|
||||
use syntax::ast_util::{def_id_of_def, local_def};
|
||||
use syntax::ast_util::{def_id_of_def, local_def, mtwt_resolve};
|
||||
use syntax::ast_util::{path_to_ident, walk_pat, trait_method_to_ty_method};
|
||||
use syntax::ast_util::{Privacy, Public, Private};
|
||||
use syntax::ast_util::{variant_visibility_to_privacy, visibility_to_privacy};
|
||||
use syntax::attr;
|
||||
use syntax::parse::token;
|
||||
use syntax::parse::token::ident_interner;
|
||||
use syntax::parse::token::{ident_interner, interner_get};
|
||||
use syntax::parse::token::special_idents;
|
||||
use syntax::print::pprust::path_to_str;
|
||||
use syntax::codemap::{Span, dummy_sp, BytePos};
|
||||
|
|
@ -51,7 +51,7 @@ pub struct binding_info {
|
|||
}
|
||||
|
||||
// Map from the name in a pattern to its binding mode.
|
||||
pub type BindingMap = HashMap<Ident,binding_info>;
|
||||
pub type BindingMap = HashMap<Name,binding_info>;
|
||||
|
||||
// Trait method resolution
|
||||
pub type TraitMap = HashMap<NodeId,@mut ~[DefId]>;
|
||||
|
|
@ -311,7 +311,7 @@ pub enum DuplicateCheckingMode {
|
|||
|
||||
/// One local scope.
|
||||
pub struct Rib {
|
||||
bindings: @mut HashMap<Ident, DefLike>,
|
||||
bindings: @mut HashMap<Name, DefLike>,
|
||||
self_binding: @mut Option<DefLike>,
|
||||
kind: RibKind,
|
||||
}
|
||||
|
|
@ -445,12 +445,12 @@ pub struct Module {
|
|||
def_id: Option<DefId>,
|
||||
kind: ModuleKind,
|
||||
|
||||
children: @mut HashMap<Ident, @mut NameBindings>,
|
||||
children: @mut HashMap<Name, @mut NameBindings>,
|
||||
imports: @mut ~[@ImportDirective],
|
||||
|
||||
// The external module children of this node that were declared with
|
||||
// `extern mod`.
|
||||
external_module_children: @mut HashMap<Ident, @mut Module>,
|
||||
external_module_children: @mut HashMap<Name, @mut Module>,
|
||||
|
||||
// The anonymous children of this node. Anonymous children are pseudo-
|
||||
// modules that are implicitly created around items contained within
|
||||
|
|
@ -469,7 +469,7 @@ pub struct Module {
|
|||
anonymous_children: @mut HashMap<NodeId,@mut Module>,
|
||||
|
||||
// The status of resolving each import in this module.
|
||||
import_resolutions: @mut HashMap<Ident, @mut ImportResolution>,
|
||||
import_resolutions: @mut HashMap<Name, @mut ImportResolution>,
|
||||
|
||||
// The number of unresolved globs that this module exports.
|
||||
glob_count: uint,
|
||||
|
|
@ -759,15 +759,14 @@ pub fn NameBindings() -> NameBindings {
|
|||
|
||||
/// Interns the names of the primitive types.
|
||||
pub struct PrimitiveTypeTable {
|
||||
primitive_types: HashMap<Ident,prim_ty>,
|
||||
primitive_types: HashMap<Name,prim_ty>,
|
||||
}
|
||||
|
||||
impl PrimitiveTypeTable {
|
||||
pub fn intern(&mut self,
|
||||
string: &str,
|
||||
primitive_type: prim_ty) {
|
||||
let ident = token::str_to_ident(string);
|
||||
self.primitive_types.insert(ident, primitive_type);
|
||||
self.primitive_types.insert(token::intern(string), primitive_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -873,7 +872,7 @@ pub struct Resolver {
|
|||
|
||||
graph_root: @mut NameBindings,
|
||||
|
||||
method_map: @mut HashMap<Ident, HashSet<DefId>>,
|
||||
method_map: @mut HashMap<Name, HashSet<DefId>>,
|
||||
structs: HashSet<DefId>,
|
||||
|
||||
// The number of imports that are currently unresolved.
|
||||
|
|
@ -1036,10 +1035,10 @@ impl Resolver {
|
|||
|
||||
// Add or reuse the child.
|
||||
let new_parent = ModuleReducedGraphParent(module_);
|
||||
match module_.children.find(&name) {
|
||||
match module_.children.find(&name.name) {
|
||||
None => {
|
||||
let child = @mut NameBindings();
|
||||
module_.children.insert(name, child);
|
||||
module_.children.insert(name.name, child);
|
||||
return (child, new_parent);
|
||||
}
|
||||
Some(&child) => {
|
||||
|
|
@ -1307,7 +1306,7 @@ impl Resolver {
|
|||
} if path.segments.len() == 1 => {
|
||||
let name = path_to_ident(path);
|
||||
|
||||
let new_parent = match parent.children.find(&name) {
|
||||
let new_parent = match parent.children.find(&name.name) {
|
||||
// It already exists
|
||||
Some(&child) if child.get_module_if_available()
|
||||
.is_some() &&
|
||||
|
|
@ -1426,7 +1425,7 @@ impl Resolver {
|
|||
match ty_m.explicit_self.node {
|
||||
sty_static => {}
|
||||
_ => {
|
||||
method_names.insert(ident, ());
|
||||
method_names.insert(ident.name, ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1582,7 +1581,7 @@ impl Resolver {
|
|||
false);
|
||||
|
||||
parent.external_module_children.insert(
|
||||
name,
|
||||
name.name,
|
||||
external_module);
|
||||
|
||||
self.build_reduced_graph_for_external_crate(
|
||||
|
|
@ -1727,7 +1726,7 @@ impl Resolver {
|
|||
|
||||
// Add it to the trait info if not static.
|
||||
if explicit_self != sty_static {
|
||||
interned_method_names.insert(method_name);
|
||||
interned_method_names.insert(method_name.name);
|
||||
}
|
||||
}
|
||||
for name in interned_method_names.iter() {
|
||||
|
|
@ -1981,7 +1980,7 @@ impl Resolver {
|
|||
self.idents_to_str(directive.module_path),
|
||||
self.session.str_of(target));
|
||||
|
||||
match module_.import_resolutions.find(&target) {
|
||||
match module_.import_resolutions.find(&target.name) {
|
||||
Some(&resolution) => {
|
||||
debug!("(building import directive) bumping \
|
||||
reference");
|
||||
|
|
@ -1996,7 +1995,7 @@ impl Resolver {
|
|||
debug!("(building import directive) creating new");
|
||||
let resolution = @mut ImportResolution::new(privacy, id);
|
||||
resolution.outstanding_references = 1;
|
||||
module_.import_resolutions.insert(target, resolution);
|
||||
module_.import_resolutions.insert(target.name, resolution);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2281,7 +2280,7 @@ impl Resolver {
|
|||
|
||||
// Search for direct children of the containing module.
|
||||
self.populate_module_if_necessary(containing_module);
|
||||
match containing_module.children.find(&source) {
|
||||
match containing_module.children.find(&source.name) {
|
||||
None => {
|
||||
// Continue.
|
||||
}
|
||||
|
|
@ -2315,7 +2314,7 @@ impl Resolver {
|
|||
// Now search the exported imports within the containing
|
||||
// module.
|
||||
|
||||
match containing_module.import_resolutions.find(&source) {
|
||||
match containing_module.import_resolutions.find(&source.name) {
|
||||
None => {
|
||||
// The containing module definitely doesn't have an
|
||||
// exported import with the name in question. We can
|
||||
|
|
@ -2386,7 +2385,7 @@ impl Resolver {
|
|||
BoundResult(*) => {}
|
||||
_ => {
|
||||
match containing_module.external_module_children
|
||||
.find(&source) {
|
||||
.find(&source.name) {
|
||||
None => {} // Continue.
|
||||
Some(module) => {
|
||||
let name_bindings =
|
||||
|
|
@ -2400,8 +2399,8 @@ impl Resolver {
|
|||
}
|
||||
|
||||
// We've successfully resolved the import. Write the results in.
|
||||
assert!(module_.import_resolutions.contains_key(&target));
|
||||
let import_resolution = module_.import_resolutions.get(&target);
|
||||
assert!(module_.import_resolutions.contains_key(&target.name));
|
||||
let import_resolution = module_.import_resolutions.get(&target.name);
|
||||
|
||||
match value_result {
|
||||
BoundResult(target_module, name_bindings) => {
|
||||
|
|
@ -2563,15 +2562,15 @@ impl Resolver {
|
|||
}
|
||||
}
|
||||
|
||||
let merge_import_resolution = |ident,
|
||||
let merge_import_resolution = |name,
|
||||
name_bindings: @mut NameBindings| {
|
||||
let dest_import_resolution;
|
||||
match module_.import_resolutions.find(&ident) {
|
||||
match module_.import_resolutions.find(&name) {
|
||||
None => {
|
||||
// Create a new import resolution from this child.
|
||||
dest_import_resolution = @mut ImportResolution::new(privacy, id);
|
||||
module_.import_resolutions.insert
|
||||
(ident, dest_import_resolution);
|
||||
(name, dest_import_resolution);
|
||||
}
|
||||
Some(&existing_import_resolution) => {
|
||||
dest_import_resolution = existing_import_resolution;
|
||||
|
|
@ -2580,7 +2579,7 @@ impl Resolver {
|
|||
|
||||
debug!("(resolving glob import) writing resolution `%s` in `%s` \
|
||||
to `%s`, privacy=%?",
|
||||
self.session.str_of(ident),
|
||||
interner_get(name),
|
||||
self.module_to_str(containing_module),
|
||||
self.module_to_str(module_),
|
||||
dest_import_resolution.privacy);
|
||||
|
|
@ -2602,15 +2601,15 @@ impl Resolver {
|
|||
|
||||
// Add all children from the containing module.
|
||||
self.populate_module_if_necessary(containing_module);
|
||||
for (&ident, name_bindings) in containing_module.children.iter() {
|
||||
merge_import_resolution(ident, *name_bindings);
|
||||
for (&name, name_bindings) in containing_module.children.iter() {
|
||||
merge_import_resolution(name, *name_bindings);
|
||||
}
|
||||
|
||||
// Add external module children from the containing module.
|
||||
for (&ident, module) in containing_module.external_module_children.iter() {
|
||||
for (&name, module) in containing_module.external_module_children.iter() {
|
||||
let name_bindings =
|
||||
@mut Resolver::create_name_bindings_from_module(*module);
|
||||
merge_import_resolution(ident, name_bindings);
|
||||
merge_import_resolution(name, name_bindings);
|
||||
}
|
||||
|
||||
debug!("(resolving glob import) successfully resolved import");
|
||||
|
|
@ -2836,7 +2835,7 @@ impl Resolver {
|
|||
// The current module node is handled specially. First, check for
|
||||
// its immediate children.
|
||||
self.populate_module_if_necessary(module_);
|
||||
match module_.children.find(&name) {
|
||||
match module_.children.find(&name.name) {
|
||||
Some(name_bindings)
|
||||
if name_bindings.defined_in_namespace(namespace) => {
|
||||
return Success(Target::new(module_, *name_bindings));
|
||||
|
|
@ -2848,7 +2847,7 @@ impl Resolver {
|
|||
// all its imports in the usual way; this is because chains of
|
||||
// adjacent import statements are processed as though they mutated the
|
||||
// current scope.
|
||||
match module_.import_resolutions.find(&name) {
|
||||
match module_.import_resolutions.find(&name.name) {
|
||||
None => {
|
||||
// Not found; continue.
|
||||
}
|
||||
|
|
@ -2872,7 +2871,7 @@ impl Resolver {
|
|||
|
||||
// Search for external modules.
|
||||
if namespace == TypeNS {
|
||||
match module_.external_module_children.find(&name) {
|
||||
match module_.external_module_children.find(&name.name) {
|
||||
None => {}
|
||||
Some(module) => {
|
||||
let name_bindings =
|
||||
|
|
@ -3034,8 +3033,9 @@ impl Resolver {
|
|||
}
|
||||
}
|
||||
|
||||
/// Resolves a "module prefix". A module prefix is one of (a) `self::`;
|
||||
/// Resolves a "module prefix". A module prefix is one or both of (a) `self::`;
|
||||
/// (b) some chain of `super::`.
|
||||
/// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) *
|
||||
pub fn resolve_module_prefix(@mut self,
|
||||
module_: @mut Module,
|
||||
module_path: &[Ident])
|
||||
|
|
@ -3091,7 +3091,7 @@ impl Resolver {
|
|||
|
||||
// First, check the direct children of the module.
|
||||
self.populate_module_if_necessary(module_);
|
||||
match module_.children.find(&name) {
|
||||
match module_.children.find(&name.name) {
|
||||
Some(name_bindings)
|
||||
if name_bindings.defined_in_namespace(namespace) => {
|
||||
debug!("(resolving name in module) found node as child");
|
||||
|
|
@ -3112,7 +3112,7 @@ impl Resolver {
|
|||
}
|
||||
|
||||
// Check the list of resolved imports.
|
||||
match module_.import_resolutions.find(&name) {
|
||||
match module_.import_resolutions.find(&name.name) {
|
||||
Some(import_resolution) => {
|
||||
if import_resolution.privacy == Public &&
|
||||
import_resolution.outstanding_references != 0 {
|
||||
|
|
@ -3147,7 +3147,7 @@ impl Resolver {
|
|||
|
||||
// Finally, search through external children.
|
||||
if namespace == TypeNS {
|
||||
match module_.external_module_children.find(&name) {
|
||||
match module_.external_module_children.find(&name.name) {
|
||||
None => {}
|
||||
Some(module) => {
|
||||
let name_bindings =
|
||||
|
|
@ -3273,7 +3273,7 @@ impl Resolver {
|
|||
|
||||
pub fn add_exports_of_namebindings(@mut self,
|
||||
exports2: &mut ~[Export2],
|
||||
ident: Ident,
|
||||
name: Name,
|
||||
namebindings: @mut NameBindings,
|
||||
ns: Namespace,
|
||||
reexport: bool) {
|
||||
|
|
@ -3282,11 +3282,11 @@ impl Resolver {
|
|||
(Some(d), Some(Public)) => {
|
||||
debug!("(computing exports) YES: %s '%s' => %?",
|
||||
if reexport { ~"reexport" } else { ~"export"},
|
||||
self.session.str_of(ident),
|
||||
interner_get(name),
|
||||
def_id_of_def(d));
|
||||
exports2.push(Export2 {
|
||||
reexport: reexport,
|
||||
name: self.session.str_of(ident),
|
||||
name: interner_get(name),
|
||||
def_id: def_id_of_def(d)
|
||||
});
|
||||
}
|
||||
|
|
@ -3302,10 +3302,10 @@ impl Resolver {
|
|||
pub fn add_exports_for_module(@mut self,
|
||||
exports2: &mut ~[Export2],
|
||||
module_: @mut Module) {
|
||||
for (ident, importresolution) in module_.import_resolutions.iter() {
|
||||
for (name, importresolution) in module_.import_resolutions.iter() {
|
||||
if importresolution.privacy != Public {
|
||||
debug!("(computing exports) not reexporting private `%s`",
|
||||
self.session.str_of(*ident));
|
||||
interner_get(*name));
|
||||
loop;
|
||||
}
|
||||
let xs = [TypeNS, ValueNS];
|
||||
|
|
@ -3313,9 +3313,9 @@ impl Resolver {
|
|||
match importresolution.target_for_namespace(*ns) {
|
||||
Some(target) => {
|
||||
debug!("(computing exports) maybe reexport '%s'",
|
||||
self.session.str_of(*ident));
|
||||
interner_get(*name));
|
||||
self.add_exports_of_namebindings(&mut *exports2,
|
||||
*ident,
|
||||
*name,
|
||||
target.bindings,
|
||||
*ns,
|
||||
true)
|
||||
|
|
@ -3354,7 +3354,7 @@ impl Resolver {
|
|||
}
|
||||
Some(name) => {
|
||||
self.populate_module_if_necessary(orig_module);
|
||||
match orig_module.children.find(&name) {
|
||||
match orig_module.children.find(&name.name) {
|
||||
None => {
|
||||
debug!("!!! (with scope) didn't find `%s` in `%s`",
|
||||
self.session.str_of(name),
|
||||
|
|
@ -3498,7 +3498,7 @@ impl Resolver {
|
|||
|
||||
pub fn search_ribs(@mut self,
|
||||
ribs: &mut ~[@Rib],
|
||||
name: Ident,
|
||||
name: Name,
|
||||
span: Span,
|
||||
allow_capturing_self: AllowCapturingSelfFlag)
|
||||
-> Option<DefLike> {
|
||||
|
|
@ -3591,7 +3591,9 @@ impl Resolver {
|
|||
// Create a new rib for the self type.
|
||||
let self_type_rib = @Rib::new(NormalRibKind);
|
||||
self.type_ribs.push(self_type_rib);
|
||||
self_type_rib.bindings.insert(self.type_self_ident,
|
||||
// plain insert (no renaming)
|
||||
let name = self.type_self_ident.name;
|
||||
self_type_rib.bindings.insert(name,
|
||||
DlDef(DefSelfTy(item.id)));
|
||||
|
||||
// Create a new rib for the trait-wide type parameters.
|
||||
|
|
@ -3723,7 +3725,7 @@ impl Resolver {
|
|||
self.type_ribs.push(function_type_rib);
|
||||
|
||||
for (index, type_parameter) in generics.ty_params.iter().enumerate() {
|
||||
let name = type_parameter.ident;
|
||||
let ident = type_parameter.ident;
|
||||
debug!("with_type_parameter_rib: %d %d", node_id,
|
||||
type_parameter.id);
|
||||
let def_like = DlDef(DefTyParam
|
||||
|
|
@ -3733,7 +3735,8 @@ impl Resolver {
|
|||
// the item that bound it
|
||||
self.record_def(type_parameter.id,
|
||||
DefTyParamBinder(node_id));
|
||||
function_type_rib.bindings.insert(name, def_like);
|
||||
// plain insert (no renaming)
|
||||
function_type_rib.bindings.insert(ident.name, def_like);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4064,17 +4067,23 @@ impl Resolver {
|
|||
None, visitor);
|
||||
}
|
||||
|
||||
// build a map from pattern identifiers to binding-info's.
|
||||
// this is done hygienically. This could arise for a macro
|
||||
// that expands into an or-pattern where one 'x' was from the
|
||||
// user and one 'x' came from the macro.
|
||||
pub fn binding_mode_map(@mut self, pat: @Pat) -> BindingMap {
|
||||
let mut result = HashMap::new();
|
||||
do pat_bindings(self.def_map, pat) |binding_mode, _id, sp, path| {
|
||||
let ident = path_to_ident(path);
|
||||
result.insert(ident,
|
||||
let name = mtwt_resolve(path_to_ident(path));
|
||||
result.insert(name,
|
||||
binding_info {span: sp,
|
||||
binding_mode: binding_mode});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// check that all of the arms in an or-pattern have exactly the
|
||||
// same set of bindings, with the same binding modes for each.
|
||||
pub fn check_consistent_bindings(@mut self, arm: &Arm) {
|
||||
if arm.pats.len() == 0 { return; }
|
||||
let map_0 = self.binding_mode_map(arm.pats[0]);
|
||||
|
|
@ -4088,7 +4097,7 @@ impl Resolver {
|
|||
p.span,
|
||||
fmt!("variable `%s` from pattern #1 is \
|
||||
not bound in pattern #%u",
|
||||
self.session.str_of(key), i + 1));
|
||||
interner_get(key), i + 1));
|
||||
}
|
||||
Some(binding_i) => {
|
||||
if binding_0.binding_mode != binding_i.binding_mode {
|
||||
|
|
@ -4096,7 +4105,7 @@ impl Resolver {
|
|||
binding_i.span,
|
||||
fmt!("variable `%s` is bound with different \
|
||||
mode in pattern #%u than in pattern #1",
|
||||
self.session.str_of(key), i + 1));
|
||||
interner_get(key), i + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4108,7 +4117,7 @@ impl Resolver {
|
|||
binding.span,
|
||||
fmt!("variable `%s` from pattern #%u is \
|
||||
not bound in pattern #1",
|
||||
self.session.str_of(key), i + 1));
|
||||
interner_get(key), i + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4170,11 +4179,11 @@ impl Resolver {
|
|||
|
||||
// First, check to see whether the name is a primitive type.
|
||||
if path.segments.len() == 1 {
|
||||
let name = path.segments.last().identifier;
|
||||
let id = path.segments.last().identifier;
|
||||
|
||||
match self.primitive_type_table
|
||||
.primitive_types
|
||||
.find(&name) {
|
||||
.find(&id.name) {
|
||||
|
||||
Some(&primitive_type) => {
|
||||
result_def =
|
||||
|
|
@ -4272,7 +4281,7 @@ impl Resolver {
|
|||
mutability: Mutability,
|
||||
// Maps idents to the node ID for the (outermost)
|
||||
// pattern that binds them
|
||||
bindings_list: Option<@mut HashMap<Ident,NodeId>>,
|
||||
bindings_list: Option<@mut HashMap<Name,NodeId>>,
|
||||
visitor: &mut ResolveVisitor) {
|
||||
let pat_id = pattern.id;
|
||||
do walk_pat(pattern) |pattern| {
|
||||
|
|
@ -4290,13 +4299,14 @@ impl Resolver {
|
|||
// what you want).
|
||||
|
||||
let ident = path.segments[0].identifier;
|
||||
let renamed = mtwt_resolve(ident);
|
||||
|
||||
match self.resolve_bare_identifier_pattern(ident) {
|
||||
FoundStructOrEnumVariant(def)
|
||||
if mode == RefutableMode => {
|
||||
debug!("(resolving pattern) resolving `%s` to \
|
||||
struct or enum variant",
|
||||
self.session.str_of(ident));
|
||||
interner_get(renamed));
|
||||
|
||||
self.enforce_default_binding_mode(
|
||||
pattern,
|
||||
|
|
@ -4310,13 +4320,12 @@ impl Resolver {
|
|||
shadows an enum \
|
||||
variant or unit-like \
|
||||
struct in scope",
|
||||
self.session
|
||||
.str_of(ident)));
|
||||
interner_get(renamed)));
|
||||
}
|
||||
FoundConst(def) if mode == RefutableMode => {
|
||||
debug!("(resolving pattern) resolving `%s` to \
|
||||
constant",
|
||||
self.session.str_of(ident));
|
||||
interner_get(renamed));
|
||||
|
||||
self.enforce_default_binding_mode(
|
||||
pattern,
|
||||
|
|
@ -4331,7 +4340,7 @@ impl Resolver {
|
|||
}
|
||||
BareIdentifierPatternUnresolved => {
|
||||
debug!("(resolving pattern) binding `%s`",
|
||||
self.session.str_of(ident));
|
||||
interner_get(renamed));
|
||||
|
||||
let is_mutable = mutability == Mutable;
|
||||
|
||||
|
|
@ -4366,16 +4375,16 @@ impl Resolver {
|
|||
|
||||
match bindings_list {
|
||||
Some(bindings_list)
|
||||
if !bindings_list.contains_key(&ident) => {
|
||||
if !bindings_list.contains_key(&renamed) => {
|
||||
let this = &mut *self;
|
||||
let last_rib = this.value_ribs[
|
||||
this.value_ribs.len() - 1];
|
||||
last_rib.bindings.insert(ident,
|
||||
last_rib.bindings.insert(renamed,
|
||||
DlDef(def));
|
||||
bindings_list.insert(ident, pat_id);
|
||||
bindings_list.insert(renamed, pat_id);
|
||||
}
|
||||
Some(b) => {
|
||||
if b.find(&ident) == Some(&pat_id) {
|
||||
if b.find(&renamed) == Some(&pat_id) {
|
||||
// Then this is a duplicate variable
|
||||
// in the same disjunct, which is an
|
||||
// error
|
||||
|
|
@ -4391,7 +4400,7 @@ impl Resolver {
|
|||
let this = &mut *self;
|
||||
let last_rib = this.value_ribs[
|
||||
this.value_ribs.len() - 1];
|
||||
last_rib.bindings.insert(ident,
|
||||
last_rib.bindings.insert(renamed,
|
||||
DlDef(def));
|
||||
}
|
||||
}
|
||||
|
|
@ -4607,6 +4616,7 @@ impl Resolver {
|
|||
return unqualified_def;
|
||||
}
|
||||
|
||||
// resolve a single identifier (used as a varref)
|
||||
pub fn resolve_identifier(@mut self,
|
||||
identifier: Ident,
|
||||
namespace: Namespace,
|
||||
|
|
@ -4639,7 +4649,7 @@ impl Resolver {
|
|||
-> NameDefinition {
|
||||
// First, search children.
|
||||
self.populate_module_if_necessary(containing_module);
|
||||
match containing_module.children.find(&name) {
|
||||
match containing_module.children.find(&name.name) {
|
||||
Some(child_name_bindings) => {
|
||||
match (child_name_bindings.def_for_namespace(namespace),
|
||||
child_name_bindings.privacy_for_namespace(namespace)) {
|
||||
|
|
@ -4662,7 +4672,7 @@ impl Resolver {
|
|||
}
|
||||
|
||||
// Next, search import resolutions.
|
||||
match containing_module.import_resolutions.find(&name) {
|
||||
match containing_module.import_resolutions.find(&name.name) {
|
||||
Some(import_resolution) if import_resolution.privacy == Public ||
|
||||
xray == Xray => {
|
||||
match (*import_resolution).target_for_namespace(namespace) {
|
||||
|
|
@ -4690,7 +4700,7 @@ impl Resolver {
|
|||
|
||||
// Finally, search through external children.
|
||||
if namespace == TypeNS {
|
||||
match containing_module.external_module_children.find(&name) {
|
||||
match containing_module.external_module_children.find(&name.name) {
|
||||
None => {}
|
||||
Some(module) => {
|
||||
match module.def_id {
|
||||
|
|
@ -4706,25 +4716,13 @@ impl Resolver {
|
|||
return NoNameDefinition;
|
||||
}
|
||||
|
||||
pub fn intern_module_part_of_path(@mut self, path: &Path) -> ~[Ident] {
|
||||
let mut module_path_idents = ~[];
|
||||
for (index, segment) in path.segments.iter().enumerate() {
|
||||
if index == path.segments.len() - 1 {
|
||||
break;
|
||||
}
|
||||
|
||||
module_path_idents.push(segment.identifier);
|
||||
}
|
||||
|
||||
return module_path_idents;
|
||||
}
|
||||
|
||||
// resolve a "module-relative" path, e.g. a::b::c
|
||||
pub fn resolve_module_relative_path(@mut self,
|
||||
path: &Path,
|
||||
xray: XrayFlag,
|
||||
namespace: Namespace)
|
||||
-> Option<Def> {
|
||||
let module_path_idents = self.intern_module_part_of_path(path);
|
||||
let module_path_idents = path.segments.init().map(|ps| ps.identifier);
|
||||
|
||||
let containing_module;
|
||||
match self.resolve_module_path(self.current_module,
|
||||
|
|
@ -4749,9 +4747,9 @@ impl Resolver {
|
|||
}
|
||||
}
|
||||
|
||||
let name = path.segments.last().identifier;
|
||||
let ident = path.segments.last().identifier;
|
||||
let def = match self.resolve_definition_of_name_in_module(containing_module,
|
||||
name,
|
||||
ident,
|
||||
namespace,
|
||||
xray) {
|
||||
NoNameDefinition => {
|
||||
|
|
@ -4764,7 +4762,7 @@ impl Resolver {
|
|||
};
|
||||
match containing_module.kind {
|
||||
TraitModuleKind | ImplModuleKind => {
|
||||
match self.method_map.find(&name) {
|
||||
match self.method_map.find(&ident.name) {
|
||||
Some(s) => {
|
||||
match containing_module.def_id {
|
||||
Some(def_id) if s.contains(&def_id) => {
|
||||
|
|
@ -4790,7 +4788,7 @@ impl Resolver {
|
|||
xray: XrayFlag,
|
||||
namespace: Namespace)
|
||||
-> Option<Def> {
|
||||
let module_path_idents = self.intern_module_part_of_path(path);
|
||||
let module_path_idents = path.segments.init().map(|ps| ps.identifier);
|
||||
|
||||
let root_module = self.graph_root.get_module();
|
||||
|
||||
|
|
@ -4841,12 +4839,14 @@ impl Resolver {
|
|||
let search_result;
|
||||
match namespace {
|
||||
ValueNS => {
|
||||
search_result = self.search_ribs(self.value_ribs, ident,
|
||||
let renamed = mtwt_resolve(ident);
|
||||
search_result = self.search_ribs(self.value_ribs, renamed,
|
||||
span,
|
||||
DontAllowCapturingSelf);
|
||||
}
|
||||
TypeNS => {
|
||||
search_result = self.search_ribs(self.type_ribs, ident,
|
||||
let name = ident.name;
|
||||
search_result = self.search_ribs(self.type_ribs, name,
|
||||
span, AllowCapturingSelf);
|
||||
}
|
||||
}
|
||||
|
|
@ -4957,7 +4957,7 @@ impl Resolver {
|
|||
while j != 0 {
|
||||
j -= 1;
|
||||
for (&k, _) in this.value_ribs[j].bindings.iter() {
|
||||
maybes.push(this.session.str_of(k));
|
||||
maybes.push(interner_get(k));
|
||||
values.push(uint::max_value);
|
||||
}
|
||||
}
|
||||
|
|
@ -5146,7 +5146,8 @@ impl Resolver {
|
|||
let this = &mut *self;
|
||||
let def_like = DlDef(DefLabel(expr.id));
|
||||
let rib = this.label_ribs[this.label_ribs.len() - 1];
|
||||
rib.bindings.insert(label, def_like);
|
||||
// plain insert (no renaming)
|
||||
rib.bindings.insert(label.name, def_like);
|
||||
}
|
||||
|
||||
visit::walk_expr(visitor, expr, ());
|
||||
|
|
@ -5156,7 +5157,8 @@ impl Resolver {
|
|||
ExprForLoop(*) => fail!("non-desugared expr_for_loop"),
|
||||
|
||||
ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
|
||||
match self.search_ribs(self.label_ribs, label, expr.span,
|
||||
let name = label.name;
|
||||
match self.search_ribs(self.label_ribs, name, expr.span,
|
||||
DontAllowCapturingSelf) {
|
||||
None =>
|
||||
self.resolve_error(expr.span,
|
||||
|
|
@ -5284,7 +5286,7 @@ impl Resolver {
|
|||
|
||||
let mut found_traits = ~[];
|
||||
let mut search_module = self.current_module;
|
||||
match self.method_map.find(&name) {
|
||||
match self.method_map.find(&name.name) {
|
||||
Some(candidate_traits) => loop {
|
||||
// Look for the current trait.
|
||||
match self.current_trait_refs {
|
||||
|
|
@ -5506,7 +5508,7 @@ impl Resolver {
|
|||
debug!("Children:");
|
||||
self.populate_module_if_necessary(module_);
|
||||
for (&name, _) in module_.children.iter() {
|
||||
debug!("* %s", self.session.str_of(name));
|
||||
debug!("* %s", interner_get(name));
|
||||
}
|
||||
|
||||
debug!("Import resolutions:");
|
||||
|
|
@ -5529,7 +5531,7 @@ impl Resolver {
|
|||
}
|
||||
}
|
||||
|
||||
debug!("* %s:%s%s", self.session.str_of(*name),
|
||||
debug!("* %s:%s%s", interner_get(*name),
|
||||
value_repr, type_repr);
|
||||
}
|
||||
}
|
||||
|
|
@ -5554,3 +5556,4 @@ pub fn resolve_crate(session: Session,
|
|||
trait_map: resolver.trait_map.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1482,7 +1482,7 @@ fn compile_submatch_continue(mut bcx: @mut Block,
|
|||
let pat_repr = adt::represent_type(bcx.ccx(), pat_ty);
|
||||
do expr::with_field_tys(tcx, pat_ty, None) |discr, field_tys| {
|
||||
let rec_vals = rec_fields.map(|field_name| {
|
||||
let ix = ty::field_idx_strict(tcx, *field_name, field_tys);
|
||||
let ix = ty::field_idx_strict(tcx, field_name.name, field_tys);
|
||||
adt::trans_field_ptr(bcx, pat_repr, val, discr, ix)
|
||||
});
|
||||
compile_submatch(
|
||||
|
|
@ -2159,7 +2159,7 @@ fn bind_irrefutable_pat(bcx: @mut Block,
|
|||
let pat_repr = adt::represent_type(bcx.ccx(), pat_ty);
|
||||
do expr::with_field_tys(tcx, pat_ty, None) |discr, field_tys| {
|
||||
for f in fields.iter() {
|
||||
let ix = ty::field_idx_strict(tcx, f.ident, field_tys);
|
||||
let ix = ty::field_idx_strict(tcx, f.ident.name, field_tys);
|
||||
let fldptr = adt::trans_field_ptr(bcx, pat_repr, val,
|
||||
discr, ix);
|
||||
bcx = bind_irrefutable_pat(bcx, f.pat, fldptr, binding_mode);
|
||||
|
|
|
|||
|
|
@ -2648,10 +2648,10 @@ pub fn p2i(ccx: &CrateContext, v: ValueRef) -> ValueRef {
|
|||
}
|
||||
|
||||
macro_rules! ifn (
|
||||
($name:expr, $args:expr, $ret:expr) => ({
|
||||
($intrinsics:ident, $name:expr, $args:expr, $ret:expr) => ({
|
||||
let name = $name;
|
||||
let f = decl_cdecl_fn(llmod, name, Type::func($args, &$ret));
|
||||
intrinsics.insert(name, f);
|
||||
$intrinsics.insert(name, f);
|
||||
})
|
||||
)
|
||||
|
||||
|
|
@ -2659,135 +2659,136 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<&'static str, ValueRef> {
|
|||
let i8p = Type::i8p();
|
||||
let mut intrinsics = HashMap::new();
|
||||
|
||||
ifn!("llvm.memcpy.p0i8.p0i8.i32",
|
||||
ifn!(intrinsics, "llvm.memcpy.p0i8.p0i8.i32",
|
||||
[i8p, i8p, Type::i32(), Type::i32(), Type::i1()], Type::void());
|
||||
ifn!("llvm.memcpy.p0i8.p0i8.i64",
|
||||
ifn!(intrinsics, "llvm.memcpy.p0i8.p0i8.i64",
|
||||
[i8p, i8p, Type::i64(), Type::i32(), Type::i1()], Type::void());
|
||||
ifn!("llvm.memmove.p0i8.p0i8.i32",
|
||||
ifn!(intrinsics, "llvm.memmove.p0i8.p0i8.i32",
|
||||
[i8p, i8p, Type::i32(), Type::i32(), Type::i1()], Type::void());
|
||||
ifn!("llvm.memmove.p0i8.p0i8.i64",
|
||||
ifn!(intrinsics, "llvm.memmove.p0i8.p0i8.i64",
|
||||
[i8p, i8p, Type::i64(), Type::i32(), Type::i1()], Type::void());
|
||||
ifn!("llvm.memset.p0i8.i32",
|
||||
ifn!(intrinsics, "llvm.memset.p0i8.i32",
|
||||
[i8p, Type::i8(), Type::i32(), Type::i32(), Type::i1()], Type::void());
|
||||
ifn!("llvm.memset.p0i8.i64",
|
||||
ifn!(intrinsics, "llvm.memset.p0i8.i64",
|
||||
[i8p, Type::i8(), Type::i64(), Type::i32(), Type::i1()], Type::void());
|
||||
|
||||
ifn!("llvm.trap", [], Type::void());
|
||||
ifn!("llvm.frameaddress", [Type::i32()], i8p);
|
||||
ifn!(intrinsics, "llvm.trap", [], Type::void());
|
||||
ifn!(intrinsics, "llvm.frameaddress", [Type::i32()], i8p);
|
||||
|
||||
ifn!("llvm.powi.f32", [Type::f32(), Type::i32()], Type::f32());
|
||||
ifn!("llvm.powi.f64", [Type::f64(), Type::i32()], Type::f64());
|
||||
ifn!("llvm.pow.f32", [Type::f32(), Type::f32()], Type::f32());
|
||||
ifn!("llvm.pow.f64", [Type::f64(), Type::f64()], Type::f64());
|
||||
ifn!(intrinsics, "llvm.powi.f32", [Type::f32(), Type::i32()], Type::f32());
|
||||
ifn!(intrinsics, "llvm.powi.f64", [Type::f64(), Type::i32()], Type::f64());
|
||||
ifn!(intrinsics, "llvm.pow.f32", [Type::f32(), Type::f32()], Type::f32());
|
||||
ifn!(intrinsics, "llvm.pow.f64", [Type::f64(), Type::f64()], Type::f64());
|
||||
|
||||
ifn!("llvm.sqrt.f32", [Type::f32()], Type::f32());
|
||||
ifn!("llvm.sqrt.f64", [Type::f64()], Type::f64());
|
||||
ifn!("llvm.sin.f32", [Type::f32()], Type::f32());
|
||||
ifn!("llvm.sin.f64", [Type::f64()], Type::f64());
|
||||
ifn!("llvm.cos.f32", [Type::f32()], Type::f32());
|
||||
ifn!("llvm.cos.f64", [Type::f64()], Type::f64());
|
||||
ifn!("llvm.exp.f32", [Type::f32()], Type::f32());
|
||||
ifn!("llvm.exp.f64", [Type::f64()], Type::f64());
|
||||
ifn!("llvm.exp2.f32", [Type::f32()], Type::f32());
|
||||
ifn!("llvm.exp2.f64", [Type::f64()], Type::f64());
|
||||
ifn!("llvm.log.f32", [Type::f32()], Type::f32());
|
||||
ifn!("llvm.log.f64", [Type::f64()], Type::f64());
|
||||
ifn!("llvm.log10.f32",[Type::f32()], Type::f32());
|
||||
ifn!("llvm.log10.f64",[Type::f64()], Type::f64());
|
||||
ifn!("llvm.log2.f32", [Type::f32()], Type::f32());
|
||||
ifn!("llvm.log2.f64", [Type::f64()], Type::f64());
|
||||
ifn!(intrinsics, "llvm.sqrt.f32", [Type::f32()], Type::f32());
|
||||
ifn!(intrinsics, "llvm.sqrt.f64", [Type::f64()], Type::f64());
|
||||
ifn!(intrinsics, "llvm.sin.f32", [Type::f32()], Type::f32());
|
||||
ifn!(intrinsics, "llvm.sin.f64", [Type::f64()], Type::f64());
|
||||
ifn!(intrinsics, "llvm.cos.f32", [Type::f32()], Type::f32());
|
||||
ifn!(intrinsics, "llvm.cos.f64", [Type::f64()], Type::f64());
|
||||
ifn!(intrinsics, "llvm.exp.f32", [Type::f32()], Type::f32());
|
||||
ifn!(intrinsics, "llvm.exp.f64", [Type::f64()], Type::f64());
|
||||
ifn!(intrinsics, "llvm.exp2.f32", [Type::f32()], Type::f32());
|
||||
ifn!(intrinsics, "llvm.exp2.f64", [Type::f64()], Type::f64());
|
||||
ifn!(intrinsics, "llvm.log.f32", [Type::f32()], Type::f32());
|
||||
ifn!(intrinsics, "llvm.log.f64", [Type::f64()], Type::f64());
|
||||
ifn!(intrinsics, "llvm.log10.f32",[Type::f32()], Type::f32());
|
||||
ifn!(intrinsics, "llvm.log10.f64",[Type::f64()], Type::f64());
|
||||
ifn!(intrinsics, "llvm.log2.f32", [Type::f32()], Type::f32());
|
||||
ifn!(intrinsics, "llvm.log2.f64", [Type::f64()], Type::f64());
|
||||
|
||||
ifn!("llvm.fma.f32", [Type::f32(), Type::f32(), Type::f32()], Type::f32());
|
||||
ifn!("llvm.fma.f64", [Type::f64(), Type::f64(), Type::f64()], Type::f64());
|
||||
ifn!(intrinsics, "llvm.fma.f32", [Type::f32(), Type::f32(), Type::f32()], Type::f32());
|
||||
ifn!(intrinsics, "llvm.fma.f64", [Type::f64(), Type::f64(), Type::f64()], Type::f64());
|
||||
|
||||
ifn!("llvm.fabs.f32", [Type::f32()], Type::f32());
|
||||
ifn!("llvm.fabs.f64", [Type::f64()], Type::f64());
|
||||
ifn!("llvm.floor.f32",[Type::f32()], Type::f32());
|
||||
ifn!("llvm.floor.f64",[Type::f64()], Type::f64());
|
||||
ifn!("llvm.ceil.f32", [Type::f32()], Type::f32());
|
||||
ifn!("llvm.ceil.f64", [Type::f64()], Type::f64());
|
||||
ifn!("llvm.trunc.f32",[Type::f32()], Type::f32());
|
||||
ifn!("llvm.trunc.f64",[Type::f64()], Type::f64());
|
||||
ifn!(intrinsics, "llvm.fabs.f32", [Type::f32()], Type::f32());
|
||||
ifn!(intrinsics, "llvm.fabs.f64", [Type::f64()], Type::f64());
|
||||
ifn!(intrinsics, "llvm.floor.f32",[Type::f32()], Type::f32());
|
||||
ifn!(intrinsics, "llvm.floor.f64",[Type::f64()], Type::f64());
|
||||
ifn!(intrinsics, "llvm.ceil.f32", [Type::f32()], Type::f32());
|
||||
ifn!(intrinsics, "llvm.ceil.f64", [Type::f64()], Type::f64());
|
||||
ifn!(intrinsics, "llvm.trunc.f32",[Type::f32()], Type::f32());
|
||||
ifn!(intrinsics, "llvm.trunc.f64",[Type::f64()], Type::f64());
|
||||
|
||||
ifn!("llvm.ctpop.i8", [Type::i8()], Type::i8());
|
||||
ifn!("llvm.ctpop.i16",[Type::i16()], Type::i16());
|
||||
ifn!("llvm.ctpop.i32",[Type::i32()], Type::i32());
|
||||
ifn!("llvm.ctpop.i64",[Type::i64()], Type::i64());
|
||||
ifn!(intrinsics, "llvm.ctpop.i8", [Type::i8()], Type::i8());
|
||||
ifn!(intrinsics, "llvm.ctpop.i16",[Type::i16()], Type::i16());
|
||||
ifn!(intrinsics, "llvm.ctpop.i32",[Type::i32()], Type::i32());
|
||||
ifn!(intrinsics, "llvm.ctpop.i64",[Type::i64()], Type::i64());
|
||||
|
||||
ifn!("llvm.ctlz.i8", [Type::i8() , Type::i1()], Type::i8());
|
||||
ifn!("llvm.ctlz.i16", [Type::i16(), Type::i1()], Type::i16());
|
||||
ifn!("llvm.ctlz.i32", [Type::i32(), Type::i1()], Type::i32());
|
||||
ifn!("llvm.ctlz.i64", [Type::i64(), Type::i1()], Type::i64());
|
||||
ifn!(intrinsics, "llvm.ctlz.i8", [Type::i8() , Type::i1()], Type::i8());
|
||||
ifn!(intrinsics, "llvm.ctlz.i16", [Type::i16(), Type::i1()], Type::i16());
|
||||
ifn!(intrinsics, "llvm.ctlz.i32", [Type::i32(), Type::i1()], Type::i32());
|
||||
ifn!(intrinsics, "llvm.ctlz.i64", [Type::i64(), Type::i1()], Type::i64());
|
||||
|
||||
ifn!("llvm.cttz.i8", [Type::i8() , Type::i1()], Type::i8());
|
||||
ifn!("llvm.cttz.i16", [Type::i16(), Type::i1()], Type::i16());
|
||||
ifn!("llvm.cttz.i32", [Type::i32(), Type::i1()], Type::i32());
|
||||
ifn!("llvm.cttz.i64", [Type::i64(), Type::i1()], Type::i64());
|
||||
ifn!(intrinsics, "llvm.cttz.i8", [Type::i8() , Type::i1()], Type::i8());
|
||||
ifn!(intrinsics, "llvm.cttz.i16", [Type::i16(), Type::i1()], Type::i16());
|
||||
ifn!(intrinsics, "llvm.cttz.i32", [Type::i32(), Type::i1()], Type::i32());
|
||||
ifn!(intrinsics, "llvm.cttz.i64", [Type::i64(), Type::i1()], Type::i64());
|
||||
|
||||
ifn!("llvm.bswap.i16",[Type::i16()], Type::i16());
|
||||
ifn!("llvm.bswap.i32",[Type::i32()], Type::i32());
|
||||
ifn!("llvm.bswap.i64",[Type::i64()], Type::i64());
|
||||
ifn!(intrinsics, "llvm.bswap.i16",[Type::i16()], Type::i16());
|
||||
ifn!(intrinsics, "llvm.bswap.i32",[Type::i32()], Type::i32());
|
||||
ifn!(intrinsics, "llvm.bswap.i64",[Type::i64()], Type::i64());
|
||||
|
||||
ifn!("llvm.sadd.with.overflow.i8",
|
||||
ifn!(intrinsics, "llvm.sadd.with.overflow.i8",
|
||||
[Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
|
||||
ifn!("llvm.sadd.with.overflow.i16",
|
||||
ifn!(intrinsics, "llvm.sadd.with.overflow.i16",
|
||||
[Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
|
||||
ifn!("llvm.sadd.with.overflow.i32",
|
||||
ifn!(intrinsics, "llvm.sadd.with.overflow.i32",
|
||||
[Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
|
||||
ifn!("llvm.sadd.with.overflow.i64",
|
||||
ifn!(intrinsics, "llvm.sadd.with.overflow.i64",
|
||||
[Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
|
||||
|
||||
ifn!("llvm.uadd.with.overflow.i8",
|
||||
ifn!(intrinsics, "llvm.uadd.with.overflow.i8",
|
||||
[Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
|
||||
ifn!("llvm.uadd.with.overflow.i16",
|
||||
ifn!(intrinsics, "llvm.uadd.with.overflow.i16",
|
||||
[Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
|
||||
ifn!("llvm.uadd.with.overflow.i32",
|
||||
ifn!(intrinsics, "llvm.uadd.with.overflow.i32",
|
||||
[Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
|
||||
ifn!("llvm.uadd.with.overflow.i64",
|
||||
ifn!(intrinsics, "llvm.uadd.with.overflow.i64",
|
||||
[Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
|
||||
|
||||
ifn!("llvm.ssub.with.overflow.i8",
|
||||
ifn!(intrinsics, "llvm.ssub.with.overflow.i8",
|
||||
[Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
|
||||
ifn!("llvm.ssub.with.overflow.i16",
|
||||
ifn!(intrinsics, "llvm.ssub.with.overflow.i16",
|
||||
[Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
|
||||
ifn!("llvm.ssub.with.overflow.i32",
|
||||
ifn!(intrinsics, "llvm.ssub.with.overflow.i32",
|
||||
[Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
|
||||
ifn!("llvm.ssub.with.overflow.i64",
|
||||
ifn!(intrinsics, "llvm.ssub.with.overflow.i64",
|
||||
[Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
|
||||
|
||||
ifn!("llvm.usub.with.overflow.i8",
|
||||
ifn!(intrinsics, "llvm.usub.with.overflow.i8",
|
||||
[Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
|
||||
ifn!("llvm.usub.with.overflow.i16",
|
||||
ifn!(intrinsics, "llvm.usub.with.overflow.i16",
|
||||
[Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
|
||||
ifn!("llvm.usub.with.overflow.i32",
|
||||
ifn!(intrinsics, "llvm.usub.with.overflow.i32",
|
||||
[Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
|
||||
ifn!("llvm.usub.with.overflow.i64",
|
||||
ifn!(intrinsics, "llvm.usub.with.overflow.i64",
|
||||
[Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
|
||||
|
||||
ifn!("llvm.smul.with.overflow.i8",
|
||||
ifn!(intrinsics, "llvm.smul.with.overflow.i8",
|
||||
[Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
|
||||
ifn!("llvm.smul.with.overflow.i16",
|
||||
ifn!(intrinsics, "llvm.smul.with.overflow.i16",
|
||||
[Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
|
||||
ifn!("llvm.smul.with.overflow.i32",
|
||||
ifn!(intrinsics, "llvm.smul.with.overflow.i32",
|
||||
[Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
|
||||
ifn!("llvm.smul.with.overflow.i64",
|
||||
ifn!(intrinsics, "llvm.smul.with.overflow.i64",
|
||||
[Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
|
||||
|
||||
ifn!("llvm.umul.with.overflow.i8",
|
||||
ifn!(intrinsics, "llvm.umul.with.overflow.i8",
|
||||
[Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
|
||||
ifn!("llvm.umul.with.overflow.i16",
|
||||
ifn!(intrinsics, "llvm.umul.with.overflow.i16",
|
||||
[Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
|
||||
ifn!("llvm.umul.with.overflow.i32",
|
||||
ifn!(intrinsics, "llvm.umul.with.overflow.i32",
|
||||
[Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
|
||||
ifn!("llvm.umul.with.overflow.i64",
|
||||
ifn!(intrinsics, "llvm.umul.with.overflow.i64",
|
||||
[Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
|
||||
|
||||
return intrinsics;
|
||||
}
|
||||
|
||||
pub fn declare_dbg_intrinsics(llmod: ModuleRef, intrinsics: &mut HashMap<&'static str, ValueRef>) {
|
||||
ifn!("llvm.dbg.declare", [Type::metadata(), Type::metadata()], Type::void());
|
||||
ifn!("llvm.dbg.value", [Type::metadata(), Type::i64(), Type::metadata()], Type::void());
|
||||
ifn!(intrinsics, "llvm.dbg.declare", [Type::metadata(), Type::metadata()], Type::void());
|
||||
ifn!(intrinsics,
|
||||
"llvm.dbg.value", [Type::metadata(), Type::i64(), Type::metadata()], Type::void());
|
||||
}
|
||||
|
||||
pub fn trap(bcx: @mut Block) {
|
||||
|
|
|
|||
|
|
@ -374,7 +374,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef {
|
|||
let brepr = adt::represent_type(cx, bt);
|
||||
let bv = const_expr(cx, base);
|
||||
do expr::with_field_tys(cx.tcx, bt, None) |discr, field_tys| {
|
||||
let ix = ty::field_idx_strict(cx.tcx, field, field_tys);
|
||||
let ix = ty::field_idx_strict(cx.tcx, field.name, field_tys);
|
||||
adt::const_get_field(cx, brepr, bv, discr, ix)
|
||||
}
|
||||
}
|
||||
|
|
@ -502,7 +502,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef {
|
|||
|discr, field_tys| {
|
||||
let cs: ~[ValueRef] = field_tys.iter().enumerate()
|
||||
.map(|(ix, &field_ty)| {
|
||||
match fs.iter().find(|f| field_ty.ident == f.ident) {
|
||||
match fs.iter().find(|f| field_ty.ident.name == f.ident.name) {
|
||||
Some(f) => const_expr(cx, (*f).expr),
|
||||
None => {
|
||||
match base_val {
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ pub struct CrateContext {
|
|||
// Cache of external const values
|
||||
extern_const_values: HashMap<ast::DefId, ValueRef>,
|
||||
|
||||
impl_method_cache: HashMap<(ast::DefId, ast::Ident), ast::DefId>,
|
||||
impl_method_cache: HashMap<(ast::DefId, ast::Name), ast::DefId>,
|
||||
|
||||
module_data: HashMap<~str, ValueRef>,
|
||||
lltypes: HashMap<ty::t, Type>,
|
||||
|
|
|
|||
|
|
@ -1012,7 +1012,7 @@ fn struct_metadata(cx: &mut CrateContext,
|
|||
|
||||
let field_llvm_types = do fields.map |field| { type_of::type_of(cx, field.mt.ty) };
|
||||
let field_names = do fields.map |field| {
|
||||
if field.ident == special_idents::unnamed_field {
|
||||
if field.ident.name == special_idents::unnamed_field.name {
|
||||
~""
|
||||
} else {
|
||||
cx.sess.str_of(field.ident).to_owned()
|
||||
|
|
@ -1875,9 +1875,12 @@ fn populate_scope_map(cx: &mut CrateContext,
|
|||
// }
|
||||
|
||||
// Is there already a binding with that name?
|
||||
// N.B.: this comparison must be UNhygienic... because
|
||||
// gdb knows nothing about the context, so any two
|
||||
// variables with the same name will cause the problem.
|
||||
let need_new_scope = scope_stack
|
||||
.iter()
|
||||
.any(|entry| entry.ident.iter().any(|i| *i == ident));
|
||||
.any(|entry| entry.ident.iter().any(|i| i.name == ident.name));
|
||||
|
||||
if need_new_scope {
|
||||
// Create a new lexical scope and push it onto the stack
|
||||
|
|
|
|||
|
|
@ -903,7 +903,7 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: @ast::Expr) -> DatumBlock {
|
|||
let base_datum = unpack_datum!(bcx, trans_to_datum(bcx, base));
|
||||
let repr = adt::represent_type(bcx.ccx(), base_datum.ty);
|
||||
do with_field_tys(bcx.tcx(), base_datum.ty, None) |discr, field_tys| {
|
||||
let ix = ty::field_idx_strict(bcx.tcx(), field, field_tys);
|
||||
let ix = ty::field_idx_strict(bcx.tcx(), field.name, field_tys);
|
||||
DatumBlock {
|
||||
datum: do base_datum.get_element(bcx,
|
||||
field_tys[ix].mt.ty,
|
||||
|
|
@ -1176,7 +1176,9 @@ fn trans_rec_or_struct(bcx: @mut Block,
|
|||
let mut need_base = vec::from_elem(field_tys.len(), true);
|
||||
|
||||
let numbered_fields = do fields.map |field| {
|
||||
let opt_pos = field_tys.iter().position(|field_ty| field_ty.ident == field.ident);
|
||||
let opt_pos =
|
||||
field_tys.iter().position(|field_ty|
|
||||
field_ty.ident.name == field.ident.name);
|
||||
match opt_pos {
|
||||
Some(i) => {
|
||||
need_base[i] = false;
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ pub fn trans_static_method_callee(bcx: @mut Block,
|
|||
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
|
||||
assert!(rcvr_substs.iter().all(|t| !ty::type_needs_infer(*t)));
|
||||
|
||||
let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
|
||||
let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name);
|
||||
let (callee_substs, callee_origins) =
|
||||
combine_impl_and_methods_tps(
|
||||
bcx, mth_id, callee_id,
|
||||
|
|
@ -294,7 +294,7 @@ pub fn trans_static_method_callee(bcx: @mut Block,
|
|||
|
||||
pub fn method_with_name(ccx: &mut CrateContext,
|
||||
impl_id: ast::DefId,
|
||||
name: ast::Ident) -> ast::DefId {
|
||||
name: ast::Name) -> ast::DefId {
|
||||
let meth_id_opt = ccx.impl_method_cache.find_copy(&(impl_id, name));
|
||||
match meth_id_opt {
|
||||
Some(m) => return m,
|
||||
|
|
@ -303,7 +303,7 @@ pub fn method_with_name(ccx: &mut CrateContext,
|
|||
|
||||
let imp = ccx.tcx.impls.find(&impl_id)
|
||||
.expect("could not find impl while translating");
|
||||
let meth = imp.methods.iter().find(|m| m.ident == name)
|
||||
let meth = imp.methods.iter().find(|m| m.ident.name == name)
|
||||
.expect("could not find method while translating");
|
||||
|
||||
ccx.impl_method_cache.insert((impl_id, name), meth.def_id);
|
||||
|
|
@ -323,7 +323,7 @@ pub fn trans_monomorphized_callee(bcx: @mut Block,
|
|||
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
|
||||
let ccx = bcx.ccx();
|
||||
let mname = ty::trait_method(ccx.tcx, trait_id, n_method).ident;
|
||||
let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
|
||||
let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name);
|
||||
|
||||
// obtain the `self` value:
|
||||
let mut temp_cleanups = ~[];
|
||||
|
|
@ -600,7 +600,7 @@ fn emit_vtable_methods(bcx: @mut Block,
|
|||
let ident = ty::method(tcx, *method_def_id).ident;
|
||||
// The substitutions we have are on the impl, so we grab
|
||||
// the method type from the impl to substitute into.
|
||||
let m_id = method_with_name(ccx, impl_id, ident);
|
||||
let m_id = method_with_name(ccx, impl_id, ident.name);
|
||||
let m = ty::method(tcx, m_id);
|
||||
debug!("(making impl vtable) emitting method %s at subst %s",
|
||||
m.repr(tcx),
|
||||
|
|
|
|||
|
|
@ -3360,19 +3360,19 @@ pub fn stmt_node_id(s: &ast::Stmt) -> ast::NodeId {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn field_idx(id: ast::Ident, fields: &[field]) -> Option<uint> {
|
||||
pub fn field_idx(name: ast::Name, fields: &[field]) -> Option<uint> {
|
||||
let mut i = 0u;
|
||||
for f in fields.iter() { if f.ident == id { return Some(i); } i += 1u; }
|
||||
for f in fields.iter() { if f.ident.name == name { return Some(i); } i += 1u; }
|
||||
return None;
|
||||
}
|
||||
|
||||
pub fn field_idx_strict(tcx: ty::ctxt, id: ast::Ident, fields: &[field])
|
||||
pub fn field_idx_strict(tcx: ty::ctxt, name: ast::Name, fields: &[field])
|
||||
-> uint {
|
||||
let mut i = 0u;
|
||||
for f in fields.iter() { if f.ident == id { return i; } i += 1u; }
|
||||
for f in fields.iter() { if f.ident.name == name { return i; } i += 1u; }
|
||||
tcx.sess.bug(fmt!(
|
||||
"No field named `%s` found in the list of fields `%?`",
|
||||
tcx.sess.str_of(id),
|
||||
token::interner_get(name),
|
||||
fields.map(|f| tcx.sess.str_of(f.ident))));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -296,13 +296,13 @@ pub fn check_struct_pat_fields(pcx: &pat_ctxt,
|
|||
// Index the class fields.
|
||||
let mut field_map = HashMap::new();
|
||||
for (i, class_field) in class_fields.iter().enumerate() {
|
||||
field_map.insert(class_field.ident, i);
|
||||
field_map.insert(class_field.ident.name, i);
|
||||
}
|
||||
|
||||
// Typecheck each field.
|
||||
let mut found_fields = HashSet::new();
|
||||
for field in fields.iter() {
|
||||
match field_map.find(&field.ident) {
|
||||
match field_map.find(&field.ident.name) {
|
||||
Some(&index) => {
|
||||
let class_field = class_fields[index];
|
||||
let field_type = ty::lookup_field_type(tcx,
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ use syntax::ast::{sty_uniq, sty_static, NodeId};
|
|||
use syntax::ast::{MutMutable, MutImmutable};
|
||||
use syntax::ast;
|
||||
use syntax::ast_map;
|
||||
use syntax::parse::token;
|
||||
|
||||
#[deriving(Eq)]
|
||||
pub enum CheckTraitsFlag {
|
||||
|
|
@ -126,7 +127,7 @@ pub fn lookup(
|
|||
self_expr: @ast::Expr, // The expression `a`.
|
||||
callee_id: NodeId, /* Where to store `a.b`'s type,
|
||||
* also the scope of the call */
|
||||
m_name: ast::Ident, // The ident `b`.
|
||||
m_name: ast::Name, // The name `b`.
|
||||
self_ty: ty::t, // The type of `a`.
|
||||
supplied_tps: &[ty::t], // The list of types X, Y, ... .
|
||||
deref_args: check::DerefArgs, // Whether we autopointer first.
|
||||
|
|
@ -173,7 +174,7 @@ pub struct LookupContext<'self> {
|
|||
expr: @ast::Expr,
|
||||
self_expr: @ast::Expr,
|
||||
callee_id: NodeId,
|
||||
m_name: ast::Ident,
|
||||
m_name: ast::Name,
|
||||
supplied_tps: &'self [ty::t],
|
||||
impl_dups: @mut HashSet<DefId>,
|
||||
inherent_candidates: @mut ~[Candidate],
|
||||
|
|
@ -515,7 +516,7 @@ impl<'self> LookupContext<'self> {
|
|||
let trait_methods = ty::trait_methods(tcx, bound_trait_ref.def_id);
|
||||
match trait_methods.iter().position(|m| {
|
||||
m.explicit_self != ast::sty_static &&
|
||||
m.ident == self.m_name })
|
||||
m.ident.name == self.m_name })
|
||||
{
|
||||
Some(pos) => {
|
||||
let method = trait_methods[pos];
|
||||
|
|
@ -558,12 +559,12 @@ impl<'self> LookupContext<'self> {
|
|||
return; // already visited
|
||||
}
|
||||
debug!("push_candidates_from_impl: %s %s %s",
|
||||
self.m_name.repr(self.tcx()),
|
||||
token::interner_get(self.m_name),
|
||||
impl_info.ident.repr(self.tcx()),
|
||||
impl_info.methods.map(|m| m.ident).repr(self.tcx()));
|
||||
|
||||
let idx = {
|
||||
match impl_info.methods.iter().position(|m| m.ident == self.m_name) {
|
||||
match impl_info.methods.iter().position(|m| m.ident.name == self.m_name) {
|
||||
Some(idx) => idx,
|
||||
None => { return; } // No method with the right name.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1117,10 +1117,10 @@ pub fn impl_self_ty(vcx: &VtableContext,
|
|||
pub fn lookup_field_ty(tcx: ty::ctxt,
|
||||
class_id: ast::DefId,
|
||||
items: &[ty::field_ty],
|
||||
fieldname: ast::Ident,
|
||||
fieldname: ast::Name,
|
||||
substs: &ty::substs) -> Option<ty::t> {
|
||||
|
||||
let o_field = items.iter().find(|f| f.ident == fieldname);
|
||||
let o_field = items.iter().find(|f| f.ident.name == fieldname);
|
||||
do o_field.map() |f| {
|
||||
ty::lookup_field_type(tcx, class_id, f.id, substs)
|
||||
}
|
||||
|
|
@ -1553,7 +1553,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||
expr,
|
||||
rcvr,
|
||||
callee_id,
|
||||
method_name,
|
||||
method_name.name,
|
||||
expr_t,
|
||||
tps,
|
||||
DontDerefArgs,
|
||||
|
|
@ -1637,7 +1637,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||
op_ex: @ast::Expr,
|
||||
self_ex: @ast::Expr,
|
||||
self_t: ty::t,
|
||||
opname: ast::Ident,
|
||||
opname: ast::Name,
|
||||
args: ~[@ast::Expr],
|
||||
deref_args: DerefArgs,
|
||||
autoderef_receiver: AutoderefReceiverFlag,
|
||||
|
|
@ -1777,7 +1777,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||
lhs_resolved_t, None)
|
||||
};
|
||||
return lookup_op_method(fcx, callee_id, ex, lhs_expr, lhs_resolved_t,
|
||||
fcx.tcx().sess.ident_of(*name),
|
||||
token::intern(*name),
|
||||
~[rhs], DoDerefArgs, DontAutoderefReceiver, if_op_unbound,
|
||||
expected_result);
|
||||
}
|
||||
|
|
@ -1811,7 +1811,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||
-> ty::t {
|
||||
lookup_op_method(
|
||||
fcx, callee_id, ex, rhs_expr, rhs_t,
|
||||
fcx.tcx().sess.ident_of(mname), ~[],
|
||||
token::intern(mname), ~[],
|
||||
DoDerefArgs, DontAutoderefReceiver,
|
||||
|| {
|
||||
fcx.type_error_message(ex.span, |actual| {
|
||||
|
|
@ -1937,7 +1937,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||
fn check_field(fcx: @mut FnCtxt,
|
||||
expr: @ast::Expr,
|
||||
base: @ast::Expr,
|
||||
field: ast::Ident,
|
||||
field: ast::Name,
|
||||
tys: &[ast::Ty]) {
|
||||
let tcx = fcx.ccx.tcx;
|
||||
let bot = check_expr(fcx, base);
|
||||
|
|
@ -1985,7 +1985,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||
|actual| {
|
||||
fmt!("attempted to take value of method `%s` on type `%s` \
|
||||
(try writing an anonymous function)",
|
||||
tcx.sess.str_of(field), actual)
|
||||
token::interner_get(field), actual)
|
||||
},
|
||||
expr_t, None);
|
||||
}
|
||||
|
|
@ -1996,7 +1996,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||
|actual| {
|
||||
fmt!("attempted access of field `%s` on type `%s`, \
|
||||
but no field with that name was found",
|
||||
tcx.sess.str_of(field), actual)
|
||||
token::interner_get(field), actual)
|
||||
},
|
||||
expr_t, None);
|
||||
}
|
||||
|
|
@ -2018,7 +2018,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||
let mut class_field_map = HashMap::new();
|
||||
let mut fields_found = 0;
|
||||
for field in field_types.iter() {
|
||||
class_field_map.insert(field.ident, (field.id, false));
|
||||
class_field_map.insert(field.ident.name, (field.id, false));
|
||||
}
|
||||
|
||||
let mut error_happened = false;
|
||||
|
|
@ -2027,7 +2027,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||
for field in ast_fields.iter() {
|
||||
let mut expected_field_type = ty::mk_err();
|
||||
|
||||
let pair = class_field_map.find(&field.ident).map_move(|x| *x);
|
||||
let pair = class_field_map.find(&field.ident.name).map_move(|x| *x);
|
||||
match pair {
|
||||
None => {
|
||||
tcx.sess.span_err(
|
||||
|
|
@ -2048,7 +2048,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||
ty::lookup_field_type(
|
||||
tcx, class_id, field_id, &substitutions);
|
||||
class_field_map.insert(
|
||||
field.ident, (field_id, true));
|
||||
field.ident.name, (field_id, true));
|
||||
fields_found += 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -2070,11 +2070,11 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||
if fields_found < field_types.len() {
|
||||
let mut missing_fields = ~[];
|
||||
for class_field in field_types.iter() {
|
||||
let name = class_field.ident;
|
||||
let name = class_field.ident.name;
|
||||
let (_, seen) = *class_field_map.get(&name);
|
||||
if !seen {
|
||||
missing_fields.push(
|
||||
~"`" + tcx.sess.str_of(name) + "`");
|
||||
~"`" + token::interner_get(name) + "`");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2846,7 +2846,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||
}
|
||||
}
|
||||
ast::ExprField(base, field, ref tys) => {
|
||||
check_field(fcx, expr, base, field, *tys);
|
||||
check_field(fcx, expr, base, field.name, *tys);
|
||||
}
|
||||
ast::ExprIndex(callee_id, base, idx) => {
|
||||
check_expr(fcx, base);
|
||||
|
|
@ -2886,7 +2886,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||
expr,
|
||||
base,
|
||||
resolved,
|
||||
index_ident,
|
||||
index_ident.name,
|
||||
~[idx],
|
||||
DoDerefArgs,
|
||||
AutoderefReceiver,
|
||||
|
|
|
|||
|
|
@ -553,13 +553,13 @@ impl CoherenceChecker {
|
|||
let mut provided_names = HashSet::new();
|
||||
// Implemented methods
|
||||
for elt in all_methods.iter() {
|
||||
provided_names.insert(elt.ident);
|
||||
provided_names.insert(elt.ident.name);
|
||||
}
|
||||
|
||||
let r = ty::trait_methods(tcx, trait_did);
|
||||
for method in r.iter() {
|
||||
debug!("checking for %s", method.ident.repr(tcx));
|
||||
if provided_names.contains(&method.ident) { loop; }
|
||||
if provided_names.contains(&method.ident.name) { loop; }
|
||||
|
||||
tcx.sess.span_err(trait_ref_span,
|
||||
fmt!("missing method `%s`",
|
||||
|
|
|
|||
|
|
@ -698,7 +698,7 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt,
|
|||
// we'll catch it in coherence
|
||||
let trait_ms = ty::trait_methods(tcx, trait_ref.def_id);
|
||||
for impl_m in impl_ms.iter() {
|
||||
match trait_ms.iter().find(|trait_m| trait_m.ident == impl_m.mty.ident) {
|
||||
match trait_ms.iter().find(|trait_m| trait_m.ident.name == impl_m.mty.ident.name) {
|
||||
Some(trait_m) => {
|
||||
let num_impl_tps = generics.ty_params.len();
|
||||
compare_impl_method(
|
||||
|
|
|
|||
|
|
@ -375,3 +375,13 @@ impl<A:IterBytes> ToBytes for A {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
// just test to see if it compiles:
|
||||
#[test] fn iterbytes_compiles () {
|
||||
takes_iterbytes((3,4,5,false));
|
||||
}
|
||||
fn takes_iterbytes<T : IterBytes>(x : T) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ use std::option::Option;
|
|||
use std::to_str::ToStr;
|
||||
use extra::serialize::{Encodable, Decodable, Encoder, Decoder};
|
||||
|
||||
|
||||
// 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
|
||||
|
|
@ -32,6 +36,36 @@ impl Ident {
|
|||
pub fn new(name: Name) -> Ident { Ident {name: name, ctxt: EMPTY_CTXT}}
|
||||
}
|
||||
|
||||
// defining eq in this way is a way of guaranteeing that later stages of the
|
||||
// compiler don't compare identifiers unhygienically. Unfortunately, some tests
|
||||
// (specifically debuginfo in no-opt) want to do these comparisons, and that
|
||||
// seems fine. If only I could find a nice way to statically ensure that
|
||||
// the compiler "proper" never compares identifiers.... I'm leaving this
|
||||
// code here (commented out) for potential use in debugging. Specifically, if
|
||||
// there's a bug where "identifiers aren't matching", it may be because
|
||||
// they should be compared using mtwt_resolve. In such a case, re-enabling this
|
||||
// code (and disabling deriving(Eq) for Idents) could help to isolate the
|
||||
// problem
|
||||
/* impl Eq 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.
|
||||
fail!(fmt!("not allowed to compare these idents: %?, %?", 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
|
||||
|
|
@ -47,6 +81,15 @@ impl Ident {
|
|||
// storage.
|
||||
pub type SyntaxContext = uint;
|
||||
|
||||
// the SCTable contains a table of SyntaxContext_'s. It
|
||||
// represents a flattened tree structure, to avoid having
|
||||
// managed pointers everywhere (that caused an ICE).
|
||||
// the mark_memo and rename_memo fields are side-tables
|
||||
// that ensure that adding the same mark to the same context
|
||||
// gives you back the same context as before. This shouldn't
|
||||
// change the semantics--everything here is immutable--but
|
||||
// it should cut down on memory use *a lot*; applying a mark
|
||||
// to a tree containing 50 identifiers would otherwise generate
|
||||
pub struct SCTable {
|
||||
table : ~[SyntaxContext_],
|
||||
mark_memo : HashMap<(SyntaxContext,Mrk),SyntaxContext>,
|
||||
|
|
@ -70,6 +113,7 @@ pub enum SyntaxContext_ {
|
|||
// in the "from" slot. In essence, they're all
|
||||
// pointers to a single "rename" event node.
|
||||
Rename (Ident,Name,SyntaxContext),
|
||||
// actually, IllegalCtxt may not be necessary.
|
||||
IllegalCtxt
|
||||
}
|
||||
|
||||
|
|
@ -99,6 +143,7 @@ pub type FnIdent = Option<Ident>;
|
|||
pub struct Lifetime {
|
||||
id: NodeId,
|
||||
span: Span,
|
||||
// FIXME #7743 : change this to Name!
|
||||
ident: Ident
|
||||
}
|
||||
|
||||
|
|
@ -443,7 +488,7 @@ pub enum BlockCheckMode {
|
|||
UnsafeBlock,
|
||||
}
|
||||
|
||||
#[deriving(Eq, Encodable, Decodable,IterBytes)]
|
||||
#[deriving(Clone, Eq, Encodable, Decodable,IterBytes)]
|
||||
pub struct Expr {
|
||||
id: NodeId,
|
||||
node: Expr_,
|
||||
|
|
@ -544,10 +589,11 @@ pub enum token_tree {
|
|||
// a delimited sequence (the delimiters appear as the first
|
||||
// and last elements of the vector)
|
||||
tt_delim(@mut ~[token_tree]),
|
||||
|
||||
// These only make sense for right-hand-sides of MBE macros:
|
||||
|
||||
// a kleene-style repetition sequence with a span, a tt_forest,
|
||||
// an optional separator (?), and a boolean where true indicates
|
||||
// an optional separator, and a boolean where true indicates
|
||||
// zero or more (*), and false indicates one or more (+).
|
||||
tt_seq(Span, @mut ~[token_tree], Option<::parse::token::Token>, bool),
|
||||
|
||||
|
|
@ -622,9 +668,13 @@ pub enum matcher_ {
|
|||
|
||||
pub type mac = Spanned<mac_>;
|
||||
|
||||
// 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, Eq, Encodable, Decodable, IterBytes)]
|
||||
pub enum mac_ {
|
||||
mac_invoc_tt(Path,~[token_tree]), // new macro-invocation
|
||||
mac_invoc_tt(Path,~[token_tree],SyntaxContext), // new macro-invocation
|
||||
}
|
||||
|
||||
pub type lit = Spanned<lit_>;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ pub fn path_name_i(idents: &[Ident]) -> ~str {
|
|||
idents.map(|i| token::interner_get(i.name)).connect("::")
|
||||
}
|
||||
|
||||
// totally scary function: ignores all but the last element, should have
|
||||
// a different name
|
||||
pub fn path_to_ident(path: &Path) -> Ident {
|
||||
path.segments.last().identifier
|
||||
}
|
||||
|
|
@ -825,9 +827,6 @@ pub fn pat_is_ident(pat: @ast::Pat) -> bool {
|
|||
|
||||
// HYGIENE FUNCTIONS
|
||||
|
||||
/// Construct an identifier with the given name and an empty context:
|
||||
pub fn new_ident(name: Name) -> Ident { Ident {name: name, ctxt: 0}}
|
||||
|
||||
/// Extend a syntax context with a given mark
|
||||
pub fn new_mark(m:Mrk, tail:SyntaxContext) -> SyntaxContext {
|
||||
new_mark_internal(m,tail,get_sctable())
|
||||
|
|
@ -908,6 +907,15 @@ pub fn get_sctable() -> @mut SCTable {
|
|||
}
|
||||
}
|
||||
|
||||
/// print out an SCTable for debugging
|
||||
pub fn display_sctable(table : &SCTable) {
|
||||
error!("SC table:");
|
||||
for (idx,val) in table.table.iter().enumerate() {
|
||||
error!("%4u : %?",idx,val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// 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);
|
||||
|
|
@ -915,35 +923,76 @@ fn idx_push<T>(vec: &mut ~[T], val: T) -> uint {
|
|||
}
|
||||
|
||||
/// Resolve a syntax object to a name, per MTWT.
|
||||
pub fn resolve(id : Ident) -> Name {
|
||||
resolve_internal(id, get_sctable())
|
||||
pub fn mtwt_resolve(id : Ident) -> Name {
|
||||
resolve_internal(id, get_sctable(), get_resolve_table())
|
||||
}
|
||||
|
||||
// FIXME #4536: must be pub for testing
|
||||
pub type ResolveTable = HashMap<(Name,SyntaxContext),Name>;
|
||||
|
||||
// okay, I admit, putting this in TLS is not so nice:
|
||||
// fetch the SCTable from TLS, create one if it doesn't yet exist.
|
||||
pub fn get_resolve_table() -> @mut ResolveTable {
|
||||
static resolve_table_key: local_data::Key<@@mut ResolveTable> = &local_data::Key;
|
||||
match local_data::get(resolve_table_key, |k| k.map(|&k| *k)) {
|
||||
None => {
|
||||
let new_table = @@mut HashMap::new();
|
||||
local_data::set(resolve_table_key,new_table);
|
||||
*new_table
|
||||
},
|
||||
Some(intr) => *intr
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve a syntax object to a name, per MTWT.
|
||||
// adding memoization to possibly resolve 500+ seconds in resolve for librustc (!)
|
||||
// FIXME #4536 : currently pub to allow testing
|
||||
pub fn resolve_internal(id : Ident, table : &mut SCTable) -> Name {
|
||||
match table.table[id.ctxt] {
|
||||
EmptyCtxt => id.name,
|
||||
// ignore marks here:
|
||||
Mark(_,subctxt) => resolve_internal(Ident{name:id.name, ctxt: subctxt},table),
|
||||
// do the rename if necessary:
|
||||
Rename(Ident{name,ctxt},toname,subctxt) => {
|
||||
// this could be cached or computed eagerly:
|
||||
let resolvedfrom = resolve_internal(Ident{name:name,ctxt:ctxt},table);
|
||||
let resolvedthis = resolve_internal(Ident{name:id.name,ctxt:subctxt},table);
|
||||
if ((resolvedthis == resolvedfrom)
|
||||
&& (marksof(ctxt,resolvedthis,table)
|
||||
== marksof(subctxt,resolvedthis,table))) {
|
||||
toname
|
||||
} else {
|
||||
resolvedthis
|
||||
}
|
||||
pub fn resolve_internal(id : Ident,
|
||||
table : &mut SCTable,
|
||||
resolve_table : &mut ResolveTable) -> Name {
|
||||
let key = (id.name,id.ctxt);
|
||||
match resolve_table.contains_key(&key) {
|
||||
false => {
|
||||
let resolved = {
|
||||
match table.table[id.ctxt] {
|
||||
EmptyCtxt => id.name,
|
||||
// ignore marks here:
|
||||
Mark(_,subctxt) =>
|
||||
resolve_internal(Ident{name:id.name, ctxt: subctxt},table,resolve_table),
|
||||
// do the rename if necessary:
|
||||
Rename(Ident{name,ctxt},toname,subctxt) => {
|
||||
let resolvedfrom =
|
||||
resolve_internal(Ident{name:name,ctxt:ctxt},table,resolve_table);
|
||||
let resolvedthis =
|
||||
resolve_internal(Ident{name:id.name,ctxt:subctxt},table,resolve_table);
|
||||
if ((resolvedthis == resolvedfrom)
|
||||
&& (marksof(ctxt,resolvedthis,table)
|
||||
== marksof(subctxt,resolvedthis,table))) {
|
||||
toname
|
||||
} else {
|
||||
resolvedthis
|
||||
}
|
||||
}
|
||||
IllegalCtxt() => fail!(~"expected resolvable context, got IllegalCtxt")
|
||||
}
|
||||
};
|
||||
resolve_table.insert(key,resolved);
|
||||
resolved
|
||||
}
|
||||
true => {
|
||||
// it's guaranteed to be there, because we just checked that it was
|
||||
// there and we never remove anything from the table:
|
||||
*(resolve_table.find(&key).unwrap())
|
||||
}
|
||||
IllegalCtxt() => fail!(~"expected resolvable context, got IllegalCtxt")
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute the marks associated with a syntax context.
|
||||
pub fn mtwt_marksof(ctxt: SyntaxContext, stopname: Name) -> ~[Mrk] {
|
||||
marksof(ctxt, stopname, get_sctable())
|
||||
}
|
||||
|
||||
// the internal function for computing marks
|
||||
// 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] {
|
||||
|
|
@ -970,6 +1019,16 @@ pub fn marksof(ctxt: SyntaxContext, stopname: Name, table: &SCTable) -> ~[Mrk] {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return the outer mark for a context with a mark at the outside.
|
||||
/// FAILS when outside is not a mark.
|
||||
pub fn mtwt_outer_mark(ctxt: SyntaxContext) -> Mrk {
|
||||
let sctable = get_sctable();
|
||||
match sctable.table[ctxt] {
|
||||
ast::Mark(mrk,_) => mrk,
|
||||
_ => fail!("can't retrieve outer mark when outside is not a mark")
|
||||
}
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
|
|
@ -986,12 +1045,55 @@ pub fn getLast(arr: &~[Mrk]) -> uint {
|
|||
*arr.last()
|
||||
}
|
||||
|
||||
// are two paths equal when compared unhygienically?
|
||||
// since I'm using this to replace ==, it seems appropriate
|
||||
// to compare the span, global, etc. fields as well.
|
||||
pub fn path_name_eq(a : &ast::Path, b : &ast::Path) -> bool {
|
||||
(a.span == b.span)
|
||||
&& (a.global == b.global)
|
||||
&& (segments_name_eq(a.segments, b.segments))
|
||||
}
|
||||
|
||||
// are two arrays of segments equal when compared unhygienically?
|
||||
pub fn segments_name_eq(a : &[ast::PathSegment], b : &[ast::PathSegment]) -> bool {
|
||||
if (a.len() != b.len()) {
|
||||
false
|
||||
} else {
|
||||
for (idx,seg) in a.iter().enumerate() {
|
||||
if (seg.identifier.name != b[idx].identifier.name)
|
||||
// FIXME #7743: ident -> name problems in lifetime comparison?
|
||||
|| (seg.lifetime != b[idx].lifetime)
|
||||
// can types contain idents?
|
||||
|| (seg.types != b[idx].types) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use ast::*;
|
||||
use super::*;
|
||||
use std::io;
|
||||
use opt_vec;
|
||||
use std::hash::HashMap;
|
||||
|
||||
fn ident_to_segment(id : &Ident) -> PathSegment {
|
||||
PathSegment{identifier:id.clone(), lifetime: None, types: opt_vec::Empty}
|
||||
}
|
||||
|
||||
#[test] fn idents_name_eq_test() {
|
||||
assert!(segments_name_eq([Ident{name:3,ctxt:4},
|
||||
Ident{name:78,ctxt:82}].map(ident_to_segment),
|
||||
[Ident{name:3,ctxt:104},
|
||||
Ident{name:78,ctxt:182}].map(ident_to_segment)));
|
||||
assert!(!segments_name_eq([Ident{name:3,ctxt:4},
|
||||
Ident{name:78,ctxt:82}].map(ident_to_segment),
|
||||
[Ident{name:3,ctxt:104},
|
||||
Ident{name:77,ctxt:182}].map(ident_to_segment)));
|
||||
}
|
||||
|
||||
#[test] fn xorpush_test () {
|
||||
let mut s = ~[];
|
||||
|
|
@ -1122,29 +1224,30 @@ mod test {
|
|||
#[test] fn resolve_tests () {
|
||||
let a = 40;
|
||||
let mut t = new_sctable_internal();
|
||||
let mut rt = HashMap::new();
|
||||
// - ctxt is MT
|
||||
assert_eq!(resolve_internal(id(a,EMPTY_CTXT),&mut t),a);
|
||||
assert_eq!(resolve_internal(id(a,EMPTY_CTXT),&mut t, &mut rt),a);
|
||||
// - simple ignored marks
|
||||
{ let sc = unfold_marks(~[1,2,3],EMPTY_CTXT,&mut t);
|
||||
assert_eq!(resolve_internal(id(a,sc),&mut t),a);}
|
||||
assert_eq!(resolve_internal(id(a,sc),&mut t, &mut rt),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_internal(id(a,sc),&mut t),a);}
|
||||
assert_eq!(resolve_internal(id(a,sc),&mut t, &mut rt),a);}
|
||||
// - rename where names do match, but marks don't
|
||||
{ let sc1 = new_mark_internal(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_internal(id(a,sc),&mut t), a);}
|
||||
assert_eq!(resolve_internal(id(a,sc),&mut t, &mut rt), 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_internal(id(a,sc),&mut t), 50); }
|
||||
assert_eq!(resolve_internal(id(a,sc),&mut t, &mut rt), 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_internal(id(a,sc),&mut t), 50); }
|
||||
assert_eq!(resolve_internal(id(a,sc),&mut t, &mut rt), 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:
|
||||
|
|
@ -1152,22 +1255,28 @@ mod 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_internal(id(a,sc),&mut t), 51); }
|
||||
assert_eq!(resolve_internal(id(a,sc),&mut t, &mut rt), 51); }
|
||||
// the simplest double-rename:
|
||||
{ let a_to_a50 = new_rename_internal(id(a,EMPTY_CTXT),50,EMPTY_CTXT,&mut t);
|
||||
let a50_to_a51 = new_rename_internal(id(a,a_to_a50),51,a_to_a50,&mut t);
|
||||
assert_eq!(resolve_internal(id(a,a50_to_a51),&mut t),51);
|
||||
assert_eq!(resolve_internal(id(a,a50_to_a51),&mut t, &mut rt),51);
|
||||
// mark on the outside doesn't stop rename:
|
||||
let sc = new_mark_internal(9,a50_to_a51,&mut t);
|
||||
assert_eq!(resolve_internal(id(a,sc),&mut t),51);
|
||||
assert_eq!(resolve_internal(id(a,sc),&mut t, &mut rt),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_internal(id(a,a50_to_a51_b),&mut t),50);}
|
||||
assert_eq!(resolve_internal(id(a,a50_to_a51_b),&mut t, &mut rt),50);}
|
||||
}
|
||||
|
||||
#[test] fn mtwt_resolve_test(){
|
||||
let a = 40;
|
||||
assert_eq!(mtwt_resolve(id(a,EMPTY_CTXT)),a);
|
||||
}
|
||||
|
||||
|
||||
#[test] fn hashing_tests () {
|
||||
let mut t = new_sctable_internal();
|
||||
assert_eq!(new_mark_internal(12,EMPTY_CTXT,&mut t),2);
|
||||
|
|
@ -1177,4 +1286,16 @@ mod test {
|
|||
// I'm assuming that the rename table will behave the same....
|
||||
}
|
||||
|
||||
#[test] fn resolve_table_hashing_tests() {
|
||||
let mut t = new_sctable_internal();
|
||||
let mut rt = HashMap::new();
|
||||
assert_eq!(rt.len(),0);
|
||||
resolve_internal(id(30,EMPTY_CTXT),&mut t, &mut rt);
|
||||
assert_eq!(rt.len(),1);
|
||||
resolve_internal(id(39,EMPTY_CTXT),&mut t, &mut rt);
|
||||
assert_eq!(rt.len(),2);
|
||||
resolve_internal(id(30,EMPTY_CTXT),&mut t, &mut rt);
|
||||
assert_eq!(rt.len(),2);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,7 @@ use std::hashmap::HashMap;
|
|||
|
||||
// new-style macro! tt code:
|
||||
//
|
||||
// SyntaxExpanderTT, SyntaxExpanderTTItem, MacResult,
|
||||
// NormalTT, IdentTT
|
||||
// MacResult, NormalTT, IdentTT
|
||||
//
|
||||
// also note that ast::mac used to have a bunch of extraneous cases and
|
||||
// is now probably a redundant AST node, can be merged with
|
||||
|
|
@ -34,33 +33,46 @@ pub struct MacroDef {
|
|||
ext: SyntaxExtension
|
||||
}
|
||||
|
||||
pub type ItemDecorator = @fn(@ExtCtxt,
|
||||
// No context arg for an Item Decorator macro, simply because
|
||||
// adding it would require adding a ctxt field to all items.
|
||||
// we could do this if it turns out to be useful.
|
||||
|
||||
pub type ItemDecoratorFun = @fn(@ExtCtxt,
|
||||
Span,
|
||||
@ast::MetaItem,
|
||||
~[@ast::item])
|
||||
-> ~[@ast::item];
|
||||
|
||||
pub struct SyntaxExpanderTT {
|
||||
expander: SyntaxExpanderTTFun,
|
||||
span: Option<Span>
|
||||
}
|
||||
|
||||
pub type SyntaxExpanderTTFun = @fn(@ExtCtxt,
|
||||
Span,
|
||||
&[ast::token_tree])
|
||||
&[ast::token_tree],
|
||||
ast::SyntaxContext)
|
||||
-> MacResult;
|
||||
|
||||
pub struct SyntaxExpanderTTItem {
|
||||
expander: SyntaxExpanderTTItemFun,
|
||||
span: Option<Span>
|
||||
}
|
||||
|
||||
pub type SyntaxExpanderTTItemFun = @fn(@ExtCtxt,
|
||||
Span,
|
||||
ast::Ident,
|
||||
~[ast::token_tree],
|
||||
ast::SyntaxContext)
|
||||
-> MacResult;
|
||||
|
||||
// oog... in order to make the presentation of builtin_normal_tt_no_ctxt
|
||||
// and builtin_ident_tt_no_ctxt palatable, we need one-off types for
|
||||
// functions that don't consume a ctxt:
|
||||
|
||||
pub type SyntaxExpanderTTFunNoCtxt = @fn(@ExtCtxt,
|
||||
Span,
|
||||
&[ast::token_tree])
|
||||
-> MacResult;
|
||||
|
||||
pub type SyntaxExpanderTTItemFunNoCtxt = @fn(@ExtCtxt,
|
||||
Span,
|
||||
ast::Ident,
|
||||
~[ast::token_tree])
|
||||
-> MacResult;
|
||||
|
||||
|
||||
|
||||
pub enum MacResult {
|
||||
MRExpr(@ast::Expr),
|
||||
MRItem(@ast::item),
|
||||
|
|
@ -73,10 +85,10 @@ pub enum MacResult {
|
|||
pub enum SyntaxExtension {
|
||||
|
||||
// #[auto_encode] and such
|
||||
ItemDecorator(ItemDecorator),
|
||||
ItemDecorator(ItemDecoratorFun),
|
||||
|
||||
// Token-tree expanders
|
||||
NormalTT(SyntaxExpanderTT),
|
||||
NormalTT(SyntaxExpanderTTFun, Option<Span>),
|
||||
|
||||
// An IdentTT is a macro that has an
|
||||
// identifier in between the name of the
|
||||
|
|
@ -86,9 +98,10 @@ pub enum SyntaxExtension {
|
|||
|
||||
// perhaps macro_rules! will lose its odd special identifier argument,
|
||||
// and this can go away also
|
||||
IdentTT(SyntaxExpanderTTItem),
|
||||
IdentTT(SyntaxExpanderTTItemFun, Option<Span>),
|
||||
}
|
||||
|
||||
|
||||
// The SyntaxEnv is the environment that's threaded through the expansion
|
||||
// of macros. It contains bindings for macros, and also a special binding
|
||||
// for " block" (not a legal identifier) that maps to a BlockInfo
|
||||
|
|
@ -120,12 +133,16 @@ type RenameList = ~[(ast::Ident,Name)];
|
|||
// AST nodes into full ASTs
|
||||
pub fn syntax_expander_table() -> SyntaxEnv {
|
||||
// utility function to simplify creating NormalTT syntax extensions
|
||||
fn builtin_normal_tt(f: SyntaxExpanderTTFun) -> @Transformer {
|
||||
@SE(NormalTT(SyntaxExpanderTT{expander: f, span: None}))
|
||||
// that ignore their contexts
|
||||
fn builtin_normal_tt_no_ctxt(f: SyntaxExpanderTTFunNoCtxt) -> @Transformer {
|
||||
let wrapped_expander : SyntaxExpanderTTFun = |a,b,c,_d|{f(a,b,c)};
|
||||
@SE(NormalTT(wrapped_expander, None))
|
||||
}
|
||||
// utility function to simplify creating IdentTT syntax extensions
|
||||
fn builtin_item_tt(f: SyntaxExpanderTTItemFun) -> @Transformer {
|
||||
@SE(IdentTT(SyntaxExpanderTTItem{expander: f, span: None}))
|
||||
// that ignore their contexts
|
||||
fn builtin_item_tt_no_ctxt(f: SyntaxExpanderTTItemFunNoCtxt) -> @Transformer {
|
||||
let wrapped_expander : SyntaxExpanderTTItemFun = |a,b,c,d,_e|{f(a,b,c,d)};
|
||||
@SE(IdentTT(wrapped_expander, None))
|
||||
}
|
||||
let mut syntax_expanders = HashMap::new();
|
||||
// NB identifier starts with space, and can't conflict with legal idents
|
||||
|
|
@ -135,16 +152,15 @@ pub fn syntax_expander_table() -> SyntaxEnv {
|
|||
pending_renames : @mut ~[]
|
||||
}));
|
||||
syntax_expanders.insert(intern(&"macro_rules"),
|
||||
builtin_item_tt(
|
||||
ext::tt::macro_rules::add_new_extension));
|
||||
@SE(IdentTT(ext::tt::macro_rules::add_new_extension, None)));
|
||||
syntax_expanders.insert(intern(&"fmt"),
|
||||
builtin_normal_tt(ext::fmt::expand_syntax_ext));
|
||||
builtin_normal_tt_no_ctxt(ext::fmt::expand_syntax_ext));
|
||||
syntax_expanders.insert(intern(&"format"),
|
||||
builtin_normal_tt(ext::ifmt::expand_format));
|
||||
builtin_normal_tt_no_ctxt(ext::ifmt::expand_format));
|
||||
syntax_expanders.insert(intern(&"write"),
|
||||
builtin_normal_tt(ext::ifmt::expand_write));
|
||||
builtin_normal_tt_no_ctxt(ext::ifmt::expand_write));
|
||||
syntax_expanders.insert(intern(&"writeln"),
|
||||
builtin_normal_tt(ext::ifmt::expand_writeln));
|
||||
builtin_normal_tt_no_ctxt(ext::ifmt::expand_writeln));
|
||||
syntax_expanders.insert(
|
||||
intern(&"auto_encode"),
|
||||
@SE(ItemDecorator(ext::auto_encode::expand_auto_encode)));
|
||||
|
|
@ -152,16 +168,16 @@ pub fn syntax_expander_table() -> SyntaxEnv {
|
|||
intern(&"auto_decode"),
|
||||
@SE(ItemDecorator(ext::auto_encode::expand_auto_decode)));
|
||||
syntax_expanders.insert(intern(&"env"),
|
||||
builtin_normal_tt(ext::env::expand_env));
|
||||
builtin_normal_tt_no_ctxt(ext::env::expand_env));
|
||||
syntax_expanders.insert(intern(&"option_env"),
|
||||
builtin_normal_tt(ext::env::expand_option_env));
|
||||
builtin_normal_tt_no_ctxt(ext::env::expand_option_env));
|
||||
syntax_expanders.insert(intern("bytes"),
|
||||
builtin_normal_tt(ext::bytes::expand_syntax_ext));
|
||||
builtin_normal_tt_no_ctxt(ext::bytes::expand_syntax_ext));
|
||||
syntax_expanders.insert(intern("concat_idents"),
|
||||
builtin_normal_tt(
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::concat_idents::expand_syntax_ext));
|
||||
syntax_expanders.insert(intern(&"log_syntax"),
|
||||
builtin_normal_tt(
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::log_syntax::expand_syntax_ext));
|
||||
syntax_expanders.insert(intern(&"deriving"),
|
||||
@SE(ItemDecorator(
|
||||
|
|
@ -169,49 +185,50 @@ pub fn syntax_expander_table() -> SyntaxEnv {
|
|||
|
||||
// Quasi-quoting expanders
|
||||
syntax_expanders.insert(intern(&"quote_tokens"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_tokens));
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::quote::expand_quote_tokens));
|
||||
syntax_expanders.insert(intern(&"quote_expr"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_expr));
|
||||
builtin_normal_tt_no_ctxt(ext::quote::expand_quote_expr));
|
||||
syntax_expanders.insert(intern(&"quote_ty"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_ty));
|
||||
builtin_normal_tt_no_ctxt(ext::quote::expand_quote_ty));
|
||||
syntax_expanders.insert(intern(&"quote_item"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_item));
|
||||
builtin_normal_tt_no_ctxt(ext::quote::expand_quote_item));
|
||||
syntax_expanders.insert(intern(&"quote_pat"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_pat));
|
||||
builtin_normal_tt_no_ctxt(ext::quote::expand_quote_pat));
|
||||
syntax_expanders.insert(intern(&"quote_stmt"),
|
||||
builtin_normal_tt(ext::quote::expand_quote_stmt));
|
||||
builtin_normal_tt_no_ctxt(ext::quote::expand_quote_stmt));
|
||||
|
||||
syntax_expanders.insert(intern(&"line"),
|
||||
builtin_normal_tt(
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_line));
|
||||
syntax_expanders.insert(intern(&"col"),
|
||||
builtin_normal_tt(
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_col));
|
||||
syntax_expanders.insert(intern(&"file"),
|
||||
builtin_normal_tt(
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_file));
|
||||
syntax_expanders.insert(intern(&"stringify"),
|
||||
builtin_normal_tt(
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_stringify));
|
||||
syntax_expanders.insert(intern(&"include"),
|
||||
builtin_normal_tt(
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_include));
|
||||
syntax_expanders.insert(intern(&"include_str"),
|
||||
builtin_normal_tt(
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_include_str));
|
||||
syntax_expanders.insert(intern(&"include_bin"),
|
||||
builtin_normal_tt(
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_include_bin));
|
||||
syntax_expanders.insert(intern(&"module_path"),
|
||||
builtin_normal_tt(
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_mod));
|
||||
syntax_expanders.insert(intern(&"asm"),
|
||||
builtin_normal_tt(ext::asm::expand_asm));
|
||||
builtin_normal_tt_no_ctxt(ext::asm::expand_asm));
|
||||
syntax_expanders.insert(intern(&"cfg"),
|
||||
builtin_normal_tt(ext::cfg::expand_cfg));
|
||||
builtin_normal_tt_no_ctxt(ext::cfg::expand_cfg));
|
||||
syntax_expanders.insert(
|
||||
intern(&"trace_macros"),
|
||||
builtin_normal_tt(ext::trace_macros::expand_trace_macros));
|
||||
builtin_normal_tt_no_ctxt(ext::trace_macros::expand_trace_macros));
|
||||
MapChain::new(~syntax_expanders)
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -293,45 +293,51 @@ pub fn expand_quote_tokens(cx: @ExtCtxt,
|
|||
sp: Span,
|
||||
tts: &[ast::token_tree]) -> base::MacResult {
|
||||
let (cx_expr, expr) = expand_tts(cx, sp, tts);
|
||||
base::MRExpr(expand_wrapper(cx, sp, cx_expr, expr))
|
||||
let expanded = expand_wrapper(cx, sp, cx_expr, expr);
|
||||
base::MRExpr(expanded)
|
||||
}
|
||||
|
||||
pub fn expand_quote_expr(cx: @ExtCtxt,
|
||||
sp: Span,
|
||||
tts: &[ast::token_tree]) -> base::MacResult {
|
||||
base::MRExpr(expand_parse_call(cx, sp, "parse_expr", ~[], tts))
|
||||
let expanded = expand_parse_call(cx, sp, "parse_expr", ~[], tts);
|
||||
base::MRExpr(expanded)
|
||||
}
|
||||
|
||||
pub fn expand_quote_item(cx: @ExtCtxt,
|
||||
sp: Span,
|
||||
tts: &[ast::token_tree]) -> base::MacResult {
|
||||
let e_attrs = cx.expr_vec_uniq(sp, ~[]);
|
||||
base::MRExpr(expand_parse_call(cx, sp, "parse_item",
|
||||
~[e_attrs], tts))
|
||||
let expanded = expand_parse_call(cx, sp, "parse_item",
|
||||
~[e_attrs], tts);
|
||||
base::MRExpr(expanded)
|
||||
}
|
||||
|
||||
pub fn expand_quote_pat(cx: @ExtCtxt,
|
||||
sp: Span,
|
||||
tts: &[ast::token_tree]) -> base::MacResult {
|
||||
let e_refutable = cx.expr_lit(sp, ast::lit_bool(true));
|
||||
base::MRExpr(expand_parse_call(cx, sp, "parse_pat",
|
||||
~[e_refutable], tts))
|
||||
let expanded = expand_parse_call(cx, sp, "parse_pat",
|
||||
~[e_refutable], tts);
|
||||
base::MRExpr(expanded)
|
||||
}
|
||||
|
||||
pub fn expand_quote_ty(cx: @ExtCtxt,
|
||||
sp: Span,
|
||||
tts: &[ast::token_tree]) -> base::MacResult {
|
||||
let e_param_colons = cx.expr_lit(sp, ast::lit_bool(false));
|
||||
base::MRExpr(expand_parse_call(cx, sp, "parse_ty",
|
||||
~[e_param_colons], tts))
|
||||
let expanded = expand_parse_call(cx, sp, "parse_ty",
|
||||
~[e_param_colons], tts);
|
||||
base::MRExpr(expanded)
|
||||
}
|
||||
|
||||
pub fn expand_quote_stmt(cx: @ExtCtxt,
|
||||
sp: Span,
|
||||
tts: &[ast::token_tree]) -> base::MacResult {
|
||||
let e_attrs = cx.expr_vec_uniq(sp, ~[]);
|
||||
base::MRExpr(expand_parse_call(cx, sp, "parse_stmt",
|
||||
~[e_attrs], tts))
|
||||
let expanded = expand_parse_call(cx, sp, "parse_stmt",
|
||||
~[e_attrs], tts);
|
||||
base::MRExpr(expanded)
|
||||
}
|
||||
|
||||
fn ids_ext(strs: ~[~str]) -> ~[ast::Ident] {
|
||||
|
|
|
|||
|
|
@ -234,6 +234,15 @@ pub fn parse_or_else(
|
|||
}
|
||||
}
|
||||
|
||||
// perform a token equality check, ignoring syntax context (that is, an unhygienic comparison)
|
||||
pub fn token_name_eq(t1 : &Token, t2 : &Token) -> bool {
|
||||
match (t1,t2) {
|
||||
(&token::IDENT(id1,_),&token::IDENT(id2,_)) =>
|
||||
id1.name == id2.name,
|
||||
_ => *t1 == *t2
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(
|
||||
sess: @mut ParseSess,
|
||||
cfg: ast::CrateConfig,
|
||||
|
|
@ -297,7 +306,10 @@ pub fn parse(
|
|||
// the *_t vars are workarounds for the lack of unary move
|
||||
match ei.sep {
|
||||
Some(ref t) if idx == len => { // we need a separator
|
||||
if tok == (*t) { //pass the separator
|
||||
// i'm conflicted about whether this should be hygienic....
|
||||
// though in this case, if the separators are never legal
|
||||
// idents, it shouldn't matter.
|
||||
if token_name_eq(&tok, t) { //pass the separator
|
||||
let mut ei_t = ei.clone();
|
||||
ei_t.idx += 1;
|
||||
next_eis.push(ei_t);
|
||||
|
|
@ -343,7 +355,8 @@ pub fn parse(
|
|||
match_nonterminal(_,_,_) => { bb_eis.push(ei) }
|
||||
match_tok(ref t) => {
|
||||
let mut ei_t = ei.clone();
|
||||
if (*t) == tok {
|
||||
//if (token_name_eq(t,&tok)) {
|
||||
if (token::mtwt_token_eq(t,&tok)) {
|
||||
ei_t.idx += 1;
|
||||
next_eis.push(ei_t);
|
||||
}
|
||||
|
|
@ -353,7 +366,7 @@ pub fn parse(
|
|||
}
|
||||
|
||||
/* error messages here could be improved with links to orig. rules */
|
||||
if tok == EOF {
|
||||
if token_name_eq(&tok, &EOF) {
|
||||
if eof_eis.len() == 1u {
|
||||
let mut v = ~[];
|
||||
for dv in eof_eis[0u].matches.mut_iter() {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use ast;
|
|||
use codemap::{Span, Spanned, dummy_sp};
|
||||
use ext::base::{ExtCtxt, MacResult, MRAny, MRDef, MacroDef, NormalTT};
|
||||
use ext::base;
|
||||
use ext::expand;
|
||||
use ext::tt::macro_parser::{error};
|
||||
use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal};
|
||||
use ext::tt::macro_parser::{parse, parse_or_else, success, failure};
|
||||
|
|
@ -23,11 +24,17 @@ use parse::token::{get_ident_interner, special_idents, gensym_ident, ident_to_st
|
|||
use parse::token::{FAT_ARROW, SEMI, nt_matchers, nt_tt};
|
||||
use print;
|
||||
|
||||
// this procedure performs the expansion of the
|
||||
// macro_rules! macro. It parses the RHS and adds
|
||||
// an extension to the current context.
|
||||
pub fn add_new_extension(cx: @ExtCtxt,
|
||||
sp: Span,
|
||||
name: Ident,
|
||||
arg: ~[ast::token_tree])
|
||||
arg: ~[ast::token_tree],
|
||||
stx_ctxt: ast::SyntaxContext)
|
||||
-> base::MacResult {
|
||||
let arg = expand::mtwt_cancel_outer_mark(arg,stx_ctxt);
|
||||
// Wrap a matcher_ in a spanned to produce a matcher.
|
||||
// these spans won't matter, anyways
|
||||
fn ms(m: matcher_) -> matcher {
|
||||
Spanned {
|
||||
|
|
@ -39,6 +46,7 @@ pub fn add_new_extension(cx: @ExtCtxt,
|
|||
let lhs_nm = gensym_ident("lhs");
|
||||
let rhs_nm = gensym_ident("rhs");
|
||||
|
||||
// The pattern that macro_rules matches.
|
||||
// The grammar for macro_rules! is:
|
||||
// $( $lhs:mtcs => $rhs:tt );+
|
||||
// ...quasiquoting this would be nice.
|
||||
|
|
@ -144,11 +152,11 @@ pub fn add_new_extension(cx: @ExtCtxt,
|
|||
cx.span_fatal(best_fail_spot, best_fail_msg);
|
||||
}
|
||||
|
||||
let exp: @fn(@ExtCtxt, Span, &[ast::token_tree]) -> MacResult =
|
||||
|cx, sp, arg| generic_extension(cx, sp, name, arg, *lhses, *rhses);
|
||||
let exp: @fn(@ExtCtxt, Span, &[ast::token_tree], ctxt: ast::SyntaxContext) -> MacResult =
|
||||
|cx, sp, arg, _ctxt| generic_extension(cx, sp, name, arg, *lhses, *rhses);
|
||||
|
||||
return MRDef(MacroDef{
|
||||
name: ident_to_str(&name),
|
||||
ext: NormalTT(base::SyntaxExpanderTT{expander: exp, span: Some(sp)})
|
||||
ext: NormalTT(exp, Some(sp))
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,14 @@ use codemap::{Span, Spanned};
|
|||
use parse::token;
|
||||
use opt_vec::OptVec;
|
||||
|
||||
// this file defines an ast_fold trait for objects that can perform
|
||||
// a "fold" on Rust ASTs. It also contains a structure that implements
|
||||
// that trait, and a "default_fold" whose fields contain closures
|
||||
// that perform "default traversals", visiting all of the sub-elements
|
||||
// and re-assembling the result. The "fun_to_ident_folder" in the
|
||||
// test module provides a simple example of creating a very simple
|
||||
// fold that only looks at identifiers.
|
||||
|
||||
pub trait ast_fold {
|
||||
fn fold_crate(@self, &Crate) -> Crate;
|
||||
fn fold_view_item(@self, &view_item) -> view_item;
|
||||
|
|
@ -35,6 +43,7 @@ pub trait ast_fold {
|
|||
fn fold_ident(@self, Ident) -> Ident;
|
||||
fn fold_path(@self, &Path) -> Path;
|
||||
fn fold_local(@self, @Local) -> @Local;
|
||||
fn fold_mac(@self, &mac) -> mac;
|
||||
fn map_exprs(@self, @fn(@Expr) -> @Expr, &[@Expr]) -> ~[@Expr];
|
||||
fn new_id(@self, NodeId) -> NodeId;
|
||||
fn new_span(@self, Span) -> Span;
|
||||
|
|
@ -64,6 +73,7 @@ pub struct AstFoldFns {
|
|||
fold_ident: @fn(Ident, @ast_fold) -> Ident,
|
||||
fold_path: @fn(&Path, @ast_fold) -> Path,
|
||||
fold_local: @fn(@Local, @ast_fold) -> @Local,
|
||||
fold_mac: @fn(&mac_, Span, @ast_fold) -> (mac_, Span),
|
||||
map_exprs: @fn(@fn(@Expr) -> @Expr, &[@Expr]) -> ~[@Expr],
|
||||
new_id: @fn(NodeId) -> NodeId,
|
||||
new_span: @fn(Span) -> Span
|
||||
|
|
@ -112,41 +122,31 @@ fn fold_arg_(a: arg, fld: @ast_fold) -> arg {
|
|||
}
|
||||
}
|
||||
|
||||
//used in noop_fold_expr, and possibly elsewhere in the future
|
||||
fn fold_mac_(m: &mac, fld: @ast_fold) -> mac {
|
||||
Spanned {
|
||||
node: match m.node {
|
||||
mac_invoc_tt(ref p,ref tts) =>
|
||||
mac_invoc_tt(fld.fold_path(p),
|
||||
fold_tts(*tts,fld))
|
||||
},
|
||||
span: fld.new_span(m.span)
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_tts(tts : &[token_tree], fld: @ast_fold) -> ~[token_tree] {
|
||||
// build a new vector of tts by appling the ast_fold's fold_ident to
|
||||
// all of the identifiers in the token trees.
|
||||
pub fn fold_tts(tts : &[token_tree], f : @ast_fold) -> ~[token_tree] {
|
||||
do tts.map |tt| {
|
||||
match *tt {
|
||||
tt_tok(span, ref tok) =>
|
||||
tt_tok(span,maybe_fold_ident(tok,fld)),
|
||||
tt_tok(span,maybe_fold_ident(tok,f)),
|
||||
tt_delim(ref tts) =>
|
||||
tt_delim(@mut fold_tts(**tts, fld)),
|
||||
tt_delim(@mut fold_tts(**tts, f)),
|
||||
tt_seq(span, ref pattern, ref sep, is_optional) =>
|
||||
tt_seq(span,
|
||||
@mut fold_tts(**pattern, fld),
|
||||
sep.map(|tok|maybe_fold_ident(tok,fld)),
|
||||
@mut fold_tts(**pattern, f),
|
||||
sep.map(|tok|maybe_fold_ident(tok,f)),
|
||||
is_optional),
|
||||
tt_nonterminal(sp,ref ident) =>
|
||||
tt_nonterminal(sp,fld.fold_ident(*ident))
|
||||
tt_nonterminal(sp,f.fold_ident(*ident))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// apply ident folder if it's an ident, otherwise leave it alone
|
||||
fn maybe_fold_ident(t: &token::Token, fld: @ast_fold) -> token::Token {
|
||||
fn maybe_fold_ident(t : &token::Token, f: @ast_fold) -> token::Token {
|
||||
match *t {
|
||||
token::IDENT(id,followed_by_colons) =>
|
||||
token::IDENT(fld.fold_ident(id),followed_by_colons),
|
||||
token::IDENT(f.fold_ident(id),followed_by_colons),
|
||||
_ => (*t).clone()
|
||||
}
|
||||
}
|
||||
|
|
@ -209,6 +209,7 @@ pub fn noop_fold_crate(c: &Crate, fld: @ast_fold) -> Crate {
|
|||
}
|
||||
|
||||
fn noop_fold_view_item(vi: &view_item_, _fld: @ast_fold) -> view_item_ {
|
||||
// FIXME #7654: doesn't iterate over idents in a view_item_use
|
||||
return /* FIXME (#2543) */ (*vi).clone();
|
||||
}
|
||||
|
||||
|
|
@ -323,11 +324,7 @@ pub fn noop_fold_item_underscore(i: &item_, fld: @ast_fold) -> item_ {
|
|||
)
|
||||
}
|
||||
item_mac(ref m) => {
|
||||
// FIXME #2888: we might actually want to do something here.
|
||||
// ... okay, we're doing something. It would probably be nicer
|
||||
// to add something to the ast_fold trait, but I'll defer
|
||||
// that work.
|
||||
item_mac(fold_mac_(m,fld))
|
||||
item_mac(fld.fold_mac(m))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -396,7 +393,6 @@ pub fn noop_fold_block(b: &Block, fld: @ast_fold) -> Block {
|
|||
}
|
||||
|
||||
fn noop_fold_stmt(s: &Stmt_, fld: @ast_fold) -> Option<Stmt_> {
|
||||
let fold_mac = |x| fold_mac_(x, fld);
|
||||
match *s {
|
||||
StmtDecl(d, nid) => {
|
||||
match fld.fold_decl(d) {
|
||||
|
|
@ -410,7 +406,7 @@ fn noop_fold_stmt(s: &Stmt_, fld: @ast_fold) -> Option<Stmt_> {
|
|||
StmtSemi(e, nid) => {
|
||||
Some(StmtSemi(fld.fold_expr(e), fld.new_id(nid)))
|
||||
}
|
||||
StmtMac(ref mac, semi) => Some(StmtMac(fold_mac(mac), semi))
|
||||
StmtMac(ref mac, semi) => Some(StmtMac(fld.fold_mac(mac), semi))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -478,6 +474,12 @@ fn noop_fold_decl(d: &Decl_, fld: @ast_fold) -> Option<Decl_> {
|
|||
}
|
||||
}
|
||||
|
||||
// lift a function in ast-thingy X fold -> ast-thingy to a function
|
||||
// in (ast-thingy X span X fold) -> (ast-thingy X span). Basically,
|
||||
// carries the span around.
|
||||
// It seems strange to me that the call to new_fold doesn't happen
|
||||
// here but instead in the impl down below.... probably just an
|
||||
// accident?
|
||||
pub fn wrap<T>(f: @fn(&T, @ast_fold) -> T)
|
||||
-> @fn(&T, Span, @ast_fold) -> (T, Span) {
|
||||
let result: @fn(&T, Span, @ast_fold) -> (T, Span) = |x, s, fld| {
|
||||
|
|
@ -496,8 +498,6 @@ pub fn noop_fold_expr(e: &Expr_, fld: @ast_fold) -> Expr_ {
|
|||
}
|
||||
let fold_field = |x| fold_field_(x, fld);
|
||||
|
||||
let fold_mac = |x| fold_mac_(x, fld);
|
||||
|
||||
match *e {
|
||||
ExprVstore(e, v) => {
|
||||
ExprVstore(fld.fold_expr(e), v)
|
||||
|
|
@ -544,7 +544,7 @@ pub fn noop_fold_expr(e: &Expr_, fld: @ast_fold) -> Expr_ {
|
|||
ExprDoBody(f) => ExprDoBody(fld.fold_expr(f)),
|
||||
ExprLit(_) => (*e).clone(),
|
||||
ExprCast(expr, ref ty) => {
|
||||
ExprCast(fld.fold_expr(expr), (*ty).clone())
|
||||
ExprCast(fld.fold_expr(expr), fld.fold_ty(ty))
|
||||
}
|
||||
ExprAddrOf(m, ohs) => ExprAddrOf(m, fld.fold_expr(ohs)),
|
||||
ExprIf(cond, ref tr, fl) => {
|
||||
|
|
@ -629,7 +629,7 @@ pub fn noop_fold_expr(e: &Expr_, fld: @ast_fold) -> Expr_ {
|
|||
.. (*a).clone()
|
||||
})
|
||||
}
|
||||
ExprMac(ref mac) => ExprMac(fold_mac(mac)),
|
||||
ExprMac(ref mac) => ExprMac(fld.fold_mac(mac)),
|
||||
ExprStruct(ref path, ref fields, maybe_expr) => {
|
||||
ExprStruct(
|
||||
fld.fold_path(path),
|
||||
|
|
@ -642,7 +642,6 @@ pub fn noop_fold_expr(e: &Expr_, fld: @ast_fold) -> Expr_ {
|
|||
}
|
||||
|
||||
pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ {
|
||||
let fold_mac = |x| fold_mac_(x, fld);
|
||||
fn fold_mt(mt: &mt, fld: @ast_fold) -> mt {
|
||||
mt {
|
||||
ty: ~fld.fold_ty(mt.ty),
|
||||
|
|
@ -698,7 +697,7 @@ pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ {
|
|||
)
|
||||
}
|
||||
ty_typeof(e) => ty_typeof(fld.fold_expr(e)),
|
||||
ty_mac(ref mac) => ty_mac(fold_mac(mac))
|
||||
ty_mac(ref mac) => ty_mac(fld.fold_mac(mac))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -785,6 +784,19 @@ fn noop_fold_local(l: @Local, fld: @ast_fold) -> @Local {
|
|||
}
|
||||
}
|
||||
|
||||
// the default macro traversal. visit the path
|
||||
// using fold_path, and the tts using fold_tts,
|
||||
// and the span using new_span
|
||||
fn noop_fold_mac(m: &mac_, fld: @ast_fold) -> mac_ {
|
||||
match *m {
|
||||
mac_invoc_tt(ref p,ref tts,ctxt) =>
|
||||
mac_invoc_tt(fld.fold_path(p),
|
||||
fold_tts(*tts,fld),
|
||||
ctxt)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* temporarily eta-expand because of a compiler bug with using `fn<T>` as a
|
||||
value */
|
||||
fn noop_map_exprs(f: @fn(@Expr) -> @Expr, es: &[@Expr]) -> ~[@Expr] {
|
||||
|
|
@ -817,6 +829,7 @@ pub fn default_ast_fold() -> ast_fold_fns {
|
|||
fold_ident: noop_fold_ident,
|
||||
fold_path: noop_fold_path,
|
||||
fold_local: noop_fold_local,
|
||||
fold_mac: wrap(noop_fold_mac),
|
||||
map_exprs: noop_map_exprs,
|
||||
new_id: noop_id,
|
||||
new_span: noop_span,
|
||||
|
|
@ -922,6 +935,10 @@ impl ast_fold for AstFoldFns {
|
|||
fn fold_local(@self, x: @Local) -> @Local {
|
||||
(self.fold_local)(x, self as @ast_fold)
|
||||
}
|
||||
fn fold_mac(@self, x: &mac) -> mac {
|
||||
let (n, s) = (self.fold_mac)(&x.node, x.span, self as @ast_fold);
|
||||
Spanned { node: n, span: (self.new_span)(s) }
|
||||
}
|
||||
fn map_exprs(@self,
|
||||
f: @fn(@Expr) -> @Expr,
|
||||
e: &[@Expr])
|
||||
|
|
@ -946,6 +963,8 @@ impl AstFoldExtensions for @ast_fold {
|
|||
}
|
||||
}
|
||||
|
||||
// brson agrees with me that this function's existence is probably
|
||||
// not a good or useful thing.
|
||||
pub fn make_fold(afp: ast_fold_fns) -> @ast_fold {
|
||||
afp as @ast_fold
|
||||
}
|
||||
|
|
@ -1018,4 +1037,15 @@ mod test {
|
|||
token::get_ident_interner()),
|
||||
~"zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)))");
|
||||
}
|
||||
|
||||
// and in cast expressions... this appears to be an existing bug.
|
||||
#[test] fn ident_transformation_in_types () {
|
||||
let zz_fold = fun_to_ident_folder(to_zz());
|
||||
let ast = string_to_crate(@"fn a() {let z = 13 as int;}");
|
||||
assert_pred!(matches_codepattern,
|
||||
"matches_codepattern",
|
||||
pprust::to_str(&zz_fold.fold_crate(ast),fake_print_crate,
|
||||
token::get_ident_interner()),
|
||||
~"fn zz(){let zz=13 as zz;}");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use ast::{_mod, BiAdd, arg, Arm, Attribute, BindByRef, BindInfer};
|
|||
use ast::{BiBitAnd, BiBitOr, BiBitXor, Block};
|
||||
use ast::{BlockCheckMode, UnBox};
|
||||
use ast::{Crate, CrateConfig, Decl, DeclItem};
|
||||
use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, enum_def, explicit_self};
|
||||
use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, enum_def, explicit_self};
|
||||
use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
|
||||
use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock};
|
||||
use ast::{ExprBreak, ExprCall, ExprCast, ExprDoBody};
|
||||
|
|
@ -1875,7 +1875,7 @@ impl Parser {
|
|||
|p| p.parse_token_tree());
|
||||
let hi = self.span.hi;
|
||||
|
||||
return self.mk_mac_expr(lo, hi, mac_invoc_tt(pth, tts));
|
||||
return self.mk_mac_expr(lo, hi, mac_invoc_tt(pth, tts, EMPTY_CTXT));
|
||||
} else if *self.token == token::LBRACE {
|
||||
// This might be a struct literal.
|
||||
if self.looking_at_record_literal() {
|
||||
|
|
@ -3197,14 +3197,14 @@ impl Parser {
|
|||
|
||||
if id == token::special_idents::invalid {
|
||||
return @spanned(lo, hi, StmtMac(
|
||||
spanned(lo, hi, mac_invoc_tt(pth, tts)), false));
|
||||
spanned(lo, hi, mac_invoc_tt(pth, tts, EMPTY_CTXT)), false));
|
||||
} else {
|
||||
// if it has a special ident, it's definitely an item
|
||||
return @spanned(lo, hi, StmtDecl(
|
||||
@spanned(lo, hi, DeclItem(
|
||||
self.mk_item(
|
||||
lo, hi, id /*id is good here*/,
|
||||
item_mac(spanned(lo, hi, mac_invoc_tt(pth, tts))),
|
||||
item_mac(spanned(lo, hi, mac_invoc_tt(pth, tts, EMPTY_CTXT))),
|
||||
inherited, ~[/*no attrs*/]))),
|
||||
self.get_id()));
|
||||
}
|
||||
|
|
@ -3518,7 +3518,10 @@ impl Parser {
|
|||
}
|
||||
|
||||
fn is_self_ident(&self) -> bool {
|
||||
*self.token == token::IDENT(special_idents::self_, false)
|
||||
match *self.token {
|
||||
token::IDENT(id, false) => id.name == special_idents::self_.name,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn expect_self_ident(&self) {
|
||||
|
|
@ -4806,7 +4809,7 @@ impl Parser {
|
|||
_ => self.fatal("expected open delimiter")
|
||||
};
|
||||
// single-variant-enum... :
|
||||
let m = ast::mac_invoc_tt(pth, tts);
|
||||
let m = ast::mac_invoc_tt(pth, tts, EMPTY_CTXT);
|
||||
let m: ast::mac = codemap::Spanned { node: m,
|
||||
span: mk_sp(self.span.lo,
|
||||
self.span.hi) };
|
||||
|
|
|
|||
|
|
@ -9,17 +9,15 @@
|
|||
// except according to those terms.
|
||||
|
||||
use ast;
|
||||
use ast::Name;
|
||||
use ast::{Name, Mrk};
|
||||
use ast_util;
|
||||
use parse::token;
|
||||
use util::interner::StrInterner;
|
||||
use util::interner;
|
||||
|
||||
use std::cast;
|
||||
use std::char;
|
||||
use std::cmp::Equiv;
|
||||
use std::local_data;
|
||||
use std::rand;
|
||||
use std::rand::RngUtil;
|
||||
|
||||
#[deriving(Clone, Encodable, Decodable, Eq, IterBytes)]
|
||||
pub enum binop {
|
||||
|
|
@ -309,22 +307,23 @@ pub fn is_bar(t: &Token) -> bool {
|
|||
match *t { BINOP(OR) | OROR => true, _ => false }
|
||||
}
|
||||
|
||||
|
||||
pub mod special_idents {
|
||||
use ast::Ident;
|
||||
|
||||
pub static underscore : Ident = Ident { name: 0, ctxt: 0};
|
||||
pub static underscore : Ident = Ident { name: 0, ctxt: 0}; // apparently unused?
|
||||
pub static anon : Ident = Ident { name: 1, ctxt: 0};
|
||||
pub static invalid : Ident = Ident { name: 2, ctxt: 0}; // ''
|
||||
pub static unary : Ident = Ident { name: 3, ctxt: 0};
|
||||
pub static not_fn : Ident = Ident { name: 4, ctxt: 0};
|
||||
pub static idx_fn : Ident = Ident { name: 5, ctxt: 0};
|
||||
pub static unary_minus_fn : Ident = Ident { name: 6, ctxt: 0};
|
||||
pub static unary : Ident = Ident { name: 3, ctxt: 0}; // apparently unused?
|
||||
pub static not_fn : Ident = Ident { name: 4, ctxt: 0}; // apparently unused?
|
||||
pub static idx_fn : Ident = Ident { name: 5, ctxt: 0}; // apparently unused?
|
||||
pub static unary_minus_fn : Ident = Ident { name: 6, ctxt: 0}; // apparently unused?
|
||||
pub static clownshoes_extensions : Ident = Ident { name: 7, ctxt: 0};
|
||||
|
||||
pub static self_ : Ident = Ident { name: 8, ctxt: 0}; // 'self'
|
||||
|
||||
/* for matcher NTs */
|
||||
// none of these appear to be used, but perhaps references to
|
||||
// these are artificially fabricated by the macro system....
|
||||
pub static item : Ident = Ident { name: 9, ctxt: 0};
|
||||
pub static block : Ident = Ident { name: 10, ctxt: 0};
|
||||
pub static stmt : Ident = Ident { name: 11, ctxt: 0};
|
||||
|
|
@ -336,7 +335,7 @@ pub mod special_idents {
|
|||
pub static tt : Ident = Ident { name: 17, ctxt: 0};
|
||||
pub static matchers : Ident = Ident { name: 18, ctxt: 0};
|
||||
|
||||
pub static str : Ident = Ident { name: 19, ctxt: 0}; // for the type
|
||||
pub static str : Ident = Ident { name: 19, ctxt: 0}; // for the type // apparently unused?
|
||||
|
||||
/* outside of libsyntax */
|
||||
pub static arg : Ident = Ident { name: 20, ctxt: 0};
|
||||
|
|
@ -349,10 +348,32 @@ pub mod special_idents {
|
|||
pub static statik : Ident = Ident { name: 27, ctxt: 0};
|
||||
pub static clownshoes_foreign_mod: Ident = Ident { name: 28, ctxt: 0};
|
||||
pub static unnamed_field: Ident = Ident { name: 29, ctxt: 0};
|
||||
pub static c_abi: Ident = Ident { name: 30, ctxt: 0};
|
||||
pub static c_abi: Ident = Ident { name: 30, ctxt: 0}; // apparently unused?
|
||||
pub static type_self: Ident = Ident { name: 31, ctxt: 0}; // `Self`
|
||||
}
|
||||
|
||||
// here are the ones that actually occur in the source. Maybe the rest
|
||||
// should be removed?
|
||||
/*
|
||||
special_idents::anon
|
||||
special_idents::arg
|
||||
special_idents::blk
|
||||
special_idents::clownshoe_abi
|
||||
special_idents::clownshoe_stack_shim
|
||||
special_idents::clownshoes_extensions
|
||||
special_idents::clownshoes_foreign_mod
|
||||
special_idents::descrim
|
||||
special_idents::invalid
|
||||
special_idents::main
|
||||
special_idents::matchers
|
||||
special_idents::opaque
|
||||
special_idents::self_
|
||||
special_idents::statik
|
||||
special_idents::tt
|
||||
special_idents::type_self
|
||||
special_idents::unnamed_field
|
||||
*/
|
||||
|
||||
/**
|
||||
* Maps a token to a record specifying the corresponding binary
|
||||
* operator
|
||||
|
|
@ -381,30 +402,8 @@ pub fn token_to_binop(tok: &Token) -> Option<ast::BinOp> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct ident_interner {
|
||||
priv interner: StrInterner,
|
||||
}
|
||||
|
||||
impl ident_interner {
|
||||
pub fn intern(&self, val: &str) -> Name {
|
||||
self.interner.intern(val)
|
||||
}
|
||||
pub fn gensym(&self, val: &str) -> Name {
|
||||
self.interner.gensym(val)
|
||||
}
|
||||
pub fn get(&self, idx: Name) -> @str {
|
||||
self.interner.get(idx)
|
||||
}
|
||||
// is this really something that should be exposed?
|
||||
pub fn len(&self) -> uint {
|
||||
self.interner.len()
|
||||
}
|
||||
pub fn find_equiv<Q:Hash + IterBytes + Equiv<@str>>(&self, val: &Q)
|
||||
-> Option<Name> {
|
||||
self.interner.find_equiv(val)
|
||||
}
|
||||
}
|
||||
|
||||
// looks like we can get rid of this completely...
|
||||
pub type ident_interner = StrInterner;
|
||||
|
||||
// return a fresh interner, preloaded with special identifiers.
|
||||
fn mk_fresh_ident_interner() -> @ident_interner {
|
||||
|
|
@ -485,9 +484,7 @@ fn mk_fresh_ident_interner() -> @ident_interner {
|
|||
"typeof", // 67
|
||||
];
|
||||
|
||||
@ident_interner {
|
||||
interner: interner::StrInterner::prefill(init_vec)
|
||||
}
|
||||
@interner::StrInterner::prefill(init_vec)
|
||||
}
|
||||
|
||||
// if an interner exists in TLS, return it. Otherwise, prepare a
|
||||
|
|
@ -508,7 +505,7 @@ pub fn get_ident_interner() -> @ident_interner {
|
|||
/* for when we don't care about the contents; doesn't interact with TLD or
|
||||
serialization */
|
||||
pub fn mk_fake_ident_interner() -> @ident_interner {
|
||||
@ident_interner { interner: interner::StrInterner::new() }
|
||||
@interner::StrInterner::new()
|
||||
}
|
||||
|
||||
// maps a string to its interned representation
|
||||
|
|
@ -543,18 +540,44 @@ pub fn gensym_ident(str : &str) -> ast::Ident {
|
|||
ast::Ident::new(gensym(str))
|
||||
}
|
||||
|
||||
// create a fresh name that maps to the same string as the old one.
|
||||
// note that this guarantees that str_ptr_eq(ident_to_str(src),interner_get(fresh_name(src)));
|
||||
// that is, that the new name and the old one are connected to ptr_eq strings.
|
||||
pub fn fresh_name(src : &ast::Ident) -> Name {
|
||||
let interner = get_ident_interner();
|
||||
interner.gensym_copy(src.name)
|
||||
// following: debug version. Could work in final except that it's incompatible with
|
||||
// good error messages and uses of struct names in ambiguous could-be-binding
|
||||
// locations. Also definitely destroys the guarantee given above about ptr_eq.
|
||||
/*let num = rand::rng().gen_uint_range(0,0xffff);
|
||||
gensym(fmt!("%s_%u",ident_to_str(src),num))*/
|
||||
}
|
||||
|
||||
// create a fresh name. In principle, this is just a
|
||||
// gensym, but for debugging purposes, you'd like the
|
||||
// resulting name to have a suggestive stringify, without
|
||||
// paying the cost of guaranteeing that the name is
|
||||
// truly unique. I'm going to try to strike a balance
|
||||
// by using a gensym with a name that has a random number
|
||||
// at the end. So, the gensym guarantees the uniqueness,
|
||||
// and the int helps to avoid confusion.
|
||||
pub fn fresh_name(src_name : &str) -> Name {
|
||||
let num = rand::rng().gen_uint_range(0,0xffff);
|
||||
gensym(fmt!("%s_%u",src_name,num))
|
||||
// it looks like there oughta be a str_ptr_eq fn, but no one bothered to implement it?
|
||||
|
||||
// determine whether two @str values are pointer-equal
|
||||
pub fn str_ptr_eq(a : @str, b : @str) -> bool {
|
||||
unsafe {
|
||||
let p : uint = cast::transmute(a);
|
||||
let q : uint = cast::transmute(b);
|
||||
let result = p == q;
|
||||
// got to transmute them back, to make sure the ref count is correct:
|
||||
let _junk1 : @str = cast::transmute(p);
|
||||
let _junk2 : @str = cast::transmute(q);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
// return true when two identifiers refer (through the intern table) to the same ptr_eq
|
||||
// string. This is used to compare identifiers in places where hygienic comparison is
|
||||
// not wanted (i.e. not lexical vars).
|
||||
pub fn ident_spelling_eq(a : &ast::Ident, b : &ast::Ident) -> bool {
|
||||
str_ptr_eq(interner_get(a.name),interner_get(b.name))
|
||||
}
|
||||
|
||||
// create a fresh mark.
|
||||
pub fn fresh_mark() -> Mrk {
|
||||
gensym("mark")
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -694,12 +717,48 @@ pub fn is_reserved_keyword(tok: &Token) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn mtwt_token_eq(t1 : &Token, t2 : &Token) -> bool {
|
||||
match (t1,t2) {
|
||||
(&IDENT(id1,_),&IDENT(id2,_)) =>
|
||||
ast_util::mtwt_resolve(id1) == ast_util::mtwt_resolve(id2),
|
||||
_ => *t1 == *t2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
#[test] fn t1() {
|
||||
let a = fresh_name("ghi");
|
||||
printfln!("interned name: %u,\ntextual name: %s\n",
|
||||
a, interner_get(a));
|
||||
use ast;
|
||||
use ast_util;
|
||||
|
||||
fn mark_ident(id : ast::Ident, m : ast::Mrk) -> ast::Ident {
|
||||
ast::Ident{name:id.name,ctxt:ast_util::new_mark(m,id.ctxt)}
|
||||
}
|
||||
|
||||
#[test] fn mtwt_token_eq_test() {
|
||||
assert!(mtwt_token_eq(>,>));
|
||||
let a = str_to_ident("bac");
|
||||
let a1 = mark_ident(a,92);
|
||||
assert!(mtwt_token_eq(&IDENT(a,true),&IDENT(a1,false)));
|
||||
}
|
||||
|
||||
|
||||
#[test] fn str_ptr_eq_tests(){
|
||||
let a = @"abc";
|
||||
let b = @"abc";
|
||||
let c = a;
|
||||
assert!(str_ptr_eq(a,c));
|
||||
assert!(!str_ptr_eq(a,b));
|
||||
}
|
||||
|
||||
#[test] fn fresh_name_pointer_sharing() {
|
||||
let ghi = str_to_ident("ghi");
|
||||
assert_eq!(ident_to_str(&ghi),@"ghi");
|
||||
assert!(str_ptr_eq(ident_to_str(&ghi),ident_to_str(&ghi)))
|
||||
let fresh = ast::Ident::new(fresh_name(&ghi));
|
||||
assert_eq!(ident_to_str(&fresh),@"ghi");
|
||||
assert!(str_ptr_eq(ident_to_str(&ghi),ident_to_str(&fresh)));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -619,7 +619,8 @@ pub fn print_item(s: @ps, item: &ast::item) {
|
|||
}
|
||||
bclose(s, item.span);
|
||||
}
|
||||
ast::item_mac(codemap::Spanned { node: ast::mac_invoc_tt(ref pth, ref tts),
|
||||
// I think it's reasonable to hide the context here:
|
||||
ast::item_mac(codemap::Spanned { node: ast::mac_invoc_tt(ref pth, ref tts, _),
|
||||
_}) => {
|
||||
print_visibility(s, item.vis);
|
||||
print_path(s, pth, false);
|
||||
|
|
@ -1021,7 +1022,8 @@ pub fn print_if(s: @ps, test: &ast::Expr, blk: &ast::Block,
|
|||
|
||||
pub fn print_mac(s: @ps, m: &ast::mac) {
|
||||
match m.node {
|
||||
ast::mac_invoc_tt(ref pth, ref tts) => {
|
||||
// I think it's reasonable to hide the ctxt here:
|
||||
ast::mac_invoc_tt(ref pth, ref tts, _) => {
|
||||
print_path(s, pth, false);
|
||||
word(s.s, "!");
|
||||
popen(s);
|
||||
|
|
@ -1924,8 +1926,8 @@ pub fn print_arg(s: @ps, input: &ast::arg) {
|
|||
match input.pat.node {
|
||||
ast::PatIdent(_, ref path, _) if
|
||||
path.segments.len() == 1 &&
|
||||
path.segments[0].identifier ==
|
||||
parse::token::special_idents::invalid => {
|
||||
path.segments[0].identifier.name ==
|
||||
parse::token::special_idents::invalid.name => {
|
||||
// Do nothing.
|
||||
}
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -117,6 +117,23 @@ impl StrInterner {
|
|||
new_idx
|
||||
}
|
||||
|
||||
// I want these gensyms to share name pointers
|
||||
// with existing entries. This would be automatic,
|
||||
// except that the existing gensym creates its
|
||||
// own managed ptr using to_managed. I think that
|
||||
// adding this utility function is the most
|
||||
// lightweight way to get what I want, though not
|
||||
// necessarily the cleanest.
|
||||
|
||||
// create a gensym with the same name as an existing
|
||||
// entry.
|
||||
pub fn gensym_copy(&self, idx : uint) -> uint {
|
||||
let new_idx = self.len();
|
||||
// leave out of map to avoid colliding
|
||||
self.vect.push(self.vect[idx]);
|
||||
new_idx
|
||||
}
|
||||
|
||||
// this isn't "pure" in the traditional sense, because it can go from
|
||||
// failing to returning a value as items are interned. But for typestate,
|
||||
// where we first check a pred and then rely on it, ceasing to fail is ok.
|
||||
|
|
@ -144,23 +161,23 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn i2 () {
|
||||
fn interner_tests () {
|
||||
let i : Interner<@str> = Interner::new();
|
||||
// first one is zero:
|
||||
assert_eq!(i.intern (@"dog"), 0);
|
||||
assert_eq!(i.intern(@"dog"), 0);
|
||||
// re-use gets the same entry:
|
||||
assert_eq!(i.intern (@"dog"), 0);
|
||||
assert_eq!(i.intern(@"dog"), 0);
|
||||
// different string gets a different #:
|
||||
assert_eq!(i.intern (@"cat"), 1);
|
||||
assert_eq!(i.intern (@"cat"), 1);
|
||||
assert_eq!(i.intern(@"cat"), 1);
|
||||
assert_eq!(i.intern(@"cat"), 1);
|
||||
// dog is still at zero
|
||||
assert_eq!(i.intern (@"dog"), 0);
|
||||
assert_eq!(i.intern(@"dog"), 0);
|
||||
// gensym gets 3
|
||||
assert_eq!(i.gensym (@"zebra" ), 2);
|
||||
assert_eq!(i.gensym(@"zebra" ), 2);
|
||||
// gensym of same string gets new number :
|
||||
assert_eq!(i.gensym (@"zebra" ), 3);
|
||||
// gensym of *existing* string gets new number:
|
||||
assert_eq!(i.gensym (@"dog"), 4);
|
||||
assert_eq!(i.gensym(@"dog"), 4);
|
||||
assert_eq!(i.get(0), @"dog");
|
||||
assert_eq!(i.get(1), @"cat");
|
||||
assert_eq!(i.get(2), @"zebra");
|
||||
|
|
@ -176,4 +193,34 @@ mod tests {
|
|||
assert_eq!(i.get(2), @"Carol");
|
||||
assert_eq!(i.intern(@"Bob"), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_interner_tests() {
|
||||
let i : StrInterner = StrInterner::new();
|
||||
// first one is zero:
|
||||
assert_eq!(i.intern("dog"), 0);
|
||||
// re-use gets the same entry:
|
||||
assert_eq!(i.intern ("dog"), 0);
|
||||
// different string gets a different #:
|
||||
assert_eq!(i.intern("cat"), 1);
|
||||
assert_eq!(i.intern("cat"), 1);
|
||||
// dog is still at zero
|
||||
assert_eq!(i.intern("dog"), 0);
|
||||
// gensym gets 3
|
||||
assert_eq!(i.gensym("zebra"), 2);
|
||||
// gensym of same string gets new number :
|
||||
assert_eq!(i.gensym("zebra"), 3);
|
||||
// gensym of *existing* string gets new number:
|
||||
assert_eq!(i.gensym("dog"), 4);
|
||||
// gensym tests again with gensym_copy:
|
||||
assert_eq!(i.gensym_copy(2), 5);
|
||||
assert_eq!(i.get(5), @"zebra");
|
||||
assert_eq!(i.gensym_copy(2), 6);
|
||||
assert_eq!(i.get(6), @"zebra");
|
||||
assert_eq!(i.get(0), @"dog");
|
||||
assert_eq!(i.get(1), @"cat");
|
||||
assert_eq!(i.get(2), @"zebra");
|
||||
assert_eq!(i.get(3), @"zebra");
|
||||
assert_eq!(i.get(4), @"dog");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,12 @@ pub fn string_to_tts_and_sess (source_str : @str) -> (~[ast::token_tree],@mut Pa
|
|||
(filemap_to_tts(ps,string_to_filemap(ps,source_str,@"bogofile")),ps)
|
||||
}
|
||||
|
||||
// map a string to tts, using a made-up filename:
|
||||
pub fn string_to_tts(source_str : @str) -> ~[ast::token_tree] {
|
||||
let (tts,_) = string_to_tts_and_sess(source_str);
|
||||
tts
|
||||
}
|
||||
|
||||
pub fn string_to_parser_and_sess(source_str: @str) -> (Parser,@mut ParseSess) {
|
||||
let ps = new_parse_sess(None);
|
||||
(new_parser_from_source_str(ps,~[],@"bogofile",source_str),ps)
|
||||
|
|
@ -40,12 +46,19 @@ fn with_error_checking_parse<T>(s: @str, f: &fn(&mut Parser) -> T) -> T {
|
|||
x
|
||||
}
|
||||
|
||||
// parse a string, return a crate.
|
||||
pub fn string_to_crate (source_str : @str) -> @ast::Crate {
|
||||
do with_error_checking_parse(source_str) |p| {
|
||||
p.parse_crate_mod()
|
||||
}
|
||||
}
|
||||
|
||||
// parse a string, return a crate and the ParseSess
|
||||
pub fn string_to_crate_and_sess (source_str : @str) -> (@ast::Crate,@mut ParseSess) {
|
||||
let (p,ps) = string_to_parser_and_sess(source_str);
|
||||
(p.parse_crate_mod(),ps)
|
||||
}
|
||||
|
||||
// parse a string, return an expr
|
||||
pub fn string_to_expr (source_str : @str) -> @ast::Expr {
|
||||
do with_error_checking_parse(source_str) |p| {
|
||||
|
|
@ -60,14 +73,6 @@ pub fn string_to_item (source_str : @str) -> Option<@ast::item> {
|
|||
}
|
||||
}
|
||||
|
||||
// parse a string, return an item and the ParseSess
|
||||
pub fn string_to_item_and_sess (source_str : @str) -> (Option<@ast::item>,@mut ParseSess) {
|
||||
let (p,ps) = string_to_parser_and_sess(source_str);
|
||||
let io = p.parse_item(~[]);
|
||||
p.abort_if_errors();
|
||||
(io,ps)
|
||||
}
|
||||
|
||||
// parse a string, return a stmt
|
||||
pub fn string_to_stmt(source_str : @str) -> @ast::Stmt {
|
||||
do with_error_checking_parse(source_str) |p| {
|
||||
|
|
|
|||
|
|
@ -22,20 +22,20 @@ use std::util;
|
|||
use std::vec;
|
||||
|
||||
macro_rules! bench (
|
||||
($id:ident) => (maybe_run_test(argv, stringify!($id).to_owned(), $id))
|
||||
($argv:expr, $id:ident) => (maybe_run_test($argv, stringify!($id).to_owned(), $id))
|
||||
)
|
||||
|
||||
fn main() {
|
||||
let argv = os::args();
|
||||
let _tests = argv.slice(1, argv.len());
|
||||
|
||||
bench!(shift_push);
|
||||
bench!(read_line);
|
||||
bench!(vec_plus);
|
||||
bench!(vec_append);
|
||||
bench!(vec_push_all);
|
||||
bench!(is_utf8_ascii);
|
||||
bench!(is_utf8_multibyte);
|
||||
bench!(argv, shift_push);
|
||||
bench!(argv, read_line);
|
||||
bench!(argv, vec_plus);
|
||||
bench!(argv, vec_append);
|
||||
bench!(argv, vec_push_all);
|
||||
bench!(argv, is_utf8_ascii);
|
||||
bench!(argv, is_utf8_multibyte);
|
||||
}
|
||||
|
||||
fn maybe_run_test(argv: &[~str], name: ~str, test: &fn()) {
|
||||
|
|
|
|||
21
src/test/run-pass/hygiene-dodging-1.rs
Normal file
21
src/test/run-pass/hygiene-dodging-1.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2012 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
mod x {
|
||||
pub fn g() -> uint {14}
|
||||
}
|
||||
|
||||
fn main(){
|
||||
// should *not* shadow the module x:
|
||||
let x = 9;
|
||||
// use it to avoid warnings:
|
||||
x+3;
|
||||
assert_eq!(x::g(),14);
|
||||
}
|
||||
16
src/test/run-pass/let-var-hygiene.rs
Normal file
16
src/test/run-pass/let-var-hygiene.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2012 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// shouldn't affect evaluation of $ex:
|
||||
macro_rules! bad_macro (($ex:expr) => ({let _x = 9; $ex}))
|
||||
fn main() {
|
||||
let _x = 8;
|
||||
assert_eq!(bad_macro!(_x),8)
|
||||
}
|
||||
|
|
@ -8,6 +8,9 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// xfail-test
|
||||
// this now fails (correctly, I claim) because hygiene prevents
|
||||
// the assembled identifier from being a reference to the binding.
|
||||
|
||||
pub fn main() {
|
||||
let asdf_fdsa = ~"<.<";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue