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
|
|
@ -44,7 +44,8 @@ const int obj_field_vtbl = 0;
|
|||
const int obj_field_box = 1;
|
||||
|
||||
const int obj_body_elt_tydesc = 0;
|
||||
const int obj_body_elt_fields = 1;
|
||||
const int obj_body_elt_typarams = 1;
|
||||
const int obj_body_elt_fields = 2;
|
||||
|
||||
const int fn_field_code = 0;
|
||||
const int fn_field_box = 1;
|
||||
|
|
@ -59,6 +60,9 @@ const int worst_case_glue_call_args = 7;
|
|||
|
||||
const int n_upcall_glues = 7;
|
||||
|
||||
const int abi_x86_rustboot_cdecl = 1;
|
||||
const int abi_x86_rustc_fastcall = 2;
|
||||
|
||||
fn memcpy_glue_name() -> str {
|
||||
ret "rust_memcpy_glue";
|
||||
}
|
||||
|
|
@ -67,6 +71,10 @@ fn bzero_glue_name() -> str {
|
|||
ret "rust_bzero_glue";
|
||||
}
|
||||
|
||||
fn vec_append_glue_name() -> str {
|
||||
ret "rust_vec_append_glue";
|
||||
}
|
||||
|
||||
fn upcall_glue_name(int n) -> str {
|
||||
ret "rust_upcall_" + util.common.istr(n);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,20 +41,117 @@ fn store_esp_to_runtime_sp() -> vec[str] {
|
|||
ret vec("movl %esp, " + wstr(abi.task_field_runtime_sp) + "(%ecx)");
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a bit of glue-code. It should be emitted once per
|
||||
* compilation unit.
|
||||
*
|
||||
* - save regs on C stack
|
||||
* - align sp on a 16-byte boundary
|
||||
* - save sp to task.runtime_sp (runtime_sp is thus always aligned)
|
||||
* - load saved task sp (switch stack)
|
||||
* - restore saved task regs
|
||||
* - return to saved task pc
|
||||
*
|
||||
* Our incoming stack looks like this:
|
||||
*
|
||||
* *esp+4 = [arg1 ] = task ptr
|
||||
* *esp = [retpc ]
|
||||
*/
|
||||
|
||||
fn rust_activate_glue() -> vec[str] {
|
||||
ret vec("movl 4(%esp), %ecx # ecx = rust_task")
|
||||
+ save_callee_saves()
|
||||
+ store_esp_to_runtime_sp()
|
||||
+ load_esp_from_rust_sp()
|
||||
|
||||
// This 'add' instruction is a bit surprising.
|
||||
// See lengthy comment in boot/be/x86.ml activate_glue.
|
||||
/*
|
||||
* There are two paths we can arrive at this code from:
|
||||
*
|
||||
*
|
||||
* 1. We are activating a task for the first time. When we switch
|
||||
* into the task stack and 'ret' to its first instruction, we'll
|
||||
* start doing whatever the first instruction says. Probably
|
||||
* saving registers and starting to establish a frame. Harmless
|
||||
* stuff, doesn't look at task->rust_sp again except when it
|
||||
* clobbers it during a later upcall.
|
||||
*
|
||||
*
|
||||
* 2. We are resuming a task that was descheduled by the yield glue
|
||||
* below. When we switch into the task stack and 'ret', we'll be
|
||||
* ret'ing to a very particular instruction:
|
||||
*
|
||||
* "esp <- task->rust_sp"
|
||||
*
|
||||
* this is the first instruction we 'ret' to after this glue,
|
||||
* because it is the first instruction following *any* upcall,
|
||||
* and the task we are activating was descheduled mid-upcall.
|
||||
*
|
||||
* Unfortunately for us, we have already restored esp from
|
||||
* task->rust_sp and are about to eat the 5 words off the top of
|
||||
* it.
|
||||
*
|
||||
*
|
||||
* | ... | <-- where esp will be once we restore + ret, below,
|
||||
* | retpc | and where we'd *like* task->rust_sp to wind up.
|
||||
* | ebp |
|
||||
* | edi |
|
||||
* | esi |
|
||||
* | ebx | <-- current task->rust_sp == current esp
|
||||
*
|
||||
*
|
||||
* This is a problem. If we return to "esp <- task->rust_sp" it
|
||||
* will push esp back down by 5 words. This manifests as a rust
|
||||
* stack that grows by 5 words on each yield/reactivate. Not
|
||||
* good.
|
||||
*
|
||||
* So what we do here is just adjust task->rust_sp up 5 words as
|
||||
* well, to mirror the movement in esp we're about to
|
||||
* perform. That way the "esp <- task->rust_sp" we 'ret' to below
|
||||
* will be a no-op. Esp won't move, and the task's stack won't
|
||||
* grow.
|
||||
*/
|
||||
+ vec("addl $20, " + wstr(abi.task_field_rust_sp) + "(%ecx)")
|
||||
|
||||
|
||||
/*
|
||||
* In most cases, the function we're returning to (activating)
|
||||
* will have saved any caller-saves before it yielded via upcalling,
|
||||
* so no work to do here. With one exception: when we're initially
|
||||
* activating, the task needs to be in the fastcall 2nd parameter
|
||||
* expected by the rust main function. That's edx.
|
||||
*/
|
||||
+ vec("mov %ecx, %edx")
|
||||
|
||||
+ restore_callee_saves()
|
||||
+ vec("ret");
|
||||
}
|
||||
|
||||
/* More glue code, this time the 'bottom half' of yielding.
|
||||
*
|
||||
* We arrived here because an upcall decided to deschedule the
|
||||
* running task. So the upcall's return address got patched to the
|
||||
* first instruction of this glue code.
|
||||
*
|
||||
* When the upcall does 'ret' it will come here, and its esp will be
|
||||
* pointing to the last argument pushed on the C stack before making
|
||||
* the upcall: the 0th argument to the upcall, which is always the
|
||||
* task ptr performing the upcall. That's where we take over.
|
||||
*
|
||||
* Our goal is to complete the descheduling
|
||||
*
|
||||
* - Switch over to the task stack temporarily.
|
||||
*
|
||||
* - Save the task's callee-saves onto the task stack.
|
||||
* (the task is now 'descheduled', safe to set aside)
|
||||
*
|
||||
* - Switch *back* to the C stack.
|
||||
*
|
||||
* - Restore the C-stack callee-saves.
|
||||
*
|
||||
* - Return to the caller on the C stack that activated the task.
|
||||
*
|
||||
*/
|
||||
|
||||
fn rust_yield_glue() -> vec[str] {
|
||||
ret vec("movl 0(%esp), %ecx # ecx = rust_task")
|
||||
+ load_esp_from_rust_sp()
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import front.parser;
|
||||
import front.token;
|
||||
import front.eval;
|
||||
import middle.trans;
|
||||
import middle.resolve;
|
||||
import middle.typeck;
|
||||
|
|
@ -13,6 +14,30 @@ import std.option.none;
|
|||
import std._str;
|
||||
import std._vec;
|
||||
|
||||
fn default_environment(session.session sess,
|
||||
str argv0,
|
||||
str input) -> eval.env {
|
||||
|
||||
auto libc = "libc.so";
|
||||
alt (sess.get_targ_cfg().os) {
|
||||
case (session.os_win32) { libc = "msvcrt.dll"; }
|
||||
case (session.os_macos) { libc = "libc.dylib"; }
|
||||
case (session.os_linux) { libc = "libc.so.6"; }
|
||||
}
|
||||
|
||||
ret
|
||||
vec(
|
||||
// Target bindings.
|
||||
tup("target_os", eval.val_str(std.os.target_os())),
|
||||
tup("target_arch", eval.val_str("x86")),
|
||||
tup("target_libc", eval.val_str(libc)),
|
||||
|
||||
// Build bindings.
|
||||
tup("build_compiler", eval.val_str(argv0)),
|
||||
tup("build_input", eval.val_str(input))
|
||||
);
|
||||
}
|
||||
|
||||
impure fn parse_input(session.session sess,
|
||||
parser.parser p,
|
||||
str input) -> @front.ast.crate {
|
||||
|
|
@ -25,20 +50,30 @@ impure fn parse_input(session.session sess,
|
|||
fail;
|
||||
}
|
||||
|
||||
impure fn compile_input(session.session sess, str input, str output,
|
||||
impure fn compile_input(session.session sess,
|
||||
eval.env env,
|
||||
str input, str output,
|
||||
bool shared) {
|
||||
auto p = parser.new_parser(sess, 0, input);
|
||||
auto p = parser.new_parser(sess, env, 0, input);
|
||||
auto crate = parse_input(sess, p, input);
|
||||
crate = resolve.resolve_crate(sess, crate);
|
||||
crate = typeck.check_crate(sess, crate);
|
||||
trans.trans_crate(sess, crate, output, shared);
|
||||
}
|
||||
|
||||
impure fn pretty_print_input(session.session sess,
|
||||
eval.env env,
|
||||
str input) {
|
||||
auto p = front.parser.new_parser(sess, env, 0, input);
|
||||
auto crate = front.parser.parse_crate_from_source_file(p);
|
||||
pretty.pprust.print_ast(crate.node.module);
|
||||
}
|
||||
|
||||
fn warn_wrong_compiler() {
|
||||
log "This is the rust 'self-hosted' compiler.";
|
||||
log "The one written in rust.";
|
||||
log "It is currently incomplete.";
|
||||
log "You may want rustboot insteaad, the compiler next door.";
|
||||
log "You may want rustboot instead, the compiler next door.";
|
||||
}
|
||||
|
||||
fn usage(session.session sess, str argv0) {
|
||||
|
|
@ -48,6 +83,7 @@ fn usage(session.session sess, str argv0) {
|
|||
log " -o <filename> write output to <filename>";
|
||||
log " -nowarn suppress wrong-compiler warning";
|
||||
log " -shared compile a shared-library crate";
|
||||
log " -pp pretty-print the input instead of compiling";
|
||||
log " -h display this message";
|
||||
log "";
|
||||
log "";
|
||||
|
|
@ -74,6 +110,7 @@ impure fn main(vec[str] args) {
|
|||
let option.t[str] output_file = none[str];
|
||||
let bool do_warn = true;
|
||||
let bool shared = false;
|
||||
let bool pretty = false;
|
||||
|
||||
auto i = 1u;
|
||||
auto len = _vec.len[str](args);
|
||||
|
|
@ -86,24 +123,21 @@ impure fn main(vec[str] args) {
|
|||
do_warn = false;
|
||||
} else if (_str.eq(arg, "-shared")) {
|
||||
shared = true;
|
||||
} else {
|
||||
// FIXME: rust could use an elif construct.
|
||||
if (_str.eq(arg, "-o")) {
|
||||
if (i+1u < len) {
|
||||
output_file = some(args.(i+1u));
|
||||
i += 1u;
|
||||
} else {
|
||||
usage(sess, args.(0));
|
||||
sess.err("-o requires an argument");
|
||||
}
|
||||
} else if (_str.eq(arg, "-pp")) {
|
||||
pretty = true;
|
||||
} else if (_str.eq(arg, "-o")) {
|
||||
if (i+1u < len) {
|
||||
output_file = some(args.(i+1u));
|
||||
i += 1u;
|
||||
} else {
|
||||
if (_str.eq(arg, "-h")) {
|
||||
usage(sess, args.(0));
|
||||
} else {
|
||||
usage(sess, args.(0));
|
||||
sess.err("unrecognized option: " + arg);
|
||||
}
|
||||
usage(sess, args.(0));
|
||||
sess.err("-o requires an argument");
|
||||
}
|
||||
} else if (_str.eq(arg, "-h")) {
|
||||
usage(sess, args.(0));
|
||||
} else {
|
||||
usage(sess, args.(0));
|
||||
sess.err("unrecognized option: " + arg);
|
||||
}
|
||||
} else {
|
||||
alt (input_file) {
|
||||
|
|
@ -115,8 +149,6 @@ impure fn main(vec[str] args) {
|
|||
input_file = some[str](arg);
|
||||
}
|
||||
}
|
||||
// FIXME: dummy node to work around typestate mis-wiring bug.
|
||||
i = i;
|
||||
}
|
||||
i += 1u;
|
||||
}
|
||||
|
|
@ -131,23 +163,29 @@ impure fn main(vec[str] args) {
|
|||
sess.err("no input filename");
|
||||
}
|
||||
case (some[str](?ifile)) {
|
||||
alt (output_file) {
|
||||
case (none[str]) {
|
||||
let vec[str] parts = _str.split(ifile, '.' as u8);
|
||||
parts = _vec.pop[str](parts);
|
||||
parts += ".bc";
|
||||
auto ofile = _str.concat(parts);
|
||||
compile_input(sess, ifile, ofile, shared);
|
||||
}
|
||||
case (some[str](?ofile)) {
|
||||
compile_input(sess, ifile, ofile, shared);
|
||||
|
||||
auto env = default_environment(sess, args.(0), ifile);
|
||||
if (pretty) {
|
||||
pretty_print_input(sess, env, ifile);
|
||||
}
|
||||
else {
|
||||
alt (output_file) {
|
||||
case (none[str]) {
|
||||
let vec[str] parts = _str.split(ifile, '.' as u8);
|
||||
parts = _vec.pop[str](parts);
|
||||
parts += ".bc";
|
||||
auto ofile = _str.concat(parts);
|
||||
compile_input(sess, env, ifile, ofile, shared);
|
||||
}
|
||||
case (some[str](?ofile)) {
|
||||
compile_input(sess, env, ifile, ofile, shared);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
// fill-column: 78;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
//
|
||||
|
|
@ -76,6 +76,25 @@ const uint LLVMIntSLT = 40u;
|
|||
const uint LLVMIntSLE = 41u;
|
||||
|
||||
|
||||
// Consts for the LLVM RealPredicate type, pre-case to uint.
|
||||
// FIXME: as above.
|
||||
|
||||
const uint LLVMRealOEQ = 1u;
|
||||
const uint LLVMRealOGT = 2u;
|
||||
const uint LLVMRealOGE = 3u;
|
||||
const uint LLVMRealOLT = 4u;
|
||||
const uint LLVMRealOLE = 5u;
|
||||
const uint LLVMRealONE = 6u;
|
||||
|
||||
const uint LLVMRealORD = 7u;
|
||||
const uint LLVMRealUNO = 8u;
|
||||
const uint LLVMRealUEQ = 9u;
|
||||
const uint LLVMRealUGT = 10u;
|
||||
const uint LLVMRealUGE = 11u;
|
||||
const uint LLVMRealULT = 12u;
|
||||
const uint LLVMRealULE = 13u;
|
||||
const uint LLVMRealUNE = 14u;
|
||||
|
||||
native mod llvm = llvm_lib {
|
||||
|
||||
type ModuleRef;
|
||||
|
|
@ -657,7 +676,7 @@ native mod llvm = llvm_lib {
|
|||
fn LLVMBuildICmp(BuilderRef B, uint Op,
|
||||
ValueRef LHS, ValueRef RHS,
|
||||
sbuf Name) -> ValueRef;
|
||||
fn LLVMBuildFCmp(BuilderRef B, RealPredicate Op,
|
||||
fn LLVMBuildFCmp(BuilderRef B, uint Op,
|
||||
ValueRef LHS, ValueRef RHS,
|
||||
sbuf Name) -> ValueRef;
|
||||
|
||||
|
|
@ -1034,7 +1053,7 @@ obj builder(BuilderRef B) {
|
|||
ret llvm.LLVMBuildICmp(B, Op, LHS, RHS, _str.buf(""));
|
||||
}
|
||||
|
||||
fn FCmp(RealPredicate Op, ValueRef LHS, ValueRef RHS) -> ValueRef {
|
||||
fn FCmp(uint Op, ValueRef LHS, ValueRef RHS) -> ValueRef {
|
||||
ret llvm.LLVMBuildFCmp(B, Op, LHS, RHS, _str.buf(""));
|
||||
}
|
||||
|
||||
|
|
@ -1151,18 +1170,70 @@ fn mk_type_handle() -> type_handle {
|
|||
ret rec(llth=th, dtor=type_handle_dtor(th));
|
||||
}
|
||||
|
||||
fn type_to_str(TypeRef ty) -> str {
|
||||
let vec[TypeRef] v = vec();
|
||||
ret type_to_str_inner(v, ty);
|
||||
|
||||
state obj type_names(std.map.hashmap[TypeRef, str] type_names,
|
||||
std.map.hashmap[str, TypeRef] named_types) {
|
||||
|
||||
fn associate(str s, TypeRef t) {
|
||||
check (!named_types.contains_key(s));
|
||||
check (!type_names.contains_key(t));
|
||||
type_names.insert(t, s);
|
||||
named_types.insert(s, t);
|
||||
}
|
||||
|
||||
fn type_has_name(TypeRef t) -> bool {
|
||||
ret type_names.contains_key(t);
|
||||
}
|
||||
|
||||
fn get_name(TypeRef t) -> str {
|
||||
ret type_names.get(t);
|
||||
}
|
||||
|
||||
fn name_has_type(str s) -> bool {
|
||||
ret named_types.contains_key(s);
|
||||
}
|
||||
|
||||
fn get_type(str s) -> TypeRef {
|
||||
ret named_types.get(s);
|
||||
}
|
||||
}
|
||||
|
||||
fn type_to_str_inner(vec[TypeRef] outer0, TypeRef ty) -> str {
|
||||
fn mk_type_names() -> type_names {
|
||||
auto nt = util.common.new_str_hash[TypeRef]();
|
||||
|
||||
fn hash(&TypeRef t) -> uint {
|
||||
ret t as uint;
|
||||
}
|
||||
|
||||
fn eq(&TypeRef a, &TypeRef b) -> bool {
|
||||
ret (a as uint) == (b as uint);
|
||||
}
|
||||
|
||||
let std.map.hashfn[TypeRef] hasher = hash;
|
||||
let std.map.eqfn[TypeRef] eqer = eq;
|
||||
auto tn = std.map.mk_hashmap[TypeRef,str](hasher, eqer);
|
||||
|
||||
ret type_names(tn, nt);
|
||||
}
|
||||
|
||||
fn type_to_str(type_names names, TypeRef ty) -> str {
|
||||
let vec[TypeRef] v = vec();
|
||||
ret type_to_str_inner(names, v, ty);
|
||||
}
|
||||
|
||||
fn type_to_str_inner(type_names names,
|
||||
vec[TypeRef] outer0, TypeRef ty) -> str {
|
||||
|
||||
if (names.type_has_name(ty)) {
|
||||
ret names.get_name(ty);
|
||||
}
|
||||
|
||||
auto outer = outer0 + vec(ty);
|
||||
|
||||
let int kind = llvm.LLVMGetTypeKind(ty);
|
||||
|
||||
fn tys_str(vec[TypeRef] outer, vec[TypeRef] tys) -> str {
|
||||
fn tys_str(type_names names,
|
||||
vec[TypeRef] outer, vec[TypeRef] tys) -> str {
|
||||
let str s = "";
|
||||
let bool first = true;
|
||||
for (TypeRef t in tys) {
|
||||
|
|
@ -1171,7 +1242,7 @@ fn type_to_str_inner(vec[TypeRef] outer0, TypeRef ty) -> str {
|
|||
} else {
|
||||
s += ", ";
|
||||
}
|
||||
s += type_to_str_inner(outer, t);
|
||||
s += type_to_str_inner(names, outer, t);
|
||||
}
|
||||
ret s;
|
||||
}
|
||||
|
|
@ -1200,9 +1271,9 @@ fn type_to_str_inner(vec[TypeRef] outer0, TypeRef ty) -> str {
|
|||
let vec[TypeRef] args =
|
||||
_vec.init_elt[TypeRef](0 as TypeRef, n_args);
|
||||
llvm.LLVMGetParamTypes(ty, _vec.buf[TypeRef](args));
|
||||
s += tys_str(outer, args);
|
||||
s += tys_str(names, outer, args);
|
||||
s += ") -> ";
|
||||
s += type_to_str_inner(outer, out_ty);
|
||||
s += type_to_str_inner(names, outer, out_ty);
|
||||
ret s;
|
||||
}
|
||||
|
||||
|
|
@ -1212,7 +1283,7 @@ fn type_to_str_inner(vec[TypeRef] outer0, TypeRef ty) -> str {
|
|||
let vec[TypeRef] elts =
|
||||
_vec.init_elt[TypeRef](0 as TypeRef, n_elts);
|
||||
llvm.LLVMGetStructElementTypes(ty, _vec.buf[TypeRef](elts));
|
||||
s += tys_str(outer, elts);
|
||||
s += tys_str(names, outer, elts);
|
||||
s += "}";
|
||||
ret s;
|
||||
}
|
||||
|
|
@ -1228,7 +1299,8 @@ fn type_to_str_inner(vec[TypeRef] outer0, TypeRef ty) -> str {
|
|||
ret "*\\" + util.common.istr(n as int);
|
||||
}
|
||||
}
|
||||
ret "*" + type_to_str_inner(outer, llvm.LLVMGetElementType(ty));
|
||||
ret "*" + type_to_str_inner(names, outer,
|
||||
llvm.LLVMGetElementType(ty));
|
||||
}
|
||||
|
||||
case (12) { ret "Opaque"; }
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import util.common.ty_mach;
|
|||
import util.common.append;
|
||||
|
||||
import front.ast;
|
||||
import front.ast.fn_decl;
|
||||
import front.ast.ident;
|
||||
import front.ast.path;
|
||||
import front.ast.mutability;
|
||||
|
|
@ -20,6 +21,7 @@ import front.ast.block;
|
|||
import front.ast.item;
|
||||
import front.ast.view_item;
|
||||
import front.ast.meta_item;
|
||||
import front.ast.native_item;
|
||||
import front.ast.arg;
|
||||
import front.ast.pat;
|
||||
import front.ast.decl;
|
||||
|
|
@ -28,6 +30,7 @@ import front.ast.def;
|
|||
import front.ast.def_id;
|
||||
import front.ast.ann;
|
||||
|
||||
import std._uint;
|
||||
import std._vec;
|
||||
|
||||
type ast_fold[ENV] =
|
||||
|
|
@ -56,6 +59,7 @@ type ast_fold[ENV] =
|
|||
vec[ast.ty_method] meths) -> @ty) fold_ty_obj,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
ast.proto proto,
|
||||
vec[rec(ast.mode mode, @ty ty)] inputs,
|
||||
@ty output) -> @ty) fold_ty_fn,
|
||||
|
||||
|
|
@ -72,7 +76,8 @@ type ast_fold[ENV] =
|
|||
vec[ast.elt] es, ann a) -> @expr) fold_expr_tup,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
vec[ast.field] fields, ann a) -> @expr) fold_expr_rec,
|
||||
vec[ast.field] fields,
|
||||
option.t[@expr] base, ann a) -> @expr) fold_expr_rec,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
@expr f, vec[@expr] args,
|
||||
|
|
@ -107,6 +112,10 @@ type ast_fold[ENV] =
|
|||
@decl decl, @expr seq, &block body,
|
||||
ann a) -> @expr) fold_expr_for,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
@decl decl, @expr seq, &block body,
|
||||
ann a) -> @expr) fold_expr_for_each,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
@expr cond, &block body,
|
||||
ann a) -> @expr) fold_expr_while,
|
||||
|
|
@ -144,6 +153,29 @@ type ast_fold[ENV] =
|
|||
&option.t[def] d,
|
||||
ann a) -> @expr) fold_expr_path,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
&path p, vec[@expr] args,
|
||||
option.t[@expr] body,
|
||||
@expr expanded,
|
||||
ann a) -> @expr) fold_expr_ext,
|
||||
|
||||
(fn(&ENV e, &span sp) -> @expr) fold_expr_fail,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
&option.t[@expr] rv) -> @expr) fold_expr_ret,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
&option.t[@expr] rv) -> @expr) fold_expr_put,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
@expr e) -> @expr) fold_expr_be,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
@expr e) -> @expr) fold_expr_log,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
@expr e) -> @expr) fold_expr_check_expr,
|
||||
|
||||
// Decl folds.
|
||||
(fn(&ENV e, &span sp,
|
||||
@ast.local local) -> @decl) fold_decl_local,
|
||||
|
|
@ -156,6 +188,9 @@ type ast_fold[ENV] =
|
|||
(fn(&ENV e, &span sp,
|
||||
ann a) -> @pat) fold_pat_wild,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
@ast.lit lit, ann a) -> @pat) fold_pat_lit,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
ident i, def_id did, ann a) -> @pat) fold_pat_bind,
|
||||
|
||||
|
|
@ -169,15 +204,6 @@ type ast_fold[ENV] =
|
|||
(fn(&ENV e, &span sp,
|
||||
@decl decl) -> @stmt) fold_stmt_decl,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
&option.t[@expr] rv) -> @stmt) fold_stmt_ret,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
@expr e) -> @stmt) fold_stmt_log,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
@expr e) -> @stmt) fold_stmt_check_expr,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
@expr e) -> @stmt) fold_stmt_expr,
|
||||
|
||||
|
|
@ -191,13 +217,24 @@ type ast_fold[ENV] =
|
|||
vec[ast.ty_param] ty_params,
|
||||
def_id id, ann a) -> @item) fold_item_fn,
|
||||
|
||||
(fn(&ENV e, &span sp, ident ident,
|
||||
&ast.fn_decl decl,
|
||||
vec[ast.ty_param] ty_params,
|
||||
def_id id, ann a) -> @native_item) fold_native_item_fn,
|
||||
|
||||
(fn(&ENV e, &span sp, ident ident,
|
||||
&ast._mod m, def_id id) -> @item) fold_item_mod,
|
||||
|
||||
(fn(&ENV e, &span sp, ident ident,
|
||||
&ast.native_mod m, def_id id) -> @item) fold_item_native_mod,
|
||||
|
||||
(fn(&ENV e, &span sp, ident ident,
|
||||
@ty t, vec[ast.ty_param] ty_params,
|
||||
def_id id, ann a) -> @item) fold_item_ty,
|
||||
|
||||
(fn(&ENV e, &span sp, ident ident,
|
||||
def_id id) -> @native_item) fold_native_item_ty,
|
||||
|
||||
(fn(&ENV e, &span sp, ident ident,
|
||||
vec[ast.variant] variants,
|
||||
vec[ast.ty_param] ty_params,
|
||||
|
|
@ -220,23 +257,30 @@ type ast_fold[ENV] =
|
|||
(fn(&ENV e, &span sp,
|
||||
&ast.block_) -> block) fold_block,
|
||||
|
||||
(fn(&ENV e, &fn_decl decl,
|
||||
ast.proto proto,
|
||||
&block body) -> ast._fn) fold_fn,
|
||||
|
||||
(fn(&ENV e, ast.effect effect,
|
||||
bool is_iter,
|
||||
vec[arg] inputs,
|
||||
@ty output, &block body) -> ast._fn) fold_fn,
|
||||
@ty output) -> ast.fn_decl) fold_fn_decl,
|
||||
|
||||
(fn(&ENV e, &ast._mod m) -> ast._mod) fold_mod,
|
||||
|
||||
(fn(&ENV e, &ast.native_mod m) -> ast.native_mod) fold_native_mod,
|
||||
|
||||
(fn(&ENV e, &span sp,
|
||||
&ast._mod m) -> @ast.crate) fold_crate,
|
||||
|
||||
(fn(&ENV e,
|
||||
vec[ast.obj_field] fields,
|
||||
vec[@ast.method] methods) -> ast._obj) fold_obj,
|
||||
vec[@ast.method] methods,
|
||||
option.t[block] dtor) -> ast._obj) fold_obj,
|
||||
|
||||
// Env updates.
|
||||
(fn(&ENV e, @ast.crate c) -> ENV) update_env_for_crate,
|
||||
(fn(&ENV e, @item i) -> ENV) update_env_for_item,
|
||||
(fn(&ENV e, @native_item i) -> ENV) update_env_for_native_item,
|
||||
(fn(&ENV e, @view_item i) -> ENV) update_env_for_view_item,
|
||||
(fn(&ENV e, &block b) -> ENV) update_env_for_block,
|
||||
(fn(&ENV e, @stmt s) -> ENV) update_env_for_stmt,
|
||||
|
|
@ -312,11 +356,13 @@ fn fold_ty[ENV](&ENV env, ast_fold[ENV] fld, @ty t) -> @ty {
|
|||
case (ast.ty_obj(?meths)) {
|
||||
let vec[ast.ty_method] meths_ = vec();
|
||||
for (ast.ty_method m in meths) {
|
||||
auto tfn = fold_ty_fn(env_, fld, t.span, m.inputs, m.output);
|
||||
auto tfn = fold_ty_fn(env_, fld, t.span, m.proto,
|
||||
m.inputs, m.output);
|
||||
alt (tfn.node) {
|
||||
case (ast.ty_fn(?ins, ?out)) {
|
||||
case (ast.ty_fn(?p, ?ins, ?out)) {
|
||||
append[ast.ty_method]
|
||||
(meths_, rec(inputs=ins, output=out with m));
|
||||
(meths_, rec(proto=p, inputs=ins, output=out
|
||||
with m));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -333,13 +379,14 @@ fn fold_ty[ENV](&ENV env, ast_fold[ENV] fld, @ty t) -> @ty {
|
|||
ret fld.fold_ty_mutable(env_, t.span, ty_);
|
||||
}
|
||||
|
||||
case (ast.ty_fn(?inputs, ?output)) {
|
||||
ret fold_ty_fn(env_, fld, t.span, inputs, output);
|
||||
case (ast.ty_fn(?proto, ?inputs, ?output)) {
|
||||
ret fold_ty_fn(env_, fld, t.span, proto, inputs, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_ty_fn[ENV](&ENV env, ast_fold[ENV] fld, &span sp,
|
||||
ast.proto proto,
|
||||
vec[rec(ast.mode mode, @ty ty)] inputs,
|
||||
@ty output) -> @ty {
|
||||
auto output_ = fold_ty(env, fld, output);
|
||||
|
|
@ -349,7 +396,7 @@ fn fold_ty_fn[ENV](&ENV env, ast_fold[ENV] fld, &span sp,
|
|||
auto input_ = rec(ty=ty_ with input);
|
||||
inputs_ += vec(input_);
|
||||
}
|
||||
ret fld.fold_ty_fn(env, sp, inputs_, output_);
|
||||
ret fld.fold_ty_fn(env, sp, proto, inputs_, output_);
|
||||
}
|
||||
|
||||
fn fold_decl[ENV](&ENV env, ast_fold[ENV] fld, @decl d) -> @decl {
|
||||
|
|
@ -397,6 +444,9 @@ fn fold_pat[ENV](&ENV env, ast_fold[ENV] fld, @ast.pat p) -> @ast.pat {
|
|||
|
||||
alt (p.node) {
|
||||
case (ast.pat_wild(?t)) { ret fld.fold_pat_wild(env_, p.span, t); }
|
||||
case (ast.pat_lit(?lt, ?t)) {
|
||||
ret fld.fold_pat_lit(env_, p.span, lt, t);
|
||||
}
|
||||
case (ast.pat_bind(?id, ?did, ?t)) {
|
||||
ret fld.fold_pat_bind(env_, p.span, id, did, t);
|
||||
}
|
||||
|
|
@ -449,12 +499,19 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr {
|
|||
ret fld.fold_expr_tup(env_, e.span, elts, t);
|
||||
}
|
||||
|
||||
case (ast.expr_rec(?fs, ?t)) {
|
||||
case (ast.expr_rec(?fs, ?base, ?t)) {
|
||||
let vec[ast.field] fields = vec();
|
||||
let option.t[@expr] b = none[@expr];
|
||||
for (ast.field f in fs) {
|
||||
fields += fold_rec_field(env, fld, f);
|
||||
}
|
||||
ret fld.fold_expr_rec(env_, e.span, fields, t);
|
||||
alt (base) {
|
||||
case (none[@ast.expr]) { }
|
||||
case (some[@ast.expr](?eb)) {
|
||||
b = some[@expr](fold_expr(env_, fld, eb));
|
||||
}
|
||||
}
|
||||
ret fld.fold_expr_rec(env_, e.span, fields, b, t);
|
||||
}
|
||||
|
||||
case (ast.expr_call(?f, ?args, ?t)) {
|
||||
|
|
@ -521,6 +578,13 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr {
|
|||
ret fld.fold_expr_for(env_, e.span, ddecl, sseq, bbody, t);
|
||||
}
|
||||
|
||||
case (ast.expr_for_each(?decl, ?seq, ?body, ?t)) {
|
||||
auto ddecl = fold_decl(env_, fld, decl);
|
||||
auto sseq = fold_expr(env_, fld, seq);
|
||||
auto bbody = fold_block(env_, fld, body);
|
||||
ret fld.fold_expr_for_each(env_, e.span, ddecl, sseq, bbody, t);
|
||||
}
|
||||
|
||||
case (ast.expr_while(?cnd, ?body, ?t)) {
|
||||
auto ccnd = fold_expr(env_, fld, cnd);
|
||||
auto bbody = fold_block(env_, fld, body);
|
||||
|
|
@ -574,9 +638,59 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr {
|
|||
auto p_ = fold_path(env_, fld, p);
|
||||
ret fld.fold_expr_path(env_, e.span, p_, r, t);
|
||||
}
|
||||
|
||||
case (ast.expr_ext(?p, ?args, ?body, ?expanded, ?t)) {
|
||||
// Only fold the expanded expression, not the
|
||||
// expressions involved in syntax extension
|
||||
auto exp = fold_expr(env_, fld, expanded);
|
||||
ret fld.fold_expr_ext(env_, e.span, p, args, body,
|
||||
exp, t);
|
||||
}
|
||||
|
||||
case (ast.expr_fail) {
|
||||
ret fld.fold_expr_fail(env_, e.span);
|
||||
}
|
||||
|
||||
case (ast.expr_ret(?oe)) {
|
||||
auto oee = none[@expr];
|
||||
alt (oe) {
|
||||
case (some[@expr](?x)) {
|
||||
oee = some(fold_expr(env_, fld, x));
|
||||
}
|
||||
case (_) { /* fall through */ }
|
||||
}
|
||||
ret fld.fold_expr_ret(env_, e.span, oee);
|
||||
}
|
||||
|
||||
case (ast.expr_put(?oe)) {
|
||||
auto oee = none[@expr];
|
||||
alt (oe) {
|
||||
case (some[@expr](?x)) {
|
||||
oee = some(fold_expr(env_, fld, x));
|
||||
}
|
||||
case (_) { /* fall through */ }
|
||||
}
|
||||
ret fld.fold_expr_put(env_, e.span, oee);
|
||||
}
|
||||
|
||||
case (ast.expr_be(?x)) {
|
||||
auto ee = fold_expr(env_, fld, x);
|
||||
ret fld.fold_expr_be(env_, e.span, ee);
|
||||
}
|
||||
|
||||
case (ast.expr_log(?x)) {
|
||||
auto ee = fold_expr(env_, fld, x);
|
||||
ret fld.fold_expr_log(env_, e.span, ee);
|
||||
}
|
||||
|
||||
case (ast.expr_check_expr(?x)) {
|
||||
auto ee = fold_expr(env_, fld, x);
|
||||
ret fld.fold_expr_check_expr(env_, e.span, ee);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ret e;
|
||||
fail;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -594,37 +708,12 @@ fn fold_stmt[ENV](&ENV env, ast_fold[ENV] fld, &@stmt s) -> @stmt {
|
|||
ret fld.fold_stmt_decl(env_, s.span, dd);
|
||||
}
|
||||
|
||||
case (ast.stmt_ret(?oe)) {
|
||||
auto oee = none[@expr];
|
||||
alt (oe) {
|
||||
case (some[@expr](?e)) {
|
||||
oee = some(fold_expr(env_, fld, e));
|
||||
}
|
||||
case (_) { /* fall through */ }
|
||||
}
|
||||
ret fld.fold_stmt_ret(env_, s.span, oee);
|
||||
}
|
||||
|
||||
case (ast.stmt_log(?e)) {
|
||||
auto ee = fold_expr(env_, fld, e);
|
||||
ret fld.fold_stmt_log(env_, s.span, ee);
|
||||
}
|
||||
|
||||
case (ast.stmt_check_expr(?e)) {
|
||||
auto ee = fold_expr(env_, fld, e);
|
||||
ret fld.fold_stmt_check_expr(env_, s.span, ee);
|
||||
}
|
||||
|
||||
case (ast.stmt_fail) {
|
||||
ret s;
|
||||
}
|
||||
|
||||
case (ast.stmt_expr(?e)) {
|
||||
auto ee = fold_expr(env_, fld, e);
|
||||
ret fld.fold_stmt_expr(env_, s.span, ee);
|
||||
}
|
||||
}
|
||||
ret s;
|
||||
fail;
|
||||
}
|
||||
|
||||
fn fold_block[ENV](&ENV env, ast_fold[ENV] fld, &block blk) -> block {
|
||||
|
|
@ -666,17 +755,22 @@ fn fold_arg[ENV](&ENV env, ast_fold[ENV] fld, &arg a) -> arg {
|
|||
ret rec(ty=ty with a);
|
||||
}
|
||||
|
||||
|
||||
fn fold_fn[ENV](&ENV env, ast_fold[ENV] fld, &ast._fn f) -> ast._fn {
|
||||
|
||||
fn fold_fn_decl[ENV](&ENV env, ast_fold[ENV] fld,
|
||||
&ast.fn_decl decl) -> ast.fn_decl {
|
||||
let vec[ast.arg] inputs = vec();
|
||||
for (ast.arg a in f.inputs) {
|
||||
for (ast.arg a in decl.inputs) {
|
||||
inputs += fold_arg(env, fld, a);
|
||||
}
|
||||
auto output = fold_ty[ENV](env, fld, f.output);
|
||||
auto output = fold_ty[ENV](env, fld, decl.output);
|
||||
ret fld.fold_fn_decl(env, decl.effect, inputs, output);
|
||||
}
|
||||
|
||||
fn fold_fn[ENV](&ENV env, ast_fold[ENV] fld, &ast._fn f) -> ast._fn {
|
||||
auto decl = fold_fn_decl(env, fld, f.decl);
|
||||
|
||||
auto body = fold_block[ENV](env, fld, f.body);
|
||||
|
||||
ret fld.fold_fn(env, f.effect, f.is_iter, inputs, output, body);
|
||||
ret fld.fold_fn(env, decl, f.proto, body);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -701,6 +795,13 @@ fn fold_obj[ENV](&ENV env, ast_fold[ENV] fld, &ast._obj ob) -> ast._obj {
|
|||
for (ast.obj_field f in ob.fields) {
|
||||
fields += fold_obj_field(env, fld, f);
|
||||
}
|
||||
let option.t[block] dtor = none[block];
|
||||
alt (ob.dtor) {
|
||||
case (none[block]) { }
|
||||
case (some[block](?b)) {
|
||||
dtor = some[block](fold_block[ENV](env, fld, b));
|
||||
}
|
||||
}
|
||||
let vec[ast.ty_param] tp = vec();
|
||||
for (@ast.method m in ob.methods) {
|
||||
// Fake-up an ast.item for this method.
|
||||
|
|
@ -715,7 +816,7 @@ fn fold_obj[ENV](&ENV env, ast_fold[ENV] fld, &ast._obj ob) -> ast._obj {
|
|||
let ENV _env = fld.update_env_for_item(env, i);
|
||||
append[@ast.method](meths, fold_method(_env, fld, m));
|
||||
}
|
||||
ret fld.fold_obj(env, fields, meths);
|
||||
ret fld.fold_obj(env, fields, meths, dtor);
|
||||
}
|
||||
|
||||
fn fold_view_item[ENV](&ENV env, ast_fold[ENV] fld, @view_item vi)
|
||||
|
|
@ -768,6 +869,11 @@ fn fold_item[ENV](&ENV env, ast_fold[ENV] fld, @item i) -> @item {
|
|||
ret fld.fold_item_mod(env_, i.span, ident, mm_, id);
|
||||
}
|
||||
|
||||
case (ast.item_native_mod(?ident, ?mm, ?id)) {
|
||||
let ast.native_mod mm_ = fold_native_mod[ENV](env_, fld, mm);
|
||||
ret fld.fold_item_native_mod(env_, i.span, ident, mm_, id);
|
||||
}
|
||||
|
||||
case (ast.item_ty(?ident, ?ty, ?params, ?id, ?ann)) {
|
||||
let @ast.ty ty_ = fold_ty[ENV](env_, fld, ty);
|
||||
ret fld.fold_item_ty(env_, i.span, ident, ty_, params, id, ann);
|
||||
|
|
@ -798,7 +904,6 @@ fn fold_item[ENV](&ENV env, ast_fold[ENV] fld, @item i) -> @item {
|
|||
fail;
|
||||
}
|
||||
|
||||
|
||||
fn fold_mod[ENV](&ENV e, ast_fold[ENV] fld, &ast._mod m) -> ast._mod {
|
||||
|
||||
let vec[@view_item] view_items = vec();
|
||||
|
|
@ -818,7 +923,50 @@ fn fold_mod[ENV](&ENV e, ast_fold[ENV] fld, &ast._mod m) -> ast._mod {
|
|||
}
|
||||
|
||||
ret fld.fold_mod(e, rec(view_items=view_items, items=items, index=index));
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_native_item[ENV](&ENV env, ast_fold[ENV] fld,
|
||||
@native_item i) -> @native_item {
|
||||
let ENV env_ = fld.update_env_for_native_item(env, i);
|
||||
|
||||
if (!fld.keep_going(env_)) {
|
||||
ret i;
|
||||
}
|
||||
alt (i.node) {
|
||||
case (ast.native_item_ty(?ident, ?id)) {
|
||||
ret fld.fold_native_item_ty(env_, i.span, ident, id);
|
||||
}
|
||||
case (ast.native_item_fn(?ident, ?fn_decl, ?ty_params, ?id, ?ann)) {
|
||||
auto d = fold_fn_decl[ENV](env_, fld, fn_decl);
|
||||
ret fld.fold_native_item_fn(env_, i.span, ident, d,
|
||||
ty_params, id, ann);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_native_mod[ENV](&ENV e, ast_fold[ENV] fld,
|
||||
&ast.native_mod m) -> ast.native_mod {
|
||||
let vec[@view_item] view_items = vec();
|
||||
let vec[@native_item] items = vec();
|
||||
auto index = new_str_hash[ast.native_mod_index_entry]();
|
||||
|
||||
for (@view_item vi in m.view_items) {
|
||||
auto new_vi = fold_view_item[ENV](e, fld, vi);
|
||||
append[@view_item](view_items, new_vi);
|
||||
}
|
||||
|
||||
for (@native_item i in m.items) {
|
||||
auto new_item = fold_native_item[ENV](e, fld, i);
|
||||
append[@native_item](items, new_item);
|
||||
ast.index_native_item(index, new_item);
|
||||
}
|
||||
|
||||
ret fld.fold_native_mod(e, rec(native_name=m.native_name,
|
||||
abi=m.abi,
|
||||
view_items=view_items,
|
||||
items=items,
|
||||
index=index));
|
||||
}
|
||||
|
||||
fn fold_crate[ENV](&ENV env, ast_fold[ENV] fld, @ast.crate c) -> @ast.crate {
|
||||
let ENV env_ = fld.update_env_for_crate(env, c);
|
||||
|
|
@ -894,9 +1042,10 @@ fn identity_fold_ty_obj[ENV](&ENV env, &span sp,
|
|||
}
|
||||
|
||||
fn identity_fold_ty_fn[ENV](&ENV env, &span sp,
|
||||
ast.proto proto,
|
||||
vec[rec(ast.mode mode, @ty ty)] inputs,
|
||||
@ty output) -> @ty {
|
||||
ret @respan(sp, ast.ty_fn(inputs, output));
|
||||
ret @respan(sp, ast.ty_fn(proto, inputs, output));
|
||||
}
|
||||
|
||||
fn identity_fold_ty_path[ENV](&ENV env, &span sp, ast.path p,
|
||||
|
|
@ -922,8 +1071,9 @@ fn identity_fold_expr_tup[ENV](&ENV env, &span sp,
|
|||
}
|
||||
|
||||
fn identity_fold_expr_rec[ENV](&ENV env, &span sp,
|
||||
vec[ast.field] fields, ann a) -> @expr {
|
||||
ret @respan(sp, ast.expr_rec(fields, a));
|
||||
vec[ast.field] fields,
|
||||
option.t[@expr] base, ann a) -> @expr {
|
||||
ret @respan(sp, ast.expr_rec(fields, base, a));
|
||||
}
|
||||
|
||||
fn identity_fold_expr_call[ENV](&ENV env, &span sp, @expr f,
|
||||
|
|
@ -971,6 +1121,12 @@ fn identity_fold_expr_for[ENV](&ENV env, &span sp,
|
|||
ret @respan(sp, ast.expr_for(d, seq, body, a));
|
||||
}
|
||||
|
||||
fn identity_fold_expr_for_each[ENV](&ENV env, &span sp,
|
||||
@decl d, @expr seq,
|
||||
&block body, ann a) -> @expr {
|
||||
ret @respan(sp, ast.expr_for_each(d, seq, body, a));
|
||||
}
|
||||
|
||||
fn identity_fold_expr_while[ENV](&ENV env, &span sp,
|
||||
@expr cond, &block body, ann a) -> @expr {
|
||||
ret @respan(sp, ast.expr_while(cond, body, a));
|
||||
|
|
@ -1019,6 +1175,40 @@ fn identity_fold_expr_path[ENV](&ENV env, &span sp,
|
|||
ret @respan(sp, ast.expr_path(p, d, a));
|
||||
}
|
||||
|
||||
fn identity_fold_expr_ext[ENV](&ENV env, &span sp,
|
||||
&path p, vec[@expr] args,
|
||||
option.t[@expr] body,
|
||||
@expr expanded,
|
||||
ann a) -> @expr {
|
||||
ret @respan(sp, ast.expr_ext(p, args, body, expanded, a));
|
||||
}
|
||||
|
||||
fn identity_fold_expr_fail[ENV](&ENV env, &span sp) -> @expr {
|
||||
ret @respan(sp, ast.expr_fail);
|
||||
}
|
||||
|
||||
fn identity_fold_expr_ret[ENV](&ENV env, &span sp,
|
||||
&option.t[@expr] rv) -> @expr {
|
||||
ret @respan(sp, ast.expr_ret(rv));
|
||||
}
|
||||
|
||||
fn identity_fold_expr_put[ENV](&ENV env, &span sp,
|
||||
&option.t[@expr] rv) -> @expr {
|
||||
ret @respan(sp, ast.expr_put(rv));
|
||||
}
|
||||
|
||||
fn identity_fold_expr_be[ENV](&ENV env, &span sp, @expr x) -> @expr {
|
||||
ret @respan(sp, ast.expr_be(x));
|
||||
}
|
||||
|
||||
fn identity_fold_expr_log[ENV](&ENV e, &span sp, @expr x) -> @expr {
|
||||
ret @respan(sp, ast.expr_log(x));
|
||||
}
|
||||
|
||||
fn identity_fold_expr_check_expr[ENV](&ENV e, &span sp, @expr x) -> @expr {
|
||||
ret @respan(sp, ast.expr_check_expr(x));
|
||||
}
|
||||
|
||||
|
||||
// Decl identities.
|
||||
|
||||
|
|
@ -1038,6 +1228,10 @@ fn identity_fold_pat_wild[ENV](&ENV e, &span sp, ann a) -> @pat {
|
|||
ret @respan(sp, ast.pat_wild(a));
|
||||
}
|
||||
|
||||
fn identity_fold_pat_lit[ENV](&ENV e, &span sp, @ast.lit lit, ann a) -> @pat {
|
||||
ret @respan(sp, ast.pat_lit(lit, a));
|
||||
}
|
||||
|
||||
fn identity_fold_pat_bind[ENV](&ENV e, &span sp, ident i, def_id did, ann a)
|
||||
-> @pat {
|
||||
ret @respan(sp, ast.pat_bind(i, did, a));
|
||||
|
|
@ -1055,19 +1249,6 @@ fn identity_fold_stmt_decl[ENV](&ENV env, &span sp, @decl d) -> @stmt {
|
|||
ret @respan(sp, ast.stmt_decl(d));
|
||||
}
|
||||
|
||||
fn identity_fold_stmt_ret[ENV](&ENV env, &span sp,
|
||||
&option.t[@expr] rv) -> @stmt {
|
||||
ret @respan(sp, ast.stmt_ret(rv));
|
||||
}
|
||||
|
||||
fn identity_fold_stmt_log[ENV](&ENV e, &span sp, @expr x) -> @stmt {
|
||||
ret @respan(sp, ast.stmt_log(x));
|
||||
}
|
||||
|
||||
fn identity_fold_stmt_check_expr[ENV](&ENV e, &span sp, @expr x) -> @stmt {
|
||||
ret @respan(sp, ast.stmt_check_expr(x));
|
||||
}
|
||||
|
||||
fn identity_fold_stmt_expr[ENV](&ENV e, &span sp, @expr x) -> @stmt {
|
||||
ret @respan(sp, ast.stmt_expr(x));
|
||||
}
|
||||
|
|
@ -1087,17 +1268,34 @@ fn identity_fold_item_fn[ENV](&ENV e, &span sp, ident i,
|
|||
ret @respan(sp, ast.item_fn(i, f, ty_params, id, a));
|
||||
}
|
||||
|
||||
fn identity_fold_native_item_fn[ENV](&ENV e, &span sp, ident i,
|
||||
&ast.fn_decl decl,
|
||||
vec[ast.ty_param] ty_params,
|
||||
def_id id, ann a) -> @native_item {
|
||||
ret @respan(sp, ast.native_item_fn(i, decl, ty_params, id, a));
|
||||
}
|
||||
|
||||
fn identity_fold_item_mod[ENV](&ENV e, &span sp, ident i,
|
||||
&ast._mod m, def_id id) -> @item {
|
||||
ret @respan(sp, ast.item_mod(i, m, id));
|
||||
}
|
||||
|
||||
fn identity_fold_item_native_mod[ENV](&ENV e, &span sp, ident i,
|
||||
&ast.native_mod m, def_id id) -> @item {
|
||||
ret @respan(sp, ast.item_native_mod(i, m, id));
|
||||
}
|
||||
|
||||
fn identity_fold_item_ty[ENV](&ENV e, &span sp, ident i,
|
||||
@ty t, vec[ast.ty_param] ty_params,
|
||||
def_id id, ann a) -> @item {
|
||||
ret @respan(sp, ast.item_ty(i, t, ty_params, id, a));
|
||||
}
|
||||
|
||||
fn identity_fold_native_item_ty[ENV](&ENV e, &span sp, ident i,
|
||||
def_id id) -> @native_item {
|
||||
ret @respan(sp, ast.native_item_ty(i, id));
|
||||
}
|
||||
|
||||
fn identity_fold_item_tag[ENV](&ENV e, &span sp, ident i,
|
||||
vec[ast.variant] variants,
|
||||
vec[ast.ty_param] ty_params,
|
||||
|
|
@ -1132,28 +1330,38 @@ fn identity_fold_block[ENV](&ENV e, &span sp, &ast.block_ blk) -> block {
|
|||
ret respan(sp, blk);
|
||||
}
|
||||
|
||||
fn identity_fold_fn_decl[ENV](&ENV e,
|
||||
ast.effect effect,
|
||||
vec[arg] inputs,
|
||||
@ty output) -> ast.fn_decl {
|
||||
ret rec(effect=effect, inputs=inputs, output=output);
|
||||
}
|
||||
|
||||
fn identity_fold_fn[ENV](&ENV e,
|
||||
ast.effect effect,
|
||||
bool is_iter,
|
||||
vec[arg] inputs,
|
||||
@ast.ty output,
|
||||
&fn_decl decl,
|
||||
ast.proto proto,
|
||||
&block body) -> ast._fn {
|
||||
ret rec(effect=effect, is_iter=is_iter, inputs=inputs,
|
||||
output=output, body=body);
|
||||
ret rec(decl=decl, proto=proto, body=body);
|
||||
}
|
||||
|
||||
fn identity_fold_mod[ENV](&ENV e, &ast._mod m) -> ast._mod {
|
||||
ret m;
|
||||
}
|
||||
|
||||
fn identity_fold_native_mod[ENV](&ENV e,
|
||||
&ast.native_mod m) -> ast.native_mod {
|
||||
ret m;
|
||||
}
|
||||
|
||||
fn identity_fold_crate[ENV](&ENV e, &span sp, &ast._mod m) -> @ast.crate {
|
||||
ret @respan(sp, rec(module=m));
|
||||
}
|
||||
|
||||
fn identity_fold_obj[ENV](&ENV e,
|
||||
vec[ast.obj_field] fields,
|
||||
vec[@ast.method] methods) -> ast._obj {
|
||||
ret rec(fields=fields, methods=methods);
|
||||
vec[@ast.method] methods,
|
||||
option.t[block] dtor) -> ast._obj {
|
||||
ret rec(fields=fields, methods=methods, dtor=dtor);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1167,6 +1375,10 @@ fn identity_update_env_for_item[ENV](&ENV e, @item i) -> ENV {
|
|||
ret e;
|
||||
}
|
||||
|
||||
fn identity_update_env_for_native_item[ENV](&ENV e, @native_item i) -> ENV {
|
||||
ret e;
|
||||
}
|
||||
|
||||
fn identity_update_env_for_view_item[ENV](&ENV e, @view_item i) -> ENV {
|
||||
ret e;
|
||||
}
|
||||
|
|
@ -1224,13 +1436,13 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
|
|||
fold_ty_tup = bind identity_fold_ty_tup[ENV](_,_,_),
|
||||
fold_ty_rec = bind identity_fold_ty_rec[ENV](_,_,_),
|
||||
fold_ty_obj = bind identity_fold_ty_obj[ENV](_,_,_),
|
||||
fold_ty_fn = bind identity_fold_ty_fn[ENV](_,_,_,_),
|
||||
fold_ty_fn = bind identity_fold_ty_fn[ENV](_,_,_,_,_),
|
||||
fold_ty_path = bind identity_fold_ty_path[ENV](_,_,_,_),
|
||||
fold_ty_mutable = bind identity_fold_ty_mutable[ENV](_,_,_),
|
||||
|
||||
fold_expr_vec = bind identity_fold_expr_vec[ENV](_,_,_,_),
|
||||
fold_expr_tup = bind identity_fold_expr_tup[ENV](_,_,_,_),
|
||||
fold_expr_rec = bind identity_fold_expr_rec[ENV](_,_,_,_),
|
||||
fold_expr_rec = bind identity_fold_expr_rec[ENV](_,_,_,_,_),
|
||||
fold_expr_call = bind identity_fold_expr_call[ENV](_,_,_,_,_),
|
||||
fold_expr_bind = bind identity_fold_expr_bind[ENV](_,_,_,_,_),
|
||||
fold_expr_binary = bind identity_fold_expr_binary[ENV](_,_,_,_,_,_),
|
||||
|
|
@ -1239,6 +1451,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
|
|||
fold_expr_cast = bind identity_fold_expr_cast[ENV](_,_,_,_,_),
|
||||
fold_expr_if = bind identity_fold_expr_if[ENV](_,_,_,_,_,_),
|
||||
fold_expr_for = bind identity_fold_expr_for[ENV](_,_,_,_,_,_),
|
||||
fold_expr_for_each
|
||||
= bind identity_fold_expr_for_each[ENV](_,_,_,_,_,_),
|
||||
fold_expr_while = bind identity_fold_expr_while[ENV](_,_,_,_,_),
|
||||
fold_expr_do_while
|
||||
= bind identity_fold_expr_do_while[ENV](_,_,_,_,_),
|
||||
|
|
@ -1250,25 +1464,36 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
|
|||
fold_expr_field = bind identity_fold_expr_field[ENV](_,_,_,_,_),
|
||||
fold_expr_index = bind identity_fold_expr_index[ENV](_,_,_,_,_),
|
||||
fold_expr_path = bind identity_fold_expr_path[ENV](_,_,_,_,_),
|
||||
fold_expr_ext = bind identity_fold_expr_ext[ENV](_,_,_,_,_,_,_),
|
||||
fold_expr_fail = bind identity_fold_expr_fail[ENV](_,_),
|
||||
fold_expr_ret = bind identity_fold_expr_ret[ENV](_,_,_),
|
||||
fold_expr_put = bind identity_fold_expr_put[ENV](_,_,_),
|
||||
fold_expr_be = bind identity_fold_expr_be[ENV](_,_,_),
|
||||
fold_expr_log = bind identity_fold_expr_log[ENV](_,_,_),
|
||||
fold_expr_check_expr
|
||||
= bind identity_fold_expr_check_expr[ENV](_,_,_),
|
||||
|
||||
fold_decl_local = bind identity_fold_decl_local[ENV](_,_,_),
|
||||
fold_decl_item = bind identity_fold_decl_item[ENV](_,_,_),
|
||||
|
||||
fold_pat_wild = bind identity_fold_pat_wild[ENV](_,_,_),
|
||||
fold_pat_lit = bind identity_fold_pat_lit[ENV](_,_,_,_),
|
||||
fold_pat_bind = bind identity_fold_pat_bind[ENV](_,_,_,_,_),
|
||||
fold_pat_tag = bind identity_fold_pat_tag[ENV](_,_,_,_,_,_),
|
||||
|
||||
fold_stmt_decl = bind identity_fold_stmt_decl[ENV](_,_,_),
|
||||
fold_stmt_ret = bind identity_fold_stmt_ret[ENV](_,_,_),
|
||||
fold_stmt_log = bind identity_fold_stmt_log[ENV](_,_,_),
|
||||
fold_stmt_check_expr
|
||||
= bind identity_fold_stmt_check_expr[ENV](_,_,_),
|
||||
fold_stmt_expr = bind identity_fold_stmt_expr[ENV](_,_,_),
|
||||
|
||||
fold_item_const= bind identity_fold_item_const[ENV](_,_,_,_,_,_,_),
|
||||
fold_item_fn = bind identity_fold_item_fn[ENV](_,_,_,_,_,_,_),
|
||||
fold_native_item_fn =
|
||||
bind identity_fold_native_item_fn[ENV](_,_,_,_,_,_,_),
|
||||
fold_item_mod = bind identity_fold_item_mod[ENV](_,_,_,_,_),
|
||||
fold_item_native_mod =
|
||||
bind identity_fold_item_native_mod[ENV](_,_,_,_,_),
|
||||
fold_item_ty = bind identity_fold_item_ty[ENV](_,_,_,_,_,_,_),
|
||||
fold_native_item_ty =
|
||||
bind identity_fold_native_item_ty[ENV](_,_,_,_),
|
||||
fold_item_tag = bind identity_fold_item_tag[ENV](_,_,_,_,_,_),
|
||||
fold_item_obj = bind identity_fold_item_obj[ENV](_,_,_,_,_,_,_),
|
||||
|
||||
|
|
@ -1278,13 +1503,17 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
|
|||
bind identity_fold_view_item_import[ENV](_,_,_,_,_,_),
|
||||
|
||||
fold_block = bind identity_fold_block[ENV](_,_,_),
|
||||
fold_fn = bind identity_fold_fn[ENV](_,_,_,_,_,_),
|
||||
fold_fn = bind identity_fold_fn[ENV](_,_,_,_),
|
||||
fold_fn_decl = bind identity_fold_fn_decl[ENV](_,_,_,_),
|
||||
fold_mod = bind identity_fold_mod[ENV](_,_),
|
||||
fold_native_mod = bind identity_fold_native_mod[ENV](_,_),
|
||||
fold_crate = bind identity_fold_crate[ENV](_,_,_),
|
||||
fold_obj = bind identity_fold_obj[ENV](_,_,_),
|
||||
fold_obj = bind identity_fold_obj[ENV](_,_,_,_),
|
||||
|
||||
update_env_for_crate = bind identity_update_env_for_crate[ENV](_,_),
|
||||
update_env_for_item = bind identity_update_env_for_item[ENV](_,_),
|
||||
update_env_for_native_item =
|
||||
bind identity_update_env_for_native_item[ENV](_,_),
|
||||
update_env_for_view_item =
|
||||
bind identity_update_env_for_view_item[ENV](_,_),
|
||||
update_env_for_block = bind identity_update_env_for_block[ENV](_,_),
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import std._vec;
|
|||
tag scope {
|
||||
scope_crate(@ast.crate);
|
||||
scope_item(@ast.item);
|
||||
scope_native_item(@ast.native_item);
|
||||
scope_loop(@ast.decl); // there's only 1 decl per loop.
|
||||
scope_block(ast.block);
|
||||
scope_arm(ast.arm);
|
||||
|
|
@ -34,6 +35,7 @@ tag def_wrap {
|
|||
def_wrap_use(@ast.view_item);
|
||||
def_wrap_import(@ast.view_item);
|
||||
def_wrap_mod(@ast.item);
|
||||
def_wrap_native_mod(@ast.item);
|
||||
def_wrap_other(def);
|
||||
def_wrap_expr_field(uint, def);
|
||||
def_wrap_resolving;
|
||||
|
|
@ -103,6 +105,29 @@ fn find_final_def(&env e, import_map index,
|
|||
// should return what a.b.c.d points to in the end.
|
||||
fn found_something(&env e, import_map index,
|
||||
&span sp, vec[ident] idents, def_wrap d) -> def_wrap {
|
||||
|
||||
fn found_mod(&env e, &import_map index, &span sp,
|
||||
vec[ident] idents, @ast.item i) -> def_wrap {
|
||||
auto len = _vec.len[ident](idents);
|
||||
auto rest_idents = _vec.slice[ident](idents, 1u, len);
|
||||
auto empty_e = rec(scopes = nil[scope],
|
||||
sess = e.sess);
|
||||
auto tmp_e = update_env_for_item(empty_e, i);
|
||||
auto next_i = rest_idents.(0);
|
||||
auto next_ = lookup_name_wrapped(tmp_e, next_i);
|
||||
alt (next_) {
|
||||
case (none[tup(@env, def_wrap)]) {
|
||||
e.sess.span_err(sp, "unresolved name: " + next_i);
|
||||
fail;
|
||||
}
|
||||
case (some[tup(@env, def_wrap)](?next)) {
|
||||
auto combined_e = update_env_for_item(e, i);
|
||||
ret found_something(combined_e, index, sp,
|
||||
rest_idents, next._1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
alt (d) {
|
||||
case (def_wrap_import(?imp)) {
|
||||
alt (imp.node) {
|
||||
|
|
@ -122,23 +147,10 @@ fn find_final_def(&env e, import_map index,
|
|||
}
|
||||
alt (d) {
|
||||
case (def_wrap_mod(?i)) {
|
||||
auto rest_idents = _vec.slice[ident](idents, 1u, len);
|
||||
auto empty_e = rec(scopes = nil[scope],
|
||||
sess = e.sess);
|
||||
auto tmp_e = update_env_for_item(empty_e, i);
|
||||
auto next_i = rest_idents.(0);
|
||||
auto next_ = lookup_name_wrapped(tmp_e, next_i);
|
||||
alt (next_) {
|
||||
case (none[tup(@env, def_wrap)]) {
|
||||
e.sess.span_err(sp, "unresolved name: " + next_i);
|
||||
fail;
|
||||
}
|
||||
case (some[tup(@env, def_wrap)](?next)) {
|
||||
auto combined_e = update_env_for_item(e, i);
|
||||
ret found_something(combined_e, index, sp,
|
||||
rest_idents, next._1);
|
||||
}
|
||||
}
|
||||
ret found_mod(e, index, sp, idents, i);
|
||||
}
|
||||
case (def_wrap_native_mod(?i)) {
|
||||
ret found_mod(e, index, sp, idents, i);
|
||||
}
|
||||
case (def_wrap_use(?c)) {
|
||||
e.sess.span_err(sp, "Crate access is not implemented");
|
||||
|
|
@ -201,6 +213,9 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] {
|
|||
case (ast.item_mod(_, _, ?id)) {
|
||||
ret def_wrap_mod(i);
|
||||
}
|
||||
case (ast.item_native_mod(_, _, ?id)) {
|
||||
ret def_wrap_native_mod(i);
|
||||
}
|
||||
case (ast.item_ty(_, _, _, ?id, _)) {
|
||||
ret def_wrap_other(ast.def_ty(id));
|
||||
}
|
||||
|
|
@ -213,6 +228,17 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] {
|
|||
}
|
||||
}
|
||||
|
||||
fn found_def_native_item(@ast.native_item i) -> def_wrap {
|
||||
alt (i.node) {
|
||||
case (ast.native_item_ty(_, ?id)) {
|
||||
ret def_wrap_other(ast.def_native_ty(id));
|
||||
}
|
||||
case (ast.native_item_fn(_, _, _, ?id, _)) {
|
||||
ret def_wrap_other(ast.def_native_fn(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn found_decl_stmt(@ast.stmt s) -> def_wrap {
|
||||
alt (s.node) {
|
||||
case (ast.stmt_decl(?d)) {
|
||||
|
|
@ -267,12 +293,48 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] {
|
|||
}
|
||||
}
|
||||
}
|
||||
case (none[ast.mod_index_entry]) { /* fall through */ }
|
||||
case (none[ast.mod_index_entry]) {
|
||||
ret none[def_wrap];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_native_mod(ast.ident i, ast.native_mod m) -> option.t[def_wrap] {
|
||||
|
||||
alt (m.index.find(i)) {
|
||||
case (some[ast.native_mod_index_entry](?ent)) {
|
||||
alt (ent) {
|
||||
case (ast.nmie_view_item(?view_item)) {
|
||||
ret some(found_def_view(view_item));
|
||||
}
|
||||
case (ast.nmie_item(?item)) {
|
||||
ret some(found_def_native_item(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
case (none[ast.native_mod_index_entry]) {
|
||||
ret none[def_wrap];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_fn_decl(ast.ident i, &ast.fn_decl decl,
|
||||
&vec[ast.ty_param] ty_params) -> option.t[def_wrap] {
|
||||
for (ast.arg a in decl.inputs) {
|
||||
if (_str.eq(a.ident, i)) {
|
||||
auto t = ast.def_arg(a.id);
|
||||
ret some(def_wrap_other(t));
|
||||
}
|
||||
}
|
||||
for (ast.ty_param tp in ty_params) {
|
||||
if (_str.eq(tp.ident, i)) {
|
||||
auto t = ast.def_ty_arg(tp.id);
|
||||
ret some(def_wrap_other(t));
|
||||
}
|
||||
}
|
||||
ret none[def_wrap];
|
||||
}
|
||||
|
||||
|
||||
fn in_scope(ast.ident i, &scope s) -> option.t[def_wrap] {
|
||||
alt (s) {
|
||||
|
||||
|
|
@ -283,18 +345,7 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] {
|
|||
case (scope_item(?it)) {
|
||||
alt (it.node) {
|
||||
case (ast.item_fn(_, ?f, ?ty_params, _, _)) {
|
||||
for (ast.arg a in f.inputs) {
|
||||
if (_str.eq(a.ident, i)) {
|
||||
auto t = ast.def_arg(a.id);
|
||||
ret some(def_wrap_other(t));
|
||||
}
|
||||
}
|
||||
for (ast.ty_param tp in ty_params) {
|
||||
if (_str.eq(tp.ident, i)) {
|
||||
auto t = ast.def_ty_arg(tp.id);
|
||||
ret some(def_wrap_other(t));
|
||||
}
|
||||
}
|
||||
ret handle_fn_decl(i, f.decl, ty_params);
|
||||
}
|
||||
case (ast.item_obj(_, ?ob, ?ty_params, _, _)) {
|
||||
for (ast.obj_field f in ob.fields) {
|
||||
|
|
@ -310,9 +361,20 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] {
|
|||
}
|
||||
}
|
||||
}
|
||||
case (ast.item_tag(_, _, ?ty_params, _)) {
|
||||
for (ast.ty_param tp in ty_params) {
|
||||
if (_str.eq(tp.ident, i)) {
|
||||
auto t = ast.def_ty_arg(tp.id);
|
||||
ret some(def_wrap_other(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
case (ast.item_mod(_, ?m, _)) {
|
||||
ret check_mod(i, m);
|
||||
}
|
||||
case (ast.item_native_mod(_, ?m, _)) {
|
||||
ret check_native_mod(i, m);
|
||||
}
|
||||
case (ast.item_ty(_, _, ?ty_params, _, _)) {
|
||||
for (ast.ty_param tp in ty_params) {
|
||||
if (_str.eq(tp.ident, i)) {
|
||||
|
|
@ -325,6 +387,14 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] {
|
|||
}
|
||||
}
|
||||
|
||||
case (scope_native_item(?it)) {
|
||||
alt (it.node) {
|
||||
case (ast.native_item_fn(_, ?decl, ?ty_params, _, _)) {
|
||||
ret handle_fn_decl(i, decl, ty_params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case (scope_loop(?d)) {
|
||||
alt (d.node) {
|
||||
case (ast.decl_local(?local)) {
|
||||
|
|
@ -432,8 +502,7 @@ fn fold_expr_path(&env e, &span sp, &ast.path p, &option.t[def] d,
|
|||
path_len = n_idents - remaining + 1u;
|
||||
}
|
||||
case (def_wrap_other(_)) {
|
||||
check (n_idents == 1u);
|
||||
path_len = 1u;
|
||||
path_len = n_idents;
|
||||
}
|
||||
case (def_wrap_mod(?m)) {
|
||||
e.sess.span_err(sp,
|
||||
|
|
@ -491,6 +560,10 @@ fn update_env_for_item(&env e, @ast.item i) -> env {
|
|||
ret rec(scopes = cons[scope](scope_item(i), @e.scopes) with e);
|
||||
}
|
||||
|
||||
fn update_env_for_native_item(&env e, @ast.native_item i) -> env {
|
||||
ret rec(scopes = cons[scope](scope_native_item(i), @e.scopes) with e);
|
||||
}
|
||||
|
||||
fn update_env_for_block(&env e, &ast.block b) -> env {
|
||||
ret rec(scopes = cons[scope](scope_block(b), @e.scopes) with e);
|
||||
}
|
||||
|
|
@ -500,6 +573,9 @@ fn update_env_for_expr(&env e, @ast.expr x) -> env {
|
|||
case (ast.expr_for(?d, _, _, _)) {
|
||||
ret rec(scopes = cons[scope](scope_loop(d), @e.scopes) with e);
|
||||
}
|
||||
case (ast.expr_for_each(?d, _, _, _)) {
|
||||
ret rec(scopes = cons[scope](scope_loop(d), @e.scopes) with e);
|
||||
}
|
||||
case (_) { }
|
||||
}
|
||||
ret e;
|
||||
|
|
@ -517,6 +593,8 @@ fn resolve_imports(session.session sess, @ast.crate crate) -> @ast.crate {
|
|||
= bind fold_view_item_import(_,_,import_index,_,_,_,_),
|
||||
update_env_for_crate = bind update_env_for_crate(_,_),
|
||||
update_env_for_item = bind update_env_for_item(_,_),
|
||||
update_env_for_native_item =
|
||||
bind update_env_for_native_item(_,_),
|
||||
update_env_for_block = bind update_env_for_block(_,_),
|
||||
update_env_for_arm = bind update_env_for_arm(_,_),
|
||||
update_env_for_expr = bind update_env_for_expr(_,_)
|
||||
|
|
@ -539,6 +617,8 @@ fn resolve_crate(session.session sess, @ast.crate crate) -> @ast.crate {
|
|||
fold_ty_path = bind fold_ty_path(_,_,_,_),
|
||||
update_env_for_crate = bind update_env_for_crate(_,_),
|
||||
update_env_for_item = bind update_env_for_item(_,_),
|
||||
update_env_for_native_item =
|
||||
bind update_env_for_native_item(_,_),
|
||||
update_env_for_block = bind update_env_for_block(_,_),
|
||||
update_env_for_arm = bind update_env_for_arm(_,_),
|
||||
update_env_for_expr = bind update_env_for_expr(_,_)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
207
src/comp/pretty/pp.rs
Normal file
207
src/comp/pretty/pp.rs
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
import std.io;
|
||||
import std._vec;
|
||||
import std._str;
|
||||
|
||||
tag boxtype {box_h; box_v; box_hv; box_align;}
|
||||
tag contexttype {cx_h; cx_v;}
|
||||
|
||||
tag token {
|
||||
brk(uint);
|
||||
word(str);
|
||||
cword(str); // closing token
|
||||
open(boxtype, uint);
|
||||
close;
|
||||
}
|
||||
|
||||
type context = rec(contexttype tp, uint indent);
|
||||
|
||||
type ps = @rec(mutable vec[context] context,
|
||||
uint width,
|
||||
mutable vec[token] buffered,
|
||||
mutable uint scandepth,
|
||||
mutable uint bufferedcol,
|
||||
mutable uint col,
|
||||
mutable bool start_of_line);
|
||||
|
||||
fn mkstate(uint width) -> ps {
|
||||
let vec[context] stack = vec(rec(tp=cx_v, indent=0u));
|
||||
let vec[token] buff = vec();
|
||||
ret @rec(mutable context=stack,
|
||||
width=width,
|
||||
mutable buffered=buff,
|
||||
mutable scandepth=0u,
|
||||
mutable bufferedcol=0u,
|
||||
mutable col=0u,
|
||||
mutable start_of_line=true);
|
||||
}
|
||||
|
||||
impure fn push_context(ps p, contexttype tp, uint indent) {
|
||||
before_print(p, false);
|
||||
p.context = _vec.push[context](p.context, rec(tp=tp, indent=base_indent(p)
|
||||
+ indent));
|
||||
}
|
||||
|
||||
impure fn pop_context(ps p) {
|
||||
p.context = _vec.pop[context](p.context);
|
||||
}
|
||||
|
||||
impure fn add_token(ps p, token tok) {
|
||||
if (p.scandepth == 0u) {do_token(p, tok);}
|
||||
else {buffer_token(p, tok);}
|
||||
}
|
||||
|
||||
impure fn buffer_token(ps p, token tok) {
|
||||
p.buffered += vec(tok);
|
||||
p.bufferedcol += token_size(tok);
|
||||
alt (p.buffered.(0)) {
|
||||
case (brk(_)) {
|
||||
alt (tok) {
|
||||
case (brk(_)) {
|
||||
if (p.scandepth == 1u) {finish_break_scan(p);}
|
||||
}
|
||||
case (open(box_h,_)) {p.scandepth += 1u;}
|
||||
case (open(_,_)) {finish_break_scan(p);}
|
||||
case (close) {
|
||||
p.scandepth -= 1u;
|
||||
if (p.scandepth == 0u) {finish_break_scan(p);}
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
}
|
||||
case (open(_,_)) {
|
||||
if (p.bufferedcol > p.width) {finish_block_scan(p, cx_v);}
|
||||
else {
|
||||
alt (tok) {
|
||||
case (open(_,_)) {p.scandepth += 1u;}
|
||||
case (close) {
|
||||
p.scandepth -= 1u;
|
||||
if (p.scandepth == 0u) {finish_block_scan(p, cx_h);}
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impure fn finish_block_scan(ps p, contexttype tp) {
|
||||
auto indent;
|
||||
alt (p.buffered.(0)){
|
||||
case (open(box_hv,?ind)) {
|
||||
indent = ind;
|
||||
}
|
||||
case (open(box_align, _)) {
|
||||
indent = p.col - base_indent(p);
|
||||
}
|
||||
}
|
||||
p.scandepth = 0u;
|
||||
push_context(p, tp, indent);
|
||||
for (token t in _vec.shift[token](p.buffered)) {add_token(p, t);}
|
||||
}
|
||||
|
||||
impure fn finish_break_scan(ps p) {
|
||||
if (p.bufferedcol > p.width) {
|
||||
write_str("\n");
|
||||
p.col = 0u;
|
||||
}
|
||||
else {
|
||||
auto width;
|
||||
alt (p.buffered.(0)) {case(brk(?w)) {width = w;}}
|
||||
auto i = 0u;
|
||||
while (i < width) {write_str(" "); i+=1u;}
|
||||
p.col += width;
|
||||
}
|
||||
p.scandepth = 0u;
|
||||
for (token t in _vec.shift[token](p.buffered)) {add_token(p, t);}
|
||||
}
|
||||
|
||||
impure fn start_scan(ps p, token tok) {
|
||||
p.buffered = vec(tok);
|
||||
p.scandepth = 1u;
|
||||
p.bufferedcol = p.col;
|
||||
}
|
||||
|
||||
fn cur_context(ps p) -> context {
|
||||
ret p.context.(_vec.len[context](p.context)-1u);
|
||||
}
|
||||
fn base_indent(ps p) -> uint {
|
||||
auto i = _vec.len[context](p.context);
|
||||
while (i > 0u) {
|
||||
i -= 1u;
|
||||
auto cx = p.context.(i);
|
||||
if (cx.tp == cx_v) {ret cx.indent;}
|
||||
}
|
||||
}
|
||||
|
||||
impure fn do_token(ps p, token tok) {
|
||||
alt (tok) {
|
||||
case (brk(?sz)) {
|
||||
alt (cur_context(p).tp) {
|
||||
case (cx_h) {
|
||||
before_print(p, false);
|
||||
start_scan(p, tok);
|
||||
}
|
||||
case (cx_v) {
|
||||
write_str("\n");
|
||||
p.col = 0u;
|
||||
p.start_of_line = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
case (word(?w)) {
|
||||
before_print(p, false);
|
||||
write_str(w);
|
||||
p.col += _str.byte_len(w); // TODO char_len
|
||||
}
|
||||
case (cword(?w)) {
|
||||
before_print(p, true);
|
||||
write_str(w);
|
||||
p.col += _str.byte_len(w); // TODO char_len
|
||||
}
|
||||
case (open(?tp, ?indent)) {
|
||||
alt (tp) {
|
||||
case (box_hv) {start_scan(p, tok);}
|
||||
case (box_align) {start_scan(p, tok);}
|
||||
case (box_h) {push_context(p, cx_h, indent);}
|
||||
case (box_v) {push_context(p, cx_v, indent);}
|
||||
}
|
||||
}
|
||||
case (close) {pop_context(p);}
|
||||
}
|
||||
}
|
||||
|
||||
impure fn before_print(ps p, bool closing) {
|
||||
if (p.start_of_line) {
|
||||
p.start_of_line = false;
|
||||
auto ind;
|
||||
if (closing) {ind = base_indent(p);}
|
||||
else {ind = cur_context(p).indent;}
|
||||
p.col = ind;
|
||||
while (ind > 0u) {write_str(" "); ind -= 1u;}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_str(str s) {
|
||||
io.writefd(1, _str.bytes(s));
|
||||
}
|
||||
|
||||
fn token_size(token tok) -> uint {
|
||||
alt (tok) {
|
||||
case (brk(?sz)) {ret sz;}
|
||||
case (word(?w)) {ret _str.byte_len(w);}
|
||||
case (cword(?w)) {ret _str.byte_len(w);}
|
||||
case (open(_, _)) {ret 0u;} // TODO exception for V blocks?
|
||||
case (close) {ret 0u;}
|
||||
}
|
||||
}
|
||||
|
||||
impure fn box(ps p, uint indent) {add_token(p, open(box_hv, indent));}
|
||||
impure fn abox(ps p) {add_token(p, open(box_align, 0u));}
|
||||
impure fn vbox(ps p, uint indent) {add_token(p, open(box_v, indent));}
|
||||
impure fn hbox(ps p, uint indent) {add_token(p, open(box_h, indent));}
|
||||
impure fn end(ps p) {add_token(p, close);}
|
||||
impure fn wrd(ps p, str wrd) {add_token(p, word(wrd));}
|
||||
impure fn cwrd(ps p, str wrd) {add_token(p, cword(wrd));}
|
||||
impure fn space(ps p) {add_token(p, brk(1u));}
|
||||
impure fn spaces(ps p, uint n) {add_token(p, brk(n));}
|
||||
impure fn line(ps p) {add_token(p, brk(0u));}
|
||||
708
src/comp/pretty/pprust.rs
Normal file
708
src/comp/pretty/pprust.rs
Normal file
|
|
@ -0,0 +1,708 @@
|
|||
import std._vec;
|
||||
import std._str;
|
||||
import std.option;
|
||||
import front.ast;
|
||||
import pp.box; import pp.abox; import pp.vbox;
|
||||
import pp.end; import pp.wrd; import pp.space; import pp.line;
|
||||
import pp.ps;
|
||||
|
||||
import foo = std.io;
|
||||
|
||||
const uint indent_unit = 2u;
|
||||
const int as_prec = 5;
|
||||
|
||||
impure fn print_ast(ast._mod _mod) {
|
||||
auto s = pp.mkstate(80u);
|
||||
for (@ast.view_item vitem in _mod.view_items) {print_view_item(s, vitem);}
|
||||
line(s);
|
||||
for (@ast.item item in _mod.items) {print_item(s, item);}
|
||||
}
|
||||
|
||||
impure fn hbox(ps s) {
|
||||
pp.hbox(s, indent_unit);
|
||||
}
|
||||
impure fn wrd1(ps s, str word) {
|
||||
wrd(s, word);
|
||||
space(s);
|
||||
}
|
||||
impure fn popen(ps s) {
|
||||
wrd(s, "(");
|
||||
abox(s);
|
||||
}
|
||||
impure fn pclose(ps s) {
|
||||
end(s);
|
||||
wrd(s, ")");
|
||||
}
|
||||
impure fn bopen(ps s) {
|
||||
wrd1(s, "{");
|
||||
vbox(s, indent_unit);
|
||||
line(s);
|
||||
}
|
||||
impure fn bclose(ps s) {
|
||||
end(s);
|
||||
pp.cwrd(s, "}");
|
||||
}
|
||||
impure fn commasep[IN](ps s, vec[IN] elts, impure fn (ps, IN) op) {
|
||||
auto first = true;
|
||||
for (IN elt in elts) {
|
||||
if (first) {first = false;}
|
||||
else {wrd1(s, ",");}
|
||||
op(s, elt);
|
||||
}
|
||||
}
|
||||
|
||||
impure fn print_type(ps s, @ast.ty ty) {
|
||||
hbox(s);
|
||||
alt (ty.node) {
|
||||
case (ast.ty_nil) {wrd(s, "()");}
|
||||
case (ast.ty_bool) {wrd(s, "bool");}
|
||||
case (ast.ty_int) {wrd(s, "int");}
|
||||
case (ast.ty_uint) {wrd(s, "uint");}
|
||||
case (ast.ty_machine(?tm)) {wrd(s, util.common.ty_mach_to_str(tm));}
|
||||
case (ast.ty_char) {wrd(s, "char");}
|
||||
case (ast.ty_str) {wrd(s, "str");}
|
||||
case (ast.ty_box(?t)) {wrd(s, "@"); print_type(s, t);}
|
||||
case (ast.ty_vec(?t)) {wrd(s, "vec["); print_type(s, t); wrd(s, "]");}
|
||||
case (ast.ty_type) {wrd(s, "type");}
|
||||
case (ast.ty_tup(?elts)) {
|
||||
wrd(s, "tup");
|
||||
popen(s);
|
||||
auto f = print_type;
|
||||
commasep[@ast.ty](s, elts, f);
|
||||
pclose(s);
|
||||
}
|
||||
case (ast.ty_rec(?fields)) {
|
||||
wrd(s, "rec");
|
||||
popen(s);
|
||||
impure fn print_field(ps s, ast.ty_field f) {
|
||||
hbox(s);
|
||||
print_type(s, f.ty);
|
||||
space(s);
|
||||
wrd(s, f.ident);
|
||||
end(s);
|
||||
}
|
||||
auto f = print_field;
|
||||
commasep[ast.ty_field](s, fields, f);
|
||||
pclose(s);
|
||||
}
|
||||
case (ast.ty_fn(?proto,?inputs,?output)) {
|
||||
if (proto == ast.proto_fn) {wrd(s, "fn");}
|
||||
else {wrd(s, "iter");}
|
||||
popen(s);
|
||||
impure fn print_arg(ps s, ast.ty_arg input) {
|
||||
if (middle.ty.mode_is_alias(input.mode)) {wrd(s, "&");}
|
||||
print_type(s, input.ty);
|
||||
}
|
||||
auto f = print_arg;
|
||||
commasep[ast.ty_arg](s, inputs, f);
|
||||
pclose(s);
|
||||
if (output.node != ast.ty_nil) {
|
||||
space(s);
|
||||
hbox(s);
|
||||
wrd1(s, "->");
|
||||
print_type(s, output);
|
||||
end(s);
|
||||
}
|
||||
}
|
||||
case (ast.ty_path(?path,_)) {
|
||||
print_path(s, path);
|
||||
}
|
||||
case (ast.ty_mutable(?t)) {
|
||||
wrd1(s, "mutable");
|
||||
print_type(s, t);
|
||||
}
|
||||
}
|
||||
end(s);
|
||||
}
|
||||
|
||||
impure fn print_item(ps s, @ast.item item) {
|
||||
hbox(s);
|
||||
alt (item.node) {
|
||||
case (ast.item_const(?id, ?ty, ?expr, _, _)) {
|
||||
wrd1(s, "const");
|
||||
print_type(s, ty);
|
||||
space(s);
|
||||
wrd1(s, id);
|
||||
wrd1(s, "=");
|
||||
print_expr(s, expr);
|
||||
wrd(s, ";");
|
||||
}
|
||||
case (ast.item_fn(?name,?_fn,?typarams,_,_)) {
|
||||
print_fn(s, _fn.decl, name, typarams);
|
||||
space(s);
|
||||
print_block(s, _fn.body);
|
||||
}
|
||||
case (ast.item_mod(?id,?_mod,_)) {
|
||||
wrd1(s, "mod");
|
||||
wrd1(s, id);
|
||||
bopen(s);
|
||||
for (@ast.item itm in _mod.items) {print_item(s, itm);}
|
||||
bclose(s);
|
||||
}
|
||||
case (ast.item_native_mod(?id,?nmod,_)) {
|
||||
wrd1(s, "native");
|
||||
alt (nmod.abi) {
|
||||
case (ast.native_abi_rust) {wrd1(s, "\"rust\"");}
|
||||
case (ast.native_abi_cdecl) {wrd1(s, "\"cdecl\"");}
|
||||
}
|
||||
wrd1(s, "mod");
|
||||
wrd1(s, id);
|
||||
bopen(s);
|
||||
for (@ast.native_item item in nmod.items) {
|
||||
hbox(s);
|
||||
alt (item.node) {
|
||||
case (ast.native_item_ty(?id,_)) {
|
||||
wrd1(s, "type");
|
||||
wrd(s, id);
|
||||
}
|
||||
case (ast.native_item_fn(?id,?decl,?typarams,_,_)) {
|
||||
print_fn(s, decl, id, typarams);
|
||||
}
|
||||
}
|
||||
wrd(s, ";");
|
||||
end(s);
|
||||
}
|
||||
bclose(s);
|
||||
}
|
||||
case (ast.item_ty(?id,?ty,?params,_,_)) {
|
||||
wrd1(s, "type");
|
||||
wrd(s, id);
|
||||
print_type_params(s, params);
|
||||
space(s);
|
||||
wrd1(s, "=");
|
||||
print_type(s, ty);
|
||||
wrd(s, ";");
|
||||
}
|
||||
case (ast.item_tag(?id,?variants,?params,_)) {
|
||||
wrd1(s, "tag");
|
||||
wrd(s, id);
|
||||
print_type_params(s, params);
|
||||
space(s);
|
||||
bopen(s);
|
||||
for (ast.variant v in variants) {
|
||||
wrd(s, v.name);
|
||||
if (_vec.len[ast.variant_arg](v.args) > 0u) {
|
||||
popen(s);
|
||||
impure fn print_variant_arg(ps s, ast.variant_arg arg) {
|
||||
print_type(s, arg.ty);
|
||||
}
|
||||
auto f = print_variant_arg;
|
||||
commasep[ast.variant_arg](s, v.args, f);
|
||||
pclose(s);
|
||||
}
|
||||
wrd(s, ";");
|
||||
line(s);
|
||||
}
|
||||
bclose(s);
|
||||
}
|
||||
case (ast.item_obj(?id,?_obj,?params,_,_)) {
|
||||
wrd1(s, "obj");
|
||||
wrd(s, id);
|
||||
print_type_params(s, params);
|
||||
popen(s);
|
||||
impure fn print_field(ps s, ast.obj_field field) {
|
||||
hbox(s);
|
||||
print_type(s, field.ty);
|
||||
space(s);
|
||||
wrd(s, field.ident);
|
||||
end(s);
|
||||
}
|
||||
auto f = print_field;
|
||||
commasep[ast.obj_field](s, _obj.fields, f);
|
||||
pclose(s);
|
||||
space(s);
|
||||
bopen(s);
|
||||
for (@ast.method meth in _obj.methods) {
|
||||
hbox(s);
|
||||
let vec[ast.ty_param] typarams = vec();
|
||||
print_fn(s, meth.node.meth.decl, meth.node.ident, typarams);
|
||||
space(s);
|
||||
print_block(s, meth.node.meth.body);
|
||||
end(s);
|
||||
line(s);
|
||||
}
|
||||
alt (_obj.dtor) {
|
||||
case (option.some[ast.block](?dtor)) {
|
||||
hbox(s);
|
||||
wrd1(s, "close");
|
||||
print_block(s, dtor);
|
||||
end(s);
|
||||
line(s);
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
bclose(s);
|
||||
}
|
||||
}
|
||||
end(s);
|
||||
line(s);
|
||||
line(s);
|
||||
}
|
||||
|
||||
impure fn print_block(ps s, ast.block blk) {
|
||||
bopen(s);
|
||||
for (@ast.stmt st in blk.node.stmts) {
|
||||
alt (st.node) {
|
||||
case (ast.stmt_decl(?decl)) {print_decl(s, decl);}
|
||||
case (ast.stmt_expr(?expr)) {print_expr(s, expr);}
|
||||
}
|
||||
if (front.parser.stmt_ends_with_semi(st)) {wrd(s, ";");}
|
||||
line(s);
|
||||
}
|
||||
alt (blk.node.expr) {
|
||||
case (option.some[@ast.expr](?expr)) {
|
||||
print_expr(s, expr);
|
||||
line(s);
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
bclose(s);
|
||||
}
|
||||
|
||||
impure fn print_literal(ps s, @ast.lit lit) {
|
||||
alt (lit.node) {
|
||||
case (ast.lit_str(?st)) {print_string(s, st);}
|
||||
case (ast.lit_char(?ch)) {
|
||||
wrd(s, "'" + escape_str(_str.from_bytes(vec(ch as u8)), '\'') + "'");
|
||||
}
|
||||
case (ast.lit_int(?val)) {
|
||||
wrd(s, util.common.istr(val));
|
||||
}
|
||||
case (ast.lit_uint(?val)) { // TODO clipping? uistr?
|
||||
wrd(s, util.common.istr(val as int) + "u");
|
||||
}
|
||||
case (ast.lit_mach_int(?mach,?val)) {
|
||||
wrd(s, util.common.istr(val as int));
|
||||
wrd(s, util.common.ty_mach_to_str(mach));
|
||||
}
|
||||
case (ast.lit_nil) {wrd(s, "()");}
|
||||
case (ast.lit_bool(?val)) {
|
||||
if (val) {wrd(s, "true");} else {wrd(s, "false");}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impure fn print_expr(ps s, @ast.expr expr) {
|
||||
auto pe = print_expr;
|
||||
hbox(s);
|
||||
alt (expr.node) {
|
||||
case (ast.expr_vec(?exprs,_)) {
|
||||
wrd(s, "vec");
|
||||
popen(s);
|
||||
commasep[@ast.expr](s, exprs, pe);
|
||||
pclose(s);
|
||||
}
|
||||
case (ast.expr_tup(?exprs,_)) {
|
||||
impure fn printElt(ps s, ast.elt elt) {
|
||||
hbox(s);
|
||||
if (elt.mut == ast.mut) {wrd1(s, "mutable");}
|
||||
print_expr(s, elt.expr);
|
||||
end(s);
|
||||
}
|
||||
wrd(s, "tup");
|
||||
popen(s);
|
||||
auto f = printElt;
|
||||
commasep[ast.elt](s, exprs, f);
|
||||
pclose(s);
|
||||
}
|
||||
case (ast.expr_rec(?fields,_,_)) {
|
||||
impure fn print_field(ps s, ast.field field) {
|
||||
hbox(s);
|
||||
if (field.mut == ast.mut) {wrd1(s, "mutable");}
|
||||
wrd(s, field.ident);
|
||||
wrd(s, "=");
|
||||
print_expr(s, field.expr);
|
||||
end(s);
|
||||
}
|
||||
wrd(s, "rec");
|
||||
popen(s);
|
||||
auto f = print_field;
|
||||
commasep[ast.field](s, fields, f);
|
||||
pclose(s);
|
||||
}
|
||||
case (ast.expr_call(?func,?args,_)) {
|
||||
print_expr(s, func);
|
||||
popen(s);
|
||||
commasep[@ast.expr](s, args, pe);
|
||||
pclose(s);
|
||||
}
|
||||
case (ast.expr_bind(?func,?args,_)) {
|
||||
impure fn print_opt(ps s, option.t[@ast.expr] expr) {
|
||||
alt (expr) {
|
||||
case (option.some[@ast.expr](?expr)) {
|
||||
print_expr(s, expr);
|
||||
}
|
||||
case (_) {wrd(s, "_");}
|
||||
}
|
||||
}
|
||||
wrd1(s, "bind");
|
||||
print_expr(s, func);
|
||||
popen(s);
|
||||
auto f = print_opt;
|
||||
commasep[option.t[@ast.expr]](s, args, f);
|
||||
pclose(s);
|
||||
}
|
||||
case (ast.expr_binary(?op,?lhs,?rhs,_)) {
|
||||
auto prec = operator_prec(op);
|
||||
print_maybe_parens(s, lhs, prec);
|
||||
space(s);
|
||||
wrd1(s, ast.binop_to_str(op));
|
||||
print_maybe_parens(s, rhs, prec + 1);
|
||||
}
|
||||
case (ast.expr_unary(?op,?expr,_)) {
|
||||
wrd(s, ast.unop_to_str(op));
|
||||
if (op == ast._mutable) {space(s);}
|
||||
print_expr(s, expr);
|
||||
}
|
||||
case (ast.expr_lit(?lit,_)) {
|
||||
print_literal(s, lit);
|
||||
}
|
||||
case (ast.expr_cast(?expr,?ty,_)) {
|
||||
print_maybe_parens(s, expr, as_prec);
|
||||
space(s);
|
||||
wrd1(s, "as");
|
||||
print_type(s, ty);
|
||||
}
|
||||
case (ast.expr_if(?test,?block,?elseopt,_)) {
|
||||
wrd1(s, "if");
|
||||
popen(s);
|
||||
print_expr(s, test);
|
||||
pclose(s);
|
||||
space(s);
|
||||
print_block(s, block);
|
||||
alt (elseopt) {
|
||||
case (option.some[@ast.expr](?_else)) {
|
||||
space(s);
|
||||
wrd1(s, "else");
|
||||
print_expr(s, _else);
|
||||
}
|
||||
}
|
||||
}
|
||||
case (ast.expr_while(?test,?block,_)) {
|
||||
wrd1(s, "while");
|
||||
popen(s);
|
||||
print_expr(s, test);
|
||||
pclose(s);
|
||||
space(s);
|
||||
print_block(s, block);
|
||||
}
|
||||
case (ast.expr_for(?decl,?expr,?block,_)) {
|
||||
wrd1(s, "for");
|
||||
popen(s);
|
||||
print_decl(s, decl);
|
||||
space(s);
|
||||
wrd1(s, "in");
|
||||
print_expr(s, expr);
|
||||
pclose(s);
|
||||
space(s);
|
||||
print_block(s, block);
|
||||
}
|
||||
case (ast.expr_for_each(?decl,?expr,?block,_)) {
|
||||
wrd1(s, "for each");
|
||||
popen(s);
|
||||
print_decl(s, decl);
|
||||
space(s);
|
||||
wrd1(s, "in");
|
||||
print_expr(s, expr);
|
||||
space(s);
|
||||
print_block(s, block);
|
||||
}
|
||||
case (ast.expr_do_while(?block,?expr,_)) {
|
||||
wrd1(s, "do");
|
||||
space(s);
|
||||
print_block(s, block);
|
||||
space(s);
|
||||
wrd1(s, "while");
|
||||
popen(s);
|
||||
print_expr(s, expr);
|
||||
pclose(s);
|
||||
}
|
||||
case (ast.expr_alt(?expr,?arms,_)) {
|
||||
wrd1(s, "alt");
|
||||
popen(s);
|
||||
print_expr(s, expr);
|
||||
pclose(s);
|
||||
space(s);
|
||||
bopen(s);
|
||||
for (ast.arm arm in arms) {
|
||||
hbox(s);
|
||||
wrd1(s, "case");
|
||||
popen(s);
|
||||
print_pat(s, arm.pat);
|
||||
pclose(s);
|
||||
space(s);
|
||||
print_block(s, arm.block);
|
||||
end(s);
|
||||
line(s);
|
||||
}
|
||||
bclose(s);
|
||||
}
|
||||
case (ast.expr_block(?block,_)) {
|
||||
print_block(s, block);
|
||||
}
|
||||
case (ast.expr_assign(?lhs,?rhs,_)) {
|
||||
print_expr(s, lhs);
|
||||
space(s);
|
||||
wrd1(s, "=");
|
||||
print_expr(s, rhs);
|
||||
}
|
||||
case (ast.expr_assign_op(?op,?lhs,?rhs,_)) {
|
||||
print_expr(s, lhs);
|
||||
space(s);
|
||||
wrd(s, ast.binop_to_str(op));
|
||||
wrd1(s, "=");
|
||||
print_expr(s, rhs);
|
||||
}
|
||||
case (ast.expr_field(?expr,?id,_)) {
|
||||
print_expr(s, expr);
|
||||
wrd(s, ".");
|
||||
wrd(s, id);
|
||||
}
|
||||
case (ast.expr_index(?expr,?index,_)) {
|
||||
print_expr(s, expr);
|
||||
wrd(s, ".");
|
||||
popen(s);
|
||||
print_expr(s, index);
|
||||
pclose(s);
|
||||
}
|
||||
case (ast.expr_path(?path,_,_)) {
|
||||
print_path(s, path);
|
||||
}
|
||||
case (ast.expr_fail) {
|
||||
wrd(s, "fail");
|
||||
}
|
||||
case (ast.expr_ret(?result)) {
|
||||
wrd(s, "ret");
|
||||
alt (result) {
|
||||
case (option.some[@ast.expr](?expr)) {
|
||||
space(s);
|
||||
print_expr(s, expr);
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
}
|
||||
case (ast.expr_put(?result)) {
|
||||
wrd(s, "put");
|
||||
alt (result) {
|
||||
case (option.some[@ast.expr](?expr)) {
|
||||
space(s);
|
||||
print_expr(s, expr);
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
}
|
||||
case (ast.expr_be(?result)) {
|
||||
wrd1(s, "be");
|
||||
print_expr(s, result);
|
||||
}
|
||||
case (ast.expr_log(?expr)) {
|
||||
wrd1(s, "log");
|
||||
print_expr(s, expr);
|
||||
}
|
||||
case (ast.expr_check_expr(?expr)) {
|
||||
wrd1(s, "check");
|
||||
print_expr(s, expr);
|
||||
}
|
||||
case (_) {wrd(s, "X");}
|
||||
// TODO expr_ext(path, vec[@expr], option.t[@expr], @expr, ann);
|
||||
}
|
||||
end(s);
|
||||
}
|
||||
|
||||
impure fn print_decl(ps s, @ast.decl decl) {
|
||||
hbox(s);
|
||||
alt (decl.node) {
|
||||
case (ast.decl_local(?loc)) {
|
||||
alt (loc.ty) {
|
||||
case (option.some[@ast.ty](?ty)) {
|
||||
wrd1(s, "let");
|
||||
print_type(s, ty);
|
||||
space(s);
|
||||
}
|
||||
case (_) {
|
||||
wrd1(s, "auto");
|
||||
}
|
||||
}
|
||||
wrd(s, loc.ident);
|
||||
alt (loc.init) {
|
||||
case (option.some[@ast.expr](?init)) {
|
||||
space(s);
|
||||
wrd1(s, "=");
|
||||
print_expr(s, init);
|
||||
}
|
||||
case (_) {}
|
||||
}
|
||||
}
|
||||
case (ast.decl_item(?item)) {
|
||||
print_item(s, item);
|
||||
}
|
||||
}
|
||||
end(s);
|
||||
}
|
||||
|
||||
impure fn print_path(ps s, ast.path path) {
|
||||
auto first = true;
|
||||
for (str id in path.node.idents) {
|
||||
if (first) {first = false;}
|
||||
else {wrd(s, ".");}
|
||||
wrd(s, id);
|
||||
}
|
||||
if (_vec.len[@ast.ty](path.node.types) > 0u) {
|
||||
wrd(s, "[");
|
||||
auto f = print_type;
|
||||
commasep[@ast.ty](s, path.node.types, f);
|
||||
wrd(s, "]");
|
||||
}
|
||||
}
|
||||
|
||||
impure fn print_pat(ps s, @ast.pat pat) {
|
||||
alt (pat.node) {
|
||||
case (ast.pat_wild(_)) {wrd(s, "_");}
|
||||
case (ast.pat_bind(?id,_,_)) {wrd(s, "?" + id);}
|
||||
case (ast.pat_lit(?lit,_)) {print_literal(s, lit);}
|
||||
case (ast.pat_tag(?path,?args,_,_)) {
|
||||
print_path(s, path);
|
||||
if (_vec.len[@ast.pat](args) > 0u) {
|
||||
popen(s);
|
||||
auto f = print_pat;
|
||||
commasep[@ast.pat](s, args, f);
|
||||
pclose(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impure fn print_fn(ps s, ast.fn_decl decl, str name,
|
||||
vec[ast.ty_param] typarams) {
|
||||
alt (decl.effect) {
|
||||
case (ast.eff_impure) {wrd1(s, "impure");}
|
||||
case (ast.eff_unsafe) {wrd1(s, "unsafe");}
|
||||
case (_) {}
|
||||
}
|
||||
wrd1(s, "fn");
|
||||
wrd(s, name);
|
||||
print_type_params(s, typarams);
|
||||
popen(s);
|
||||
impure fn print_arg(ps s, ast.arg x) {
|
||||
hbox(s);
|
||||
print_type(s, x.ty);
|
||||
space(s);
|
||||
wrd(s, x.ident);
|
||||
end(s);
|
||||
}
|
||||
auto f = print_arg;
|
||||
commasep[ast.arg](s, decl.inputs, f);
|
||||
pclose(s);
|
||||
if (decl.output.node != ast.ty_nil) {
|
||||
space(s);
|
||||
hbox(s);
|
||||
wrd1(s, "->");
|
||||
print_type(s, decl.output);
|
||||
end(s);
|
||||
}
|
||||
}
|
||||
|
||||
impure fn print_type_params(ps s, vec[ast.ty_param] params) {
|
||||
if (_vec.len[ast.ty_param](params) > 0u) {
|
||||
wrd(s, "[");
|
||||
impure fn printParam(ps s, ast.ty_param param) {wrd(s, param.ident);}
|
||||
auto f = printParam;
|
||||
commasep[ast.ty_param](s, params, f);
|
||||
wrd(s, "]");
|
||||
}
|
||||
}
|
||||
|
||||
impure fn print_view_item(ps s, @ast.view_item item) {
|
||||
hbox(s);
|
||||
alt (item.node) {
|
||||
case (ast.view_item_use(?id,?mta,_)) {
|
||||
wrd1(s, "use");
|
||||
wrd(s, id);
|
||||
if (_vec.len[@ast.meta_item](mta) > 0u) {
|
||||
popen(s);
|
||||
impure fn print_meta(ps s, @ast.meta_item item) {
|
||||
hbox(s);
|
||||
wrd1(s, item.node.name);
|
||||
wrd1(s, "=");
|
||||
print_string(s, item.node.value);
|
||||
end(s);
|
||||
}
|
||||
auto f = print_meta;
|
||||
commasep[@ast.meta_item](s, mta, f);
|
||||
pclose(s);
|
||||
}
|
||||
}
|
||||
case (ast.view_item_import(?id,?ids,_,_)) {
|
||||
wrd1(s, "import");
|
||||
if (!_str.eq(id, ids.(_vec.len[str](ids)-1u))) {
|
||||
wrd1(s, id);
|
||||
wrd1(s, "=");
|
||||
}
|
||||
auto first = true;
|
||||
for (str elt in ids) {
|
||||
if (first) {first = false;}
|
||||
else {wrd(s, ".");}
|
||||
wrd(s, elt);
|
||||
}
|
||||
}
|
||||
case (ast.view_item_export(?id)) {
|
||||
wrd1(s, "export");
|
||||
wrd(s, id);
|
||||
}
|
||||
}
|
||||
end(s);
|
||||
wrd(s, ";");
|
||||
line(s);
|
||||
}
|
||||
|
||||
// FIXME: The fact that this builds up the table anew for every call is
|
||||
// not good. Eventually, table should be a const.
|
||||
fn operator_prec(ast.binop op) -> int {
|
||||
for (front.parser.op_spec spec in front.parser.prec_table()) {
|
||||
if (spec.op == op) {ret spec.prec;}
|
||||
}
|
||||
fail;
|
||||
}
|
||||
|
||||
impure fn print_maybe_parens(ps s, @ast.expr expr, int outer_prec) {
|
||||
auto add_them;
|
||||
alt (expr.node) {
|
||||
case (ast.expr_binary(?op,_,_,_)) {
|
||||
add_them = operator_prec(op) < outer_prec;
|
||||
}
|
||||
case (ast.expr_cast(_,_,_)) {
|
||||
add_them = as_prec < outer_prec;
|
||||
}
|
||||
case (_) {
|
||||
add_them = false;
|
||||
}
|
||||
}
|
||||
if (add_them) {popen(s);}
|
||||
print_expr(s, expr);
|
||||
if (add_them) {pclose(s);}
|
||||
}
|
||||
|
||||
// TODO non-ascii
|
||||
fn escape_str(str st, char to_escape) -> str {
|
||||
let str out = "";
|
||||
auto len = _str.byte_len(st);
|
||||
auto i = 0u;
|
||||
while (i < len) {
|
||||
alt (st.(i) as char) {
|
||||
case ('\n') {out += "\\n";}
|
||||
case ('\t') {out += "\\t";}
|
||||
case ('\r') {out += "\\r";}
|
||||
case ('\\') {out += "\\\\";}
|
||||
case (?cur) {
|
||||
if (cur == to_escape) {out += "\\";}
|
||||
out += cur as u8;
|
||||
}
|
||||
}
|
||||
i += 1u;
|
||||
}
|
||||
ret out;
|
||||
}
|
||||
|
||||
impure fn print_string(ps s, str st) {
|
||||
wrd(s, "\""); wrd(s, escape_str(st, '"')); wrd(s, "\"");
|
||||
}
|
||||
|
|
@ -5,9 +5,12 @@ use std;
|
|||
|
||||
mod front {
|
||||
mod ast;
|
||||
mod extfmt;
|
||||
mod lexer;
|
||||
mod parser;
|
||||
mod pretty;
|
||||
mod token;
|
||||
mod eval;
|
||||
}
|
||||
|
||||
mod middle {
|
||||
|
|
@ -28,6 +31,11 @@ mod driver {
|
|||
mod session;
|
||||
}
|
||||
|
||||
mod pretty {
|
||||
mod pp;
|
||||
mod pprust;
|
||||
}
|
||||
|
||||
mod util {
|
||||
mod common;
|
||||
}
|
||||
|
|
@ -38,7 +46,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") {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@ import std._uint;
|
|||
import std._int;
|
||||
import front.ast;
|
||||
|
||||
|
||||
type filename = str;
|
||||
type pos = rec(uint line, uint col);
|
||||
type span = rec(str filename, pos lo, pos hi);
|
||||
type span = rec(filename filename, pos lo, pos hi);
|
||||
type spanned[T] = rec(T node, span span);
|
||||
|
||||
tag ty_mach {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue