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