Make #fmt work from inside std. Issue #175

At long last, this patch makes #fmt usable from inside the standard library.
The way it does it us very hackish, but at least it works now.
This commit is contained in:
Brian Anderson 2011-07-10 17:00:28 -07:00
parent e494e73cdd
commit 6d3513eaee
2 changed files with 25 additions and 10 deletions

View File

@ -36,7 +36,8 @@ type next_id_fn = fn() -> ast::node_id ;
// Provides a limited set of services necessary for syntax extensions
// to do their thing
type ext_ctxt =
rec(span_msg_fn span_fatal,
rec(str crate_file_name_hack,
span_msg_fn span_fatal,
span_msg_fn span_unimpl,
next_id_fn next_id);
@ -50,9 +51,19 @@ fn mk_ctxt(&parse_sess sess) -> ext_ctxt {
codemap::emit_error(option::some(sp), "unimplemented " + msg, cm);
fail;
}
// FIXME: Some extensions work by building ASTs with paths to functions
// they need to call at runtime. As those functions live in the std crate,
// the paths are prefixed with "std::". Unfortunately, these paths can't
// work for code called from inside the stdard library, so here we pass
// the extensions the file name of the crate being compiled so they can
// use it to guess whether paths should be prepended with "std::". This is
// super-ugly and needs a better solution.
auto crate_file_name_hack = sess.cm.files.(0).name;
auto ext_span_unimpl = bind ext_span_unimpl_(sess.cm, _, _);
auto ext_next_id = bind parse::parser::next_node_id(sess);
ret rec(span_fatal=ext_span_fatal,
ret rec(crate_file_name_hack=crate_file_name_hack,
span_fatal=ext_span_fatal,
span_unimpl=ext_span_unimpl,
next_id=ext_next_id);
}

View File

@ -92,15 +92,19 @@ fn pieces_to_expr(&ext_ctxt cx, span sp, vec[piece] pieces,
auto recexpr = ast::expr_rec(astfields, option::none[@ast::expr]);
ret @rec(id=cx.next_id(), node=recexpr, span=sp);
}
fn make_path_vec(str ident) -> str[] {
// FIXME: #fmt can't currently be used from within std
// because we're explicitly referencing the 'std' crate here
ret ~["std", "extfmt", "rt", ident];
fn make_path_vec(&ext_ctxt cx, str ident) -> str[] {
fn compiling_std(&ext_ctxt cx) -> bool {
ret str::find(cx.crate_file_name_hack, "std.rc") >= 0;
}
if (compiling_std(cx)) {
ret ~["extfmt", "rt", ident];
} else {
ret ~["std", "extfmt", "rt", ident];
}
}
fn make_rt_path_expr(&ext_ctxt cx, span sp, str ident) ->
@ast::expr {
auto path = make_path_vec(ident);
auto path = make_path_vec(cx, ident);
ret make_path_expr(cx, sp, path);
}
// Produces an AST expression that represents a RT::conv record,
@ -141,7 +145,7 @@ fn pieces_to_expr(&ext_ctxt cx, span sp, vec[piece] pieces,
}
case (count_is(?c)) {
auto count_lit = make_new_int(cx, sp, c);
auto count_is_path = make_path_vec("count_is");
auto count_is_path = make_path_vec(cx, "count_is");
auto count_is_args = ~[count_lit];
ret make_call(cx, sp, count_is_path, count_is_args);
}
@ -184,7 +188,7 @@ fn pieces_to_expr(&ext_ctxt cx, span sp, vec[piece] pieces,
fn make_conv_call(&ext_ctxt cx, span sp, str conv_type, &conv cnv,
@ast::expr arg) -> @ast::expr {
auto fname = "conv_" + conv_type;
auto path = make_path_vec(fname);
auto path = make_path_vec(cx, fname);
auto cnv_expr = make_rt_conv_expr(cx, sp, cnv);
auto args = ~[cnv_expr, arg];
ret make_call(cx, arg.span, path, args);