2011-07-05 16:23:07 -07:00
|
|
|
// The Rust abstract syntax tree.
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-05 16:23:07 -07:00
|
|
|
import std::ivec;
|
2011-05-12 17:24:54 +02:00
|
|
|
import std::option;
|
2011-05-17 20:41:41 +02:00
|
|
|
import std::str;
|
2011-07-05 11:48:19 +02:00
|
|
|
import codemap::span;
|
|
|
|
import codemap::filename;
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type spanned[T] = {node: T, span: span};
|
|
|
|
fn respan[T](sp: &span, t: &T) -> spanned[T] { ret {node: t, span: sp}; }
|
2010-08-18 09:00:10 -07:00
|
|
|
|
|
|
|
type ident = str;
|
2011-06-24 15:11:22 -07:00
|
|
|
// Functions may or may not have names.
|
|
|
|
type fn_ident = option::t[ident];
|
2010-08-18 09:00:10 -07:00
|
|
|
|
2011-06-24 22:17:17 -07:00
|
|
|
// FIXME: with typestate constraint, could say
|
|
|
|
// idents and types are the same length, and are
|
|
|
|
// non-empty
|
2011-07-27 14:19:39 +02:00
|
|
|
type path_ = {global: bool, idents: ident[], types: (@ty)[]};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-01-13 17:42:28 -08:00
|
|
|
type path = spanned[path_];
|
2010-10-04 17:25:52 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
fn path_name(p: &path) -> str { path_name_i(p.node.idents) }
|
2011-07-08 20:52:54 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
fn path_name_i(idents: &ident[]) -> str { str::connect_ivec(idents, "::") }
|
A revised, improved alias-checker
The old system tried to ensure that the location an alias pointed at
would retain its type. That turned out to not be strong enough in the
face of aliases to the inside of tags.
The new system instead proves that values pointed to by aliases are
not replaced (or invalidated in some other way) at all. It knows of
two sufficient conditions for this, and tries to prove at least of
them:
A) The alias is 'immutably rooted' in a local, and this local is not
reassigned for the lifetime of the alias. Immutably rooted means
the alias refers to the local itself, or to something reachable
from the local through immutable dereferencing.
B) No value whose type might include the type of the 'inner mutable
element' of the thing the alias refers to (for example, the box in
rec(mutable x = @mutable int)) is from the outer scope is accessed
for the lifetime of the alias. This means for functions, no other
argument types may include the alias's inner mutable type. For alt,
for each, and for, it means the body does not refer to any locals
originating from outside their scope that include this type.
The lifetime of an alias in an alt, for each, or for body is defined
as the range from its definition to its last use, not to the point
where it goes out of scope. This makes working around these
restrictions somewhat less annoying. For example, you can assign to
your alt-ed value you don't refer to any bindings afterwards.
2011-06-07 11:20:51 +02:00
|
|
|
|
2010-10-05 18:21:44 -07:00
|
|
|
type crate_num = int;
|
2011-06-19 22:41:21 +02:00
|
|
|
type node_id = int;
|
2011-07-27 14:19:39 +02:00
|
|
|
type def_id = {crate: crate_num, node: node_id};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
const local_crate: crate_num = 0;
|
|
|
|
fn local_def(id: node_id) -> def_id { ret {crate: local_crate, node: id}; }
|
2010-10-18 16:15:25 -07:00
|
|
|
|
2011-04-12 15:09:50 -07:00
|
|
|
type ty_param = ident;
|
2010-11-24 18:01:20 -08:00
|
|
|
|
2010-10-18 16:15:25 -07:00
|
|
|
tag def {
|
2011-06-20 17:29:54 -07:00
|
|
|
def_fn(def_id, purity);
|
2010-12-30 15:27:19 -08:00
|
|
|
def_obj_field(def_id);
|
2010-10-18 16:15:25 -07:00
|
|
|
def_mod(def_id);
|
2011-03-10 21:33:53 -05:00
|
|
|
def_native_mod(def_id);
|
2010-10-18 16:15:25 -07:00
|
|
|
def_const(def_id);
|
|
|
|
def_arg(def_id);
|
|
|
|
def_local(def_id);
|
2011-06-15 11:19:50 -07:00
|
|
|
def_variant(def_id, /* tag */def_id);
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
/* variant */
|
2010-10-18 16:15:25 -07:00
|
|
|
def_ty(def_id);
|
2011-04-12 15:09:50 -07:00
|
|
|
def_ty_arg(uint);
|
2010-12-10 18:08:32 -08:00
|
|
|
def_binding(def_id);
|
2011-01-01 13:13:00 -05:00
|
|
|
def_use(def_id);
|
2011-02-07 15:07:27 -05:00
|
|
|
def_native_ty(def_id);
|
|
|
|
def_native_fn(def_id);
|
2011-07-22 12:34:47 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
|
2011-07-22 12:34:47 -07:00
|
|
|
/* A "fake" def for upvars. This never appears in the def_map, but
|
|
|
|
* freevars::def_lookup will return it for a def that is an upvar.
|
|
|
|
* It contains the actual def. */
|
|
|
|
def_upvar(def_id, @def);
|
2010-10-05 18:21:44 -07:00
|
|
|
}
|
2010-10-04 17:25:52 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
fn variant_def_ids(d: &def) -> {tg: def_id, var: def_id} {
|
|
|
|
alt d { def_variant(tag_id, var_id) { ret {tg: tag_id, var: var_id}; } }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn def_id_of_def(d: def) -> def_id {
|
|
|
|
alt d {
|
|
|
|
def_fn(id, _) { ret id; }
|
|
|
|
def_obj_field(id) { ret id; }
|
|
|
|
def_mod(id) { ret id; }
|
|
|
|
def_native_mod(id) { ret id; }
|
|
|
|
def_const(id) { ret id; }
|
|
|
|
def_arg(id) { ret id; }
|
|
|
|
def_local(id) { ret id; }
|
|
|
|
def_variant(_, id) { ret id; }
|
|
|
|
def_ty(id) { ret id; }
|
|
|
|
def_ty_arg(_) { fail; }
|
|
|
|
def_binding(id) { ret id; }
|
|
|
|
def_use(id) { ret id; }
|
|
|
|
def_native_ty(id) { ret id; }
|
|
|
|
def_native_fn(id) { ret id; }
|
|
|
|
def_upvar(id, _) { ret id; }
|
2011-03-29 13:21:16 -07:00
|
|
|
}
|
|
|
|
fail;
|
|
|
|
}
|
|
|
|
|
2011-06-29 18:07:15 -07:00
|
|
|
// The set of meta_items that define the compilation environment of the crate,
|
|
|
|
// used to drive conditional compilation
|
2011-07-05 17:57:34 -07:00
|
|
|
type crate_cfg = (@meta_item)[];
|
2011-06-29 18:07:15 -07:00
|
|
|
|
2010-10-05 18:21:44 -07:00
|
|
|
type crate = spanned[crate_];
|
2010-08-18 09:00:10 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type crate_ =
|
|
|
|
{directives: (@crate_directive)[],
|
|
|
|
module: _mod,
|
|
|
|
attrs: attribute[],
|
|
|
|
config: crate_cfg};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-02-23 14:37:39 -08:00
|
|
|
tag crate_directive_ {
|
2011-07-05 17:02:51 -07:00
|
|
|
cdir_src_mod(ident, option::t[filename], attribute[]);
|
2011-07-27 14:19:39 +02:00
|
|
|
cdir_dir_mod(ident,
|
|
|
|
option::t[filename],
|
|
|
|
(@crate_directive)[],
|
|
|
|
attribute[]);
|
2011-02-23 14:37:39 -08:00
|
|
|
cdir_view_item(@view_item);
|
|
|
|
cdir_syntax(path);
|
2011-04-19 13:35:49 -07:00
|
|
|
cdir_auth(path, _auth);
|
2011-02-23 14:37:39 -08:00
|
|
|
}
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
type crate_directive = spanned[crate_directive_];
|
2011-02-23 14:37:39 -08:00
|
|
|
|
2010-12-30 11:21:37 -05:00
|
|
|
type meta_item = spanned[meta_item_];
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-06-21 14:23:16 -07:00
|
|
|
tag meta_item_ {
|
|
|
|
meta_word(ident);
|
2011-07-05 17:57:34 -07:00
|
|
|
meta_list(ident, (@meta_item)[]);
|
2011-07-05 17:01:23 -07:00
|
|
|
meta_name_value(ident, lit);
|
2011-06-21 14:23:16 -07:00
|
|
|
}
|
2010-12-30 11:21:37 -05:00
|
|
|
|
2011-07-25 14:16:12 -07:00
|
|
|
type blk = spanned[blk_];
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type blk_ = {stmts: (@stmt)[], expr: option::t[@expr], id: node_id};
|
2010-08-18 09:00:10 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type pat = {id: node_id, node: pat_, span: span};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type field_pat = {ident: ident, pat: @pat};
|
2011-07-11 14:13:20 +02:00
|
|
|
|
2010-11-24 14:42:01 -08:00
|
|
|
tag pat_ {
|
2011-07-04 21:53:33 +02:00
|
|
|
pat_wild;
|
|
|
|
pat_bind(ident);
|
|
|
|
pat_lit(@lit);
|
2011-07-06 19:00:00 -07:00
|
|
|
pat_tag(path, (@pat)[]);
|
2011-07-11 14:13:20 +02:00
|
|
|
pat_rec(field_pat[], bool);
|
2011-07-13 10:50:16 +02:00
|
|
|
pat_box(@pat);
|
2010-11-24 14:42:01 -08:00
|
|
|
}
|
|
|
|
|
2011-07-08 16:27:55 +02:00
|
|
|
type pat_id_map = std::map::hashmap[str, ast::node_id];
|
|
|
|
|
|
|
|
// This is used because same-named variables in alternative patterns need to
|
|
|
|
// use the node_id of their namesake in the first pattern.
|
2011-07-27 14:19:39 +02:00
|
|
|
fn pat_id_map(pat: &@pat) -> pat_id_map {
|
|
|
|
let map = std::map::new_str_hash[node_id]();
|
|
|
|
fn walk(map: &pat_id_map, pat: &@pat) {
|
|
|
|
alt pat.node {
|
|
|
|
pat_bind(name) { map.insert(name, pat.id); }
|
|
|
|
pat_tag(_, sub) { for p: @pat in sub { walk(map, p); } }
|
|
|
|
pat_rec(fields, _) {
|
|
|
|
for f: field_pat in fields { walk(map, f.pat); }
|
|
|
|
}
|
|
|
|
pat_box(inner) { walk(map, inner); }
|
|
|
|
_ { }
|
2011-07-08 16:27:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
walk(map, pat);
|
|
|
|
ret map;
|
|
|
|
}
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
tag mutability { mut; imm; maybe_mut; }
|
2010-11-29 14:18:26 -08:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
tag layer { layer_value; layer_state; layer_gc; }
|
2010-12-03 18:03:28 -08:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
tag _auth { auth_unsafe; }
|
2010-12-03 18:03:28 -08:00
|
|
|
|
2011-07-19 18:21:41 -07:00
|
|
|
tag proto { proto_iter; proto_fn; proto_block; proto_closure; }
|
2011-02-18 17:30:57 -08:00
|
|
|
|
2010-09-27 18:25:02 -07:00
|
|
|
tag binop {
|
2010-09-28 10:30:34 -07:00
|
|
|
add;
|
|
|
|
sub;
|
|
|
|
mul;
|
|
|
|
div;
|
|
|
|
rem;
|
|
|
|
and;
|
|
|
|
or;
|
|
|
|
bitxor;
|
2010-09-27 18:25:02 -07:00
|
|
|
bitand;
|
|
|
|
bitor;
|
|
|
|
lsl;
|
|
|
|
lsr;
|
|
|
|
asr;
|
|
|
|
eq;
|
|
|
|
lt;
|
|
|
|
le;
|
|
|
|
ne;
|
|
|
|
ge;
|
|
|
|
gt;
|
|
|
|
}
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
fn binop_to_str(op: binop) -> str {
|
|
|
|
alt op {
|
|
|
|
add. { ret "+"; }
|
|
|
|
sub. { ret "-"; }
|
|
|
|
mul. { ret "*"; }
|
|
|
|
div. { ret "/"; }
|
|
|
|
rem. { ret "%"; }
|
|
|
|
and. { ret "&&"; }
|
|
|
|
or. { ret "||"; }
|
|
|
|
bitxor. { ret "^"; }
|
|
|
|
bitand. { ret "&"; }
|
|
|
|
bitor. { ret "|"; }
|
|
|
|
lsl. { ret "<<"; }
|
|
|
|
lsr. { ret ">>"; }
|
|
|
|
asr. { ret ">>>"; }
|
|
|
|
eq. { ret "=="; }
|
|
|
|
lt. { ret "<"; }
|
|
|
|
le. { ret "<="; }
|
|
|
|
ne. { ret "!="; }
|
|
|
|
ge. { ret ">="; }
|
|
|
|
gt. { ret ">"; }
|
2011-03-04 07:22:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
pred lazy_binop(b: binop) -> bool {
|
|
|
|
alt b { and. { true } or. { true } _ { false } }
|
2011-06-28 13:06:43 -07:00
|
|
|
}
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
tag unop { box(mutability); deref; not; neg; }
|
2010-09-27 18:25:02 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
fn unop_to_str(op: unop) -> str {
|
|
|
|
alt op {
|
|
|
|
box(mt) { if mt == mut { ret "@mutable "; } ret "@"; }
|
|
|
|
deref. { ret "*"; }
|
|
|
|
not. { ret "!"; }
|
|
|
|
neg. { ret "-"; }
|
2011-03-04 07:22:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
tag mode { val; alias(bool); }
|
2010-12-03 18:03:28 -08:00
|
|
|
|
2010-10-05 18:21:44 -07:00
|
|
|
type stmt = spanned[stmt_];
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2010-10-05 18:21:44 -07:00
|
|
|
tag stmt_ {
|
2011-06-19 22:41:21 +02:00
|
|
|
stmt_decl(@decl, node_id);
|
|
|
|
stmt_expr(@expr, node_id);
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
|
2011-02-24 15:54:55 -08:00
|
|
|
// These only exist in crate-level blocks.
|
|
|
|
stmt_crate_directive(@crate_directive);
|
2010-09-09 15:59:29 -07:00
|
|
|
}
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
tag init_op { init_assign; init_recv; init_move; }
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type initializer = {op: init_op, expr: @expr};
|
2011-03-24 21:04:29 -04:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
type local_ =
|
2011-07-27 14:19:39 +02:00
|
|
|
{ty: option::t[@ty],
|
|
|
|
infer: bool,
|
|
|
|
ident: ident,
|
|
|
|
init: option::t[initializer],
|
|
|
|
id: node_id};
|
2011-03-24 21:04:29 -04:00
|
|
|
|
2011-06-16 15:58:25 -07:00
|
|
|
type local = spanned[local_];
|
2010-10-18 18:19:16 -07:00
|
|
|
|
2010-10-05 18:21:44 -07:00
|
|
|
type decl = spanned[decl_];
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-22 17:19:06 +02:00
|
|
|
tag decl_ { decl_local((@local)[]); decl_item(@item); }
|
2010-09-09 15:59:29 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type arm = {pats: (@pat)[], block: blk};
|
2010-11-24 15:45:59 -08:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type elt = {mut: mutability, expr: @expr};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type field_ = {mut: mutability, ident: ident, expr: @expr};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-05-30 15:56:01 -07:00
|
|
|
type field = spanned[field_];
|
2010-11-30 16:31:43 -08:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
tag spawn_dom { dom_implicit; dom_thread; }
|
|
|
|
|
2011-06-28 16:29:37 -07:00
|
|
|
tag check_mode { checked; unchecked; }
|
2011-03-26 00:53:57 -04:00
|
|
|
|
2011-06-09 17:11:21 -07:00
|
|
|
// FIXME: temporary
|
2011-06-15 11:19:50 -07:00
|
|
|
tag seq_kind { sk_unique; sk_rc; }
|
2011-06-09 17:11:21 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type expr = {id: node_id, node: expr_, span: span};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2010-10-05 18:21:44 -07:00
|
|
|
tag expr_ {
|
2011-07-06 19:00:00 -07:00
|
|
|
expr_vec((@expr)[], mutability, seq_kind);
|
|
|
|
expr_rec(field[], option::t[@expr]);
|
|
|
|
expr_call(@expr, (@expr)[]);
|
2011-06-21 22:16:40 +02:00
|
|
|
expr_self_method(ident);
|
2011-07-06 19:00:00 -07:00
|
|
|
expr_bind(@expr, (option::t[@expr])[]);
|
|
|
|
expr_spawn(spawn_dom, option::t[str], @expr, (@expr)[]);
|
2011-06-21 22:16:40 +02:00
|
|
|
expr_binary(binop, @expr, @expr);
|
|
|
|
expr_unary(unop, @expr);
|
|
|
|
expr_lit(@lit);
|
|
|
|
expr_cast(@expr, @ty);
|
2011-07-25 14:16:12 -07:00
|
|
|
expr_if(@expr, blk, option::t[@expr]);
|
2011-06-23 15:15:50 -07:00
|
|
|
expr_ternary(@expr, @expr, @expr);
|
2011-07-25 14:16:12 -07:00
|
|
|
expr_while(@expr, blk);
|
|
|
|
expr_for(@local, @expr, blk);
|
|
|
|
expr_for_each(@local, @expr, blk);
|
|
|
|
expr_do_while(blk, @expr);
|
2011-07-06 19:00:00 -07:00
|
|
|
expr_alt(@expr, arm[]);
|
2011-06-21 22:16:40 +02:00
|
|
|
expr_fn(_fn);
|
2011-07-25 14:16:12 -07:00
|
|
|
expr_block(blk);
|
2011-07-27 14:19:39 +02:00
|
|
|
|
2011-06-16 16:55:46 -07:00
|
|
|
/*
|
|
|
|
* FIXME: many of these @exprs should be constrained with
|
|
|
|
* is_lval once we have constrained types working.
|
|
|
|
*/
|
2011-06-21 22:16:40 +02:00
|
|
|
expr_move(@expr, @expr);
|
2011-07-27 14:19:39 +02:00
|
|
|
expr_assign(@expr, @expr);
|
2011-06-21 22:16:40 +02:00
|
|
|
expr_swap(@expr, @expr);
|
|
|
|
expr_assign_op(binop, @expr, @expr);
|
|
|
|
expr_send(@expr, @expr);
|
|
|
|
expr_recv(@expr, @expr);
|
|
|
|
expr_field(@expr, ident);
|
|
|
|
expr_index(@expr, @expr);
|
|
|
|
expr_path(path);
|
2011-07-01 14:33:15 -04:00
|
|
|
expr_fail(option::t[@expr]);
|
2011-06-21 22:16:40 +02:00
|
|
|
expr_break;
|
|
|
|
expr_cont;
|
|
|
|
expr_ret(option::t[@expr]);
|
|
|
|
expr_put(option::t[@expr]);
|
|
|
|
expr_be(@expr);
|
|
|
|
expr_log(int, @expr);
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
/* just an assert, no significance to typestate */
|
2011-06-21 22:16:40 +02:00
|
|
|
expr_assert(@expr);
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
/* preds that typestate is aware of */
|
2011-06-28 16:29:37 -07:00
|
|
|
expr_check(check_mode, @expr);
|
2011-07-27 14:19:39 +02:00
|
|
|
|
|
|
|
/* FIXME Would be nice if expr_check desugared
|
|
|
|
to expr_if_check. */
|
2011-07-25 14:16:12 -07:00
|
|
|
expr_if_check(@expr, blk, option::t[@expr]);
|
2011-06-28 15:54:16 -07:00
|
|
|
expr_port(option::t[@ty]);
|
2011-07-08 16:35:09 -07:00
|
|
|
expr_chan(@expr);
|
2011-07-21 15:08:15 -07:00
|
|
|
expr_anon_obj(anon_obj);
|
2011-07-08 16:35:09 -07:00
|
|
|
expr_mac(mac);
|
|
|
|
}
|
|
|
|
|
|
|
|
type mac = spanned[mac_];
|
|
|
|
|
|
|
|
tag mac_ {
|
|
|
|
mac_invoc(path, (@expr)[], option::t[str]);
|
|
|
|
mac_embed_type(@ty);
|
2011-07-25 14:16:12 -07:00
|
|
|
mac_embed_block(blk);
|
2011-07-11 16:13:17 -07:00
|
|
|
mac_ellipsis;
|
2010-09-09 15:59:29 -07:00
|
|
|
}
|
|
|
|
|
2010-10-05 18:21:44 -07:00
|
|
|
type lit = spanned[lit_];
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2010-10-05 18:21:44 -07:00
|
|
|
tag lit_ {
|
2011-06-09 17:11:21 -07:00
|
|
|
lit_str(str, seq_kind);
|
2010-09-09 15:59:29 -07:00
|
|
|
lit_char(char);
|
|
|
|
lit_int(int);
|
2010-09-21 16:22:32 -07:00
|
|
|
lit_uint(uint);
|
2010-11-22 17:41:26 -08:00
|
|
|
lit_mach_int(ty_mach, int);
|
2011-03-21 17:12:05 -07:00
|
|
|
lit_float(str);
|
2011-03-22 17:25:40 -07:00
|
|
|
lit_mach_float(ty_mach, str);
|
2010-09-20 23:56:43 -07:00
|
|
|
lit_nil;
|
2010-09-09 15:59:29 -07:00
|
|
|
lit_bool(bool);
|
|
|
|
}
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
fn is_path(e: &@expr) -> bool {
|
|
|
|
ret alt e.node { expr_path(_) { true } _ { false } };
|
2011-06-25 12:16:48 +02:00
|
|
|
}
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2010-11-03 16:43:12 -07:00
|
|
|
// NB: If you change this, you'll probably want to change the corresponding
|
2010-12-21 12:13:51 -08:00
|
|
|
// type structure in middle/ty.rs as well.
|
2011-07-27 14:19:39 +02:00
|
|
|
type mt = {ty: @ty, mut: mutability};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type ty_field_ = {ident: ident, mt: mt};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type ty_arg_ = {mode: mode, ty: @ty};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
|
|
|
type ty_method_ =
|
2011-07-27 14:19:39 +02:00
|
|
|
{proto: proto,
|
|
|
|
ident: ident,
|
|
|
|
inputs: ty_arg[],
|
|
|
|
output: @ty,
|
|
|
|
cf: controlflow,
|
|
|
|
constrs: (@constr)[]};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-06-03 15:26:03 -07:00
|
|
|
type ty_field = spanned[ty_field_];
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-06-03 15:26:03 -07:00
|
|
|
type ty_arg = spanned[ty_arg_];
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-06-03 15:26:03 -07:00
|
|
|
type ty_method = spanned[ty_method_];
|
|
|
|
|
2011-07-05 11:48:19 +02:00
|
|
|
tag ty_mach {
|
|
|
|
ty_i8;
|
|
|
|
ty_i16;
|
|
|
|
ty_i32;
|
|
|
|
ty_i64;
|
|
|
|
ty_u8;
|
|
|
|
ty_u16;
|
|
|
|
ty_u32;
|
|
|
|
ty_u64;
|
|
|
|
ty_f32;
|
|
|
|
ty_f64;
|
|
|
|
}
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
fn ty_mach_to_str(tm: ty_mach) -> str {
|
|
|
|
alt tm {
|
|
|
|
ty_u8. { ret "u8"; }
|
|
|
|
ty_u16. { ret "u16"; }
|
|
|
|
ty_u32. { ret "u32"; }
|
|
|
|
ty_u64. { ret "u64"; }
|
|
|
|
ty_i8. { ret "i8"; }
|
|
|
|
ty_i16. { ret "i16"; }
|
|
|
|
ty_i32. { ret "i32"; }
|
|
|
|
ty_i64. { ret "i64"; }
|
|
|
|
ty_f32. { ret "f32"; }
|
|
|
|
ty_f64. { ret "f64"; }
|
2011-07-05 11:48:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-05 18:21:44 -07:00
|
|
|
type ty = spanned[ty_];
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2010-10-05 18:21:44 -07:00
|
|
|
tag ty_ {
|
2010-09-20 23:56:43 -07:00
|
|
|
ty_nil;
|
2011-05-14 19:02:30 -07:00
|
|
|
ty_bot; /* return type of ! functions and type of
|
|
|
|
ret/fail/break/cont. there is no syntax
|
|
|
|
for this type. */
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
/* bot represents the value of functions that don't return a value
|
|
|
|
locally to their context. in contrast, things like log that do
|
|
|
|
return, but don't return a meaningful value, have result type nil. */
|
2011-07-27 14:19:39 +02:00
|
|
|
ty_bool;
|
2010-09-20 23:56:43 -07:00
|
|
|
ty_int;
|
2010-09-21 16:22:32 -07:00
|
|
|
ty_uint;
|
2011-03-21 17:12:05 -07:00
|
|
|
ty_float;
|
2011-07-05 11:48:19 +02:00
|
|
|
ty_machine(ty_mach);
|
2010-09-20 23:56:43 -07:00
|
|
|
ty_char;
|
2010-09-21 16:22:32 -07:00
|
|
|
ty_str;
|
2011-06-15 11:19:50 -07:00
|
|
|
ty_istr; // interior string
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
|
|
|
|
|
2011-03-17 17:39:47 -07:00
|
|
|
ty_box(mt);
|
|
|
|
ty_vec(mt);
|
2011-06-15 11:19:50 -07:00
|
|
|
ty_ivec(mt); // interior vector
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
|
|
|
|
|
2011-06-03 14:34:19 -04:00
|
|
|
ty_ptr(mt);
|
2011-05-31 16:27:39 -07:00
|
|
|
ty_task;
|
2011-03-10 22:58:55 -05:00
|
|
|
ty_port(@ty);
|
|
|
|
ty_chan(@ty);
|
2011-07-06 16:01:47 -07:00
|
|
|
ty_rec(ty_field[]);
|
2011-07-06 16:12:39 -07:00
|
|
|
ty_fn(proto, ty_arg[], @ty, controlflow, (@constr)[]);
|
2011-07-06 16:01:47 -07:00
|
|
|
ty_obj(ty_method[]);
|
2011-06-19 22:41:21 +02:00
|
|
|
ty_path(path, node_id);
|
2011-02-01 14:56:21 -08:00
|
|
|
ty_type;
|
2011-07-19 17:52:34 -07:00
|
|
|
ty_constr(@ty, (@ty_constr)[]);
|
2011-07-08 16:35:09 -07:00
|
|
|
ty_mac(mac);
|
2010-09-09 15:59:29 -07:00
|
|
|
}
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-06-10 19:12:42 -07:00
|
|
|
/*
|
|
|
|
A constraint arg that's a function argument is referred to by its position
|
|
|
|
rather than name. This is so we could have higher-order functions that have
|
|
|
|
constraints (potentially -- right now there's no way to write that), and also
|
|
|
|
so that the typestate pass doesn't have to map a function name onto its decl.
|
|
|
|
So, the constr_arg type is parameterized: it's instantiated with uint for
|
|
|
|
declarations, and ident for uses.
|
|
|
|
*/
|
2011-06-15 11:19:50 -07:00
|
|
|
tag constr_arg_general_[T] { carg_base; carg_ident(T); carg_lit(@lit); }
|
|
|
|
|
2011-07-19 17:52:34 -07:00
|
|
|
type fn_constr_arg = constr_arg_general_[uint];
|
|
|
|
type sp_constr_arg[T] = spanned[constr_arg_general_[T]];
|
|
|
|
type ty_constr_arg = sp_constr_arg[path];
|
|
|
|
type constr_arg = spanned[fn_constr_arg];
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-19 17:52:34 -07:00
|
|
|
// Constrained types' args are parameterized by paths, since
|
|
|
|
// we refer to paths directly and not by indices.
|
|
|
|
// The implicit root of such path, in the constraint-list for a
|
|
|
|
// constrained type, is * (referring to the base record)
|
2011-06-10 19:12:42 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type constr_general_[ARG, ID] =
|
|
|
|
{path: path, args: (@spanned[constr_arg_general_[ARG]])[], id: ID};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-19 17:52:34 -07:00
|
|
|
// In the front end, constraints have a node ID attached.
|
|
|
|
// Typeck turns this to a def_id, using the output of resolve.
|
|
|
|
type constr_general[ARG] = spanned[constr_general_[ARG, node_id]];
|
|
|
|
type constr_ = constr_general_[uint, node_id];
|
|
|
|
type constr = spanned[constr_general_[uint, node_id]];
|
|
|
|
type ty_constr_ = ast::constr_general_[ast::path, ast::node_id];
|
|
|
|
type ty_constr = spanned[ty_constr_];
|
2011-06-16 16:55:46 -07:00
|
|
|
|
2011-06-15 15:14:30 -07:00
|
|
|
/* The parser generates ast::constrs; resolve generates
|
|
|
|
a mapping from each function to a list of ty::constr_defs,
|
|
|
|
corresponding to these. */
|
2011-07-27 14:19:39 +02:00
|
|
|
type arg = {mode: mode, ty: @ty, ident: ident, id: node_id};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
|
|
|
type fn_decl =
|
2011-07-27 14:19:39 +02:00
|
|
|
{inputs: arg[],
|
|
|
|
output: @ty,
|
|
|
|
purity: purity,
|
|
|
|
cf: controlflow,
|
|
|
|
constraints: (@constr)[]};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-05-04 11:28:13 -07:00
|
|
|
tag purity {
|
2011-06-15 11:19:50 -07:00
|
|
|
pure_fn; // declared with "pred"
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
|
|
|
|
|
2011-05-04 11:28:13 -07:00
|
|
|
impure_fn; // declared with "fn"
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-05-04 11:28:13 -07:00
|
|
|
}
|
|
|
|
|
2011-05-14 19:02:30 -07:00
|
|
|
tag controlflow {
|
|
|
|
noreturn; // functions with return type _|_ that always
|
|
|
|
// raise an error or exit (i.e. never return to the caller)
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
return; // everything else
|
|
|
|
|
2011-05-14 19:02:30 -07:00
|
|
|
}
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type _fn = {decl: fn_decl, proto: proto, body: blk};
|
2010-08-18 09:00:10 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type method_ = {ident: ident, meth: _fn, id: node_id};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2010-12-14 15:32:13 -08:00
|
|
|
type method = spanned[method_];
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type obj_field = {mut: mutability, ty: @ty, ident: ident, id: node_id};
|
|
|
|
type anon_obj_field =
|
|
|
|
{mut: mutability, ty: @ty, expr: @expr, ident: ident, id: node_id};
|
2010-12-14 15:32:13 -08:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
type _obj =
|
2011-07-27 14:19:39 +02:00
|
|
|
{fields: obj_field[], methods: (@method)[], dtor: option::t[@method]};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
|
|
|
type anon_obj =
|
2011-07-27 14:19:39 +02:00
|
|
|
// New fields and methods, if they exist.
|
2011-05-06 17:08:41 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
// with_obj: the original object being extended, if it exists.
|
|
|
|
{fields: option::t[anon_obj_field[]],
|
|
|
|
methods: (@method)[],
|
|
|
|
with_obj: option::t[@expr]};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type _mod = {view_items: (@view_item)[], items: (@item)[]};
|
2010-08-18 09:00:10 -07:00
|
|
|
|
2011-02-23 14:06:37 -05:00
|
|
|
tag native_abi {
|
|
|
|
native_abi_rust;
|
|
|
|
native_abi_cdecl;
|
2011-03-28 08:24:11 -07:00
|
|
|
native_abi_llvm;
|
2011-05-03 18:03:59 -07:00
|
|
|
native_abi_rust_intrinsic;
|
2011-07-18 13:14:33 -07:00
|
|
|
native_abi_x86stdcall;
|
2011-02-23 14:06:37 -05:00
|
|
|
}
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
type native_mod =
|
2011-07-27 14:19:39 +02:00
|
|
|
{native_name: str,
|
|
|
|
abi: native_abi,
|
|
|
|
view_items: (@view_item)[],
|
|
|
|
items: (@native_item)[]};
|
2011-02-01 13:40:04 -05:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type variant_arg = {ty: @ty, id: node_id};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type variant_ = {name: str, args: variant_arg[], id: node_id};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-03-29 12:46:55 +02:00
|
|
|
type variant = spanned[variant_];
|
2010-11-24 11:36:35 -08:00
|
|
|
|
2011-01-01 12:55:18 -05:00
|
|
|
type view_item = spanned[view_item_];
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-01-01 12:55:18 -05:00
|
|
|
tag view_item_ {
|
2011-07-05 17:57:34 -07:00
|
|
|
view_item_use(ident, (@meta_item)[], node_id);
|
2011-07-07 15:31:54 -07:00
|
|
|
view_item_import(ident, ident[], node_id);
|
|
|
|
view_item_import_glob(ident[], node_id);
|
2011-06-19 22:41:21 +02:00
|
|
|
view_item_export(ident, node_id);
|
2011-01-01 12:55:18 -05:00
|
|
|
}
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type obj_def_ids = {ty: node_id, ctor: node_id};
|
2011-03-30 17:23:25 -07:00
|
|
|
|
2011-06-14 16:13:19 -07:00
|
|
|
|
|
|
|
// Meta-data associated with an item
|
|
|
|
type attribute = spanned[attribute_];
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-06-14 16:13:19 -07:00
|
|
|
// Distinguishes between attributes that decorate items and attributes that
|
|
|
|
// are contained as statements within items. These two cases need to be
|
|
|
|
// distinguished for pretty-printing.
|
2011-06-15 11:19:50 -07:00
|
|
|
tag attr_style { attr_outer; attr_inner; }
|
2011-06-14 16:13:19 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type attribute_ = {style: attr_style, value: meta_item};
|
2011-06-14 16:13:19 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type item = // For objs and resources, this is the type def_id
|
|
|
|
{ident: ident, attrs: attribute[], id: node_id, node: item_, span: span};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2010-10-05 18:21:44 -07:00
|
|
|
tag item_ {
|
2011-06-16 11:53:06 +02:00
|
|
|
item_const(@ty, @expr);
|
2011-07-06 19:00:00 -07:00
|
|
|
item_fn(_fn, ty_param[]);
|
2011-06-16 11:53:06 +02:00
|
|
|
item_mod(_mod);
|
|
|
|
item_native_mod(native_mod);
|
2011-07-06 19:00:00 -07:00
|
|
|
item_ty(@ty, ty_param[]);
|
|
|
|
item_tag(variant[], ty_param[]);
|
2011-07-27 14:19:39 +02:00
|
|
|
item_obj(_obj, ty_param[], /* constructor id */node_id);
|
|
|
|
item_res(
|
|
|
|
/* dtor */
|
|
|
|
_fn,
|
|
|
|
|
|
|
|
/* dtor id */
|
|
|
|
node_id,
|
|
|
|
ty_param[],
|
|
|
|
|
|
|
|
/* ctor id */
|
|
|
|
node_id);
|
2011-05-11 15:10:24 +02:00
|
|
|
}
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
type native_item =
|
|
|
|
{ident: ident,
|
|
|
|
attrs: attribute[],
|
|
|
|
node: native_item_,
|
|
|
|
id: node_id,
|
|
|
|
span: span};
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-02-02 10:43:57 -05:00
|
|
|
tag native_item_ {
|
2011-06-21 23:01:08 +02:00
|
|
|
native_item_ty;
|
2011-07-06 19:00:00 -07:00
|
|
|
native_item_fn(option::t[str], fn_decl, ty_param[]);
|
2011-02-02 10:43:57 -05:00
|
|
|
}
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
fn is_exported(i: ident, m: _mod) -> bool {
|
|
|
|
let nonlocal = true;
|
|
|
|
for it: @ast::item in m.items {
|
|
|
|
if it.ident == i { nonlocal = false; }
|
|
|
|
alt it.node {
|
|
|
|
item_tag(variants, _) {
|
|
|
|
for v: variant in variants {
|
|
|
|
if v.node.name == i { nonlocal = false; }
|
2011-05-31 18:24:06 -07:00
|
|
|
}
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
|
|
|
_ { }
|
2011-05-31 18:24:06 -07:00
|
|
|
}
|
2011-07-27 14:19:39 +02:00
|
|
|
if !nonlocal { break; }
|
2011-05-31 18:24:06 -07:00
|
|
|
}
|
2011-07-27 14:19:39 +02:00
|
|
|
let count = 0u;
|
|
|
|
for vi: @ast::view_item in m.view_items {
|
|
|
|
alt vi.node {
|
|
|
|
ast::view_item_export(id, _) {
|
|
|
|
if str::eq(i, id) {
|
|
|
|
// even if it's nonlocal (since it's explicit)
|
|
|
|
|
|
|
|
ret true;
|
2011-05-02 20:29:39 -04:00
|
|
|
}
|
2011-07-27 14:19:39 +02:00
|
|
|
count += 1u;
|
|
|
|
}
|
|
|
|
_ {/* fall through */ }
|
2011-05-02 20:29:39 -04:00
|
|
|
}
|
|
|
|
}
|
2011-07-13 15:44:09 -07:00
|
|
|
// If there are no declared exports then
|
2011-05-31 18:24:06 -07:00
|
|
|
// everything not imported is exported
|
2011-06-16 16:55:46 -07:00
|
|
|
|
2011-06-16 11:53:06 +02:00
|
|
|
ret count == 0u && !nonlocal;
|
2011-05-02 20:29:39 -04:00
|
|
|
}
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
fn is_call_expr(e: @expr) -> bool {
|
|
|
|
alt e.node { expr_call(_, _) { ret true; } _ { ret false; } }
|
2011-02-09 22:36:37 -05:00
|
|
|
}
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
fn is_constraint_arg(e: @expr) -> bool {
|
|
|
|
alt e.node {
|
|
|
|
expr_lit(_) { ret true; }
|
|
|
|
expr_path(_) { ret true; }
|
|
|
|
_ { ret false; }
|
2011-05-02 14:28:35 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
fn eq_ty(a: &@ty, b: &@ty) -> bool { ret std::box::ptr_eq(a, b); }
|
2011-06-02 14:03:17 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
fn hash_ty(t: &@ty) -> uint { ret t.span.lo << 16u + t.span.hi; }
|
2011-06-23 15:15:50 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
fn block_from_expr(e: @expr) -> blk {
|
|
|
|
let blk_ = {stmts: ~[], expr: option::some[@expr](e), id: e.id};
|
|
|
|
ret {node: blk_, span: e.span};
|
2011-06-23 15:15:50 -07:00
|
|
|
}
|
|
|
|
|
2011-07-21 15:10:12 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
fn obj_field_from_anon_obj_field(f: &anon_obj_field) -> obj_field {
|
|
|
|
ret {mut: f.mut, ty: f.ty, ident: f.ident, id: f.id};
|
2011-07-21 15:10:12 -07:00
|
|
|
}
|
|
|
|
|
2011-06-23 15:15:50 -07:00
|
|
|
// This is a convenience function to transfor ternary expressions to if
|
|
|
|
// expressions so that they can be treated the same
|
2011-07-27 14:19:39 +02:00
|
|
|
fn ternary_to_if(e: &@expr) -> @ast::expr {
|
|
|
|
alt e.node {
|
|
|
|
expr_ternary(cond, then, els) {
|
|
|
|
let then_blk = block_from_expr(then);
|
|
|
|
let els_blk = block_from_expr(els);
|
|
|
|
let els_expr =
|
|
|
|
@{id: els.id, node: expr_block(els_blk), span: els.span};
|
|
|
|
ret @{id: e.id,
|
|
|
|
node: expr_if(cond, then_blk, option::some(els_expr)),
|
|
|
|
span: e.span};
|
|
|
|
}
|
|
|
|
_ { fail; }
|
2011-06-23 15:15:50 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-12 10:27:50 -07:00
|
|
|
//
|
|
|
|
// Local Variables:
|
|
|
|
// mode: rust
|
|
|
|
// fill-column: 78;
|
|
|
|
// indent-tabs-mode: nil
|
|
|
|
// c-basic-offset: 4
|
|
|
|
// buffer-file-coding-system: utf-8-unix
|
2011-03-25 15:07:27 -07:00
|
|
|
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
|
2010-08-12 10:27:50 -07:00
|
|
|
// End:
|
|
|
|
//
|