@@ -2,31 +2,94 @@ import driver::session;
2
2
3
3
import option :: { none, some} ;
4
4
5
- import syntax:: ast:: { crate, expr_, expr_mac, mac_invoc, mac_qq, mac_var} ;
5
+ import syntax:: ast:: { crate, expr_, expr_mac, mac_invoc,
6
+ mac_qq, mac_aq, mac_var} ;
6
7
import syntax:: fold:: * ;
8
+ import syntax:: visit:: * ;
7
9
import syntax:: ext:: base:: * ;
8
10
import syntax:: ext:: build:: * ;
9
11
import syntax:: parse:: parser:: parse_expr_from_source_str;
10
12
13
+ import syntax:: print:: * ;
14
+ import std:: io:: * ;
15
+
11
16
import codemap:: span;
12
17
13
- fn expand_qquote ( cx : ext_ctxt , sp : span , _e : @ast:: expr ) -> ast:: expr_ {
14
- let str = codemap:: span_to_snippet ( sp, cx. session ( ) . parse_sess . cm ) ;
18
+ type aq_ctxt = @{ lo : uint ,
19
+ mutable gather: [ { lo : uint , hi : uint , e : @ast:: expr } ] } ;
20
+
21
+ fn gather_anti_quotes ( lo : uint , e : @ast:: expr ) -> aq_ctxt
22
+ {
23
+ let v = @{ visit_expr: visit_expr_aq
24
+ with * default_visitor ( ) } ;
25
+ let cx = @{ lo: lo, mutable gather: [ ] } ;
26
+ visit_expr_aq ( e, cx, mk_vt ( v) ) ;
27
+ ret cx;
28
+ }
29
+
30
+ fn visit_expr_aq ( expr : @ast:: expr , & & cx: aq_ctxt , v : vt < aq_ctxt > )
31
+ {
32
+ alt ( expr. node ) {
33
+ expr_mac ( { node: mac_aq ( sp, e) , _} ) {
34
+ cx. gather += [ { lo: sp. lo - cx. lo , hi: sp. hi - cx. lo ,
35
+ e: e} ] ;
36
+ }
37
+ _ { visit_expr( expr, cx, v) ; }
38
+ }
39
+ }
40
+
41
+ fn expand_qquote ( ecx : ext_ctxt , sp : span , e : @ast:: expr ) -> ast:: expr_ {
42
+ let str = codemap:: span_to_snippet ( sp, ecx. session ( ) . parse_sess . cm ) ;
43
+ let qcx = gather_anti_quotes ( sp. lo , e) ;
44
+ let cx = qcx;
45
+ let prev = 0 u;
46
+ for { lo: lo, _} in cx. gather {
47
+ assert lo > prev;
48
+ prev = lo;
49
+ }
50
+ let str2 = "" ;
51
+ let active = true ;
52
+ let i = 0 u, j = 0 u;
53
+ let g_len = vec:: len ( cx. gather ) ;
54
+ str:: chars_iter ( str) { |ch|
55
+ if ( active && j < g_len && i == cx. gather [ j] . lo ) {
56
+ assert ch == '$' ;
57
+ active = false ;
58
+ str2 += #fmt ( " $%u " , j) ;
59
+ }
60
+ if ( active) { str:: push_char ( str2, ch) ; }
61
+ i += 1 u;
62
+ if ( !active && j < g_len && i == cx. gather [ j] . hi ) {
63
+ assert ch == ')' ;
64
+ active = true ;
65
+ j += 1 u;
66
+ }
67
+ }
68
+
69
+ let cx = ecx;
15
70
let session_call = bind mk_call_ ( cx, sp,
16
71
mk_access ( cx, sp, [ "ext_cx" ] , "session" ) ,
17
72
[ ] ) ;
18
- let call = mk_call ( cx, sp,
73
+ let pcall = mk_call ( cx, sp,
19
74
[ "syntax" , "parse" , "parser" ,
20
75
"parse_expr_from_source_str" ] ,
21
76
[ mk_str ( cx, sp, "<anon>" ) ,
22
77
mk_unary ( cx, sp, ast:: box ( ast:: imm) ,
23
- mk_str ( cx, sp, str ) ) ,
78
+ mk_str ( cx, sp, str2 ) ) ,
24
79
mk_access_ ( cx, sp,
25
80
mk_access_ ( cx, sp, session_call ( ) , "opts" ) ,
26
81
"cfg" ) ,
27
82
mk_access_ ( cx, sp, session_call ( ) , "parse_sess" ) ]
28
83
) ;
29
- ret call. node ;
84
+ let rcall = pcall;
85
+ if ( g_len > 0 u) {
86
+ rcall = mk_call ( cx, sp,
87
+ [ "syntax" , "ext" , "qquote" , "replace" ] ,
88
+ [ pcall,
89
+ mk_vec_e ( cx, sp, vec:: map ( qcx. gather , { |g| g. e } ) ) ] ) ;
90
+ }
91
+
92
+ ret rcall. node ;
30
93
}
31
94
32
95
fn replace ( e : @ast:: expr , repls : [ @ast:: expr ] ) -> @ast:: expr {
@@ -43,14 +106,20 @@ fn replace_expr(repls: [@ast::expr],
43
106
orig : fn @( ast:: expr_ , span , ast_fold ) ->( ast:: expr_ , span ) )
44
107
-> ( ast:: expr_ , span )
45
108
{
46
- // note: nested enum matching will be really nice here so I can jusy say
47
- // expr_mac(mac_var(i))
48
109
alt e {
49
110
expr_mac( { node : mac_var ( i) , _} ) { let r = repls[ i] ; ( r. node , r. span ) }
50
111
_ { orig( e, s, fld) }
51
112
}
52
113
}
53
114
115
+ fn print_expr ( expr : @ast:: expr ) {
116
+ let stdout = std:: io:: stdout ( ) ;
117
+ let pp = pprust:: rust_printer ( stdout) ;
118
+ pprust:: print_expr ( pp, expr) ;
119
+ pp:: eof ( pp. s ) ;
120
+ stdout. write_str ( "\n " ) ;
121
+ }
122
+
54
123
// Local Variables:
55
124
// mode: rust
56
125
// fill-column: 78;
0 commit comments