1 // Functions for building ASTs, without having to fuss with spans.
3 // To start with, it will be use dummy spans, but it might someday do
6 import ast::{ident, node_id};
8 import ext::base::mk_ctxt;
10 // Transitional reexports so qquote can find the paths it is looking for
18 fn ident(s: &str) -> ast::ident {
22 fn path(id: ident, span: span) -> @ast::path {
30 fn empty_span() -> span {
31 {lo: 0, hi: 0, expn_info: none}
35 fn add_ty(ty: @ast::ty) -> @ast::path;
36 fn add_tys(+tys: ~[@ast::ty]) -> @ast::path;
39 impl @ast::path: append_types {
40 fn add_ty(ty: @ast::ty) -> @ast::path {
41 @{types: vec::append_one(self.types, ty)
45 fn add_tys(+tys: ~[@ast::ty]) -> @ast::path {
46 @{types: vec::append(self.types, tys)
51 trait ext_ctxt_ast_builder {
52 fn ty_param(id: ast::ident, +bounds: ~[ast::ty_param_bound])
54 fn arg(name: ident, ty: @ast::ty) -> ast::arg;
55 fn arg_mode(name: ident, ty: @ast::ty, mode: ast::rmode) -> ast::arg;
56 fn expr_block(e: @ast::expr) -> ast::blk;
57 fn fn_decl(+inputs: ~[ast::arg], output: @ast::ty) -> ast::fn_decl;
58 fn item(name: ident, span: span, +node: ast::item_) -> @ast::item;
59 fn item_fn_poly(name: ident,
62 +ty_params: ~[ast::ty_param],
63 +body: ast::blk) -> @ast::item;
64 fn item_fn(name: ident,
67 +body: ast::blk) -> @ast::item;
68 fn item_enum_poly(name: ident,
70 +enum_definition: ast::enum_def,
71 +ty_params: ~[ast::ty_param]) -> @ast::item;
72 fn item_enum(name: ident, span: span,
73 +enum_definition: ast::enum_def) -> @ast::item;
74 fn variant(name: ident, span: span, +tys: ~[@ast::ty]) -> ast::variant;
75 fn item_mod(name: ident, span: span, +items: ~[@ast::item]) -> @ast::item;
76 fn ty_path_ast_builder(path: @ast::path) -> @ast::ty;
77 fn item_ty_poly(name: ident,
80 +params: ~[ast::ty_param]) -> @ast::item;
81 fn item_ty(name: ident, span: span, ty: @ast::ty) -> @ast::item;
82 fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::ty];
83 fn ty_field_imm(name: ident, ty: @ast::ty) -> ast::ty_field;
84 fn ty_rec(+~[ast::ty_field]) -> @ast::ty;
85 fn field_imm(name: ident, e: @ast::expr) -> ast::field;
86 fn rec(+~[ast::field]) -> @ast::expr;
87 fn block(+stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk;
88 fn stmt_let(ident: ident, e: @ast::expr) -> @ast::stmt;
89 fn stmt_expr(e: @ast::expr) -> @ast::stmt;
90 fn block_expr(b: ast::blk) -> @ast::expr;
91 fn empty_span() -> span;
92 fn ty_option(ty: @ast::ty) -> @ast::ty;
95 impl ext_ctxt: ext_ctxt_ast_builder {
96 fn ty_option(ty: @ast::ty) -> @ast::ty {
97 self.ty_path_ast_builder(path(@~"option", self.empty_span())
101 fn empty_span() -> span {
102 {lo: 0, hi: 0, expn_info: self.backtrace()}
105 fn block_expr(b: ast::blk) -> @ast::expr {
106 @{id: self.next_id(),
107 callee_id: self.next_id(),
108 node: ast::expr_block(b),
109 span: self.empty_span()}
112 fn stmt_expr(e: @ast::expr) -> @ast::stmt {
113 @{node: ast::stmt_expr(e, self.next_id()),
114 span: self.empty_span()}
117 fn stmt_let(ident: ident, e: @ast::expr) -> @ast::stmt {
118 // If the quasiquoter could interpolate idents, this is all
122 //#ast[stmt] { let $(ident) = $(e) }
124 @{node: ast::stmt_decl(@{node: ast::decl_local(~[
125 @{node: {is_mutbl: false,
127 pat: @{id: self.next_id(),
128 node: ast::pat_ident(ast::bind_by_implicit_ref,
132 span: self.empty_span()},
133 init: some({op: ast::init_move,
136 span: self.empty_span()}]),
137 span: self.empty_span()}, self.next_id()),
138 span: self.empty_span()}
141 fn field_imm(name: ident, e: @ast::expr) -> ast::field {
142 {node: {mutbl: ast::m_imm, ident: name, expr: e},
143 span: self.empty_span()}
146 fn rec(+fields: ~[ast::field]) -> @ast::expr {
147 @{id: self.next_id(),
148 callee_id: self.next_id(),
149 node: ast::expr_rec(fields, none),
150 span: self.empty_span()}
153 fn ty_field_imm(name: ident, ty: @ast::ty) -> ast::ty_field {
154 {node: {ident: name, mt: { ty: ty, mutbl: ast::m_imm } },
155 span: self.empty_span()}
158 fn ty_rec(+fields: ~[ast::ty_field]) -> @ast::ty {
159 @{id: self.next_id(),
160 node: ast::ty_rec(fields),
161 span: self.empty_span()}
164 fn ty_infer() -> @ast::ty {
165 @{id: self.next_id(),
167 span: self.empty_span()}
170 fn ty_param(id: ast::ident, +bounds: ~[ast::ty_param_bound])
173 {ident: id, id: self.next_id(), bounds: @bounds}
176 fn arg(name: ident, ty: @ast::ty) -> ast::arg {
177 {mode: ast::infer(self.next_id()),
183 fn arg_mode(name: ident, ty: @ast::ty, mode: ast::rmode) -> ast::arg {
184 {mode: ast::expl(mode),
190 fn block(+stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk {
191 let blk = {view_items: ~[],
195 rules: ast::default_blk};
198 span: self.empty_span()}
201 fn expr_block(e: @ast::expr) -> ast::blk {
205 fn fn_decl(+inputs: ~[ast::arg],
206 output: @ast::ty) -> ast::fn_decl {
209 purity: ast::impure_fn,
215 +node: ast::item_) -> @ast::item {
224 fn item_fn_poly(name: ident,
225 +inputs: ~[ast::arg],
227 +ty_params: ~[ast::ty_param],
228 +body: ast::blk) -> @ast::item {
231 ast::item_fn(self.fn_decl(inputs, output),
236 fn item_fn(name: ident,
237 +inputs: ~[ast::arg],
239 +body: ast::blk) -> @ast::item {
240 self.item_fn_poly(name, inputs, output, ~[], body)
243 fn item_enum_poly(name: ident,
245 +enum_definition: ast::enum_def,
246 +ty_params: ~[ast::ty_param]) -> @ast::item {
247 self.item(name, span, ast::item_enum(enum_definition, ty_params))
250 fn item_enum(name: ident, span: span,
251 +enum_definition: ast::enum_def) -> @ast::item {
252 self.item_enum_poly(name, span, enum_definition, ~[])
255 fn variant(name: ident,
257 +tys: ~[@ast::ty]) -> ast::variant {
258 let args = tys.map(|ty| {ty: ty, id: self.next_id()});
262 kind: ast::tuple_variant_kind(args),
269 fn item_mod(name: ident,
271 +items: ~[@ast::item]) -> @ast::item {
279 fn ty_path_ast_builder(path: @ast::path) -> @ast::ty {
280 @{id: self.next_id(),
281 node: ast::ty_path(path, self.next_id()),
285 fn ty_nil_ast_builder() -> @ast::ty {
286 @{id: self.next_id(),
288 span: self.empty_span()}
291 fn item_ty_poly(name: ident,
294 +params: ~[ast::ty_param]) -> @ast::item {
295 self.item(name, span, ast::item_ty(ty, params))
298 fn item_ty(name: ident, span: span, ty: @ast::ty) -> @ast::item {
299 self.item_ty_poly(name, span, ty, ~[])
302 fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::ty] {
303 ty_params.map(|p| self.ty_path_ast_builder(
304 path(p.ident, self.empty_span())))