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.nim176
1 files changed, 176 insertions, 0 deletions
diff --git a/lib/macros.nim b/lib/macros.nim
new file mode 100644
index 000000000..af5e0d17d
--- /dev/null
+++ b/lib/macros.nim
@@ -0,0 +1,176 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2008 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+
+## This module contains the interface to the compiler's abstract syntax tree.
+## Abstract syntax trees should be modified in macros.
+
+#[[[cog
+#def toEnum(name, elems, prefix):
+#  body = ""
+#  counter = 0
+#  for e in elems:
+#    if counter % 4 == 0: p = "\n    "
+#    else: p = ""
+#    body += p + prefix + e[2:] + ', '
+#    counter += 1
+#
+#  return "  TNimrod%s* = enum%s\n  TNim%ss* = set[TNimrod%s]\n" \
+#            % (name, body.rstrip(", "), name, name)
+#
+#enums = eval(file("data/ast.yml").read())
+#cog.out("type\n")
+#i = 0
+#for key, val in enums.iteritems():
+#  if key.endswith("Flag"): continue
+#  cog.out(toEnum(key, val, ["nnk", "nty", "nsk"][i]))
+#  i += 1
+#]]]
+type
+  TNimrodNodeKind* = enum
+    nnkNone, nnkEmpty, nnkIdent, nnkSym, 
+    nnkType, nnkCharLit, nnkIntLit, nnkInt8Lit, 
+    nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkFloatLit, 
+    nnkFloat32Lit, nnkFloat64Lit, nnkStrLit, nnkRStrLit, 
+    nnkTripleStrLit, nnkMetaNode, nnkNilLit, nnkDotCall, 
+    nnkCommand, nnkCall, nnkGenericCall, nnkExplicitTypeListCall, 
+    nnkExprEqExpr, nnkExprColonExpr, nnkIdentDefs, nnkInfix, 
+    nnkPrefix, nnkPostfix, nnkPar, nnkCurly, 
+    nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange, 
+    nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr, 
+    nnkElifExpr, nnkElseExpr, nnkLambda, nnkAccQuoted, 
+    nnkHeaderQuoted, nnkTableConstr, nnkQualified, nnkHiddenStdConv, 
+    nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast, 
+    nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv, 
+    nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange, 
+    nnkStringToCString, nnkCStringToString, nnkPassAsOpenArray, nnkAsgn, 
+    nnkDefaultTypeParam, nnkGenericParams, nnkFormalParams, nnkOfInherit, 
+    nnkModule, nnkProcDef, nnkConverterDef, nnkMacroDef, 
+    nnkTemplateDef, nnkIteratorDef, nnkOfBranch, nnkElifBranch, 
+    nnkExceptBranch, nnkElse, nnkMacroStmt, nnkAsmStmt, 
+    nnkPragma, nnkIfStmt, nnkWhenStmt, nnkForStmt, 
+    nnkWhileStmt, nnkCaseStmt, nnkVarSection, nnkConstSection, 
+    nnkConstDef, nnkTypeSection, nnkTypeDef, nnkYieldStmt, 
+    nnkTryStmt, nnkFinally, nnkRaiseStmt, nnkReturnStmt, 
+    nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkDiscardStmt, 
+    nnkStmtList, nnkImportStmt, nnkFromStmt, nnkImportAs, 
+    nnkIncludeStmt, nnkAccessStmt, nnkCommentStmt, nnkStmtListExpr, 
+    nnkBlockExpr, nnkVm, nnkTypeOfExpr, nnkObjectTy, 
+    nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen, 
+    nnkRefTy, nnkPtrTy, nnkVarTy, nnkProcTy, 
+    nnkEnumTy, nnkEnumFieldDef, nnkReturnToken
+  TNimNodeKinds* = set[TNimrodNodeKind]
+  TNimrodTypeKind* = enum
+    ntyNone, ntyBool, ntyChar, ntyEmptySet, 
+    ntyArrayConstr, ntyNil, ntyGeneric, ntyGenericInst, 
+    ntyGenericParam, ntyEnum, ntyAnyEnum, ntyArray, 
+    ntyObject, ntyTuple, ntySet, ntyRange, 
+    ntyPtr, ntyRef, ntyVar, ntySequence, 
+    ntyProc, ntyPointer, ntyOpenArray, ntyString, 
+    ntyCString, ntyForward, ntyInt, ntyInt8, 
+    ntyInt16, ntyInt32, ntyInt64, ntyFloat, 
+    ntyFloat32, ntyFloat64, ntyFloat128
+  TNimTypeKinds* = set[TNimrodTypeKind]
+  TNimrodSymKind* = enum
+    nskUnknownSym, nskConditional, nskDynLib, nskParam, 
+    nskTypeParam, nskTemp, nskType, nskConst, 
+    nskVar, nskProc, nskIterator, nskConverter, 
+    nskMacro, nskTemplate, nskField, nskEnumField, 
+    nskForVar, nskModule, nskLabel
+  TNimSymKinds* = set[TNimrodSymKind]
+#[[[end]]]
+
+type
+  TNimrodNode {.final.} = object   # hidden
+  TNimrodSymbol {.final.} = object # hidden
+  TNimrodType {.final.} = object   # hidden
+  PNimrodType* {.compilerproc.} = ref TNimrodType
+  PNimrodSymbol* {.compilerproc.} = ref TNimrodSymbol
+  PNimrodNode* {.compilerproc.} = ref TNimrodNode
+  expr* = PNimrodNode
+  stmt* = PNimrodNode
+
+# 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?
+
+proc `[]`* (n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild".}
+proc `[]=`* (n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild".}
+  ## provide access to `n`'s children
+
+type
+  TNimrodIdent = object of TObject
+
+converter StrToIdent*(s: string): TNimrodIdent {.magic: "StrToIdent".}
+proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".}
+proc `==`* (a, b: TNimrodIdent): bool {.magic: "EqIdent".}
+
+proc len*(n: PNimrodNode): int {.magic: "NLen".}
+
+## 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".}
+proc del*(father: PNimrodNode, idx = 0, n = 1) {.magic: "NDel".}
+proc kind*(n: PNimrodNode): TNimrodNodeKind {.magic: "NKind".}
+
+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): PNimrodType {.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 `symbol=`*(n: PNimrodNode, val: PNimrodSymbol) {.magic: "NSetSymbol".}
+proc `ident=`*(n: PNimrodNode, val: TNimrodIdent) {.magic: "NSetIdent".}
+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".}
+proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode".}
+proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree".}
+
+proc error*(msg: string) {.magic: "NError".}
+proc warning*(msg: string) {.magic: "NWarning".}
+proc hint*(msg: string) {.magic: "NHint".}
+
+proc newStrLitNode*(s: string): PNimrodNode {.nodecl.} = 
+  result = newNimNode(nnkStrLit)
+  result.strVal = s
+
+proc newIntLitNode*(i: biggestInt): PNimrodNode {.nodecl.} = 
+  result = newNimNode(nnkIntLit)
+  result.intVal = i
+
+proc newIntLitNode*(f: biggestFloat): PNimrodNode {.nodecl.} = 
+  result = newNimNode(nnkFloatLit)
+  result.floatVal = f
+
+proc newIdentNode*(i: TNimrodIdent): PNimrodNode {.nodecl.} = 
+  result = newNimNode(nnkIdent)
+  result.ident = i
+
+proc toStrLit*(n: PNimrodNode): PNimrodNode {.nodecl.} = 
+  return newStrLitNode(repr(n))
+
+proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.nodecl.} =
+  if n.kind != k: error("macro expects a node of kind: " & repr(k))
+
+proc expectMinLen*(n: PNimrodNode, min: int) {.nodecl.} =
+  if n.len < min: error("macro expects a node with " & $min & " children")
+
+proc newCall*(theProc: TNimrodIdent,
+              args: openArray[PNimrodNode]): PNimrodNode {.nodecl.} =
+  ## 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)