-
Notifications
You must be signed in to change notification settings - Fork 2
/
macroFor.nim
96 lines (83 loc) · 2.58 KB
/
macroFor.nim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import
macros
type
TPattern = tuple
patNode, resNode: PNimrodNode
proc isEqual(n1, n2: PNimrodNode): bool {.compiletime.} =
if n1.kind == nnkIdent and n2.kind == nnkIdent :
#echo n1.ident, " same ", n2.ident
return n1.ident == n2.ident
if n1.len == n2.len and n1.kind == n2.kind :
# echo n1.len, " same ", n2.len, " and ", n1.kind, " same ", n2.kind
for i in 0 .. n1.len -1:
if not isEqual(n1[i], n2[i]): return false
return true
return false
proc replace(n: var PNimrodNode, pat: TPattern): Bool {.compiletime.} =
if isEqual(n, pat.patNode):
n = pat.resNode
return true
proc forAll(node: PNimrodNode, pat: TPattern, call: proc(n: var PNimrodNode, pat:TPattern): Bool ): PNimrodNode {.compiletime.} =
result = node
for i in 0 .. result.len -1:
var ri = result[i]
if ri != nil :
var changed = call(ri, pat)
if changed :
result[i] = ri
else :
result[i] = forAll(ri, pat, call)
macro macFor* (x:stmt): stmt {.immediate.} =
result = newNimNode(nnkStmtList)
let n = callsite()
var patterns: seq[TPattern] = @[]
var stm: PNimrodNode
var maxPat = 0
block ok:
block error:
#echo n.len
if n.len > 2 :
for i in 1 .. n.len - 1:
case n[i].kind
of nnkStmtList :
stm = n[i]
break
of nnkInfix :
if n[i][0].kind != nnkIdent or n[i][0].ident != !"->" or
n[i][1].kind != nnkIdent or
n[i][2].kind != nnkBracket:
break error
if n[i][2].len > maxPat : maxPat = n[i][2].len
patterns.add((n[i][1], n[i][2]))
else : break error
break ok
error "usage macFor C->[X,Y,Z] : C = 2 * C"
for i in 0..maxPat-1:
var stm1 = stm.copyNimTree
for p in patterns:
var pat = p.patNode
var res = p.resNode[i mod p.resNode.len]
echo pat.repr, "-> ", res.repr
#echo "in ", stm1.treerepr
stm1 = stm1.forAll((pat, res), replace)
#echo "out ", stm1.treerepr
#echo "here ", stm1.repr
result.add(stm1)
#echo result.repr
when isMainModule:
var
x, y, z: int
r,g,b: int
macFor Cn ->[X, Y, Z], Dn->[Y,Z,X], Rn->[R,G,B]:
Rn = Cn + Dn
const
CBaseShift = 8
CBaseSize = 1 shl CBaseShift
CBaseMask = CBaseSize - 1
type
TColor = tuple
R,G,B,A: byte
proc Gradient(c1, c2: TColor; k: float): TColor =
var Ik = (K * CBaseSize.toFloat).toInt
macFor Col->[R,G,B,A]:
Result.Col = Byte(int(c1.Col) + ((int(c2.Col) - c1.Col.int) * Ik) shr CBaseShift)