From cb3a38afa2de4401af55fbb7b6050f499b182bf4 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 3 Apr 2016 23:38:29 +0200 Subject: fixes #1152 --- tests/macros/typesafeprintf.nim | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 tests/macros/typesafeprintf.nim (limited to 'tests/macros') diff --git a/tests/macros/typesafeprintf.nim b/tests/macros/typesafeprintf.nim new file mode 100644 index 000000000..2f4622f3e --- /dev/null +++ b/tests/macros/typesafeprintf.nim @@ -0,0 +1,48 @@ +discard """ + output: '''test 10''' +""" + +# bug #1152 + +import macros, typetraits +proc printfImpl(formatstr: cstring) {.importc: "printf", varargs.} + +iterator tokenize(format: string): char = + var i = 0 + while true: + case format[i] + of '%': + case format[i+1] + of '\0': break + else: yield format[i+1] + i.inc + of '\0': break + else: discard + i.inc + +macro printf(formatString: string{lit}, args: varargs[typed]): untyped = + var i = 0 + let err = getType(bindSym"ValueError") + for c in tokenize(formatString.strVal): + var expectedType = case c + of 'c': getType(bindSym"char") + of 'd', 'i', 'x', 'X': getType(bindSym"int") + of 'f', 'e', 'E', 'g', 'G': getType(bindSym"float") + of 's': getType(bindSym"string") + of 'p': getType(bindSym"pointer") + else: err + + var actualType = getType(args[i]) + inc i + + if sameType(expectedType, err): + error c & " is not a valid format character" + elif not sameType(expectedType, actualType): + error "type mismatch for argument " & $i & ". expected type: " & + $expectedType & ", actual type: " & $actualType + + # keep the original callsite, but use cprintf instead + result = callsite() + result[0] = bindSym"printfImpl" + +printf("test %d\n", 10) -- cgit 1.4.1-2-gfad0