summary refs log tree commit diff stats
path: root/lib/core/macros.nim
diff options
context:
space:
mode:
authorAndreas Rumpf <ar@kimeta.de>2014-04-10 01:47:20 +0200
committerAndreas Rumpf <ar@kimeta.de>2014-04-10 01:47:20 +0200
commitdcfc7a8896166563f6fd80fbab81bc50e0b5a217 (patch)
tree4a247ec2d64bafec53e5ab24b0fda89642908a07 /lib/core/macros.nim
parenta86c774932afd8b6782df1925837df9df04ef381 (diff)
parent8b82004359b8d852fa0107d79cc78b21eb35c028 (diff)
downloadNim-dcfc7a8896166563f6fd80fbab81bc50e0b5a217.tar.gz
resolved conflict
Diffstat (limited to 'lib/core/macros.nim')
-rw-r--r--lib/core/macros.nim98
1 files changed, 55 insertions, 43 deletions
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index 52ee9326f..79bf34b7c 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -48,18 +48,19 @@ type
     nnkYieldStmt, nnkTryStmt, nnkFinally, nnkRaiseStmt,
     nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkStaticStmt,
     nnkDiscardStmt, nnkStmtList, 
-    
     nnkImportStmt,
     nnkImportExceptStmt,
     nnkExportStmt,
     nnkExportExceptStmt,
     nnkFromStmt,
     nnkIncludeStmt,
-    
     nnkBindStmt, nnkMixinStmt, nnkUsingStmt,
     nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr,
-    nnkStmtListType, nnkBlockType, nnkTypeOfExpr, nnkObjectTy,
-    nnkTupleTy, nnkTypeClassTy, nnkRecList, nnkRecCase, nnkRecWhen,
+    nnkStmtListType, nnkBlockType,
+    nnkWith, nnkWithout,
+    nnkTypeOfExpr, nnkObjectTy,
+    nnkTupleTy, nnkTypeClassTy, nnkStaticTy,
+    nnkRecList, nnkRecCase, nnkRecWhen,
     nnkRefTy, nnkPtrTy, nnkVarTy,
     nnkConstTy, nnkMutableTy,
     nnkDistinctTy,
@@ -87,7 +88,7 @@ type
     nskUnknown, nskConditional, nskDynLib, nskParam,
     nskGenericParam, nskTemp, nskModule, nskType, nskVar, nskLet, 
     nskConst, nskResult,
-    nskProc, nskMethod, nskIterator,
+    nskProc, nskMethod, nskIterator, nskClosureIterator,
     nskConverter, nskMacro, nskTemplate, nskField,
     nskEnumField, nskForVar, nskLabel,
     nskStub
@@ -147,18 +148,24 @@ proc del*(father: PNimrodNode, idx = 0, n = 1) {.magic: "NDel".}
 proc kind*(n: PNimrodNode): TNimrodNodeKind {.magic: "NKind".}
   ## returns the `kind` of the node `n`.
 
-proc intVal*(n: PNimrodNode): biggestInt {.magic: "NIntVal".}
-proc floatVal*(n: PNimrodNode): biggestFloat {.magic: "NFloatVal".}
+proc intVal*(n: PNimrodNode): BiggestInt {.magic: "NIntVal".}
+proc floatVal*(n: PNimrodNode): BiggestFloat {.magic: "NFloatVal".}
 proc symbol*(n: PNimrodNode): PNimrodSymbol {.magic: "NSymbol".}
 proc ident*(n: PNimrodNode): TNimrodIdent {.magic: "NIdent".}
 proc typ*(n: PNimrodNode): typedesc {.magic: "NGetType".}
 proc strVal*(n: PNimrodNode): string  {.magic: "NStrVal".}
 
-proc `intVal=`*(n: PNimrodNode, val: biggestInt) {.magic: "NSetIntVal".}
-proc `floatVal=`*(n: PNimrodNode, val: biggestFloat) {.magic: "NSetFloatVal".}
+proc `intVal=`*(n: PNimrodNode, val: BiggestInt) {.magic: "NSetIntVal".}
+proc `floatVal=`*(n: PNimrodNode, val: BiggestFloat) {.magic: "NSetFloatVal".}
 proc `symbol=`*(n: PNimrodNode, val: PNimrodSymbol) {.magic: "NSetSymbol".}
 proc `ident=`*(n: PNimrodNode, val: TNimrodIdent) {.magic: "NSetIdent".}
-proc `typ=`*(n: PNimrodNode, typ: typedesc) {.magic: "NSetType".}
+#proc `typ=`*(n: PNimrodNode, typ: typedesc) {.magic: "NSetType".}
+# this is not sound! Unfortunately forbidding 'typ=' is not enough, as you
+# can easily do:
+#   let bracket = semCheck([1, 2])
+#   let fake = semCheck(2.0)
+#   bracket[0] = fake  # constructs a mixed array with ints and floats!
+
 proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal".}
 
 proc newNimNode*(kind: TNimrodNodeKind,
@@ -181,12 +188,12 @@ proc newStrLitNode*(s: string): PNimrodNode {.compileTime.} =
   result = newNimNode(nnkStrLit)
   result.strVal = s
 
-proc newIntLitNode*(i: biggestInt): PNimrodNode {.compileTime.} =
+proc newIntLitNode*(i: BiggestInt): PNimrodNode {.compileTime.} =
   ## creates a int literal node from `i`
   result = newNimNode(nnkIntLit)
   result.intVal = i
 
-proc newFloatLitNode*(f: biggestFloat): PNimrodNode {.compileTime.} =
+proc newFloatLitNode*(f: BiggestFloat): PNimrodNode {.compileTime.} =
   ## creates a float literal node from `f`
   result = newNimNode(nnkFloatLit)
   result.floatVal = f
@@ -287,17 +294,6 @@ proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst".}
   ##       if not `ex`:
   ##         echo `info` & ": Check failed: " & `expString`
   
-template emit*(e: expr[string]): stmt =
-  ## accepts a single string argument and treats it as nimrod code
-  ## that should be inserted verbatim in the program
-  ## Example:
-  ##
-  ## .. code-block:: nimrod
-  ##
-  ##   emit("echo " & '"' & "hello world".toUpper & '"')
-  ##
-  eval: result = e.parseStmt
-
 proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
   ## checks that `n` is of kind `k`. If this is not the case,
   ## compilation aborts with an error message. This is useful for writing
@@ -345,12 +341,12 @@ proc newLit*(c: char): PNimrodNode {.compileTime.} =
   result = newNimNode(nnkCharLit)
   result.intVal = ord(c)
 
-proc newLit*(i: biggestInt): PNimrodNode {.compileTime.} =
+proc newLit*(i: BiggestInt): PNimrodNode {.compileTime.} =
   ## produces a new integer literal node.
   result = newNimNode(nnkIntLit)
   result.intVal = i
 
-proc newLit*(f: biggestFloat): PNimrodNode {.compileTime.} =
+proc newLit*(f: BiggestFloat): PNimrodNode {.compileTime.} =
   ## produces a new float literal node.
   result = newNimNode(nnkFloatLit)
   result.floatVal = f
@@ -381,7 +377,7 @@ proc treeRepr*(n: PNimrodNode): string {.compileTime.} =
     res.add(($n.kind).substr(3))
 
     case n.kind
-    of nnkEmpty: nil # same as nil node in this representation
+    of nnkEmpty: discard # 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)
@@ -406,13 +402,14 @@ proc lispRepr*(n: PNimrodNode): string {.compileTime.} =
   add(result, "(")
 
   case n.kind
-  of nnkEmpty: nil # same as nil node in this representation
+  of nnkEmpty: discard # same as nil node in this representation
   of nnkNilLit: add(result, "nil")
   of nnkCharLit..nnkInt64Lit: add(result, $n.intVal)
   of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal)
   of nnkStrLit..nnkTripleStrLit: add(result, $n.strVal)
   of nnkIdent: add(result, "!\"" & $n.ident & '"')
-  of nnkSym, nnkNone: assert false
+  of nnkSym: add(result, $n.symbol)
+  of nnkNone: assert false
   else:
     add(result, lispRepr(n[0]))
     for j in 1..n.len-1:
@@ -519,7 +516,7 @@ proc last*(node: PNimrodNode): PNimrodNode {.compileTime.} = node[node.high]
 
 
 const
-  RoutineNodes* = {nnkProcDef, nnkMethodDef, nnkDo, nnkLambda}
+  RoutineNodes* = {nnkProcDef, nnkMethodDef, nnkDo, nnkLambda, nnkIteratorDef}
   AtomicNodes* = {nnkNone..nnkNilLit}
   CallNodes* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand, 
     nnkCallStrLit, nnkHiddenCallConv}
@@ -529,7 +526,7 @@ from strutils import cmpIgnoreStyle, format
 proc expectKind*(n: PNimrodNode; k: set[TNimrodNodeKind]) {.compileTime.} =
   assert n.kind in k, "Expected one of $1, got $2".format(k, n.kind)
 
-proc newProc*(name = newEmptyNode(); params: openarray[PNimrodNode] = [newEmptyNode()];  
+proc newProc*(name = newEmptyNode(); params: openArray[PNimrodNode] = [newEmptyNode()];  
     body: PNimrodNode = newStmtList(), procType = nnkProcDef): PNimrodNode {.compileTime.} =
   ## shortcut for creating a new proc
   ##
@@ -567,7 +564,7 @@ proc copyChildrenTo*(src, dest: PNimrodNode) {.compileTime.}=
     dest.add src[i].copyNimTree
 
 template expectRoutine(node: PNimrodNode): stmt =
-  expectKind(node, routineNodes)
+  expectKind(node, RoutineNodes)
   
 proc name*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
   someProc.expectRoutine
@@ -601,10 +598,10 @@ template badnodekind(k; f): stmt{.immediate.} =
 
 proc body*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
   case someProc.kind:
-  of routineNodes:
+  of RoutineNodes:
     return someProc[6]
   of nnkBlockStmt, nnkWhileStmt:
-    return someproc[1]
+    return someProc[1]
   of nnkForStmt:
     return someProc.last
   else: 
@@ -612,7 +609,7 @@ proc body*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
 
 proc `body=`*(someProc: PNimrodNode, val: PNimrodNode) {.compileTime.} =
   case someProc.kind 
-  of routineNodes:
+  of RoutineNodes:
     someProc[6] = val
   of nnkBlockStmt, nnkWhileStmt:
     someProc[1] = val
@@ -628,7 +625,7 @@ proc `$`*(node: PNimrodNode): string {.compileTime.} =
   of nnkIdent:
     result = $node.ident
   of nnkStrLit:
-    result = node.strval
+    result = node.strVal
   else: 
     badNodeKind node.kind, "$"
 
@@ -639,10 +636,13 @@ iterator children*(n: PNimrodNode): PNimrodNode {.inline.}=
   for i in 0 .. high(n):
     yield n[i]
 
-template findChild*(n: PNimrodNode; cond: expr): PNimrodNode {.immediate, dirty.} =
-  ## Find the first child node matching condition (or nil)
-  ## var res = findChild(n, it.kind == nnkPostfix and it.basename.ident == !"foo")
-  
+template findChild*(n: PNimrodNode; cond: expr): PNimrodNode {.
+  immediate, dirty.} =
+  ## Find the first child node matching condition (or nil).
+  ## 
+  ## .. code-block:: nimrod
+  ##   var res = findChild(n, it.kind == nnkPostfix and
+  ##                          it.basename.ident == !"foo")
   block:
     var result: PNimrodNode
     for it in n.children:
@@ -651,7 +651,7 @@ template findChild*(n: PNimrodNode; cond: expr): PNimrodNode {.immediate, dirty.
         break
     result
 
-proc insert*(a: PNimrodNOde; pos: int; b: PNimrodNode) {.compileTime.} =
+proc insert*(a: PNimrodNode; pos: int; b: PNimrodNode) {.compileTime.} =
   ## Insert node B into A at pos
   if high(a) < pos:
     ## add some empty nodes first
@@ -672,14 +672,14 @@ proc basename*(a: PNimrodNode): PNimrodNode {.compiletime.} =
   of nnkIdent: return a
   of nnkPostfix, nnkPrefix: return a[1]
   else: 
-    quit "Do not know how to get basename of ("& treerepr(a) &")\n"& repr(a)
+    quit "Do not know how to get basename of ("& treeRepr(a) &")\n"& repr(a)
     
 proc `basename=`*(a: PNimrodNode; val: string) {.compileTime.}=
   case a.kind
   of nnkIdent: macros.`ident=`(a,  !val)
   of nnkPostfix, nnkPrefix: a[1] = ident(val)
   else:
-    quit "Do not know how to get basename of ("& treerepr(a)& ")\n"& repr(a)
+    quit "Do not know how to get basename of ("& treeRepr(a)& ")\n"& repr(a)
 
 proc postfix*(node: PNimrodNode; op: string): PNimrodNode {.compileTime.} = 
   newNimNode(nnkPostfix).add(ident(op), node)
@@ -730,6 +730,18 @@ proc addIdentIfAbsent*(dest: PNimrodNode, ident: string) {.compiletime.} =
       if ident.eqIdent($node): return
     of nnkExprColonExpr:
       if ident.eqIdent($node[0]): return
-    else: nil
+    else: discard
   dest.add(ident(ident))
 
+when not defined(booting):
+  template emit*(e: static[string]): stmt =
+    ## accepts a single string argument and treats it as nimrod code
+    ## that should be inserted verbatim in the program
+    ## Example:
+    ##
+    ## .. code-block:: nimrod
+    ##   emit("echo " & '"' & "hello world".toUpper & '"')
+    ##
+    macro payload: stmt {.gensym.} =
+      result = parseStmt(e)
+    payload()