Make the macro system more modular.

This commit is contained in:
Paul Stansifer 2011-06-02 18:58:23 -07:00 committed by Graydon Hoare
parent cfc75695a5
commit 79fcd51b46
4 changed files with 63 additions and 74 deletions

View file

@ -14,9 +14,9 @@ import std::generic_os;
export expand_syntax_ext; export expand_syntax_ext;
// FIXME: Need to thread parser through here to handle errors correctly // FIXME: Need to thread parser through here to handle errors correctly
fn expand_syntax_ext(parser::parser p, fn expand_syntax_ext(&parser::parser p,
common::span sp, common::span sp,
vec[@ast::expr] args, &vec[@ast::expr] args,
option::t[str] body) -> @ast::expr { option::t[str] body) -> @ast::expr {
if (vec::len[@ast::expr](args) != 1u) { if (vec::len[@ast::expr](args) != 1u) {

View file

@ -13,41 +13,12 @@ import std::option;
import std::option::none; import std::option::none;
import std::option::some; import std::option::some;
import std::extfmt::ct::signedness; import std::extfmt::ct::*;
import std::extfmt::ct::signed;
import std::extfmt::ct::unsigned;
import std::extfmt::ct::caseness;
import std::extfmt::ct::case_upper;
import std::extfmt::ct::case_lower;
import std::extfmt::ct::ty;
import std::extfmt::ct::ty_bool;
import std::extfmt::ct::ty_str;
import std::extfmt::ct::ty_char;
import std::extfmt::ct::ty_int;
import std::extfmt::ct::ty_bits;
import std::extfmt::ct::ty_hex;
import std::extfmt::ct::ty_octal;
import std::extfmt::ct::flag;
import std::extfmt::ct::flag_left_justify;
import std::extfmt::ct::flag_left_zero_pad;
import std::extfmt::ct::flag_space_for_sign;
import std::extfmt::ct::flag_sign_always;
import std::extfmt::ct::flag_alternate;
import std::extfmt::ct::count;
import std::extfmt::ct::count_is;
import std::extfmt::ct::count_is_param;
import std::extfmt::ct::count_is_next_param;
import std::extfmt::ct::count_implied;
import std::extfmt::ct::conv;
import std::extfmt::ct::piece;
import std::extfmt::ct::piece_string;
import std::extfmt::ct::piece_conv;
import std::extfmt::ct::parse_fmt_string;
export expand_syntax_ext; export expand_syntax_ext;
fn expand_syntax_ext(parser p, fn expand_syntax_ext(&parser p, common::span sp,
vec[@ast::expr] args, &vec[@ast::expr] args,
option::t[str] body) -> @ast::expr { option::t[str] body) -> @ast::expr {
if (vec::len[@ast::expr](args) == 0u) { if (vec::len[@ast::expr](args) == 0u) {

View file

@ -27,6 +27,11 @@ tag file_type {
type ty_or_bang = util::common::ty_or_bang[@ast::ty]; type ty_or_bang = util::common::ty_or_bang[@ast::ty];
// Temporary: to introduce a tag in order to make a recursive type work
tag xmacro {
x(macro);
}
state type parser = state type parser =
state obj { state obj {
fn peek() -> token::token; fn peek() -> token::token;
@ -48,11 +53,15 @@ state type parser =
fn get_reader() -> lexer::reader; fn get_reader() -> lexer::reader;
fn get_filemap() -> codemap::filemap; fn get_filemap() -> codemap::filemap;
fn get_bad_expr_words() -> std::map::hashmap[str, ()]; fn get_bad_expr_words() -> std::map::hashmap[str, ()];
fn get_macros() -> std::map::hashmap[str, xmacro];
fn get_chpos() -> uint; fn get_chpos() -> uint;
fn get_ann() -> ast::ann; fn get_ann() -> ast::ann;
fn next_ann_num() -> uint; fn next_ann_num() -> uint;
}; };
type macro = fn(&parser, common::span, &vec[@ast::expr], option::t[str])
-> @ast::expr;
fn new_parser(session::session sess, fn new_parser(session::session sess,
eval::env env, eval::env env,
ast::def_id initial_def, ast::def_id initial_def,
@ -70,7 +79,8 @@ fn new_parser(session::session sess,
lexer::reader rdr, lexer::reader rdr,
vec[op_spec] precs, vec[op_spec] precs,
mutable uint next_ann_var, mutable uint next_ann_var,
std::map::hashmap[str, ()] bad_words) std::map::hashmap[str, ()] bad_words,
std::map::hashmap[str, xmacro] macros)
{ {
fn peek() -> token::token { fn peek() -> token::token {
ret tok; ret tok;
@ -143,6 +153,10 @@ fn new_parser(session::session sess,
ret bad_words; ret bad_words;
} }
fn get_macros() -> std::map::hashmap[str, xmacro] {
ret macros;
}
fn get_chpos() -> uint {ret rdr.get_chpos();} fn get_chpos() -> uint {ret rdr.get_chpos();}
fn get_ann() -> ast::ann { fn get_ann() -> ast::ann {
@ -169,7 +183,7 @@ fn new_parser(session::session sess,
ret stdio_parser(sess, env, ftype, lexer::next_token(rdr), ret stdio_parser(sess, env, ftype, lexer::next_token(rdr),
npos, npos, npos, initial_def._1, UNRESTRICTED, npos, npos, npos, initial_def._1, UNRESTRICTED,
initial_def._0, rdr, prec_table(), next_ann, initial_def._0, rdr, prec_table(), next_ann,
bad_expr_word_table()); bad_expr_word_table(), macro_table());
} }
// These are the words that shouldn't be allowed as value identifiers, // These are the words that shouldn't be allowed as value identifiers,
@ -213,6 +227,13 @@ fn bad_expr_word_table() -> std::map::hashmap[str, ()] {
ret words; ret words;
} }
fn macro_table() -> std::map::hashmap[str, xmacro] {
auto macros = new_str_hash[xmacro]();
macros.insert("fmt", x(extfmt::expand_syntax_ext));
macros.insert("env", x(extenv::expand_syntax_ext));
ret macros;
}
fn unexpected(&parser p, token::token t) -> ! { fn unexpected(&parser p, token::token t) -> ! {
let str s = "unexpected token: "; let str s = "unexpected token: ";
s += token::to_str(p.get_reader(), t); s += token::to_str(p.get_reader(), t);
@ -1037,23 +1058,15 @@ fn expand_syntax_ext(&parser p, common::span sp,
assert (vec::len[ast::ident](path.node.idents) > 0u); assert (vec::len[ast::ident](path.node.idents) > 0u);
auto extname = path.node.idents.(0); auto extname = path.node.idents.(0);
if (str::eq(extname, "fmt")) {
auto expanded = extfmt::expand_syntax_ext(p, args, body);
auto newexpr = ast::expr_ext(path, args, body,
expanded,
p.get_ann());
ret newexpr; alt (p.get_macros().find(extname)) {
} else if (str::eq(extname, "env")) { case (none[xmacro]) {
auto expanded = extenv::expand_syntax_ext(p, sp, args, body); p.err("unknown macro: '" + extname + "'");
auto newexpr = ast::expr_ext(path, args, body, }
expanded, case (some[xmacro](x(?ext))) {
ret ast::expr_ext(path, args, body, ext(p, sp, args, body),
p.get_ann()); p.get_ann());
}
ret newexpr;
} else {
p.err("unknown syntax extension");
fail;
} }
} }

View file

@ -0,0 +1,5 @@
// error-pattern:unknown macro
fn main() {
#iamnotanextensionthatexists("");
}