summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-03-25 00:47:03 +0100
committerAraq <rumpf_a@web.de>2011-03-25 00:47:03 +0100
commit032599c156260a0892522b6ce858b1cdff08df84 (patch)
tree582c86f5e7a23595e1253af47133be3c4764da1f
parent220dd54acfd5527c7c569811013b178fc462898e (diff)
downloadNim-032599c156260a0892522b6ce858b1cdff08df84.tar.gz
bugfix: type converter that converts to bool in 'if' context
-rwxr-xr-xlib/system.nim5
-rwxr-xr-xrod/evals.nim1
-rwxr-xr-xrod/sem.nim30
-rwxr-xr-xrod/semexprs.nim3
-rwxr-xr-xrod/semstmts.nim12
-rwxr-xr-xrod/semtypes.nim9
-rwxr-xr-xrod/sigmatch.nim6
-rw-r--r--tests/accept/compile/tcan_alias_generic.nim11
-rw-r--r--tests/accept/compile/tcan_alias_specialised_generic.nim11
-rw-r--r--tests/accept/compile/ttypeconverter1.nim6
-rw-r--r--tests/reject/tno_int_in_bool_context.nim8
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?"
+