diff options
author | Andreas Rumpf <andreas@andreas-laptop> | 2010-05-28 23:32:46 +0200 |
---|---|---|
committer | Andreas Rumpf <andreas@andreas-laptop> | 2010-05-28 23:32:46 +0200 |
commit | 6c2050912166a4960b40c3825afb1a31cfdde0eb (patch) | |
tree | d753cb2baa1d18d4798d64a564fdb692c54146f7 /rod | |
parent | e90665bff2e062598b51ada915c4861db6e94a8d (diff) | |
download | Nim-6c2050912166a4960b40c3825afb1a31cfdde0eb.tar.gz |
explicit types for generic routines
Diffstat (limited to 'rod')
-rwxr-xr-x | rod/docgen.nim | 11 | ||||
-rwxr-xr-x | rod/evals.nim | 3 | ||||
-rwxr-xr-x | rod/semexprs.nim | 2 | ||||
-rwxr-xr-x | rod/seminst.nim | 59 | ||||
-rwxr-xr-x | rod/semstmts.nim | 5 | ||||
-rwxr-xr-x | rod/semtypes.nim | 135 | ||||
-rwxr-xr-x | rod/sigmatch.nim | 54 | ||||
-rwxr-xr-x | rod/transf.nim | 106 |
8 files changed, 186 insertions, 189 deletions
diff --git a/rod/docgen.nim b/rod/docgen.nim index 10516bf73..9da191d8d 100755 --- a/rod/docgen.nim +++ b/rod/docgen.nim @@ -417,23 +417,20 @@ proc renderRstToRst(d: PDoc, n: PRstNode): PRope = # debugging, but most code is already debugged... const lvlToChar: array[0..8, char] = ['!', '=', '-', '~', '`', '<', '*', '|', '+'] - var - L: int - ind: PRope result = nil if n == nil: return - ind = toRope(repeatChar(d.indent)) + var ind = toRope(repeatChar(d.indent)) case n.kind of rnInner: result = renderRstSons(d, n) of rnHeadline: result = renderRstSons(d, n) - L = ropeLen(result) + var L = ropeLen(result) result = ropef("$n$1$2$n$1$3", [ind, result, toRope(repeatChar(L, lvlToChar[n.level]))]) of rnOverline: result = renderRstSons(d, n) - L = ropeLen(result) + var L = ropeLen(result) result = ropef("$n$1$3$n$1$2$n$1$3", [ind, result, toRope(repeatChar(L, lvlToChar[n.level]))]) of rnTransition: @@ -464,7 +461,7 @@ proc renderRstToRst(d: PDoc, n: PRstNode): PRope = dec(d.indent, 2) of rnField: result = renderRstToRst(d, n.sons[0]) - L = max(ropeLen(result) + 3, 30) + var L = max(ropeLen(result) + 3, 30) inc(d.indent, L) result = ropef("$n$1:$2:$3$4", [ind, result, toRope( repeatChar(L - ropeLen(result) - 2)), renderRstToRst(d, n.sons[1])]) diff --git a/rod/evals.nim b/rod/evals.nim index 7306f61b1..4232bb832 100755 --- a/rod/evals.nim +++ b/rod/evals.nim @@ -714,8 +714,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode = var a = result result = newNodeIT(nkIntLit, n.info, n.typ) case a.kind - of nkEmpty..nkNilLit: - nil + of nkEmpty..nkNilLit: nil else: result.intVal = sonsLen(a) of mNChild: result = evalAux(c, n.sons[1], {efLValue}) diff --git a/rod/semexprs.nim b/rod/semexprs.nim index 8d8b627eb..6ce1628d5 100755 --- a/rod/semexprs.nim +++ b/rod/semexprs.nim @@ -1022,8 +1022,6 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = var s = qualifiedLookup(c, n.sons[0], false) if s != nil and s.kind in {skProc, skMethod, skConverter, skIterator}: # type parameters: partial generic specialization - # XXX: too implement! - internalError(n.info, "explicit generic instantation not implemented") result = partialSpecialization(c, n, s) else: result = semArrayAccess(c, n, flags) diff --git a/rod/seminst.nim b/rod/seminst.nim index ba1f05cb2..417922825 100755 --- a/rod/seminst.nim +++ b/rod/seminst.nim @@ -1,29 +1,28 @@ # # # The Nimrod Compiler -# (c) Copyright 2009 Andreas Rumpf +# (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # + # This module does the instantiation of generic procs and types. -proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, info: TLineInfo): PSym +proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, + info: TLineInfo): PSym # generates an instantiated proc proc searchInstTypes(tab: TIdTable, key: PType): PType = - var - t: PType - match: bool # returns nil if we need to declare this type result = PType(IdTableGet(tab, key)) if (result == nil) and (tab.counter > 0): # we have to do a slow linear search because types may need # to be compared by their structure: for h in countup(0, high(tab.data)): - t = PType(tab.data[h].key) + var t = PType(tab.data[h].key) if t != nil: if key.containerId == t.containerID: - match = true + var match = true for j in countup(0, sonsLen(t) - 1): # XXX sameType is not really correct for nested generics? if not sameType(t.sons[j], key.sons[j]): @@ -39,20 +38,16 @@ proc containsGenericType(t: PType): bool = result = iterOverType(t, containsGenericTypeIter, nil) proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) = - var - s, q: PSym - t: PType - a: PNode if (n.kind != nkGenericParams): InternalError(n.info, "instantiateGenericParamList; no generic params") for i in countup(0, sonsLen(n) - 1): - a = n.sons[i] + var a = n.sons[i] if a.kind != nkSym: InternalError(a.info, "instantiateGenericParamList; no symbol") - q = a.sym + var q = a.sym if not (q.typ.kind in {tyTypeDesc, tyGenericParam}): continue - s = newSym(skType, q.name, getCurrOwner()) - t = PType(IdTableGet(pt, q.typ)) + var s = newSym(skType, q.name, getCurrOwner()) + var t = PType(IdTableGet(pt, q.typ)) if t == nil: liMessage(a.info, errCannotInstantiateX, s.name.s) if (t.kind == tyGenericParam): InternalError(a.info, "instantiateGenericParamList: " & q.name.s) @@ -60,27 +55,26 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) = addDecl(c, s) proc GenericCacheGet(c: PContext, genericSym, instSym: PSym): PSym = - var a, b: PSym result = nil for i in countup(0, sonsLen(c.generics) - 1): if c.generics.sons[i].kind != nkExprEqExpr: InternalError(genericSym.info, "GenericCacheGet") - a = c.generics.sons[i].sons[0].sym + var a = c.generics.sons[i].sons[0].sym if genericSym.id == a.id: - b = c.generics.sons[i].sons[1].sym + var b = c.generics.sons[i].sons[1].sym if equalParams(b.typ.n, instSym.typ.n) == paramsEqual: #if gVerbosity > 0 then # MessageOut('found in cache: ' + getProcHeader(instSym)); return b proc GenericCacheAdd(c: PContext, genericSym, instSym: PSym) = - var n: PNode - n = newNode(nkExprEqExpr) + var n = newNode(nkExprEqExpr) addSon(n, newSymNode(genericSym)) addSon(n, newSymNode(instSym)) addSon(c.generics, n) -proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, info: TLineInfo): PSym = +proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, + info: TLineInfo): PSym = # generates an instantiated proc var oldPrc, oldMod: PSym @@ -89,8 +83,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, info: TLineInfo): PSy if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep") inc(c.InstCounter) oldP = c.p # restore later - # NOTE: for access of private fields within generics from a different module - # and other identifiers we fake the current module temporarily! + # NOTE: for access of private fields within generics from a different module + # and other identifiers we fake the current module temporarily! oldMod = c.module c.module = getModule(fn) result = copySym(fn, false) @@ -151,8 +145,6 @@ type proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode = - var length: int - result = nil if n != nil: result = copyNode(n) result.typ = ReplaceTypeVarsT(cl, n.typ) @@ -162,7 +154,7 @@ proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode = of nkSym: result.sym = ReplaceTypeVarsS(cl, n.sym) else: - length = sonsLen(n) + var length = sonsLen(n) if length > 0: newSons(result, length) for i in countup(0, length - 1): @@ -172,7 +164,7 @@ proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym = if s == nil: return nil result = PSym(idTableGet(cl.symMap, s)) - if (result == nil): + if result == nil: result = copySym(s, false) incl(result.flags, sfFromGeneric) idTablePut(cl.symMap, s, result) @@ -229,8 +221,9 @@ proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType = result.sons[i] = ReplaceTypeVarsT(cl, result.sons[i]) result.n = ReplaceTypeVarsN(cl, result.n) if result.Kind in GenericTypes: - liMessage(cl.info, errCannotInstantiateX, TypeToString(t, preferName)) #writeln(output, ropeToStr(Typetoyaml(result))); - #checkConstructedType(cl.info, result); + liMessage(cl.info, errCannotInstantiateX, TypeToString(t, preferName)) + #writeln(output, ropeToStr(Typetoyaml(result))) + #checkConstructedType(cl.info, result) proc instGenericContainer(c: PContext, n: PNode, header: PType): PType = var cl: TReplTypeVars @@ -240,7 +233,8 @@ proc instGenericContainer(c: PContext, n: PNode, header: PType): PType = cl.c = c result = ReplaceTypeVarsT(cl, header) -proc generateTypeInstance(p: PContext, pt: TIdTable, arg: PNode, t: PType): PType = +proc generateTypeInstance(p: PContext, pt: TIdTable, arg: PNode, + t: PType): PType = var cl: TReplTypeVars InitIdTable(cl.symMap) copyIdTable(cl.typeMap, pt) @@ -251,4 +245,9 @@ proc generateTypeInstance(p: PContext, pt: TIdTable, arg: PNode, t: PType): PTyp popInfoContext() proc partialSpecialization(c: PContext, n: PNode, s: PSym): PNode = + for i in 1..sonsLen(n)-1: + n.sons[i].typ = semTypeNode(c, n.sons[i], nil) + # we cannot check for the proper number of type parameters because in + # `f[a,b](x, y)` `f` is not resolved yet properly. + # XXX: BUG this should be checked somehow! result = n diff --git a/rod/semstmts.nim b/rod/semstmts.nim index b07e724bc..0f96e5b94 100755 --- a/rod/semstmts.nim +++ b/rod/semstmts.nim @@ -6,6 +6,7 @@ # See the file "copying.txt", included in this # distribution, for details about the copyright. # + # this module does the semantic checking of statements proc semExprNoType(c: PContext, n: PNode): PNode = @@ -267,14 +268,13 @@ proc SemReturn(c: PContext, n: PNode): PNode = liMessage(n.info, errCannotReturnExpr) proc SemYield(c: PContext, n: PNode): PNode = - var restype: PType result = n checkSonsLen(n, 1) if (c.p.owner == nil) or (c.p.owner.kind != skIterator): liMessage(n.info, errYieldNotAllowedHere) if (n.sons[0] != nil): n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility: - restype = c.p.owner.typ.sons[0] + var restype = c.p.owner.typ.sons[0] if (restype != nil): n.sons[0] = fitNode(c, restype, n.sons[0]) if (n.sons[0].typ == nil): InternalError(n.info, "semYield") @@ -477,6 +477,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = s = newSymS(skType, a.sons[j], c) s.typ = newTypeS(tyGenericParam, c) else: + # not a type param, but an expression s = newSymS(skGenericParam, a.sons[j], c) s.typ = typ s.ast = def diff --git a/rod/semtypes.nim b/rod/semtypes.nim index f4b17f071..a88490ce0 100755 --- a/rod/semtypes.nim +++ b/rod/semtypes.nim @@ -6,6 +6,7 @@ # See the file "copying.txt", included in this # distribution, for details about the copyright. # + # this module does the semantic checking of type declarations proc fitNode(c: PContext, formal: PType, arg: PNode): PNode = @@ -63,10 +64,9 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType = inc(counter) proc semSet(c: PContext, n: PNode, prev: PType): PType = - var base: PType result = newOrPrevType(tySet, prev, c) if sonsLen(n) == 2: - base = semTypeNode(c, n.sons[1], nil) + var base = semTypeNode(c, n.sons[1], nil) addSon(result, base) if base.kind == tyGenericInst: base = lastSon(base) if base.kind != tyGenericParam: @@ -77,29 +77,26 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType = proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, prev: PType): PType = - var base: PType result = newOrPrevType(kind, prev, c) if sonsLen(n) == 2: - base = semTypeNode(c, n.sons[1], nil) + var base = semTypeNode(c, n.sons[1], nil) addSon(result, base) else: liMessage(n.info, errXExpectsOneTypeParam, kindStr) proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, prev: PType): PType = - var base: PType result = newOrPrevType(kind, prev, c) if sonsLen(n) == 1: - base = semTypeNode(c, n.sons[0], nil) + var base = semTypeNode(c, n.sons[0], nil) addSon(result, base) else: liMessage(n.info, errXExpectsOneTypeParam, kindStr) proc semVarType(c: PContext, n: PNode, prev: PType): PType = - var base: PType result = newOrPrevType(tyVar, prev, c) if sonsLen(n) == 1: - base = semTypeNode(c, n.sons[0], nil) + var base = semTypeNode(c, n.sons[0], nil) if base.kind == tyVar: liMessage(n.info, errVarVarTypeNotAllowed) addSon(result, base) else: @@ -111,15 +108,14 @@ proc semDistinct(c: PContext, n: PNode, prev: PType): PType = else: liMessage(n.info, errXExpectsOneTypeParam, "distinct") proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = - var a, b: PNode if (n.kind != nkRange): InternalError(n.info, "semRangeAux") checkSonsLen(n, 2) result = newOrPrevType(tyRange, prev, c) result.n = newNodeI(nkRange, n.info) if (n.sons[0] == nil) or (n.sons[1] == nil): liMessage(n.Info, errRangeIsEmpty) - a = semConstExpr(c, n.sons[0]) - b = semConstExpr(c, n.sons[1]) + var a = semConstExpr(c, n.sons[0]) + var b = semConstExpr(c, n.sons[1]) if not sameType(a.typ, b.typ): liMessage(n.info, errPureTypeMismatch) if not (a.typ.kind in {tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}): @@ -159,10 +155,9 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType = liMessage(n.info, errArrayExpectsTwoTypeParams) proc semOrdinal(c: PContext, n: PNode, prev: PType): PType = - var base: PType result = newOrPrevType(tyOrdinal, prev, c) if sonsLen(n) == 2: - base = semTypeNode(c, n.sons[1], nil) + var base = semTypeNode(c, n.sons[1], nil) if base.kind != tyGenericParam: if not isOrdinalType(base): liMessage(n.sons[1].info, errOrdinalTypeExpected) @@ -231,7 +226,7 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, allowed: TSymFlags): PSym = # identifier with visibility if n.kind == nkPostfix: - if (sonsLen(n) == 2) and (n.sons[0].kind == nkIdent): + if sonsLen(n) == 2 and n.sons[0].kind == nkIdent: result = newSymS(kind, n.sons[1], c) var v = n.sons[0].ident if (sfStar in allowed) and (v.id == ord(wStar)): @@ -426,7 +421,7 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType = base: PType pos: int IntSetInit(check) - pos = 0 # n.sons[0] contains the pragmas (if any). We process these later... + pos = 0 # n.sons[0] contains the pragmas (if any). We process these later... checkSonsLen(n, 3) if n.sons[1] != nil: base = semTypeNode(c, n.sons[1].sons[0], nil) @@ -444,28 +439,30 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType = proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode, cl: var TIntSet): PType = - var - L: int - s: PSym result = t - if (t == nil): return + if t == nil: return if IntSetContainsOrIncl(cl, t.id): return case t.kind of tyGenericBody: + #debug(t) result = newTypeS(tyGenericInvokation, c) addSon(result, t) for i in countup(0, sonsLen(t) - 2): if t.sons[i].kind != tyGenericParam: InternalError("addTypeVarsOfGenericBody") - s = copySym(t.sons[i].sym) + # do not declare ``TKey`` twice: + #if not IntSetContainsOrIncl(cl, t.sons[i].sym.ident.id): + var s = copySym(t.sons[i].sym) s.position = sonsLen(genericParams) addDecl(c, s) addSon(genericParams, newSymNode(s)) addSon(result, t.sons[i]) of tyGenericInst: - L = sonsLen(t) - 1 + #debug(t) + var L = sonsLen(t) - 1 t.sons[L] = addTypeVarsOfGenericBody(c, t.sons[L], genericParams, cl) of tyGenericInvokation: + #debug(t) for i in countup(1, sonsLen(t) - 1): t.sons[i] = addTypeVarsOfGenericBody(c, t.sons[i], genericParams, cl) else: @@ -476,13 +473,12 @@ proc paramType(c: PContext, n, genericParams: PNode, cl: var TIntSet): PType = result = semTypeNode(c, n, nil) if (genericParams != nil) and (sonsLen(genericParams) == 0): result = addTypeVarsOfGenericBody(c, result, genericParams, cl) + #if result.kind == tyGenericInvokation: debug(result) proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType = var - length, counter: int - a, def, res: PNode + def, res: PNode typ: PType - arg: PSym check, cl: TIntSet checkMinSonsLen(n, 1) result = newOrPrevType(tyProc, prev, c) @@ -491,27 +487,29 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType = if (genericParams != nil) and (sonsLen(genericParams) == 0): IntSetInit(cl) if n.sons[0] == nil: addSon(result, nil) # return type - addSon(result.n, newNodeI(nkType, n.info)) # BUGFIX: nkType must exist! - # XXX but it does not, if n.sons[paramsPos] == nil? + addSon(result.n, newNodeI(nkType, n.info)) + # BUGFIX: nkType must exist! + # XXX but it does not, if n.sons[paramsPos] == nil? else: addSon(result, nil) res = newNodeI(nkType, n.info) addSon(result.n, res) IntSetInit(check) - counter = 0 + var counter = 0 for i in countup(1, sonsLen(n) - 1): - a = n.sons[i] - if (a.kind != nkIdentDefs): IllFormedAst(a) + var a = n.sons[i] + if a.kind != nkIdentDefs: IllFormedAst(a) checkMinSonsLen(a, 3) - length = sonsLen(a) + var length = sonsLen(a) if a.sons[length - 2] != nil: typ = paramType(c, a.sons[length - 2], genericParams, cl) else: typ = nil if a.sons[length - 1] != nil: - def = semExprWithType(c, a.sons[length - 1]) # check type compability between def.typ and typ: - if (typ != nil): - if (cmpTypes(typ, def.typ) < isConvertible): + def = semExprWithType(c, a.sons[length - 1]) + # check type compability between def.typ and typ: + if typ != nil: + if cmpTypes(typ, def.typ) < isConvertible: typeMismatch(a.sons[length - 1], typ, def.typ) def = fitNode(c, typ, def) else: @@ -519,7 +517,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType = else: def = nil for j in countup(0, length - 3): - arg = newSymS(skParam, a.sons[j], c) + var arg = newSymS(skParam, a.sons[j], c) arg.typ = typ arg.position = counter inc(counter) @@ -600,21 +598,16 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = markUsed(n, n.sym) else: liMessage(n.info, errTypeExpected) - of nkObjectTy: - result = semObjectNode(c, n, prev) - of nkTupleTy: - result = semTuple(c, n, prev) - of nkRefTy: - result = semAnyRef(c, n, tyRef, "ref", prev) - of nkPtrTy: - result = semAnyRef(c, n, tyPtr, "ptr", prev) - of nkVarTy: - result = semVarType(c, n, prev) - of nkDistinctTy: - result = semDistinct(c, n, prev) + of nkObjectTy: result = semObjectNode(c, n, prev) + of nkTupleTy: result = semTuple(c, n, prev) + of nkRefTy: result = semAnyRef(c, n, tyRef, "ref", prev) + of nkPtrTy: result = semAnyRef(c, n, tyPtr, "ptr", prev) + of nkVarTy: result = semVarType(c, n, prev) + of nkDistinctTy: result = semDistinct(c, n, prev) of nkProcTy: checkSonsLen(n, 2) - result = semProcTypeNode(c, n.sons[0], nil, prev) # dummy symbol for `pragma`: + result = semProcTypeNode(c, n.sons[0], nil, prev) + # dummy symbol for `pragma`: s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c) s.typ = result pragma(c, s, n.sons[1], procTypePragmas) @@ -636,49 +629,33 @@ proc setMagicType(m: PSym, kind: TTypeKind, size: int) = proc processMagicType(c: PContext, m: PSym) = case m.magic #registerSysType(m.typ); - of mInt: - setMagicType(m, tyInt, intSize) - of mInt8: - setMagicType(m, tyInt8, 1) - of mInt16: - setMagicType(m, tyInt16, 2) - of mInt32: - setMagicType(m, tyInt32, 4) - of mInt64: - setMagicType(m, tyInt64, 8) - of mFloat: - setMagicType(m, tyFloat, floatSize) - of mFloat32: - setMagicType(m, tyFloat32, 4) - of mFloat64: - setMagicType(m, tyFloat64, 8) - of mBool: - setMagicType(m, tyBool, 1) - of mChar: - setMagicType(m, tyChar, 1) + of mInt: setMagicType(m, tyInt, intSize) + of mInt8: setMagicType(m, tyInt8, 1) + of mInt16: setMagicType(m, tyInt16, 2) + of mInt32: setMagicType(m, tyInt32, 4) + of mInt64: setMagicType(m, tyInt64, 8) + of mFloat: setMagicType(m, tyFloat, floatSize) + of mFloat32: setMagicType(m, tyFloat32, 4) + of mFloat64: setMagicType(m, tyFloat64, 8) + of mBool: setMagicType(m, tyBool, 1) + of mChar: setMagicType(m, tyChar, 1) of mString: setMagicType(m, tyString, ptrSize) addSon(m.typ, getSysType(tyChar)) of mCstring: setMagicType(m, tyCString, ptrSize) addSon(m.typ, getSysType(tyChar)) - of mPointer: - setMagicType(m, tyPointer, ptrSize) + of mPointer: setMagicType(m, tyPointer, ptrSize) of mEmptySet: setMagicType(m, tySet, 1) addSon(m.typ, newTypeS(tyEmpty, c)) of mIntSetBaseType: setMagicType(m, tyRange, intSize) #intSetBaseType := m.typ; return - of mNil: - setMagicType(m, tyNil, ptrSize) - of mExpr: - setMagicType(m, tyExpr, 0) - of mStmt: - setMagicType(m, tyStmt, 0) - of mTypeDesc: - setMagicType(m, tyTypeDesc, 0) - of mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal: - return + of mNil: setMagicType(m, tyNil, ptrSize) + of mExpr: setMagicType(m, tyExpr, 0) + of mStmt: setMagicType(m, tyStmt, 0) + of mTypeDesc: setMagicType(m, tyTypeDesc, 0) + of mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal: return else: liMessage(m.info, errTypeExpected) diff --git a/rod/sigmatch.nim b/rod/sigmatch.nim index 0698bf18d..a1b322d86 100755 --- a/rod/sigmatch.nim +++ b/rod/sigmatch.nim @@ -30,7 +30,7 @@ type TTypeRelation = enum # order is important! isNone, isConvertible, isIntConv, isSubtype, isGeneric, isEqual -proc initCandidate(c: var TCandidate, callee: PType) = +proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} = c.exactMatches = 0 c.subtypeMatches = 0 c.convMatches = 0 @@ -38,11 +38,25 @@ proc initCandidate(c: var TCandidate, callee: PType) = c.genericMatches = 0 c.state = csEmpty c.callee = callee - c.calleeSym = nil c.call = nil c.baseTypeMatch = false - initIdTable(c.bindings) #assert(c.callee <> nil); - + +proc initCandidate(c: var TCandidate, callee: PType) = + initCandidateAux(c, callee) + c.calleeSym = nil + initIdTable(c.bindings) + +proc initCandidate(c: var TCandidate, callee: PSym, binding: PNode) = + initCandidateAux(c, callee.typ) + c.calleeSym = callee + initIdTable(c.bindings) + if binding != nil: + var typeParams = callee.ast[genericParamsPos] + for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1): + var formalTypeParam = typeParams.sons[i-1].typ + #debug(formalTypeParam) + IdTablePut(c.bindings, formalTypeParam, binding[i].typ) + proc copyCandidate(a: var TCandidate, b: TCandidate) = a.exactMatches = b.exactMatches a.subtypeMatches = b.subtypeMatches @@ -326,7 +340,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation = case a.kind of tyPointer: result = isEqual of tyNil: result = isSubtype - of tyRef, tyPtr, tyProc, tyCString: result = isConvertible + of tyPtr, tyProc, tyCString: result = isConvertible else: nil of tyString: case a.kind @@ -664,21 +678,20 @@ proc sameMethodDispatcher(a, b: PSym): bool = if aa.kind == nkSym and bb.kind == nkSym and aa.sym == bb.sym: result = true -proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode = - var +proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds, + initialBinding: PNode): PNode = + var o: TOverloadIter x, y, z: TCandidate #liMessage(n.info, warnUser, renderTree(n)); - var sym = initOverloadIter(o, c, n.sons[0]) + var sym = initOverloadIter(o, c, f) result = nil if sym == nil: return - initCandidate(x, sym.typ) - x.calleeSym = sym - initCandidate(y, sym.typ) - y.calleeSym = sym + initCandidate(x, sym, initialBinding) + initCandidate(y, sym, initialBinding) while sym != nil: if sym.kind in filter: - initCandidate(z, sym.typ) + initCandidate(z, sym, initialBinding) z.calleeSym = sym matches(c, n, z) if z.state == csMatch: @@ -689,7 +702,7 @@ proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode = if cmp < 0: x = z # z is better than x elif cmp == 0: y = z # z is as good as x else: nil - sym = nextOverloadIter(o, c, n.sons[0]) + sym = nextOverloadIter(o, c, f) if x.state == csEmpty: # no overloaded proc found # do not generate an error yet; the semantic checking will check for @@ -714,3 +727,16 @@ proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode = result = x.call result.sons[0] = newSymNode(x.calleeSym) result.typ = x.callee.sons[0] + +proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode = + # process the bindings once: + var initialBinding: PNode + var f = n.sons[0] + if f.kind == nkBracketExpr: + # fill in the bindings: + initialBinding = f + f = f.sons[0] + else: + initialBinding = nil + result = semDirectCallWithBinding(c, n, f, filter, initialBinding) + diff --git a/rod/transf.nim b/rod/transf.nim index ac746f834..16c279c80 100755 --- a/rod/transf.nim +++ b/rod/transf.nim @@ -63,55 +63,55 @@ proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PSym = incl(result.flags, sfFromGeneric) proc transform(c: PTransf, n: PNode): PNode - # - # - #Transforming iterators into non-inlined versions is pretty hard, but - #unavoidable for not bloating the code too much. If we had direct access to - #the program counter, things'd be much easier. - #:: - # - # iterator items(a: string): char = - # var i = 0 - # while i < length(a): - # yield a[i] - # inc(i) - # - # for ch in items("hello world"): # `ch` is an iteration variable - # echo(ch) - # - #Should be transformed into:: - # - # type - # TItemsClosure = record - # i: int - # state: int - # proc items(a: string, c: var TItemsClosure): char = - # case c.state - # of 0: goto L0 # very difficult without goto! - # of 1: goto L1 # can be implemented by GCC's computed gotos - # - # block L0: - # c.i = 0 - # while c.i < length(a): - # c.state = 1 - # return a[i] - # block L1: inc(c.i) - # - #More efficient, but not implementable:: - # - # type - # TItemsClosure = record - # i: int - # pc: pointer - # - # proc items(a: string, c: var TItemsClosure): char = - # goto c.pc - # c.i = 0 - # while c.i < length(a): - # c.pc = label1 - # return a[i] - # label1: inc(c.i) - # + +# Transforming iterators into non-inlined versions is pretty hard, but +# unavoidable for not bloating the code too much. If we had direct access to +# the program counter, things'd be much easier. +# :: +# +# iterator items(a: string): char = +# var i = 0 +# while i < length(a): +# yield a[i] +# inc(i) +# +# for ch in items("hello world"): # `ch` is an iteration variable +# echo(ch) +# +# Should be transformed into:: +# +# type +# TItemsClosure = record +# i: int +# state: int +# proc items(a: string, c: var TItemsClosure): char = +# case c.state +# of 0: goto L0 # very difficult without goto! +# of 1: goto L1 # can be implemented by GCC's computed gotos +# +# block L0: +# c.i = 0 +# while c.i < length(a): +# c.state = 1 +# return a[i] +# block L1: inc(c.i) +# +# More efficient, but not implementable:: +# +# type +# TItemsClosure = record +# i: int +# pc: pointer +# +# proc items(a: string, c: var TItemsClosure): char = +# goto c.pc +# c.i = 0 +# while c.i < length(a): +# c.pc = label1 +# return a[i] +# label1: inc(c.i) +# + proc newAsgnStmt(c: PTransf, le, ri: PNode): PNode = result = newNodeI(nkFastAsgn, ri.info) addSon(result, le) @@ -290,8 +290,8 @@ proc transformConv(c: PTransf, n: PNode): PNode = if not isOrdinalType(source): # XXX int64 -> float conversion? result = n - elif (firstOrd(dest) <= firstOrd(source)) and - (lastOrd(source) <= lastOrd(dest)): + elif firstOrd(dest) <= firstOrd(source) and + lastOrd(source) <= lastOrd(dest): # BUGFIX: simply leave n as it is; we need a nkConv node, # but no range check: result = n @@ -540,8 +540,8 @@ proc getMergeOp(n: PNode): PSym = proc flattenTreeAux(d, a: PNode, op: PSym) = var op2 = getMergeOp(a) - if (op2 != nil) and - ((op2.id == op.id) or (op.magic != mNone) and (op2.magic == op.magic)): + if op2 != nil and + (op2.id == op.id or op.magic != mNone and op2.magic == op.magic): for i in countup(1, sonsLen(a) - 1): flattenTreeAux(d, a.sons[i], op) else: addSon(d, copyTree(a)) |