summary refs log tree commit diff stats
path: root/lib/macros.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/macros.nim')
-rw-r--r--lib/macros.nim90
1 files changed, 76 insertions, 14 deletions
diff --git a/lib/macros.nim b/lib/macros.nim
index f2783b637..2c71f31c8 100644
--- a/lib/macros.nim
+++ b/lib/macros.nim
@@ -58,12 +58,12 @@ type
     nnkTypeDef, nnkYieldStmt, nnkTryStmt, nnkFinally, 
     nnkRaiseStmt, nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, 
     nnkBlockStmt, nnkDiscardStmt, nnkStmtList, nnkImportStmt, 
-    nnkFromStmt, nnkImportAs, nnkIncludeStmt, nnkAccessStmt, 
-    nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr, nnkStmtListType, 
-    nnkBlockType, nnkVm, nnkTypeOfExpr, nnkObjectTy, 
-    nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen, 
-    nnkRefTy, nnkPtrTy, nnkVarTy, nnkProcTy, 
-    nnkEnumTy, nnkEnumFieldDef, nnkReturnToken
+    nnkFromStmt, nnkImportAs, nnkIncludeStmt, nnkCommentStmt, 
+    nnkStmtListExpr, nnkBlockExpr, nnkStmtListType, nnkBlockType, 
+    nnkVm, nnkTypeOfExpr, nnkObjectTy, nnkTupleTy, 
+    nnkRecList, nnkRecCase, nnkRecWhen, nnkRefTy, 
+    nnkPtrTy, nnkVarTy, nnkProcTy, nnkEnumTy, 
+    nnkEnumFieldDef, nnkReturnToken
   TNimNodeKinds* = set[TNimrodNodeKind]
   TNimrodTypeKind* = enum
     ntyNone, ntyBool, ntyChar, ntyEmpty, 
@@ -86,12 +86,24 @@ type
 #[[[end]]]

 

 type

+  TNimrodIdent = object of TObject

+    ## represents a Nimrod identifier in the AST

+

   TNimrodNode {.final.} = object   # hidden

   TNimrodSymbol {.final.} = object # hidden

   TNimrodType {.final.} = object   # hidden

+  

   PNimrodType* {.compilerproc.} = ref TNimrodType

+    ## represents a Nimrod type in the compiler; currently this is not very

+    ## useful as there is no API to deal with Nimrod types.

+  

   PNimrodSymbol* {.compilerproc.} = ref TNimrodSymbol

+    ## represents a Nimrod *symbol* in the compiler; a *symbol* is a looked-up

+    ## *ident*.

+  

   PNimrodNode* {.compilerproc.} = ref TNimrodNode

+    ## represents a Nimrod AST node. Macros operate on this type.

+    

   expr* = PNimrodNode

   stmt* = PNimrodNode

 

@@ -100,23 +112,35 @@ type
 # its father. How to do this without back references?

 

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

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

+

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

-  ## provide access to `n`'s children

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

 

-type

-  TNimrodIdent = object of TObject

+proc `!` *(s: string): TNimrodIdent {.magic: "StrToIdent".}
+  ## constructs an identifier from the string `s`

 

-converter StrToIdent*(s: string): TNimrodIdent {.magic: "StrToIdent".}

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

+  ## converts a Nimrod identifier to a string

+

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

+  ## compares two Nimrod identifiers

 

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

+  ## returns the number of children of `n`.

 

-## returns the number of children that a node has

 proc add*(father, child: PNimrodNode) {.magic: "NAdd".}

-proc add*(father: PNimrodNode, child: openArray[PNimrodNode]) {.magic: "NAddMultiple".}

+  ## adds the `child` to the `father` node

+

+proc add*(father: PNimrodNode, children: openArray[PNimrodNode]) {.

+  magic: "NAddMultiple".}

+  ## adds each `children` to the `father` node

+

 proc del*(father: PNimrodNode, idx = 0, n = 1) {.magic: "NDel".}

+  ## deletes `n` children of `father` starting at index `idx`. 

+

 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".}

@@ -133,43 +157,81 @@ proc `typ=`*(n: PNimrodNode, typ: PNimrodType) {.magic: "NSetType".}
 proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal".}

 

 proc newNimNode*(kind: TNimrodNodeKind,

-                 n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode".}

+                 n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode".}
+
 proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode".}

 proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree".}

 

 proc error*(msg: string) {.magic: "NError".}

+  ## writes an error message at compile time

+

 proc warning*(msg: string) {.magic: "NWarning".}

+  ## writes a warning message at compile time

+

 proc hint*(msg: string) {.magic: "NHint".}

+  ## writes a hint message at compile time

 

 proc newStrLitNode*(s: string): PNimrodNode {.compileTime.} =

+  ## creates a string literal node from `s`

   result = newNimNode(nnkStrLit)

   result.strVal = s

 

 proc newIntLitNode*(i: biggestInt): PNimrodNode {.compileTime.} =

+  ## creates a int literal node from `i`

   result = newNimNode(nnkIntLit)

   result.intVal = i

 

-proc newIntLitNode*(f: biggestFloat): PNimrodNode {.compileTime.} =

+proc newFloatLitNode*(f: biggestFloat): PNimrodNode {.compileTime.} =

+  ## creates a float literal node from `f`

   result = newNimNode(nnkFloatLit)

   result.floatVal = f

 

 proc newIdentNode*(i: TNimrodIdent): PNimrodNode {.compileTime.} =

+  ## creates an identifier node from `i`

   result = newNimNode(nnkIdent)

   result.ident = i

+
+proc newIdentNode*(i: string): PNimrodNode {.compileTime.} =

+  ## creates an identifier node from `i`

+  result = newNimNode(nnkIdent)

+  result.ident = !i
 

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

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

+  ## in a string literal node

   return newStrLitNode(repr(n))

 

 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

+  ## macros that check the AST that is passed to them.

   if n.kind != k: error("macro expects a node of kind: " & repr(k))

 

 proc expectMinLen*(n: PNimrodNode, min: int) {.compileTime.} =

+  ## checks that `n` has at least `min` children. If this is not the case,

+  ## compilation aborts with an error message. This is useful for writing

+  ## macros that check its number of arguments. 

   if n.len < min: error("macro expects a node with " & $min & " children")

 

+proc expectLen*(n: PNimrodNode, len: int) {.compileTime.} =

+  ## checks that `n` has exactly `len` children. If this is not the case,

+  ## compilation aborts with an error message. This is useful for writing

+  ## macros that check its number of arguments. 

+  if n.len != len: error("macro expects a node with " & $len & " children")

+

 proc newCall*(theProc: TNimrodIdent,

               args: openArray[PNimrodNode]): PNimrodNode {.compileTime.} =

   ## produces a new call node. `theProc` is the proc that is called with

   ## the arguments ``args[0..]``.

   result = newNimNode(nnkCall)

   result.add(newIdentNode(theProc))

+  result.add(args)
+  

+proc newCall*(theProc: string,

+              args: openArray[PNimrodNode]): PNimrodNode {.compileTime.} =

+  ## produces a new call node. `theProc` is the proc that is called with

+  ## the arguments ``args[0..]``.

+  result = newNimNode(nnkCall)

+  result.add(newIdentNode(theProc))

   result.add(args)

+