diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2018-06-27 00:08:21 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-27 00:08:21 +0200 |
commit | d8f7174ddaa19c0e88d1a3ffc851189be2f704df (patch) | |
tree | 732dfb1b8af0b3ce5f2731277fc43355918ad2ff /compiler | |
parent | edc3806aa283c03aa6bae0d9300d381b1150d58d (diff) | |
parent | 101f23f3a65fabd5cba2f03070be1e157e572d79 (diff) | |
download | Nim-d8f7174ddaa19c0e88d1a3ffc851189be2f704df.tar.gz |
Merge pull request #7736 from cooldome/range_float_type
Language feature: range float types
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/semtypes.nim | 4 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 30 | ||||
-rw-r--r-- | compiler/types.nim | 49 |
3 files changed, 60 insertions, 23 deletions
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index a0144500e..d1ebb950c 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -238,8 +238,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(c.config, n.info, "type mismatch") - elif not rangeT[0].isOrdinalType: - localError(c.config, n.info, "ordinal type expected") + elif not rangeT[0].isOrdinalType and rangeT[0].kind notin tyFloat..tyFloat128: + localError(c.config, n.info, "ordinal or float type expected") elif enumHasHoles(rangeT[0]): localError(c.config, n.info, "enum '$1' has holes" % typeToString(rangeT[0])) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 784b5c11c..84e59349e 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -637,20 +637,22 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation = else: discard proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} = - let - a0 = firstOrd(nil, a) - a1 = lastOrd(nil, a) - f0 = firstOrd(nil, f) - f1 = lastOrd(nil, 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 + template checkRange[T](a0, a1, f0, f1: T): TTypeRelation = + if a0 == f0 and a1 == f1: + isEqual + elif a0 >= f0 and a1 <= f1: + isConvertible + elif a0 <= f1 and f0 <= a1: + # X..Y and C..D overlap iff (X <= D and C <= Y) + isConvertible + else: + isNone + + if f.isOrdinalType: + checkRange(firstOrd(nil, a), lastOrd(nil, a), firstOrd(nil, f), lastOrd(nil, f)) + else: + checkRange(firstFloat(a), lastFloat(a), firstFloat(f), lastFloat(f)) + proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType = var diff --git a/compiler/types.nim b/compiler/types.nim index f78e975ee..16a84dee6 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -89,13 +89,16 @@ proc isPureObject*(typ: PType): bool = proc getOrdValue*(n: PNode): BiggestInt = case n.kind - of nkCharLit..nkUInt64Lit: result = n.intVal - of nkNilLit: result = 0 - of nkHiddenStdConv: result = getOrdValue(n.sons[1]) - else: - #localError(n.info, errOrdinalTypeExpected) - # XXX check usages of getOrdValue - result = high(BiggestInt) + of nkCharLit..nkUInt64Lit: n.intVal + of nkNilLit: 0 + of nkHiddenStdConv: getOrdValue(n.sons[1]) + else: high(BiggestInt) + +proc getFloatValue*(n: PNode): BiggestFloat = + case n.kind + of nkFloatLiterals: n.floatVal + of nkHiddenStdConv: getFloatValue(n.sons[1]) + else: NaN proc isIntLit*(t: PType): bool {.inline.} = result = t.kind == tyInt and t.n != nil and t.n.kind == nkIntLit @@ -593,6 +596,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = result = typeToStr[t.kind] result.addTypeFlags(t) + proc firstOrd*(conf: ConfigRef; t: PType): BiggestInt = case t.kind of tyBool, tyChar, tySequence, tyOpenArray, tyString, tyVarargs, tyProxy: @@ -627,6 +631,21 @@ proc firstOrd*(conf: ConfigRef; t: PType): BiggestInt = internalError(conf, "invalid kind for firstOrd(" & $t.kind & ')') result = 0 + +proc firstFloat*(t: PType): BiggestFloat = + case t.kind + of tyFloat..tyFloat128: -Inf + of tyRange: + assert(t.n != nil) # range directly given: + assert(t.n.kind == nkRange) + getFloatValue(t.n.sons[0]) + of tyVar: firstFloat(t.sons[0]) + of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tyStatic, tyInferred: + firstFloat(lastSon(t)) + else: + internalError(newPartialConfigRef(), "invalid kind for firstFloat(" & $t.kind & ')') + NaN + proc lastOrd*(conf: ConfigRef; t: PType; fixedUnsigned = false): BiggestInt = case t.kind of tyBool: result = 1 @@ -667,6 +686,22 @@ proc lastOrd*(conf: ConfigRef; t: PType; fixedUnsigned = false): BiggestInt = internalError(conf, "invalid kind for lastOrd(" & $t.kind & ')') result = 0 + +proc lastFloat*(t: PType): BiggestFloat = + case t.kind + of tyFloat..tyFloat128: Inf + of tyVar: lastFloat(t.sons[0]) + of tyRange: + assert(t.n != nil) # range directly given: + assert(t.n.kind == nkRange) + getFloatValue(t.n.sons[1]) + of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tyStatic, tyInferred: + lastFloat(lastSon(t)) + else: + internalError(newPartialConfigRef(), "invalid kind for lastFloat(" & $t.kind & ')') + NaN + + proc lengthOrd*(conf: ConfigRef; t: PType): BiggestInt = case t.kind of tyInt64, tyInt32, tyInt: result = lastOrd(conf, t) |