-
-
Save alapini/3ad224da4e9db6bf64e28cc9b93b6dd7 to your computer and use it in GitHub Desktop.
nim class macro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import macros | |
proc typeName(head: NimNode): NimNode = | |
if head.len == 0: head else: head[1] | |
proc baseName(head: NimNode): NimNode = | |
if head.len == 0: newIdentNode("RootObj") else: head[2] | |
proc isObjectDef(head: NimNode): bool = | |
head.len == 0 or head[2].kind == nnkIdent | |
proc buildObjectTypeDecl(head: NimNode): NimNode = | |
template typeDecl(a, b): untyped = | |
type a* = ref object of b | |
result = getAst(typeDecl(head.typeName, head.baseName)) | |
proc buildBasicTypeDecl(head: NimNode): NimNode = | |
result = newNimNode(nnkTypeSection) | |
result.add(newNimNode(nnkTypeDef)) | |
result[0].add(newIdentNode($head[1])) | |
result[0].add(newNimNode(nnkEmpty)) | |
result[0].add(head[2]) | |
proc buildTypeDecl(head: NimNode): NimNode = | |
if head.isObjectDef: | |
head.buildObjectTypeDecl | |
else: | |
head.buildBasicTypeDecl | |
macro class*(head, body: untyped): untyped = | |
result = newStmtList() | |
result.add(head.buildTypeDecl) | |
let | |
typeName = head.typeName | |
ctorName = newIdentNode("new" & $typeName) | |
var recList = newNimNode(nnkRecList) | |
for node in body.children: | |
case node.kind: | |
of nnkMethodDef, nnkProcDef, nnkIteratorDef: | |
if node.name.kind != nnkAccQuoted and node.name == ctorName: | |
node.params[0] = typeName | |
else: | |
node.params.insert(1, newIdentDefs(ident("self"), typeName)) | |
result.add(node) | |
of nnkVarSection: | |
if not head.isObjectDef: | |
error "Invalid node: " & node.lispRepr | |
for n in node.children: | |
recList.add(n) | |
else: | |
result.add(node) | |
if head.isObjectDef: | |
result[0][0][2][0][2] = recList |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import class | |
class Animal: | |
var name: string | |
var age: int | |
method vocalize: string {.base.} = | |
"..." | |
method age_human_yrs: int {.base.} = | |
self.age | |
class Dog of Animal: | |
method vocalize: string = | |
"woof" | |
method age_human_yrs: int = | |
self.age * 7 | |
class Cat of Animal: | |
method vocalize: string = | |
"meow" | |
class Rabbit of Animal: | |
proc newRabbit(name: string, age: int) = | |
result = Rabbit(name: name, age: age) | |
method vocalize: string = | |
"meep" | |
proc `$`: string = | |
"rabbit:" & self.name & ":" & $self.age | |
class Range: | |
var min, max: int | |
iterator items(): int = | |
for n in self.min..self.max: | |
yield n | |
class Point of tuple[x, y: int]: | |
proc newPoint(x, y: int) = | |
(x: x, y: y) | |
proc `$`():string = | |
"x:" & $self.x & " y:" & $self.y | |
class Main: | |
proc animalDemo() = | |
var animals: seq[Animal] = @[] | |
animals.add(Dog(name: "Sparky", age: 10)) | |
animals.add(Cat(name: "Mitten", age: 10)) | |
for a in animals: | |
echo a.vocalize() | |
echo a.age_human_yrs() | |
let r = newRabbit("Fluffy", 3) | |
echo r.vocalize() | |
echo r.age_human_yrs() | |
echo r | |
proc iteratorDemo() = | |
for n in Range(min:3, max:12): | |
echo n | |
proc tupleClassDemo() = | |
echo (x:1, y:2) | |
echo (3, 4) | |
echo newPoint(5, 6) | |
proc run() = | |
self.animalDemo | |
self.iteratorDemo | |
self.tupleClassDemo | |
Main().run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment