summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xcompiler/ast.nim2
-rwxr-xr-xcompiler/evals.nim44
-rwxr-xr-xcompiler/renderer.nim2
-rwxr-xr-xcompiler/sem.nim6
-rwxr-xr-xcompiler/semexprs.nim15
-rwxr-xr-xcompiler/semgnrc.nim4
-rwxr-xr-xcompiler/semstmts.nim3
-rwxr-xr-xcompiler/semtypes.nim8
-rwxr-xr-xdoc/manual.txt15
-rwxr-xr-xdoc/tut2.txt12
-rwxr-xr-xlib/core/macros.nim66
-rwxr-xr-xlib/pure/htmlgen.nim231
-rwxr-xr-xlib/pure/terminal.nim3
-rwxr-xr-xlib/pure/xmltree.nim5
-rwxr-xr-xtodo.txt32
-rwxr-xr-xweb/news.txt2
16 files changed, 270 insertions, 180 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 79adafcf8..a8176501f 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -441,7 +441,7 @@ type
     mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal, 
     mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, mNLineInfo,
     mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mIdentToStr, 
-    mNBindSym,
+    mNBindSym, mNCallSite,
     mEqIdent, mEqNimrodNode, mNHint, mNWarning, mNError, 
     mInstantiationInfo, mGetTypeInfo
 
diff --git a/compiler/evals.nim b/compiler/evals.nim
index 4ec6cb4d7..bb0e5936d 100755
--- a/compiler/evals.nim
+++ b/compiler/evals.nim
@@ -38,6 +38,7 @@ type
     module*: PSym
     tos*: PStackFrame         # top of stack
     lastException*: PNode
+    callsite: PNode           # for 'callsite' magic
     mode*: TEvalMode
     globals*: TIdNodeTable    # state of global vars
   
@@ -74,7 +75,7 @@ proc popStackFrame*(c: PEvalContext) {.inline.} =
   if c.tos != nil: c.tos = c.tos.next
   else: InternalError("popStackFrame")
 
-proc evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode
+proc evalMacroCall*(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode
 proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode
 
 proc raiseCannotEval(c: PEvalContext, info: TLineInfo): PNode = 
@@ -106,8 +107,11 @@ proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg = "") =
 proc isSpecial(n: PNode): bool {.inline.} =
   result = n.kind == nkExceptBranch
 
-proc myreset(n: PNode) {.inline.} =
-  when defined(system.reset): reset(n[])
+proc myreset(n: PNode) =
+  when defined(system.reset): 
+    var oldInfo = n.info
+    reset(n[])
+    n.info = oldInfo
 
 proc evalIf(c: PEvalContext, n: PNode): PNode = 
   var i = 0
@@ -245,6 +249,11 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
   of tyObject: 
     result = newNodeIT(nkPar, info, t)
     getNullValueAux(t.n, result)
+    # initialize inherited fields:
+    var base = t.sons[0]
+    while base != nil:
+      getNullValueAux(skipTypes(base, skipPtrs).n, result)
+      base = base.sons[0]
   of tyArray, tyArrayConstr: 
     result = newNodeIT(nkBracket, info, t)
     for i in countup(0, int(lengthOrd(t)) - 1): 
@@ -925,7 +934,7 @@ proc evalExpandToAst(c: PEvalContext, original: PNode): PNode =
     # we want to replace it with nkIdent node featuring
     # the original unmangled macro name.
     macroCall.sons[0] = newIdentNode(expandedSym.name, expandedSym.info)
-    result = evalMacroCall(c, macroCall, expandedSym)
+    result = evalMacroCall(c, macroCall, original, expandedSym)
   else:
     InternalError(macroCall.info,
       "ExpandToAst: expanded symbol is no macro or template")
@@ -1166,10 +1175,13 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
   of mIdentToStr: 
     result = evalAux(c, n.sons[1], {})
     if isSpecial(result): return 
-    if result.kind != nkIdent: InternalError(n.info, "no ident node")
     var a = result
     result = newNodeIT(nkStrLit, n.info, n.typ)
-    result.strVal = a.ident.s
+    if a.kind == nkSym:
+      result.strVal = a.sym.name.s
+    else:
+      if a.kind != nkIdent: InternalError(n.info, "no ident node")
+      result.strVal = a.ident.s
   of mEqIdent: 
     result = evalAux(c, n.sons[1], {})
     if isSpecial(result): return 
@@ -1226,6 +1238,9 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
     var a = result
     result = newNodeIT(nkStrLit, n.info, n.typ)
     result.strVal = newString(0)
+  of mNCallSite:
+    if c.callsite != nil: result = c.callsite
+    else: stackTrace(c, n, errFieldXNotFound, "callsite")
   else:
     result = evalAux(c, n.sons[1], {})
     if isSpecial(result): return 
@@ -1355,24 +1370,31 @@ proc evalConstExpr*(module: PSym, e: PNode): PNode =
 proc evalStaticExpr*(module: PSym, e: PNode): PNode = 
   result = evalConstExprAux(module, e, emStatic)
 
-proc evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode =
+proc setupMacroParam(x: PNode): PNode =
+  result = x
+  if result.kind == nkHiddenStdConv: result = result.sons[1]
+
+proc evalMacroCall(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode =
   # XXX GlobalError() is ugly here, but I don't know a better solution for now
   inc(evalTemplateCounter)
-  if evalTemplateCounter > 100: 
+  if evalTemplateCounter > 100:
     GlobalError(n.info, errTemplateInstantiationTooNested)
 
-  #inc genSymBaseId
+  c.callsite = nOrig
   var s = newStackFrame()
   s.call = n
-  setlen(s.params, 2)
+  setlen(s.params, n.len)
+  # return value:
   s.params[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0])
-  s.params[1] = n
+  # setup parameters:
+  for i in 1 .. < n.len: s.params[i] = setupMacroParam(n.sons[i])
   pushStackFrame(c, s)
   discard eval(c, sym.getBody)
   result = s.params[0]
   popStackFrame(c)
   if cyclicTree(result): GlobalError(n.info, errCyclicTree)
   dec(evalTemplateCounter)
+  c.callsite = nil
 
 proc myOpen(module: PSym, filename: string): PPassContext = 
   var c = newEvalContext(module, filename, emRepl)
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index c24a22fd5..b6b34287a 100755
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -774,7 +774,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
       put(g, tkRStrLit, '\"' & replace(n[1].strVal, "\"", "\"\"") & '\"')
     else: 
       gsub(g, n.sons[1])
-  of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: gsub(g, n.sons[0])
+  of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: gsub(g, n.sons[1])
   of nkCast: 
     put(g, tkCast, "cast")
     put(g, tkBracketLe, "[")
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 34b6f1f78..d92c1657d 100755
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -81,7 +81,7 @@ proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
 
 proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode
 
-proc semMacroExpr(c: PContext, n: PNode, sym: PSym, 
+proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, 
                   semCheck: bool = true): PNode
 
 proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
@@ -127,14 +127,14 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
     #GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
   dec(evalTemplateCounter)
 
-proc semMacroExpr(c: PContext, n: PNode, sym: PSym, 
+proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, 
                   semCheck: bool = true): PNode = 
   markUsed(n, sym)
   if sym == c.p.owner:
     GlobalError(n.info, errRecursiveDependencyX, sym.name.s)
   if c.evalContext == nil:
     c.evalContext = newEvalContext(c.module, "", emStatic)
-  result = evalMacroCall(c.evalContext, n, sym)
+  result = evalMacroCall(c.evalContext, n, nOrig, sym)
   if semCheck: result = semAfterMacroCall(c, result, sym)
 
 proc forceBool(c: PContext, n: PNode): PNode = 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 06014bf6f..9219cacf6 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -98,7 +98,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
       else: result = newSymNode(s, n.info)
     else:
       result = newSymNode(s, n.info)
-  of skMacro: result = semMacroExpr(c, n, s)
+  of skMacro: result = semMacroExpr(c, n, n, s)
   of skTemplate: result = semTemplateExpr(c, n, s)
   of skVar, skLet, skResult, skParam, skForVar:
     markUsed(n, s)
@@ -705,7 +705,7 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
       return errorNode(c, n)
   let callee = result.sons[0].sym
   case callee.kind
-  of skMacro: result = semMacroExpr(c, nOrig, callee)
+  of skMacro: result = semMacroExpr(c, result, nOrig, callee)
   of skTemplate: result = semTemplateExpr(c, nOrig, callee)
   else:
     fixAbstractType(c, result)
@@ -1398,7 +1398,8 @@ proc semBlockExpr(c: PContext, n: PNode): PNode =
   closeScope(c.tab)
   Dec(c.p.nestedBlockCounter)
 
-proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode = 
+proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
+  # XXX why no overloading here?
   checkMinSonsLen(n, 2)
   var a: PNode
   if isCallExpr(n.sons[0]): a = n.sons[0].sons[0]
@@ -1407,7 +1408,7 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
   if s != nil: 
     case s.kind
     of skMacro: 
-      result = semMacroExpr(c, n, s, semCheck)
+      result = semMacroExpr(c, n, n, s, semCheck)
     of skTemplate: 
       # transform
       # nkMacroStmt(nkCall(a...), stmt, b...)
@@ -1499,16 +1500,16 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     if s != nil: 
       case s.kind
       of skMacro:
-        if false and sfImmediate notin s.flags: # XXX not yet enabled
+        if sfImmediate notin s.flags:
           result = semDirectOp(c, n, flags)
         else:
-          result = semMacroExpr(c, n, s)
+          result = semMacroExpr(c, n, n, s)
       of skTemplate:
         if sfImmediate notin s.flags:
           result = semDirectOp(c, n, flags)
         else:
           result = semTemplateExpr(c, n, s)
-      of skType: 
+      of skType:
         # XXX think about this more (``set`` procs)
         if n.len == 2:
           result = semConv(c, n, s)
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index 849d04fb1..ea3eebc3a 100755
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -51,7 +51,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode =
   of skTemplate:
     result = semTemplateExpr(c, n, s, false)
   of skMacro: 
-    result = semMacroExpr(c, n, s, false)
+    result = semMacroExpr(c, n, n, s, false)
   of skGenericParam: 
     result = newSymNode(s, n.info)
   of skParam: 
@@ -97,7 +97,7 @@ proc semGenericStmt(c: PContext, n: PNode,
       incl(s.flags, sfUsed)
       case s.kind
       of skMacro: 
-        result = semMacroExpr(c, n, s, false)
+        result = semMacroExpr(c, n, n, s, false)
       of skTemplate: 
         result = semTemplateExpr(c, n, s, false)
         # BUGFIX: we must not return here, we need to do first phase of
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index d12ad23cf..3a8424d9e 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -892,13 +892,10 @@ proc semConverterDef(c: PContext, n: PNode): PNode =
 
 proc semMacroDef(c: PContext, n: PNode): PNode = 
   checkSonsLen(n, bodyPos + 1)
-  if n.sons[genericParamsPos].kind != nkEmpty: 
-    LocalError(n.info, errNoGenericParamsAllowedForX, "macro")
   result = semProcAux(c, n, skMacro, macroPragmas)
   var s = result.sons[namePos].sym
   var t = s.typ
   if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "macro")
-  if sonsLen(t) != 2: LocalError(n.info, errXRequiresOneArgument, "macro")
   if n.sons[bodyPos].kind == nkEmpty:
     LocalError(n.info, errImplOfXexpected, s.name.s)
   
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 5b6183005..8ec3c337c 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -237,9 +237,11 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
           return errorSym(c, n)
       if result.typ.kind != tyGenericParam:
         # XXX get rid of this hack!
+        var oldInfo = n.info
         reset(n[])
         n.kind = nkSym
         n.sym = result
+        n.info = oldInfo
     else:
       LocalError(n.info, errIdentifierExpected)
       result = errorSym(c, n)
@@ -549,7 +551,9 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
     incl(result.flags, tfFinal)
   
 proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
-  if kind == skMacro and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}:
+  if kind == skMacro:
+    # within a macro, every param has the type PNimrodNode!
+    # and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}:
     let nn = getSysSym"PNimrodNode"
     var a = copySym(param)
     a.typ = nn.typ
@@ -779,7 +783,7 @@ proc semTypeFromMacro(c: PContext, n: PNode): PType =
   markUsed(n, sym)
   case sym.kind
   of skMacro:
-    result = semTypeNode(c, semMacroExpr(c, n, sym), nil)
+    result = semTypeNode(c, semMacroExpr(c, n, n, sym), nil)
   of skTemplate:
     result = semTypeNode(c, semTemplateExpr(c, n, sym), nil)
   else:
diff --git a/doc/manual.txt b/doc/manual.txt
index e10c934f1..df64649ed 100755
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -3102,7 +3102,7 @@ a template. ``inject`` and ``gensym`` have no effect in ``dirty`` templates.
 Macros

 ------

 

-A `macro`:idx: is a special kind of low level template. They can be used

+A `macro`:idx: is a special kind of low level template. Macros can be used

 to implement `domain specific languages`:idx:. Like templates, macros come in
 the 2 flavors *immediate* and *ordinary*.

 

@@ -3129,12 +3129,12 @@ variable number of arguments:
   # ``macros`` module:

   import macros

 

-  macro debug(n: expr): stmt =

+  macro debug(n: varargs[expr]): stmt =

     # `n` is a Nimrod AST that contains the whole macro invocation

     # this macro returns a list of statements:

     result = newNimNode(nnkStmtList, n)

     # iterate over any argument that is passed to this macro:

-    for i in 1..n.len-1:

+    for i in 0..n.len-1:

       # add a call to the statement list that writes the expression;

       # `toStrLit` converts an AST to its string representation:

       add(result, newCall("write", newIdentNode("stdout"), toStrLit(n[i])))

@@ -3167,6 +3167,11 @@ The macro call expands to:
   writeln(stdout, x)

 
 
+Arguments that are passed to a ``varargs`` parameter are wrapped in an array
+constructor expression. This is why ``debug`` iterates over all of ``n``'s
+children.
+
+
 BindSym
 ~~~~~~~

 
@@ -3179,9 +3184,9 @@ builtin can be used for that:
 .. code-block:: nimrod

   import macros

 

-  macro debug(n: expr): stmt =

+  macro debug(n: varargs[expr]): stmt =

     result = newNimNode(nnkStmtList, n)

-    for i in 1..n.len-1:

+    for i in 0..n.len-1:

       # we can bind symbols in scope via 'bindSym':

       add(result, newCall(bindSym"write", bindSym"stdout", toStrLit(n[i])))

       add(result, newCall(bindSym"write", bindSym"stdout", newStrLitNode(": ")))

diff --git a/doc/tut2.txt b/doc/tut2.txt
index 96507bcb1..85a68c983 100755
--- a/doc/tut2.txt
+++ b/doc/tut2.txt
@@ -67,7 +67,7 @@ Objects have access to their type at runtime. There is an
     person: TPerson
   assert(student of TStudent) # is true
 
-Object fields that should be visible from outside the defining module, have to
+Object fields that should be visible from outside the defining module have to
 be marked by ``*``. In contrast to tuples, different object types are
 never *equivalent*. New object types can only be defined within a type
 section.
@@ -631,19 +631,19 @@ Expression Macros
 -----------------
 
 The following example implements a powerful ``debug`` command that accepts a
-variable number of arguments (this cannot be done with templates):
+variable number of arguments:
 
 .. code-block:: nimrod
   # to work with Nimrod syntax trees, we need an API that is defined in the
   # ``macros`` module:
   import macros
 
-  macro debug(n: expr): stmt =
-    # `n` is a Nimrod AST that contains the whole macro expression
+  macro debug(n: varargs[expr]): stmt =
+    # `n` is a Nimrod AST that contains a list of expressions;
     # this macro returns a list of statements:
     result = newNimNode(nnkStmtList, n)
     # iterate over any argument that is passed to this macro:
-    for i in 1..n.len-1:
+    for i in 0..n.len-1:
       # add a call to the statement list that writes the expression;
       # `toStrLit` converts an AST to its string representation:
       result.add(newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
@@ -702,5 +702,3 @@ regular expressions:
     return tkOperator
   else:
     return tkUnknown
-
-
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index fac935430..610360fb2 100755
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -96,27 +96,25 @@ const
   nnkCallKinds* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,

                    nnkCallStrLit}

 

-# Nodes should be reference counted to make the `copy` operation very fast!

-# However, this is difficult to achieve: modify(n[0][1]) should propagate to

-# its father. How to do this without back references? Hm, BS, it works without 

-# them.

-

-proc `[]`* (n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild".}

+proc `[]`*(n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild".}

   ## get `n`'s `i`'th child.

 

-proc `[]=`* (n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild".}

+proc `[]=`*(n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild".}

   ## set `n`'s `i`'th child to `child`.

 

-proc `!` *(s: string): TNimrodIdent {.magic: "StrToIdent".}

+proc `!`*(s: string): TNimrodIdent {.magic: "StrToIdent".}

   ## constructs an identifier from the string `s`

 

 proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".}

   ## converts a Nimrod identifier to a string

 

-proc `==`* (a, b: TNimrodIdent): bool {.magic: "EqIdent", noSideEffect.}

+proc `$`*(s: PNimrodSymbol): string {.magic: "IdentToStr".}

+  ## converts a Nimrod symbol to a string

+
+proc `==`*(a, b: TNimrodIdent): bool {.magic: "EqIdent", noSideEffect.}

   ## compares two Nimrod identifiers

 

-proc `==`* (a, b: PNimrodNode): bool {.magic: "EqNimrodNode", noSideEffect.}

+proc `==`*(a, b: PNimrodNode): bool {.magic: "EqNimrodNode", noSideEffect.}

   ## compares two Nimrod nodes

 

 proc len*(n: PNimrodNode): int {.magic: "NLen".}

@@ -209,6 +207,9 @@ proc bindSym*(ident: string, rule: TBindSymRule = brClosed): PNimrodNode {.
   ## returned or ``nkSym`` if the symbol is not ambiguous.
   ## If ``rule == brForceOpen`` always an ``nkOpenSymChoice`` tree is
   ## returned even if the symbol is not ambiguous.
+
+proc callsite*(): PNimrodNode {.magic: "NCallSite".}
+  ## returns the AST if the invokation expression that invoked this macro. 
 

 proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =

   ## converts the AST `n` to the concrete Nimrod code and wraps that

@@ -246,15 +247,6 @@ template emit*(s: expr): stmt =
   block:
     const evaluated = s
     eval: result = evaluated.parseStmt
-  when false:

-    template once(x: expr): expr =
-      block:
-        const y = x
-        y
-
-    macro `payload`(x: stmt): stmt = result = once(s).parseStmt
-    `payload`()
-
 

 proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =

   ## checks that `n` is of kind `k`. If this is not the case,

@@ -312,27 +304,23 @@ proc treeRepr*(n: PNimrodNode): string {.compileTime.} =
   ## Convert the AST `n` to a human-readable tree-like string.

   ##

   ## See also `repr` and `lispRepr`.

-

   proc traverse(res: var string, level: int, n: PNimrodNode) =

     for i in 0..level-1: res.add "  "

+    res.add(($n.kind).substr(3))

     

-    if n == nil:

-      res.add "nil"

+    case n.kind

+    of nnkEmpty: nil # same as nil node in this representation

+    of nnkNilLit: res.add(" nil")

+    of nnkCharLit..nnkInt64Lit: res.add(" " & $n.intVal)

+    of nnkFloatLit..nnkFloat64Lit: res.add(" " & $n.floatVal)

+    of nnkStrLit..nnkTripleStrLit: res.add(" " & $n.strVal)

+    of nnkIdent: res.add(" !\"" & $n.ident & '"')

+    of nnkSym: res.add(" \"" & $n.symbol & '"')
+    of nnkNone: assert false

     else:

-      res.add(($n.kind).substr(3))

-      

-      case n.kind

-      of nnkEmpty: nil # same as nil node in this representation

-      of nnkNilLit: res.add(" nil")

-      of nnkCharLit..nnkInt64Lit: res.add(" " & $n.intVal)

-      of nnkFloatLit..nnkFloat64Lit: res.add(" " & $n.floatVal)

-      of nnkStrLit..nnkTripleStrLit: res.add(" " & $n.strVal)

-      of nnkIdent: res.add(" !\"" & $n.ident & '"')

-      of nnkSym, nnkNone: assert false

-      else:

-        for j in 0..n.len-1:

-          res.add "\n"

-          traverse(res, level + 1, n[j])

+      for j in 0..n.len-1:

+        res.add "\n"

+        traverse(res, level + 1, n[j])

 

   result = ""

   traverse(result, 0, n)

@@ -342,8 +330,6 @@ proc lispRepr*(n: PNimrodNode): string {.compileTime.} =
   ##

   ## See also `repr` and `treeRepr`.

   

-  if n == nil: return "nil"

-

   result = ($n.kind).substr(3)

   add(result, "(")

   

@@ -363,7 +349,7 @@ proc lispRepr*(n: PNimrodNode): string {.compileTime.} =
 

   add(result, ")")

 

-macro dumpTree*(s: stmt): stmt = echo s[1].treeRepr

+macro dumpTree*(s: stmt): stmt = echo s.treeRepr

   ## Accepts a block of nimrod code and prints the parsed abstract syntax

   ## tree using the `toTree` function. Printing is done *at compile time*.

   ##

@@ -371,7 +357,7 @@ macro dumpTree*(s: stmt): stmt = echo s[1].treeRepr
   ## tree and to discover what kind of nodes must be created to represent

   ## a certain expression/statement.

 

-macro dumpLisp*(s: stmt): stmt = echo s[1].lispRepr

+macro dumpLisp*(s: stmt): stmt = echo s.lispRepr

   ## Accepts a block of nimrod code and prints the parsed abstract syntax

   ## tree using the `toLisp` function. Printing is done *at compile time*.

   ##

diff --git a/lib/pure/htmlgen.nim b/lib/pure/htmlgen.nim
index 86ee4159b..75af2c892 100755
--- a/lib/pure/htmlgen.nim
+++ b/lib/pure/htmlgen.nim
@@ -15,11 +15,11 @@
 ##
 ## .. code-block:: nimrod
 ##   var nim = "Nimrod"
-##   echo h1(a(href="http://force7.de/nimrod", nim))
+##   echo h1(a(href="http://nimrod-code.org", nim))
 ##  
 ## Writes the string::
 ##   
-##   <h1><a href="http://force7.de/nimrod">Nimrod</a></h1>
+##   <h1><a href="http://nimrod-code.org">Nimrod</a></h1>
 ##
 
 import
@@ -88,319 +88,394 @@ proc xmlCheckedTag*(e: PNimrodNode, tag: string,
   result = NestList(!"&", result)
 
 
-macro a*(e: expr): expr = 
+macro a*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``a`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "a", "href charset type hreflang rel rev " &
     "accesskey tabindex" & commonAttr)
 
-macro acronym*(e: expr): expr = 
+macro acronym*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``acronym`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "acronym", commonAttr)
 
-macro address*(e: expr): expr = 
+macro address*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``address`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "address", commonAttr)
 
-macro area*(e: expr): expr = 
+macro area*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``area`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "area", "shape coords href nohref" &
     " accesskey tabindex" & commonAttr, "alt", true)
 
-macro b*(e: expr): expr = 
+macro b*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``b`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "b", commonAttr)
 
-macro base*(e: expr): expr = 
+macro base*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``base`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "base", "", "href", true)
 
-macro big*(e: expr): expr = 
+macro big*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``big`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "big", commonAttr)
 
-macro blockquote*(e: expr): expr = 
+macro blockquote*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``blockquote`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "blockquote", " cite" & commonAttr)
 
-macro body*(e: expr): expr = 
+macro body*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``body`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "body", commonAttr)
 
-macro br*(e: expr): expr = 
+macro br*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``br`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "br", "", "", true)
 
-macro button*(e: expr): expr = 
+macro button*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``button`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "button", "accesskey tabindex " &
     "disabled name type value" & commonAttr)
 
-macro caption*(e: expr): expr = 
+macro caption*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``caption`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "caption", commonAttr)
 
-macro cite*(e: expr): expr = 
+macro cite*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``cite`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "cite", commonAttr)
 
-macro code*(e: expr): expr = 
+macro code*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``code`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "code", commonAttr)
 
-macro col*(e: expr): expr = 
+macro col*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``col`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "col", "span align valign" & commonAttr, "", true)
 
-macro colgroup*(e: expr): expr = 
+macro colgroup*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``colgroup`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "colgroup", "span align valign" & commonAttr)
 
-macro dd*(e: expr): expr = 
+macro dd*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``dd`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "dd", commonAttr)
 
-macro del*(e: expr): expr = 
+macro del*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``del`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "del", "cite datetime" & commonAttr)
 
-macro dfn*(e: expr): expr = 
+macro dfn*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``dfn`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "dfn", commonAttr)
 
-macro `div`*(e: expr): expr = 
+macro `div`*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``div`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "div", commonAttr)
 
-macro dl*(e: expr): expr = 
+macro dl*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``dl`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "dl", commonAttr)
 
-macro dt*(e: expr): expr = 
+macro dt*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``dt`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "dt", commonAttr)
 
-macro em*(e: expr): expr = 
+macro em*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``em`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "em", commonAttr)
 
-macro fieldset*(e: expr): expr = 
+macro fieldset*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``fieldset`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "fieldset", commonAttr)
 
-macro form*(e: expr): expr = 
+macro form*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``form`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "form", "method encype accept accept-charset" & 
     commonAttr, "action")
 
-macro h1*(e: expr): expr = 
+macro h1*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``h1`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "h1", commonAttr)
 
-macro h2*(e: expr): expr = 
+macro h2*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``h2`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "h2", commonAttr)
 
-macro h3*(e: expr): expr = 
+macro h3*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``h3`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "h3", commonAttr)
 
-macro h4*(e: expr): expr = 
+macro h4*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``h4`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "h4", commonAttr)
 
-macro h5*(e: expr): expr = 
+macro h5*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``h5`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "h5", commonAttr)
 
-macro h6*(e: expr): expr = 
+macro h6*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``h6`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "h6", commonAttr)
 
-macro head*(e: expr): expr = 
+macro head*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``head`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "head", "profile")
 
-macro html*(e: expr): expr = 
+macro html*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``html`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "html", "xmlns", "")
 
-macro hr*(e: expr): expr = 
+macro hr*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``hr`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "hr", commonAttr, "", true)
 
-macro i*(e: expr): expr = 
+macro i*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``i`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "i", commonAttr)
 
-macro img*(e: expr): expr = 
+macro img*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``img`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "img", "longdesc height width", "src alt", true)
 
-macro input*(e: expr): expr = 
+macro input*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``input`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "input", "name type value checked maxlength src" &
     " alt accept disabled readonly accesskey tabindex" & commonAttr, "", true)
 
-macro ins*(e: expr): expr = 
+macro ins*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``ins`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "ins", "cite datetime" & commonAttr)
 
-macro kbd*(e: expr): expr = 
+macro kbd*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``kbd`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "kbd", commonAttr)
 
-macro label*(e: expr): expr = 
+macro label*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``label`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "label", "for accesskey" & commonAttr)
 
-macro legend*(e: expr): expr = 
+macro legend*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``legend`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "legend", "accesskey" & commonAttr)
 
-macro li*(e: expr): expr = 
+macro li*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``li`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "li", commonAttr)
 
-macro link*(e: expr): expr = 
+macro link*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``link`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "link", "href charset hreflang type rel rev media" & 
     commonAttr, "", true)
 
-macro map*(e: expr): expr = 
+macro map*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``map`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "map", "class title" & eventAttr, "id", false)
 
-macro meta*(e: expr): expr = 
+macro meta*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``meta`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "meta", "name http-equiv scheme", "content", true)
 
-macro noscript*(e: expr): expr = 
+macro noscript*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``noscript`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "noscript", commonAttr)
 
-macro `object`*(e: expr): expr = 
+macro `object`*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``object`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "object", "classid data codebase declare type " &
     "codetype archive standby width height name tabindex" & commonAttr)
 
-macro ol*(e: expr): expr = 
+macro ol*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``ol`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "ol", commonAttr)
 
-macro optgroup*(e: expr): expr = 
+macro optgroup*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``optgroup`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "optgroup", "disabled" & commonAttr, "label", false)
 
-macro option*(e: expr): expr = 
+macro option*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``option`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "option", "selected value" & commonAttr)
 
-macro p*(e: expr): expr = 
+macro p*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``p`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "p", commonAttr)
 
-macro param*(e: expr): expr = 
+macro param*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``param`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "param", "value id type valuetype", "name", true)
 
-macro pre*(e: expr): expr = 
+macro pre*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``pre`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "pre", commonAttr)
 
-macro q*(e: expr): expr = 
+macro q*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``q`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "q", "cite" & commonAttr)
 
-macro samp*(e: expr): expr = 
+macro samp*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``samp`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "samp", commonAttr)
 
-macro script*(e: expr): expr = 
+macro script*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``script`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "script", "src charset defer", "type", false)
 
-macro select*(e: expr): expr = 
+macro select*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``select`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "select", "name size multiple disabled tabindex" & 
     commonAttr)
 
-macro small*(e: expr): expr = 
+macro small*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``small`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "small", commonAttr)
 
-macro span*(e: expr): expr = 
+macro span*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``span`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "span", commonAttr)
 
-macro strong*(e: expr): expr = 
+macro strong*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``strong`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "strong", commonAttr)
 
-macro style*(e: expr): expr = 
+macro style*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``style`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "style", "media title", "type")
 
-macro sub*(e: expr): expr = 
+macro sub*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``sub`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "sub", commonAttr)
 
-macro sup*(e: expr): expr = 
+macro sup*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``sup`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "sup", commonAttr)
 
-macro table*(e: expr): expr = 
+macro table*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``table`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "table", "summary border cellpadding cellspacing" &
     " frame rules width" & commonAttr)
 
-macro tbody*(e: expr): expr = 
+macro tbody*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``tbody`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "tbody", "align valign" & commonAttr)
 
-macro td*(e: expr): expr = 
+macro td*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``td`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "td", "colspan rowspan abbr axis headers scope" &
     " align valign" & commonAttr)
 
-macro textarea*(e: expr): expr = 
+macro textarea*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``textarea`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "textarea", " name disabled readonly accesskey" &
     " tabindex" & commonAttr, "rows cols", false)
 
-macro tfoot*(e: expr): expr = 
+macro tfoot*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``tfoot`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "tfoot", "align valign" & commonAttr)
 
-macro th*(e: expr): expr = 
+macro th*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``th`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "th", "colspan rowspan abbr axis headers scope" &
     " align valign" & commonAttr)
 
-macro thead*(e: expr): expr = 
+macro thead*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``thead`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "thead", "align valign" & commonAttr)
 
-macro title*(e: expr): expr = 
+macro title*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``title`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "title")
 
-macro tr*(e: expr): expr = 
+macro tr*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``tr`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "tr", "align valign" & commonAttr)
 
-macro tt*(e: expr): expr = 
+macro tt*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``tt`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "tt", commonAttr)
 
-macro ul*(e: expr): expr = 
+macro ul*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``ul`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "ul", commonAttr)
 
-macro `var`*(e: expr): expr = 
+macro `var`*(e: expr): expr {.immediate.} = 
   ## generates the HTML ``var`` element.
+  let e = callsite()
   result = xmlCheckedTag(e, "var", commonAttr)
 
 when isMainModule:
   var nim = "Nimrod"
-  echo h1(a(href="http://force7.de/nimrod", nim))
+  echo h1(a(href="http://nimrod-code.org", nim))
 
diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim
index d24d81112..3be6088ed 100755
--- a/lib/pure/terminal.nim
+++ b/lib/pure/terminal.nim
@@ -325,8 +325,9 @@ proc styledEchoProcessArg(style: set[TStyle])      = setStyle style
 proc styledEchoProcessArg(color: TForegroundColor) = setForeGroundColor color

 proc styledEchoProcessArg(color: TBackgroundColor) = setBackGroundColor color

 

-macro styledEcho*(m: stmt): stmt =
+macro styledEcho*(m: varargs[expr]): stmt =
   ## to be documented.
+  let m = callsite()
   result = newNimNode(nnkStmtList)

 

   for i in countup(1, m.len - 1):

diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim
index 0ea777e93..b657ee05c 100755
--- a/lib/pure/xmltree.nim
+++ b/lib/pure/xmltree.nim
@@ -262,12 +262,13 @@ macro `<>`*(x: expr): expr =
   ## Constructor macro for XML. Example usage:
   ##
   ## .. code-block:: nimrod
-  ##   <>a(href="http://force7.de/nimrod", "Nimrod rules.")
+  ##   <>a(href="http://nimrod-code.org", "Nimrod rules.")
   ##
   ## Produces an XML tree for::
   ##
-  ##  <a href="http://force7.de/nimrod">Nimrod rules.</a>
+  ##  <a href="http://nimrod-code.org">Nimrod rules.</a>
   ##
+  let x = callsite()
   result = xmlConstructor(x)
 
 proc child*(n: PXmlNode, name: string): PXmlNode =
diff --git a/todo.txt b/todo.txt
index a255315a7..8c5d172da 100755
--- a/todo.txt
+++ b/todo.txt
@@ -1,7 +1,9 @@
 version 0.9.0
 =============
 
-- introduce 'callsite' magic and make macros and templates the same
+- make 'm: stmt' use overloading resolution
+
+- implement the high level optimizer
 - make 'bind' default for templates and introduce 'mixin'
 
 - implement "closure tuple consists of a single 'ref'" optimization
@@ -32,6 +34,17 @@ Bugs
 version 0.9.XX
 ==============
 
+- make:
+  p(a, b): 
+    echo a
+    echo b
+  
+  the same as:
+  
+  p(a, b, proc() =
+    echo a
+    echo b)
+
 - JS gen:
   - fix exception handling
 
@@ -52,7 +65,6 @@ version 0.9.XX
 - document nimdoc properly finally
 - make 'clamp' a magic for the range stuff
 - implement a warning message for shadowed 'result' variable
-- implement the high level optimizer
 - we need to support iteration of 2 different data structures in parallel
 - implement proper coroutines
 - proc specialization in the code gen for write barrier specialization
@@ -71,17 +83,6 @@ version 0.9.XX
   * For parameter ``tyExpr`` any argument matches.
   * Argument ``tyProxy`` matches any parameter.
   
-- nice idea:
-
-  p(a, b): 
-    echo a
-    echo b
-  
-  is the same as:
-  
-  p(a, b, proc() =
-    echo a
-    echo b)
 
 Library
 -------
@@ -114,10 +115,7 @@ Low priority
   escape analysis for string/seq seems to be easy to do too;
   even further write barrier specialization
 - GC: marker procs Boehm GC
-- implement marker procs for assignment and message passing
-- warning for implicit openArray -> varargs conversion
-- implement explicit varargs; **but** ``len(varargs)`` problem remains! 
-  --> solve by implicit conversion from varargs to openarray
+- implement marker procs for message passing
 - optimize method dispatchers
 - activate more thread tests
 - implement ``--script:sh|bat`` command line option; think about script 
diff --git a/web/news.txt b/web/news.txt
index e456f70f3..80f74cd1e 100755
--- a/web/news.txt
+++ b/web/news.txt
@@ -111,6 +111,8 @@ Changes affecting backwards compatibility
 - Objects that have no ancestor are now implicitely ``final``. Use 
   the ``inheritable`` pragma to introduce new object roots apart 
   from ``TObject``.
+- Macros now receive parameters like templates do; use the ``callsite`` builtin
+  to gain access to the invokating AST.
 
 
 Compiler Additions