make more tests green

This commit is contained in:
Zahary Karadjov 2013-12-29 00:00:37 +02:00
commit 66a2556525
15 changed files with 176 additions and 162 deletions

View file

@ -906,17 +906,15 @@ proc evalParseStmt(c: PEvalContext, n: PNode): PNode =
result = parseString(code.getStrValue, code.info.toFilename, result = parseString(code.getStrValue, code.info.toFilename,
code.info.line.int) code.info.line.int)
#result.typ = newType(tyStmt, c.module) #result.typ = newType(tyStmt, c.module)
proc evalTypeTrait*(trait, operand: PNode, context: PSym): PNode =
InternalAssert operand.kind == nkSym
let typ = operand.sym.typ.skipTypes({tyTypeDesc}) proc evalTypeTrait*(trait, operand: PNode, context: PSym): PNode =
let typ = operand.typ.skipTypes({tyTypeDesc})
case trait.sym.name.s.normalize case trait.sym.name.s.normalize
of "name": of "name":
result = newStrNode(nkStrLit, typ.typeToString(preferName)) result = newStrNode(nkStrLit, typ.typeToString(preferName))
result.typ = newType(tyString, context) result.typ = newType(tyString, context)
result.info = trait.info result.info = trait.info
of "arity": of "arity":
result = newIntNode(nkIntLit, typ.n.len-1) result = newIntNode(nkIntLit, typ.n.len-1)
result.typ = newType(tyInt, context) result.typ = newType(tyInt, context)
result.info = trait.info result.info = trait.info
@ -1330,7 +1328,7 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
if gNestedEvals <= 0: stackTrace(c, n.info, errTooManyIterations) if gNestedEvals <= 0: stackTrace(c, n.info, errTooManyIterations)
case n.kind case n.kind
of nkSym: result = evalSym(c, n, flags) of nkSym: result = evalSym(c, n, flags)
of nkType..nkNilLit: of nkType..nkNilLit, nkTypeOfExpr:
# nkStrLit is VERY common in the traces, so we should avoid # nkStrLit is VERY common in the traces, so we should avoid
# the 'copyNode' here. # the 'copyNode' here.
result = n #.copyNode result = n #.copyNode

View file

@ -158,16 +158,15 @@ proc IsOpImpl(c: PContext, n: PNode): PNode
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
semCheck: bool = true): PNode semCheck: bool = true): PNode
when false: proc symFromType(t: PType, info: TLineInfo): PSym =
proc symFromType(t: PType, info: TLineInfo): PSym = if t.sym != nil: return t.sym
if t.sym != nil: return t.sym result = newSym(skType, getIdent"AnonType", t.owner, info)
result = newSym(skType, getIdent"AnonType", t.owner, info) result.flags.incl sfAnon
result.flags.incl sfAnon result.typ = t
result.typ = t
proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode = proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
result = newSymNode(symFromType(t, info), info) result = newSymNode(symFromType(t, info), info)
result.typ = makeTypeDesc(c, t) result.typ = makeTypeDesc(c, t)
proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext = proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext =
result = newEvalContext(c.module, mode) result = newEvalContext(c.module, mode)

View file

@ -301,10 +301,10 @@ proc semOf(c: PContext, n: PNode): PNode =
proc isOpImpl(c: PContext, n: PNode): PNode = proc isOpImpl(c: PContext, n: PNode): PNode =
InternalAssert n.sonsLen == 3 and InternalAssert n.sonsLen == 3 and
n[1].kind == nkSym and n[1].sym.kind == skType and n[1].typ != nil and n[1].typ.kind == tyTypeDesc and
n[2].kind in {nkStrLit..nkTripleStrLit, nkType} n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
let t1 = n[1].sym.typ.skipTypes({tyTypeDesc}) let t1 = n[1].typ.skipTypes({tyTypeDesc})
if n[2].kind in {nkStrLit..nkTripleStrLit}: if n[2].kind in {nkStrLit..nkTripleStrLit}:
case n[2].strVal.normalize case n[2].strVal.normalize
@ -1942,7 +1942,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
# type parameters: partial generic specialization # type parameters: partial generic specialization
n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s) n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
result = explicitGenericInstantiation(c, n, s) result = explicitGenericInstantiation(c, n, s)
else: elif s != nil and s.kind in {skType}:
result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
else:
result = semArrayAccess(c, n, flags) result = semArrayAccess(c, n, flags)
of nkCurlyExpr: of nkCurlyExpr:
result = semExpr(c, buildOverloadedSubscripts(n, getIdent"{}"), flags) result = semExpr(c, buildOverloadedSubscripts(n, getIdent"{}"), flags)

View file

@ -588,8 +588,9 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
result = newSymNodeTypeDesc(s, n.info) result = newSymNodeTypeDesc(s, n.info)
of skGenericParam: of skGenericParam:
if s.typ.kind == tyStatic: if s.typ.kind == tyStatic:
result = s.typ.n if s.typ.n != nil:
result.typ = s.typ.sons[0] result = s.typ.n
result.typ = s.typ.sons[0]
else: else:
result = newSymNodeTypeDesc(s, n.info) result = newSymNodeTypeDesc(s, n.info)
else: nil else: nil

View file

@ -198,14 +198,31 @@ proc fixupProcType(c: PContext, genericType: PType,
case genericType.kind case genericType.kind
of tyGenericParam, tyTypeClasses: of tyGenericParam, tyTypeClasses:
result = inst.concreteTypes[genericType.sym.position] result = inst.concreteTypes[genericType.sym.position]
of tyTypeDesc: of tyTypeDesc:
result = inst.concreteTypes[genericType.sym.position] result = inst.concreteTypes[genericType.sym.position]
if tfUnresolved in genericType.flags: if tfUnresolved in genericType.flags:
result = result.sons[0] result = result.sons[0]
of tyStatic: of tyStatic:
result = inst.concreteTypes[genericType.sym.position] result = inst.concreteTypes[genericType.sym.position]
of tyGenericInst: of tyGenericInst:
result = fixupProcType(c, result.lastSon, inst) result = fixupProcType(c, result.lastSon, inst)
of tyObject:
var recList = genericType.n
for i in 0 .. <recList.sonsLen:
let field = recList[i].sym
let changed = fixupProcType(c, field.typ, inst)
if field.typ != changed:
if result == genericType:
result = copyType(genericType, genericType.owner, false)
result.n = copyTree(recList)
result.n.sons[i].sym = copySym(recList[i].sym, true)
result.n.sons[i].typ = changed
result.n.sons[i].sym.typ = changed
of tyOpenArray, tyArray, tySet, tySequence, tyTuple, tyProc, of tyOpenArray, tyArray, tySet, tySequence, tyTuple, tyProc,
tyPtr, tyVar, tyRef, tyOrdinal, tyRange, tyVarargs: tyPtr, tyVar, tyRef, tyOrdinal, tyRange, tyVarargs:
if genericType.sons == nil: return if genericType.sons == nil: return
@ -268,7 +285,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
info: TLineInfo): PSym = info: TLineInfo): PSym =
# no need to instantiate generic templates/macros: # no need to instantiate generic templates/macros:
if fn.kind in {skTemplate, skMacro}: return fn if fn.kind in {skTemplate, skMacro}: return fn
# generates an instantiated proc # generates an instantiated proc
if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep") if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep")
inc(c.InstCounter) inc(c.InstCounter)

View file

@ -34,10 +34,9 @@ proc semInstantiationInfo(c: PContext, n: PNode): PNode =
proc semTypeTraits(c: PContext, n: PNode): PNode = proc semTypeTraits(c: PContext, n: PNode): PNode =
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2)
internalAssert n.sons[1].kind == nkSym internalAssert n.sons[1].typ.kind == tyTypeDesc
let typArg = n.sons[1].sym let typArg = n.sons[1].typ
if typArg.kind == skType or if typArg.sonsLen > 0:
(typArg.kind == skParam and typArg.typ.sonsLen > 0):
# This is either a type known to sem or a typedesc # This is either a type known to sem or a typedesc
# param to a regular proc (again, known at instantiation) # param to a regular proc (again, known at instantiation)
result = evalTypeTrait(n[0], n[1], GetCurrOwner()) result = evalTypeTrait(n[0], n[1], GetCurrOwner())

View file

@ -1039,8 +1039,12 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
# for DLL generation it is annoying to check for sfImportc! # for DLL generation it is annoying to check for sfImportc!
if sfBorrow in s.flags: if sfBorrow in s.flags:
LocalError(n.sons[bodyPos].info, errImplOfXNotAllowed, s.name.s) LocalError(n.sons[bodyPos].info, errImplOfXNotAllowed, s.name.s)
if n.sons[genericParamsPos].kind == nkEmpty: let usePseudoGenerics = kind in {skMacro, skTemplate}
ParamsTypeCheck(c, s.typ) # Macros and Templates can have generic parameters, but they are
# only used for overload resolution (there is no instantiation of
# the symbol, so we must process the body now)
if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics:
if not usePseudoGenerics: ParamsTypeCheck(c, s.typ)
pushProcCon(c, s) pushProcCon(c, s)
maybeAddResult(c, s, n) maybeAddResult(c, s, n)
if sfImportc notin s.flags: if sfImportc notin s.flags:

View file

@ -594,12 +594,7 @@ let typedescId = getIdent"typedesc"
proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
paramType: PType, paramName: string, paramType: PType, paramName: string,
info: TLineInfo, anon = false): PType = info: TLineInfo, anon = false): PType =
if procKind in {skMacro, skTemplate}:
# generic param types in macros and templates affect overload
# resolution, but don't work as generic params when it comes
# to proc instantiation. We don't need to lift such params here.
return
proc addImplicitGenericImpl(typeClass: PType, typId: PIdent): PType = proc addImplicitGenericImpl(typeClass: PType, typId: PIdent): PType =
let finalTypId = if typId != nil: typId let finalTypId = if typId != nil: typId
else: getIdent(paramName & ":type") else: getIdent(paramName & ":type")
@ -620,7 +615,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
s.position = genericParams.len s.position = genericParams.len
genericParams.addSon(newSymNode(s)) genericParams.addSon(newSymNode(s))
result = typeClass result = typeClass
# XXX: There are codegen errors if this is turned into a nested proc # XXX: There are codegen errors if this is turned into a nested proc
template liftingWalk(typ: PType, anonFlag = false): expr = template liftingWalk(typ: PType, anonFlag = false): expr =
liftParamType(c, procKind, genericParams, typ, paramName, info, anonFlag) liftParamType(c, procKind, genericParams, typ, paramName, info, anonFlag)
@ -635,20 +630,25 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
case paramType.kind: case paramType.kind:
of tyAnything: of tyAnything:
result = addImplicitGeneric(newTypeS(tyGenericParam, c)) result = addImplicitGeneric(newTypeS(tyGenericParam, c))
of tyStatic: of tyStatic:
# proc(a: expr{string}, b: expr{nkLambda}) # proc(a: expr{string}, b: expr{nkLambda})
# overload on compile time values and AST trees # overload on compile time values and AST trees
result = addImplicitGeneric(c.newTypeWithSons(tyStatic, paramType.sons)) result = addImplicitGeneric(c.newTypeWithSons(tyStatic, paramType.sons))
result.flags.incl tfHasStatic
of tyTypeDesc: of tyTypeDesc:
if tfUnresolved notin paramType.flags: if tfUnresolved notin paramType.flags:
# naked typedescs are not bindOnce types # naked typedescs are not bindOnce types
if paramType.sonsLen == 0 and paramTypId != nil and if paramType.sonsLen == 0 and paramTypId != nil and
paramTypId.id == typedescId.id: paramTypId = nil paramTypId.id == typedescId.id: paramTypId = nil
result = addImplicitGeneric(c.newTypeWithSons(tyTypeDesc, paramType.sons)) result = addImplicitGeneric(c.newTypeWithSons(tyTypeDesc, paramType.sons))
of tyDistinct: of tyDistinct:
if paramType.sonsLen == 1: if paramType.sonsLen == 1:
# disable the bindOnce behavior for the type class # disable the bindOnce behavior for the type class
result = liftingWalk(paramType.sons[0], true) result = liftingWalk(paramType.sons[0], true)
of tySequence, tySet, tyArray, tyOpenArray: of tySequence, tySet, tyArray, tyOpenArray:
# XXX: this is a bit strange, but proc(s: seq) # XXX: this is a bit strange, but proc(s: seq)
# produces tySequence(tyGenericParam, null). # produces tySequence(tyGenericParam, null).
@ -657,7 +657,8 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
# Maybe there is another better place to associate # Maybe there is another better place to associate
# the seq type class with the seq identifier. # the seq type class with the seq identifier.
if paramType.lastSon == nil: if paramType.lastSon == nil:
let typ = c.newTypeWithSons(tyTypeClass, @[newTypeS(paramType.kind, c)]) let typ = c.newTypeWithSons(tyBuiltInTypeClass,
@[newTypeS(paramType.kind, c)])
result = addImplicitGeneric(typ) result = addImplicitGeneric(typ)
else: else:
for i in 0 .. <paramType.sons.len: for i in 0 .. <paramType.sons.len:
@ -678,20 +679,26 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
result = addImplicitGeneric(result) result = addImplicitGeneric(result)
of tyGenericInst: of tyGenericInst:
# XXX: It should be possible to set tfHasMeta in semtypinst, when the
# instance was generated
for i in 1 .. (paramType.sons.len - 2): for i in 1 .. (paramType.sons.len - 2):
var lifted = liftingWalk(paramType.sons[i]) var lifted = liftingWalk(paramType.sons[i])
if lifted != nil: if lifted != nil:
paramType.sons[i] = lifted paramType.sons[i] = lifted
result = paramType result = paramType
paramType.lastSon.flags.incl tfHasMeta
let liftBody = liftingWalk(paramType.lastSon) let liftBody = liftingWalk(paramType.lastSon)
if liftBody != nil: result = liftBody if liftBody != nil:
result = liftBody
result.flags.incl tfHasMeta
of tyTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot: of tyTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot:
result = addImplicitGeneric(copyType(paramType, getCurrOwner(), true)) result = addImplicitGeneric(copyType(paramType, getCurrOwner(), true))
of tyExpr: of tyExpr:
result = addImplicitGeneric(newTypeS(tyGenericParam, c)) if procKind notin {skMacro, skTemplate}:
result = addImplicitGeneric(newTypeS(tyGenericParam, c))
of tyGenericParam: of tyGenericParam:
if tfGenericTypeParam in paramType.flags and false: if tfGenericTypeParam in paramType.flags and false:
@ -881,8 +888,8 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
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})
if n.kind == nkSym and n.sym.kind == skType: if n.typ.kind == tyTypeDesc:
result = n.sym.typ result = n.typ.base
else: else:
LocalError(n.info, errTypeExpected, n.renderTree) LocalError(n.info, errTypeExpected, n.renderTree)

View file

@ -201,11 +201,12 @@ proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
result = t result = t
if t == nil: return if t == nil: return
if t.kind == tyStatic and t.sym != nil and t.sym.kind == skGenericParam: if t.kind == tyStatic and t.sym != nil and t.sym.kind == skGenericParam:
return lookupTypeVar(cl, t) let s = lookupTypeVar(cl, t)
return if s != nil: s else: t
case t.kind case t.kind
of tyTypeClass: nil of tyTypeClass, tyBuiltInTypeClass: nil
of tyGenericParam: of tyGenericParam, tyCompositeTypeClass:
result = lookupTypeVar(cl, t) result = lookupTypeVar(cl, t)
if result == nil: return t if result == nil: return t
if result.kind == tyGenericInvokation: if result.kind == tyGenericInvokation:

View file

@ -210,7 +210,7 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1): string =
add(result, argTypeToString(arg)) add(result, argTypeToString(arg))
if i != sonsLen(n) - 1: add(result, ", ") if i != sonsLen(n) - 1: add(result, ", ")
proc typeRel*(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation proc typeRel*(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation
proc concreteType(c: TCandidate, t: PType): PType = proc concreteType(c: TCandidate, t: PType): PType =
case t.kind case t.kind
of tyArrayConstr: of tyArrayConstr:
@ -305,8 +305,7 @@ proc minRel(a, b: TTypeRelation): TTypeRelation =
proc recordRel(c: var TCandidate, f, a: PType): TTypeRelation = proc recordRel(c: var TCandidate, f, a: PType): TTypeRelation =
result = isNone result = isNone
if sameType(f, a): if sameType(f, a): result = isEqual
result = isEqual
elif sonsLen(a) == sonsLen(f): elif sonsLen(a) == sonsLen(f):
result = isEqual result = isEqual
let firstField = if f.kind == tyTuple: 0 let firstField = if f.kind == tyTuple: 0
@ -323,6 +322,8 @@ proc recordRel(c: var TCandidate, f, a: PType): TTypeRelation =
else: else:
var x = f.n.sons[i].sym var x = f.n.sons[i].sym
var y = a.n.sons[i].sym var y = a.n.sons[i].sym
if f.kind == tyObject and typeRel(c, x.typ, y.typ) < isSubtype:
return isNone
if x.name.id != y.name.id: return isNone if x.name.id != y.name.id: return isNone
proc allowsNil(f: PType): TTypeRelation {.inline.} = proc allowsNil(f: PType): TTypeRelation {.inline.} =
@ -390,7 +391,7 @@ proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
else: else:
result = isNone result = isNone
proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation = proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
# typeRel can be used to establish various relationships between types: # typeRel can be used to establish various relationships between types:
# #
# 1) When used with concrete types, it will check for type equivalence # 1) When used with concrete types, it will check for type equivalence
@ -409,7 +410,10 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
result = isNone result = isNone
assert(f != nil) assert(f != nil)
assert(a != nil) assert(aOrig != nil)
# var and static arguments match regular modifier-free types
let a = aOrig.skipTypes({tyStatic, tyVar})
if a.kind == tyGenericInst and if a.kind == tyGenericInst and
skipTypes(f, {tyVar}).kind notin { skipTypes(f, {tyVar}).kind notin {
@ -417,11 +421,8 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
tyGenericParam} + tyTypeClasses: tyGenericParam} + tyTypeClasses:
return typeRel(c, f, lastSon(a)) return typeRel(c, f, lastSon(a))
if a.kind == tyVar and f.kind != tyVar:
return typeRel(c, f, a.sons[0])
template bindingRet(res) = template bindingRet(res) =
when res == isGeneric: put(c.bindings, f, a) when res == isGeneric: put(c.bindings, f, aOrig)
return res return res
case a.kind case a.kind
@ -495,9 +496,9 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
of tyFloat32: result = handleFloatRange(f, a) of tyFloat32: result = handleFloatRange(f, a)
of tyFloat64: result = handleFloatRange(f, a) of tyFloat64: result = handleFloatRange(f, a)
of tyFloat128: result = handleFloatRange(f, a) of tyFloat128: result = handleFloatRange(f, a)
of tyVar: of tyVar:
if a.kind == f.kind: result = typeRel(c, base(f), base(a)) if aOrig.kind == tyVar: result = typeRel(c, f.base, aOrig.base)
else: result = typeRel(c, base(f), a) else: result = typeRel(c, f.base, aOrig)
of tyArray, tyArrayConstr: of tyArray, tyArrayConstr:
# tyArrayConstr cannot happen really, but # tyArrayConstr cannot happen really, but
# we wanna be safe here # we wanna be safe here
@ -551,7 +552,6 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
of tyOrdinal: of tyOrdinal:
if isOrdinalType(a): if isOrdinalType(a):
var x = if a.kind == tyOrdinal: a.sons[0] else: a var x = if a.kind == tyOrdinal: a.sons[0] else: a
if f.sonsLen == 0: if f.sonsLen == 0:
result = isGeneric result = isGeneric
else: else:
@ -683,21 +683,21 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
of tyAnd: of tyAnd:
for branch in f.sons: for branch in f.sons:
if typeRel(c, branch, a) == isNone: if typeRel(c, branch, aOrig) == isNone:
return isNone return isNone
bindingRet isGeneric bindingRet isGeneric
of tyOr: of tyOr:
for branch in f.sons: for branch in f.sons:
if typeRel(c, branch, a) != isNone: if typeRel(c, branch, aOrig) != isNone:
bindingRet isGeneric bindingRet isGeneric
return isNone return isNone
of tyNot: of tyNot:
for branch in f.sons: for branch in f.sons:
if typeRel(c, branch, a) != isNone: if typeRel(c, branch, aOrig) != isNone:
return isNone return isNone
bindingRet isGeneric bindingRet isGeneric
@ -716,7 +716,7 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
var prev = PType(idTableGet(c.bindings, f)) var prev = PType(idTableGet(c.bindings, f))
if prev == nil: if prev == nil:
let targetKind = f.sons[0].kind let targetKind = f.sons[0].kind
if targetKind == a.skipTypes({tyRange}).kind or if targetKind == a.skipTypes({tyRange, tyGenericInst}).kind or
(targetKind in {tyProc, tyPointer} and a.kind == tyNil): (targetKind in {tyProc, tyPointer} and a.kind == tyNil):
put(c.bindings, f, a) put(c.bindings, f, a)
return isGeneric return isGeneric
@ -775,9 +775,9 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
result = typeRel(c, x, a) # check if it fits result = typeRel(c, x, a) # check if it fits
of tyStatic: of tyStatic:
if a.kind == tyStatic: if aOrig.kind == tyStatic:
result = typeRel(c, f.lastSon, a.lastSon) result = typeRel(c, f.lastSon, a)
if result != isNone: put(c.bindings, f, a) if result != isNone: put(c.bindings, f, aOrig)
else: else:
result = isNone result = isNone
@ -788,8 +788,8 @@ proc typeRel(c: var TCandidate, f, a: PType, doBind = true): TTypeRelation =
if f.sonsLen == 0: if f.sonsLen == 0:
result = isGeneric result = isGeneric
else: else:
result = typeRel(c, f, a.sons[0]) result = typeRel(c, f.sons[0], a.sons[0])
if result == isGeneric: if result != isNone:
put(c.bindings, f, a) put(c.bindings, f, a)
else: else:
result = isNone result = isNone
@ -939,7 +939,7 @@ proc ParamTypesMatchAux(m: var TCandidate, f, argType: PType,
arg = argSemantized arg = argSemantized
c = m.c c = m.c
argType = argType argType = argType
if tfHasStatic in fMaybeStatic.flags: if tfHasStatic in fMaybeStatic.flags:
# XXX: When implicit statics are the default # XXX: When implicit statics are the default
# this will be done earlier - we just have to # this will be done earlier - we just have to
@ -950,7 +950,7 @@ proc ParamTypesMatchAux(m: var TCandidate, f, argType: PType,
arg.typ.sons = @[evaluated.typ] arg.typ.sons = @[evaluated.typ]
arg.typ.n = evaluated arg.typ.n = evaluated
argType = arg.typ argType = arg.typ
var var
r: TTypeRelation r: TTypeRelation
a = if c.InTypeClass > 0: argType.skipTypes({tyTypeDesc}) a = if c.InTypeClass > 0: argType.skipTypes({tyTypeDesc})

View file

@ -1,67 +1,67 @@
# Test nested loops and some other things # Test nested loops and some other things
proc andTest() = proc andTest() =
var a = 0 == 5 and 6 == 6 var a = 0 == 5 and 6 == 6
proc incx(x: var int) = # is built-in proc proc incx(x: var int) = # is built-in proc
x = x + 1 x = x + 1
proc decx(x: var int) = proc decx(x: var int) =
x = x - 1 x = x - 1
proc First(y: var int) = proc First(y: var int) =
var x: int var x: int
i_ncx(x) i_ncx(x)
if x == 10: if x == 10:
y = 0 y = 0
else: else:
if x == 0: if x == 0:
incx(x) incx(x)
else: else:
x=11 x=11
proc TestLoops() = proc TestLoops() =
var i, j: int var i, j: int
while i >= 0: while i >= 0:
if i mod 3 == 0: if i mod 3 == 0:
break break
i = i + 1 i = i + 1
while j == 13: while j == 13:
j = 13 j = 13
break break
break break
while True: while True:
break break
proc Foo(n: int): int = proc Foo(n: int): int =
var var
a, old: int a, old: int
b, c: bool b, c: bool
F_irst(a) F_irst(a)
if a == 10: if a == 10:
a = 30 a = 30
elif a == 11: elif a == 11:
a = 22 a = 22
elif a == 12: elif a == 12:
a = 23 a = 23
elif b: elif b:
old = 12 old = 12
else: else:
a = 40 a = 40
# #
b = false or 2 == 0 and 3 == 9 b = false or 2 == 0 and 3 == 9
a = 0 + 3 * 5 + 6 + 7 + +8 # 36 a = 0 + 3 * 5 + 6 + 7 + +8 # 36
while b: while b:
a = a + 3 a = a + 3
a = a + 5 a = a + 5
write(stdout, "Hello!") write(stdout, "Hello!")
# We should come till here :-) # We should come till here :-)
discard Foo(345) discard Foo(345)
# test the new type symbol lookup feature: # test the new type symbol lookup feature:

View file

@ -1,6 +1,6 @@
discard """ discard """
msg: "test 1\ntest 2" msg: "test 1\ntest 2\ntest 3"
output: "TEST 1\nTEST 2\nTEST 2" output: "TEST 1\nTEST 2\nTEST 3"
""" """
import strutils import strutils
@ -10,8 +10,8 @@ proc foo(s: static[string]): string =
const R = s.toUpper const R = s.toUpper
return R return R
echo foo("test 1") echo foo("test 1")
echo foo("test 2") echo foo("test 2")
echo foo("test " & $2) echo foo("test " & $3)

View file

@ -10,9 +10,9 @@ type
TBar[T; I: static[int]] = object TBar[T; I: static[int]] = object
data: array[I, T] data: array[I, T]
#TA1[T; I: static[int]] = array[I, T] TA1[T; I: static[int]] = array[I, T]
#TA2[T; I: static[int]] = array[0..I, T] # TA2[T; I: static[int]] = array[0..I, T]
TA3[T; I: static[int]] = array[I-1, T] # TA3[T; I: static[int]] = array[I-1, T]
proc takeFoo(x: TFoo) = proc takeFoo(x: TFoo) =
echo "abracadabra" echo "abracadabra"
@ -25,7 +25,7 @@ var y: TBar[float, 4]
echo high(y.data) echo high(y.data)
var var
t1: TA1 t1: TA1[float, 1]
t2: TA2 # t2: TA2[string, 4]
t3: TA3 # t3: TA3[int, 10]

View file

@ -1,6 +1,6 @@
discard """ discard """
msg: "int\nstring\nTBar[int]" msg: "int\nstring\nTBar[int]"
output: "int\nstring\nTBar[int]\nint\nrange 0..2\nstring" output: "int\nstring\nTBar[int]\nint\nrange 0..2(int)\nstring"
""" """
import typetraits import typetraits

View file

@ -8,25 +8,11 @@ import
# This macro mimics the using statement from C# # This macro mimics the using statement from C#
# #
# XXX: # It's kept only as a test for the macro system
# It doen't match the C# version exactly yet. # Nimrod's destructors offer a mechanism for automatic
# In particular, it's not recursive, which prevents it from dealing # disposal of resources.
# with exceptions thrown from the variable initializers when multiple.
# variables are used.
# #
# Also, since nimrod relies less on exceptions in general, a more macro autoClose(e: expr): stmt {.immediate.} =
# idiomatic definition could be:
# var x = init()
# if opened(x):
# try:
# body
# finally:
# close(x)
#
# `opened` here could be an overloaded proc which any type can define.
# A common practice can be returing an Optional[Resource] obj for which
# `opened` is defined to `optional.hasValue`
macro using(e: expr): stmt {.immediate.} =
let e = callsite() let e = callsite()
if e.len != 3: if e.len != 3:
error "Using statement: unexpected number of arguments. Got " & error "Using statement: unexpected number of arguments. Got " &
@ -97,7 +83,7 @@ proc close(r: var TResource) =
proc use(r: var TResource) = proc use(r: var TResource) =
write(stdout, "Using " & r.field & ".") write(stdout, "Using " & r.field & ".")
using(r = openResource("test")): autoClose(r = openResource("test")):
use r use r