File: typesafeprintf.nim

package info (click to toggle)
nim 0.19.4-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 462,356 kB
  • sloc: sh: 11,089; ansic: 4,699; makefile: 706; python: 309; sql: 297; asm: 141; xml: 13
file content (49 lines) | stat: -rw-r--r-- 1,325 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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 i < format.len:
    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 = newCall(bindSym"printfImpl")
  result.add formatString
  for a in args: result.add a

printf("test %d\n", 10)