Implement #fmt conversion for int and uint

This commit is contained in:
Brian Anderson 2011-02-27 19:44:57 -05:00 committed by Graydon Hoare
parent f9144d5972
commit 61edf544a2

View File

@ -21,6 +21,8 @@ import std.option;
import std.option.none;
import std.option.some;
export expand_syntax_ext;
tag signedness {
signed;
unsigned;
@ -61,7 +63,7 @@ type conv = rec(option.t[int] param,
vec[flag] flags,
count width,
count precision,
ty typ);
ty ty);
// A fragment of the output sequence
tag piece {
@ -74,6 +76,7 @@ fn bad_fmt_call() {
fail;
}
// TODO: Need to thread parser through here to handle errors correctly
fn expand_syntax_ext(vec[@ast.expr] args,
option.t[@ast.expr] body) -> @ast.expr {
@ -96,6 +99,8 @@ fn expand_syntax_ext(vec[@ast.expr] args,
}
}
log "done printing all pieces";
auto args_len = _vec.len[@ast.expr](args);
auto fmt_args = _vec.slice[@ast.expr](args, 1u, args_len - 1u);
ret pieces_to_expr(pieces, args);
}
@ -179,7 +184,7 @@ fn parse_conversion(str s, uint i, uint lim) -> tup(piece, uint) {
flags = flags._0,
width = width._0,
precision = prec._0,
typ = ty._0)),
ty = ty._0)),
ty._1);
}
@ -252,22 +257,107 @@ fn parse_type(str s, uint i, uint lim) -> tup(ty, uint) {
fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr {
fn make_new_str(common.span sp, str s) -> @ast.expr {
auto strlit = ast.lit_str(s);
auto spstrlit = @parser.spanned[ast.lit_](sp, sp, strlit);
auto expr = ast.expr_lit(spstrlit, ast.ann_none);
fn make_new_lit(common.span sp, ast.lit_ lit) -> @ast.expr {
auto sp_lit = @parser.spanned[ast.lit_](sp, sp, lit);
auto expr = ast.expr_lit(sp_lit, ast.ann_none);
ret @parser.spanned[ast.expr_](sp, sp, expr);
}
fn make_new_str(common.span sp, str s) -> @ast.expr {
auto lit = ast.lit_str(s);
ret make_new_lit(sp, lit);
}
fn make_new_uint(common.span sp, uint u) -> @ast.expr {
auto lit = ast.lit_uint(u);
ret make_new_lit(sp, lit);
}
fn make_add_expr(common.span sp,
@ast.expr lhs, @ast.expr rhs) -> @ast.expr {
auto binexpr = ast.expr_binary(ast.add, lhs, rhs, ast.ann_none);
ret @parser.spanned[ast.expr_](sp, sp, binexpr);
}
fn make_call(common.span sp, vec[ast.ident] fn_path,
vec[@ast.expr] args) -> @ast.expr {
let vec[ast.ident] path_idents = fn_path;
let vec[@ast.ty] path_types = vec();
auto path = rec(idents = path_idents, types = path_types);
auto sp_path = parser.spanned[ast.path_](sp, sp, path);
auto pathexpr = ast.expr_path(sp_path, none[ast.def], ast.ann_none);
auto sp_pathexpr = @parser.spanned[ast.expr_](sp, sp, pathexpr);
auto callexpr = ast.expr_call(sp_pathexpr, args, ast.ann_none);
auto sp_callexpr = @parser.spanned[ast.expr_](sp, sp, callexpr);
ret sp_callexpr;
}
fn make_new_conv(conv cnv, @ast.expr arg) -> @ast.expr {
auto unsupported = "conversion not supported in #fmt string";
alt (cnv.param) {
case (option.none[int]) {
}
case (_) {
log unsupported;
fail;
}
}
if (_vec.len[flag](cnv.flags) != 0u) {
log unsupported;
fail;
}
alt (cnv.width) {
case (count_implied) {
}
case (_) {
log unsupported;
fail;
}
}
alt (cnv.precision) {
case (count_implied) {
}
case (_) {
log unsupported;
fail;
}
}
alt (cnv.ty) {
case (ty_str) {
ret arg;
}
case (ty_int(?sign)) {
alt (sign) {
case (signed) {
let vec[str] path = vec("std", "_int", "to_str");
auto radix_expr = make_new_uint(arg.span, 10u);
let vec[@ast.expr] args = vec(arg, radix_expr);
ret make_call(arg.span, path, args);
}
case (unsigned) {
let vec[str] path = vec("std", "_uint", "to_str");
auto radix_expr = make_new_uint(arg.span, 10u);
let vec[@ast.expr] args = vec(arg, radix_expr);
ret make_call(arg.span, path, args);
}
}
}
case (_) {
log unsupported;
fail;
}
}
}
auto sp = args.(0).span;
auto n = 0;
auto tmp_expr = make_new_str(sp, "whatever");
auto n = 0u;
auto tmp_expr = make_new_str(sp, "");
for (piece p in pieces) {
alt (p) {
@ -276,6 +366,15 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr {
tmp_expr = make_add_expr(sp, tmp_expr, s_expr);
}
case (piece_conv(?conv)) {
if (n >= _vec.len[@ast.expr](args)) {
log "too many conversions in #fmt string";
fail;
}
n += 1u;
auto arg_expr = args.(n);
auto c_expr = make_new_conv(conv, arg_expr);
tmp_expr = make_add_expr(sp, tmp_expr, c_expr);
}
}
}