1
Fork 0

Make extracting syntax extension arguments easier.

This commit is contained in:
Paul Stansifer 2012-05-14 15:32:32 -07:00
parent cdcce3ed5d
commit 9fe547d3a7
12 changed files with 62 additions and 80 deletions

View file

@ -136,7 +136,7 @@ fn connect_many(paths: [path]) -> path {
}
#[doc = "
Split a path into it's individual components
Split a path into its individual components
Splits a given path by path separators and returns a vector containing
each piece of the path. On Windows, if the path is absolute then

View file

@ -153,10 +153,37 @@ fn make_new_lit(cx: ext_ctxt, sp: codemap::span, lit: ast::lit_) ->
ret @{id: cx.next_id(), node: ast::expr_lit(sp_lit), span: sp};
}
fn get_mac_arg(cx: ext_ctxt, sp: span, arg: ast::mac_arg) -> @ast::expr {
alt (arg) {
some(expr) {expr}
none {cx.span_fatal(sp, "missing macro args")}
fn get_mac_args_no_max(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
min: uint, name: str) -> [@ast::expr] {
ret get_mac_args(cx, sp, arg, min, none, name);
}
fn get_mac_args(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
min: uint, max: option<uint>, name: str) -> [@ast::expr] {
alt arg {
some(expr) {
alt expr.node {
ast::expr_vec(elts, _) {
let elts_len = vec::len(elts);
alt max {
some(max) if ! (min <= elts_len && elts_len <= max) {
cx.span_fatal(sp,
#fmt["#%s takes between %u and %u arguments.",
name, min, max]);
}
none if ! (min <= elts_len) {
cx.span_fatal(sp, #fmt["#%s needs at least %u arguments.",
name, min]);
}
_ { ret elts; /* we're good */}
}
}
_ {
cx.span_fatal(sp, #fmt["#%s: malformed invocation", name])
}
}
}
none {cx.span_fatal(sp, #fmt["#%s: missing arguments", name])}
}
}

View file

@ -2,14 +2,7 @@ import base::*;
fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
_body: ast::mac_body) -> @ast::expr {
let arg = get_mac_arg(cx,sp,arg);
let args: [@ast::expr] =
alt arg.node {
ast::expr_vec(elts, _) { elts }
_ {
cx.span_fatal(sp, "#concat_idents requires a vector argument .")
}
};
let args = get_mac_args_no_max(cx,sp,arg,1u,"concat_idents");
let mut res: ast::ident = "";
for args.each {|e|
res += expr_to_ident(cx, e, "expected an ident");

View file

@ -9,17 +9,8 @@ export expand_syntax_ext;
fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
_body: ast::mac_body) -> @ast::expr {
let arg = get_mac_arg(cx,sp,arg);
let args: [@ast::expr] =
alt arg.node {
ast::expr_vec(elts, _) { elts }
_ {
cx.span_fatal(sp, "#env requires arguments of the form `[...]`.")
}
};
if vec::len::<@ast::expr>(args) != 1u {
cx.span_fatal(sp, "malformed #env call");
}
let args = get_mac_args(cx, sp, arg, 1u, option::some(1u), "env");
// FIXME: if this was more thorough it would manufacture an
// option<str> rather than just an maybe-empty string. (Issue #2248)

View file

@ -13,17 +13,7 @@ export expand_syntax_ext;
fn expand_syntax_ext(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
_body: ast::mac_body) -> @ast::expr {
let arg = get_mac_arg(cx,sp,arg);
let args: [@ast::expr] =
alt arg.node {
ast::expr_vec(elts, _) { elts }
_ {
cx.span_fatal(sp, "#fmt requires arguments of the form `[...]`.")
}
};
if vec::len::<@ast::expr>(args) == 0u {
cx.span_fatal(sp, "#fmt requires a format string");
}
let args = get_mac_args_no_max(cx, sp, arg, 1u, "fmt");
let fmt =
expr_to_str(cx, args[0],
"first argument to #fmt must be a string literal.");

View file

@ -1,21 +1,11 @@
import base::*;
import option;
fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
_body: ast::mac_body) -> @ast::expr {
let arg = get_mac_arg(cx,sp,arg);
let args: [@ast::expr] =
alt arg.node {
ast::expr_vec(elts, _) { elts }
_ {
cx.span_fatal(sp, "#ident_to_str requires a vector argument .")
}
};
if vec::len::<@ast::expr>(args) != 1u {
cx.span_fatal(sp, "malformed #ident_to_str call");
}
let args = get_mac_args(cx,sp,arg,1u,option::some(1u),"ident_to_str");
ret make_new_lit(cx, sp,
ast::lit_str(expr_to_ident(cx, args[0u],
"expected an ident")));
}

View file

@ -14,18 +14,8 @@ export str;
mod str {
fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
_body: ast::mac_body) -> @ast::expr {
let arg = get_mac_arg(cx,sp,arg);
let args: [@ast::expr] =
alt arg.node {
ast::expr_vec(elts, _) { elts }
_ {
cx.span_fatal(sp, "#include_str requires arguments \
of the form `[...]`.")
}
};
if vec::len::<@ast::expr>(args) != 1u {
cx.span_fatal(sp, "malformed #include_str call");
}
let args = get_mac_args(cx,sp,arg,1u,option::some(1u),"include_str");
let mut path = expr_to_str(cx, args[0], "#include_str requires \
a string");

View file

@ -3,9 +3,12 @@ import io::writer_util;
fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
_body: ast::mac_body) -> @ast::expr {
let arg = get_mac_arg(cx,sp,arg);
let args = get_mac_args_no_max(cx,sp,arg,0u,"log_syntax");
cx.print_backtrace();
io::stdout().write_line(print::pprust::expr_to_str(arg));
io::stdout().write_line(
str::connect(vec::map(args,
{|&&ex| print::pprust::expr_to_str(ex)}), ", ")
);
//trivial expression
ret @{id: cx.next_id(), node: ast::expr_rec([], option::none), span: sp};

View file

@ -668,15 +668,7 @@ fn p_t_s_r_actual_vector(cx: ext_ctxt, elts: [@expr], _repeat_after: bool,
fn add_new_extension(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
_body: ast::mac_body) -> base::macro_def {
let arg = get_mac_arg(cx,sp,arg);
let args: [@ast::expr] =
alt arg.node {
ast::expr_vec(elts, _) { elts }
_ {
cx.span_fatal(sp,
"#macro requires arguments of the form `[...]`.")
}
};
let args = get_mac_args_no_max(cx, sp, arg, 0u, "macro");
let mut macro_name: option<str> = none;
let mut clauses: [@clause] = [];
@ -712,9 +704,13 @@ fn add_new_extension(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
"macro name must not be a path");
}
}
let arg = alt invoc_arg {
some(arg) { arg }
none { cx.span_fatal(mac.span,
"macro must have arguments")}
};
clauses +=
[@{params: pattern_to_selectors
(cx, get_mac_arg(cx,mac.span,invoc_arg)),
[@{params: pattern_to_selectors(cx, arg),
body: elts[1u]}];
// FIXME: check duplicates (or just simplify
@ -746,16 +742,18 @@ fn add_new_extension(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
alt macro_name {
some(id) { id }
none {
cx.span_fatal(sp,
"macro definition must have " +
"at least one clause")
cx.span_fatal(sp, "macro definition must have " +
"at least one clause")
}
},
ext: normal({expander: ext, span: some(arg.span)})};
ext: normal({expander: ext, span: some(option::get(arg).span)})};
fn generic_extension(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
_body: ast::mac_body, clauses: [@clause]) -> @expr {
let arg = get_mac_arg(cx,sp,arg);
let arg = alt arg {
some(arg) { arg }
none { cx.span_fatal(sp, "macro must have arguments")}
};
for clauses.each {|c|
alt use_selectors_to_bind(c.params, arg) {
some(bindings) { ret transcribe(cx, bindings, c.body); }

View file

@ -1,3 +1,3 @@
// error-pattern:malformed #env call
// error-pattern:#env takes between 1 and 1 arguments
fn main() { #env[]; }

View file

@ -1,3 +1,3 @@
// error-pattern:malformed #env call
// error-pattern:#env takes between 1 and 1 arguments
fn main() { #env["one", "two"]; }

View file

@ -1,3 +1,3 @@
// error-pattern:format string
// error-pattern:#fmt needs at least 1 arguments
fn main() { #fmt[]; }