create serializer project which autogenerates serialization code
This commit is contained in:
parent
5d57fa3403
commit
dbcb54f4dc
653
src/comp/metadata/astencode.rs
Normal file
653
src/comp/metadata/astencode.rs
Normal file
@ -0,0 +1,653 @@
|
||||
// Encoding of ASTs and the associated side tables.
|
||||
|
||||
import middle::base::trans::common::crate_ctxt;
|
||||
import syntax::ast;
|
||||
import syntax::codemap::{span, filename};
|
||||
import std::ebml::writer;
|
||||
import metadata::common::*;
|
||||
|
||||
enum ast_tag {
|
||||
at_span,
|
||||
at_id,
|
||||
|
||||
at_span_expninfo_callie_name,
|
||||
at_span_expninfo_callie_span,
|
||||
|
||||
at_blk,
|
||||
at_blk_stmts,
|
||||
at_blk_expr,
|
||||
at_blk_rules,
|
||||
|
||||
at_stmt,
|
||||
at_stmt_node_decl,
|
||||
at_stmt_node_expr,
|
||||
|
||||
at_expr,
|
||||
at_expr_node_vec,
|
||||
at_expr_node_rec,
|
||||
at_expr_node_call,
|
||||
at_expr_node_tup,
|
||||
at_expr_node_bind,
|
||||
at_expr_node_bind_args,
|
||||
at_expr_node_binary,
|
||||
at_expr_node_unary,
|
||||
at_expr_node_lit,
|
||||
at_expr_node_cast,
|
||||
at_expr_node_if,
|
||||
at_expr_node_while,
|
||||
|
||||
at_none,
|
||||
at_some,
|
||||
}
|
||||
|
||||
type ast_ctxt = {
|
||||
embl_w: ebml::writer,
|
||||
ccx: crate_ctxt,
|
||||
};
|
||||
|
||||
impl ast_output for ast_ctxt {
|
||||
fn tag(tag: ast_tag, blk: fn()) {
|
||||
self.embl_w.wr_tag(tag as uint, blk)
|
||||
}
|
||||
|
||||
fn uint(v: uint) {
|
||||
self.embl_w.wr_uint(v)
|
||||
}
|
||||
|
||||
fn opt<T>(x: option<T>, blk: fn(T)) {
|
||||
alt x {
|
||||
none { self.tag(at_none) {||} }
|
||||
some(v) { self.tag(at_some) {|| blk(v) } }
|
||||
}
|
||||
}
|
||||
|
||||
fn str(tag: ast_tag, v: str) {
|
||||
self.tag(tag) {|| self.embl_w.wr_str(v) };
|
||||
}
|
||||
|
||||
fn vec<T>(tag: ast_tag, v: [T], blk: fn(T)) {
|
||||
self.tag(tag) {||
|
||||
self.uint(vec::len(v));
|
||||
vec::iter(v) {|e| blk(e) };
|
||||
}
|
||||
}
|
||||
|
||||
fn span(sp: span) {
|
||||
self.tag(at_span) {||
|
||||
self.uint(sp.lo);
|
||||
self.uint(sp.hi);
|
||||
self.opt(sp.expn_info) {|ei|
|
||||
self.span(ei.call_site);
|
||||
self.str(at_span_expninfo_callie_name, ei.callie.name);
|
||||
self.opt(ei.callie.span) {|v| self.span(v) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn id(id: uint) {
|
||||
self.tag(at_id) {|| self.uint(id); }
|
||||
}
|
||||
|
||||
fn blk(blk: ast::blk) {
|
||||
self.tag(at_blk) {||
|
||||
self.id(blk.node.id);
|
||||
self.span(blk.span);
|
||||
self.vec(at_blk_stmts, blk.node.stmts) {|stmt|
|
||||
self.stmt(stmt)
|
||||
}
|
||||
self.tag(at_blk_expr) {||
|
||||
self.opt(blk.node.expr) {|e| self.expr(e) }
|
||||
}
|
||||
self.tag(at_blk_rules) {||
|
||||
self.uint(blk.node.rules as uint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn decl(decl: ast::decl) {
|
||||
self.span(decl.span);
|
||||
alt decl.node {
|
||||
ast::decl_local(lcls) {
|
||||
self.vec(at_decl_local, lcls) {|lcl|
|
||||
self.local(lcl)
|
||||
}
|
||||
}
|
||||
|
||||
ast::decl_item(item) {
|
||||
self.tag(at_decl_item) {||
|
||||
self.item(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn local(lcl: ast::local) {
|
||||
self.span(lcl.span);
|
||||
self.ty(lcl.ty);
|
||||
self.pat(lcl.pat);
|
||||
self.opt(lcl.init) {|i| self.initializer(i) };
|
||||
self.uint(lcl.id);
|
||||
}
|
||||
|
||||
fn pat(pat: ast::pat) {
|
||||
self.uint(pat.id);
|
||||
self.span(pat.span);
|
||||
alt pat_util::normalize_pat(pat.node) {
|
||||
pat_wild {
|
||||
self.tag(at_pat_wild) {||
|
||||
}
|
||||
}
|
||||
pat_ident(path, o_pat) {
|
||||
self.tag(at_pat_ident) {||
|
||||
self.path(path);
|
||||
self.opt(o_pat) {|p|
|
||||
self.pat(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
pat_enum(path, pats) {
|
||||
self.tag(at_pat_enum) {||
|
||||
self.path(path);
|
||||
self.vec(at_pat_enum_pats, pats) {|p| self.pat(p) };
|
||||
}
|
||||
}
|
||||
pat_rec(field_pats, b) {
|
||||
self.tag(at_pat_rec) {||
|
||||
self.vec(at_pat_rec_fields, field_pats) {|p|
|
||||
self.field_pat(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
pat_tup(pats) {
|
||||
self.vec(at_pat_tup, pats) {|p| self.pat(p); }
|
||||
}
|
||||
pat_box(pat) {
|
||||
self.tag(at_pat_box) {|| self.pat(pat) }
|
||||
}
|
||||
pat_lit(expr) {
|
||||
self.tag(at_pat_lit) {|| self.expr(expr) }
|
||||
}
|
||||
pat_range(l, h) {
|
||||
self.tag(at_pat_range) {||
|
||||
self.expr(l);
|
||||
self.expr(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn stmt(stmt: ast::stmt) {
|
||||
self.tag(at_stmt) {||
|
||||
self.span(stmt.span);
|
||||
alt stmt.node {
|
||||
ast::stmt_decl(d, nid) {
|
||||
self.id(nid);
|
||||
self.tag(at_stmt_node_decl) {|| self.decl(d) };
|
||||
}
|
||||
ast::stmt_expr(e, nid) | ast::stmt_semi(e, nid) {
|
||||
self.id(nid);
|
||||
self.tag(at_stmt_node_expr) {|| self.expr(e) };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn exprs(exprs: [ast::expr]) {
|
||||
self.vec(at_exprs, exprs) {|e| self.expr(e) };
|
||||
}
|
||||
|
||||
fn expr(expr: ast:expr) {
|
||||
self.id(expr.id);
|
||||
self.span(expr.span);
|
||||
alt expr.node {
|
||||
ast::expr_vec(subexprs, mutbl) {
|
||||
self.tag(at_expr_node_vec) {||
|
||||
self.exprs(subexprs);
|
||||
self.mutbl(mutbl);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_rec(fields, opt_expr) {
|
||||
self.tag(at_expr_node_rec) {||
|
||||
self.fields(fields);
|
||||
self.opt(opt_expr) {|e| self.expr(e) };
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_call(func, args, _) {
|
||||
self.tag(at_expr_node_call) {||
|
||||
self.expr(func);
|
||||
self.exprs(args);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_tup(exprs) {
|
||||
self.tag(at_expr_node_tup) {||
|
||||
self.exprs(exprs);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_bind(f, args) {
|
||||
self.tag(at_expr_node_bind) {||
|
||||
self.expr(f);
|
||||
self.vec(at_expr_node_bind_args, args) {|opt_e|
|
||||
self.opt(opt_e) {|e| self.expr(e)};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_binary(binop, l, r) {
|
||||
self.tag(at_expr_node_binary) {||
|
||||
self.uint(binop as uint);
|
||||
self.expr(l);
|
||||
self.expr(r);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_unary(unop, l, r) {
|
||||
self.tag(at_expr_node_unary) {||
|
||||
self.uint(unop as uint);
|
||||
self.expr(l);
|
||||
self.expr(r);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_lit(lit) {
|
||||
self.tag(at_expr_node_lit) {|| self.lit(lit) }
|
||||
}
|
||||
|
||||
ast::expr_cast(expr, ty) {
|
||||
self.tag(at_expr_node_cast) {||
|
||||
self.expr(expr);
|
||||
self.ty(ty);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_if(cond, blk_then, o_blk_else) {
|
||||
self.tag(at_expr_node_if) {||
|
||||
self.expr(cond);
|
||||
self.blk(blk_then);
|
||||
self.opt(o_blk_else) {|b| self.blk(b)};
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_while(cond, blk) {
|
||||
self.tag(at_expr_node_while) {||
|
||||
self.expr(cond);
|
||||
self.blk(blk);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_for(lcl, expr, blk) {
|
||||
self.tag(at_expr_node_for) {||
|
||||
self.local(lcl);
|
||||
self.expr(expr);
|
||||
self.blk(blk);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_do_while(blk, cond) {
|
||||
self.tag(at_expr_node_do_while) {||
|
||||
self.blk(blk);
|
||||
self.expr(cond);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_alt(cond, arms) {
|
||||
self.tag(at_expr_node_alt) {||
|
||||
self.blk(blk);
|
||||
self.expr(cond);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_block(blk) {
|
||||
self.tag(at_expr_node_blk) {||
|
||||
self.blk(blk);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_copy(expr) {
|
||||
self.tag(at_expr_node_copy) {||
|
||||
self.expr(expr);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_move(l, r) {
|
||||
self.tag(at_expr_node_move) {||
|
||||
self.expr(l);
|
||||
self.expr(r);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_assign(l, r) {
|
||||
self.tag(at_expr_node_assign) {||
|
||||
self.expr(l);
|
||||
self.expr(r);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_swap(l, r) {
|
||||
self.tag(at_expr_node_swap) {||
|
||||
self.expr(l);
|
||||
self.expr(r);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_assign_of(binop, l, r) {
|
||||
self.tag(at_expr_node_assign_op) {||
|
||||
self.uint(binop as uint);
|
||||
self.expr(l);
|
||||
self.expr(r);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_field(base, f, tys) {
|
||||
self.tag(at_expr_node_field) {||
|
||||
self.expr(base);
|
||||
self.str(at_ident, f);
|
||||
self.vec(at_tys) {|v| self.ty(v) }
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_index(l, r) {
|
||||
self.tag(at_expr_node_index) {||
|
||||
self.expr(l);
|
||||
self.expr(r);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_path(pth) {
|
||||
self.tag(at_expr_node_path) {||
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_fail(o_expr) {
|
||||
self.tag(at_expr_node_fail) {||
|
||||
self.opt(o_expr) {|e| self.expr(e) }
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_break {
|
||||
self.tag(at_expr_node_break) {||}
|
||||
}
|
||||
|
||||
ast::expr_cont {
|
||||
self.tag(at_expr_node_cont) {||}
|
||||
}
|
||||
|
||||
ast::expr_ret(o_expr) {
|
||||
self.tag(at_expr_node_ret) {||
|
||||
self.opt(o_expr) {|e| self.expr(e) }
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_be(expr) {
|
||||
self.tag(at_expr_node_be) {||
|
||||
self.expr(expr)
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_log(i, e1, e2) {
|
||||
self.tag(at_expr_node_log) {||
|
||||
self.uint(i);
|
||||
self.expr(e1);
|
||||
self.expr(e2);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_assert(e) {
|
||||
self.tag(at_expr_node_assert) {||
|
||||
self.expr(e);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_check(mode, e) {
|
||||
self.tag(at_expr_node_check) {||
|
||||
self.uint(mode as uint);
|
||||
self.expr(e);
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_if_check(cond, b, e) {
|
||||
self.tag(at_expr_node_if_check) {||
|
||||
self.expr(cond);
|
||||
self.blk(b);
|
||||
self.opt(e) {|e| self.blk(e)};
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_mac(m) {
|
||||
self.tag(at_expr_node_mac) {||
|
||||
/* todo */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lit(l: ast::lit) {
|
||||
alt l {
|
||||
lit_str(s) {
|
||||
self.str(at_lit_str, s);
|
||||
}
|
||||
lit_int(i, t) {
|
||||
self.tag(at_lit_int) {||
|
||||
self.i64(i);
|
||||
self.int_ty(t);
|
||||
}
|
||||
}
|
||||
lit_uint(i, t) {
|
||||
self.tag(at_lit_uint) {||
|
||||
self.u64(i);
|
||||
self.uint_ty(t);
|
||||
}
|
||||
}
|
||||
lit_float(s, f) {
|
||||
self.tag(at_lit_float) {||
|
||||
self.str(at_value, s);
|
||||
self.float_ty(f);
|
||||
}
|
||||
}
|
||||
lit_nil {
|
||||
self.tag(at_lit_nil) {||}
|
||||
}
|
||||
lit_bool(true) {
|
||||
self.tag(at_lit_true) {||}
|
||||
}
|
||||
lit_bool(false) {
|
||||
self.tag(at_lit_false) {||}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn int_ty(t: ast::int_ty) {
|
||||
self.uint(t as uint);
|
||||
}
|
||||
|
||||
fn uint_ty(t: ast::uint_ty) {
|
||||
self.uint(t as uint);
|
||||
}
|
||||
|
||||
fn float_ty(t: ast::float_ty) {
|
||||
self.uint(t as uint);
|
||||
}
|
||||
|
||||
fn ty(ty: ast::ty) {
|
||||
self.tag(at_ty) {||
|
||||
self.span(ty.span);
|
||||
alt ty.node {
|
||||
ty_nil {
|
||||
self.tag(at_ty_nil) {||}
|
||||
}
|
||||
|
||||
ty_bot {
|
||||
self.tag(at_ty_bot) {||}
|
||||
}
|
||||
|
||||
ty_box({ty: ty, mut: m}) {
|
||||
self.tag(at_ty_box) {||
|
||||
self.ty(ty);
|
||||
self.mutbl(m);
|
||||
}
|
||||
}
|
||||
|
||||
ty_uniq({ty: ty, mut: m}) {
|
||||
self.tag(at_ty_uniq) {||
|
||||
self.ty(ty);
|
||||
self.mutbl(m);
|
||||
}
|
||||
}
|
||||
|
||||
ty_vec({ty: ty, mut: m}) {
|
||||
self.tag(at_ty_vec) {||
|
||||
self.ty(ty);
|
||||
self.mutbl(m);
|
||||
}
|
||||
}
|
||||
|
||||
ty_ptr({ty: ty, mut: m}) {
|
||||
self.tag(at_ty_ptr) {||
|
||||
self.ty(ty);
|
||||
self.mutbl(m);
|
||||
}
|
||||
}
|
||||
|
||||
ty_rec(fields) {
|
||||
self.vec(at_ty_rec) {|f|
|
||||
self.field(f)
|
||||
}
|
||||
}
|
||||
|
||||
ty_fn(proto, fd) {
|
||||
self.tag(at_ty_fn) {||
|
||||
self.uint(proto as uint);
|
||||
self.fn_decl(fd)
|
||||
}
|
||||
}
|
||||
|
||||
ty_tup(tys) {
|
||||
self.vec(at_ty_tups) {|ty| self.ty(ty)}
|
||||
}
|
||||
|
||||
ty_path(p, id) {
|
||||
self.tag(at_ty_path) {||
|
||||
self.path(p);
|
||||
self.uint(id);
|
||||
}
|
||||
}
|
||||
|
||||
ty_constr(t, tcs) {
|
||||
self.tag(at_ty_constr) {||
|
||||
self.ty(t);
|
||||
// ... constrs ... who cares ...
|
||||
}
|
||||
}
|
||||
|
||||
ty_mac(m) {
|
||||
self.tag(at_ty_mac) {||
|
||||
self.mac(m);
|
||||
};
|
||||
}
|
||||
|
||||
ty_infer {
|
||||
self.tag(at_ty_infer) {||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn item(item: @ast::item) {
|
||||
self.tag(at_item) {||
|
||||
self.str(at_item_ident, item);
|
||||
self.vec(at_item_attrs, item.attrs) {|a| self.attr(a)}
|
||||
self.uint(item.id);
|
||||
self.span(item.span);
|
||||
|
||||
alt item.node {
|
||||
item_const(t, e) {
|
||||
self.tag(at_item_const) {||
|
||||
self.ty(t);
|
||||
self.expr(e);
|
||||
}
|
||||
}
|
||||
item_fn(d, tps, blk) {
|
||||
self.tag(at_item_fn) {||
|
||||
self.fn_decl(d);
|
||||
self.ty_params(tps);
|
||||
}
|
||||
}
|
||||
item_mod(m) {
|
||||
self.tag(at_item_mod) {||
|
||||
self.mod_(m)
|
||||
}
|
||||
}
|
||||
item_native_mod(nm) {
|
||||
self.tag(at_item_native_mod) {||
|
||||
self.mod_(nm)
|
||||
}
|
||||
}
|
||||
item_ty(ty, tps) {
|
||||
self.tag(at_item_ty) {||
|
||||
self.ty(ty);
|
||||
self.ty_params(tps);
|
||||
}
|
||||
}
|
||||
item_enum(variants, tps) {
|
||||
self.tag(at_item_enum) {||
|
||||
self.ty(ty);
|
||||
self.ty_params(tps);
|
||||
}
|
||||
}
|
||||
item_res(fd, tps, blk, node_id, node_id) {
|
||||
self.tag(at_item_res) {||
|
||||
self.fn_decl(fd);
|
||||
self.ty_params(tps);
|
||||
}
|
||||
}
|
||||
item_class(tps, citems, fn_decl, blk) {
|
||||
self.tag(at_item_class) {||
|
||||
self.ty_params(tps);
|
||||
self.class_items(citems);
|
||||
self.fn_decl(fn_decl);
|
||||
self.blk(blk);
|
||||
}
|
||||
}
|
||||
item_iface(tps, tms) {
|
||||
self.tag(at_item_iface) {||
|
||||
self.ty_params(tps);
|
||||
self.ty_methods(tms);
|
||||
}
|
||||
}
|
||||
item_impl(tps, iface_ty, self_ty, mthds) {
|
||||
self.tag(at_item_impl) {||
|
||||
self.ty_params(tps);
|
||||
self.opt(iface_ty) {|t| self.ty(t) };
|
||||
self.ty(self_ty);
|
||||
self.methods(mthds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_params(tps: [ast::ty_param]) {
|
||||
self.vec(at_item_tps, tps) {|t| self.ty_param(t) }
|
||||
}
|
||||
|
||||
fn ty_param(tp: ast::ty_param) {
|
||||
self.str(at_ty_param_ident, tp.ident);
|
||||
self.uint(at_ty_param_id, tp.id);
|
||||
self.vec(at_param_bounds, *tp.bounds) {|b| self.ty_param_bound(b) };
|
||||
}
|
||||
|
||||
fn ty_param_bound(b: ast::ty_param_bound) {
|
||||
alt b {
|
||||
bound_copy { self.tag(at_ty_param_bound_copy) {||} }
|
||||
bound_send { self.tag(at_ty_param_bound_send) {||} }
|
||||
bound_iface(t) {
|
||||
self.tag(at_ty_param_bound_iface) {|| self.ty(t) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ export sty;
|
||||
export substitute_type_params;
|
||||
export t;
|
||||
export new_ty_hash;
|
||||
export enum_variants;
|
||||
export enum_variants, substd_enum_variants;
|
||||
export iface_methods, store_iface_methods, impl_iface;
|
||||
export enum_variant_with_id;
|
||||
export ty_param_bounds_and_ty;
|
||||
@ -2357,6 +2357,20 @@ fn impl_iface(cx: ctxt, id: ast::def_id) -> option<t> {
|
||||
type variant_info = @{args: [t], ctor_ty: t, name: str,
|
||||
id: ast::def_id, disr_val: int};
|
||||
|
||||
fn substd_enum_variants(cx: ctxt, id: ast::def_id, tps: [ty::t])
|
||||
-> [variant_info] {
|
||||
vec::map(*enum_variants(cx, id)) { |variant_info|
|
||||
let substd_args = vec::map(variant_info.args) {|aty|
|
||||
substitute_type_params(cx, tps, aty)
|
||||
};
|
||||
|
||||
let substd_ctor_ty =
|
||||
substitute_type_params(cx, tps, variant_info.ctor_ty);
|
||||
|
||||
@{args: substd_args, ctor_ty: substd_ctor_ty with *variant_info}
|
||||
}
|
||||
}
|
||||
|
||||
fn enum_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] {
|
||||
alt cx.enum_var_cache.find(id) {
|
||||
some(variants) { ret variants; }
|
||||
|
17
src/serializer/serializer.rc
Normal file
17
src/serializer/serializer.rc
Normal file
@ -0,0 +1,17 @@
|
||||
// -*- rust -*-
|
||||
|
||||
// serializer --- Rust metadata encoder/decoder generator.
|
||||
//
|
||||
// This tool is not intended to generate usable modules (just yet),
|
||||
// though perhaps it will be beefed up. But it can do a lot of the
|
||||
// grunt work for you.
|
||||
|
||||
#[link(name = "serializer",
|
||||
vers = "0.1",
|
||||
uuid = "9ff87a04-8fed-4295-9ff8-f99bb802650b",
|
||||
url = "http://rust-lang.org/doc/serializer")];
|
||||
|
||||
#[crate_type = "bin"];
|
||||
|
||||
use std;
|
||||
use rustc;
|
294
src/serializer/serializer.rs
Normal file
294
src/serializer/serializer.rs
Normal file
@ -0,0 +1,294 @@
|
||||
import rustc::driver::{driver,session};
|
||||
import rustc::syntax::{ast, codemap};
|
||||
import rustc::syntax::parse::parser;
|
||||
import rustc::driver::diagnostic;
|
||||
import rustc::syntax::print::pprust;
|
||||
import rustc::syntax::codemap::span;
|
||||
import rustc::middle::ty;
|
||||
import rustc::middle::ast_map;
|
||||
import rustc::util::ppaux;
|
||||
import std::map::{hashmap, map, new_int_hash};
|
||||
import std::getopts;
|
||||
import std::io;
|
||||
import std::io::writer_util;
|
||||
import driver::build_session_options;
|
||||
import driver::build_session;
|
||||
import driver::build_configuration;
|
||||
|
||||
type parse_result = {
|
||||
crate: @ast::crate,
|
||||
tcx: ty::ctxt,
|
||||
roots: [str]
|
||||
};
|
||||
|
||||
fn parse(argv: [str]) -> parse_result {
|
||||
let argv = argv;
|
||||
let argv0 = vec::shift(argv);
|
||||
let match = result::get(getopts::getopts(argv, driver::opts()));
|
||||
let sessopts = build_session_options(match, diagnostic::emit);
|
||||
let sess = build_session(sessopts, "", diagnostic::emit);
|
||||
let (ifile, roots) = {
|
||||
let free = match.free;
|
||||
if check vec::is_not_empty(free) {
|
||||
let t = vec::tail(free);
|
||||
(free[0], t)
|
||||
} else {
|
||||
fail "No input filename given.";
|
||||
}
|
||||
};
|
||||
let cfg = build_configuration(sess, argv0, ifile);
|
||||
alt driver::compile_upto(sess, cfg, ifile, driver::cu_typeck, none) {
|
||||
{crate, tcx: some(tcx)} { {crate:crate, tcx:tcx, roots:roots} }
|
||||
_ { fail "no type context"; }
|
||||
}
|
||||
}
|
||||
|
||||
type ast_expr = str;
|
||||
type ast_stmt = str;
|
||||
type ast_blk = str;
|
||||
type ast_pat = str;
|
||||
type ast_ty = str;
|
||||
type ast_item = str;
|
||||
|
||||
type tp_map = map<ast::node_id, ty::t>;
|
||||
|
||||
type serialize_ctx = {
|
||||
crate: @ast::crate,
|
||||
tcx: ty::ctxt,
|
||||
|
||||
tyfns: hashmap<ty::t, str>,
|
||||
mutable item_fns: [ast_item],
|
||||
mutable constants: [str]
|
||||
|
||||
// needed for #ast:
|
||||
// opts: @{cfg: ast::crate_cfg},
|
||||
// psess: parser::parse_sess
|
||||
};
|
||||
|
||||
fn item_has_name(&&item: @ast::item, &&name: str) -> bool {
|
||||
item.ident == name
|
||||
}
|
||||
|
||||
fn lookup(_mod: ast::_mod, idx: uint, names: [str]) -> @ast::item {
|
||||
let name = names[idx];
|
||||
alt vec::find(_mod.items, bind item_has_name(_, name)) {
|
||||
none { fail #fmt["cannot resolve name %s at index %u", name, idx]; }
|
||||
some(item) if idx == vec::len(names) - 1u { item }
|
||||
some(item) {
|
||||
alt item.node {
|
||||
ast::item_mod(_m) { lookup(_m, idx + 1u, names) }
|
||||
_ { fail #fmt["name %s at index %u not a module", name, idx]; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl serialize_ctx for serialize_ctx {
|
||||
// fn session() -> parser::parse_sess { self.psess }
|
||||
|
||||
fn add_item(item: ast_item) {
|
||||
self.item_fns += [item];
|
||||
}
|
||||
|
||||
fn mk_serialize_named_item_fn(name: str) -> str {
|
||||
let names = str::split_str(name, "::");
|
||||
let item = lookup(self.crate.node.module, 0u, names);
|
||||
let def_id = {crate: ast::local_crate, node: item.id};
|
||||
self.mk_serialize_item_fn(def_id, [])
|
||||
}
|
||||
|
||||
fn tp_map(ty_params: [ast::ty_param], tps: [ty::t]) -> tp_map {
|
||||
assert vec::len(tps) == vec::len(ty_params);
|
||||
let tps_map = new_int_hash();
|
||||
vec::iter2(ty_params, tps) {|tp_def,tp_val|
|
||||
tps_map.insert(tp_def.id, tp_val);
|
||||
}
|
||||
ret tps_map;
|
||||
}
|
||||
|
||||
fn path(mod_: [str], id: str) -> str {
|
||||
str::connect(mod_ + [id], "::")
|
||||
}
|
||||
|
||||
fn ident(mod_: [str], id: str) -> str {
|
||||
str::connect(mod_ + [id], "_")
|
||||
}
|
||||
|
||||
fn instantiate(id: ast::def_id, args: [ty::t]) -> ty::t {
|
||||
let {bounds, ty} = ty::lookup_item_type(self.tcx, id);
|
||||
|
||||
// typeck should guarantee this
|
||||
assert vec::len(*bounds) == vec::len(args);
|
||||
|
||||
ret if vec::len(args) == 0u {
|
||||
ty
|
||||
} else {
|
||||
ty::substitute_type_params(self.tcx, args, ty)
|
||||
};
|
||||
}
|
||||
|
||||
fn mk_serialize_item_fn(id: ast::def_id,
|
||||
tps: [ty::t]) -> str {
|
||||
let item_ty = self.instantiate(id, tps);
|
||||
self.mk_serialize_ty_fn(item_ty)
|
||||
}
|
||||
|
||||
fn blk(stmts: [ast_stmt]) -> ast_blk {
|
||||
"{" + str::connect(stmts, ";") + "}"
|
||||
}
|
||||
|
||||
fn blk_expr(stmts: [ast_stmt]) -> ast_expr {
|
||||
self.blk(stmts)
|
||||
}
|
||||
|
||||
// Generates a function to serialize the given type.
|
||||
// Returns an AST fragment that names this function.
|
||||
fn serialize_ty(ty0: ty::t, v: ast_expr) -> ast_expr {
|
||||
let fname = self.mk_serialize_ty_fn(ty0);
|
||||
#fmt["%s(cx, %s)", fname, v]
|
||||
}
|
||||
|
||||
fn mk_serialize_ty_fn(ty0: ty::t) -> str {
|
||||
// check for existing function
|
||||
alt self.tyfns.find(ty0) {
|
||||
some(name) { ret name; }
|
||||
none { /* fallthrough */ }
|
||||
}
|
||||
|
||||
// define the name and insert into the hashtable
|
||||
// in case of recursive calls:
|
||||
let id = self.tyfns.size();
|
||||
let ty0_str = ppaux::ty_to_str(self.tcx, ty0);
|
||||
let name = #fmt["serialize_%u /*%s*/", id, ty0_str];
|
||||
self.tyfns.insert(ty0, name);
|
||||
let v = "v";
|
||||
|
||||
let body_node = alt ty::get(ty0).struct {
|
||||
ty::ty_nil | ty::ty_bot { "()" }
|
||||
ty::ty_int(_) { #fmt["serialize_i64(cx, %s as i64)", v] }
|
||||
ty::ty_uint(_) { #fmt["serialize_u64(cx, %s as u64)", v] }
|
||||
ty::ty_float(_) { #fmt["serialize_float(cx, %s as float)", v] }
|
||||
ty::ty_bool { #fmt["serialize_bool(cx, %s)", v] }
|
||||
ty::ty_str { #fmt["serialize_str(cx, %s)", v] }
|
||||
ty::ty_enum(def_id, tps) { self.serialize_enum(v, def_id, tps) }
|
||||
ty::ty_box(mt) | ty::ty_uniq(mt) | ty::ty_ptr(mt) {
|
||||
self.serialize_ty(mt.ty, #fmt["*%s", v])
|
||||
}
|
||||
ty::ty_vec(mt) {
|
||||
let selem = self.serialize_ty(mt.ty, "i");
|
||||
#fmt["start_vec(cx); \
|
||||
vec::iter(v) {|i| \
|
||||
start_vec_item(cx); \
|
||||
%s; \
|
||||
end_vec_item(cx); \
|
||||
} \
|
||||
end_vec(cx);", selem]
|
||||
}
|
||||
ty::ty_rec(fields) {
|
||||
let stmts = vec::map(fields) {|field|
|
||||
let f_name = field.ident;
|
||||
let f_ty = field.mt.ty;
|
||||
self.serialize_ty(f_ty, #fmt["%s.%s", v, f_name])
|
||||
};
|
||||
self.blk_expr(stmts)
|
||||
}
|
||||
ty::ty_tup(tys) {
|
||||
let (pat, stmts) = self.serialize_arm("", tys);
|
||||
#fmt["alt %s { \
|
||||
%s %s \
|
||||
}", v, pat, self.blk_expr(stmts)]
|
||||
}
|
||||
ty::ty_constr(t, _) {
|
||||
self.serialize_ty(t, v)
|
||||
}
|
||||
ty::ty_fn(_) |
|
||||
ty::ty_iface(_, _) |
|
||||
ty::ty_res(_, _, _) |
|
||||
ty::ty_var(_) | ty::ty_param(_, _) |
|
||||
ty::ty_self(_) | ty::ty_type | ty::ty_send_type |
|
||||
ty::ty_opaque_closure_ptr(_) | ty::ty_opaque_box {
|
||||
fail #fmt["Unhandled type %s", ty0_str]
|
||||
}
|
||||
};
|
||||
|
||||
let item = #fmt["fn %s(cx: ctxt, v: %s) {\
|
||||
%s;\
|
||||
}", name, ty0_str, body_node];
|
||||
self.add_item(item);
|
||||
ret name;
|
||||
}
|
||||
|
||||
fn serialize_enum(v: ast_expr,
|
||||
id: ast::def_id,
|
||||
tps: [ty::t]) -> ast_expr {
|
||||
let path = [];
|
||||
let variants = ty::substd_enum_variants(self.tcx, id, tps);
|
||||
|
||||
let arms = vec::map(variants) {|variant|
|
||||
let v_path = self.path(path, variant.name);
|
||||
let n_args = vec::len(variant.args);
|
||||
let (v_pat, stmts) = {
|
||||
if n_args == 0u {
|
||||
(v_path, [])
|
||||
} else {
|
||||
self.serialize_arm(v_path, variant.args)
|
||||
}
|
||||
};
|
||||
|
||||
let v_const = #fmt["at_%s", self.ident(path, variant.name)];
|
||||
|
||||
#fmt["%s { \
|
||||
start_variant(cx, %s); \
|
||||
%s \
|
||||
end_variant(cx, %s); \
|
||||
}", v_pat, v_const, self.blk(stmts), v_const]
|
||||
};
|
||||
|
||||
#fmt["alt %s { \
|
||||
%s \
|
||||
}", v, str::connect(arms, "\n")]
|
||||
}
|
||||
|
||||
fn serialize_arm(v_path: str, args: [ty::t]) -> (ast_pat, [ast_stmt]) {
|
||||
let n_args = vec::len(args);
|
||||
let arg_nms = vec::init_fn(n_args) {|i| #fmt["v%u", i] };
|
||||
let v_pat =
|
||||
#fmt["%s(%s)", v_path, str::connect(arg_nms, ", ")];
|
||||
let stmts = vec::init_fn(n_args) {|i|
|
||||
let arg_ty = args[i];
|
||||
let serialize_expr =
|
||||
self.serialize_ty(arg_ty, arg_nms[i]);
|
||||
#fmt["%s;", serialize_expr]
|
||||
};
|
||||
(v_pat, stmts)
|
||||
}
|
||||
}
|
||||
|
||||
fn main(argv: [str]) {
|
||||
let {crate, tcx, roots} = parse(argv);
|
||||
let sctx: serialize_ctx = {
|
||||
// let cm = codemap::new_codemap();
|
||||
// let handler = diagnostic::mk_handler(option::none);
|
||||
// let psess: parser::parse_sess = @{
|
||||
// cm: cm,
|
||||
// mutable next_id: 1,
|
||||
// span_diagnostic: diagnostic::mk_span_handler(handler, cm),
|
||||
// mutable chpos: 0u,
|
||||
// mutable byte_pos: 0u
|
||||
// };
|
||||
{crate: crate,
|
||||
tcx: tcx,
|
||||
tyfns: ty::new_ty_hash::<str>(),
|
||||
mutable item_fns: [],
|
||||
mutable constants: []}
|
||||
};
|
||||
|
||||
vec::iter(roots) {|root|
|
||||
sctx.mk_serialize_named_item_fn(root);
|
||||
}
|
||||
|
||||
let stdout = io::stdout();
|
||||
vec::iter(copy sctx.item_fns) {|item|
|
||||
stdout.write_str(#fmt["%s\n", item])
|
||||
}
|
||||
}
|
31
src/serializer/stest.rs
Normal file
31
src/serializer/stest.rs
Normal file
@ -0,0 +1,31 @@
|
||||
// Testing types for the serializer. This should be made more formal.
|
||||
|
||||
enum test1 {
|
||||
t1_a(int), t1_b(str)
|
||||
}
|
||||
|
||||
type test2 = {
|
||||
f: int, g: str
|
||||
};
|
||||
|
||||
enum test3 {
|
||||
t3_a, t3_b
|
||||
}
|
||||
|
||||
enum test4 {
|
||||
t4_a(test1), t4_b(test2), t4_c(@test2), t4_d(@test4)
|
||||
}
|
||||
|
||||
type spanned<A> = {
|
||||
node: A,
|
||||
span: { lo: uint, hi: uint }
|
||||
};
|
||||
|
||||
type test5 = {
|
||||
s1: spanned<test4>,
|
||||
s2: spanned<uint>
|
||||
};
|
||||
|
||||
type test6 = option<int>;
|
||||
|
||||
fn main() {}
|
Loading…
x
Reference in New Issue
Block a user