about summary refs log tree commit diff
path: root/src/comp/front
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2011-05-16 19:04:45 -0700
committerGraydon Hoare <graydon@mozilla.com>2011-05-16 19:04:45 -0700
commita2e2e781035a7e99cd4b8320caeeb8566590d21e (patch)
tree0987ea09d9297789023c0b982a569f5107ba92ee /src/comp/front
parentfbbc1a77d242fafa1393127defa7ffec0bcb9e54 (diff)
parent41b7af9652038712acf223bf9a309a3cc9be6281 (diff)
downloadrust-a2e2e781035a7e99cd4b8320caeeb8566590d21e.tar.gz
rust-a2e2e781035a7e99cd4b8320caeeb8566590d21e.zip
Merge remote branch 'origin/master' into HEAD
Conflicts:
	src/comp/middle/trans.rs
Diffstat (limited to 'src/comp/front')
-rw-r--r--src/comp/front/ast.rs18
-rw-r--r--src/comp/front/parser.rs42
2 files changed, 48 insertions, 12 deletions
diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs
index d795d6c2363..5dfc2d8ddfa 100644
--- a/src/comp/front/ast.rs
+++ b/src/comp/front/ast.rs
@@ -1,4 +1,3 @@
-
 import std::map::hashmap;
 import std::option;
 import std::_str;
@@ -7,7 +6,7 @@ import util::common::span;
 import util::common::spanned;
 import util::common::ty_mach;
 import util::common::filename;
-import util::typestate_ann::ts_ann;
+import middle::tstate::ann::ts_ann;
 
 type ident = str;
 
@@ -323,6 +322,12 @@ type ty_method = rec(proto proto, ident ident,
 type ty = spanned[ty_];
 tag ty_ {
     ty_nil;
+    ty_bot; /* return type of ! functions and type of
+             ret/fail/break/cont. there is no syntax
+             for this type. */
+    /* bot represents the value of functions that don't return a value
+       locally to their context. in contrast, things like log that do
+       return, but don't return a meaningful value, have result type nil. */
     ty_bool;
     ty_int;
     ty_uint;
@@ -354,12 +359,19 @@ type constr = spanned[constr_];
 type arg = rec(mode mode, @ty ty, ident ident, def_id id);
 type fn_decl = rec(vec[arg] inputs,
                    @ty output,
-                   purity purity);
+                   purity purity,
+                   controlflow cf);
 tag purity {
     pure_fn;   // declared with "pred"
     impure_fn; // declared with "fn"
 }
 
+tag controlflow {
+    noreturn; // functions with return type _|_ that always
+              // raise an error or exit (i.e. never return to the caller)
+    return;  // everything else
+}
+
 type _fn = rec(fn_decl decl,
                proto proto,
                block body);
diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs
index 3fa25857d3f..104c2c6f71a 100644
--- a/src/comp/front/parser.rs
+++ b/src/comp/front/parser.rs
@@ -23,6 +23,11 @@ tag file_type {
     SOURCE_FILE;
 }
 
+tag ty_or_bang {
+    a_ty(@ast::ty);
+    a_bang;
+}
+
 state type parser =
     state obj {
           fn peek() -> token::token;
@@ -448,6 +453,13 @@ fn parse_ty_constrs(@ast::ty t, parser p) -> @ast::ty {
    ret t;
 }
 
+fn parse_ty_or_bang(parser p) -> ty_or_bang {
+    alt (p.peek()) {
+        case (token::NOT) { p.bump(); ret a_bang; }
+        case (_)         { ret a_ty(parse_ty(p)); }
+    }
+}
+
 fn parse_ty(parser p) -> @ast::ty {
     auto lo = p.get_lo_pos();
     auto hi = lo;
@@ -1713,7 +1725,7 @@ fn parse_fn_decl(parser p, ast::purity purity) -> ast::fn_decl {
          some(token::COMMA),
          pf, p);
 
-    let @ast::ty output;
+    let ty_or_bang res;
 
     // FIXME: dropping constrs on the floor at the moment.
     // pick them up when they're used by typestate pass.
@@ -1721,12 +1733,23 @@ fn parse_fn_decl(parser p, ast::purity purity) -> ast::fn_decl {
 
     if (p.peek() == token::RARROW) {
         p.bump();
-        output = parse_ty(p);
+        res = parse_ty_or_bang(p);
     } else {
-        output = @spanned(inputs.span.lo, inputs.span.hi, ast::ty_nil);
+        res = a_ty(@spanned(inputs.span.lo, inputs.span.hi, ast::ty_nil));
+    }
+
+    alt (res) {
+        case (a_ty(?t)) {
+            ret rec(inputs=inputs.node, output=t,
+              purity=purity, cf=ast::return);
+        }
+        case (a_bang) {
+            ret rec(inputs=inputs.node,
+                    output=@spanned(p.get_lo_pos(),
+                                    p.get_hi_pos(), ast::ty_bot),
+                    purity=purity, cf=ast::noreturn);
+        }
     }
-    // FIXME
-    ret rec(inputs=inputs.node, output=output, purity=purity);
 }
 
 fn parse_fn(parser p, ast::proto proto, ast::purity purity) -> ast::_fn {
@@ -1778,11 +1801,12 @@ fn parse_dtor(parser p) -> @ast::method {
     let vec[ast::arg] inputs = [];
     let @ast::ty output = @spanned(lo, lo, ast::ty_nil);
     let ast::fn_decl d = rec(inputs=inputs,
-                            output=output,
-                            purity=ast::impure_fn);
+                             output=output,
+                             purity=ast::impure_fn,
+                             cf=ast::return); 
     let ast::_fn f = rec(decl = d,
-                        proto = ast::proto_fn,
-                        body = b);
+                         proto = ast::proto_fn,
+                         body = b);
     let ast::method_ m = rec(ident="drop",
                             meth=f,
                             id=p.next_def_id(),