# # meta.nim # import tables import macros type NodeSeq* = seq[NimNode] Ident* = tuple[name: string, exported: bool] Bracket* = seq[Ident] Field* = tuple[identifier: Ident, type_name: string, default: string] FieldSeq* = seq[Field] TypeDef* = object identifier*: Ident fields*: FieldSeq is_ref*: bool object_type*: string base_type*: string TypeDefSeq* = seq[TypeDef] Proc* = tuple[identifier: Ident, params: FieldSeq, returns: Ident, generics: FieldSeq, body: NimNode] ProcSeq* = seq[Proc] # Ident procs proc newIdent*(name: string, exported = false): Ident = result.name = name result.exported = exported proc newIdent*(node: NimNode): Ident = case node.kind: of nnkPostfix: result = newIdent(node[1]) result.exported = true of nnkIdent, nnkSym: result.name = $(node) else: let msg = "newIdent cannot initialize from node kind: " & $(node.kind) raise newException(ValueError, msg) proc render*(i: Ident): NimNode {.compileTime.} = if i.name == "": return newNimNode(nnkEmpty) if i.exported: result = newNimNode(nnkPostfix) result.add(ident "*") result.add(ident i.name) else: result = ident i.name proc `$`*(identifier: Ident): string = identifier.name converter toString*(x: Ident): string = x.name proc newBracket*(node: NimNode): Bracket = result = @[] case node.kind: of nnkBracket: for child in node: if child.kind != nnkIdent: let msg = "Bracket members can only be nnkIdent not kind: " & $(node.kind) raise newException(ValueError, msg) result.add(newIdent(child)) else: let msg = "newBracket must initialize from node kind nnkBracket not: " & $(node.kind) raise newException(ValueError, msg) # Field procs proc newField*(identifier: Ident, type_name: string, default: string = ""): Field = result.identifier = identifier result.type_name = type_name result.default = default proc newField*(node: NimNode): Field = case node.kind: of nnkIdentDefs: if node.len > 3: let msg = "newField cannot initialize from nnkIdentDefs with multiple names" raise newException(ValueError, msg) result.identifier = newIdent(node[0]) result.type_name = $(node[1]) case node[2].kind: of nnkIdent: result.default = $(node[2]) else: result.default = "" else: let msg = "newField cannot initialize from node kind: " & $(node.kind) raise newException(ValueError, msg) # FieldSeq procs proc newFieldSeq*(node: NimNode): FieldSeq = result = @[] case node.kind: of nnkIdentDefs: let type_name = $(node[node.len - 2]) default_node = node[node.len - 1] var default: string case default_node.kind: of nnkIdent: default = $(default_node) else: default = "" for i in 0..node.len - 3: let name = newIdent(node[i]) result.add(newField(name, type_name, default)) of nnkRecList, nnkVarSection, nnkGenericParams: for child in node: result = result & newFieldSeq(child) else: let msg = "newFieldSeq cannot initialize from node kind: " & $(node.kind) raise newException(ValueError, msg) proc render*(f: Field): NimNode {.compileTime.} = let identifier = f.identifier.render() let type_name = if f.type_name != "": ident(f.type_name) else: newEmptyNode() let default = if f.default != "": ident(f.default) else: newEmptyNode() newIdentDefs(identifier, type_name, default) proc render*(fs: FieldSeq): NimNode {