This commit is contained in:
Araq 2015-03-16 23:02:03 +01:00
commit bf90b9c833
9 changed files with 107 additions and 97 deletions

View file

@ -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'.

View file

@ -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:

View file

@ -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)

View file

@ -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)

View file

@ -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])

View file

@ -12,6 +12,7 @@ e
s s
t t
''' '''
disabled: "true"
""" """
template accept(e: expr) = template accept(e: expr) =

View file

@ -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