nim-lang / Nim

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula. Its design focuses on efficiency, expressiveness, and elegance (in that order of priority).
https://nim-lang.org
Other
16.58k stars 1.47k forks source link

Macro causes compile error from gcc #9967

Open rehartmann opened 5 years ago

rehartmann commented 5 years ago

The following code:

import macros

type
   Expression* = ref object of RootObj

   StringExpression = ref object of Expression
      value: string

   BooleanExpression = ref object of Expression
      value: bool

   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 toExpr(s: string): Expression =
  ## Converts a string value to an expression.
  return StringExpression(value: s)

proc toExpr(b: bool): Expression =
  return BooleanExpression(value: b)

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 assign*(assigns: varargs[Assignment]) =
  return

assign(myUpdate(t3, toExpr(true), s := toExpr("Bar")))

causes the following error when compiling:

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:687:112: error: ‘T3_Len_0’ undeclared (first use in this function)
  T1_[0] = updateAssignment_W9aVjf64l6HNbKHPkoTWOgA(((NimStringDesc*) &TM_rFCIiNhfswqwZJUDLErU2g_13), T2_, T3_, T3_Len_0);
                                                                                                                ^~~~~~~~
/home/rene/projects/nidurodb/test/nimcache/assigntest.c:687:112: note: each undeclared identifier is reported only once for each function it appears in
rehartmann commented 5 years ago

The problem disappears if the definition of myUpdate is changed to:

macro myUpdate*(dest: untyped, cond: Expression,
              attrUpdates: varargs[AttrUpdate]): Assignment =
  var updateAssignmentArgs: seq[NimNode] = @[toStrLit(dest), cond]
  for attrUpdate in attrUpdates:
    updateAssignmentArgs.add(attrUpdate)
  result = newCall("updateAssignment", updateAssignmentArgs)
krux02 commented 5 years ago

Please elaborate a bit on what you are trying to do and what might cause the crash. Also please try to boil the code down to what is causing the crash.

rehartmann commented 5 years ago

The reason is probably that myUpdate() passes its arguments directly to newCall(), instead of passing them as NimNodes. But this should result in an compile error rather than invalid C code being generated.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. If you think it is still a valid issue, write a comment below; otherwise it will be closed. Thank you for your contributions.