diff --git a/src/comp/front/lexer.rs b/src/comp/front/lexer.rs index 3659af1c655e2..cbc8314bd7d22 100644 --- a/src/comp/front/lexer.rs +++ b/src/comp/front/lexer.rs @@ -611,7 +611,6 @@ fn next_token(reader rdr) -> token.token { alt (c) { // One-byte tokens. - case (':') { rdr.bump(); ret token.COLON; } case ('?') { rdr.bump(); ret token.QUES; } case (';') { rdr.bump(); ret token.SEMI; } case (',') { rdr.bump(); ret token.COMMA; } @@ -628,6 +627,16 @@ fn next_token(reader rdr) -> token.token { // Multi-byte tokens. + case (':') { + rdr.bump(); + if (rdr.curr() == ':') { + rdr.bump(); + ret token.COLONCOLON; + } else { + ret token.COLON; + } + } + case ('=') { rdr.bump(); if (rdr.curr() == '=') { diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index fdd41cf0ff702..ebb7ff1c5972c 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1007,6 +1007,29 @@ fn parse_dot_or_call_expr(parser p) -> @ast.expr { } } + case (token.COLONCOLON) { + // Pseudomethod calls: e::pm() is sugar for pm(e). + p.bump(); + + auto pm = parse_bottom_expr(p); + + // Parse the rest of the arguments. + auto pf = parse_expr; + auto lo = p.get_lo_pos(); + auto hi = p.get_hi_pos(); + expect(p, token.LPAREN); + auto result = parse_seq_to_end[@ast.expr](token.RPAREN, + some(token.COMMA), + pf, hi, p); + + // Get all the arguments together. + let vec[@ast.expr] args = vec(e) + result; + auto es = @spanned(lo, hi, args); + + auto e_ = ast.expr_call(pm, es.node, ast.ann_none); + e = @spanned(lo, hi, e_); + } + case (token.DOT) { p.bump(); alt (p.peek()) { diff --git a/src/comp/front/token.rs b/src/comp/front/token.rs index f367bcc6835a2..6101291c5162a 100644 --- a/src/comp/front/token.rs +++ b/src/comp/front/token.rs @@ -45,6 +45,7 @@ tag token { COMMA; SEMI; COLON; + COLONCOLON; QUES; RARROW; SEND; @@ -214,6 +215,7 @@ fn to_str(token t) -> str { case (COMMA) { ret ","; } case (SEMI) { ret ";"; } case (COLON) { ret ":"; } + case (COLONCOLON) { ret "::"; } case (QUES) { ret "?"; } case (RARROW) { ret "->"; } case (SEND) { ret "<|"; } diff --git a/src/test/run-pass/pseudomethod.rs b/src/test/run-pass/pseudomethod.rs new file mode 100644 index 0000000000000..33a79ace87fb4 --- /dev/null +++ b/src/test/run-pass/pseudomethod.rs @@ -0,0 +1,55 @@ +// xfail-boot +use std; +import std._vec.len; +fn main() { + + // Pseudomethod using a library function + let uint a = len[int](vec(1, 2, 3, 4)); + log a; + let uint b = vec(1, 2, 3, 4)::len[int](); + log b; + check (a == b); + + let vec[int] v = vec(1, 2, 3, 4); + let uint c = len[int](v); + log c; + let uint d = v::len[int](); + log d; + check (c == d); + + // User-defined pseudomethods + fn exclaim(str s) -> str { ret s + "!"; } + let str e = exclaim("hello"); + log e; + let str f = "hello"::exclaim(); + log f; + check (e == f); + + fn plus(int a, int b) -> int { ret a + b; } + let int m = 2 * 3::plus(4) + 5; + let int n = 2 * (3 + 4) + 5; + log m; + log n; + check (m == n); + + // Multi-argument pseudomethod + fn bang_huh(str s1, str s2) -> str { + ret s1 + "!" + s2 + "?"; + } + let str g = bang_huh("hello", "world"); + log g; + let str h = "hello"::bang_huh("world"); + log h; + check (g == h); + + // Stacking pseudomethods + let str i = "hello"::exclaim()::bang_huh("world"); + log i; + let str j = bang_huh(exclaim("hello"), "world"); + log j; + check (i == j); + + let int k = (vec("foo", "bar", "baz")::len[str]() as int)::plus(50); + log k; + check (k == 53); +}