Seems I managed to bring the macro/generics processing to its limits.
Compiling the following program fails with a compile error from gcc:
import macros
type
Expression* = ref object of RootObj
VarExpression = ref object of Expression
name: string
StringExpression = ref object of Expression
value: string
IntExpression = ref object of Expression
value: int
OpExpression = ref object of Expression
name: string
args: seq[Expression]
AssignmentKind = enum
akCopy, akInsert, akUpdate, akDelete
AttrUpdate* = object
name: string
exp: Expression
Assignment* = ref object
case kind: AssignmentKind
of akCopy:
copyDest: string
of akInsert:
insertDest: string
insertFlags: int
of akUpdate:
updateDest: string
updateCond: Expression
attrUpdates: seq[AttrUpdate]
of akDelete:
deleteDest: string
deleteCond: Expression
proc `$=`(exp1: Expression, val: int): Expression =
## Creates a = expression
result = OpExpression(name: "=", args: @[exp1, IntExpression(value: val)])
macro V(varname: untyped): Expression =
## Converts an identifier to a variable name.
result = newCall("toVar", @[toStrLit(varname)])
proc toVar(varname: string): VarExpression =
result = VarExpression(name: varname)
proc toExpr(s: string): Expression =
## Converts a string value to an expression.
return StringExpression(value: s)
proc updateAssignment(tbName: string, cond: Expression,
attrUpdates: varargs[AttrUpdate]): Assignment =
result = new Assignment
result.kind = akUpdate
result.updateDest = tbName
result.updateCond = cond
result.attrUpdates = newSeq[AttrUpdate](attrUpdates.len)
for i in 0..<result.attrUpdates.len:
result.attrUpdates[i] = attrUpdates[i]
macro myUpdate(dest: untyped, cond: Expression,
assigns: varargs[AttrUpdate]): Assignment =
result = newCall("updateAssignment", toStrLit(dest), cond, assigns)
proc attributeAssignment(dest: string, src: Expression): AttrUpdate =
result.name = dest
result.exp = src
macro `:=`(dest: untyped, src: Expression): AttrUpdate =
result = newCall("attributeAssignment", toStrLit(dest), src)
proc assign3*(assigns: varargs[Assignment]): int =
result = 0
discard assign3(myUpdate(t3, V(n) $= 1, s := toExpr("Bar")))
When compiling with nim 0.17.2 I get the following error: (Didn't try with newer versions)
Error:
execution of an external compiler program 'gcc -c -w -I/usr/lib/nim -o /home/rene/projects/nidurodb/test/nimcache/assigntest.o /home/rene/projects/nidurodb/test/nimcache/assigntest.c' failed with exit code: 1 :: /home/rene/projects/nidurodb/test/nimcache/assigntest.c: In function ‘NimMainModule’: /home/rene/projects/nidurodb/test/nimcache/assigntest.c:782:112: error: ‘T5_Len_0’ undeclared (first use in this function) T1_[0] = updateAssignment_W9aVjf64l6HNbKHPkoTWOgA(((NimStringDesc*) &TM_rFCIiNhfswqwZJUDLErU2g_15 ), T4_, T5_, T5_Len_0); ^~~~~~~~