summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-06-28 08:33:25 +0200
committerAraq <rumpf_a@web.de>2012-06-28 08:33:25 +0200
commit2900ceae3580a9f1e83b500cf1abcdfe77762cad (patch)
tree1279b1199dcd7f1af2949355e692b1857960a0ee /compiler
parentb5d34242ca7156ec702f8e63a01c9cd059d28e5f (diff)
downloadNim-2900ceae3580a9f1e83b500cf1abcdfe77762cad.tar.gz
changed integer promotion rules; added math.fmod
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/ast.nim7
-rwxr-xr-xcompiler/magicsys.nim23
-rwxr-xr-xcompiler/msgs.nim8
-rwxr-xr-xcompiler/semexprs.nim24
-rwxr-xr-xcompiler/semfold.nim2
-rwxr-xr-xcompiler/sigmatch.nim56
-rwxr-xr-xcompiler/transf.nim4
7 files changed, 65 insertions, 59 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index d14bef9f7..511d6f116 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -334,12 +334,10 @@ type
     tfEnumHasHoles,   # enum cannot be mapped into a range
     tfShallow,        # type can be shallow copied on assignment
     tfThread,         # proc type is marked as ``thread``
-    tfUniIntLit       # type represents literal value that could be either
-                      # singed or unsigned integer (e.g. 100)
-    tfFromGeneric     # type is an instantiation of a generic; this is needed
+    tfFromGeneric,    # type is an instantiation of a generic; this is needed
                       # because for instantiations of objects, structural
                       # type equality has to be used
-    tfAll             # type class requires all constraints to be met (default)
+    tfAll,            # type class requires all constraints to be met (default)
     tfAny             # type class requires any constraint to be met
 
   TTypeFlags* = set[TTypeFlag]
@@ -587,6 +585,7 @@ type
                               # for range types a nkRange node
                               # for record types a nkRecord node
                               # for enum types a list of symbols
+                              # for tyInt it can be the int literal
                               # else: unused
     destructor*: PSym         # destructor. warning: nil here may not necessary
                               # mean that there is no destructor.
diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim
index a69b40fbf..09c99c027 100755
--- a/compiler/magicsys.nim
+++ b/compiler/magicsys.nim
@@ -24,7 +24,7 @@ proc FinishSystem*(tab: TStrTable)
 proc getSysSym*(name: string): PSym
 # implementation
 
-var 
+var
   gSysTypes: array[TTypeKind, PType]
   compilerprocs: TStrTable
 
@@ -73,7 +73,26 @@ proc getSysType(kind: TTypeKind): PType =
   if result.kind != kind: 
     InternalError("wanted: " & $kind & " got: " & $result.kind)
   if result == nil: InternalError("type not found: " & $kind)
-  
+
+when false:
+  var
+    intTypeCache: array[-5..64, PType]
+
+  proc getIntLitType*(literal: PNode): PType =
+    # we cache some common integer literal types for performance:
+    let value = literal.intVal
+    if value >= low(intTypeCache) and value <= high(intTypeCache):
+      result = intTypeCache[value.int]
+      if result == nil:
+        let ti = getSysType(tyInt)
+        result = copyType(ti, ti.owner, false)
+        result.n = literal
+        intTypeCache[value.int] = result
+    else:
+      let ti = getSysType(tyInt)
+      result = copyType(ti, ti.owner, false)
+      result.n = literal
+
 proc getCompilerProc(name: string): PSym = 
   var ident = getIdent(name, hashIgnoreStyle(name))
   result = StrTableGet(compilerprocs, ident)
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 0b79a68a2..53438c722 100755
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -102,7 +102,7 @@ type
     warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel, 
     warnUnknownSubstitutionX, warnLanguageXNotSupported, warnCommentXIgnored, 
     warnXisPassedToProcVar, warnAnalysisLoophole,
-    warnDifferentHeaps, warnWriteToForeignHeap,
+    warnDifferentHeaps, warnWriteToForeignHeap, warnImplicitNarrowing,
     warnUser, 
     hintSuccess, hintSuccessX, 
     hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded, 
@@ -345,6 +345,7 @@ const
     warnAnalysisLoophole: "thread analysis incomplete due to unkown call '$1' [AnalysisLoophole]",
     warnDifferentHeaps: "possible inconsistency of thread local heaps [DifferentHeaps]",
     warnWriteToForeignHeap: "write to foreign heap [WriteToForeignHeap]",
+    warnImplicitNarrowing: "implicit narrowing conversion: '$1'",
     warnUser: "$1 [User]", 
     hintSuccess: "operation successful [Success]", 
     hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#) [SuccessX]", 
@@ -362,13 +363,14 @@ const
     hintUser: "$1 [User]"]
 
 const
-  WarningsToStr*: array[0..16, string] = ["CannotOpenFile", "OctalEscape", 
+  WarningsToStr*: array[0..17, string] = ["CannotOpenFile", "OctalEscape", 
     "XIsNeverRead", "XmightNotBeenInit",
     "Deprecated", "ConfigDeprecated",
     "SmallLshouldNotBeUsed", "UnknownMagic", 
     "RedefinitionOfLabel", "UnknownSubstitutionX", "LanguageXNotSupported", 
     "CommentXIgnored", "XisPassedToProcVar",
-    "AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap", "User"]
+    "AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap",
+    "ImplicitNarrowing,", "User"]
 
   HintsToStr*: array[0..13, string] = ["Success", "SuccessX", "LineTooLong", 
     "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 00acbbe65..501b7ed72 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1285,20 +1285,6 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
     GlobalError(n.info, errInvalidExpressionX, 
                 renderTree(a, {renderNoComments}))
 
-proc uniIntType(kind: TTypeKind): PType =
-  result = getSysType(kind).copyType(getCurrOwner(), true)
-  result.flags.incl(tfUniIntLit)
-
-template memoize(e: expr): expr =
-  var `*guard` {.global.} = false
-  var `*memo` {.global.} : type(e)
-
-  if not `*guard`:
-    `*memo` = e
-    `*guard` = true
-
-  `*memo`
-
 proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = 
   result = n
   if gCmd == cmdIdeTools: suggestExpr(c, n)
@@ -1319,15 +1305,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     if result.typ == nil: 
       let i = result.intVal
       if i >= low(int32) and i <= high(int32):
-        if i >= 0:
-          result.typ = uniIntType(tyInt).memoize
-        else:
-          result.typ = getSysType(tyInt)
+        result.typ = getSysType(tyInt)
       else:
-        if i >= 0:
-          result.typ = uniIntType(tyInt64).memoize
-        else:
-          result.typ = getSysType(tyInt64)
+        result.typ = getSysType(tyInt64)
   of nkInt8Lit: 
     if result.typ == nil: result.typ = getSysType(tyInt8)
   of nkInt16Lit: 
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index f67e58e2f..66d7e98fc 100755
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -13,7 +13,7 @@
 import 
   strutils, lists, options, ast, astalgo, trees, treetab, nimsets, times, 
   nversion, platform, math, msgs, os, condsyms, idents, renderer, types,
-  commands
+  commands, magicsys
 
 proc getConstExpr*(m: PSym, n: PNode): PNode
   # evaluates the constant expression or returns nil if it is no constant
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 7e985e981..7a5d959df 100755
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -159,16 +159,29 @@ proc concreteType(mapping: TIdTable, t: PType): PType =
 proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation = 
   if a.kind == f.kind: 
     result = isEqual
-  else: 
+  else:
     var k = skipTypes(a, {tyRange}).kind
     if k == f.kind: result = isSubtype
-    elif f.kind == tyInt and k in {tyInt..tyInt32}: result = isIntConv
-    elif f.kind == tyUInt and k in {tyUInt..tyUInt32}: result = isIntConv
-    elif f.kind in {tyUInt..tyUInt64} and k == tyInt and tfUniIntLit in a.flags:
+    elif k == tyInt:
+      # and a.n != nil and a.n.intVal >= firstOrd(f) and
+      #                    a.n.intVal <= lastOrd(f):
+      # integer literal in the proper range; we want ``i16 + 4`` to stay an
+      # ``int16`` operation so we declare the ``4`` pseudo-equal to int16
       result = isIntConv
     elif k >= min and k <= max: result = isConvertible
     else: result = isNone
-  
+    #elif f.kind == tyInt and k in {tyInt..tyInt32}: result = isIntConv
+    #elif f.kind == tyUInt and k in {tyUInt..tyUInt32}: result = isIntConv
+
+proc isConvertibleToRange(f, a: PType): bool =
+  # be less picky for tyRange, as that it is used for array indexing:
+  if f.kind in {tyInt..tyInt64, tyUInt..tyUInt64} and
+     a.kind in {tyInt..tyInt64, tyUInt..tyUInt64}:
+    result = true
+  elif f.kind in {tyFloat..tyFloat128} and
+       a.kind in {tyFloat..tyFloat128}:
+    result = true
+
 proc handleFloatRange(f, a: PType): TTypeRelation = 
   if a.kind == f.kind: 
     result = isEqual
@@ -227,10 +240,10 @@ proc matchTypeClass(mapping: var TIdTable, f, a: PType): TTypeRelation =
       else: nil
 
     if tfAny in f.flags:
-      if match == true:
+      if match:
         return isGeneric
     else:
-      if match == false:
+      if not match:
         return isNone
 
   # if the loop finished without returning, either all constraints matched
@@ -287,9 +300,9 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
   if a.kind == tyGenericInst and
       skipTypes(f, {tyVar}).kind notin {
         tyGenericBody, tyGenericInvokation,
-        tyGenericParam, tyTypeClass }:
+        tyGenericParam, tyTypeClass}:
     return typeRel(mapping, f, lastSon(a))
-  if a.kind == tyVar and f.kind != tyVar: 
+  if a.kind == tyVar and f.kind != tyVar:
     return typeRel(mapping, f, a.sons[0])
   case f.kind
   of tyEnum: 
@@ -302,18 +315,20 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
     if a.kind == f.kind: 
       result = typeRel(mapping, base(a), base(f))
       if result < isGeneric: result = isNone
-    elif skipTypes(f, {tyRange}).kind == a.kind: 
+    elif skipTypes(f, {tyRange}).kind == a.kind:
+      result = isIntConv
+    elif isConvertibleToRange(skipTypes(f, {tyRange}), a):
       result = isConvertible  # a convertible to f
   of tyInt:      result = handleRange(f, a, tyInt8, tyInt32)
   of tyInt8:     result = handleRange(f, a, tyInt8, tyInt8)
   of tyInt16:    result = handleRange(f, a, tyInt8, tyInt16)
-  of tyInt32:    result = handleRange(f, a, tyInt, tyInt32)
+  of tyInt32:    result = handleRange(f, a, tyInt8, tyInt32)
   of tyInt64:    result = handleRange(f, a, tyInt, tyInt64)
-  of tyUInt:      result = handleRange(f, a, tyUInt8, tyUInt32)
-  of tyUInt8:     result = handleRange(f, a, tyUInt8, tyUInt8)
-  of tyUInt16:    result = handleRange(f, a, tyUInt8, tyUInt16)
-  of tyUInt32:    result = handleRange(f, a, tyUInt, tyUInt32)
-  of tyUInt64:    result = handleRange(f, a, tyUInt, tyUInt64)
+  of tyUInt:     result = handleRange(f, a, tyUInt8, tyUInt32)
+  of tyUInt8:    result = handleRange(f, a, tyUInt8, tyUInt8)
+  of tyUInt16:   result = handleRange(f, a, tyUInt8, tyUInt16)
+  of tyUInt32:   result = handleRange(f, a, tyUInt8, tyUInt32)
+  of tyUInt64:   result = handleRange(f, a, tyUInt, tyUInt64)
   of tyFloat:    result = handleFloatRange(f, a)
   of tyFloat32:  result = handleFloatRange(f, a)
   of tyFloat64:  result = handleFloatRange(f, a)
@@ -789,12 +804,3 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
         # use default value:
         setSon(m.call, formal.position + 1, copyTree(formal.ast))
     inc(f)
-
-  when false:
-    if sfSystemModule notin c.module.flags:
-      if fileInfoIdx("temp.nim") == c.module.info.fileIndex:
-        echo "########################"
-        echo m.call.renderTree
-        for i in 1..m.call.len-1:
-          debug m.call[i].typ
-
diff --git a/compiler/transf.nim b/compiler/transf.nim
index f6e87e828..7c2353c54 100755
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -12,7 +12,7 @@
 #
 # * inlines iterators
 # * inlines constants
-# * performes contant folding
+# * performes constant folding
 # * converts "continue" to "break"
 # * introduces method dispatchers
 # * performs lambda lifting for closure support
@@ -401,7 +401,7 @@ proc transformConv(c: PTransf, n: PNode): PTransNode =
       result = transformSons(c, n)
     else: 
       # generate a range check:
-      if (dest.kind == tyInt64) or (source.kind == tyInt64): 
+      if dest.kind == tyInt64 or source.kind == tyInt64: 
         result = newTransNode(nkChckRange64, n, 3)
       else: 
         result = newTransNode(nkChckRange, n, 3)