Skip to content

Instantly share code, notes, and snippets.

@onionhammer
Last active August 29, 2015 14:12
Show Gist options
  • Save onionhammer/2a07be3a4e2a937fbd3a to your computer and use it in GitHub Desktop.
Save onionhammer/2a07be3a4e2a937fbd3a to your computer and use it in GitHub Desktop.
new non-ref
import macros
proc makeRef(obj: PNimrodNode): PNimrodNode {.compiletime.} =
var typeName: string
var assignments = newSeq[PNimrodNode]()
for i in obj.children:
if i.kind == nnkIdent:
typeName = $i
elif i.kind == nnkExprColonExpr:
var left, right: PNimrodNode
for value in i.children:
if left == nil: left = value
else: right = value
var assignment = newNimNode(nnkAsgn).add(
newNimNode(nnkDotExpr).add(ident"i", left),
right
)
assignments.add(assignment)
# Compose resulting AST
var resultExpr = newStmtList()
resultExpr.add(
newNimNode(nnkVarSection).add(
newNimNode(nnkIdentDefs).add(
ident"i",
newNimNode(nnkRefTy).add(typeName.ident),
newNimNode(nnkEmpty)
)
)
)
resultExpr.add(parseExpr("new(i)"))
resultExpr.add(assignments)
resultExpr.add(ident"i")
return newStmtList().add(
newNimNode(nnkBlockStmt).add(newNimNode(nnkEmpty), resultExpr))
macro new*(obj: expr{nkObjConstr|nkCall}): expr =
return makeRef(obj)
when isMainModule:
type MyType = object
value: int
other: ref MyType
proc square(self: MyType|ref MyType): auto =
if self.other != nil:
self.other.value * self.other.value
else:
self.value * self.value
var item1 = MyType(value: 5) # Creates: MyType
var item2 = new MyType(value: 5) # Creates: ref MyType
var item3 = new MyType(other: new MyType(value: 7))
assert(item2 != nil)
assert(item1.value == 5)
assert(item2.value == 5)
echo item1.square
echo item2.square
echo item3.square
assert(declared(i) == false, "`i` leaked to main scope")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment