diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2016-04-03 23:38:29 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2016-04-03 23:38:29 +0200 |
commit | cb3a38afa2de4401af55fbb7b6050f499b182bf4 (patch) | |
tree | 7cb34d8933480dedcab82281a39f491fbf545368 /tests/macros | |
parent | 6e53300f83dc7646fbad834c494c34470a393885 (diff) | |
download | Nim-cb3a38afa2de4401af55fbb7b6050f499b182bf4.tar.gz |
fixes #1152
Diffstat (limited to 'tests/macros')
-rw-r--r-- | tests/macros/typesafeprintf.nim | 48 |
1 files changed, 48 insertions, 0 deletions
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) |