@@ -70,6 +70,13 @@ deserializer `d`.
70
70
71
71
TODO--Hygiene. Search for "__" strings.
72
72
73
+ Misc notes:
74
+ -----------
75
+
76
+ I use move mode arguments for ast nodes that will get inserted as is
77
+ into the tree. This is intended to prevent us from inserting the same
78
+ node twice.
79
+
73
80
*/
74
81
import base:: * ;
75
82
import driver:: session:: session;
@@ -85,12 +92,12 @@ enum ser_cx = {
85
92
86
93
fn expand_auto_serialize ( cx : ext_ctxt ,
87
94
span : span ,
88
- mitem : ast:: meta_item ,
95
+ _mitem : ast:: meta_item ,
89
96
in_items : [ @ast:: item ] ) -> [ @ast:: item ] {
90
97
vec:: flat_map ( in_items) { |in_item|
91
98
alt in_item. node {
92
99
ast:: item_ty ( ty, tps) {
93
- [ in_item, ty_module ( cx, in_item. ident , ty, tps) ]
100
+ [ in_item, ty_module ( cx, in_item. ident , copy ty, tps) ]
94
101
}
95
102
96
103
ast:: item_enum ( variants, tps) {
@@ -107,9 +114,7 @@ fn expand_auto_serialize(cx: ext_ctxt,
107
114
}
108
115
}
109
116
110
- impl helpers for ser_cx {
111
- fn session ( ) -> session { self . ext_cx . session ( ) }
112
-
117
+ impl helpers for ext_ctxt {
113
118
fn next_id ( ) -> ast:: node_id { self . session ( ) . next_node_id ( ) }
114
119
115
120
fn path ( span : span , strs : [ str ] ) -> @ast:: path {
@@ -119,14 +124,25 @@ impl helpers for ser_cx {
119
124
span: span}
120
125
}
121
126
122
- fn expr ( span : span , node : ast:: expr_ ) -> @ast:: expr {
123
- @{ id: self . next_id ( ) , node: node, span: span}
124
- }
125
-
126
127
fn ty_path ( span : span , strs : [ str ] ) -> @ast:: ty {
127
128
@{ node: ast:: ty_path ( self . path ( span, strs) , self . next_id ( ) ) ,
128
129
span: span}
129
130
}
131
+ }
132
+
133
+ impl helpers for ser_cx {
134
+ fn session ( ) -> session { self . ext_cx . session ( ) }
135
+ fn next_id ( ) -> ast:: node_id { self . ext_cx . next_id ( ) }
136
+ fn path ( span : span , strs : [ str ] ) -> @ast:: path {
137
+ self . ext_cx . path ( span, strs)
138
+ }
139
+ fn ty_path ( span : span , strs : [ str ] ) -> @ast:: ty {
140
+ self . ext_cx . ty_path ( span, strs)
141
+ }
142
+
143
+ fn expr ( span : span , node : ast:: expr_ ) -> @ast:: expr {
144
+ @{ id: self . next_id ( ) , node: node, span: span}
145
+ }
130
146
131
147
fn var_ref ( span : span , name : str ) -> @ast:: expr {
132
148
self . expr ( span, ast:: expr_path ( self . path ( span, [ name] ) ) )
@@ -163,6 +179,27 @@ impl helpers for ser_cx {
163
179
ast:: expr_alt ( v, arms, ast:: alt_exhaustive) ) )
164
180
}
165
181
182
+ fn lit_str ( span : span , s : str ) -> @ast:: expr {
183
+ self . expr (
184
+ span,
185
+ ast:: expr_lit (
186
+ @{ node: ast:: lit_str ( s) ,
187
+ span: span} ) )
188
+ }
189
+
190
+ fn lit_uint ( span : span , i : uint ) -> @ast:: expr {
191
+ self . expr (
192
+ span,
193
+ ast:: expr_lit (
194
+ @{ node: ast:: lit_uint ( i as u64 , ast:: ty_u) ,
195
+ span: span} ) )
196
+ }
197
+
198
+ fn lambda ( -blk : @ast:: blk ) -> @ast:: expr {
199
+ let blk_e = cx. expr ( blk. span , expr_block ( blk) ) ;
200
+ #ast ( expr) { { || $( blk_e) } }
201
+ }
202
+
166
203
fn clone ( v : @ast:: expr ) -> @ast:: expr {
167
204
let fld = fold:: make_fold ( {
168
205
new_id: { |_id| self . next_id ( ) }
@@ -197,7 +234,8 @@ impl helpers for ser_cx {
197
234
}
198
235
}
199
236
200
- fn serialize_path ( cx : ser_cx , path : @ast:: path , -s : @ast:: expr , -v : @ast:: expr )
237
+ fn serialize_path ( cx : ser_cx , path : @ast:: path ,
238
+ -s : @ast:: expr , -v : @ast:: expr )
201
239
-> [ @ast:: stmt ] {
202
240
let ext_cx = cx. ext_cx ;
203
241
@@ -225,17 +263,28 @@ fn serialize_variant(cx: ser_cx,
225
263
tys : [ @ast:: ty ] ,
226
264
span : span ,
227
265
-s : @ast:: expr ,
228
- pfn : fn ( [ @ast:: pat ] ) -> ast:: pat_ ) -> ast:: arm {
266
+ pfn : fn ( [ @ast:: pat ] ) -> ast:: pat_ ,
267
+ bodyfn : fn ( -@ast:: expr , @ast:: blk ) -> @ast:: expr ,
268
+ argfn : fn ( -@ast:: expr , uint , @ast:: blk ) -> @ast:: expr )
269
+ -> ast:: arm {
229
270
let vnames = vec:: init_fn ( vec:: len ( tys) ) { |i| #fmt[ "__v%u" , i] } ;
230
271
let pats = vec:: init_fn ( vec:: len ( tys) ) { |i|
231
272
cx. binder_pat ( tys[ i] . span , vnames[ i] )
232
273
} ;
233
274
let pat: @ast:: pat = @{ id: cx. next_id ( ) , node: pfn ( pats) , span: span} ;
234
275
let stmts = vec:: init_fn ( vec:: len ( tys) ) { |i|
235
276
let v = cx. var_ref ( span, vnames[ i] ) ;
236
- serialize_ty ( cx, tys[ i] , cx. clone ( s) , v)
277
+ let arg_blk =
278
+ cx. blk (
279
+ span,
280
+ serialize_ty ( cx, tys[ i] , cx. clone ( s) , v) ) ;
281
+ cx. stmt ( argfn ( cx. clone ( s) , i, arg_blk) )
237
282
} ;
238
- { pats: [ pat] , guard: none, body: cx. blk ( span, vec:: concat ( stmts) ) }
283
+
284
+ let body_blk = cx. blk ( span, vec:: concat ( stmts) ) ;
285
+ let body = cx. blk ( span, [ cx. stmt ( bodyfn ( s, body_blk) ) ] ) ;
286
+
287
+ { pats: [ pat] , guard: none, body: body}
239
288
}
240
289
241
290
fn serialize_ty ( cx : ser_cx , ty : @ast:: ty , -s : @ast:: expr , -v : @ast:: expr )
@@ -278,8 +327,30 @@ fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
278
327
// };
279
328
280
329
let arms = [
281
- serialize_variant ( cx, tys, ty. span , s,
282
- { |pats| ast:: pat_tup ( pats) } )
330
+ serialize_variant (
331
+
332
+ cx, tys, ty. span , s,
333
+
334
+ // Generate pattern (v1, v2, v3)
335
+ { |pats| ast:: pat_tup ( pats) } ,
336
+
337
+ // Generate body s.emit_tup(3, {|| blk })
338
+ { |-s, -blk|
339
+ let sz = cx. lit_uint ( ty. span , vec:: len ( tys) ) ;
340
+ let body = cx. lambda ( blk) ;
341
+ #ast[ expr] {
342
+ $( s) . emit_tup ( $( sz) , $( body) )
343
+ }
344
+ } ,
345
+
346
+ // Generate s.emit_tup_elt(i, {|| blk })
347
+ { |-s, i, -blk|
348
+ let idx = cx. lit_uint ( ty. span , i) ;
349
+ let body = cx. lambda ( blk) ;
350
+ #ast[ expr] {
351
+ $( s) . emit_tup_elt ( $( idx) , $( body) )
352
+ }
353
+ } )
283
354
] ;
284
355
[ cx. alt_stmt ( arms, ty. span , v) ]
285
356
}
@@ -318,7 +389,7 @@ fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
318
389
let ser_e =
319
390
cx. expr (
320
391
ty. span ,
321
- expr_block (
392
+ ast :: expr_block (
322
393
cx. blk (
323
394
ty. span ,
324
395
serialize_ty (
@@ -327,46 +398,71 @@ fn serialize_ty(cx: ser_cx, ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
327
398
cx. at (
328
399
ty. span ,
329
400
#ast ( expr) { __e} ) ) ) ) ) ;
330
- [ #ast ( stmt) { $( s) . emit_from_vec ( $( v) , { |__e| $( ser_e) } ) } ]
401
+
402
+ [ cx. stmt (
403
+ cx. expr (
404
+ ty. span ,
405
+ ast:: expr_call (
406
+ #ast ( expr) { $( s) . emit_from_vec } ,
407
+ [ #ast ( expr) { { |__e| $( ser_e) } } ] ,
408
+ false ) ) ) ]
331
409
}
332
410
}
333
411
}
334
412
335
- fn ty_module ( ext_cx : ext_ctxt , name : str , -ty : @ast:: ty , tps : [ ast:: ty_param ] )
413
+ fn mk_ser_fn ( ext_cx : ext_ctxt , span : span ,
414
+ -v_ty : @ast:: ty , tps : [ ast:: ty_param ] ,
415
+ f : fn ( ser_cx , @ast:: ty , -@ast:: expr , -@ast:: expr ) -> [ @ast:: stmt ] )
336
416
-> @ast:: item {
337
417
338
418
let cx = ser_cx ( { ext_cx: ext_cx, tps: map:: new_str_hash ( ) } ) ;
339
419
420
+ let tp_inputs =
421
+ vec:: map ( tps, { |tp|
422
+ { mode: ast:: expl ( ast:: by_ref) ,
423
+ ty: cx. ty_path ( span, [ tp. ident ] ) ,
424
+ ident: "__s" + tp. ident ,
425
+ id: cx. next_id ( ) } } ) ;
426
+
340
427
let ser_inputs: [ ast:: arg ] =
341
428
[ { mode: ast:: expl ( ast:: by_ref) ,
342
- ty: cx. ty_path ( ty . span , [ "__S" ] ) ,
429
+ ty: cx. ty_path ( span, [ "__S" ] ) ,
343
430
ident: "__s" ,
344
431
id: cx. next_id ( ) } ,
345
432
{ mode: ast:: expl ( ast:: by_ref) ,
346
- ty: ty ,
433
+ ty: v_ty ,
347
434
ident: "__v" ,
348
- id: cx. next_id ( ) } ] +
349
- vec:: map ( tps, { |tp|
350
- { mode: ast:: expl ( ast:: by_ref) ,
351
- ty: cx. ty_path ( ty. span , [ tp. ident ] ) ,
352
- ident: "__v" ,
353
- id: cx. next_id ( ) } } ) ;
435
+ id: cx. next_id ( ) } ]
436
+ + tp_inputs;
437
+
438
+ vec:: iter2 ( tps, ser_inputs) { |tp, arg|
439
+ let arg_ident = arg. ident ;
440
+ cx. tps . insert (
441
+ tp. ident ,
442
+ fn @( v: @ast:: expr) -> [ @ast:: stmt] {
443
+ let f = cx. var_ref ( span, arg_ident) ;
444
+ [ cx. stmt (
445
+ cx. expr (
446
+ span,
447
+ ast:: expr_call ( f, [ v] , false ) ) ) ]
448
+ } ) ;
449
+ }
354
450
355
- let ser_bnds = @[ ast:: bound_iface ( cx. ty_path ( ty . span ,
451
+ let ser_bnds = @[ ast:: bound_iface ( cx. ty_path ( span,
356
452
[ "__std" , "serialization" ,
357
453
"serializer" ] ) ) ] ;
454
+
358
455
let ser_tps: [ ast:: ty_param ] =
359
456
[ { ident: "__S" ,
360
457
id: cx. next_id ( ) ,
361
458
bounds: ser_bnds} ] +
362
459
vec:: map ( tps) { |tp| cx. clone_ty_param ( tp) } ;
363
460
364
461
let ser_output: @ast:: ty = @{ node: ast:: ty_nil,
365
- span: ty . span } ;
462
+ span: span} ;
366
463
367
- let ser_blk = cx. blk ( ty. span ,
368
- serialize_ty ( cx, ty,
369
- #ast ( expr) { "__s" } , #ast ( expr) { "__v" } ) ) ;
464
+ let ser_blk = cx. blk ( span,
465
+ f ( cx, v_ty, #ast ( expr) { "__s" } , #ast ( expr) { "__v" } ) ) ;
370
466
371
467
@{ ident: "serialize" ,
372
468
attrs: [ ] ,
@@ -378,11 +474,91 @@ fn ty_module(ext_cx: ext_ctxt, name: str, -ty: @ast::ty, tps: [ast::ty_param])
378
474
constraints: [ ] } ,
379
475
ser_tps,
380
476
ser_blk) ,
381
- span: ty. span }
477
+ span: span}
478
+ }
479
+
480
+ fn ty_module ( ext_cx : ext_ctxt , name : str , -ty : @ast:: ty , tps : [ ast:: ty_param ] )
481
+ -> @ast:: item {
482
+
483
+ let span = ty. span ;
484
+ let ser_fn = mk_ser_fn ( ext_cx, span, ty, tps, serialize_ty) ;
485
+
486
+ // Return a module containing the serialization and deserialization
487
+ // functions:
488
+ @{ ident: name,
489
+ attrs: [ ] ,
490
+ id: ext_cx. session ( ) . next_node_id ( ) ,
491
+ node: ast:: item_mod ( { view_items: [ ] ,
492
+ items: [ ser_fn] } ) ,
493
+ span: span}
382
494
}
383
495
384
- fn enum_module ( cx : ext_ctxt , name : str ,
496
+ fn enum_module ( ext_cx : ext_ctxt , name : str , span : span ,
385
497
variants : [ ast:: variant ] , tps : [ ast:: ty_param ] )
386
498
-> @ast:: item {
387
499
388
- }
500
+ let span = ty. span ;
501
+ let ty = ext_cx. ty_path ( span, [ name] ) ;
502
+ let ser_fn = mk_ser_fn ( ext_cx, span, ty, tps) { |cx, ty, s, v|
503
+ let arms = vec:: init_fn ( vec:: len ( variants) ) { |vidx|
504
+ let variant = variants[ vidx] ;
505
+
506
+ if vec:: is_empty ( variant. args ) {
507
+ // degenerate case.
508
+ let pat = { id: cx. next_id ( ) ,
509
+ node: ast:: pat_ident ( cx. path ( variant. ident ) , none) ,
510
+ Span : variant. span } ;
511
+ //#ast(expr){
512
+ // $(s).emit_enum_variant(X, Y, SZ) {||
513
+ // };
514
+ //}
515
+ }
516
+
517
+ let variant_tys = vec:: map ( variant. args ) { |a| a. ty } ;
518
+
519
+ serialize_variant (
520
+ cx, variant_tys, variant. span , cx. clone ( s) ,
521
+
522
+ // Generate pattern var(v1, v2, v3)
523
+ { |pats|
524
+ let pat = { id: cx. next_id ( ) ,
525
+ node: ast:: pat_enum ( cx. path ( variant. ident ) ) ,
526
+ span: variant. span } ;
527
+
528
+ { id: cx. next_id ( ) ,
529
+ node: expr_call ( s, [ v_name,
530
+ v_id,
531
+ sz,
532
+ f] , false ) ,
533
+ span: variant. span }
534
+ } ,
535
+
536
+ // Generate body s.emit_enum_variant("foo", 0u, 3u, {|| blk })
537
+ { |-s, -blk|
538
+ let v_name = cx. lit_str ( variant. span , variant. ident ) ;
539
+ let v_id = cx. lit_uint ( variant. span , vidx) ;
540
+ let sz = cx. lit_uint ( variant. span , vec:: len ( variant_tys) ) ;
541
+ let body = cx. lambda ( blk) ;
542
+ #ast[ expr] {
543
+ $( s) . emit_enum_variant ( $( v_name) , $( v_id) , $( sz) , $( body) )
544
+ }
545
+ } ,
546
+
547
+ // Generate s.emit_enum_variant_arg(i, {|| blk })
548
+ { |-s, i, -blk|
549
+ let idx = cx. lit_uint ( i) ;
550
+ let body = cx. lambda ( blk) ;
551
+ #ast[ expr] {
552
+ $( s) . emit_enum_variant_arg ( $( idx) , $( body) )
553
+ }
554
+ } )
555
+ } ;
556
+ } ;
557
+
558
+ @{ ident: name,
559
+ attrs: [ ] ,
560
+ id: ext_cx. session ( ) . next_node_id ( ) ,
561
+ node: ast:: item_mod ( { view_items: [ ] ,
562
+ items: [ ser_fn] } ) ,
563
+ span: span}
564
+ }
0 commit comments