diff --git a/src/comp/metadata/astencode.rs b/src/comp/metadata/astencode.rs new file mode 100644 index 0000000000000..002296a656dfe --- /dev/null +++ b/src/comp/metadata/astencode.rs @@ -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(x: option, 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(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) } + } + } + } +} + diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 826ed0ea4bd8b..5c6e956508fc6 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -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 { 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; } diff --git a/src/serializer/serializer.rc b/src/serializer/serializer.rc new file mode 100644 index 0000000000000..ba3a8467b9da0 --- /dev/null +++ b/src/serializer/serializer.rc @@ -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; diff --git a/src/serializer/serializer.rs b/src/serializer/serializer.rs new file mode 100644 index 0000000000000..f8c4349a7ce65 --- /dev/null +++ b/src/serializer/serializer.rs @@ -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; + +type serialize_ctx = { + crate: @ast::crate, + tcx: ty::ctxt, + + tyfns: hashmap, + 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::(), + 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]) + } +} \ No newline at end of file diff --git a/src/serializer/stest.rs b/src/serializer/stest.rs new file mode 100644 index 0000000000000..c7161e07a2756 --- /dev/null +++ b/src/serializer/stest.rs @@ -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 = { + node: A, + span: { lo: uint, hi: uint } +}; + +type test5 = { + s1: spanned, + s2: spanned +}; + +type test6 = option; + +fn main() {} \ No newline at end of file