Brian Anderson | 45efb1f | 2011-06-27 23:03:01 | [diff] [blame] | 1 | // Metadata encoding |
| 2 | |
Patrick Walton | 0e2fff5 | 2011-07-07 02:00:00 | [diff] [blame] | 3 | import std::ivec; |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 4 | import std::str; |
| 5 | import std::vec; |
| 6 | import std::uint; |
| 7 | import std::io; |
| 8 | import std::option; |
| 9 | import std::option::some; |
| 10 | import std::option::none; |
| 11 | import std::ebml; |
Marijn Haverbeke | 6fd6fde | 2011-07-05 09:48:19 | [diff] [blame] | 12 | import syntax::ast::*; |
Brian Anderson | e29ef1b | 2011-07-07 19:22:39 | [diff] [blame] | 13 | import common::*; |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 14 | import middle::trans::crate_ctxt; |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 15 | import middle::ty; |
Brian Anderson | d236259 | 2011-07-07 17:10:10 | [diff] [blame] | 16 | import middle::ty::node_id_to_monotype; |
Brian Anderson | 5de916d | 2011-06-30 06:42:35 | [diff] [blame] | 17 | import front::attr; |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 18 | |
| 19 | export def_to_str; |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 20 | export encode_metadata; |
Brian Anderson | 7d26d1d | 2011-07-07 19:47:39 | [diff] [blame^] | 21 | export ty_str; |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 22 | |
| 23 | // Path table encoding |
| 24 | fn encode_name(&ebml::writer ebml_w, &str name) { |
| 25 | ebml::start_tag(ebml_w, tag_paths_data_name); |
| 26 | ebml_w.writer.write(str::bytes(name)); |
| 27 | ebml::end_tag(ebml_w); |
| 28 | } |
| 29 | |
| 30 | fn encode_def_id(&ebml::writer ebml_w, &def_id id) { |
| 31 | ebml::start_tag(ebml_w, tag_def_id); |
| 32 | ebml_w.writer.write(str::bytes(def_to_str(id))); |
| 33 | ebml::end_tag(ebml_w); |
| 34 | } |
| 35 | |
Patrick Walton | 0e2fff5 | 2011-07-07 02:00:00 | [diff] [blame] | 36 | fn encode_tag_variant_paths(&ebml::writer ebml_w, &variant[] variants, |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 37 | &vec[str] path, |
| 38 | &mutable vec[tup(str, uint)] index) { |
| 39 | for (variant variant in variants) { |
| 40 | add_to_index(ebml_w, path, index, variant.node.name); |
| 41 | ebml::start_tag(ebml_w, tag_paths_data_item); |
| 42 | encode_name(ebml_w, variant.node.name); |
| 43 | encode_def_id(ebml_w, local_def(variant.node.id)); |
| 44 | ebml::end_tag(ebml_w); |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | fn add_to_index(&ebml::writer ebml_w, &vec[str] path, |
| 49 | &mutable vec[tup(str, uint)] index, &str name) { |
| 50 | auto full_path = path + [name]; |
| 51 | index += [tup(str::connect(full_path, "::"), ebml_w.writer.tell())]; |
| 52 | } |
| 53 | |
| 54 | fn encode_native_module_item_paths(&ebml::writer ebml_w, |
| 55 | &native_mod nmod, &vec[str] path, |
| 56 | &mutable vec[tup(str, uint)] index) { |
| 57 | for (@native_item nitem in nmod.items) { |
| 58 | add_to_index(ebml_w, path, index, nitem.ident); |
| 59 | ebml::start_tag(ebml_w, tag_paths_data_item); |
| 60 | encode_name(ebml_w, nitem.ident); |
| 61 | encode_def_id(ebml_w, local_def(nitem.id)); |
| 62 | ebml::end_tag(ebml_w); |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | fn encode_module_item_paths(&ebml::writer ebml_w, &_mod module, |
| 67 | &vec[str] path, |
| 68 | &mutable vec[tup(str, uint)] index) { |
| 69 | for (@item it in module.items) { |
| 70 | if (!is_exported(it.ident, module)) { cont; } |
| 71 | alt (it.node) { |
| 72 | case (item_const(_, _)) { |
| 73 | add_to_index(ebml_w, path, index, it.ident); |
| 74 | ebml::start_tag(ebml_w, tag_paths_data_item); |
| 75 | encode_name(ebml_w, it.ident); |
| 76 | encode_def_id(ebml_w, local_def(it.id)); |
| 77 | ebml::end_tag(ebml_w); |
| 78 | } |
| 79 | case (item_fn(_, ?tps)) { |
| 80 | add_to_index(ebml_w, path, index, it.ident); |
| 81 | ebml::start_tag(ebml_w, tag_paths_data_item); |
| 82 | encode_name(ebml_w, it.ident); |
| 83 | encode_def_id(ebml_w, local_def(it.id)); |
| 84 | ebml::end_tag(ebml_w); |
| 85 | } |
| 86 | case (item_mod(?_mod)) { |
| 87 | add_to_index(ebml_w, path, index, it.ident); |
| 88 | ebml::start_tag(ebml_w, tag_paths_data_mod); |
| 89 | encode_name(ebml_w, it.ident); |
| 90 | encode_def_id(ebml_w, local_def(it.id)); |
| 91 | encode_module_item_paths(ebml_w, _mod, path + [it.ident], |
| 92 | index); |
| 93 | ebml::end_tag(ebml_w); |
| 94 | } |
| 95 | case (item_native_mod(?nmod)) { |
| 96 | add_to_index(ebml_w, path, index, it.ident); |
| 97 | ebml::start_tag(ebml_w, tag_paths_data_mod); |
| 98 | encode_name(ebml_w, it.ident); |
| 99 | encode_def_id(ebml_w, local_def(it.id)); |
| 100 | encode_native_module_item_paths(ebml_w, nmod, |
| 101 | path + [it.ident], index); |
| 102 | ebml::end_tag(ebml_w); |
| 103 | } |
| 104 | case (item_ty(_, ?tps)) { |
| 105 | add_to_index(ebml_w, path, index, it.ident); |
| 106 | ebml::start_tag(ebml_w, tag_paths_data_item); |
| 107 | encode_name(ebml_w, it.ident); |
| 108 | encode_def_id(ebml_w, local_def(it.id)); |
| 109 | ebml::end_tag(ebml_w); |
| 110 | } |
| 111 | case (item_res(_, _, ?tps, ?ctor_id)) { |
| 112 | add_to_index(ebml_w, path, index, it.ident); |
| 113 | ebml::start_tag(ebml_w, tag_paths_data_item); |
| 114 | encode_name(ebml_w, it.ident); |
| 115 | encode_def_id(ebml_w, local_def(ctor_id)); |
| 116 | ebml::end_tag(ebml_w); |
| 117 | add_to_index(ebml_w, path, index, it.ident); |
| 118 | ebml::start_tag(ebml_w, tag_paths_data_item); |
| 119 | encode_name(ebml_w, it.ident); |
| 120 | encode_def_id(ebml_w, local_def(it.id)); |
| 121 | ebml::end_tag(ebml_w); |
| 122 | } |
| 123 | case (item_tag(?variants, ?tps)) { |
| 124 | add_to_index(ebml_w, path, index, it.ident); |
| 125 | ebml::start_tag(ebml_w, tag_paths_data_item); |
| 126 | encode_name(ebml_w, it.ident); |
| 127 | encode_def_id(ebml_w, local_def(it.id)); |
| 128 | ebml::end_tag(ebml_w); |
| 129 | encode_tag_variant_paths(ebml_w, variants, path, index); |
| 130 | } |
| 131 | case (item_obj(_, ?tps, ?ctor_id)) { |
| 132 | add_to_index(ebml_w, path, index, it.ident); |
| 133 | ebml::start_tag(ebml_w, tag_paths_data_item); |
| 134 | encode_name(ebml_w, it.ident); |
| 135 | encode_def_id(ebml_w, local_def(ctor_id)); |
| 136 | ebml::end_tag(ebml_w); |
| 137 | add_to_index(ebml_w, path, index, it.ident); |
| 138 | ebml::start_tag(ebml_w, tag_paths_data_item); |
| 139 | encode_name(ebml_w, it.ident); |
| 140 | encode_def_id(ebml_w, local_def(it.id)); |
| 141 | ebml::end_tag(ebml_w); |
| 142 | } |
| 143 | } |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | fn encode_item_paths(&ebml::writer ebml_w, &@crate crate) -> |
| 148 | vec[tup(str, uint)] { |
| 149 | let vec[tup(str, uint)] index = []; |
| 150 | let vec[str] path = []; |
| 151 | ebml::start_tag(ebml_w, tag_paths); |
| 152 | encode_module_item_paths(ebml_w, crate.node.module, path, index); |
| 153 | ebml::end_tag(ebml_w); |
| 154 | ret index; |
| 155 | } |
| 156 | |
| 157 | |
| 158 | // Item info table encoding |
| 159 | fn encode_kind(&ebml::writer ebml_w, u8 c) { |
| 160 | ebml::start_tag(ebml_w, tag_items_data_item_kind); |
| 161 | ebml_w.writer.write([c]); |
| 162 | ebml::end_tag(ebml_w); |
| 163 | } |
| 164 | |
| 165 | fn def_to_str(&def_id did) -> str { ret #fmt("%d:%d", did._0, did._1); } |
| 166 | |
Patrick Walton | 0e2fff5 | 2011-07-07 02:00:00 | [diff] [blame] | 167 | fn encode_type_param_count(&ebml::writer ebml_w, &ty_param[] tps) { |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 168 | ebml::start_tag(ebml_w, tag_items_data_item_ty_param_count); |
Patrick Walton | 0e2fff5 | 2011-07-07 02:00:00 | [diff] [blame] | 169 | ebml::write_vint(ebml_w.writer, ivec::len[ty_param](tps)); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 170 | ebml::end_tag(ebml_w); |
| 171 | } |
| 172 | |
| 173 | fn encode_variant_id(&ebml::writer ebml_w, &def_id vid) { |
| 174 | ebml::start_tag(ebml_w, tag_items_data_item_variant); |
| 175 | ebml_w.writer.write(str::bytes(def_to_str(vid))); |
| 176 | ebml::end_tag(ebml_w); |
| 177 | } |
| 178 | |
| 179 | fn encode_type(&@crate_ctxt cx, &ebml::writer ebml_w, &ty::t typ) { |
| 180 | ebml::start_tag(ebml_w, tag_items_data_item_type); |
| 181 | auto f = def_to_str; |
| 182 | auto ty_str_ctxt = |
Graydon Hoare | c796a8f | 2011-06-29 22:11:20 | [diff] [blame] | 183 | @rec(ds=f, tcx=cx.tcx, |
| 184 | abbrevs=tyencode::ac_use_abbrevs(cx.type_abbrevs)); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 185 | tyencode::enc_ty(io::new_writer_(ebml_w.writer), ty_str_ctxt, typ); |
| 186 | ebml::end_tag(ebml_w); |
| 187 | } |
| 188 | |
| 189 | fn encode_symbol(&@crate_ctxt cx, &ebml::writer ebml_w, |
| 190 | node_id id) { |
| 191 | ebml::start_tag(ebml_w, tag_items_data_item_symbol); |
| 192 | ebml_w.writer.write(str::bytes(cx.item_symbols.get(id))); |
| 193 | ebml::end_tag(ebml_w); |
| 194 | } |
| 195 | |
| 196 | fn encode_discriminant(&@crate_ctxt cx, &ebml::writer ebml_w, |
| 197 | node_id id) { |
| 198 | ebml::start_tag(ebml_w, tag_items_data_item_symbol); |
| 199 | ebml_w.writer.write(str::bytes(cx.discrim_symbols.get(id))); |
| 200 | ebml::end_tag(ebml_w); |
| 201 | } |
| 202 | |
| 203 | fn encode_tag_id(&ebml::writer ebml_w, &def_id id) { |
| 204 | ebml::start_tag(ebml_w, tag_items_data_item_tag_id); |
| 205 | ebml_w.writer.write(str::bytes(def_to_str(id))); |
| 206 | ebml::end_tag(ebml_w); |
| 207 | } |
| 208 | |
| 209 | fn encode_tag_variant_info(&@crate_ctxt cx, &ebml::writer ebml_w, |
Patrick Walton | 0e2fff5 | 2011-07-07 02:00:00 | [diff] [blame] | 210 | node_id id, &variant[] variants, |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 211 | &mutable vec[tup(int, uint)] index, |
Patrick Walton | 0e2fff5 | 2011-07-07 02:00:00 | [diff] [blame] | 212 | &ty_param[] ty_params) { |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 213 | for (variant variant in variants) { |
| 214 | index += [tup(variant.node.id, ebml_w.writer.tell())]; |
| 215 | ebml::start_tag(ebml_w, tag_items_data_item); |
| 216 | encode_def_id(ebml_w, local_def(variant.node.id)); |
| 217 | encode_kind(ebml_w, 'v' as u8); |
| 218 | encode_tag_id(ebml_w, local_def(id)); |
Brian Anderson | d236259 | 2011-07-07 17:10:10 | [diff] [blame] | 219 | encode_type(cx, ebml_w, node_id_to_monotype(cx.tcx, variant.node.id)); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 220 | if (vec::len[variant_arg](variant.node.args) > 0u) { |
| 221 | encode_symbol(cx, ebml_w, variant.node.id); |
| 222 | } |
| 223 | encode_discriminant(cx, ebml_w, variant.node.id); |
| 224 | encode_type_param_count(ebml_w, ty_params); |
| 225 | ebml::end_tag(ebml_w); |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | fn encode_info_for_item(@crate_ctxt cx, &ebml::writer ebml_w, |
| 230 | @item item, &mutable vec[tup(int, uint)] index) { |
| 231 | alt (item.node) { |
| 232 | case (item_const(_, _)) { |
| 233 | ebml::start_tag(ebml_w, tag_items_data_item); |
| 234 | encode_def_id(ebml_w, local_def(item.id)); |
| 235 | encode_kind(ebml_w, 'c' as u8); |
Brian Anderson | d236259 | 2011-07-07 17:10:10 | [diff] [blame] | 236 | encode_type(cx, ebml_w, node_id_to_monotype(cx.tcx, item.id)); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 237 | encode_symbol(cx, ebml_w, item.id); |
| 238 | ebml::end_tag(ebml_w); |
| 239 | } |
| 240 | case (item_fn(?fd, ?tps)) { |
| 241 | ebml::start_tag(ebml_w, tag_items_data_item); |
| 242 | encode_def_id(ebml_w, local_def(item.id)); |
| 243 | encode_kind(ebml_w, alt (fd.decl.purity) { |
| 244 | case (pure_fn) { 'p' } |
| 245 | case (impure_fn) { 'f' } } as u8); |
| 246 | encode_type_param_count(ebml_w, tps); |
Brian Anderson | d236259 | 2011-07-07 17:10:10 | [diff] [blame] | 247 | encode_type(cx, ebml_w, node_id_to_monotype(cx.tcx, item.id)); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 248 | encode_symbol(cx, ebml_w, item.id); |
| 249 | ebml::end_tag(ebml_w); |
| 250 | } |
| 251 | case (item_mod(_)) { |
| 252 | ebml::start_tag(ebml_w, tag_items_data_item); |
| 253 | encode_def_id(ebml_w, local_def(item.id)); |
| 254 | encode_kind(ebml_w, 'm' as u8); |
| 255 | ebml::end_tag(ebml_w); |
| 256 | } |
| 257 | case (item_native_mod(_)) { |
| 258 | ebml::start_tag(ebml_w, tag_items_data_item); |
| 259 | encode_def_id(ebml_w, local_def(item.id)); |
| 260 | encode_kind(ebml_w, 'n' as u8); |
| 261 | ebml::end_tag(ebml_w); |
| 262 | } |
| 263 | case (item_ty(_, ?tps)) { |
| 264 | ebml::start_tag(ebml_w, tag_items_data_item); |
| 265 | encode_def_id(ebml_w, local_def(item.id)); |
| 266 | encode_kind(ebml_w, 'y' as u8); |
| 267 | encode_type_param_count(ebml_w, tps); |
Brian Anderson | d236259 | 2011-07-07 17:10:10 | [diff] [blame] | 268 | encode_type(cx, ebml_w, node_id_to_monotype(cx.tcx, item.id)); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 269 | ebml::end_tag(ebml_w); |
| 270 | } |
| 271 | case (item_tag(?variants, ?tps)) { |
| 272 | ebml::start_tag(ebml_w, tag_items_data_item); |
| 273 | encode_def_id(ebml_w, local_def(item.id)); |
| 274 | encode_kind(ebml_w, 't' as u8); |
| 275 | encode_type_param_count(ebml_w, tps); |
Brian Anderson | d236259 | 2011-07-07 17:10:10 | [diff] [blame] | 276 | encode_type(cx, ebml_w, node_id_to_monotype(cx.tcx, item.id)); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 277 | for (variant v in variants) { |
| 278 | encode_variant_id(ebml_w, local_def(v.node.id)); |
| 279 | } |
| 280 | ebml::end_tag(ebml_w); |
| 281 | encode_tag_variant_info(cx, ebml_w, item.id, variants, index, |
| 282 | tps); |
| 283 | } |
| 284 | case (item_res(_, _, ?tps, ?ctor_id)) { |
Brian Anderson | d236259 | 2011-07-07 17:10:10 | [diff] [blame] | 285 | auto fn_ty = node_id_to_monotype(cx.tcx, ctor_id); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 286 | |
| 287 | ebml::start_tag(ebml_w, tag_items_data_item); |
Graydon Hoare | 5b2c17f | 2011-06-29 19:08:35 | [diff] [blame] | 288 | encode_def_id(ebml_w, local_def(ctor_id)); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 289 | encode_kind(ebml_w, 'y' as u8); |
| 290 | encode_type_param_count(ebml_w, tps); |
| 291 | encode_type(cx, ebml_w, ty::ty_fn_ret(cx.tcx, fn_ty)); |
Marijn Haverbeke | 31ec26d | 2011-06-30 10:35:19 | [diff] [blame] | 292 | encode_symbol(cx, ebml_w, item.id); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 293 | ebml::end_tag(ebml_w); |
| 294 | |
| 295 | index += [tup(ctor_id, ebml_w.writer.tell())]; |
| 296 | ebml::start_tag(ebml_w, tag_items_data_item); |
| 297 | encode_def_id(ebml_w, local_def(ctor_id)); |
| 298 | encode_kind(ebml_w, 'f' as u8); |
| 299 | encode_type_param_count(ebml_w, tps); |
| 300 | encode_type(cx, ebml_w, fn_ty); |
| 301 | encode_symbol(cx, ebml_w, ctor_id); |
| 302 | ebml::end_tag(ebml_w); |
| 303 | } |
| 304 | case (item_obj(_, ?tps, ?ctor_id)) { |
Brian Anderson | d236259 | 2011-07-07 17:10:10 | [diff] [blame] | 305 | auto fn_ty = node_id_to_monotype(cx.tcx, ctor_id); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 306 | |
| 307 | ebml::start_tag(ebml_w, tag_items_data_item); |
| 308 | encode_def_id(ebml_w, local_def(item.id)); |
| 309 | encode_kind(ebml_w, 'y' as u8); |
| 310 | encode_type_param_count(ebml_w, tps); |
| 311 | encode_type(cx, ebml_w, ty::ty_fn_ret(cx.tcx, fn_ty)); |
| 312 | ebml::end_tag(ebml_w); |
| 313 | |
| 314 | index += [tup(ctor_id, ebml_w.writer.tell())]; |
| 315 | ebml::start_tag(ebml_w, tag_items_data_item); |
| 316 | encode_def_id(ebml_w, local_def(ctor_id)); |
| 317 | encode_kind(ebml_w, 'f' as u8); |
| 318 | encode_type_param_count(ebml_w, tps); |
| 319 | encode_type(cx, ebml_w, fn_ty); |
| 320 | encode_symbol(cx, ebml_w, ctor_id); |
| 321 | ebml::end_tag(ebml_w); |
| 322 | } |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | fn encode_info_for_native_item(&@crate_ctxt cx, &ebml::writer ebml_w, |
| 327 | &@native_item nitem) { |
| 328 | ebml::start_tag(ebml_w, tag_items_data_item); |
| 329 | alt (nitem.node) { |
| 330 | case (native_item_ty) { |
| 331 | encode_def_id(ebml_w, local_def(nitem.id)); |
| 332 | encode_kind(ebml_w, 'T' as u8); |
Marijn Haverbeke | 77f5d14 | 2011-07-01 16:39:24 | [diff] [blame] | 333 | encode_type(cx, ebml_w, |
| 334 | ty::mk_native(cx.tcx, local_def(nitem.id))); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 335 | } |
| 336 | case (native_item_fn(_, _, ?tps)) { |
| 337 | encode_def_id(ebml_w, local_def(nitem.id)); |
| 338 | encode_kind(ebml_w, 'F' as u8); |
| 339 | encode_type_param_count(ebml_w, tps); |
Brian Anderson | d236259 | 2011-07-07 17:10:10 | [diff] [blame] | 340 | encode_type(cx, ebml_w, node_id_to_monotype(cx.tcx, nitem.id)); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 341 | encode_symbol(cx, ebml_w, nitem.id); |
| 342 | } |
| 343 | } |
| 344 | ebml::end_tag(ebml_w); |
| 345 | } |
| 346 | |
| 347 | fn encode_info_for_items(&@crate_ctxt cx, &ebml::writer ebml_w) -> |
| 348 | vec[tup(int, uint)] { |
| 349 | let vec[tup(int, uint)] index = []; |
| 350 | ebml::start_tag(ebml_w, tag_items_data); |
Graydon Hoare | c796a8f | 2011-06-29 22:11:20 | [diff] [blame] | 351 | for each (@tup(node_id, middle::ast_map::ast_node) kvp in |
| 352 | cx.ast_map.items()) { |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 353 | alt (kvp._1) { |
| 354 | case (middle::ast_map::node_item(?i)) { |
| 355 | index += [tup(kvp._0, ebml_w.writer.tell())]; |
| 356 | encode_info_for_item(cx, ebml_w, i, index); |
| 357 | } |
| 358 | case (middle::ast_map::node_native_item(?i)) { |
| 359 | index += [tup(kvp._0, ebml_w.writer.tell())]; |
| 360 | encode_info_for_native_item(cx, ebml_w, i); |
| 361 | } |
| 362 | case (_) {} |
| 363 | } |
| 364 | } |
| 365 | ebml::end_tag(ebml_w); |
| 366 | ret index; |
| 367 | } |
| 368 | |
| 369 | |
| 370 | // Path and definition ID indexing |
| 371 | |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 372 | fn create_index[T](&vec[tup(T, uint)] index, fn(&T) -> uint hash_fn) -> |
| 373 | vec[vec[tup(T, uint)]] { |
| 374 | let vec[mutable vec[tup(T, uint)]] buckets = vec::empty_mut(); |
| 375 | for each (uint i in uint::range(0u, 256u)) { buckets += [mutable []]; } |
| 376 | for (tup(T, uint) elt in index) { |
| 377 | auto h = hash_fn(elt._0); |
| 378 | buckets.(h % 256u) += [elt]; |
| 379 | } |
| 380 | ret vec::freeze(buckets); |
| 381 | } |
| 382 | |
| 383 | fn encode_index[T](&ebml::writer ebml_w, &vec[vec[tup(T, uint)]] buckets, |
| 384 | fn(&io::writer, &T) write_fn) { |
| 385 | auto writer = io::new_writer_(ebml_w.writer); |
| 386 | ebml::start_tag(ebml_w, tag_index); |
| 387 | let vec[uint] bucket_locs = []; |
| 388 | ebml::start_tag(ebml_w, tag_index_buckets); |
| 389 | for (vec[tup(T, uint)] bucket in buckets) { |
| 390 | bucket_locs += [ebml_w.writer.tell()]; |
| 391 | ebml::start_tag(ebml_w, tag_index_buckets_bucket); |
| 392 | for (tup(T, uint) elt in bucket) { |
| 393 | ebml::start_tag(ebml_w, tag_index_buckets_bucket_elt); |
| 394 | writer.write_be_uint(elt._1, 4u); |
| 395 | write_fn(writer, elt._0); |
| 396 | ebml::end_tag(ebml_w); |
| 397 | } |
| 398 | ebml::end_tag(ebml_w); |
| 399 | } |
| 400 | ebml::end_tag(ebml_w); |
| 401 | ebml::start_tag(ebml_w, tag_index_table); |
| 402 | for (uint pos in bucket_locs) { writer.write_be_uint(pos, 4u); } |
| 403 | ebml::end_tag(ebml_w); |
| 404 | ebml::end_tag(ebml_w); |
| 405 | } |
| 406 | |
| 407 | fn write_str(&io::writer writer, &str s) { writer.write_str(s); } |
| 408 | |
| 409 | fn write_int(&io::writer writer, &int n) { |
| 410 | writer.write_be_uint(n as uint, 4u); |
| 411 | } |
| 412 | |
Brian Anderson | f53c4f7 | 2011-06-28 02:41:48 | [diff] [blame] | 413 | fn encode_meta_item(&ebml::writer ebml_w, &meta_item mi) { |
Brian Anderson | f53c4f7 | 2011-06-28 02:41:48 | [diff] [blame] | 414 | alt (mi.node) { |
Brian Anderson | cab73f8 | 2011-06-28 06:02:02 | [diff] [blame] | 415 | case (meta_word(?name)) { |
| 416 | ebml::start_tag(ebml_w, tag_meta_item_word); |
| 417 | ebml::start_tag(ebml_w, tag_meta_item_name); |
| 418 | ebml_w.writer.write(str::bytes(name)); |
| 419 | ebml::end_tag(ebml_w); |
| 420 | ebml::end_tag(ebml_w); |
| 421 | } |
| 422 | case (meta_name_value(?name, ?value)) { |
Brian Anderson | 2cb1293 | 2011-07-06 00:01:23 | [diff] [blame] | 423 | alt (value.node) { |
| 424 | case (lit_str(?value, _)) { |
| 425 | ebml::start_tag(ebml_w, tag_meta_item_name_value); |
| 426 | ebml::start_tag(ebml_w, tag_meta_item_name); |
| 427 | ebml_w.writer.write(str::bytes(name)); |
| 428 | ebml::end_tag(ebml_w); |
| 429 | ebml::start_tag(ebml_w, tag_meta_item_value); |
| 430 | ebml_w.writer.write(str::bytes(value)); |
| 431 | ebml::end_tag(ebml_w); |
| 432 | ebml::end_tag(ebml_w); |
| 433 | } |
| 434 | case (_) { /* FIXME (#611) */ } |
| 435 | } |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 436 | } |
Brian Anderson | cab73f8 | 2011-06-28 06:02:02 | [diff] [blame] | 437 | case (meta_list(?name, ?items)) { |
| 438 | ebml::start_tag(ebml_w, tag_meta_item_list); |
| 439 | ebml::start_tag(ebml_w, tag_meta_item_name); |
| 440 | ebml_w.writer.write(str::bytes(name)); |
| 441 | ebml::end_tag(ebml_w); |
| 442 | for (@meta_item inner_item in items) { |
| 443 | encode_meta_item(ebml_w, *inner_item); |
| 444 | } |
| 445 | ebml::end_tag(ebml_w); |
Brian Anderson | f53c4f7 | 2011-06-28 02:41:48 | [diff] [blame] | 446 | } |
| 447 | } |
Brian Anderson | f53c4f7 | 2011-06-28 02:41:48 | [diff] [blame] | 448 | } |
| 449 | |
| 450 | fn encode_attributes(&ebml::writer ebml_w, &vec[attribute] attrs) { |
| 451 | ebml::start_tag(ebml_w, tag_attributes); |
| 452 | for (attribute attr in attrs) { |
| 453 | ebml::start_tag(ebml_w, tag_attribute); |
| 454 | encode_meta_item(ebml_w, attr.node.value); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 455 | ebml::end_tag(ebml_w); |
| 456 | } |
Brian Anderson | f53c4f7 | 2011-06-28 02:41:48 | [diff] [blame] | 457 | ebml::end_tag(ebml_w); |
| 458 | } |
| 459 | |
Graydon Hoare | c796a8f | 2011-06-29 22:11:20 | [diff] [blame] | 460 | // So there's a special crate attribute called 'link' which defines the |
| 461 | // metadata that Rust cares about for linking crates. This attribute requires |
Brian Anderson | 70a28dc | 2011-07-01 00:03:08 | [diff] [blame] | 462 | // 'name' and 'vers' items, so if the user didn't provide them we will throw |
Graydon Hoare | c796a8f | 2011-06-29 22:11:20 | [diff] [blame] | 463 | // them in anyway with default values. |
Brian Anderson | 29afe1a | 2011-06-29 21:17:23 | [diff] [blame] | 464 | fn synthesize_crate_attrs(&@crate_ctxt cx, |
| 465 | &@crate crate) -> vec[attribute] { |
| 466 | |
Patrick Walton | 401b636 | 2011-07-06 00:57:34 | [diff] [blame] | 467 | fn synthesize_link_attr(&@crate_ctxt cx, &(@meta_item)[] items) |
| 468 | -> attribute { |
Brian Anderson | 29afe1a | 2011-06-29 21:17:23 | [diff] [blame] | 469 | |
Brian Anderson | 70a28dc | 2011-07-01 00:03:08 | [diff] [blame] | 470 | assert cx.link_meta.name != ""; |
| 471 | assert cx.link_meta.vers != ""; |
Brian Anderson | 29afe1a | 2011-06-29 21:17:23 | [diff] [blame] | 472 | |
Brian Anderson | 2cb1293 | 2011-07-06 00:01:23 | [diff] [blame] | 473 | auto name_item = attr::mk_name_value_item_str("name", |
| 474 | cx.link_meta.name); |
| 475 | auto vers_item = attr::mk_name_value_item_str("vers", |
| 476 | cx.link_meta.vers); |
Brian Anderson | 29afe1a | 2011-06-29 21:17:23 | [diff] [blame] | 477 | |
| 478 | auto other_items = { |
| 479 | auto tmp = attr::remove_meta_items_by_name(items, "name"); |
| 480 | attr::remove_meta_items_by_name(tmp, "vers") |
| 481 | }; |
| 482 | |
Patrick Walton | 401b636 | 2011-07-06 00:57:34 | [diff] [blame] | 483 | auto meta_items = ~[name_item, vers_item] + other_items; |
Brian Anderson | 70a28dc | 2011-07-01 00:03:08 | [diff] [blame] | 484 | auto link_item = attr::mk_list_item("link", meta_items); |
Brian Anderson | 29afe1a | 2011-06-29 21:17:23 | [diff] [blame] | 485 | |
Brian Anderson | 70a28dc | 2011-07-01 00:03:08 | [diff] [blame] | 486 | ret attr::mk_attr(link_item); |
Brian Anderson | 29afe1a | 2011-06-29 21:17:23 | [diff] [blame] | 487 | } |
| 488 | |
| 489 | let vec[attribute] attrs = []; |
| 490 | auto found_link_attr = false; |
| 491 | for (attribute attr in crate.node.attrs) { |
| 492 | attrs += if (attr::get_attr_name(attr) != "link") { |
| 493 | [attr] |
| 494 | } else { |
| 495 | alt (attr.node.value.node) { |
| 496 | case (meta_list(?n, ?l)) { |
| 497 | found_link_attr = true; |
| 498 | [synthesize_link_attr(cx, l)] |
| 499 | } |
| 500 | case (_) { [attr] } |
| 501 | } |
| 502 | } |
| 503 | } |
| 504 | |
| 505 | if (!found_link_attr) { |
Patrick Walton | 401b636 | 2011-07-06 00:57:34 | [diff] [blame] | 506 | attrs += [synthesize_link_attr(cx, ~[])]; |
Brian Anderson | 29afe1a | 2011-06-29 21:17:23 | [diff] [blame] | 507 | } |
| 508 | |
| 509 | ret attrs; |
| 510 | } |
| 511 | |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 512 | fn encode_metadata(&@crate_ctxt cx, &@crate crate) -> str { |
| 513 | auto string_w = io::string_writer(); |
| 514 | auto buf_w = string_w.get_writer().get_buf_writer(); |
| 515 | auto ebml_w = ebml::create_writer(buf_w); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 516 | |
Brian Anderson | 29afe1a | 2011-06-29 21:17:23 | [diff] [blame] | 517 | auto crate_attrs = synthesize_crate_attrs(cx, crate); |
| 518 | encode_attributes(ebml_w, crate_attrs); |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 519 | // Encode and index the paths. |
| 520 | |
| 521 | ebml::start_tag(ebml_w, tag_paths); |
| 522 | auto paths_index = encode_item_paths(ebml_w, crate); |
| 523 | auto str_writer = write_str; |
| 524 | auto path_hasher = hash_path; |
| 525 | auto paths_buckets = create_index[str](paths_index, path_hasher); |
| 526 | encode_index[str](ebml_w, paths_buckets, str_writer); |
| 527 | ebml::end_tag(ebml_w); |
| 528 | // Encode and index the items. |
| 529 | |
| 530 | ebml::start_tag(ebml_w, tag_items); |
| 531 | auto items_index = encode_info_for_items(cx, ebml_w); |
| 532 | auto int_writer = write_int; |
Brian Anderson | b723082 | 2011-07-07 19:12:25 | [diff] [blame] | 533 | auto item_hasher = hash_node_id; |
Brian Anderson | 33294c7 | 2011-06-27 22:20:17 | [diff] [blame] | 534 | auto items_buckets = create_index[int](items_index, item_hasher); |
| 535 | encode_index[int](ebml_w, items_buckets, int_writer); |
| 536 | ebml::end_tag(ebml_w); |
| 537 | // Pad this, since something (LLVM, presumably) is cutting off the |
| 538 | // remaining % 4 bytes. |
| 539 | |
| 540 | buf_w.write([0u8, 0u8, 0u8, 0u8]); |
| 541 | ret string_w.get_str(); |
| 542 | } |
Brian Anderson | 894e222 | 2011-06-28 02:16:16 | [diff] [blame] | 543 | |
Brian Anderson | 7d26d1d | 2011-07-07 19:47:39 | [diff] [blame^] | 544 | // Get the encoded string for a type |
| 545 | fn ty_str(&ty::ctxt tcx, &ty::t t) -> str { |
| 546 | auto cx = @rec(ds = encoder::def_to_str, |
| 547 | tcx = tcx, |
| 548 | abbrevs = metadata::tyencode::ac_no_abbrevs); |
| 549 | auto sw = io::string_writer(); |
| 550 | tyencode::enc_ty(sw.get_writer(), cx, t); |
| 551 | ret sw.get_str(); |
| 552 | } |
| 553 | |
Brian Anderson | 894e222 | 2011-06-28 02:16:16 | [diff] [blame] | 554 | |
| 555 | // Local Variables: |
| 556 | // mode: rust |
| 557 | // fill-column: 78; |
| 558 | // indent-tabs-mode: nil |
| 559 | // c-basic-offset: 4 |
| 560 | // buffer-file-coding-system: utf-8-unix |
| 561 | // compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; |
| 562 | // End: |