make more tests green
This commit is contained in:
parent
eb1d23c0c7
commit
66a2556525
15 changed files with 176 additions and 162 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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})
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue