about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorTim Chevalier <chevalier@alum.wellesley.edu>2012-10-08 09:00:23 -0700
committerTim Chevalier <chevalier@alum.wellesley.edu>2012-10-08 09:00:23 -0700
commit7bdab1e4a45bf734e4b25a2d58f4ee21ee5c9fdc (patch)
treeb24c818211cffeb1f2b8cc7bf7bc31fe3eecfdc9 /src/libsyntax
parent79603f573e504163db7b5c2afa0917c27e3f98ed (diff)
downloadrust-7bdab1e4a45bf734e4b25a2d58f4ee21ee5c9fdc.tar.gz
rust-7bdab1e4a45bf734e4b25a2d58f4ee21ee5c9fdc.zip
Revert "remove ctor from ast"
This reverts commit ed3689d57c988e1dd477930d957c4308c37d1a64.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs9
-rw-r--r--src/libsyntax/ast_map.rs20
-rw-r--r--src/libsyntax/ast_util.rs13
-rw-r--r--src/libsyntax/fold.rs19
-rw-r--r--src/libsyntax/parse/parser.rs65
-rw-r--r--src/libsyntax/print/pprust.rs12
-rw-r--r--src/libsyntax/visit.rs33
7 files changed, 148 insertions, 23 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index ced64daa8d6..1c279f81cc3 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -135,7 +135,7 @@ enum def {
               @def,     // closed over def
               node_id,  // expr node that creates the closure
               node_id), // id for the block/body of the closure expr
-    def_class(def_id),
+    def_class(def_id, bool /* has constructor */),
     def_typaram_binder(node_id), /* class, impl or trait that has ty params */
     def_region(node_id),
     def_label(node_id)
@@ -235,9 +235,9 @@ impl def : cmp::Eq {
                     _ => false
                 }
             }
-            def_class(e0a) => {
+            def_class(e0a, e1a) => {
                 match (*other) {
-                    def_class(e0b) => e0a == e0b,
+                    def_class(e0b, e1b) => e0a == e0b && e1a == e1b,
                     _ => false
                 }
             }
@@ -1462,6 +1462,8 @@ type struct_def = {
     fields: ~[@struct_field], /* fields */
     methods: ~[@method],    /* methods */
     /* (not including ctor or dtor) */
+    /* ctor is optional, and will soon go away */
+    ctor: Option<class_ctor>,
     /* dtor is optional */
     dtor: Option<class_dtor>
 };
@@ -1561,6 +1563,7 @@ enum inlined_item {
     ii_item(@item),
     ii_method(def_id /* impl id */, @method),
     ii_foreign(@foreign_item),
+    ii_ctor(class_ctor, ident, ~[ty_param], def_id /* parent id */),
     ii_dtor(class_dtor, ident, ~[ty_param], def_id /* parent id */)
 }
 
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index 8555ceed2db..d05c6eadaf6 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -71,6 +71,9 @@ enum ast_node {
     // order they are introduced.
     node_arg(arg, uint),
     node_local(uint),
+    // Constructor for a class
+    // def_id is parent id
+    node_ctor(ident, ~[ty_param], @class_ctor, def_id, @path),
     // Destructor for a class
     node_dtor(~[ty_param], @class_dtor, def_id, @path),
     node_block(blk),
@@ -129,7 +132,7 @@ fn map_decoded_item(diag: span_handler,
     // don't decode and instantiate the impl, but just the method, we have to
     // add it to the table now:
     match ii {
-      ii_item(*) | ii_dtor(*) => { /* fallthrough */ }
+      ii_item(*) | ii_ctor(*) | ii_dtor(*) => { /* fallthrough */ }
       ii_foreign(i) => {
         cx.map.insert(i.id, node_foreign_item(i, foreign_abi_rust_intrinsic,
                                              @path));
@@ -152,6 +155,18 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
         cx.local_id += 1u;
     }
     match fk {
+      visit::fk_ctor(nm, attrs, tps, self_id, parent_id) => {
+          let ct = @{node: {id: id,
+                            attrs: attrs,
+                            self_id: self_id,
+                            dec: /* FIXME (#2543) */ copy decl,
+                            body: /* FIXME (#2543) */ copy body},
+                    span: sp};
+          cx.map.insert(id, node_ctor(/* FIXME (#2543) */ copy nm,
+                                      /* FIXME (#2543) */ copy tps,
+                                      ct, parent_id,
+                                      @/* FIXME (#2543) */ copy cx.path));
+      }
       visit::fk_dtor(tps, attrs, self_id, parent_id) => {
           let dt = @{node: {id: id, attrs: attrs, self_id: self_id,
                      body: /* FIXME (#2543) */ copy body}, span: sp};
@@ -367,6 +382,9 @@ fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str {
       Some(node_local(_)) => { // add more info here
         fmt!("local (id=%?)", id)
       }
+      Some(node_ctor(*)) => { // add more info here
+        fmt!("node_ctor (id=%?)", id)
+      }
       Some(node_dtor(*)) => { // add more info here
         fmt!("node_dtor (id=%?)", id)
       }
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 9e44c42a702..47cbdb7ac6c 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -57,7 +57,7 @@ pure fn def_id_of_def(d: def) -> def_id {
       def_fn(id, _) | def_static_method(id, _) | def_mod(id) |
       def_foreign_mod(id) | def_const(id) |
       def_variant(_, id) | def_ty(id) | def_ty_param(id, _) |
-      def_use(id) | def_class(id) => {
+      def_use(id) | def_class(id, _) => {
         id
       }
       def_arg(id, _) | def_local(id, _) | def_self(id) |
@@ -339,6 +339,7 @@ impl inlined_item: inlined_item_utils {
           ii_item(i) => /* FIXME (#2543) */ copy i.ident,
           ii_foreign(i) => /* FIXME (#2543) */ copy i.ident,
           ii_method(_, m) => /* FIXME (#2543) */ copy m.ident,
+          ii_ctor(_, nm, _, _) => /* FIXME (#2543) */ copy nm,
           ii_dtor(_, nm, _, _) => /* FIXME (#2543) */ copy nm
         }
     }
@@ -348,6 +349,7 @@ impl inlined_item: inlined_item_utils {
           ii_item(i) => i.id,
           ii_foreign(i) => i.id,
           ii_method(_, m) => m.id,
+          ii_ctor(ctor, _, _, _) => ctor.node.id,
           ii_dtor(dtor, _, _, _) => dtor.node.id
         }
     }
@@ -357,6 +359,9 @@ impl inlined_item: inlined_item_utils {
           ii_item(i) => v.visit_item(i, e, v),
           ii_foreign(i) => v.visit_foreign_item(i, e, v),
           ii_method(_, m) => visit::visit_method_helper(m, e, v),
+          ii_ctor(ctor, nm, tps, parent_id) => {
+              visit::visit_class_ctor_helper(ctor, nm, tps, parent_id, e, v);
+          }
           ii_dtor(dtor, _, tps, parent_id) => {
               visit::visit_class_dtor_helper(dtor, tps, parent_id, e, v);
           }
@@ -490,6 +495,12 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
             vfn(id);
 
             match fk {
+                visit::fk_ctor(_, _, tps, self_id, parent_id) => {
+                    for vec::each(tps) |tp| { vfn(tp.id); }
+                    vfn(id);
+                    vfn(self_id);
+                    vfn(parent_id.node);
+                }
                 visit::fk_dtor(tps, _, self_id, parent_id) => {
                     for vec::each(tps) |tp| { vfn(tp.id); }
                     vfn(id);
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 68d9cd80430..088df01985e 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -271,6 +271,23 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
 
 fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold)
                 -> @ast::struct_def {
+    let resulting_optional_constructor;
+    match struct_def.ctor {
+        None => {
+            resulting_optional_constructor = None;
+        }
+        Some(constructor) => {
+            resulting_optional_constructor = Some({
+                node: {
+                    body: fld.fold_block(constructor.node.body),
+                    dec: fold_fn_decl(constructor.node.dec, fld),
+                    id: fld.new_id(constructor.node.id),
+                    .. constructor.node
+                },
+                .. constructor
+            });
+        }
+    }
     let dtor = do option::map(&struct_def.dtor) |dtor| {
         let dtor_body = fld.fold_block(dtor.node.body);
         let dtor_id   = fld.new_id(dtor.node.id);
@@ -281,6 +298,7 @@ fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold)
         traits: vec::map(struct_def.traits, |p| fold_trait_ref(*p, fld)),
         fields: vec::map(struct_def.fields, |f| fold_struct_field(*f, fld)),
         methods: vec::map(struct_def.methods, |m| fld.fold_method(*m)),
+        ctor: resulting_optional_constructor,
         dtor: dtor
     };
 }
@@ -567,6 +585,7 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ {
                                  |f| fld.fold_struct_field(*f)),
                 methods: vec::map(struct_def.methods,
                                   |m| fld.fold_method(*m)),
+                ctor: None,
                 dtor: dtor
             })
         }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index f2e17c0a7e6..22c25186c91 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -115,7 +115,8 @@ enum class_member {
   So that we can distinguish a class ctor or dtor
   from other class members
  */
-enum class_contents { dtor_decl(blk, ~[attribute], codemap::span),
+enum class_contents { ctor_decl(fn_decl, ~[attribute], blk, codemap::span),
+                      dtor_decl(blk, ~[attribute], codemap::span),
                       members(~[@class_member]) }
 
 type arg_or_capture_item = Either<arg, capture_item>;
@@ -2682,13 +2683,30 @@ impl parser {
 
         let mut fields: ~[@struct_field];
         let mut methods: ~[@method] = ~[];
+        let mut the_ctor: Option<(fn_decl, ~[attribute], blk, codemap::span)>
+            = None;
         let mut the_dtor: Option<(blk, ~[attribute], codemap::span)> = None;
+        let ctor_id = self.get_id();
 
         if self.eat(token::LBRACE) {
             // It's a record-like struct.
             fields = ~[];
             while self.token != token::RBRACE {
                 match self.parse_class_item() {
+                  ctor_decl(a_fn_decl, attrs, blk, s) => {
+                      match the_ctor {
+                        Some((_, _, _, s_first)) => {
+                          self.span_note(s, #fmt("Duplicate constructor \
+                                     declaration for class %s",
+                                     *self.interner.get(class_name)));
+                           self.span_fatal(copy s_first, ~"First constructor \
+                                                          declared here");
+                        }
+                        None    => {
+                          the_ctor = Some((a_fn_decl, attrs, blk, s));
+                        }
+                      }
+                  }
                   dtor_decl(blk, attrs, s) => {
                       match the_dtor {
                         Some((_, _, s_first)) => {
@@ -2746,14 +2764,36 @@ impl parser {
                     self_id: self.get_id(),
                     body: d_body},
              span: d_s}};
-        (class_name,
-         item_class(@{
-             traits: traits,
-             fields: move fields,
-             methods: move methods,
-             dtor: actual_dtor
-         }, ty_params),
-         None)
+        match the_ctor {
+          Some((ct_d, ct_attrs, ct_b, ct_s)) => {
+            (class_name,
+             item_class(@{
+                traits: traits,
+                fields: move fields,
+                methods: move methods,
+                ctor: Some({
+                 node: {id: ctor_id,
+                        attrs: ct_attrs,
+                        self_id: self.get_id(),
+                        dec: ct_d,
+                        body: ct_b},
+                 span: ct_s}),
+                dtor: actual_dtor
+             }, ty_params),
+             None)
+          }
+          None => {
+            (class_name,
+             item_class(@{
+                    traits: traits,
+                    fields: move fields,
+                    methods: move methods,
+                    ctor: None,
+                    dtor: actual_dtor
+             }, ty_params),
+             None)
+          }
+        }
     }
 
     fn token_is_pound_or_doc_comment(++tok: token::token) -> bool {
@@ -3057,6 +3097,12 @@ impl parser {
         let mut methods: ~[@method] = ~[];
         while self.token != token::RBRACE {
             match self.parse_class_item() {
+                ctor_decl(*) => {
+                    self.span_fatal(copy self.span,
+                                    ~"deprecated explicit \
+                                      constructors are not allowed \
+                                      here");
+                }
                 dtor_decl(blk, attrs, s) => {
                     match the_dtor {
                         Some((_, _, s_first)) => {
@@ -3097,6 +3143,7 @@ impl parser {
             traits: ~[],
             fields: move fields,
             methods: move methods,
+            ctor: None,
             dtor: actual_dtor
         };
     }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index b98014f421b..bff356e5cb7 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -653,6 +653,18 @@ fn print_struct(s: ps, struct_def: @ast::struct_def, tps: ~[ast::ty_param],
     }
     bopen(s);
     hardbreak_if_not_bol(s);
+    do struct_def.ctor.iter |ctor| {
+      maybe_print_comment(s, ctor.span.lo);
+      print_outer_attributes(s, ctor.node.attrs);
+      // Doesn't call head because there shouldn't be a space after new.
+      cbox(s, indent_unit);
+      ibox(s, 4);
+      word(s.s, ~"new(");
+      print_fn_args(s, ctor.node.dec, ~[], None);
+      word(s.s, ~")");
+      space(s.s);
+      print_block(s, ctor.node.body);
+    }
     do struct_def.dtor.iter |dtor| {
       hardbreak_if_not_bol(s);
       maybe_print_comment(s, dtor.span.lo);
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 50fbd21f7b8..e6fd65eb458 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -17,6 +17,8 @@ enum fn_kind {
     fk_method(ident, ~[ty_param], @method),
     fk_anon(proto, capture_clause),  //< an anonymous function like fn@(...)
     fk_fn_block(capture_clause),     //< a block {||...}
+    fk_ctor(ident, ~[attribute], ~[ty_param], node_id /* self id */,
+            def_id /* parent class id */), // class constructor
     fk_dtor(~[ty_param], ~[attribute], node_id /* self id */,
             def_id /* parent class id */) // class destructor
 
@@ -24,9 +26,8 @@ enum fn_kind {
 
 fn name_of_fn(fk: fn_kind) -> ident {
     match fk {
-      fk_item_fn(name, _, _) | fk_method(name, _, _) => {
-          /* FIXME (#2543) */ copy name
-      }
+      fk_item_fn(name, _, _) | fk_method(name, _, _)
+          | fk_ctor(name, _, _, _, _) =>  /* FIXME (#2543) */ copy name,
       fk_anon(*) | fk_fn_block(*) => parse::token::special_idents::anon,
       fk_dtor(*)                  => parse::token::special_idents::dtor
     }
@@ -34,11 +35,11 @@ fn name_of_fn(fk: fn_kind) -> ident {
 
 fn tps_of_fn(fk: fn_kind) -> ~[ty_param] {
     match fk {
-        fk_item_fn(_, tps, _) | fk_method(_, tps, _) |
-        fk_dtor(tps, _, _, _) => {
-            /* FIXME (#2543) */ copy tps
-        }
-        fk_anon(*) | fk_fn_block(*) => ~[]
+      fk_item_fn(_, tps, _) | fk_method(_, tps, _)
+          | fk_ctor(_, _, tps, _, _) | fk_dtor(tps, _, _, _) => {
+          /* FIXME (#2543) */ copy tps
+      }
+      fk_anon(*) | fk_fn_block(*) => ~[]
     }
 }
 
@@ -290,6 +291,17 @@ fn visit_method_helper<E>(m: @method, e: E, v: vt<E>) {
                m.decl, m.body, m.span, m.id, e, v);
 }
 
+// Similar logic to the comment on visit_method_helper - Tim
+fn visit_class_ctor_helper<E>(ctor: class_ctor, nm: ident, tps: ~[ty_param],
+                              parent_id: def_id, e: E, v: vt<E>) {
+    v.visit_fn(fk_ctor(/* FIXME (#2543) */ copy nm,
+                       ctor.node.attrs,
+                       /* FIXME (#2543) */ copy tps,
+                       ctor.node.self_id, parent_id),
+        ctor.node.dec, ctor.node.body, ctor.span, ctor.node.id, e, v)
+
+}
+
 fn visit_class_dtor_helper<E>(dtor: class_dtor, tps: ~[ty_param],
                               parent_id: def_id, e: E, v: vt<E>) {
     v.visit_fn(fk_dtor(/* FIXME (#2543) */ copy tps, dtor.node.attrs,
@@ -318,7 +330,7 @@ fn visit_trait_method<E>(m: trait_method, e: E, v: vt<E>) {
     }
 }
 
-fn visit_struct_def<E>(sd: @struct_def, _nm: ast::ident, tps: ~[ty_param],
+fn visit_struct_def<E>(sd: @struct_def, nm: ast::ident, tps: ~[ty_param],
                        id: node_id, e: E, v: vt<E>) {
     for sd.fields.each |f| {
         v.visit_struct_field(*f, e, v);
@@ -329,6 +341,9 @@ fn visit_struct_def<E>(sd: @struct_def, _nm: ast::ident, tps: ~[ty_param],
     for sd.traits.each |p| {
         visit_path(p.path, e, v);
     }
+    do option::iter(&sd.ctor) |ctor| {
+      visit_class_ctor_helper(*ctor, nm, tps, ast_util::local_def(id), e, v);
+    };
     do option::iter(&sd.dtor) |dtor| {
       visit_class_dtor_helper(*dtor, tps, ast_util::local_def(id), e, v)
     };