Skip to content

Instantly share code, notes, and snippets.

@geekrelief
Created January 22, 2022 19:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save geekrelief/af14d3b38a5b6c3efca0acd7f4f21cca to your computer and use it in GitHub Desktop.
Save geekrelief/af14d3b38a5b6c3efca0acd7f4f21cca to your computer and use it in GitHub Desktop.
Nim: Check if a type is nilable in a macro.
import std/[ macros, strformat ]
proc parseParts(x: NimNode): seq[NimNode]
proc parseDotExpr(x: NimNode): seq[NimNode] =
result.add parseParts(x[0])
result.add x
proc parseBracketExpr(x: NimNode): seq[NimNode] =
result.add parseParts(x[0])
result.add x
proc parseParts(x: NimNode): seq[NimNode] =
result.add case x.kind:
of nnkBracketExpr: parseBracketExpr(x)
of nnkDotExpr: parseDotExpr(x)
of nnkHiddenDeref: parseParts(x[0])
else: @[x]
proc isNilable(x:NimNode): bool =
if x.kind == nnkHiddenDeref: return true
var t = getType(x)
case t.kind:
of nnkBracketExpr:
case t[0].strVal:
of "ref", "ptr", "proc": true
else: false
of nnkHiddenDeref: true
of nnkSym:
case t.strVal:
of "pointer", "cstring": true
else: false
else: false
macro `~`(x: typed): untyped =
echo x.repr
echo x.treerepr
# echo "============="
var parts = parseParts(x)
var nilables:seq[NimNode]
for p in parts:
# echo &"==== {p.repr} {isNilable(p)}"
# echo p.treerepr
# echo &"==== t "
#var t = getType(p)
#echo t.treerepr
if isNilable(p):
nilables.add p
#echo parts.repr
echo nilables.repr
type
A = object
b: ptr B
s: seq[ptr C]
p: proc()
d: D
cs: cstring
pp: pointer
B = object
foo: float
C = object
bar: bool
D = ref object
val: int
#~a.b.c.d
#~a[1].b.c.d
#~a.b[1]
var a = cast[ptr A](alloc(sizeof(A)))
var b = cast[ptr B](alloc(sizeof(B)))
b.foo = 100f
var c = cast[ptr C](alloc(sizeof(C)))
c.bar = true
var d:D
a.b = b
a.s = @[c]
#~a
#~a.b
#~a.s
var p:proc()
#~p
#~a.p
#~d
#~a.d
#~a.s[0]
#~a.s[0].bar
#~a.cs
~a.pp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment