Begin implementing #fmt in rustc
This commit is contained in:
parent
e2d36e00ce
commit
9528c34774
@ -185,7 +185,7 @@ tag expr_ {
|
||||
expr_field(@expr, ident, ann);
|
||||
expr_index(@expr, @expr, ann);
|
||||
expr_path(path, option.t[def], ann);
|
||||
expr_ext(path, vec[@expr], option.t[@expr], ann);
|
||||
expr_ext(path, vec[@expr], option.t[@expr], option.t[@expr], ann);
|
||||
expr_fail;
|
||||
expr_ret(option.t[@expr]);
|
||||
expr_put(option.t[@expr]);
|
||||
@ -363,6 +363,17 @@ fn is_call_expr(@expr e) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_ext_expr(@expr e) -> bool {
|
||||
alt (e.node) {
|
||||
case (expr_ext(_, _, _, _, _)) {
|
||||
ret true;
|
||||
}
|
||||
case (_) {
|
||||
ret false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
|
84
src/comp/front/extfmt.rs
Normal file
84
src/comp/front/extfmt.rs
Normal file
@ -0,0 +1,84 @@
|
||||
/* The 'fmt' extension is modeled on the posix printf system.
|
||||
*
|
||||
* A posix conversion ostensibly looks like this:
|
||||
*
|
||||
* %[parameter][flags][width][.precision][length]type
|
||||
*
|
||||
* Given the different numeric type bestiary we have, we omit the 'length'
|
||||
* parameter and support slightly different conversions for 'type':
|
||||
*
|
||||
* %[parameter][flags][width][.precision]type
|
||||
*
|
||||
* we also only support translating-to-rust a tiny subset of the possible
|
||||
* combinations at the moment.
|
||||
*/
|
||||
|
||||
use std;
|
||||
|
||||
import std.option;
|
||||
|
||||
tag signedness {
|
||||
signed;
|
||||
unsigned;
|
||||
}
|
||||
|
||||
tag caseness {
|
||||
case_upper;
|
||||
case_lower;
|
||||
}
|
||||
|
||||
tag ty {
|
||||
ty_bool;
|
||||
ty_str;
|
||||
ty_char;
|
||||
ty_int(signedness);
|
||||
ty_bits;
|
||||
ty_hex(caseness);
|
||||
// FIXME: More types
|
||||
}
|
||||
|
||||
tag flag {
|
||||
flag_left_justify;
|
||||
flag_left_zero_pad;
|
||||
flag_left_space_pad;
|
||||
flag_plus_if_positive;
|
||||
flag_alternate;
|
||||
}
|
||||
|
||||
tag count {
|
||||
count_is(int);
|
||||
count_is_param(int);
|
||||
count_is_next_param;
|
||||
count_implied;
|
||||
}
|
||||
|
||||
// A formatted conversion from an expression to a string
|
||||
tag conv {
|
||||
conv_param(option.t[int]);
|
||||
conv_flags(vec[flag]);
|
||||
conv_width(count);
|
||||
conv_precision(count);
|
||||
conv_ty(ty);
|
||||
}
|
||||
|
||||
// A fragment of the output sequence
|
||||
tag piece {
|
||||
piece_string(str);
|
||||
piece_conv(str);
|
||||
}
|
||||
|
||||
fn expand_syntax_ext(vec[@ast.expr] args,
|
||||
option.t[@ast.expr] body) -> @ast.expr {
|
||||
fail;
|
||||
}
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
// fill-column: 78;
|
||||
// indent-tabs-mode: nil
|
||||
// c-basic-offset: 4
|
||||
// buffer-file-coding-system: utf-8-unix
|
||||
// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
|
||||
// End:
|
||||
//
|
@ -656,7 +656,10 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr {
|
||||
some(token.COMMA),
|
||||
pf, p);
|
||||
hi = es.span;
|
||||
ex = ast.expr_ext(pth, es.node, none[@ast.expr], ast.ann_none);
|
||||
ex = ast.expr_ext(pth, es.node, none[@ast.expr],
|
||||
none[@ast.expr], ast.ann_none);
|
||||
// FIXME: Here is probably not the right place for this
|
||||
ex = expand_syntax_ext(p, @spanned(lo, hi, ex)).node;
|
||||
}
|
||||
|
||||
case (token.FAIL) {
|
||||
@ -736,6 +739,36 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr {
|
||||
ret @spanned(lo, hi, ex);
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: This is a crude approximation of the syntax-extension system,
|
||||
* for purposes of prototyping and/or hard-wiring any extensions we
|
||||
* wish to use while bootstrapping. The eventual aim is to permit
|
||||
* loading rust crates to process extensions, but this will likely
|
||||
* require a rust-based frontend, or an ocaml-FFI-based connection to
|
||||
* rust crates. At the moment we have neither.
|
||||
*/
|
||||
|
||||
impure fn expand_syntax_ext(parser p, @ast.expr ext) -> @ast.expr {
|
||||
check (ast.is_ext_expr(ext));
|
||||
alt (ext.node) {
|
||||
case (ast.expr_ext(?path, ?args, ?body, _, ?ann)) {
|
||||
check (_vec.len[ast.ident](path.node.idents) > 0u);
|
||||
auto extname = path.node.idents.(0);
|
||||
if (_str.eq(extname, "fmt")) {
|
||||
auto expanded = extfmt.expand_syntax_ext(args, body);
|
||||
check (ast.is_ext_expr(expanded));
|
||||
auto newexpr = ast.expr_ext(path, args, body,
|
||||
some[@ast.expr](expanded), ann);
|
||||
|
||||
ret @spanned(ext.span, ext.span, newexpr);
|
||||
} else {
|
||||
p.err("unknown syntax extension");
|
||||
}
|
||||
}
|
||||
}
|
||||
fail;
|
||||
}
|
||||
|
||||
impure fn extend_expr_by_ident(parser p, span lo, span hi,
|
||||
@ast.expr e, ast.ident i) -> @ast.expr {
|
||||
auto e_ = e.node;
|
||||
|
@ -5,6 +5,7 @@ use std;
|
||||
|
||||
mod front {
|
||||
mod ast;
|
||||
mod extfmt;
|
||||
mod lexer;
|
||||
mod parser;
|
||||
mod token;
|
||||
|
@ -1,5 +1,13 @@
|
||||
use std;
|
||||
fn main() {
|
||||
auto s = #fmt("hello %d friends and %s things", 10, "formatted");
|
||||
log s;
|
||||
import std._str;
|
||||
|
||||
fn test(str actual, str expected) {
|
||||
log actual;
|
||||
log expected;
|
||||
check (_str.eq(actual, expected));
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test(#fmt("hello %d friends and %s things", 10, "formatted"),
|
||||
"hello 10 friends and formatted things");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user