mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-03 10:24:44 +00:00
changed integer promotion rules; added math.fmod
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -188,7 +188,7 @@ type
|
||||
Tid* {.importc: "id_t", header: "<sys/types.h>".} = int
|
||||
Tino* {.importc: "ino_t", header: "<sys/types.h>".} = int
|
||||
TKey* {.importc: "key_t", header: "<sys/types.h>".} = int
|
||||
TMode* {.importc: "mode_t", header: "<sys/types.h>".} = int
|
||||
TMode* {.importc: "mode_t", header: "<sys/types.h>".} = cint
|
||||
TNlink* {.importc: "nlink_t", header: "<sys/types.h>".} = int
|
||||
TOff* {.importc: "off_t", header: "<sys/types.h>".} = int64
|
||||
TPid* {.importc: "pid_t", header: "<sys/types.h>".} = int
|
||||
|
||||
@@ -188,6 +188,8 @@ when not defined(ECMAScript):
|
||||
proc floor*(x: float): float {.importc: "floor", nodecl.}
|
||||
proc ceil*(x: float): float {.importc: "ceil", nodecl.}
|
||||
|
||||
proc fmod*(x, y: float): float {.importc: "fmod", header: "<math.h>".}
|
||||
|
||||
else:
|
||||
proc mathrandom(): float {.importc: "Math.random", nodecl.}
|
||||
proc floor*(x: float): float {.importc: "Math.floor", nodecl.}
|
||||
@@ -230,10 +232,13 @@ else:
|
||||
var y = exp(2.0*x)
|
||||
return (y-1.0)/(y+1.0)
|
||||
|
||||
proc `mod`*(x, y: float): float =
|
||||
result = if y == 0.0: x else: x - y * (x/y).floor
|
||||
|
||||
type
|
||||
TRunningStat* = object ## an accumulator for statistical data
|
||||
n*: int ## number of pushed data
|
||||
sum*, min*, max*, mean*: float ## self-explaining
|
||||
TRunningStat* {.pure,final.} = object ## an accumulator for statistical data
|
||||
n*: int ## number of pushed data
|
||||
sum*, min*, max*, mean*: float ## self-explaining
|
||||
oldM, oldS, newS: float
|
||||
|
||||
proc push*(s: var TRunningStat, x: float) =
|
||||
|
||||
@@ -23,7 +23,7 @@ when defined(posix):
|
||||
const
|
||||
PROT_READ = 1 # page can be read
|
||||
PROT_WRITE = 2 # page can be written
|
||||
MAP_PRIVATE = 2 # Changes are private
|
||||
MAP_PRIVATE = 2'i32 # Changes are private
|
||||
|
||||
when defined(macosx) or defined(bsd):
|
||||
const MAP_ANONYMOUS = 0x1000
|
||||
@@ -40,7 +40,7 @@ when defined(posix):
|
||||
|
||||
proc osAllocPages(size: int): pointer {.inline.} =
|
||||
result = mmap(nil, size, PROT_READ or PROT_WRITE,
|
||||
MAP_PRIVATE or MAP_ANONYMOUS, -1, 0)
|
||||
MAP_PRIVATE or MAP_ANONYMOUS, -1, 0)
|
||||
if result == nil or result == cast[pointer](-1):
|
||||
raiseOutOfMem()
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
{.push hints:off}
|
||||
|
||||
proc c_strcmp(a, b: CString): cint {.nodecl, noSideEffect, importc: "strcmp".}
|
||||
proc c_memcmp(a, b: CString, size: cint): cint {.
|
||||
proc c_memcmp(a, b: CString, size: int): cint {.
|
||||
nodecl, noSideEffect, importc: "memcmp".}
|
||||
proc c_memcpy(a, b: CString, size: cint) {.nodecl, importc: "memcpy".}
|
||||
proc c_memcpy(a, b: CString, size: int) {.nodecl, importc: "memcpy".}
|
||||
proc c_strlen(a: CString): int {.nodecl, noSideEffect, importc: "strlen".}
|
||||
proc c_memset(p: pointer, value: cint, size: int) {.nodecl, importc: "memset".}
|
||||
|
||||
|
||||
@@ -199,8 +199,8 @@ proc Open(f: var TFile, filename: string,
|
||||
var p: pointer = fopen(filename, FormatOpen[mode])
|
||||
result = (p != nil)
|
||||
f = cast[TFile](p)
|
||||
if bufSize > 0:
|
||||
if setvbuf(f, nil, IOFBF, bufSize) != 0'i32:
|
||||
if bufSize > 0 and bufSize <= high(cint):
|
||||
if setvbuf(f, nil, IOFBF, bufSize.cint) != 0'i32:
|
||||
raise newException(EOutOfMemory, "out of memory")
|
||||
elif bufSize == 0:
|
||||
discard setvbuf(f, nil, IONBF, 0)
|
||||
|
||||
5
todo.txt
5
todo.txt
@@ -11,6 +11,7 @@ New pragmas:
|
||||
- ``borrow`` needs to take type classes into account
|
||||
- make templates hygienic by default: try to gensym() everything in the 'block'
|
||||
of a template; find a better solution for gensym instead of `*ident`
|
||||
- introduce ``;`` to the parser
|
||||
- make use of ``tyIter`` to fix the implicit items/pairs issue
|
||||
- ``=`` should be overloadable; requires specialization for ``=``
|
||||
- optimize genericAssign in the code generator
|
||||
@@ -21,8 +22,7 @@ New pragmas:
|
||||
- implement "closure tuple consists of a single 'ref'" optimization
|
||||
|
||||
- document 'do' notation
|
||||
- unsigned ints and bignums; requires abstract integer literal type:
|
||||
use tyInt+node for that
|
||||
- finish support for unsigned ints
|
||||
- rethink the syntax: distinction between expr and stmt is unfortunate;
|
||||
indentation handling is quite complex too; problem with exception handling
|
||||
is that often the scope of ``try`` is wrong and apart from that ``try`` is
|
||||
@@ -100,6 +100,7 @@ Library
|
||||
Low priority
|
||||
------------
|
||||
|
||||
- bignums
|
||||
- change how comments are part of the AST
|
||||
- ``with proc `+`(x, y: T): T`` for generic code
|
||||
- new feature: ``distinct T with operations``
|
||||
|
||||
Reference in New Issue
Block a user