fixes #2346
This commit is contained in:
parent
bc264618f5
commit
bf90b9c833
9 changed files with 107 additions and 97 deletions
|
|
@ -174,7 +174,8 @@ type
|
||||||
arLValue, # is an l-value
|
arLValue, # is an l-value
|
||||||
arLocalLValue, # is an l-value, but local var; must not escape
|
arLocalLValue, # is an l-value, but local var; must not escape
|
||||||
# its stack frame!
|
# its stack frame!
|
||||||
arDiscriminant # is a discriminant
|
arDiscriminant, # is a discriminant
|
||||||
|
arStrange # it is a strange beast like 'typedesc[var T]'
|
||||||
|
|
||||||
proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
|
proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
|
||||||
## 'owner' can be nil!
|
## 'owner' can be nil!
|
||||||
|
|
@ -188,6 +189,9 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
|
||||||
result = arLocalLValue
|
result = arLocalLValue
|
||||||
else:
|
else:
|
||||||
result = arLValue
|
result = arLValue
|
||||||
|
elif n.sym.kind == skType:
|
||||||
|
let t = n.sym.typ.skipTypes({tyTypeDesc})
|
||||||
|
if t.kind == tyVar: result = arStrange
|
||||||
of nkDotExpr:
|
of nkDotExpr:
|
||||||
if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in
|
if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in
|
||||||
{tyVar, tyPtr, tyRef}:
|
{tyVar, tyPtr, tyRef}:
|
||||||
|
|
@ -222,7 +226,7 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc isLValue*(n: PNode): bool =
|
proc isLValue*(n: PNode): bool =
|
||||||
isAssignable(nil, n) in {arLValue, arLocalLValue}
|
isAssignable(nil, n) in {arLValue, arLocalLValue, arStrange}
|
||||||
|
|
||||||
proc matchNodeKinds*(p, n: PNode): bool =
|
proc matchNodeKinds*(p, n: PNode): bool =
|
||||||
# matches the parameter constraint 'p' against the concrete AST 'n'.
|
# matches the parameter constraint 'p' against the concrete AST 'n'.
|
||||||
|
|
|
||||||
|
|
@ -287,6 +287,7 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
|
||||||
return n
|
return n
|
||||||
result = getConstExpr(c.module, e)
|
result = getConstExpr(c.module, e)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
|
#if e.kind == nkEmpty: globalError(n.info, errConstExprExpected)
|
||||||
result = evalConstExpr(c.module, e)
|
result = evalConstExpr(c.module, e)
|
||||||
if result == nil or result.kind == nkEmpty:
|
if result == nil or result.kind == nkEmpty:
|
||||||
if e.info != n.info:
|
if e.info != n.info:
|
||||||
|
|
|
||||||
|
|
@ -800,7 +800,9 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
|
|
||||||
for i in 0 .. paramType.sonsLen - 2:
|
for i in 0 .. paramType.sonsLen - 2:
|
||||||
if paramType.sons[i].kind == tyStatic:
|
if paramType.sons[i].kind == tyStatic:
|
||||||
result.rawAddSon makeTypeFromExpr(c, ast.emptyNode) # aka 'tyUnknown'
|
var x = copyNode(ast.emptyNode)
|
||||||
|
x.typ = paramType.sons[i]
|
||||||
|
result.rawAddSon makeTypeFromExpr(c, x) # aka 'tyUnknown'
|
||||||
else:
|
else:
|
||||||
result.rawAddSon newTypeS(tyAnything, c)
|
result.rawAddSon newTypeS(tyAnything, c)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,9 @@ proc checkPartialConstructedType(info: TLineInfo, t: PType) =
|
||||||
proc checkConstructedType*(info: TLineInfo, typ: PType) =
|
proc checkConstructedType*(info: TLineInfo, typ: PType) =
|
||||||
var t = typ.skipTypes({tyDistinct})
|
var t = typ.skipTypes({tyDistinct})
|
||||||
if t.kind in tyTypeClasses: discard
|
if t.kind in tyTypeClasses: discard
|
||||||
elif tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject:
|
elif tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject:
|
||||||
localError(info, errInvalidPragmaX, "acyclic")
|
localError(info, errInvalidPragmaX, "acyclic")
|
||||||
elif t.kind == tyVar and t.sons[0].kind == tyVar:
|
elif t.kind == tyVar and t.sons[0].kind == tyVar:
|
||||||
localError(info, errVarVarTypeNotAllowed)
|
localError(info, errVarVarTypeNotAllowed)
|
||||||
elif computeSize(t) == szIllegalRecursion:
|
elif computeSize(t) == szIllegalRecursion:
|
||||||
localError(info, errIllegalRecursionInTypeX, typeToString(t))
|
localError(info, errIllegalRecursionInTypeX, typeToString(t))
|
||||||
|
|
@ -44,7 +44,7 @@ proc checkConstructedType*(info: TLineInfo, typ: PType) =
|
||||||
sharedPtrCheck(info, t)
|
sharedPtrCheck(info, t)
|
||||||
when false:
|
when false:
|
||||||
if t.kind == tyObject and t.sons[0] != nil:
|
if t.kind == tyObject and t.sons[0] != nil:
|
||||||
if t.sons[0].kind != tyObject or tfFinal in t.sons[0].flags:
|
if t.sons[0].kind != tyObject or tfFinal in t.sons[0].flags:
|
||||||
localError(info, errInheritanceOnlyWithNonFinalObjects)
|
localError(info, errInheritanceOnlyWithNonFinalObjects)
|
||||||
|
|
||||||
proc searchInstTypes*(key: PType): PType =
|
proc searchInstTypes*(key: PType): PType =
|
||||||
|
|
@ -69,7 +69,7 @@ proc searchInstTypes*(key: PType): PType =
|
||||||
if not compareTypes(inst.sons[j], key.sons[j],
|
if not compareTypes(inst.sons[j], key.sons[j],
|
||||||
flags = {ExactGenericParams}):
|
flags = {ExactGenericParams}):
|
||||||
break matchType
|
break matchType
|
||||||
|
|
||||||
return inst
|
return inst
|
||||||
|
|
||||||
proc cacheTypeInst*(inst: PType) =
|
proc cacheTypeInst*(inst: PType) =
|
||||||
|
|
@ -79,7 +79,7 @@ proc cacheTypeInst*(inst: PType) =
|
||||||
genericTyp.sym.typeInstCache.safeAdd(inst)
|
genericTyp.sym.typeInstCache.safeAdd(inst)
|
||||||
|
|
||||||
type
|
type
|
||||||
TReplTypeVars* {.final.} = object
|
TReplTypeVars* {.final.} = object
|
||||||
c*: PContext
|
c*: PContext
|
||||||
typeMap*: TIdTable # map PType to PType
|
typeMap*: TIdTable # map PType to PType
|
||||||
symMap*: TIdTable # map PSym to PSym
|
symMap*: TIdTable # map PSym to PSym
|
||||||
|
|
@ -151,7 +151,7 @@ proc reResolveCallsWithTypedescParams(cl: var TReplTypeVars, n: PNode): PNode =
|
||||||
if needsFixing:
|
if needsFixing:
|
||||||
n.sons[0] = newSymNode(n.sons[0].sym.owner)
|
n.sons[0] = newSymNode(n.sons[0].sym.owner)
|
||||||
return cl.c.semOverloadedCall(cl.c, n, n, {skProc})
|
return cl.c.semOverloadedCall(cl.c, n, n, {skProc})
|
||||||
|
|
||||||
for i in 0 .. <n.safeLen:
|
for i in 0 .. <n.safeLen:
|
||||||
n.sons[i] = reResolveCallsWithTypedescParams(cl, n[i])
|
n.sons[i] = reResolveCallsWithTypedescParams(cl, n[i])
|
||||||
|
|
||||||
|
|
@ -203,18 +203,18 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
|
||||||
newSons(result, length)
|
newSons(result, length)
|
||||||
for i in countup(0, length - 1):
|
for i in countup(0, length - 1):
|
||||||
result.sons[i] = replaceTypeVarsN(cl, n.sons[i])
|
result.sons[i] = replaceTypeVarsN(cl, n.sons[i])
|
||||||
|
|
||||||
proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
|
proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
|
||||||
if s == nil: return nil
|
if s == nil: return nil
|
||||||
result = PSym(idTableGet(cl.symMap, s))
|
result = PSym(idTableGet(cl.symMap, s))
|
||||||
if result == nil:
|
if result == nil:
|
||||||
result = copySym(s, false)
|
result = copySym(s, false)
|
||||||
incl(result.flags, sfFromGeneric)
|
incl(result.flags, sfFromGeneric)
|
||||||
idTablePut(cl.symMap, s, result)
|
idTablePut(cl.symMap, s, result)
|
||||||
result.owner = s.owner
|
result.owner = s.owner
|
||||||
result.typ = replaceTypeVarsT(cl, s.typ)
|
result.typ = replaceTypeVarsT(cl, s.typ)
|
||||||
result.ast = replaceTypeVarsN(cl, s.ast)
|
result.ast = replaceTypeVarsN(cl, s.ast)
|
||||||
|
|
||||||
proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType =
|
proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType =
|
||||||
result = PType(idTableGet(cl.typeMap, t))
|
result = PType(idTableGet(cl.typeMap, t))
|
||||||
if result == nil:
|
if result == nil:
|
||||||
|
|
@ -234,7 +234,7 @@ proc instCopyType*(cl: var TReplTypeVars, t: PType): PType =
|
||||||
result.flags.incl tfFromGeneric
|
result.flags.incl tfFromGeneric
|
||||||
result.flags.excl tfInstClearedFlags
|
result.flags.excl tfInstClearedFlags
|
||||||
|
|
||||||
proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
|
proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
|
||||||
# tyGenericInvocation[A, tyGenericInvocation[A, B]]
|
# tyGenericInvocation[A, tyGenericInvocation[A, B]]
|
||||||
# is difficult to handle:
|
# is difficult to handle:
|
||||||
var body = t.sons[0]
|
var body = t.sons[0]
|
||||||
|
|
@ -256,7 +256,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
|
||||||
propagateToOwner(header, x)
|
propagateToOwner(header, x)
|
||||||
else:
|
else:
|
||||||
propagateToOwner(header, x)
|
propagateToOwner(header, x)
|
||||||
|
|
||||||
if header != t:
|
if header != t:
|
||||||
# search again after first pass:
|
# search again after first pass:
|
||||||
result = searchInstTypes(header)
|
result = searchInstTypes(header)
|
||||||
|
|
@ -282,7 +282,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
|
||||||
header.sons[i] = x
|
header.sons[i] = x
|
||||||
propagateToOwner(header, x)
|
propagateToOwner(header, x)
|
||||||
idTablePut(cl.typeMap, body.sons[i-1], x)
|
idTablePut(cl.typeMap, body.sons[i-1], x)
|
||||||
|
|
||||||
for i in countup(1, sonsLen(t) - 1):
|
for i in countup(1, sonsLen(t) - 1):
|
||||||
# if one of the params is not concrete, we cannot do anything
|
# if one of the params is not concrete, we cannot do anything
|
||||||
# but we already raised an error!
|
# but we already raised an error!
|
||||||
|
|
@ -310,7 +310,7 @@ proc eraseVoidParams*(t: PType) =
|
||||||
# don't deal with '(): void':
|
# don't deal with '(): void':
|
||||||
if t.sons[0] != nil and t.sons[0].kind == tyEmpty:
|
if t.sons[0] != nil and t.sons[0].kind == tyEmpty:
|
||||||
t.sons[0] = nil
|
t.sons[0] = nil
|
||||||
|
|
||||||
for i in 1 .. <t.sonsLen:
|
for i in 1 .. <t.sonsLen:
|
||||||
# don't touch any memory unless necessary
|
# don't touch any memory unless necessary
|
||||||
if t.sons[i].kind == tyEmpty:
|
if t.sons[i].kind == tyEmpty:
|
||||||
|
|
@ -332,7 +332,7 @@ proc skipIntLiteralParams*(t: PType) =
|
||||||
if skipped != p:
|
if skipped != p:
|
||||||
t.sons[i] = skipped
|
t.sons[i] = skipped
|
||||||
if i > 0: t.n.sons[i].sym.typ = skipped
|
if i > 0: t.n.sons[i].sym.typ = skipped
|
||||||
|
|
||||||
# when the typeof operator is used on a static input
|
# when the typeof operator is used on a static input
|
||||||
# param, the results gets infected with static as well:
|
# param, the results gets infected with static as well:
|
||||||
if t.sons[0] != nil and t.sons[0].kind == tyStatic:
|
if t.sons[0] != nil and t.sons[0].kind == tyStatic:
|
||||||
|
|
@ -359,7 +359,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||||
if t.kind in {tyStatic, tyGenericParam, tyIter} + tyTypeClasses:
|
if t.kind in {tyStatic, tyGenericParam, tyIter} + tyTypeClasses:
|
||||||
let lookup = PType(idTableGet(cl.typeMap, t))
|
let lookup = PType(idTableGet(cl.typeMap, t))
|
||||||
if lookup != nil: return lookup
|
if lookup != nil: return lookup
|
||||||
|
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyGenericInvocation:
|
of tyGenericInvocation:
|
||||||
result = handleGenericInvocation(cl, t)
|
result = handleGenericInvocation(cl, t)
|
||||||
|
|
@ -373,7 +373,8 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||||
if cl.allowMetaTypes: return
|
if cl.allowMetaTypes: return
|
||||||
assert t.n.typ != t
|
assert t.n.typ != t
|
||||||
var n = prepareNode(cl, t.n)
|
var n = prepareNode(cl, t.n)
|
||||||
n = cl.c.semConstExpr(cl.c, n)
|
if n.kind != nkEmpty:
|
||||||
|
n = cl.c.semConstExpr(cl.c, n)
|
||||||
if n.typ.kind == tyTypeDesc:
|
if n.typ.kind == tyTypeDesc:
|
||||||
# XXX: sometimes, chained typedescs enter here.
|
# XXX: sometimes, chained typedescs enter here.
|
||||||
# It may be worth investigating why this is happening,
|
# It may be worth investigating why this is happening,
|
||||||
|
|
@ -394,7 +395,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||||
|
|
||||||
of tyInt, tyFloat:
|
of tyInt, tyFloat:
|
||||||
result = skipIntLit(t)
|
result = skipIntLit(t)
|
||||||
|
|
||||||
of tyTypeDesc:
|
of tyTypeDesc:
|
||||||
let lookup = PType(idTableGet(cl.typeMap, t)) # lookupTypeVar(cl, t)
|
let lookup = PType(idTableGet(cl.typeMap, t)) # lookupTypeVar(cl, t)
|
||||||
if lookup != nil:
|
if lookup != nil:
|
||||||
|
|
@ -402,7 +403,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||||
if tfUnresolved in t.flags: result = result.base
|
if tfUnresolved in t.flags: result = result.base
|
||||||
elif t.sons[0].kind != tyNone:
|
elif t.sons[0].kind != tyNone:
|
||||||
result = makeTypeDesc(cl.c, replaceTypeVarsT(cl, t.sons[0]))
|
result = makeTypeDesc(cl.c, replaceTypeVarsT(cl, t.sons[0]))
|
||||||
|
|
||||||
of tyUserTypeClass:
|
of tyUserTypeClass:
|
||||||
result = t
|
result = t
|
||||||
|
|
||||||
|
|
@ -411,31 +412,31 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||||
for i in 1 .. <result.sonsLen:
|
for i in 1 .. <result.sonsLen:
|
||||||
result.sons[i] = replaceTypeVarsT(cl, result.sons[i])
|
result.sons[i] = replaceTypeVarsT(cl, result.sons[i])
|
||||||
propagateToOwner(result, result.lastSon)
|
propagateToOwner(result, result.lastSon)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if containsGenericType(t):
|
if containsGenericType(t):
|
||||||
result = instCopyType(cl, t)
|
result = instCopyType(cl, t)
|
||||||
result.size = -1 # needs to be recomputed
|
result.size = -1 # needs to be recomputed
|
||||||
|
|
||||||
for i in countup(0, sonsLen(result) - 1):
|
for i in countup(0, sonsLen(result) - 1):
|
||||||
if result.sons[i] != nil:
|
if result.sons[i] != nil:
|
||||||
result.sons[i] = replaceTypeVarsT(cl, result.sons[i])
|
result.sons[i] = replaceTypeVarsT(cl, result.sons[i])
|
||||||
propagateToOwner(result, result.sons[i])
|
propagateToOwner(result, result.sons[i])
|
||||||
|
|
||||||
result.n = replaceTypeVarsN(cl, result.n)
|
result.n = replaceTypeVarsN(cl, result.n)
|
||||||
|
|
||||||
case result.kind
|
case result.kind
|
||||||
of tyArray:
|
of tyArray:
|
||||||
let idx = result.sons[0]
|
let idx = result.sons[0]
|
||||||
internalAssert idx.kind != tyStatic
|
internalAssert idx.kind != tyStatic
|
||||||
|
|
||||||
of tyObject, tyTuple:
|
of tyObject, tyTuple:
|
||||||
propagateFieldFlags(result, result.n)
|
propagateFieldFlags(result, result.n)
|
||||||
|
|
||||||
of tyProc:
|
of tyProc:
|
||||||
eraseVoidParams(result)
|
eraseVoidParams(result)
|
||||||
skipIntLiteralParams(result)
|
skipIntLiteralParams(result)
|
||||||
|
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc initTypeVars*(p: PContext, pt: TIdTable, info: TLineInfo): TReplTypeVars =
|
proc initTypeVars*(p: PContext, pt: TIdTable, info: TLineInfo): TReplTypeVars =
|
||||||
|
|
@ -450,7 +451,7 @@ proc replaceTypesInBody*(p: PContext, pt: TIdTable, n: PNode): PNode =
|
||||||
pushInfoContext(n.info)
|
pushInfoContext(n.info)
|
||||||
result = replaceTypeVarsN(cl, n)
|
result = replaceTypeVarsN(cl, n)
|
||||||
popInfoContext()
|
popInfoContext()
|
||||||
|
|
||||||
proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo,
|
proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo,
|
||||||
t: PType): PType =
|
t: PType): PType =
|
||||||
var cl = initTypeVars(p, pt, info)
|
var cl = initTypeVars(p, pt, info)
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
# this doesn't matter. However it matters for strings and other complex
|
# this doesn't matter. However it matters for strings and other complex
|
||||||
# types that use the 'node' field; the reason is that slots are
|
# types that use the 'node' field; the reason is that slots are
|
||||||
# re-used in a register based VM. Example:
|
# re-used in a register based VM. Example:
|
||||||
#
|
#
|
||||||
# .. code-block:: nim
|
# .. code-block:: nim
|
||||||
# let s = a & b # no matter what, create fresh node
|
# let s = a & b # no matter what, create fresh node
|
||||||
# s = a & b # no matter what, keep the node
|
# s = a & b # no matter what, keep the node
|
||||||
|
|
@ -64,17 +64,17 @@ proc codeListing(c: PCtx, result: var string, start=0; last = -1) =
|
||||||
let y = c.code[i+1]
|
let y = c.code[i+1]
|
||||||
let z = c.code[i+2]
|
let z = c.code[i+2]
|
||||||
result.addf("\t$#\tr$#, r$#, $#, $#", ($opc).substr(3), x.regA, x.regB,
|
result.addf("\t$#\tr$#, r$#, $#, $#", ($opc).substr(3), x.regA, x.regB,
|
||||||
c.types[y.regBx-wordExcess].typeToString,
|
c.types[y.regBx-wordExcess].typeToString,
|
||||||
c.types[z.regBx-wordExcess].typeToString)
|
c.types[z.regBx-wordExcess].typeToString)
|
||||||
inc i, 2
|
inc i, 2
|
||||||
elif opc < firstABxInstr:
|
elif opc < firstABxInstr:
|
||||||
result.addf("\t$#\tr$#, r$#, r$#", ($opc).substr(3), x.regA,
|
result.addf("\t$#\tr$#, r$#, r$#", ($opc).substr(3), x.regA,
|
||||||
x.regB, x.regC)
|
x.regB, x.regC)
|
||||||
elif opc in relativeJumps:
|
elif opc in relativeJumps:
|
||||||
result.addf("\t$#\tr$#, L$#", ($opc).substr(3), x.regA,
|
result.addf("\t$#\tr$#, L$#", ($opc).substr(3), x.regA,
|
||||||
i+x.regBx-wordExcess)
|
i+x.regBx-wordExcess)
|
||||||
elif opc in {opcLdConst, opcAsgnConst}:
|
elif opc in {opcLdConst, opcAsgnConst}:
|
||||||
result.addf("\t$#\tr$#, $#", ($opc).substr(3), x.regA,
|
result.addf("\t$#\tr$#, $#", ($opc).substr(3), x.regA,
|
||||||
c.constants[x.regBx-wordExcess].renderTree)
|
c.constants[x.regBx-wordExcess].renderTree)
|
||||||
else:
|
else:
|
||||||
result.addf("\t$#\tr$#, $#", ($opc).substr(3), x.regA, x.regBx-wordExcess)
|
result.addf("\t$#\tr$#, $#", ($opc).substr(3), x.regA, x.regBx-wordExcess)
|
||||||
|
|
@ -117,7 +117,7 @@ proc gABx(c: PCtx; n: PNode; opc: TOpcode; a: TRegister = 0; bx: int) =
|
||||||
# Applies `opc` to `bx` and stores it into register `a`
|
# Applies `opc` to `bx` and stores it into register `a`
|
||||||
# `bx` must be signed and in the range [-32767, 32768]
|
# `bx` must be signed and in the range [-32767, 32768]
|
||||||
if bx >= -32767 and bx <= 32768:
|
if bx >= -32767 and bx <= 32768:
|
||||||
let ins = (opc.uint32 or a.uint32 shl 8'u32 or
|
let ins = (opc.uint32 or a.uint32 shl 8'u32 or
|
||||||
(bx+wordExcess).uint32 shl 16'u32).TInstr
|
(bx+wordExcess).uint32 shl 16'u32).TInstr
|
||||||
c.code.add(ins)
|
c.code.add(ins)
|
||||||
c.debug.add(n.info)
|
c.debug.add(n.info)
|
||||||
|
|
@ -174,7 +174,7 @@ proc getTemp(c: PCtx; typ: PType): TRegister =
|
||||||
if c.slots[i].kind == k and not c.slots[i].inUse:
|
if c.slots[i].kind == k and not c.slots[i].inUse:
|
||||||
c.slots[i].inUse = true
|
c.slots[i].inUse = true
|
||||||
return TRegister(i)
|
return TRegister(i)
|
||||||
|
|
||||||
# if register pressure is high, we re-use more aggressively:
|
# if register pressure is high, we re-use more aggressively:
|
||||||
if c.maxSlots >= HighRegisterPressure:
|
if c.maxSlots >= HighRegisterPressure:
|
||||||
for i in 0 .. c.maxSlots-1:
|
for i in 0 .. c.maxSlots-1:
|
||||||
|
|
@ -208,7 +208,7 @@ proc getTempRange(c: PCtx; n: int; kind: TSlotKind): TRegister =
|
||||||
result = TRegister(c.maxSlots)
|
result = TRegister(c.maxSlots)
|
||||||
inc c.maxSlots, n
|
inc c.maxSlots, n
|
||||||
for k in result .. result+n-1: c.slots[k] = (inUse: true, kind: kind)
|
for k in result .. result+n-1: c.slots[k] = (inUse: true, kind: kind)
|
||||||
|
|
||||||
proc freeTempRange(c: PCtx; start: TRegister, n: int) =
|
proc freeTempRange(c: PCtx; start: TRegister, n: int) =
|
||||||
for i in start .. start+n-1: c.freeTemp(TRegister(i))
|
for i in start .. start+n-1: c.freeTemp(TRegister(i))
|
||||||
|
|
||||||
|
|
@ -217,7 +217,7 @@ template withTemp(tmp, typ: expr, body: stmt) {.immediate, dirty.} =
|
||||||
body
|
body
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
|
|
||||||
proc popBlock(c: PCtx; oldLen: int) =
|
proc popBlock(c: PCtx; oldLen: int) =
|
||||||
for f in c.prc.blocks[oldLen].fixups:
|
for f in c.prc.blocks[oldLen].fixups:
|
||||||
c.patch(f)
|
c.patch(f)
|
||||||
c.prc.blocks.setLen(oldLen)
|
c.prc.blocks.setLen(oldLen)
|
||||||
|
|
@ -386,7 +386,7 @@ proc genLiteral(c: PCtx; n: PNode): int =
|
||||||
result = rawGenLiteral(c, n)
|
result = rawGenLiteral(c, n)
|
||||||
|
|
||||||
proc unused(n: PNode; x: TDest) {.inline.} =
|
proc unused(n: PNode; x: TDest) {.inline.} =
|
||||||
if x >= 0:
|
if x >= 0:
|
||||||
#debug(n)
|
#debug(n)
|
||||||
internalError(n.info, "not unused")
|
internalError(n.info, "not unused")
|
||||||
|
|
||||||
|
|
@ -446,11 +446,11 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
var blen = len(it)
|
var blen = len(it)
|
||||||
# first opcExcept contains the end label of the 'except' block:
|
# first opcExcept contains the end label of the 'except' block:
|
||||||
let endExcept = c.xjmp(it, opcExcept, 0)
|
let endExcept = c.xjmp(it, opcExcept, 0)
|
||||||
for j in countup(0, blen - 2):
|
for j in countup(0, blen - 2):
|
||||||
assert(it.sons[j].kind == nkType)
|
assert(it.sons[j].kind == nkType)
|
||||||
let typ = it.sons[j].typ.skipTypes(abstractPtrs-{tyTypeDesc})
|
let typ = it.sons[j].typ.skipTypes(abstractPtrs-{tyTypeDesc})
|
||||||
c.gABx(it, opcExcept, 0, c.genType(typ))
|
c.gABx(it, opcExcept, 0, c.genType(typ))
|
||||||
if blen == 1:
|
if blen == 1:
|
||||||
# general except section:
|
# general except section:
|
||||||
c.gABx(it, opcExcept, 0, 0)
|
c.gABx(it, opcExcept, 0, 0)
|
||||||
c.gen(it.lastSon, dest)
|
c.gen(it.lastSon, dest)
|
||||||
|
|
@ -498,7 +498,7 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
|
template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
|
||||||
proc isGlobal(n: PNode): bool = n.kind == nkSym and isGlobal(n.sym)
|
proc isGlobal(n: PNode): bool = n.kind == nkSym and isGlobal(n.sym)
|
||||||
|
|
||||||
proc needsAsgnPatch(n: PNode): bool =
|
proc needsAsgnPatch(n: PNode): bool =
|
||||||
n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr,
|
n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr,
|
||||||
nkDerefExpr, nkHiddenDeref} or (n.kind == nkSym and n.sym.isGlobal)
|
nkDerefExpr, nkHiddenDeref} or (n.kind == nkSym and n.sym.isGlobal)
|
||||||
|
|
||||||
|
|
@ -552,9 +552,9 @@ proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
|
||||||
proc genNew(c: PCtx; n: PNode) =
|
proc genNew(c: PCtx; n: PNode) =
|
||||||
let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(n.sons[1].typ)
|
let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(n.sons[1].typ)
|
||||||
else: c.genx(n.sons[1])
|
else: c.genx(n.sons[1])
|
||||||
# we use the ref's base type here as the VM conflates 'ref object'
|
# we use the ref's base type here as the VM conflates 'ref object'
|
||||||
# and 'object' since internally we already have a pointer.
|
# and 'object' since internally we already have a pointer.
|
||||||
c.gABx(n, opcNew, dest,
|
c.gABx(n, opcNew, dest,
|
||||||
c.genType(n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).sons[0]))
|
c.genType(n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).sons[0]))
|
||||||
c.genAsgnPatch(n.sons[1], dest)
|
c.genAsgnPatch(n.sons[1], dest)
|
||||||
c.freeTemp(dest)
|
c.freeTemp(dest)
|
||||||
|
|
@ -657,7 +657,7 @@ proc genUnaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
|
||||||
proc genVarargsABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
|
proc genVarargsABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
|
||||||
if dest < 0: dest = getTemp(c, n.typ)
|
if dest < 0: dest = getTemp(c, n.typ)
|
||||||
var x = c.getTempRange(n.len-1, slotTempStr)
|
var x = c.getTempRange(n.len-1, slotTempStr)
|
||||||
for i in 1..n.len-1:
|
for i in 1..n.len-1:
|
||||||
var r: TRegister = x+i-1
|
var r: TRegister = x+i-1
|
||||||
c.gen(n.sons[i], r)
|
c.gen(n.sons[i], r)
|
||||||
c.gABC(n, opc, dest, x, n.len-1)
|
c.gABC(n, opc, dest, x, n.len-1)
|
||||||
|
|
@ -681,7 +681,7 @@ proc genAddSubInt(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
|
||||||
genBinaryABC(c, n, dest, opc)
|
genBinaryABC(c, n, dest, opc)
|
||||||
c.genNarrow(n, dest)
|
c.genNarrow(n, dest)
|
||||||
|
|
||||||
proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
|
proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
|
||||||
let tmp = c.genx(arg)
|
let tmp = c.genx(arg)
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
c.gABC(n, opc, dest, tmp)
|
c.gABC(n, opc, dest, tmp)
|
||||||
|
|
@ -792,12 +792,12 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
genNarrow(c, n, dest)
|
genNarrow(c, n, dest)
|
||||||
of mUnaryMinusF64: genUnaryABC(c, n, dest, opcUnaryMinusFloat)
|
of mUnaryMinusF64: genUnaryABC(c, n, dest, opcUnaryMinusFloat)
|
||||||
of mUnaryPlusI, mUnaryPlusI64, mUnaryPlusF64: gen(c, n.sons[1], dest)
|
of mUnaryPlusI, mUnaryPlusI64, mUnaryPlusF64: gen(c, n.sons[1], dest)
|
||||||
of mBitnotI, mBitnotI64:
|
of mBitnotI, mBitnotI64:
|
||||||
genUnaryABC(c, n, dest, opcBitnotInt)
|
genUnaryABC(c, n, dest, opcBitnotInt)
|
||||||
genNarrowU(c, n, dest)
|
genNarrowU(c, n, dest)
|
||||||
of mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64,
|
of mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64,
|
||||||
mToU8, mToU16, mToU32, mToFloat, mToBiggestFloat, mToInt,
|
mToU8, mToU16, mToU32, mToFloat, mToBiggestFloat, mToInt,
|
||||||
mToBiggestInt, mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr,
|
mToBiggestInt, mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr,
|
||||||
mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr:
|
mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr:
|
||||||
genConv(c, n, n.sons[1], dest)
|
genConv(c, n, n.sons[1], dest)
|
||||||
of mEqStr: genBinaryABC(c, n, dest, opcEqStr)
|
of mEqStr: genBinaryABC(c, n, dest, opcEqStr)
|
||||||
|
|
@ -825,7 +825,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
c.gABC(n, if m == mSetLengthStr: opcSetLenStr else: opcSetLenSeq, d, tmp)
|
c.gABC(n, if m == mSetLengthStr: opcSetLenStr else: opcSetLenSeq, d, tmp)
|
||||||
c.genAsgnPatch(n.sons[1], d)
|
c.genAsgnPatch(n.sons[1], d)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
of mSwap:
|
of mSwap:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
var
|
var
|
||||||
d1 = c.genx(n.sons[1])
|
d1 = c.genx(n.sons[1])
|
||||||
|
|
@ -874,7 +874,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
c.freeTemp(tmp1)
|
c.freeTemp(tmp1)
|
||||||
c.freeTemp(tmp3)
|
c.freeTemp(tmp3)
|
||||||
c.genAsgnPatch(d2AsNode, d2)
|
c.genAsgnPatch(d2AsNode, d2)
|
||||||
c.freeTemp(d2)
|
c.freeTemp(d2)
|
||||||
of mReset:
|
of mReset:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
var d = c.genx(n.sons[1])
|
var d = c.genx(n.sons[1])
|
||||||
|
|
@ -913,7 +913,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
of mAppendStrCh:
|
of mAppendStrCh:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
genBinaryStmtVar(c, n, opcAddStrCh)
|
genBinaryStmtVar(c, n, opcAddStrCh)
|
||||||
of mAppendStrStr:
|
of mAppendStrStr:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
genBinaryStmtVar(c, n, opcAddStrStr)
|
genBinaryStmtVar(c, n, opcAddStrStr)
|
||||||
of mAppendSeqElem:
|
of mAppendSeqElem:
|
||||||
|
|
@ -923,7 +923,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
genUnaryABC(c, n, dest, opcParseExprToAst)
|
genUnaryABC(c, n, dest, opcParseExprToAst)
|
||||||
of mParseStmtToAst:
|
of mParseStmtToAst:
|
||||||
genUnaryABC(c, n, dest, opcParseStmtToAst)
|
genUnaryABC(c, n, dest, opcParseStmtToAst)
|
||||||
of mTypeTrait:
|
of mTypeTrait:
|
||||||
let tmp = c.genx(n.sons[1])
|
let tmp = c.genx(n.sons[1])
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
c.gABx(n, opcSetType, tmp, c.genType(n.sons[1].typ))
|
c.gABx(n, opcSetType, tmp, c.genType(n.sons[1].typ))
|
||||||
|
|
@ -960,19 +960,19 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
of mNSetIntVal:
|
of mNSetIntVal:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
genBinaryStmt(c, n, opcNSetIntVal)
|
genBinaryStmt(c, n, opcNSetIntVal)
|
||||||
of mNSetFloatVal:
|
of mNSetFloatVal:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
genBinaryStmt(c, n, opcNSetFloatVal)
|
genBinaryStmt(c, n, opcNSetFloatVal)
|
||||||
of mNSetSymbol:
|
of mNSetSymbol:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
genBinaryStmt(c, n, opcNSetSymbol)
|
genBinaryStmt(c, n, opcNSetSymbol)
|
||||||
of mNSetIdent:
|
of mNSetIdent:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
genBinaryStmt(c, n, opcNSetIdent)
|
genBinaryStmt(c, n, opcNSetIdent)
|
||||||
of mNSetType:
|
of mNSetType:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
genBinaryStmt(c, n, opcNSetType)
|
genBinaryStmt(c, n, opcNSetType)
|
||||||
of mNSetStrVal:
|
of mNSetStrVal:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
genBinaryStmt(c, n, opcNSetStrVal)
|
genBinaryStmt(c, n, opcNSetStrVal)
|
||||||
of mNNewNimNode: genBinaryABC(c, n, dest, opcNNewNimNode)
|
of mNNewNimNode: genBinaryABC(c, n, dest, opcNNewNimNode)
|
||||||
|
|
@ -990,10 +990,10 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent)
|
of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent)
|
||||||
of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimrodNode)
|
of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimrodNode)
|
||||||
of mNLineInfo: genUnaryABC(c, n, dest, opcNLineInfo)
|
of mNLineInfo: genUnaryABC(c, n, dest, opcNLineInfo)
|
||||||
of mNHint:
|
of mNHint:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
genUnaryStmt(c, n, opcNHint)
|
genUnaryStmt(c, n, opcNHint)
|
||||||
of mNWarning:
|
of mNWarning:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
genUnaryStmt(c, n, opcNWarning)
|
genUnaryStmt(c, n, opcNWarning)
|
||||||
of mNError:
|
of mNError:
|
||||||
|
|
@ -1024,7 +1024,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
else:
|
else:
|
||||||
globalError(n.info, "expandToAst requires a call expression")
|
globalError(n.info, "expandToAst requires a call expression")
|
||||||
else:
|
else:
|
||||||
# mGCref, mGCunref,
|
# mGCref, mGCunref,
|
||||||
internalError(n.info, "cannot generate code for: " & $m)
|
internalError(n.info, "cannot generate code for: " & $m)
|
||||||
|
|
||||||
const
|
const
|
||||||
|
|
@ -1056,7 +1056,7 @@ proc unneededIndirection(n: PNode): bool =
|
||||||
n.typ.skipTypes(abstractInst-{tyTypeDesc}).kind == tyRef
|
n.typ.skipTypes(abstractInst-{tyTypeDesc}).kind == tyRef
|
||||||
|
|
||||||
proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
|
proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
|
||||||
flags: TGenFlags) =
|
flags: TGenFlags) =
|
||||||
# a nop for certain types
|
# a nop for certain types
|
||||||
let isAddr = opc in {opcAddrNode, opcAddrReg}
|
let isAddr = opc in {opcAddrNode, opcAddrReg}
|
||||||
let newflags = if isAddr: flags+{gfAddrOf} else: flags
|
let newflags = if isAddr: flags+{gfAddrOf} else: flags
|
||||||
|
|
@ -1144,7 +1144,7 @@ proc checkCanEval(c: PCtx; n: PNode) =
|
||||||
# proc foo() = var x ...
|
# proc foo() = var x ...
|
||||||
let s = n.sym
|
let s = n.sym
|
||||||
if {sfCompileTime, sfGlobal} <= s.flags: return
|
if {sfCompileTime, sfGlobal} <= s.flags: return
|
||||||
if s.kind in {skVar, skTemp, skLet, skParam, skResult} and
|
if s.kind in {skVar, skTemp, skLet, skParam, skResult} and
|
||||||
not s.isOwnedBy(c.prc.sym) and s.owner != c.module:
|
not s.isOwnedBy(c.prc.sym) and s.owner != c.module:
|
||||||
cannotEval(n)
|
cannotEval(n)
|
||||||
|
|
||||||
|
|
@ -1338,27 +1338,27 @@ proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||||
else:
|
else:
|
||||||
genArrAccess2(c, n, dest, opcLdArr, flags)
|
genArrAccess2(c, n, dest, opcLdArr, flags)
|
||||||
|
|
||||||
proc getNullValueAux(obj: PNode, result: PNode) =
|
proc getNullValueAux(obj: PNode, result: PNode) =
|
||||||
case obj.kind
|
case obj.kind
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
for i in countup(0, sonsLen(obj) - 1): getNullValueAux(obj.sons[i], result)
|
for i in countup(0, sonsLen(obj) - 1): getNullValueAux(obj.sons[i], result)
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
getNullValueAux(obj.sons[0], result)
|
getNullValueAux(obj.sons[0], result)
|
||||||
for i in countup(1, sonsLen(obj) - 1):
|
for i in countup(1, sonsLen(obj) - 1):
|
||||||
getNullValueAux(lastSon(obj.sons[i]), result)
|
getNullValueAux(lastSon(obj.sons[i]), result)
|
||||||
of nkSym:
|
of nkSym:
|
||||||
addSon(result, getNullValue(obj.sym.typ, result.info))
|
addSon(result, getNullValue(obj.sym.typ, result.info))
|
||||||
else: internalError(result.info, "getNullValueAux")
|
else: internalError(result.info, "getNullValueAux")
|
||||||
|
|
||||||
proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
var t = skipTypes(typ, abstractRange-{tyTypeDesc})
|
var t = skipTypes(typ, abstractRange-{tyTypeDesc})
|
||||||
result = emptyNode
|
result = emptyNode
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyBool, tyEnum, tyChar, tyInt..tyInt64:
|
of tyBool, tyEnum, tyChar, tyInt..tyInt64:
|
||||||
result = newNodeIT(nkIntLit, info, t)
|
result = newNodeIT(nkIntLit, info, t)
|
||||||
of tyUInt..tyUInt64:
|
of tyUInt..tyUInt64:
|
||||||
result = newNodeIT(nkUIntLit, info, t)
|
result = newNodeIT(nkUIntLit, info, t)
|
||||||
of tyFloat..tyFloat128:
|
of tyFloat..tyFloat128:
|
||||||
result = newNodeIT(nkFloatLit, info, t)
|
result = newNodeIT(nkFloatLit, info, t)
|
||||||
of tyCString, tyString:
|
of tyCString, tyString:
|
||||||
result = newNodeIT(nkStrLit, info, t)
|
result = newNodeIT(nkStrLit, info, t)
|
||||||
|
|
@ -1372,7 +1372,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
result = newNodeIT(nkPar, info, t)
|
result = newNodeIT(nkPar, info, t)
|
||||||
result.add(newNodeIT(nkNilLit, info, t))
|
result.add(newNodeIT(nkNilLit, info, t))
|
||||||
result.add(newNodeIT(nkNilLit, info, t))
|
result.add(newNodeIT(nkNilLit, info, t))
|
||||||
of tyObject:
|
of tyObject:
|
||||||
result = newNodeIT(nkPar, info, t)
|
result = newNodeIT(nkPar, info, t)
|
||||||
getNullValueAux(t.n, result)
|
getNullValueAux(t.n, result)
|
||||||
# initialize inherited fields:
|
# initialize inherited fields:
|
||||||
|
|
@ -1380,9 +1380,9 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
while base != nil:
|
while base != nil:
|
||||||
getNullValueAux(skipTypes(base, skipPtrs).n, result)
|
getNullValueAux(skipTypes(base, skipPtrs).n, result)
|
||||||
base = base.sons[0]
|
base = base.sons[0]
|
||||||
of tyArray, tyArrayConstr:
|
of tyArray, tyArrayConstr:
|
||||||
result = newNodeIT(nkBracket, info, t)
|
result = newNodeIT(nkBracket, info, t)
|
||||||
for i in countup(0, int(lengthOrd(t)) - 1):
|
for i in countup(0, int(lengthOrd(t)) - 1):
|
||||||
addSon(result, getNullValue(elemType(t), info))
|
addSon(result, getNullValue(elemType(t), info))
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
result = newNodeIT(nkPar, info, t)
|
result = newNodeIT(nkPar, info, t)
|
||||||
|
|
@ -1459,7 +1459,7 @@ proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||||
c.gABx(n, opcNewSeq, dest, c.genType(seqType))
|
c.gABx(n, opcNewSeq, dest, c.genType(seqType))
|
||||||
c.gABx(n, opcNewSeq, tmp, 0)
|
c.gABx(n, opcNewSeq, tmp, 0)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
|
|
||||||
if n.len > 0:
|
if n.len > 0:
|
||||||
var tmp = getTemp(c, intType)
|
var tmp = getTemp(c, intType)
|
||||||
c.gABx(n, opcLdNullReg, tmp, c.genType(intType))
|
c.gABx(n, opcLdNullReg, tmp, c.genType(intType))
|
||||||
|
|
@ -1536,7 +1536,7 @@ proc procIsCallback(c: PCtx; s: PSym): bool =
|
||||||
if s.offset < -1: return true
|
if s.offset < -1: return true
|
||||||
var i = -2
|
var i = -2
|
||||||
for key, value in items(c.callbacks):
|
for key, value in items(c.callbacks):
|
||||||
if s.matches(key):
|
if s.matches(key):
|
||||||
doAssert s.offset == -1
|
doAssert s.offset == -1
|
||||||
s.offset = i
|
s.offset = i
|
||||||
return true
|
return true
|
||||||
|
|
@ -1584,7 +1584,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||||
of nkNilLit:
|
of nkNilLit:
|
||||||
if not n.typ.isEmptyType: genLit(c, getNullValue(n.typ, n.info), dest)
|
if not n.typ.isEmptyType: genLit(c, getNullValue(n.typ, n.info), dest)
|
||||||
else: unused(n, dest)
|
else: unused(n, dest)
|
||||||
of nkAsgn, nkFastAsgn:
|
of nkAsgn, nkFastAsgn:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
genAsgn(c, n.sons[0], n.sons[1], n.kind == nkAsgn)
|
genAsgn(c, n.sons[0], n.sons[1], n.kind == nkAsgn)
|
||||||
of nkDotExpr: genObjAccess(c, n, dest, flags)
|
of nkDotExpr: genObjAccess(c, n, dest, flags)
|
||||||
|
|
@ -1633,7 +1633,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||||
let s = n.sons[namePos].sym
|
let s = n.sons[namePos].sym
|
||||||
discard genProc(c, s)
|
discard genProc(c, s)
|
||||||
genLit(c, n.sons[namePos], dest)
|
genLit(c, n.sons[namePos], dest)
|
||||||
of nkChckRangeF, nkChckRange64, nkChckRange:
|
of nkChckRangeF, nkChckRange64, nkChckRange:
|
||||||
let
|
let
|
||||||
tmp0 = c.genx(n.sons[0])
|
tmp0 = c.genx(n.sons[0])
|
||||||
tmp1 = c.genx(n.sons[1])
|
tmp1 = c.genx(n.sons[1])
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ e
|
||||||
s
|
s
|
||||||
t
|
t
|
||||||
'''
|
'''
|
||||||
|
disabled: "true"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
template accept(e: expr) =
|
template accept(e: expr) =
|
||||||
|
|
@ -3,6 +3,7 @@ discard """
|
||||||
[1, 3]
|
[1, 3]
|
||||||
[2, 1, 2]
|
[2, 1, 2]
|
||||||
'''
|
'''
|
||||||
|
disabled: "true"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import macros, strutils
|
import macros, strutils
|
||||||
|
|
@ -18,14 +19,14 @@ proc swizzleIdx(c: char): int =
|
||||||
of 'x': 0
|
of 'x': 0
|
||||||
of 'y': 1
|
of 'y': 1
|
||||||
of 'z': 2
|
of 'z': 2
|
||||||
of 'w': 3
|
of 'w': 3
|
||||||
of 'r': 0
|
of 'r': 0
|
||||||
of 'g': 1
|
of 'g': 1
|
||||||
of 'b': 2
|
of 'b': 2
|
||||||
of 'a': 3
|
of 'a': 3
|
||||||
else: 0
|
else: 0
|
||||||
|
|
||||||
proc isSwizzle(s: string): bool =
|
proc isSwizzle(s: string): bool {.compileTime.} =
|
||||||
template trySet(name, set) =
|
template trySet(name, set) =
|
||||||
block search:
|
block search:
|
||||||
for c in s:
|
for c in s:
|
||||||
|
|
@ -35,10 +36,10 @@ proc isSwizzle(s: string): bool =
|
||||||
|
|
||||||
trySet coords, {'x', 'y', 'z', 'w'}
|
trySet coords, {'x', 'y', 'z', 'w'}
|
||||||
trySet colors, {'r', 'g', 'b', 'a'}
|
trySet colors, {'r', 'g', 'b', 'a'}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|
||||||
type
|
type
|
||||||
StringIsSwizzle = generic value
|
StringIsSwizzle = generic value
|
||||||
value.isSwizzle
|
value.isSwizzle
|
||||||
|
|
||||||
|
|
@ -47,33 +48,33 @@ type
|
||||||
proc foo(x: SwizzleStr) =
|
proc foo(x: SwizzleStr) =
|
||||||
echo "sw"
|
echo "sw"
|
||||||
|
|
||||||
accept foo("xx")
|
#foo("xx")
|
||||||
reject foo("xe")
|
reject foo("xe")
|
||||||
|
|
||||||
type
|
type
|
||||||
Vec[N: static[int]; T] = array[N, T]
|
Vec[N: static[int]; T] = array[N, T]
|
||||||
|
|
||||||
|
when false:
|
||||||
|
proc card(x: Vec): int = x.N
|
||||||
|
proc `$`(x: Vec): string = x.repr.strip
|
||||||
|
|
||||||
proc card(x: Vec): int = x.N
|
macro `.`(x: Vec, swizzle: SwizzleStr): expr =
|
||||||
proc `$`(x: Vec): string = x.repr.strip
|
var
|
||||||
|
cardinality = swizzle.len
|
||||||
|
values = newNimNode(nnkBracket)
|
||||||
|
v = genSym()
|
||||||
|
|
||||||
macro `.`(x: Vec, swizzle: SwizzleStr): expr =
|
for c in swizzle:
|
||||||
var
|
values.add newNimNode(nnkBracketExpr).add(
|
||||||
cardinality = swizzle.len
|
v, c.swizzleIdx.newIntLitNode)
|
||||||
values = newNimNode(nnkBracket)
|
|
||||||
v = genSym()
|
|
||||||
|
|
||||||
for c in swizzle:
|
return quote do:
|
||||||
values.add newNimNode(nnkBracketExpr).add(
|
let `v` = `x`
|
||||||
v, c.swizzleIdx.newIntLitNode)
|
Vec[`cardinality`, `v`.T](`values`)
|
||||||
|
|
||||||
return quote do:
|
|
||||||
let `v` = `x`
|
|
||||||
Vec[`cardinality`, `v`.T](`values`)
|
|
||||||
|
|
||||||
var z = Vec([1, 2, 3])
|
var z = Vec([1, 2, 3])
|
||||||
|
|
||||||
echo z.card
|
#echo z.card
|
||||||
echo z.xz
|
#echo z.xz
|
||||||
echo z.yxy
|
#echo z.yxy
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue