meta.nim 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #
  2. # meta.nim
  3. #
  4. import tables
  5. import macros
  6. type
  7. NodeSeq* = seq[NimNode]
  8. Ident* = tuple[name: string, exported: bool]
  9. Bracket* = seq[Ident]
  10. Field* = tuple[identifier: Ident, type_name: string, default: string]
  11. FieldSeq* = seq[Field]
  12. TypeDef* = object
  13. identifier*: Ident
  14. fields*: FieldSeq
  15. is_ref*: bool
  16. object_type*: string
  17. base_type*: string
  18. TypeDefSeq* = seq[TypeDef]
  19. Proc* = tuple[identifier: Ident, params: FieldSeq,
  20. returns: Ident, generics: FieldSeq, body: NimNode]
  21. ProcSeq* = seq[Proc]
  22. # Ident procs
  23. proc newIdent*(name: string, exported = false): Ident =
  24. result.name = name
  25. result.exported = exported
  26. proc newIdent*(node: NimNode): Ident =
  27. case node.kind:
  28. of nnkPostfix:
  29. result = newIdent(node[1])
  30. result.exported = true
  31. of nnkIdent, nnkSym:
  32. result.name = $(node)
  33. else:
  34. let msg = "newIdent cannot initialize from node kind: " & $(node.kind)
  35. raise newException(ValueError, msg)
  36. proc render*(i: Ident): NimNode {.compileTime.} =
  37. if i.name == nil:
  38. return newNimNode(nnkEmpty)
  39. if i.exported:
  40. result = newNimNode(nnkPostfix)
  41. result.add(ident "*")
  42. result.add(ident i.name)
  43. else:
  44. result = ident i.name
  45. proc `$`*(identifier: Ident): string = identifier.name
  46. converter toString*(x: Ident): string = x.name
  47. proc newBracket*(node: NimNode): Bracket =
  48. result = @[]
  49. case node.kind:
  50. of nnkBracket:
  51. for child in node:
  52. if child.kind != nnkIdent:
  53. let msg = "Bracket members can only be nnkIdent not kind: " & $(node.kind)
  54. raise newException(ValueError, msg)
  55. result.add(newIdent(child))
  56. else:
  57. let msg = "newBracket must initialize from node kind nnkBracket not: " & $(node.kind)
  58. raise newException(ValueError, msg)
  59. # Field procs
  60. proc newField*(identifier: Ident, type_name: string, default: string = nil): Field =
  61. result.identifier = identifier
  62. result.type_name = type_name
  63. result.default = default
  64. proc newField*(node: NimNode): Field =
  65. case node.kind:
  66. of nnkIdentDefs:
  67. if node.len > 3:
  68. let msg = "newField cannot initialize from nnkIdentDefs with multiple names"
  69. raise newException(ValueError, msg)
  70. result.identifier = newIdent(node[0])
  71. result.type_name = $(node[1])
  72. case node[2].kind:
  73. of nnkIdent:
  74. result.default = $(node[2])
  75. else:
  76. result.default = nil
  77. else:
  78. let msg = "newField cannot initialize from node kind: " & $(node.kind)
  79. raise newException(ValueError, msg)
  80. # FieldSeq procs
  81. proc newFieldSeq*(node: NimNode): FieldSeq =
  82. result = @[]
  83. case node.kind:
  84. of nnkIdentDefs:
  85. let
  86. type_name = $(node[node.len - 2])
  87. default_node = node[node.len - 1]
  88. var default: string
  89. case default_node.kind:
  90. of nnkIdent:
  91. default = $(default_node)
  92. else:
  93. default = nil
  94. for i in 0..node.len - 3:
  95. let name = newIdent(node[i])
  96. result.add(newField(name, type_name, default))
  97. of nnkRecList, nnkVarSection, nnkGenericParams:
  98. for child in node:
  99. result = result & newFieldSeq(child)
  100. else:
  101. let msg = "newFieldSeq cannot initialize from node kind: " & $(node.kind)
  102. raise newException(ValueError, msg)
  103. proc render*(f: Field): NimNode {.compileTime.} =
  104. let identifier = f.identifier.render()
  105. let type_name = if f.type_name != nil: ident(f.type_name) else: newEmptyNode()
  106. let default = if f.default != nil: ident(f.default) else: newEmptyNode()
  107. newIdentDefs(identifier, type_name, default)
  108. proc render*(fs: FieldSeq): NimNode {.compileTime.} =
  109. result = newNimNode(nnkRecList)
  110. for field in fs:
  111. result.add(field.render())
  112. # TypeDef procs
  113. proc newTypeDef*(identifier: Ident, is_ref = false,
  114. object_type = "object",
  115. base_type: string = nil): TypeDef {.compileTime.} =
  116. result.identifier = identifier
  117. result.fields = @[]
  118. result.is_ref = is_ref
  119. result.object_type = "object"
  120. result.base_type = base_type
  121. proc newTypeDef*(node: NimNode): TypeDef {.compileTime.} =
  122. case node.kind:
  123. of nnkTypeDef:
  124. result.identifier = newIdent($(node[0]))
  125. var object_node: NimNode
  126. case node[2].kind:
  127. of nnkRefTy:
  128. object_node = node[2][0]
  129. result.is_ref = true
  130. of nnkObjectTy:
  131. object_node = node[2]
  132. result.is_ref = false
  133. else:
  134. let msg = "newTypeDef could not parse RefTy/ObjectTy, found: " & $(node[2].kind)
  135. raise newException(ValueError, msg)
  136. case object_node[1].kind:
  137. of nnkOfInherit:
  138. result.base_type = $(object_node[1][0])
  139. else:
  140. result.base_type = "object"
  141. result.fields = newFieldSeq(object_node[2])
  142. else:
  143. let msg = "newTypeDef cannot initialize from node kind: " & $(node.kind)
  144. raise newException(ValueError, msg)
  145. proc render*(typedef: TypeDef): NimNode {.compileTime.} =
  146. result = newNimNode(nnkTypeDef)
  147. result.add(typedef.identifier.render)
  148. result.add(newEmptyNode())
  149. let object_node = newNimNode(nnkObjectTy)
  150. object_node.add(newEmptyNode())
  151. if typedef.base_type == nil:
  152. object_node.add(newEmptyNode())
  153. else:
  154. var base_type = newNimNode(nnkOfInherit)
  155. base_type.add(ident(typedef.base_type))
  156. object_node.add(base_type)
  157. let fields = typedef.fields.render()
  158. object_node.add(fields)
  159. if typedef.is_ref:
  160. let ref_node = newNimNode(nnkRefTy)
  161. ref_node.add(object_node)
  162. result.add(ref_node)
  163. else:
  164. result.add(object_node)
  165. proc newTypeDefSeq*(node: NimNode): TypeDefSeq =
  166. result = @[]
  167. case node.kind:
  168. of nnkTypeSection:
  169. for child in node:
  170. result.add(newTypeDef(child))
  171. else:
  172. let msg = "newTypeSection could not parse TypeDef, found: " & $(node.kind)
  173. raise newException(ValueError, msg)
  174. proc render*(typeseq: TypeDefSeq): NimNode {.compileTime.} =
  175. result = newNimNode(nnkTypeSection)
  176. for typedef in typeseq:
  177. result.add(typedef.render())
  178. proc newProc*(identifier: Ident, params: FieldSeq = nil,
  179. returns: Ident, generics: FieldSeq = nil): Proc =
  180. result.identifier = identifier
  181. result.params = params
  182. result.returns = returns
  183. result.generics = generics
  184. proc newProc*(node: NimNode): Proc =
  185. case node.kind:
  186. of nnkProcDef, nnkMethodDef:
  187. result.identifier = newIdent(node[0])
  188. case node[2].kind:
  189. of nnkGenericParams:
  190. result.generics = newFieldSeq(node[2])
  191. else: result.generics = nil
  192. let formal_params = node[3]
  193. case formal_params[0].kind:
  194. of nnkIdent:
  195. result.returns = newIdent(formal_params[0])
  196. else: discard
  197. result.params = @[]
  198. for i in 1..formal_params.len - 1:
  199. let param = formal_params[i]
  200. for field in newFieldSeq(param):
  201. result.params.add(field)
  202. result.body = node[6]
  203. else:
  204. let msg = "newProc cannot initialize from node kind: " & $(node.kind)
  205. raise newException(ValueError, msg)
  206. proc render*(procdef: Proc): NimNode {.compileTime.} =
  207. result = newNimNode(nnkProcDef)
  208. result.add(procdef.identifier.render())
  209. result.add(newEmptyNode())
  210. result.add(newEmptyNode())
  211. let formal_params = newNimNode(nnkFormalParams)
  212. formal_params.add(procdef.returns.render())
  213. for param in procdef.params:
  214. formal_params.add(param.render())
  215. result.add(formal_params)
  216. result.add(newEmptyNode())
  217. result.add(newEmptyNode())
  218. result.add(procdef.body)