【发布时间】:2021-07-14 17:17:57
【问题描述】:
尝试编写访问器以获取具有 kind 成员的对象的值,但在宏中出现无效缩进错误,我不知道为什么
我想我可能会错误地构建宏,但如果有更好的方法来抽象对象中的类型种类,那就太好了。
这是我正在工作的实现:
import macros,strutils,tables
type Types = enum Integer,Float,String,Array
type StyleName = enum X,Y,W,H,Left,Margin,Padding,Color,BorderColor
type Value=object
case kind : Types
of Integer: ival:int
of Float: fval:float
of String: sval:string
of Array: cval:array[4,int]
proc toValue(x:float):Value=Value(kind:Float,fval:x)
proc toValue(x:int):Value=Value(kind:Integer,ival:x)
proc toValue(x:string):Value=Value(kind:String,sval:x)
proc toValue(x:array[4,int]):Value=Value(kind:Array,cval:x)
#Construct {stylename:value,...} to {stylename:Value(kind,value),...}
macro style(args: varargs[untyped]): Table[StyleName,Value] =
#echo repr(args), args.treeRepr
var s:seq[string]
for arg in args:
s.add arg[0].repr & ":" & "toValue(" & arg[1].repr & ")"
result = parseStmt("{" & s.join(",") & "}.toTable")
变体对象“值”的宏访问器
macro getWithKind(style:Table[StyleName,Value], prop:StyleName, kind:Types):untyped=
var accesor:string
case kind.repr:
of "Integer": accesor="ival"
of "Float": accesor="fval"
of "String": accesor="sval"
of "Array": accesor="cval"
result = parseStmt(style.repr & "[" & prop.repr & "]." & accesor)
#Transforms simple get(style,prop) call to getWithKind(style,prop,kind)
macro get(style:Table[StyleName,Value], prop:StyleName):untyped=
result = parseStmt(style.repr & ".getWithKind(" & prop.repr & ", kind=" & style.repr & "[" & prop.repr & "].kind)")
这是我得到的输出: 不能在另一个宏里面调用宏吗?
let style1 = style(X=1,Y=2.0,Color=[0,0,0,0]) #build a table of (StyleName:Value)
echo style1 #output: {X: (kind: Integer, ival: 1), Y: (kind: Float, fval: 2.0), Color: (kind: Array, cval: [0, 0, 0, 0])}
echo style1[X].ival # output:1
echo style1[X].kind # output:Integer
echo style1.getWithKind(X,kind=Integer) # output:1
echo style1.get(X) #(should get 1), output:
C:\Users\cravs\Desktop\test.nim(109, 21) getWithKind
C:\nim-1.4.8\lib\core\macros.nim(558, 17) parseStmt
C:\Users\cravs\Desktop\test.nim(119, 12) template/generic instantiation of `get` from here
C:\nim-1.4.8\lib\core\macros.nim(557, 7) template/generic instantiation of `getWithKind` from here
C:\nim-1.4.8\lib\core\macros.nim(558, 17) Error: unhandled exception: C:\nim-1.4.8\lib\core\macros.nim(557, 11) Error: invalid indentation [ValueError]
编辑: 这是另一个尝试
macro getWithKind(style:Table[StyleName,Value], prop:StyleName, kind:Types):untyped=
var accesor:string
case kind.repr
of "Integer": accesor="ival"
of "Float": accesor="fval"
of "String": accesor="sval"
of "Array": accesor="cval"
result = newDotExpr(newTree(nnkBracketExpr,style,prop), newIdentNode(accesor))
#echo parseStmt(style.repr & "[" & prop.repr & "]." & accesor)
macro get(style:Table[StyleName,Value], prop:StyleName):untyped=
#result = parseStmt(style.repr & ".getWithKind(" & prop.repr & ", kind=" & style.repr & "[" & prop.repr & "].kind)")
let kind = newDotExpr(newTree(nnkBracketExpr,style,prop), newIdentNode("kind"))
echo treeRepr kind
quote do:
echo `kind` #prints Integer
getWithKind(`style`,`prop`,kind=`kind`)
let style1 = style(X=1,Y=2.0,Color=[0,0,0,0]) #build a table of (StyleName:Value)
echo style1 #output: {X: (kind: Integer, ival: 1), Y: (kind: Float, fval: 2.0), Color: (kind: Array, cval: [0, 0, 0, 0])}
echo style1[X].ival # output:1
echo style1[X].kind # output:Integer
echo style1.getWithKind(X,kind=Integer) # output:1
echo style1.get(X) #(should get 1), output:
C:\Users\...\test.nim(127, 3) Error: undeclared field: '' for type test.Value [declared in C:\Users\...\test.nim(80, 6)]
【问题讨论】:
标签: variant nim-lang type-kinds