From 7c2979e26f23739b62fcda7500d4c5eac092c42c Mon Sep 17 00:00:00 2001 From: Lindsey Kuper Date: Fri, 6 May 2011 17:08:41 -0700 Subject: [PATCH] Starting on support for anonymous objects. Just syntax so far. --- src/comp/front/ast.rs | 20 +++++++++++ src/comp/front/parser.rs | 50 ++++++++++++++++++++++++++ src/test/run-pass/method-overriding.rs | 26 ++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 src/test/run-pass/method-overriding.rs diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 5e5185bf7ee..51977b5f7fb 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -296,6 +296,7 @@ tag expr_ { expr_check(@expr, ann); expr_port(ann); expr_chan(@expr, ann); + expr_anon_obj(anon_obj, vec[ty_param], obj_def_ids, ann); } type lit = spanned[lit_]; @@ -371,6 +372,25 @@ type _obj = rec(vec[obj_field] fields, vec[@method] methods, option::t[@method] dtor); + +// Hmm. An anon_obj might extend an existing object, in which case it'll +// probably add fields and methods. +type anon_obj = rec(option.t[vec[obj_field]] fields, + vec[@method] methods, + option.t[ident] with_obj); + +tag mod_index_entry { + mie_view_item(@view_item); + mie_item(@item); + mie_tag_variant(@item /* tag item */, uint /* variant index */); +} + +tag native_mod_index_entry { + nmie_view_item(@view_item); + nmie_item(@native_item); +} + +type mod_index = hashmap[ident,mod_index_entry]; type _mod = rec(vec[@view_item] view_items, vec[@item] items); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 520090a52c7..f395ea16f3d 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -799,6 +799,56 @@ fn parse_bottom_expr(parser p) -> @ast::expr { } ex = ast::expr_rec(fields, base, p.get_ann()); + } + // Anonymous object + else if (eat_word(p, "obj")) { + + // FIXME: Can anonymous objects have ty params? + auto ty_params = parse_ty_params(p); + + // Only make people type () if they're actually adding new fields + let option.t[vec[ast.obj_field]] fields = none[vec[ast.obj_field]]; + if (p.peek() == token.LPAREN) { + auto pf = parse_obj_field; + hi = p.get_hi_pos(); + expect(p, token.LPAREN); + fields = some[vec[ast.obj_field]] + (parse_seq_to_end[ast.obj_field] + (token.RPAREN, + some(token.COMMA), + pf, hi, p)); + } + + let vec[@ast.method] meths = vec(); + let option.t[ast.ident] with_obj = none[ast.ident]; + + expect(p, token.LBRACE); + while (p.peek() != token.RBRACE) { + alt (p.peek()) { + case (token.WITH) { + with_obj = some[ast.ident](parse_ident(p)); + } + case (_) { + // fall through + } + } + } + hi = p.get_hi_pos(); + expect(p, token.RBRACE); + + // fields and methods may be *additional* or *overriding* fields + // and methods if there's a with_obj, or they may be the *only* + // fields and methods if there's no with_obj. + + // We don't need to pull ".node" out of fields because it's not a + // "spanned". + let ast.anon_obj ob = rec(fields=fields, + methods=meths, + with_obj=with_obj); + + auto odid = rec(ty=p.next_def_id(), ctor=p.next_def_id()); + + ex = ast.expr_anon_obj(ob, ty_params, odid, ast.ann_none); } else if (eat_word(p, "bind")) { auto e = parse_expr_res(p, RESTRICT_NO_CALL_EXPRS); fn parse_expr_opt(parser p) -> option::t[@ast::expr] { diff --git a/src/test/run-pass/method-overriding.rs b/src/test/run-pass/method-overriding.rs new file mode 100644 index 00000000000..bf68ddd1e42 --- /dev/null +++ b/src/test/run-pass/method-overriding.rs @@ -0,0 +1,26 @@ +// xfail-boot +// xfail-stage0 +use std; +import std._vec.len; +fn main() { + + obj a() { + fn foo() -> int { + ret 2; + } + fn bar() -> int { + ret self.foo(); + } + } + + auto my_a = a(); + + // Step 1 is to add support for this "with" syntax + auto my_b = obj { + fn baz() -> int { + ret self.foo(); + } + with my_a + }; + +}