summary refs log tree commit diff stats
path: root/tests/niminaction/Chapter9
diff options
context:
space:
mode:
authorDominik Picheta <dominikpicheta@gmail.com>2017-10-01 17:17:40 +0100
committerDominik Picheta <dominikpicheta@gmail.com>2017-10-01 17:17:40 +0100
commit7889c03cbc50afaa67e1e0eedb4fdcc577913bcd (patch)
tree96f310842e9313166e69a0a4ccdd74645f1a9098 /tests/niminaction/Chapter9
parenta585748f2747bfa9f5e9d5585a74928a9fd13dc5 (diff)
downloadNim-7889c03cbc50afaa67e1e0eedb4fdcc577913bcd.tar.gz
Add tests for examples from Nim in Action.
Diffstat (limited to 'tests/niminaction/Chapter9')
-rw-r--r--tests/niminaction/Chapter9/configurator/configurator.nim84
1 files changed, 84 insertions, 0 deletions
diff --git a/tests/niminaction/Chapter9/configurator/configurator.nim b/tests/niminaction/Chapter9/configurator/configurator.nim
new file mode 100644
index 000000000..0d5627889
--- /dev/null
+++ b/tests/niminaction/Chapter9/configurator/configurator.nim
@@ -0,0 +1,84 @@
+import macros
+
+proc createRefType(ident: NimIdent, identDefs: seq[NimNode]): NimNode =
+  result = newTree(nnkTypeSection,
+    newTree(nnkTypeDef,
+      newIdentNode(ident),
+      newEmptyNode(),
+      newTree(nnkRefTy,
+        newTree(nnkObjectTy,
+          newEmptyNode(),
+          newEmptyNode(),
+          newTree(nnkRecList,
+            identDefs
+          )
+        )
+      )
+    )
+  )
+
+proc toIdentDefs(stmtList: NimNode): seq[NimNode] =
+  expectKind(stmtList, nnkStmtList)
+  result = @[]
+
+  for child in stmtList:
+    expectKind(child, nnkCall)
+    result.add(newIdentDefs(child[0], child[1][0]))
+
+template constructor(ident: untyped): untyped =
+  proc `new ident`(): `ident` =
+    new result
+
+proc createLoadProc(typeName: NimIdent, identDefs: seq[NimNode]): NimNode =
+  var cfgIdent = newIdentNode("cfg")
+  var filenameIdent = newIdentNode("filename")
+  var objIdent = newIdentNode("obj")
+
+  var body = newStmtList()
+  body.add quote do:
+    var `objIdent` = parseFile(`filenameIdent`)
+
+  for identDef in identDefs:
+    let fieldNameIdent = identDef[0]
+    let fieldName = $fieldNameIdent.ident
+    case $identDef[1].ident
+    of "string":
+      body.add quote do:
+        `cfgIdent`.`fieldNameIdent` = `objIdent`[`fieldName`].getStr
+    of "int":
+      body.add quote do:
+        `cfgIdent`.`fieldNameIdent` = `objIdent`[`fieldName`].getNum().int
+    else:
+      doAssert(false, "Not Implemented")
+
+  return newProc(newIdentNode("load"),
+    [newEmptyNode(),
+     newIdentDefs(cfgIdent, newIdentNode(typeName)),
+     newIdentDefs(filenameIdent, newIdentNode("string"))],
+    body)
+
+macro config*(typeName: untyped, fields: untyped): untyped =
+  result = newStmtList()
+
+  let identDefs = toIdentDefs(fields)
+  result.add createRefType(typeName.ident, identDefs)
+  result.add getAst(constructor(typeName.ident))
+  result.add createLoadProc(typeName.ident, identDefs)
+
+  echo treeRepr(typeName)
+  echo treeRepr(fields)
+
+  echo treeRepr(result)
+  echo toStrLit(result)
+  # TODO: Verify that we can export fields in config type so that it can be
+  # used in another module.
+
+import json
+config MyAppConfig:
+  address: string
+  port: int
+
+var myConf = newMyAppConfig()
+myConf.load("myappconfig.cfg")
+echo("Address: ", myConf.address)
+echo("Port: ", myConf.port)