Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Static[T] fixes #7333

Merged
merged 8 commits into from
Mar 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,7 @@ const

nkPragmaCallKinds* = {nkExprColonExpr, nkCall, nkCallStrLit}
nkLiterals* = {nkCharLit..nkTripleStrLit}
nkFloatLiterals* = {nkFloatLit..nkFloat128Lit}
nkLambdaKinds* = {nkLambda, nkDo}
declarativeDefs* = {nkProcDef, nkFuncDef, nkMethodDef, nkIteratorDef, nkConverterDef}
procDefs* = nkLambdaKinds + declarativeDefs
Expand Down Expand Up @@ -1476,7 +1477,7 @@ proc copyNode*(src: PNode): PNode =
echo "COMES FROM ", src.id
case src.kind
of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
of nkFloatLiterals: result.floatVal = src.floatVal
of nkSym: result.sym = src.sym
of nkIdent: result.ident = src.ident
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
Expand All @@ -1495,7 +1496,7 @@ proc shallowCopy*(src: PNode): PNode =
echo "COMES FROM ", src.id
case src.kind
of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
of nkFloatLiterals: result.floatVal = src.floatVal
of nkSym: result.sym = src.sym
of nkIdent: result.ident = src.ident
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
Expand All @@ -1515,7 +1516,7 @@ proc copyTree*(src: PNode): PNode =
echo "COMES FROM ", src.id
case src.kind
of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
of nkFloatLiterals: result.floatVal = src.floatVal
of nkSym: result.sym = src.sym
of nkIdent: result.ident = src.ident
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
Expand Down Expand Up @@ -1564,7 +1565,7 @@ proc getInt*(a: PNode): BiggestInt =

proc getFloat*(a: PNode): BiggestFloat =
case a.kind
of nkFloatLit..nkFloat128Lit: result = a.floatVal
of nkFloatLiterals: result = a.floatVal
else:
internalError(a.info, "getFloat")
result = 0.0
Expand Down
7 changes: 7 additions & 0 deletions compiler/ccgtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,13 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
# always call for sideeffects:
assert t.kind != tyTuple
discard getRecordDesc(m, t, result, check)
# The resulting type will include commas and these won't play well
# with the C macros for defining procs such as N_NIMCALL. We must
# create a typedef for the type and use it in the proc signature:
let typedefName = ~"TY" & $sig
addf(m.s[cfsTypes], "typedef $1 $2;$n", [result, typedefName])
m.typeCache[sig] = typedefName
result = typedefName
else:
when false:
if t.sym != nil and t.sym.name.s == "KeyValuePair":
Expand Down
3 changes: 2 additions & 1 deletion compiler/lookups.nim
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ proc considerQuotedIdent*(n: PNode, origin: PNode = nil): PIdent =
case x.kind
of nkIdent: id.add(x.ident.s)
of nkSym: id.add(x.sym.name.s)
of nkLiterals - nkFloatLiterals: id.add(x.renderTree)
else: handleError(n, origin)
result = getIdent(id)
of nkOpenSymChoice, nkClosedSymChoice:
Expand Down Expand Up @@ -456,4 +457,4 @@ proc pickSym*(c: PContext, n: PNode; kinds: set[TSymKind];
a = nextOverloadIter(o, c, n)

proc isInfixAs*(n: PNode): bool =
return n.kind == nkInfix and considerQuotedIdent(n[0]).s == "as"
return n.kind == nkInfix and considerQuotedIdent(n[0]).s == "as"
40 changes: 34 additions & 6 deletions compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,9 @@ const

proc readTypeParameter(c: PContext, typ: PType,
paramName: PIdent, info: TLineInfo): PNode =
# Note: This function will return emptyNode when attempting to read
# a static type parameter that is not yet resolved (e.g. this may
# happen in proc signatures such as `proc(x: T): array[T.sizeParam, U]`
if typ.kind in {tyUserTypeClass, tyUserTypeClassInst}:
for statement in typ.n:
case statement.kind
Expand Down Expand Up @@ -910,7 +913,10 @@ proc readTypeParameter(c: PContext, typ: PType,
if tParam.sym.name.id == paramName.id:
let rawTyp = ty.sons[s + 1]
if rawTyp.kind == tyStatic:
return rawTyp.n
if rawTyp.n != nil:
return rawTyp.n
else:
return emptyNode
else:
let foundTyp = makeTypeDesc(c, rawTyp)
return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
Expand Down Expand Up @@ -1075,21 +1081,43 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
template tryReadingGenericParam(t: PType) =
case t.kind
of tyTypeParamsHolders:
return readTypeParameter(c, t, i, n.info)
result = readTypeParameter(c, t, i, n.info)
if result == emptyNode:
result = n
n.typ = makeTypeFromExpr(c, n.copyTree)
return
of tyUserTypeClasses:
if t.isResolvedUserTypeClass:
return readTypeParameter(c, t, i, n.info)
else:
n.typ = makeTypeFromExpr(c, copyTree(n))
return n
of tyGenericParam:
of tyGenericParam, tyAnything:
n.typ = makeTypeFromExpr(c, copyTree(n))
return n
else:
discard

if isTypeExpr(n.sons[0]) or (ty.kind == tyTypeDesc and ty.base.kind != tyNone):
if ty.kind == tyTypeDesc: ty = ty.base
var argIsType = false

if ty.kind == tyTypeDesc:
if ty.base.kind == tyNone:
# This is a still unresolved typedesc parameter.
# If this is a regular proc, then all bets are off and we must return
# tyFromExpr, but when this happen in a macro this is not a built-in
# field access and we leave the compiler to compile a normal call:
if getCurrOwner(c).kind != skMacro:
n.typ = makeTypeFromExpr(c, n.copyTree)
return n
else:
return nil
else:
ty = ty.base
argIsType = true
else:
argIsType = isTypeExpr(n.sons[0])

if argIsType:
ty = ty.skipTypes(tyDotOpTransparent)
case ty.kind
of tyEnum:
Expand Down Expand Up @@ -2172,7 +2200,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
# because of the changed symbol binding, this does not mean that we
# don't have to check the symbol for semantics here again!
result = semSym(c, n, n.sym, flags)
of nkEmpty, nkNone, nkCommentStmt:
of nkEmpty, nkNone, nkCommentStmt, nkType:
discard
of nkNilLit:
if result.typ == nil: result.typ = getSysType(tyNil)
Expand Down
30 changes: 30 additions & 0 deletions compiler/seminst.nim
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ proc sideEffectsCheck(c: PContext, s: PSym) =

proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
allowMetaTypes = false): PType =
internalAssert header.kind == tyGenericInvocation

var
typeMap: LayeredIdTable
cl: TReplTypeVars
Expand All @@ -185,7 +187,35 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
cl.info = info
cl.c = c
cl.allowMetaTypes = allowMetaTypes

# We must add all generic params in scope, because the generic body
# may include tyFromExpr nodes depending on these generic params.
# XXX: This looks quite similar to the code in matchUserTypeClass,
# perhaps the code can be extracted in a shared function.
openScope(c)
let genericTyp = header.base
for i in 0 .. (genericTyp.len - 2):
let genParam = genericTyp[i]
var param: PSym

template paramSym(kind): untyped =
newSym(kind, genParam.sym.name, genericTyp.sym, genParam.sym.info)

if genParam.kind == tyStatic:
param = paramSym skConst
param.ast = header[i+1].n
param.typ = header[i+1]
else:
param = paramSym skType
param.typ = makeTypeDesc(c, header[i+1])

# this scope was not created by the user,
# unused params shoudn't be reported.
param.flags.incl sfUsed
addDecl(c, param)

result = replaceTypeVarsT(cl, header)
closeScope(c)

proc instantiateProcType(c: PContext, pt: TIdTable,
prc: PSym, info: TLineInfo) =
Expand Down
5 changes: 4 additions & 1 deletion compiler/semtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1396,7 +1396,10 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
fixupTypeOf(c, prev, typExpr)
result = typExpr.typ
else:
result = semTypeExpr(c, n, prev)
if c.inGenericContext > 0 and n.kind == nkCall:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is only nkCall checked here and not all call kinds?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fix turned out to be a bit tricky, due to some tricks involving the use of types and operators (as in the T -> U syntax from module for example). That's why I avoid the handling of such operators here.

All in all, I'm not particularly happy with this broad application of tyFromExpr and my first attempt was to try to introduce more logic in the compiler allowing unresolved statics to pass-through sem without executing the macros where they are used as arguments, but this turned out to be quite involved. We still need a lot of work on enabling implicit statics by default and I think these developments will allow for a nicer solution in the future.

result = makeTypeFromExpr(c, n.copyTree)
else:
result = semTypeExpr(c, n, prev)
of nkWhenStmt:
var whenResult = semWhen(c, n, false)
if whenResult.kind == nkStmtList: whenResult.kind = nkStmtListType
Expand Down
4 changes: 4 additions & 0 deletions compiler/semtypinst.nim
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,10 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =

of tyFromExpr:
if cl.allowMetaTypes: return
# This assert is triggered when a tyFromExpr was created in a cyclic
# way. You should break the cycle at the point of creation by introducing
# a call such as: `n.typ = makeTypeFromExpr(c, n.copyTree)`
# Otherwise, the cycle will be fatal for the prepareNode call below
assert t.n.typ != t
var n = prepareNode(cl, t.n)
if n.kind != nkEmpty:
Expand Down
2 changes: 1 addition & 1 deletion compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1883,7 +1883,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
return arg
elif f.kind == tyTypeDesc:
return arg
elif f.kind == tyStatic:
elif f.kind == tyStatic and arg.typ.n != nil:
return arg.typ.n
else:
return argSemantized # argOrig
Expand Down
2 changes: 2 additions & 0 deletions compiler/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1136,6 +1136,8 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
of tyTypeClasses:
if tfGenericTypeParam in t.flags or taConcept in flags: #or taField notin flags:
discard
elif t.isResolvedUserTypeClass:
result = typeAllowedAux(marker, t.lastSon, kind, flags)
elif kind notin {skParam, skResult}:
result = t
of tyGenericBody, tyGenericParam, tyGenericInvocation,
Expand Down
19 changes: 19 additions & 0 deletions tests/concepts/tseqofconcept.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
discard """
output: "1\n2\n3"
"""

type
MyConcept = concept x
someProc(x)

SomeSeq = seq[MyConcept]

proc someProc(x:int) = echo x

proc work (s: SomeSeq) =
for item in s:
someProc item

var s = @[1, 2, 3]
work s

2 changes: 1 addition & 1 deletion tests/cpp/tcovariancerules.nim
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ reject wantsVarPointer2(pcat)

# covariance may be allowed for certain extern types

{.emit: """
{.emit: """/*TYPESECTION*/
template <class T> struct FN { typedef void (*type)(T); };
template <class T> struct ARR { typedef T DataType[2]; DataType data; };
""".}
Expand Down
2 changes: 1 addition & 1 deletion tests/cpp/tvector_iterator.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ discard """
targets: "cpp"
"""

{.emit: """
{.emit: """/*TYPESECTION*/

template <class T>
struct Vector {
Expand Down
13 changes: 7 additions & 6 deletions tests/metatype/tstaticparammacro.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ AST b
20Test
20
'''
disabled: true
"""

import macros
Expand All @@ -26,7 +25,7 @@ type

const data: Tconfig = (@["aa", "bb"], @[11, 22])

macro mymacro(data: static[TConfig]) =
macro mymacro(data: static[TConfig]): untyped =
echo "letters"
for s in items(data.letters):
echo s
Expand All @@ -44,10 +43,10 @@ const
a : Ta = @[(11, 22), (33, 44)]
b : Tb = (@[55,66], @[77, 88])

macro mA(data: static[Ta]) =
macro mA(data: static[Ta]): untyped =
echo "AST a \n", repr(data)

macro mB(data: static[Tb]) =
macro mB(data: static[Tb]): untyped =
echo "AST b \n", repr(data)
echo data.e[0]

Expand All @@ -57,13 +56,15 @@ mB(b)
type
Foo[N: static[int], Z: static[string]] = object

macro staticIntMacro(f: static[int]) = echo f
macro staticIntMacro(f: static[int]): untyped =
echo f

staticIntMacro 10

var
x: Foo[20, "Test"]

macro genericMacro[N; Z: static[string]](f: Foo[N, Z], ll = 3, zz = 12) =
macro genericMacro[N; Z: static[string]](f: Foo[N, Z], ll = 3, zz = 12): untyped =
echo N, Z

genericMacro x
Expand Down
Loading