diff options
author | Dominik Picheta <dominikpicheta@gmail.com> | 2017-10-01 17:17:40 +0100 |
---|---|---|
committer | Dominik Picheta <dominikpicheta@gmail.com> | 2017-10-01 17:17:40 +0100 |
commit | 7889c03cbc50afaa67e1e0eedb4fdcc577913bcd (patch) | |
tree | 96f310842e9313166e69a0a4ccdd74645f1a9098 /tests/niminaction/Chapter9 | |
parent | a585748f2747bfa9f5e9d5585a74928a9fd13dc5 (diff) | |
download | Nim-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.nim | 84 |
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) |