diff options
author | Araq <rumpf_a@web.de> | 2011-03-25 00:47:03 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-03-25 00:47:03 +0100 |
commit | 032599c156260a0892522b6ce858b1cdff08df84 (patch) | |
tree | 582c86f5e7a23595e1253af47133be3c4764da1f | |
parent | 220dd54acfd5527c7c569811013b178fc462898e (diff) | |
download | Nim-032599c156260a0892522b6ce858b1cdff08df84.tar.gz |
bugfix: type converter that converts to bool in 'if' context
-rwxr-xr-x | lib/system.nim | 5 | ||||
-rwxr-xr-x | rod/evals.nim | 1 | ||||
-rwxr-xr-x | rod/sem.nim | 30 | ||||
-rwxr-xr-x | rod/semexprs.nim | 3 | ||||
-rwxr-xr-x | rod/semstmts.nim | 12 | ||||
-rwxr-xr-x | rod/semtypes.nim | 9 | ||||
-rwxr-xr-x | rod/sigmatch.nim | 6 | ||||
-rw-r--r-- | tests/accept/compile/tcan_alias_generic.nim | 11 | ||||
-rw-r--r-- | tests/accept/compile/tcan_alias_specialised_generic.nim | 11 | ||||
-rw-r--r-- | tests/accept/compile/ttypeconverter1.nim | 6 | ||||
-rw-r--r-- | tests/reject/tno_int_in_bool_context.nim | 8 |
11 files changed, 77 insertions, 25 deletions
diff --git a/lib/system.nim b/lib/system.nim index 043275302..a43b0435b 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -87,6 +87,11 @@ proc new*[T](a: var ref T, finalizer: proc (x: ref T)) {. ## freeing the object. Note: The `finalizer` refers to the type `T`, not to ## the object! This means that for each object of type `T` the finalizer ## will be called! + +proc reset*(obj: var T) {.magic: "Reset", noSideEffect.} +proc reset*(obj: ref T) {.noSideEffect.} = reset(obj^) + ## resets an object `obj` to its initial (binary zero) value. This needs to + ## be called before any possible `object branch transition`:idx:. # for low and high the return type T may not be correct, but # we handle that with compiler magic in SemLowHigh() diff --git a/rod/evals.nim b/rod/evals.nim index 37e080d44..f25db3d8a 100755 --- a/rod/evals.nim +++ b/rod/evals.nim @@ -361,6 +361,7 @@ proc evalAsgn(c: PEvalContext, n: PNode): PNode = var x = result result = evalAux(c, n.sons[1], {}) if isSpecial(result): return + when defined(system.reset): reset(x) x.kind = result.kind x.typ = result.typ case x.kind diff --git a/rod/sem.nim b/rod/sem.nim index eec579dda..1ede5f7f8 100755 --- a/rod/sem.nim +++ b/rod/sem.nim @@ -114,17 +114,37 @@ proc semMacroExpr(c: PContext, n: PNode, sym: PSym, dec(evalTemplateCounter) include seminst, semcall - -proc CheckBool(t: PNode) = - if (t.Typ == nil) or - (skipTypes(t.Typ, {tyGenericInst, tyVar, tyOrdinal}).kind != tyBool): - LocalError(t.Info, errExprMustBeBool) proc typeMismatch(n: PNode, formal, actual: PType) = GlobalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) & typeToString(actual) & ") " & `%`(msgKindToString(errButExpectedX), [typeToString(formal)])) +proc fitNode(c: PContext, formal: PType, arg: PNode): PNode = + result = IndexTypesMatch(c, formal, arg.typ, arg) + if result == nil: + #debug(arg) + typeMismatch(arg, formal, arg.typ) + +proc forceBool(c: PContext, n: PNode): PNode = + result = fitNode(c, getSysType(tyBool), n) + if result == nil: result = n + when false: + result = t + if (t.Typ == nil) or + (skipTypes(t.Typ, {tyGenericInst, tyVar, tyOrdinal}).kind != tyBool): + var a = ConvertTo(c, getSysType(tyBool), t) + if a != nil: result = a + else: LocalError(t.Info, errExprMustBeBool) + +proc semConstBoolExpr(c: PContext, n: PNode): PNode = + result = fitNode(c, getSysType(tyBool), semExprWithType(c, n)) + if result == nil: + GlobalError(n.info, errConstExprExpected) + return + result = getConstExpr(c.module, result) + if result == nil: GlobalError(n.info, errConstExprExpected) + include semtypes, semexprs, semgnrc, semstmts proc addCodeForGenerics(c: PContext, n: PNode) = diff --git a/rod/semexprs.nim b/rod/semexprs.nim index 712ce4e6e..cf9900155 100755 --- a/rod/semexprs.nim +++ b/rod/semexprs.nim @@ -792,8 +792,7 @@ proc semIfExpr(c: PContext, n: PNode): PNode = case it.kind of nkElifExpr: checkSonsLen(it, 2) - it.sons[0] = semExprWithType(c, it.sons[0]) - checkBool(it.sons[0]) + it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0])) it.sons[1] = semExprWithType(c, it.sons[1]) if typ == nil: typ = it.sons[1].typ else: it.sons[1] = fitNode(c, typ, it.sons[1]) diff --git a/rod/semstmts.nim b/rod/semstmts.nim index 34b95c936..8f0fc64b5 100755 --- a/rod/semstmts.nim +++ b/rod/semstmts.nim @@ -38,8 +38,7 @@ proc semWhen(c: PContext, n: PNode): PNode = case it.kind of nkElifBranch: checkSonsLen(it, 2) - var e = semConstExpr(c, it.sons[0]) - checkBool(e) + var e = semConstBoolExpr(c, it.sons[0]) if (e.kind != nkIntLit): InternalError(n.info, "semWhen") if (e.intVal != 0) and (result == nil): result = semStmt(c, it.sons[1]) # do not open a new scope! @@ -63,8 +62,7 @@ proc semIf(c: PContext, n: PNode): PNode = of nkElifBranch: checkSonsLen(it, 2) openScope(c.tab) - it.sons[0] = semExprWithType(c, it.sons[0]) - checkBool(it.sons[0]) + it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0])) it.sons[1] = semStmt(c, it.sons[1]) closeScope(c.tab) of nkElse: @@ -121,8 +119,7 @@ proc semWhile(c: PContext, n: PNode): PNode = result = n checkSonsLen(n, 2) openScope(c.tab) - n.sons[0] = semExprWithType(c, n.sons[0]) - CheckBool(n.sons[0]) + n.sons[0] = forceBool(c, semExprWithType(c, n.sons[0])) inc(c.p.nestedLoopCounter) n.sons[1] = semStmt(c, n.sons[1]) dec(c.p.nestedLoopCounter) @@ -162,8 +159,7 @@ proc semCase(c: PContext, n: PNode): PNode = of nkElifBranch: chckCovered = false checkSonsLen(x, 2) - x.sons[0] = semExprWithType(c, x.sons[0]) - checkBool(x.sons[0]) + x.sons[0] = forceBool(c, semExprWithType(c, x.sons[0])) x.sons[1] = semStmtScope(c, x.sons[1]) of nkElse: chckCovered = false diff --git a/rod/semtypes.nim b/rod/semtypes.nim index d2e6cd7f5..ec5bb9e2f 100755 --- a/rod/semtypes.nim +++ b/rod/semtypes.nim @@ -9,12 +9,6 @@ # this module does the semantic checking of type declarations -proc fitNode(c: PContext, formal: PType, arg: PNode): PNode = - result = IndexTypesMatch(c, formal, arg.typ, arg) - if result == nil: - #debug(arg) - typeMismatch(arg, formal, arg.typ) - proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType = if prev == nil: result = newTypeS(kind, c) @@ -355,8 +349,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int, case it.kind of nkElifBranch: checkSonsLen(it, 2) - e = semConstExpr(c, it.sons[0]) - checkBool(e) + e = semConstBoolExpr(c, it.sons[0]) if (e.kind != nkIntLit): InternalError(e.info, "semRecordNodeAux") if (e.intVal != 0) and (branch == nil): branch = it.sons[1] of nkElse: diff --git a/rod/sigmatch.nim b/rod/sigmatch.nim index 2192c168a..8144cff0b 100755 --- a/rod/sigmatch.nim +++ b/rod/sigmatch.nim @@ -461,6 +461,7 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType, var dest = c.converters[i].typ.sons[0] if (typeRel(m.bindings, f, dest) == isEqual) and (typeRel(m.bindings, src, a) == isEqual): + markUsed(arg, c.converters[i]) var s = newSymNode(c.converters[i]) s.typ = c.converters[i].typ s.info = arg.info @@ -564,6 +565,11 @@ proc IndexTypesMatch*(c: PContext, f, a: PType, arg: PNode): PNode = initCandidate(m, f) result = paramTypesMatch(c, m, f, a, arg) +proc ConvertTo*(c: PContext, f: PType, n: PNode): PNode = + var m: TCandidate + initCandidate(m, f) + result = paramTypesMatch(c, m, f, n.typ, n) + proc argtypeMatches*(c: PContext, f, a: PType): bool = var m: TCandidate initCandidate(m, f) diff --git a/tests/accept/compile/tcan_alias_generic.nim b/tests/accept/compile/tcan_alias_generic.nim new file mode 100644 index 000000000..e90bdc6d2 --- /dev/null +++ b/tests/accept/compile/tcan_alias_generic.nim @@ -0,0 +1,11 @@ +## +## can_alias_generic Nimrod Module +## +## Created by Eric Doughty-Papassideris on 2011-02-16. +## Copyright (c) 2011 FWA. All rights reserved. + +type + TGen[T] = object + TGen2[T] = TGen[T] + + diff --git a/tests/accept/compile/tcan_alias_specialised_generic.nim b/tests/accept/compile/tcan_alias_specialised_generic.nim new file mode 100644 index 000000000..9e93e7266 --- /dev/null +++ b/tests/accept/compile/tcan_alias_specialised_generic.nim @@ -0,0 +1,11 @@ +## +## can_alias_specialised_generic Nimrod Module +## +## Created by Eric Doughty-Papassideris on 2011-02-16. +## Copyright (c) 2011 FWA. All rights reserved. + +type + TGen[T] = object + TSpef = TGen[string] + + diff --git a/tests/accept/compile/ttypeconverter1.nim b/tests/accept/compile/ttypeconverter1.nim index 9553f6568..b9a5e88ae 100644 --- a/tests/accept/compile/ttypeconverter1.nim +++ b/tests/accept/compile/ttypeconverter1.nim @@ -1,6 +1,8 @@ converter p(i: int): bool = return i != 0 -if 0: - echo "foo" +if 1: + echo if 4: "foo" else: "barr" +while 0: + echo "bar" diff --git a/tests/reject/tno_int_in_bool_context.nim b/tests/reject/tno_int_in_bool_context.nim new file mode 100644 index 000000000..a98a14826 --- /dev/null +++ b/tests/reject/tno_int_in_bool_context.nim @@ -0,0 +1,8 @@ +discard """ + line: 6 + errormsg: "Error: type mismatch: got (int) but expected 'bool'" +""" + +if 1: + echo "wtf?" + |