introduce tyFromExpr; fixes #618
This commit is contained in:
parent
02533c260b
commit
789ba107cf
13 changed files with 109 additions and 28 deletions
|
|
@ -339,19 +339,31 @@ type
|
||||||
tyTypeClass
|
tyTypeClass
|
||||||
tyParametricTypeClass # structured similarly to tyGenericInst
|
tyParametricTypeClass # structured similarly to tyGenericInst
|
||||||
# lastSon is the body of the type class
|
# lastSon is the body of the type class
|
||||||
tyBuiltInTypeClass
|
|
||||||
tyCompositeTypeClass
|
tyBuiltInTypeClass # Type such as the catch-all object, tuple, seq, etc
|
||||||
tyAnd
|
|
||||||
tyOr
|
tyCompositeTypeClass #
|
||||||
tyNot
|
|
||||||
tyAnything
|
tyAnd, tyOr, tyNot # boolean type classes such as `string|int`,`not seq`,
|
||||||
tyStatic
|
# `Sortable and Enumable`, etc
|
||||||
|
|
||||||
|
tyAnything # a type class matching any type
|
||||||
|
|
||||||
|
tyStatic # a value known at compile type (the underlying type is .base)
|
||||||
|
|
||||||
|
tyFromExpr # This is a type representing an expression that depends
|
||||||
|
# on generic parameters (the exprsesion is stored in t.n)
|
||||||
|
# It will be converted to a real type only during generic
|
||||||
|
# instantiation and prior to this it has the potential to
|
||||||
|
# be any type.
|
||||||
|
|
||||||
const
|
const
|
||||||
tyPureObject* = tyTuple
|
tyPureObject* = tyTuple
|
||||||
GcTypeKinds* = {tyRef, tySequence, tyString}
|
GcTypeKinds* = {tyRef, tySequence, tyString}
|
||||||
tyError* = tyProxy # as an errornous node should match everything
|
tyError* = tyProxy # as an errornous node should match everything
|
||||||
|
|
||||||
|
tyUnknownTypes* = {tyError, tyFromExpr}
|
||||||
|
|
||||||
tyTypeClasses* = {tyTypeClass, tyBuiltInTypeClass, tyCompositeTypeClass,
|
tyTypeClasses* = {tyTypeClass, tyBuiltInTypeClass, tyCompositeTypeClass,
|
||||||
tyParametricTypeClass, tyAnd, tyOr, tyNot, tyAnything}
|
tyParametricTypeClass, tyAnd, tyOr, tyNot, tyAnything}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,8 @@ proc getUniqueType*(key: PType): PType =
|
||||||
if result == nil:
|
if result == nil:
|
||||||
gCanonicalTypes[k] = key
|
gCanonicalTypes[k] = key
|
||||||
result = key
|
result = key
|
||||||
of tyTypeDesc, tyTypeClasses:
|
of tyTypeDesc, tyTypeClasses, tyGenericParam,
|
||||||
internalError("value expected, but got a type")
|
tyFromExpr, tyStatic:
|
||||||
of tyGenericParam, tyStatic:
|
|
||||||
internalError("GetUniqueType")
|
internalError("GetUniqueType")
|
||||||
of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
|
of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
|
||||||
result = getUniqueType(lastSon(key))
|
result = getUniqueType(lastSon(key))
|
||||||
|
|
|
||||||
|
|
@ -129,8 +129,9 @@ proc mapType(typ: PType): TJSTypeKind =
|
||||||
tyVarargs:
|
tyVarargs:
|
||||||
result = etyObject
|
result = etyObject
|
||||||
of tyNil: result = etyNull
|
of tyNil: result = etyNull
|
||||||
of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvokation, tyNone,
|
of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvokation,
|
||||||
tyForward, tyEmpty, tyExpr, tyStmt, tyStatic, tyTypeDesc, tyTypeClasses:
|
tyNone, tyFromExpr, tyForward, tyEmpty,
|
||||||
|
tyExpr, tyStmt, tyStatic, tyTypeDesc, tyTypeClasses:
|
||||||
result = etyNone
|
result = etyNone
|
||||||
of tyProc: result = etyProc
|
of tyProc: result = etyProc
|
||||||
of tyCString: result = etyString
|
of tyCString: result = etyString
|
||||||
|
|
|
||||||
|
|
@ -293,6 +293,14 @@ proc semConstBoolExpr(c: PContext, n: PNode): PNode =
|
||||||
localError(n.info, errConstExprExpected)
|
localError(n.info, errConstExprExpected)
|
||||||
result = nn
|
result = nn
|
||||||
|
|
||||||
|
type
|
||||||
|
TSemGenericFlag = enum
|
||||||
|
withinBind, withinTypeDesc, withinMixin
|
||||||
|
TSemGenericFlags = set[TSemGenericFlag]
|
||||||
|
|
||||||
|
proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags,
|
||||||
|
ctx: var TIntSet): PNode
|
||||||
|
|
||||||
include semtypes, semtempl, semgnrc, semstmts, semexprs
|
include semtypes, semtempl, semgnrc, semstmts, semexprs
|
||||||
|
|
||||||
proc addCodeForGenerics(c: PContext, n: PNode) =
|
proc addCodeForGenerics(c: PContext, n: PNode) =
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,10 @@ proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
|
||||||
let sym = newSym(skType, idAnon, getCurrOwner(), info).linkTo(typedesc)
|
let sym = newSym(skType, idAnon, getCurrOwner(), info).linkTo(typedesc)
|
||||||
return newSymNode(sym, info)
|
return newSymNode(sym, info)
|
||||||
|
|
||||||
|
proc makeTypeFromExpr*(c: PContext, n: PNode): PType =
|
||||||
|
result = newTypeS(tyFromExpr, c)
|
||||||
|
result.n = n
|
||||||
|
|
||||||
proc makeAndType*(c: PContext, t1, t2: PType): PType =
|
proc makeAndType*(c: PContext, t1, t2: PType): PType =
|
||||||
result = newTypeS(tyAnd, c)
|
result = newTypeS(tyAnd, c)
|
||||||
result.sons = @[t1, t2]
|
result.sons = @[t1, t2]
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,6 @@
|
||||||
|
|
||||||
# included from sem.nim
|
# included from sem.nim
|
||||||
|
|
||||||
type
|
|
||||||
TSemGenericFlag = enum
|
|
||||||
withinBind, withinTypeDesc, withinMixin
|
|
||||||
TSemGenericFlags = set[TSemGenericFlag]
|
|
||||||
|
|
||||||
proc getIdentNode(n: PNode): PNode =
|
proc getIdentNode(n: PNode): PNode =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkPostfix: result = getIdentNode(n.sons[1])
|
of nkPostfix: result = getIdentNode(n.sons[1])
|
||||||
|
|
@ -31,8 +26,6 @@ proc getIdentNode(n: PNode): PNode =
|
||||||
illFormedAst(n)
|
illFormedAst(n)
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags,
|
|
||||||
ctx: var TIntSet): PNode
|
|
||||||
proc semGenericStmtScope(c: PContext, n: PNode,
|
proc semGenericStmtScope(c: PContext, n: PNode,
|
||||||
flags: TSemGenericFlags,
|
flags: TSemGenericFlags,
|
||||||
ctx: var TIntSet): PNode =
|
ctx: var TIntSet): PNode =
|
||||||
|
|
|
||||||
|
|
@ -988,6 +988,12 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
result.rawAddSon(semTypeNode(c, n.sons[i], nil))
|
result.rawAddSon(semTypeNode(c, n.sons[i], nil))
|
||||||
else: result = semGeneric(c, n, s, prev)
|
else: result = semGeneric(c, n, s, prev)
|
||||||
of nkIdent, nkDotExpr, nkAccQuoted:
|
of nkIdent, nkDotExpr, nkAccQuoted:
|
||||||
|
if n.kind == nkDotExpr:
|
||||||
|
let head = qualifiedLookUp(c, n[0], {checkAmbiguity, checkUndeclared})
|
||||||
|
if head.kind in {skType}:
|
||||||
|
var toBind = initIntSet()
|
||||||
|
var preprocessed = semGenericStmt(c, n, {}, toBind)
|
||||||
|
return makeTypeFromExpr(c, preprocessed)
|
||||||
var s = semTypeIdent(c, n)
|
var s = semTypeIdent(c, n)
|
||||||
if s.typ == nil:
|
if s.typ == nil:
|
||||||
if s.kind != skError: localError(n.info, errTypeExpected)
|
if s.kind != skError: localError(n.info, errTypeExpected)
|
||||||
|
|
|
||||||
|
|
@ -287,6 +287,10 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||||
of tyGenericBody:
|
of tyGenericBody:
|
||||||
internalError(cl.info, "ReplaceTypeVarsT: tyGenericBody" )
|
internalError(cl.info, "ReplaceTypeVarsT: tyGenericBody" )
|
||||||
result = replaceTypeVarsT(cl, lastSon(t))
|
result = replaceTypeVarsT(cl, lastSon(t))
|
||||||
|
of tyFromExpr:
|
||||||
|
var n = prepareNode(cl, t.n)
|
||||||
|
n = cl.c.semExpr(cl.c, n, {})
|
||||||
|
result = n.typ.skipTypes({tyTypeDesc})
|
||||||
of tyInt:
|
of tyInt:
|
||||||
result = skipIntLit(t)
|
result = skipIntLit(t)
|
||||||
# XXX now there are also float literals
|
# XXX now there are also float literals
|
||||||
|
|
|
||||||
|
|
@ -667,8 +667,12 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
let rootf = f.skipGenericAlias
|
let rootf = f.skipGenericAlias
|
||||||
if a.kind == tyGenericInst and roota.base == rootf.base :
|
if a.kind == tyGenericInst and roota.base == rootf.base :
|
||||||
for i in 1 .. rootf.sonsLen-2:
|
for i in 1 .. rootf.sonsLen-2:
|
||||||
result = typeRel(c, rootf.sons[i], roota.sons[i])
|
let ff = rootf.sons[i]
|
||||||
|
let aa = roota.sons[i]
|
||||||
|
result = typeRel(c, ff, aa)
|
||||||
if result == isNone: return
|
if result == isNone: return
|
||||||
|
if ff.kind == tyRange and result != isEqual: return isNone
|
||||||
|
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
else:
|
else:
|
||||||
result = typeRel(c, lastSon(f), a)
|
result = typeRel(c, lastSon(f), a)
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
# this module contains routines for accessing and iterating over types
|
# this module contains routines for accessing and iterating over types
|
||||||
|
|
||||||
import
|
import
|
||||||
intsets, ast, astalgo, trees, msgs, strutils, platform
|
intsets, ast, astalgo, trees, msgs, strutils, platform, renderer
|
||||||
|
|
||||||
proc firstOrd*(t: PType): BiggestInt
|
proc firstOrd*(t: PType): BiggestInt
|
||||||
proc lastOrd*(t: PType): BiggestInt
|
proc lastOrd*(t: PType): BiggestInt
|
||||||
|
|
@ -406,7 +406,7 @@ const
|
||||||
"bignum", "const ",
|
"bignum", "const ",
|
||||||
"!", "varargs[$1]", "iter[$1]", "Error Type", "TypeClass",
|
"!", "varargs[$1]", "iter[$1]", "Error Type", "TypeClass",
|
||||||
"ParametricTypeClass", "BuiltInTypeClass", "CompositeTypeClass",
|
"ParametricTypeClass", "BuiltInTypeClass", "CompositeTypeClass",
|
||||||
"and", "or", "not", "any", "static"]
|
"and", "or", "not", "any", "static", "TypeFromExpr"]
|
||||||
|
|
||||||
proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
var t = typ
|
var t = typ
|
||||||
|
|
@ -448,6 +448,8 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
of tyExpr:
|
of tyExpr:
|
||||||
InternalAssert t.len == 0
|
InternalAssert t.len == 0
|
||||||
result = "expr"
|
result = "expr"
|
||||||
|
of tyFromExpr:
|
||||||
|
result = renderTree(t.n)
|
||||||
of tyArray:
|
of tyArray:
|
||||||
if t.sons[0].kind == tyRange:
|
if t.sons[0].kind == tyRange:
|
||||||
result = "array[" & rangeToStr(t.sons[0].n) & ", " &
|
result = "array[" & rangeToStr(t.sons[0].n) & ", " &
|
||||||
|
|
@ -837,7 +839,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
||||||
of tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString,
|
of tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString,
|
||||||
tyInt..tyBigNum, tyStmt, tyExpr:
|
tyInt..tyBigNum, tyStmt, tyExpr:
|
||||||
result = sameFlags(a, b)
|
result = sameFlags(a, b)
|
||||||
of tyStatic:
|
of tyStatic, tyFromExpr:
|
||||||
result = exprStructuralEquivalent(a.n, b.n) and sameFlags(a, b)
|
result = exprStructuralEquivalent(a.n, b.n) and sameFlags(a, b)
|
||||||
of tyObject:
|
of tyObject:
|
||||||
ifFastObjectTypeCheckFailed(a, b):
|
ifFastObjectTypeCheckFailed(a, b):
|
||||||
|
|
@ -1018,7 +1020,8 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind,
|
||||||
result = taField in flags
|
result = taField in flags
|
||||||
of tyTypeClasses:
|
of tyTypeClasses:
|
||||||
result = true
|
result = true
|
||||||
of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation:
|
of tyGenericBody, tyGenericParam, tyGenericInvokation,
|
||||||
|
tyNone, tyForward, tyFromExpr:
|
||||||
result = false
|
result = false
|
||||||
of tyNil:
|
of tyNil:
|
||||||
result = kind == skConst
|
result = kind == skConst
|
||||||
|
|
|
||||||
6
tests/compile/compilehelpers.nim
Normal file
6
tests/compile/compilehelpers.nim
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
template accept(e: expr) =
|
||||||
|
static: assert(compiles(e))
|
||||||
|
|
||||||
|
template reject(e: expr) =
|
||||||
|
static: assert(not compiles(e))
|
||||||
|
|
||||||
41
tests/compile/tmatrix3.nim
Normal file
41
tests/compile/tmatrix3.nim
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
discard """
|
||||||
|
output: '''0.0000000000000000e+00
|
||||||
|
0.0000000000000000e+00
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
include compilehelpers
|
||||||
|
|
||||||
|
type
|
||||||
|
Matrix*[M, N, T] = object
|
||||||
|
aij*: array[M, array[N, T]]
|
||||||
|
|
||||||
|
Matrix2*[T] = Matrix[range[0..1], range[0..1], T]
|
||||||
|
|
||||||
|
Matrix3*[T] = Matrix[range[0..2], range[0..2], T]
|
||||||
|
|
||||||
|
proc mn(x: Matrix): Matrix.T = x.aij[0][0]
|
||||||
|
|
||||||
|
proc m2(x: Matrix2): Matrix2.T = x.aij[0][0]
|
||||||
|
|
||||||
|
proc m3(x: Matrix3): auto = x.aij[0][0]
|
||||||
|
|
||||||
|
var
|
||||||
|
matn: Matrix[range[0..3], range[0..2], int]
|
||||||
|
mat2: Matrix2[int]
|
||||||
|
mat3: Matrix3[float]
|
||||||
|
|
||||||
|
echo m3(mat3)
|
||||||
|
echo mn(mat3)
|
||||||
|
echo m2(mat2)
|
||||||
|
echo mn(mat2)
|
||||||
|
echo mn(matn)
|
||||||
|
|
||||||
|
reject m3(mat2)
|
||||||
|
reject m3(matn)
|
||||||
|
reject m2(mat3)
|
||||||
|
reject m2(matn)
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
discard """
|
discard """
|
||||||
output: '''----
|
output: '''----
|
||||||
myobj constructed
|
myobj constructed
|
||||||
myobj destructed
|
myobj destroyed
|
||||||
----
|
----
|
||||||
mygeneric1 constructed
|
mygeneric1 constructed
|
||||||
mygeneric1 destroyed
|
mygeneric1 destroyed
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue