Revert "static and default params for generics"

This reverts commit 46813bbe4e.
This commit is contained in:
Araq 2013-05-27 23:18:38 +02:00
commit 0662ec4a43
4 changed files with 62 additions and 93 deletions

View file

@ -674,8 +674,6 @@ type
# for record types a nkRecord node # for record types a nkRecord node
# for enum types a list of symbols # for enum types a list of symbols
# for tyInt it can be the int literal # for tyInt it can be the int literal
# for procs and tyGenericBody, it's the
# formal param list
# else: unused # else: unused
destructor*: PSym # destructor. warning: nil here may not necessary destructor*: PSym # destructor. warning: nil here may not necessary
# mean that there is no destructor. # mean that there is no destructor.

View file

@ -710,8 +710,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
# TGObj[T] = object # TGObj[T] = object
# TAlias[T] = TGObj[T] # TAlias[T] = TGObj[T]
# #
s.typ.n = semGenericParamList(c, a.sons[1], s.typ) a.sons[1] = semGenericParamList(c, a.sons[1], s.typ)
a.sons[1] = s.typ.n
s.typ.size = -1 # could not be computed properly s.typ.size = -1 # could not be computed properly
# we fill it out later. For magic generics like 'seq', it won't be filled # we fill it out later. For magic generics like 'seq', it won't be filled
# so we use tyEmpty instead of nil to not crash for strange conversions # so we use tyEmpty instead of nil to not crash for strange conversions

View file

@ -794,44 +794,29 @@ proc semGenericParamInInvokation(c: PContext, n: PNode): PType =
proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
result = newOrPrevType(tyGenericInvokation, prev, c) result = newOrPrevType(tyGenericInvokation, prev, c)
addSonSkipIntLit(result, s.typ) var isConcrete = true
template addToResult(typ) =
if typ.isNil:
InternalAssert false
rawAddSon(result, typ)
else: addSonSkipIntLit(result, typ)
if s.typ == nil: if s.typ == nil:
LocalError(n.info, errCannotInstantiateX, s.name.s) LocalError(n.info, errCannotInstantiateX, s.name.s)
return newOrPrevType(tyError, prev, c) return newOrPrevType(tyError, prev, c)
elif s.typ.kind == tyForward: elif s.typ.kind != tyGenericBody:
for i in countup(1, sonsLen(n)-1): isConcrete = false
var elem = semGenericParamInInvokation(c, n.sons[i]) elif sonsLen(n) != sonsLen(s.typ):
addToResult(elem) LocalError(n.info, errWrongNumberOfArguments)
else: return newOrPrevType(tyError, prev, c)
internalAssert s.typ.kind == tyGenericBody addSonSkipIntLit(result, s.typ)
# iterate over arguments:
var m = newCandidate(s, n) for i in countup(1, sonsLen(n)-1):
matches(c, n, copyTree(n), m) var elem = semGenericParamInInvokation(c, n.sons[i])
if containsGenericType(elem): isConcrete = false
if m.state != csMatch: #if elem.kind in {tyGenericParam, tyGenericInvokation}: isConcrete = false
LocalError(n.info, errWrongNumberOfArguments) if elem.isNil: rawAddSon(result, elem)
return newOrPrevType(tyError, prev, c) else: addSonSkipIntLit(result, elem)
if isConcrete:
var isConcrete = true if s.ast == nil:
LocalError(n.info, errCannotInstantiateX, s.name.s)
for i in 1 .. <m.call.len: result = newOrPrevType(tyError, prev, c)
let typ = m.call[i].typ.skipTypes({tyTypeDesc}) else:
if containsGenericType(typ): isConcrete = false result = instGenericContainer(c, n, result)
addToResult(typ)
if isConcrete:
if s.ast == nil:
LocalError(n.info, errCannotInstantiateX, s.name.s)
result = newOrPrevType(tyError, prev, c)
else:
result = instGenericContainer(c, n, result)
proc semTypeExpr(c: PContext, n: PNode): PType = proc semTypeExpr(c: PContext, n: PNode): PType =
var n = semExprWithType(c, n, {efDetermineType}) var n = semExprWithType(c, n, {efDetermineType})
@ -1033,61 +1018,57 @@ proc processMagicType(c: PContext, m: PSym) =
of mPNimrodNode: nil of mPNimrodNode: nil
else: LocalError(m.info, errTypeExpected) else: LocalError(m.info, errTypeExpected)
proc semGenericConstraints(c: PContext, x: PType): PType = proc semGenericConstraints(c: PContext, n: PNode, result: PType) =
var x = semTypeNode(c, n, nil)
if x.kind in StructuralEquivTypes and ( if x.kind in StructuralEquivTypes and (
sonsLen(x) == 0 or x.sons[0].kind in {tyGenericParam, tyEmpty}): sonsLen(x) == 0 or x.sons[0].kind in {tyGenericParam, tyEmpty}):
result = newConstraint(c, x.kind) x = newConstraint(c, x.kind)
else: result.addSonSkipIntLit(x)
result = newTypeWithSons(c, tyGenericParam, @[x])
proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
result = copyNode(n) result = copyNode(n)
if n.kind != nkGenericParams: if n.kind != nkGenericParams:
illFormedAst(n) illFormedAst(n)
return return
for i in countup(0, sonsLen(n)-1): var position = 0
for i in countup(0, sonsLen(n)-1):
var a = n.sons[i] var a = n.sons[i]
if a.kind != nkIdentDefs: illFormedAst(n) if a.kind != nkIdentDefs: illFormedAst(n)
let L = a.len var L = sonsLen(a)
var def = a{-1} var def = a.sons[L-1]
let constraint = a{-2}
var typ: PType var typ: PType
if a.sons[L-2].kind != nkEmpty:
if constraint.kind != nkEmpty:
typ = semTypeNode(c, constraint, nil)
if typ.kind != tyExpr or typ.len == 0:
if typ.len == 0 and typ.kind == tyTypeDesc:
typ = newTypeS(tyGenericParam, c)
else:
typ = semGenericConstraints(c, typ)
if def.kind != nkEmpty:
def = semConstExpr(c, def)
if typ == nil:
if def.typ.kind != tyTypeDesc:
typ = newTypeWithSons(c, tyExpr, @[def.typ])
else:
if not containsGenericType(def.typ):
def = fitNode(c, typ, def)
if typ == nil:
typ = newTypeS(tyGenericParam, c) typ = newTypeS(tyGenericParam, c)
semGenericConstraints(c, a.sons[L-2], typ)
for j in countup(0, L-3): if sonsLen(typ) == 1 and typ.sons[0].kind == tyTypeDesc:
let finalType = if j == 0: typ typ = typ.sons[0]
else: copyType(typ, typ.owner, false) elif def.kind != nkEmpty: typ = newTypeS(tyExpr, c)
# it's important the we create an unique else: typ = nil
# type for each generic param. the index for j in countup(0, L-3):
# of the parameter will be stored in the var s: PSym
# attached symbol. if typ == nil:
var s = case finalType.kind s = newSymG(skType, a.sons[j], c)
s.typ = newTypeS(tyGenericParam, c)
else:
case typ.kind
of tyTypeDesc:
s = newSymG(skType, a.sons[j], c)
s.typ = newTypeS(tyGenericParam, c)
of tyExpr: of tyExpr:
newSymG(skGenericParam, a.sons[j], c).linkTo(finalType) #echo "GENERIC EXPR ", a.info.toFileLineCol
# not a type param, but an expression
# proc foo[x: expr](bar: int) what is this?
s = newSymG(skGenericParam, a.sons[j], c)
s.typ = typ
else: else:
newSymG(skType, a.sons[j], c).linkTo(finalType) # This handles cases like proc foo[t: tuple]
# XXX: we want to turn that into a type class
s = newSymG(skType, a.sons[j], c)
s.typ = typ
if def.kind != nkEmpty: s.ast = def if def.kind != nkEmpty: s.ast = def
s.typ.sym = s
if father != nil: addSonSkipIntLit(father, s.typ) if father != nil: addSonSkipIntLit(father, s.typ)
s.position = result.len s.position = position
inc position
addSon(result, newSymNode(s)) addSon(result, newSymNode(s))
if sfGenSym notin s.flags: addDecl(c, s) if sfGenSym notin s.flags: addDecl(c, s)

View file

@ -84,9 +84,6 @@ proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode,
#debug(formalTypeParam) #debug(formalTypeParam)
put(c.bindings, formalTypeParam, binding[i].typ) put(c.bindings, formalTypeParam, binding[i].typ)
proc newCandidate*(callee: PSym, binding: PNode, calleeScope = -1): TCandidate =
initCandidate(result, callee, binding, calleeScope)
proc copyCandidate(a: var TCandidate, b: TCandidate) = proc copyCandidate(a: var TCandidate, b: TCandidate) =
a.exactMatches = b.exactMatches a.exactMatches = b.exactMatches
a.subtypeMatches = b.subtypeMatches a.subtypeMatches = b.subtypeMatches
@ -864,22 +861,16 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
else: else:
m.state = csNoMatch m.state = csNoMatch
return return
var var f = 1 # iterates over formal parameters
# iterates over formal parameters var a = 1 # iterates over the actual given arguments
f = if m.callee.kind != tyGenericBody: 1 m.state = csMatch # until proven otherwise
else: 0
# iterates over the actual given arguments
a = 1
m.state = csMatch # until proven otherwise
m.call = newNodeI(n.kind, n.info) m.call = newNodeI(n.kind, n.info)
m.call.typ = base(m.callee) # may be nil m.call.typ = base(m.callee) # may be nil
var formalLen = m.callee.n.len var formalLen = sonsLen(m.callee.n)
addSon(m.call, copyTree(n.sons[0])) addSon(m.call, copyTree(n.sons[0]))
var container: PNode = nil # constructed container var container: PNode = nil # constructed container
var formal: PSym = nil var formal: PSym = nil
while a < n.len: while a < n.len:
if n.sons[a].kind == nkExprEqExpr: if n.sons[a].kind == nkExprEqExpr:
# named param # named param