-
-
Save okeyokoro/8aeacaae17f6a0605884c805338ec40c 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