summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/msgs.nim5
-rw-r--r--compiler/semtypes.nim4
-rw-r--r--compiler/sigmatch.nim33
-rw-r--r--compiler/types.nim192
4 files changed, 145 insertions, 89 deletions
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 5ae2c4970..e16a5cea2 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -46,7 +46,8 @@ type
     errInvalidArgForX, errStmtHasNoEffect, errXExpectsTypeOrValue,
     errXExpectsArrayType, errIteratorCannotBeInstantiated, errExprXAmbiguous,
     errConstantDivisionByZero, errOrdinalTypeExpected,
-    errOrdinalOrFloatTypeExpected, errOverOrUnderflow,
+    errOrdinalOrFloatTypeExpected, errFloatTypeExpected, errStringTypeExpected,
+    errOverOrUnderflow,
     errCannotEvalXBecauseIncompletelyDefined, errChrExpectsRange0_255,
     errDynlibRequiresExportc, errUndeclaredFieldX, errNilAccess,
     errIndexOutOfBounds, errIndexTypesDoNotMatch, errBracketsInvalidForType,
@@ -219,6 +220,8 @@ const
     errConstantDivisionByZero: "division by zero",
     errOrdinalTypeExpected: "ordinal type expected",
     errOrdinalOrFloatTypeExpected: "ordinal or float type expected",
+    errFloatTypeExpected: "float type expected",
+    errStringTypeExpected: "string type expected",
     errOverOrUnderflow: "over- or underflow",
     errCannotEvalXBecauseIncompletelyDefined: "cannot evaluate '$1' because type is not defined completely",
     errChrExpectsRange0_255: "\'chr\' expects an int in the range 0..255",
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 1fc263617..0d1688d33 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -205,8 +205,8 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
   if not hasUnknownTypes:
     if not sameType(rangeT[0].skipTypes({tyRange}), rangeT[1].skipTypes({tyRange})):
       localError(n.info, errPureTypeMismatch)
-    elif not rangeT[0].isOrdinalType:
-      localError(n.info, errOrdinalTypeExpected)
+    elif not rangeT[0].isOrdinalType and rangeT[0].kind notin tyFloat..tyFloat128:
+      localError(n.info, errOrdinalOrFloatTypeExpected)
     elif enumHasHoles(rangeT[0]):
       localError(n.info, errEnumXHasHoles, rangeT[0].sym.name.s)
 
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 96d815df7..cb821c02f 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -628,20 +628,27 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
   else: discard
 
 proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
-  let
-    a0 = firstOrd(a)
-    a1 = lastOrd(a)
-    f0 = firstOrd(f)
-    f1 = lastOrd(f)
-  if a0 == f0 and a1 == f1:
-    result = isEqual
-  elif a0 >= f0 and a1 <= f1:
-    result = isConvertible
-  elif a0 <= f1 and f0 <= a1:
-    # X..Y and C..D overlap iff (X <= D and C <= Y)
-    result = isConvertible
+  template check_range_in(t: typedesc): untyped = 
+    let
+      a0 = firstValue[t](a)
+      a1 = lastValue[t](a)
+      f0 = firstValue[t](f)
+      f1 = lastValue[t](f)
+    if a0 == f0 and a1 == f1:
+      result = isEqual
+    elif a0 >= f0 and a1 <= f1:
+      result = isConvertible
+    elif a0 <= f1 and f0 <= a1:
+      # X..Y and C..D overlap iff (X <= D and C <= Y)
+      result = isConvertible
+    else:
+      result = isNone
+  
+  if f.isOrdinalType: 
+    check_range_in(BiggestInt)
   else:
-    result = isNone
+    check_range_in(BiggestFloat)
+    
 
 proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
   var
diff --git a/compiler/types.nim b/compiler/types.nim
index 5d60fa9b4..19e61a332 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -86,14 +86,33 @@ proc isPureObject*(typ: PType): bool =
     t = t.sons[0].skipTypes(skipPtrs)
   result = t.sym != nil and sfPure in t.sym.flags
 
-proc getOrdValue*(n: PNode): BiggestInt =
+proc getValue*[T:BiggestInt|BiggestFloat|string](n: PNode): T =
+  ## get value of liternal node
   case n.kind
-  of nkCharLit..nkUInt64Lit: result = n.intVal
-  of nkNilLit: result = 0
-  of nkHiddenStdConv: result = getOrdValue(n.sons[1])
+  of nkNilLit: reset(result)
+  of nkHiddenStdConv: result = getValue[T](n.sons[1])
   else:
-    localError(n.info, errOrdinalTypeExpected)
-    result = 0
+    when T is BiggestInt:
+      case n.kind
+      of nkCharLit..nkUInt64Lit: result = n.intVal
+      else:
+        localError(n.info, errOrdinalTypeExpected)
+        result = 0
+    elif T is BiggestFloat:
+      case n.kind
+      of nkFloatLiterals: result = n.floatVal
+      else:
+        localError(n.info, errFloatTypeExpected)
+        result = NaN
+    else:
+      case n.kind:
+      of nkStrLit..nkTripleStrLit: result = n.strVal
+      else:
+        localError(n.info, errStringTypeExpected)
+        result = nil
+
+proc getOrdValue*(n: PNode): BiggestInt {.inline.} =
+  getValue[BiggestInt](n)
 
 proc isIntLit*(t: PType): bool {.inline.} =
   result = t.kind == tyInt and t.n != nil and t.n.kind == nkIntLit
@@ -587,79 +606,106 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
     result = typeToStr[t.kind]
   result.addTypeFlags(t)
 
-proc firstOrd*(t: PType): BiggestInt =
-  case t.kind
-  of tyBool, tyChar, tySequence, tyOpenArray, tyString, tyVarargs, tyProxy:
-    result = 0
-  of tySet, tyVar: result = firstOrd(t.sons[0])
-  of tyArray: result = firstOrd(t.sons[0])
-  of tyRange:
-    assert(t.n != nil)        # range directly given:
-    assert(t.n.kind == nkRange)
-    result = getOrdValue(t.n.sons[0])
-  of tyInt:
-    if platform.intSize == 4: result = - (2147483646) - 2
-    else: result = 0x8000000000000000'i64
-  of tyInt8: result = - 128
-  of tyInt16: result = - 32768
-  of tyInt32: result = - 2147483646 - 2
-  of tyInt64: result = 0x8000000000000000'i64
-  of tyUInt..tyUInt64: result = 0
-  of tyEnum:
-    # if basetype <> nil then return firstOrd of basetype
-    if sonsLen(t) > 0 and t.sons[0] != nil:
-      result = firstOrd(t.sons[0])
+proc firstValue*[T:BiggestInt|BiggestFloat](t: PType): T =
+  case t.kind:
+    of tyVar: result = firstValue[T](t.sons[0])
+    of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias:
+      result = firstValue[T](lastSon(t))
+    of tyRange:
+      assert(t.n != nil)        # range directly given:
+      assert(t.n.kind == nkRange)
+      result = getValue[T](t.n.sons[0])
     else:
-      assert(t.n.sons[0].kind == nkSym)
-      result = t.n.sons[0].sym.position
-  of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias:
-    result = firstOrd(lastSon(t))
-  of tyOrdinal:
-    if t.len > 0: result = firstOrd(lastSon(t))
-    else: internalError("invalid kind for first(" & $t.kind & ')')
-  else:
-    internalError("invalid kind for first(" & $t.kind & ')')
-    result = 0
-
-proc lastOrd*(t: PType; fixedUnsigned = false): BiggestInt =
+      when T is BiggestInt:
+        case t.kind:
+        of tyBool, tyChar, tySequence, tyOpenArray, tyString, tyVarargs, tyProxy:
+          result = 0
+        of tySet, tyVar: result = firstValue[T](t.sons[0])
+        of tyArray: result = firstValue[T](t.sons[0])
+        of tyInt:
+          if platform.intSize == 4: result = - (2147483646) - 2
+          else: result = 0x8000000000000000'i64
+        of tyInt8: result = - 128
+        of tyInt16: result = - 32768
+        of tyInt32: result = - 2147483646 - 2
+        of tyInt64: result = 0x8000000000000000'i64
+        of tyUInt..tyUInt64: result = 0
+        of tyEnum:
+          # if basetype <> nil then return firstOrd of basetype
+          if sonsLen(t) > 0 and t.sons[0] != nil:
+            result = firstValue[T](t.sons[0])
+          else:
+            assert(t.n.sons[0].kind == nkSym)
+            result = t.n.sons[0].sym.position
+        of tyOrdinal:
+          if t.len > 0: result = firstValue[T](lastSon(t))
+          else: internalError("invalid kind for first(" & $t.kind & ')')
+        else:
+          internalError("invalid kind for first(" & $t.kind & ')')
+          result = 0
+
+      elif T is BiggestFloat:
+        case t.kind:
+          of tyFloat..tyFloat128: result = -Inf
+          else:
+            internalError("invalid kind for first(" & $t.kind & ')')
+            result = NaN
+
+proc firstOrd*(t: PType): BiggestInt {.inline.} =
+  firstValue[BiggestInt](t)
+
+proc lastValue*[T:BiggestInt|BiggestFloat](t: PType; fixedUnsigned = false): T =
   case t.kind
-  of tyBool: result = 1
-  of tyChar: result = 255
-  of tySet, tyVar: result = lastOrd(t.sons[0])
-  of tyArray: result = lastOrd(t.sons[0])
+  of tyVar: result = lastValue[T](t.sons[0])
+  of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias:
+    result = lastValue[T](lastSon(t))
   of tyRange:
     assert(t.n != nil)        # range directly given:
     assert(t.n.kind == nkRange)
-    result = getOrdValue(t.n.sons[1])
-  of tyInt:
-    if platform.intSize == 4: result = 0x7FFFFFFF
-    else: result = 0x7FFFFFFFFFFFFFFF'i64
-  of tyInt8: result = 0x0000007F
-  of tyInt16: result = 0x00007FFF
-  of tyInt32: result = 0x7FFFFFFF
-  of tyInt64: result = 0x7FFFFFFFFFFFFFFF'i64
-  of tyUInt:
-    if platform.intSize == 4: result = 0xFFFFFFFF
-    elif fixedUnsigned: result = 0xFFFFFFFFFFFFFFFF'i64
-    else: result = 0x7FFFFFFFFFFFFFFF'i64
-  of tyUInt8: result = 0xFF
-  of tyUInt16: result = 0xFFFF
-  of tyUInt32: result = 0xFFFFFFFF
-  of tyUInt64:
-    if fixedUnsigned: result = 0xFFFFFFFFFFFFFFFF'i64
-    else: result = 0x7FFFFFFFFFFFFFFF'i64
-  of tyEnum:
-    assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
-    result = t.n.sons[sonsLen(t.n) - 1].sym.position
-  of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias:
-    result = lastOrd(lastSon(t))
-  of tyProxy: result = 0
-  of tyOrdinal:
-    if t.len > 0: result = lastOrd(lastSon(t))
-    else: internalError("invalid kind for last(" & $t.kind & ')')
+    result = getValue[T](t.n.sons[1])
   else:
-    internalError("invalid kind for last(" & $t.kind & ')')
-    result = 0
+    when T is BiggestInt:
+      case t.kind
+      of tyBool: result = 1
+      of tyChar: result = 255
+      of tySet, tyArray: result = lastValue[T](t.sons[0])
+      of tyInt:
+        if platform.intSize == 4: result = 0x7FFFFFFF
+        else: result = 0x7FFFFFFFFFFFFFFF'i64
+      of tyInt8: result = 0x0000007F
+      of tyInt16: result = 0x00007FFF
+      of tyInt32: result = 0x7FFFFFFF
+      of tyInt64: result = 0x7FFFFFFFFFFFFFFF'i64
+      of tyUInt:
+        if platform.intSize == 4: result = 0xFFFFFFFF
+        elif fixedUnsigned: result = 0xFFFFFFFFFFFFFFFF'i64
+        else: result = 0x7FFFFFFFFFFFFFFF'i64
+      of tyUInt8: result = 0xFF
+      of tyUInt16: result = 0xFFFF
+      of tyUInt32: result = 0xFFFFFFFF
+      of tyUInt64:
+        if fixedUnsigned: result = 0xFFFFFFFFFFFFFFFF'i64
+        else: result = 0x7FFFFFFFFFFFFFFF'i64
+      of tyEnum:
+        assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
+        result = t.n.sons[sonsLen(t.n) - 1].sym.position
+
+      of tyProxy: result = 0
+      of tyOrdinal:
+        if t.len > 0: result = lastValue[T](lastSon(t))
+        else: internalError("invalid kind for last(" & $t.kind & ')')
+      else:
+        internalError("invalid kind for last(" & $t.kind & ')')
+        result = 0
+    elif T is BiggestFloat:
+      case t.kind:
+        of tyFloat..tyFloat128: result = Inf
+        else:
+          internalError("invalid kind for first(" & $t.kind & ')')
+          result = NaN
+
+proc lastOrd*(t: PType; fixedUnsigned = false): BiggestInt {.inline.}= 
+  lastValue[BiggestInt](t, fixedUnsigned)
 
 proc lengthOrd*(t: PType): BiggestInt =
   case t.kind