tvarargsuntyped.nim 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. discard """
  2. output: '''Let's go!
  3. (left: 2, r: 7, x: 8, height: 4, s: test, width: 3, y: 9, top: 1, g: 7, b: 8)
  4. (left: 2, r: 7, x: 8, height: 4, s: text, width: 3, y: 9, top: 1, g: 7, b: 8)
  5. (left: 2, r: 7, x: 8, height: 4, s: text, width: 3, y: 9, top: 4, g: 7, b: 8)
  6. (left: 2, r: 7, x: 8, height: 4, s: test, width: 3, y: 9, top: 1, g: 7, b: 8)'''
  7. """
  8. import macros
  9. proc internalBar(top, left, width, height: cint, s: string, x, y: int, r,g,b: int) =
  10. echo "(left: ", left, ", r: ", r, ", x: ", x, ", height: ", height, ", s: ", s,
  11. ", width: ", width, ", y: ", y, ", top: ", top, ", g: ", g, ", b: ", b, ")"
  12. # we need these dummy constructors due to the wrong implementation
  13. # of 'varargs[untyped]' in the compiler:
  14. proc point(x, y: int): int = discard
  15. proc color(r, g, b: int): int = discard
  16. proc rect(a, b, c, d: int): int = discard
  17. template declareUnpackingMacro(nimname,extname) =
  18. macro nimname(n: varargs[untyped]): untyped =
  19. var s: string = astToStr(extname) & "("
  20. var first = true
  21. echo repr n
  22. for x in n.children:
  23. var unpack = false
  24. if x.kind in nnkCallKinds:
  25. case $x[0]
  26. of "point":
  27. expectLen(x, 3)
  28. unpack = true
  29. of "rect":
  30. expectLen(x, 5)
  31. unpack = true
  32. of "color":
  33. expectLen(x, 4)
  34. unpack = true
  35. else: discard
  36. if unpack:
  37. for i in 1..<x.len:
  38. if first:
  39. first = false
  40. else:
  41. add(s, ", ")
  42. add(s, repr(x[i]))
  43. else:
  44. if first:
  45. first = false
  46. else:
  47. add(s, ", ")
  48. add(s, repr(x))
  49. add(s, ")")
  50. echo s
  51. result = parseStmt(s)
  52. declareUnpackingMacro(bar,internalBar)
  53. type MyInt = distinct int
  54. proc myInt(i: int): MyInt = cast[MyInt](i)
  55. converter toCInt(mi: MyInt): cint = cast[cint](mi)
  56. echo "Let's go!"
  57. bar(rect(1, 2, 3, 4), "test", point(8, 9), color(7,7,8))
  58. bar(1,2,3,4,"text",8,9,7,7,8)
  59. bar(myInt(4),2,3,4,"text",8,9,7,7,8)
  60. let top: cint = 1
  61. let left: cint = 2
  62. let width: cint = 3
  63. let height: cint = 4
  64. bar(rect(top, left, width, height), "test", point(8, 9), color(7,7,8))