Merge branch 'master' into recursive-elseif
Conflicts: src/Makefile src/comp/front/ast.rs src/comp/front/parser.rs src/comp/middle/fold.rs src/comp/middle/trans.rs
This commit is contained in:
commit
9fc4db6b89
66 changed files with 8303 additions and 2468 deletions
|
|
@ -5,6 +5,7 @@ import std._vec;
|
|||
import util.common.span;
|
||||
import util.common.spanned;
|
||||
import util.common.ty_mach;
|
||||
import util.common.filename;
|
||||
|
||||
type ident = str;
|
||||
|
||||
|
|
@ -36,11 +37,29 @@ tag def {
|
|||
def_ty_arg(def_id);
|
||||
def_binding(def_id);
|
||||
def_use(def_id);
|
||||
def_native_ty(def_id);
|
||||
def_native_fn(def_id);
|
||||
}
|
||||
|
||||
type crate = spanned[crate_];
|
||||
type crate_ = rec(_mod module);
|
||||
|
||||
tag crate_directive_ {
|
||||
cdir_expr(@expr);
|
||||
// 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);
|
||||
cdir_meta(vec[@meta_item]);
|
||||
cdir_syntax(path);
|
||||
cdir_auth(path, effect);
|
||||
}
|
||||
type crate_directive = spanned[crate_directive_];
|
||||
|
||||
|
||||
type meta_item = spanned[meta_item_];
|
||||
type meta_item_ = rec(ident name, str value);
|
||||
|
||||
|
|
@ -55,6 +74,7 @@ type pat = spanned[pat_];
|
|||
tag pat_ {
|
||||
pat_wild(ann);
|
||||
pat_bind(ident, def_id, ann);
|
||||
pat_lit(@lit, ann);
|
||||
pat_tag(path, vec[@pat], option.t[variant_def], ann);
|
||||
}
|
||||
|
||||
|
|
@ -63,6 +83,11 @@ tag mutability {
|
|||
imm;
|
||||
}
|
||||
|
||||
tag opacity {
|
||||
op_abstract;
|
||||
op_transparent;
|
||||
}
|
||||
|
||||
tag layer {
|
||||
layer_value;
|
||||
layer_state;
|
||||
|
|
@ -75,6 +100,11 @@ tag effect {
|
|||
eff_unsafe;
|
||||
}
|
||||
|
||||
tag proto {
|
||||
proto_iter;
|
||||
proto_fn;
|
||||
}
|
||||
|
||||
tag binop {
|
||||
add;
|
||||
sub;
|
||||
|
|
@ -97,12 +127,49 @@ tag binop {
|
|||
gt;
|
||||
}
|
||||
|
||||
fn binop_to_str(binop op) -> str {
|
||||
alt (op) {
|
||||
case (add) {ret "+";}
|
||||
case (sub) {ret "-";}
|
||||
case (mul) {ret "*";}
|
||||
case (div) {ret "/";}
|
||||
case (rem) {ret "%";}
|
||||
case (and) {ret "&&";}
|
||||
case (or) {ret "||";}
|
||||
case (bitxor) {ret "^";}
|
||||
case (bitand) {ret "&";}
|
||||
case (bitor) {ret "|";}
|
||||
case (lsl) {ret "<<";}
|
||||
case (lsr) {ret ">>";}
|
||||
case (asr) {ret ">>>";}
|
||||
case (eq) {ret "==";}
|
||||
case (lt) {ret "<";}
|
||||
case (le) {ret "<=";}
|
||||
case (ne) {ret "!=";}
|
||||
case (ge) {ret ">=";}
|
||||
case (gt) {ret ">";}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tag unop {
|
||||
box;
|
||||
deref;
|
||||
bitnot;
|
||||
not;
|
||||
neg;
|
||||
_mutable;
|
||||
}
|
||||
|
||||
fn unop_to_str(unop op) -> str {
|
||||
alt (op) {
|
||||
case (box) {ret "@";}
|
||||
case (deref) {ret "*";}
|
||||
case (bitnot) {ret "~";}
|
||||
case (not) {ret "!";}
|
||||
case (neg) {ret "-";}
|
||||
case (_mutable) {ret "mutable";}
|
||||
}
|
||||
}
|
||||
|
||||
tag mode {
|
||||
|
|
@ -113,11 +180,9 @@ tag mode {
|
|||
type stmt = spanned[stmt_];
|
||||
tag stmt_ {
|
||||
stmt_decl(@decl);
|
||||
stmt_ret(option.t[@expr]);
|
||||
stmt_log(@expr);
|
||||
stmt_check_expr(@expr);
|
||||
stmt_fail;
|
||||
stmt_expr(@expr);
|
||||
// These only exist in crate-level blocks.
|
||||
stmt_crate_directive(@crate_directive);
|
||||
}
|
||||
|
||||
type local = rec(option.t[@ty] ty,
|
||||
|
|
@ -142,7 +207,7 @@ type expr = spanned[expr_];
|
|||
tag expr_ {
|
||||
expr_vec(vec[@expr], ann);
|
||||
expr_tup(vec[elt], ann);
|
||||
expr_rec(vec[field], ann);
|
||||
expr_rec(vec[field], option.t[@expr], ann);
|
||||
expr_call(@expr, vec[@expr], ann);
|
||||
expr_bind(@expr, vec[option.t[@expr]], ann);
|
||||
expr_binary(binop, @expr, @expr, ann);
|
||||
|
|
@ -152,6 +217,7 @@ tag expr_ {
|
|||
expr_if(@expr, block, option.t[@expr], ann);
|
||||
expr_while(@expr, block, ann);
|
||||
expr_for(@decl, @expr, block, ann);
|
||||
expr_for_each(@decl, @expr, block, ann);
|
||||
expr_do_while(block, @expr, ann);
|
||||
expr_alt(@expr, vec[arm], ann);
|
||||
expr_block(block, ann);
|
||||
|
|
@ -160,6 +226,13 @@ tag expr_ {
|
|||
expr_field(@expr, ident, ann);
|
||||
expr_index(@expr, @expr, ann);
|
||||
expr_path(path, option.t[def], ann);
|
||||
expr_ext(path, vec[@expr], option.t[@expr], @expr, ann);
|
||||
expr_fail;
|
||||
expr_ret(option.t[@expr]);
|
||||
expr_put(option.t[@expr]);
|
||||
expr_be(@expr);
|
||||
expr_log(@expr);
|
||||
expr_check_expr(@expr);
|
||||
}
|
||||
|
||||
type lit = spanned[lit_];
|
||||
|
|
@ -179,7 +252,8 @@ tag lit_ {
|
|||
type ty_field = rec(ident ident, @ty ty);
|
||||
type ty_arg = rec(mode mode, @ty ty);
|
||||
// TODO: effect
|
||||
type ty_method = rec(ident ident, vec[ty_arg] inputs, @ty output);
|
||||
type ty_method = rec(proto proto, ident ident,
|
||||
vec[ty_arg] inputs, @ty output);
|
||||
type ty = spanned[ty_];
|
||||
tag ty_ {
|
||||
ty_nil;
|
||||
|
|
@ -193,17 +267,28 @@ tag ty_ {
|
|||
ty_vec(@ty);
|
||||
ty_tup(vec[@ty]);
|
||||
ty_rec(vec[ty_field]);
|
||||
ty_fn(vec[ty_arg], @ty); // TODO: effect
|
||||
ty_fn(proto, vec[ty_arg], @ty); // TODO: effect
|
||||
ty_obj(vec[ty_method]);
|
||||
ty_path(path, option.t[def]);
|
||||
ty_mutable(@ty);
|
||||
ty_type;
|
||||
ty_constr(@ty, vec[@constr]);
|
||||
}
|
||||
|
||||
tag constr_arg_ {
|
||||
carg_base;
|
||||
carg_ident(ident);
|
||||
}
|
||||
type constr_arg = spanned[constr_arg_];
|
||||
type constr_ = rec(path path, vec[@constr_arg] args);
|
||||
type constr = spanned[constr_];
|
||||
|
||||
type arg = rec(mode mode, @ty ty, ident ident, def_id id);
|
||||
type _fn = rec(effect effect,
|
||||
bool is_iter,
|
||||
vec[arg] inputs,
|
||||
@ty output,
|
||||
type fn_decl = rec(effect effect,
|
||||
vec[arg] inputs,
|
||||
@ty output);
|
||||
type _fn = rec(fn_decl decl,
|
||||
proto proto,
|
||||
block body);
|
||||
|
||||
|
||||
|
|
@ -212,8 +297,8 @@ type method = spanned[method_];
|
|||
|
||||
type obj_field = rec(@ty ty, ident ident, def_id id, ann ann);
|
||||
type _obj = rec(vec[obj_field] fields,
|
||||
vec[@method] methods);
|
||||
|
||||
vec[@method] methods,
|
||||
option.t[block] dtor);
|
||||
|
||||
tag mod_index_entry {
|
||||
mie_view_item(@view_item);
|
||||
|
|
@ -221,11 +306,28 @@ tag mod_index_entry {
|
|||
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,
|
||||
mod_index index);
|
||||
|
||||
tag native_abi {
|
||||
native_abi_rust;
|
||||
native_abi_cdecl;
|
||||
}
|
||||
|
||||
type native_mod = rec(str native_name,
|
||||
native_abi abi,
|
||||
vec[@view_item] view_items,
|
||||
vec[@native_item] items,
|
||||
native_mod_index index);
|
||||
type native_mod_index = hashmap[ident,native_mod_index_entry];
|
||||
|
||||
type variant_arg = rec(@ty ty, def_id id);
|
||||
type variant = rec(str name, vec[variant_arg] args, def_id id, ann ann);
|
||||
|
||||
|
|
@ -233,6 +335,7 @@ type view_item = spanned[view_item_];
|
|||
tag view_item_ {
|
||||
view_item_use(ident, vec[@meta_item], def_id);
|
||||
view_item_import(ident, vec[ident], def_id, option.t[def]);
|
||||
view_item_export(ident);
|
||||
}
|
||||
|
||||
type item = spanned[item_];
|
||||
|
|
@ -240,11 +343,18 @@ tag item_ {
|
|||
item_const(ident, @ty, @expr, def_id, ann);
|
||||
item_fn(ident, _fn, vec[ty_param], def_id, ann);
|
||||
item_mod(ident, _mod, def_id);
|
||||
item_native_mod(ident, native_mod, def_id);
|
||||
item_ty(ident, @ty, vec[ty_param], def_id, ann);
|
||||
item_tag(ident, vec[variant], vec[ty_param], def_id);
|
||||
item_obj(ident, _obj, vec[ty_param], def_id, ann);
|
||||
}
|
||||
|
||||
type native_item = spanned[native_item_];
|
||||
tag native_item_ {
|
||||
native_item_ty(ident, def_id);
|
||||
native_item_fn(ident, fn_decl, vec[ty_param], def_id, ann);
|
||||
}
|
||||
|
||||
fn index_view_item(mod_index index, @view_item it) {
|
||||
alt (it.node) {
|
||||
case(ast.view_item_use(?id, _, _)) {
|
||||
|
|
@ -253,6 +363,11 @@ fn index_view_item(mod_index index, @view_item it) {
|
|||
case(ast.view_item_import(?def_ident,_,_,_)) {
|
||||
index.insert(def_ident, ast.mie_view_item(it));
|
||||
}
|
||||
case(ast.view_item_export(_)) {
|
||||
// NB: don't index these, they might collide with
|
||||
// the import or use that they're exporting. Have
|
||||
// to do linear search for exports.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -267,6 +382,9 @@ fn index_item(mod_index index, @item it) {
|
|||
case (ast.item_mod(?id, _, _)) {
|
||||
index.insert(id, ast.mie_item(it));
|
||||
}
|
||||
case (ast.item_native_mod(?id, _, _)) {
|
||||
index.insert(id, ast.mie_item(it));
|
||||
}
|
||||
case (ast.item_ty(?id, _, _, _, _)) {
|
||||
index.insert(id, ast.mie_item(it));
|
||||
}
|
||||
|
|
@ -285,6 +403,41 @@ fn index_item(mod_index index, @item it) {
|
|||
}
|
||||
}
|
||||
|
||||
fn index_native_item(native_mod_index index, @native_item it) {
|
||||
alt (it.node) {
|
||||
case (ast.native_item_ty(?id, _)) {
|
||||
index.insert(id, ast.nmie_item(it));
|
||||
}
|
||||
case (ast.native_item_fn(?id, _, _, _, _)) {
|
||||
index.insert(id, ast.nmie_item(it));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn index_native_view_item(native_mod_index index, @view_item it) {
|
||||
alt (it.node) {
|
||||
case(ast.view_item_import(?def_ident,_,_,_)) {
|
||||
index.insert(def_ident, ast.nmie_view_item(it));
|
||||
}
|
||||
case(ast.view_item_export(_)) {
|
||||
// NB: don't index these, they might collide with
|
||||
// the import or use that they're exporting. Have
|
||||
// to do linear search for exports.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_call_expr(@expr e) -> bool {
|
||||
alt (e.node) {
|
||||
case (expr_call(_, _, _)) {
|
||||
ret true;
|
||||
}
|
||||
case (_) {
|
||||
ret false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
|
|
|
|||
436
src/comp/front/eval.rs
Normal file
436
src/comp/front/eval.rs
Normal file
|
|
@ -0,0 +1,436 @@
|
|||
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, ?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);
|
||||
}
|
||||
|
||||
alt (elopt) {
|
||||
case (some[@ast.expr](?els)) {
|
||||
ret eval_crate_directive_expr(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 (ast.expr_block(?block, _)) {
|
||||
ret eval_crate_directive_block(p, e, block, prefix,
|
||||
view_items, items,
|
||||
index);
|
||||
}
|
||||
|
||||
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(), e, 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, full_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:
|
||||
//
|
||||
553
src/comp/front/extfmt.rs
Normal file
553
src/comp/front/extfmt.rs
Normal file
|
|
@ -0,0 +1,553 @@
|
|||
/* The 'fmt' extension is modeled on the posix printf system.
|
||||
*
|
||||
* A posix conversion ostensibly looks like this:
|
||||
*
|
||||
* %[parameter][flags][width][.precision][length]type
|
||||
*
|
||||
* Given the different numeric type bestiary we have, we omit the 'length'
|
||||
* parameter and support slightly different conversions for 'type':
|
||||
*
|
||||
* %[parameter][flags][width][.precision]type
|
||||
*
|
||||
* we also only support translating-to-rust a tiny subset of the possible
|
||||
* combinations at the moment.
|
||||
*/
|
||||
|
||||
import util.common;
|
||||
|
||||
import std._str;
|
||||
import std._vec;
|
||||
import std.option;
|
||||
import std.option.none;
|
||||
import std.option.some;
|
||||
|
||||
export expand_syntax_ext;
|
||||
|
||||
tag signedness {
|
||||
signed;
|
||||
unsigned;
|
||||
}
|
||||
|
||||
tag caseness {
|
||||
case_upper;
|
||||
case_lower;
|
||||
}
|
||||
|
||||
tag ty {
|
||||
ty_bool;
|
||||
ty_str;
|
||||
ty_char;
|
||||
ty_int(signedness);
|
||||
ty_bits;
|
||||
ty_hex(caseness);
|
||||
// FIXME: More types
|
||||
}
|
||||
|
||||
tag flag {
|
||||
flag_left_justify;
|
||||
flag_left_zero_pad;
|
||||
flag_left_space_pad;
|
||||
flag_plus_if_positive;
|
||||
flag_alternate;
|
||||
}
|
||||
|
||||
tag count {
|
||||
count_is(int);
|
||||
count_is_param(int);
|
||||
count_is_next_param;
|
||||
count_implied;
|
||||
}
|
||||
|
||||
// A formatted conversion from an expression to a string
|
||||
type conv = rec(option.t[int] param,
|
||||
vec[flag] flags,
|
||||
count width,
|
||||
count precision,
|
||||
ty ty);
|
||||
|
||||
// A fragment of the output sequence
|
||||
tag piece {
|
||||
piece_string(str);
|
||||
piece_conv(conv);
|
||||
}
|
||||
|
||||
// TODO: Need to thread parser through here to handle errors correctly
|
||||
fn expand_syntax_ext(vec[@ast.expr] args,
|
||||
option.t[@ast.expr] body) -> @ast.expr {
|
||||
|
||||
if (_vec.len[@ast.expr](args) == 0u) {
|
||||
log "malformed #fmt call";
|
||||
fail;
|
||||
}
|
||||
|
||||
auto fmt = expr_to_str(args.(0));
|
||||
|
||||
// log "Format string:";
|
||||
// log fmt;
|
||||
|
||||
auto pieces = parse_fmt_string(fmt);
|
||||
auto args_len = _vec.len[@ast.expr](args);
|
||||
auto fmt_args = _vec.slice[@ast.expr](args, 1u, args_len - 1u);
|
||||
ret pieces_to_expr(pieces, args);
|
||||
}
|
||||
|
||||
fn expr_to_str(@ast.expr expr) -> str {
|
||||
alt (expr.node) {
|
||||
case (ast.expr_lit(?l, _)) {
|
||||
alt (l.node) {
|
||||
case (ast.lit_str(?s)) {
|
||||
ret s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
log "malformed #fmt call";
|
||||
fail;
|
||||
}
|
||||
|
||||
fn parse_fmt_string(str s) -> vec[piece] {
|
||||
let vec[piece] pieces = vec();
|
||||
auto lim = _str.byte_len(s);
|
||||
auto buf = "";
|
||||
|
||||
fn flush_buf(str buf, &vec[piece] pieces) -> str {
|
||||
if (_str.byte_len(buf) > 0u) {
|
||||
auto piece = piece_string(buf);
|
||||
pieces += piece;
|
||||
}
|
||||
ret "";
|
||||
}
|
||||
|
||||
auto i = 0u;
|
||||
while (i < lim) {
|
||||
auto curr = _str.substr(s, i, 1u);
|
||||
if (_str.eq(curr, "%")) {
|
||||
i += 1u;
|
||||
if (i >= lim) {
|
||||
log "unterminated conversion at end of string";
|
||||
fail;
|
||||
}
|
||||
auto curr2 = _str.substr(s, i, 1u);
|
||||
if (_str.eq(curr2, "%")) {
|
||||
i += 1u;
|
||||
} else {
|
||||
buf = flush_buf(buf, pieces);
|
||||
auto res = parse_conversion(s, i, lim);
|
||||
pieces += res._0;
|
||||
i = res._1;
|
||||
}
|
||||
} else {
|
||||
buf += curr;
|
||||
i += 1u;
|
||||
}
|
||||
}
|
||||
buf = flush_buf(buf, pieces);
|
||||
ret pieces;
|
||||
}
|
||||
|
||||
fn peek_num(str s, uint i, uint lim) -> option.t[tup(uint, uint)] {
|
||||
if (i >= lim) {
|
||||
ret none[tup(uint, uint)];
|
||||
}
|
||||
|
||||
auto c = s.(i);
|
||||
if (!('0' as u8 <= c && c <= '9' as u8)) {
|
||||
ret option.none[tup(uint, uint)];
|
||||
}
|
||||
|
||||
auto n = (c - ('0' as u8)) as uint;
|
||||
alt (peek_num(s, i + 1u, lim)) {
|
||||
case (none[tup(uint, uint)]) {
|
||||
ret some[tup(uint, uint)](tup(n, i + 1u));
|
||||
}
|
||||
case (some[tup(uint, uint)](?next)) {
|
||||
auto m = next._0;
|
||||
auto j = next._1;
|
||||
ret some[tup(uint, uint)](tup(n * 10u + m, j));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn parse_conversion(str s, uint i, uint lim) -> tup(piece, uint) {
|
||||
auto parm = parse_parameter(s, i, lim);
|
||||
auto flags = parse_flags(s, parm._1, lim);
|
||||
auto width = parse_count(s, flags._1, lim);
|
||||
auto prec = parse_precision(s, width._1, lim);
|
||||
auto ty = parse_type(s, prec._1, lim);
|
||||
ret tup(piece_conv(rec(param = parm._0,
|
||||
flags = flags._0,
|
||||
width = width._0,
|
||||
precision = prec._0,
|
||||
ty = ty._0)),
|
||||
ty._1);
|
||||
}
|
||||
|
||||
fn parse_parameter(str s, uint i, uint lim) -> tup(option.t[int], uint) {
|
||||
if (i >= lim) {
|
||||
ret tup(none[int], i);
|
||||
}
|
||||
|
||||
auto num = peek_num(s, i, lim);
|
||||
alt (num) {
|
||||
case (none[tup(uint, uint)]) {
|
||||
ret tup(none[int], i);
|
||||
}
|
||||
case (some[tup(uint, uint)](?t)) {
|
||||
auto n = t._0;
|
||||
auto j = t._1;
|
||||
if (j < lim && s.(j) == '$' as u8) {
|
||||
ret tup(some[int](n as int), j + 1u);
|
||||
}
|
||||
else {
|
||||
ret tup(none[int], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_flags(str s, uint i, uint lim) -> tup(vec[flag], uint) {
|
||||
let vec[flag] noflags = vec();
|
||||
|
||||
if (i >= lim) {
|
||||
ret tup(noflags, i);
|
||||
}
|
||||
|
||||
fn more_(flag f, str s, uint i, uint lim) -> tup(vec[flag], uint) {
|
||||
auto next = parse_flags(s, i + 1u, lim);
|
||||
auto rest = next._0;
|
||||
auto j = next._1;
|
||||
let vec[flag] curr = vec(f);
|
||||
ret tup(curr + rest, j);
|
||||
}
|
||||
|
||||
auto more = bind more_(_, s, i, lim);
|
||||
|
||||
auto f = s.(i);
|
||||
if (f == ('-' as u8)) {
|
||||
ret more(flag_left_justify);
|
||||
} else if (f == ('0' as u8)) {
|
||||
ret more(flag_left_zero_pad);
|
||||
} else if (f == (' ' as u8)) {
|
||||
ret more(flag_left_space_pad);
|
||||
} else if (f == ('+' as u8)) {
|
||||
ret more(flag_plus_if_positive);
|
||||
} else if (f == ('#' as u8)) {
|
||||
ret more(flag_alternate);
|
||||
} else {
|
||||
ret tup(noflags, i);
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_count(str s, uint i, uint lim) -> tup(count, uint) {
|
||||
if (i >= lim) {
|
||||
ret tup(count_implied, i);
|
||||
}
|
||||
|
||||
if (s.(i) == ('*' as u8)) {
|
||||
auto param = parse_parameter(s, i + 1u, lim);
|
||||
auto j = param._1;
|
||||
alt (param._0) {
|
||||
case (none[int]) {
|
||||
ret tup(count_is_next_param, j);
|
||||
}
|
||||
case (some[int](?n)) {
|
||||
ret tup(count_is_param(n), j);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto num = peek_num(s, i, lim);
|
||||
alt (num) {
|
||||
case (none[tup(uint, uint)]) {
|
||||
ret tup(count_implied, i);
|
||||
}
|
||||
case (some[tup(uint, uint)](?num)) {
|
||||
ret tup(count_is(num._0 as int), num._1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_precision(str s, uint i, uint lim) -> tup(count, uint) {
|
||||
if (i >= lim) {
|
||||
ret tup(count_implied, i);
|
||||
}
|
||||
|
||||
if (s.(i) == '.' as u8) {
|
||||
ret parse_count(s, i + 1u, lim);
|
||||
} else {
|
||||
ret tup(count_implied, i);
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_type(str s, uint i, uint lim) -> tup(ty, uint) {
|
||||
if (i >= lim) {
|
||||
log "missing type in conversion";
|
||||
fail;
|
||||
}
|
||||
|
||||
auto t;
|
||||
auto tstr = _str.substr(s, i, 1u);
|
||||
if (_str.eq(tstr, "b")) {
|
||||
t = ty_bool;
|
||||
} else if (_str.eq(tstr, "s")) {
|
||||
t = ty_str;
|
||||
} else if (_str.eq(tstr, "c")) {
|
||||
t = ty_char;
|
||||
} else if (_str.eq(tstr, "d")
|
||||
|| _str.eq(tstr, "i")) {
|
||||
// TODO: Do we really want two signed types here?
|
||||
// How important is it to be printf compatible?
|
||||
t = ty_int(signed);
|
||||
} else if (_str.eq(tstr, "u")) {
|
||||
t = ty_int(unsigned);
|
||||
} else if (_str.eq(tstr, "x")) {
|
||||
t = ty_hex(case_lower);
|
||||
} else if (_str.eq(tstr, "X")) {
|
||||
t = ty_hex(case_upper);
|
||||
} else if (_str.eq(tstr, "t")) {
|
||||
t = ty_bits;
|
||||
} else {
|
||||
log "unknown type in conversion";
|
||||
fail;
|
||||
}
|
||||
|
||||
ret tup(t, i + 1u);
|
||||
}
|
||||
|
||||
fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr {
|
||||
|
||||
fn make_new_lit(common.span sp, ast.lit_ lit) -> @ast.expr {
|
||||
auto sp_lit = @parser.spanned[ast.lit_](sp, sp, lit);
|
||||
auto expr = ast.expr_lit(sp_lit, ast.ann_none);
|
||||
ret @parser.spanned[ast.expr_](sp, sp, expr);
|
||||
}
|
||||
|
||||
fn make_new_str(common.span sp, str s) -> @ast.expr {
|
||||
auto lit = ast.lit_str(s);
|
||||
ret make_new_lit(sp, lit);
|
||||
}
|
||||
|
||||
fn make_new_uint(common.span sp, uint u) -> @ast.expr {
|
||||
auto lit = ast.lit_uint(u);
|
||||
ret make_new_lit(sp, lit);
|
||||
}
|
||||
|
||||
fn make_add_expr(common.span sp,
|
||||
@ast.expr lhs, @ast.expr rhs) -> @ast.expr {
|
||||
auto binexpr = ast.expr_binary(ast.add, lhs, rhs, ast.ann_none);
|
||||
ret @parser.spanned[ast.expr_](sp, sp, binexpr);
|
||||
}
|
||||
|
||||
fn make_call(common.span sp, vec[ast.ident] fn_path,
|
||||
vec[@ast.expr] args) -> @ast.expr {
|
||||
let vec[ast.ident] path_idents = fn_path;
|
||||
let vec[@ast.ty] path_types = vec();
|
||||
auto path = rec(idents = path_idents, types = path_types);
|
||||
auto sp_path = parser.spanned[ast.path_](sp, sp, path);
|
||||
auto pathexpr = ast.expr_path(sp_path, none[ast.def], ast.ann_none);
|
||||
auto sp_pathexpr = @parser.spanned[ast.expr_](sp, sp, pathexpr);
|
||||
auto callexpr = ast.expr_call(sp_pathexpr, args, ast.ann_none);
|
||||
auto sp_callexpr = @parser.spanned[ast.expr_](sp, sp, callexpr);
|
||||
ret sp_callexpr;
|
||||
}
|
||||
|
||||
fn make_new_conv(conv cnv, @ast.expr arg) -> @ast.expr {
|
||||
|
||||
auto unsupported = "conversion not supported in #fmt string";
|
||||
|
||||
alt (cnv.param) {
|
||||
case (option.none[int]) {
|
||||
}
|
||||
case (_) {
|
||||
log unsupported;
|
||||
fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (_vec.len[flag](cnv.flags) != 0u) {
|
||||
log unsupported;
|
||||
fail;
|
||||
}
|
||||
|
||||
alt (cnv.width) {
|
||||
case (count_implied) {
|
||||
}
|
||||
case (_) {
|
||||
log unsupported;
|
||||
fail;
|
||||
}
|
||||
}
|
||||
|
||||
alt (cnv.precision) {
|
||||
case (count_implied) {
|
||||
}
|
||||
case (_) {
|
||||
log unsupported;
|
||||
fail;
|
||||
}
|
||||
}
|
||||
|
||||
alt (cnv.ty) {
|
||||
case (ty_str) {
|
||||
ret arg;
|
||||
}
|
||||
case (ty_int(?sign)) {
|
||||
alt (sign) {
|
||||
case (signed) {
|
||||
let vec[str] path = vec("std", "_int", "to_str");
|
||||
auto radix_expr = make_new_uint(arg.span, 10u);
|
||||
let vec[@ast.expr] args = vec(arg, radix_expr);
|
||||
ret make_call(arg.span, path, args);
|
||||
}
|
||||
case (unsigned) {
|
||||
let vec[str] path = vec("std", "_uint", "to_str");
|
||||
auto radix_expr = make_new_uint(arg.span, 10u);
|
||||
let vec[@ast.expr] args = vec(arg, radix_expr);
|
||||
ret make_call(arg.span, path, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
case (_) {
|
||||
log unsupported;
|
||||
fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn log_conv(conv c) {
|
||||
alt (c.param) {
|
||||
case (some[int](?p)) {
|
||||
log "param: " + std._int.to_str(p, 10u);
|
||||
}
|
||||
case (_) {
|
||||
log "param: none";
|
||||
}
|
||||
}
|
||||
for (flag f in c.flags) {
|
||||
alt (f) {
|
||||
case (flag_left_justify) {
|
||||
log "flag: left justify";
|
||||
}
|
||||
case (flag_left_zero_pad) {
|
||||
log "flag: left zero pad";
|
||||
}
|
||||
case (flag_left_space_pad) {
|
||||
log "flag: left space pad";
|
||||
}
|
||||
case (flag_plus_if_positive) {
|
||||
log "flag: plus if positive";
|
||||
}
|
||||
case (flag_alternate) {
|
||||
log "flag: alternate";
|
||||
}
|
||||
}
|
||||
}
|
||||
alt (c.width) {
|
||||
case (count_is(?i)) {
|
||||
log "width: count is " + std._int.to_str(i, 10u);
|
||||
}
|
||||
case (count_is_param(?i)) {
|
||||
log "width: count is param " + std._int.to_str(i, 10u);
|
||||
}
|
||||
case (count_is_next_param) {
|
||||
log "width: count is next param";
|
||||
}
|
||||
case (count_implied) {
|
||||
log "width: count is implied";
|
||||
}
|
||||
}
|
||||
alt (c.precision) {
|
||||
case (count_is(?i)) {
|
||||
log "prec: count is " + std._int.to_str(i, 10u);
|
||||
}
|
||||
case (count_is_param(?i)) {
|
||||
log "prec: count is param " + std._int.to_str(i, 10u);
|
||||
}
|
||||
case (count_is_next_param) {
|
||||
log "prec: count is next param";
|
||||
}
|
||||
case (count_implied) {
|
||||
log "prec: count is implied";
|
||||
}
|
||||
}
|
||||
alt (c.ty) {
|
||||
case (ty_bool) {
|
||||
log "type: bool";
|
||||
}
|
||||
case (ty_str) {
|
||||
log "type: str";
|
||||
}
|
||||
case (ty_char) {
|
||||
log "type: char";
|
||||
}
|
||||
case (ty_int(?s)) {
|
||||
alt (s) {
|
||||
case (signed) {
|
||||
log "type: signed";
|
||||
}
|
||||
case (unsigned) {
|
||||
log "type: unsigned";
|
||||
}
|
||||
}
|
||||
}
|
||||
case (ty_bits) {
|
||||
log "type: bits";
|
||||
}
|
||||
case (ty_hex(?cs)) {
|
||||
alt (cs) {
|
||||
case (case_upper) {
|
||||
log "type: uhex";
|
||||
}
|
||||
case (case_lower) {
|
||||
log "type: lhex";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto sp = args.(0).span;
|
||||
auto n = 0u;
|
||||
auto tmp_expr = make_new_str(sp, "");
|
||||
|
||||
for (piece p in pieces) {
|
||||
alt (p) {
|
||||
case (piece_string(?s)) {
|
||||
auto s_expr = make_new_str(sp, s);
|
||||
tmp_expr = make_add_expr(sp, tmp_expr, s_expr);
|
||||
}
|
||||
case (piece_conv(?conv)) {
|
||||
if (n >= _vec.len[@ast.expr](args)) {
|
||||
log "too many conversions in #fmt string";
|
||||
fail;
|
||||
}
|
||||
|
||||
// TODO: Remove debug logging
|
||||
// log "Building conversion:";
|
||||
// log_conv(conv);
|
||||
|
||||
n += 1u;
|
||||
auto arg_expr = args.(n);
|
||||
auto c_expr = make_new_conv(conv, arg_expr);
|
||||
tmp_expr = make_add_expr(sp, tmp_expr, c_expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove this debug logging
|
||||
// log "dumping expanded ast:";
|
||||
// log pretty.print_expr(tmp_expr);
|
||||
ret tmp_expr;
|
||||
}
|
||||
|
||||
//
|
||||
// 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:
|
||||
//
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import std._io.stdio_reader;
|
||||
import std.io.stdio_reader;
|
||||
import std._str;
|
||||
import std.map;
|
||||
import std.map.hashmap;
|
||||
|
|
@ -90,7 +90,6 @@ fn new_reader(stdio_reader rdr, str filename) -> reader
|
|||
}
|
||||
|
||||
auto keywords = new_str_hash[token.token]();
|
||||
auto reserved = new_str_hash[()]();
|
||||
|
||||
keywords.insert("mod", token.MOD);
|
||||
keywords.insert("use", token.USE);
|
||||
|
|
@ -191,6 +190,16 @@ fn new_reader(stdio_reader rdr, str filename) -> reader
|
|||
keywords.insert("f32", token.MACH(common.ty_f32));
|
||||
keywords.insert("f64", token.MACH(common.ty_f64));
|
||||
|
||||
auto reserved = new_str_hash[()]();
|
||||
|
||||
reserved.insert("f16", ()); // IEEE 754-2008 'binary16' interchange fmt
|
||||
reserved.insert("f80", ()); // IEEE 754-1985 'extended'
|
||||
reserved.insert("f128", ()); // IEEE 754-2008 'binary128'
|
||||
reserved.insert("m32", ()); // IEEE 754-2008 'decimal32'
|
||||
reserved.insert("m64", ()); // IEEE 754-2008 'decimal64'
|
||||
reserved.insert("m128", ()); // IEEE 754-2008 'decimal128'
|
||||
reserved.insert("dec", ()); // One of m32, m64, m128
|
||||
|
||||
ret reader(rdr, filename, rdr.getc() as char, rdr.getc() as char,
|
||||
1u, 0u, 1u, 0u, keywords, reserved);
|
||||
}
|
||||
|
|
@ -425,6 +434,12 @@ impure fn next_token(reader rdr) -> token.token {
|
|||
ret kwds.get(accum_str);
|
||||
}
|
||||
|
||||
auto rsvd = rdr.get_reserved();
|
||||
if (rsvd.contains_key(accum_str)) {
|
||||
log "reserved keyword";
|
||||
fail;
|
||||
}
|
||||
|
||||
ret token.IDENT(accum_str);
|
||||
}
|
||||
|
||||
|
|
@ -650,12 +665,9 @@ impure fn next_token(reader rdr) -> token.token {
|
|||
case ('%') {
|
||||
ret binop(rdr, token.PERCENT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
log "lexer stopping at ";
|
||||
log c;
|
||||
ret token.EOF;
|
||||
fail;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
87
src/comp/front/pretty.rs
Normal file
87
src/comp/front/pretty.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
import std._int;
|
||||
import std._str;
|
||||
import std._uint;
|
||||
import std._vec;
|
||||
|
||||
export print_expr;
|
||||
|
||||
// FIXME this is superseded by ../pretty/pprust.rs. can it be dropped?
|
||||
|
||||
fn unknown() -> str {
|
||||
ret "<unknown ast node>";
|
||||
}
|
||||
|
||||
fn print_expr(@ast.expr expr) -> str {
|
||||
alt (expr.node) {
|
||||
case (ast.expr_lit(?lit, _)) {
|
||||
ret print_lit(lit);
|
||||
}
|
||||
case (ast.expr_binary(?op, ?lhs, ?rhs, _)) {
|
||||
ret print_expr_binary(op, lhs, rhs);
|
||||
}
|
||||
case (ast.expr_call(?path, ?args, _)) {
|
||||
ret print_expr_call(path, args);
|
||||
}
|
||||
case (ast.expr_path(?path, _, _)) {
|
||||
ret print_path(path);
|
||||
}
|
||||
case (_) {
|
||||
ret unknown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_lit(@ast.lit lit) -> str {
|
||||
alt (lit.node) {
|
||||
case (ast.lit_str(?s)) {
|
||||
ret "\"" + s + "\"";
|
||||
}
|
||||
case (ast.lit_int(?i)) {
|
||||
ret _int.to_str(i, 10u);
|
||||
}
|
||||
case (ast.lit_uint(?u)) {
|
||||
ret _uint.to_str(u, 10u);
|
||||
}
|
||||
case (_) {
|
||||
ret unknown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_expr_binary(ast.binop op, @ast.expr lhs, @ast.expr rhs) -> str {
|
||||
alt (op) {
|
||||
case (ast.add) {
|
||||
auto l = print_expr(lhs);
|
||||
auto r = print_expr(rhs);
|
||||
ret l + " + " + r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_expr_call(@ast.expr path_expr, vec[@ast.expr] args) -> str {
|
||||
auto s = print_expr(path_expr);
|
||||
|
||||
s += "(";
|
||||
fn print_expr_ref(&@ast.expr e) -> str { ret print_expr(e); }
|
||||
auto mapfn = print_expr_ref;
|
||||
auto argstrs = _vec.map[@ast.expr, str](mapfn, args);
|
||||
s += _str.connect(argstrs, ", ");
|
||||
s += ")";
|
||||
|
||||
ret s;
|
||||
}
|
||||
|
||||
fn print_path(ast.path path) -> str {
|
||||
ret _str.connect(path.node.idents, ".");
|
||||
}
|
||||
|
||||
//
|
||||
// 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:
|
||||
//
|
||||
Loading…
Add table
Add a link
Reference in a new issue