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:
Brian Anderson 2011-03-07 21:21:01 -05:00
commit 9fc4db6b89
66 changed files with 8303 additions and 2468 deletions

View file

@ -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
View 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
View 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:
//

View file

@ -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
View 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:
//