about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2011-02-24 15:54:55 -0800
committerGraydon Hoare <graydon@mozilla.com>2011-02-24 15:55:10 -0800
commitb2a09562a6c0683ca528c866abc1ecc99b4bdcf0 (patch)
tree9af4389c4f5b857890575954e247c07fb6f5b536 /src/comp
parentdcd65fac199d3caac4b1019304ef5e1b480f31ff (diff)
downloadrust-b2a09562a6c0683ca528c866abc1ecc99b4bdcf0.tar.gz
rust-b2a09562a6c0683ca528c866abc1ecc99b4bdcf0.zip
Factor crate expr evaluator out of parser, expand to simple scalars and ops, if, alt.
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/front/ast.rs8
-rw-r--r--src/comp/front/eval.rs443
-rw-r--r--src/comp/front/parser.rs82
-rw-r--r--src/comp/rustc.rc2
4 files changed, 453 insertions, 82 deletions
diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs
index 088ef4ed920..f5c03bd7e74 100644
--- a/src/comp/front/ast.rs
+++ b/src/comp/front/ast.rs
@@ -46,7 +46,10 @@ type crate_ = rec(_mod module);
 
 tag crate_directive_ {
     cdir_expr(@expr);
-    cdir_const(@item);
+    // FIXME: cdir_let should be eliminated
+    // and redirected to the use of const stmt_decls inside
+    // crate directive blocks.
+    cdir_let(ident, @expr, vec[@crate_directive]);
     cdir_src_mod(ident, option.t[filename]);
     cdir_dir_mod(ident, option.t[filename], vec[@crate_directive]);
     cdir_view_item(@view_item);
@@ -137,6 +140,8 @@ type stmt = spanned[stmt_];
 tag stmt_ {
     stmt_decl(@decl);
     stmt_expr(@expr);
+    // These only exist in crate-level blocks.
+    stmt_crate_directive(@crate_directive);
 }
 
 type local = rec(option.t[@ty] ty,
@@ -175,7 +180,6 @@ tag expr_ {
     expr_do_while(block, @expr, ann);
     expr_alt(@expr, vec[arm], ann);
     expr_block(block, ann);
-    expr_crate_directive_block(vec[crate_directive_]);
     expr_assign(@expr /* TODO: @expr|is_lval */, @expr, ann);
     expr_assign_op(binop, @expr /* TODO: @expr|is_lval */, @expr, ann);
     expr_field(@expr, ident, ann);
diff --git a/src/comp/front/eval.rs b/src/comp/front/eval.rs
new file mode 100644
index 00000000000..7275e55711e
--- /dev/null
+++ b/src/comp/front/eval.rs
@@ -0,0 +1,443 @@
+import std._vec;
+import std._str;
+import std.option;
+import std.option.some;
+import std.option.none;
+import std.map.hashmap;
+
+import driver.session;
+import ast.ident;
+import front.parser.parser;
+import front.parser.spanned;
+import front.parser.new_parser;
+import front.parser.parse_mod_items;
+import util.common;
+import util.common.filename;
+import util.common.append;
+import util.common.span;
+import util.common.new_str_hash;
+
+
+// Simple dynamic-typed value type for eval_expr.
+tag val {
+    val_bool(bool);
+    val_int(int);
+    val_str(str);
+}
+
+type env = vec[tup(ident, val)];
+
+fn mk_env() -> env {
+    let env e = vec();
+    ret e;
+}
+
+fn val_is_bool(val v) -> bool {
+    alt (v) {
+        case (val_bool(_)) { ret true; }
+        case (_) { }
+    }
+    ret false;
+}
+
+fn val_is_int(val v) -> bool {
+    alt (v) {
+        case (val_bool(_)) { ret true; }
+        case (_) { }
+    }
+    ret false;
+}
+
+fn val_is_str(val v) -> bool {
+    alt (v) {
+        case (val_str(_)) { ret true; }
+        case (_) { }
+    }
+    ret false;
+}
+
+fn val_as_bool(val v) -> bool {
+    alt (v) {
+        case (val_bool(?b)) { ret b; }
+        case (_) { }
+    }
+    fail;
+}
+
+fn val_as_int(val v) -> int {
+    alt (v) {
+        case (val_int(?i)) { ret i; }
+        case (_) { }
+    }
+    fail;
+}
+
+fn val_as_str(val v) -> str {
+    alt (v) {
+        case (val_str(?s)) { ret s; }
+        case (_) { }
+    }
+    fail;
+}
+
+fn lookup(session.session sess, env e, span sp, ident i) -> val {
+    for (tup(ident, val) pair in e) {
+        if (_str.eq(i, pair._0)) {
+            ret pair._1;
+        }
+    }
+    sess.span_err(sp, "unknown variable: " + i);
+    fail;
+}
+
+fn eval_lit(session.session sess, env e, span sp, @ast.lit lit) -> val {
+    alt (lit.node) {
+        case (ast.lit_bool(?b)) { ret val_bool(b); }
+        case (ast.lit_int(?i)) { ret val_int(i); }
+        case (ast.lit_str(?s)) { ret val_str(s); }
+        case (_) {
+            sess.span_err(sp, "evaluating unsupported literal");
+        }
+    }
+    fail;
+}
+
+fn eval_expr(session.session sess, env e, @ast.expr x) -> val {
+    alt (x.node) {
+        case (ast.expr_path(?pth, _, _)) {
+            if (_vec.len[ident](pth.node.idents) == 1u &&
+                _vec.len[@ast.ty](pth.node.types) == 0u) {
+                ret lookup(sess, e, x.span, pth.node.idents.(0));
+            }
+            sess.span_err(x.span, "evaluating structured path-name");
+        }
+
+        case (ast.expr_lit(?lit, _)) {
+            ret eval_lit(sess, e, x.span, lit);
+        }
+
+        case (ast.expr_unary(?op, ?a, _)) {
+            auto av = eval_expr(sess, e, a);
+            alt (op) {
+                case (ast.not) {
+                    if (val_is_bool(av)) {
+                        ret val_bool(!val_as_bool(av));
+                    }
+                    sess.span_err(x.span, "bad types in '!' expression");
+                }
+                case (_) {
+                    sess.span_err(x.span, "evaluating unsupported unop");
+                }
+            }
+        }
+
+        case (ast.expr_binary(?op, ?a, ?b, _)) {
+            auto av = eval_expr(sess, e, a);
+            auto bv = eval_expr(sess, e, b);
+            alt (op) {
+                case (ast.add) {
+                    if (val_is_int(av) && val_is_int(bv)) {
+                        ret val_int(val_as_int(av) + val_as_int(bv));
+                    }
+                    if (val_is_str(av) && val_is_str(bv)) {
+                        ret val_str(val_as_str(av) + val_as_str(bv));
+                    }
+                    sess.span_err(x.span, "bad types in '+' expression");
+                }
+
+                case (ast.sub) {
+                    if (val_is_int(av) && val_is_int(bv)) {
+                        ret val_int(val_as_int(av) - val_as_int(bv));
+                    }
+                    sess.span_err(x.span, "bad types in '-' expression");
+                }
+
+                case (ast.mul) {
+                    if (val_is_int(av) && val_is_int(bv)) {
+                        ret val_int(val_as_int(av) * val_as_int(bv));
+                    }
+                    sess.span_err(x.span, "bad types in '*' expression");
+                }
+
+                case (ast.div) {
+                    if (val_is_int(av) && val_is_int(bv)) {
+                        ret val_int(val_as_int(av) / val_as_int(bv));
+                    }
+                    sess.span_err(x.span, "bad types in '/' expression");
+                }
+
+                case (ast.rem) {
+                    if (val_is_int(av) && val_is_int(bv)) {
+                        ret val_int(val_as_int(av) % val_as_int(bv));
+                    }
+                    sess.span_err(x.span, "bad types in '%' expression");
+                }
+
+                case (ast.and) {
+                    if (val_is_bool(av) && val_is_bool(bv)) {
+                        ret val_bool(val_as_bool(av) && val_as_bool(bv));
+                    }
+                    sess.span_err(x.span, "bad types in '&&' expression");
+                }
+
+                case (ast.or) {
+                    if (val_is_bool(av) && val_is_bool(bv)) {
+                        ret val_bool(val_as_bool(av) || val_as_bool(bv));
+                    }
+                    sess.span_err(x.span, "bad types in '||' expression");
+                }
+
+                case (ast.eq) {
+                    ret val_bool(val_eq(sess, x.span, av, bv));
+                }
+
+                case (ast.ne) {
+                    ret val_bool(! val_eq(sess, x.span, av, bv));
+                }
+
+                case (_) {
+                    sess.span_err(x.span, "evaluating unsupported binop");
+                }
+            }
+        }
+        case (_) {
+            sess.span_err(x.span, "evaluating unsupported expression");
+        }
+    }
+    fail;
+}
+
+fn val_eq(session.session sess, span sp, val av, val bv) -> bool {
+    if (val_is_bool(av) && val_is_bool(bv)) {
+        ret val_as_bool(av) == val_as_bool(bv);
+    }
+    if (val_is_int(av) && val_is_int(bv)) {
+        ret val_as_int(av) == val_as_int(bv);
+    }
+    if (val_is_str(av) && val_is_str(bv)) {
+        ret _str.eq(val_as_str(av),
+                    val_as_str(bv));
+    }
+    sess.span_err(sp, "bad types in comparison");
+    fail;
+}
+
+impure fn eval_crate_directives(parser p,
+                                env e,
+                                vec[@ast.crate_directive] cdirs,
+                                str prefix,
+                                &mutable vec[@ast.view_item] view_items,
+                                &mutable vec[@ast.item] items,
+                                hashmap[ast.ident,
+                                        ast.mod_index_entry] index) {
+
+    for (@ast.crate_directive sub_cdir in cdirs) {
+        eval_crate_directive(p, e, sub_cdir, prefix,
+                             view_items, items, index);
+    }
+}
+
+
+impure fn eval_crate_directives_to_mod(parser p,
+                                       env e,
+                                       vec[@ast.crate_directive] cdirs,
+                                       str prefix) -> ast._mod {
+    let vec[@ast.view_item] view_items = vec();
+    let vec[@ast.item] items = vec();
+    auto index = new_str_hash[ast.mod_index_entry]();
+
+    eval_crate_directives(p, e, cdirs, prefix,
+                          view_items, items, index);
+
+    ret rec(view_items=view_items, items=items, index=index);
+}
+
+
+impure fn eval_crate_directive_block(parser p,
+                                     env e,
+                                     &ast.block blk,
+                                     str prefix,
+                                     &mutable vec[@ast.view_item] view_items,
+                                     &mutable vec[@ast.item] items,
+                                     hashmap[ast.ident,
+                                             ast.mod_index_entry] index) {
+
+    for (@ast.stmt s in blk.node.stmts) {
+        alt (s.node) {
+            case (ast.stmt_crate_directive(?cdir)) {
+                eval_crate_directive(p, e, cdir, prefix,
+                                     view_items, items, index);
+            }
+            case (_) {
+                auto sess = p.get_session();
+                sess.span_err(s.span,
+                              "unsupported stmt in crate-directive block");
+            }
+        }
+    }
+}
+
+impure fn eval_crate_directive_expr(parser p,
+                                    env e,
+                                    @ast.expr x,
+                                    str prefix,
+                                    &mutable vec[@ast.view_item] view_items,
+                                    &mutable vec[@ast.item] items,
+                                    hashmap[ast.ident,
+                                            ast.mod_index_entry] index) {
+    auto sess = p.get_session();
+
+    alt (x.node) {
+
+        case (ast.expr_if(?cond, ?thn, ?elifs, ?elopt, _)) {
+            auto cv = eval_expr(sess, e, cond);
+            if (!val_is_bool(cv)) {
+                sess.span_err(x.span, "bad cond type in 'if'");
+            }
+
+            if (val_as_bool(cv)) {
+                ret eval_crate_directive_block(p, e, thn, prefix,
+                                               view_items, items,
+                                               index);
+            }
+
+            for (tup(@ast.expr, ast.block) elif in elifs) {
+                auto cv = eval_expr(sess, e, elif._0);
+                if (!val_is_bool(cv)) {
+                    sess.span_err(x.span, "bad cond type in 'else if'");
+                }
+
+                if (val_as_bool(cv)) {
+                    ret eval_crate_directive_block(p, e, elif._1, prefix,
+                                                   view_items, items,
+                                                   index);
+                }
+            }
+
+            alt (elopt) {
+                case (some[ast.block](?els)) {
+                    ret eval_crate_directive_block(p, e, els, prefix,
+                                                   view_items, items,
+                                                   index);
+                }
+                case (_) {
+                    // Absent-else is ok.
+                }
+            }
+        }
+
+        case (ast.expr_alt(?v, ?arms, _)) {
+            auto vv = eval_expr(sess, e, v);
+            for (ast.arm arm in arms) {
+                alt (arm.pat.node) {
+                    case (ast.pat_lit(?lit, _)) {
+                        auto pv = eval_lit(sess, e,
+                                           arm.pat.span, lit);
+                        if (val_eq(sess, arm.pat.span, vv, pv)) {
+                            ret eval_crate_directive_block
+                                (p, e, arm.block, prefix,
+                                 view_items, items, index);
+                        }
+                    }
+                    case (ast.pat_wild(_)) {
+                        ret eval_crate_directive_block
+                            (p, e, arm.block, prefix,
+                             view_items, items, index);
+                    }
+                    case (_) {
+                        sess.span_err(arm.pat.span,
+                                      "bad pattern type in 'alt'");
+                    }
+                }
+            }
+            sess.span_err(x.span, "no cases matched in 'alt'");
+        }
+
+        case (_) {
+            sess.span_err(x.span, "unsupported expr type");
+        }
+    }
+}
+
+impure fn eval_crate_directive(parser p,
+                               env e,
+                               @ast.crate_directive cdir,
+                               str prefix,
+                               &mutable vec[@ast.view_item] view_items,
+                               &mutable vec[@ast.item] items,
+                               hashmap[ast.ident,
+                                       ast.mod_index_entry] index) {
+    alt (cdir.node) {
+
+        case (ast.cdir_let(?id, ?x, ?cdirs)) {
+            auto v = eval_expr(p.get_session(), e, x);
+            auto e0 = vec(tup(id, v)) + e;
+            eval_crate_directives(p, e0, cdirs, prefix,
+                                  view_items, items, index);
+        }
+
+        case (ast.cdir_expr(?x)) {
+            eval_crate_directive_expr(p, e, x, prefix,
+                                      view_items, items, index);
+        }
+
+        case (ast.cdir_src_mod(?id, ?file_opt)) {
+
+            auto file_path = id + ".rs";
+            alt (file_opt) {
+                case (some[filename](?f)) {
+                    file_path = f;
+                }
+                case (none[filename]) {}
+            }
+
+            auto full_path = prefix + std.os.path_sep() + file_path;
+
+            auto p0 = new_parser(p.get_session(), 0, full_path);
+            auto m0 = parse_mod_items(p0, token.EOF);
+            auto im = ast.item_mod(id, m0, p.next_def_id());
+            auto i = @spanned(cdir.span, cdir.span, im);
+            ast.index_item(index, i);
+            append[@ast.item](items, i);
+        }
+
+        case (ast.cdir_dir_mod(?id, ?dir_opt, ?cdirs)) {
+
+            auto path = id;
+            alt (dir_opt) {
+                case (some[filename](?d)) {
+                    path = d;
+                }
+                case (none[filename]) {}
+            }
+
+            auto full_path = prefix + std.os.path_sep() + path;
+            auto m0 = eval_crate_directives_to_mod(p, e, cdirs, path);
+            auto im = ast.item_mod(id, m0, p.next_def_id());
+            auto i = @spanned(cdir.span, cdir.span, im);
+            ast.index_item(index, i);
+            append[@ast.item](items, i);
+        }
+
+        case (ast.cdir_view_item(?vi)) {
+            append[@ast.view_item](view_items, vi);
+            ast.index_view_item(index, vi);
+        }
+
+        case (ast.cdir_meta(?mi)) {}
+        case (ast.cdir_syntax(?pth)) {}
+        case (ast.cdir_auth(?pth, ?eff)) {}
+    }
+}
+
+
+//
+// Local Variables:
+// mode: rust
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+// End:
+//
diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs
index 944e14240ba..3579a3a087f 100644
--- a/src/comp/front/parser.rs
+++ b/src/comp/front/parser.rs
@@ -2111,80 +2111,6 @@ impure fn parse_crate_from_source_file(parser p) -> @ast.crate {
 //
 // Each directive imperatively extends its environment with 0 or more items.
 
-impure fn eval_crate_directives(parser p,
-                                vec[@ast.crate_directive] cdirs,
-                                str prefix) -> ast._mod {
-    let vec[@ast.item] items = vec();
-    auto index = new_str_hash[ast.mod_index_entry]();
-    auto view_items = parse_view(p, index);
-
-    for (@ast.crate_directive sub_cdir in cdirs) {
-        eval_crate_directive(p, sub_cdir, prefix,
-                             view_items, items, index);
-    }
-
-    ret rec(view_items=view_items, items=items, index=index);
-}
-
-impure fn eval_crate_directive(parser p,
-                               @ast.crate_directive cdir,
-                               str prefix,
-                               &mutable vec[@ast.view_item] view_items,
-                               &mutable vec[@ast.item] items,
-                               hashmap[ast.ident,ast.mod_index_entry] index) {
-    alt (cdir.node) {
-        case (ast.cdir_expr(?e)) {}
-        case (ast.cdir_const(?i)) {}
-
-        case (ast.cdir_src_mod(?id, ?file_opt)) {
-
-            auto file_path = id + ".rs";
-            alt (file_opt) {
-                case (some[filename](?f)) {
-                    file_path = f;
-                }
-                case (none[filename]) {}
-            }
-
-            auto full_path = prefix + std.os.path_sep() + file_path;
-
-            auto p0 = new_parser(p.get_session(), 0, full_path);
-            auto m0 = parse_mod_items(p0, token.EOF);
-            auto im = ast.item_mod(id, m0, p.next_def_id());
-            auto i = @spanned(cdir.span, cdir.span, im);
-            ast.index_item(index, i);
-            append[@ast.item](items, i);
-        }
-
-        case (ast.cdir_dir_mod(?id, ?dir_opt, ?cdirs)) {
-
-            auto path = id;
-            alt (dir_opt) {
-                case (some[filename](?d)) {
-                    path = d;
-                }
-                case (none[filename]) {}
-            }
-
-            auto full_path = prefix + std.os.path_sep() + path;
-            auto m0 = eval_crate_directives(p, cdirs, path);
-            auto im = ast.item_mod(id, m0, p.next_def_id());
-            auto i = @spanned(cdir.span, cdir.span, im);
-            ast.index_item(index, i);
-            append[@ast.item](items, i);
-        }
-
-        case (ast.cdir_view_item(?vi)) {
-            append[@ast.view_item](view_items, vi);
-            ast.index_view_item(index, vi);
-        }
-
-        case (ast.cdir_meta(?mi)) {}
-        case (ast.cdir_syntax(?pth)) {}
-        case (ast.cdir_auth(?pth, ?eff)) {}
-    }
-}
-
 impure fn parse_crate_directive(parser p) -> ast.crate_directive
 {
     auto lo = p.get_span();
@@ -2201,10 +2127,7 @@ impure fn parse_crate_directive(parser p) -> ast.crate_directive
             expect(p, token.SEMI);
             ret spanned(lo, hi, ast.cdir_auth(n, e));
         }
-        case (token.CONST) {
-            auto c = parse_item_const(p);
-            ret spanned(c.span, c.span, ast.cdir_const(c));
-         }
+
         case (token.MOD) {
             p.bump();
             auto id = parse_ident(p);
@@ -2267,7 +2190,8 @@ impure fn parse_crate_from_crate_file(parser p) -> @ast.crate {
     auto hi = lo;
     auto prefix = std.path.dirname(lo.filename);
     auto cdirs = parse_crate_directives(p, token.EOF);
-    auto m = eval_crate_directives(p, cdirs, prefix);
+    auto m = eval.eval_crate_directives_to_mod(p, eval.mk_env(),
+                                               cdirs, prefix);
     hi = p.get_span();
     expect(p, token.EOF);
     ret @spanned(lo, hi, rec(module=m));
diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc
index b439632cfbc..bc4aaa52c1a 100644
--- a/src/comp/rustc.rc
+++ b/src/comp/rustc.rc
@@ -8,6 +8,7 @@ mod front {
     mod lexer;
     mod parser;
     mod token;
+    mod eval;
 }
 
 mod middle {
@@ -38,7 +39,6 @@ auth middle.trans.copy_args_to_allocas = impure;
 auth middle.trans.trans_block = impure;
 auth lib.llvm = unsafe;
 
-
 mod lib {
     alt (target_os) {
         case ("win32") {