bugfixes; field discriminant checks; linearScanEnd, unroll, shallow pragmas
This commit is contained in:
parent
8d734244b1
commit
5b789f2da8
45 changed files with 2342 additions and 243 deletions
|
|
@ -81,7 +81,7 @@ gcc.options.debug = "-g"
|
||||||
@end
|
@end
|
||||||
@else:
|
@else:
|
||||||
@if not release:
|
@if not release:
|
||||||
gcc.options.always = "-w -O1"
|
gcc.options.always = "-w"
|
||||||
@else:
|
@else:
|
||||||
gcc.options.always = "-w"
|
gcc.options.always = "-w"
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -2614,6 +2614,26 @@ The `final`:idx: pragma can be used for an object type to specify that it
|
||||||
cannot be inherited from.
|
cannot be inherited from.
|
||||||
|
|
||||||
|
|
||||||
|
shallow pragma
|
||||||
|
--------------
|
||||||
|
The `shallow`:idx: pragma affects the semantics of a type: The compiler is
|
||||||
|
allowed to make a shallow copy. This can cause serious semantic issues and
|
||||||
|
break memory safety! However, it can speed up assignments considerably,
|
||||||
|
because the semantics of Nimrod require deep copying of sequences and strings.
|
||||||
|
This can be expensive, especially if sequences are used to build a tree
|
||||||
|
structure:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
type
|
||||||
|
TNodeKind = enum nkLeaf, nkInner
|
||||||
|
TNode {.final, shallow.} = object
|
||||||
|
case kind: TNodeKind
|
||||||
|
of nkLeaf:
|
||||||
|
strVal: string
|
||||||
|
of nkInner:
|
||||||
|
children: seq[TNode]
|
||||||
|
|
||||||
|
|
||||||
Pure pragma
|
Pure pragma
|
||||||
-----------
|
-----------
|
||||||
The `pure`:idx: pragma serves two completely different purposes:
|
The `pure`:idx: pragma serves two completely different purposes:
|
||||||
|
|
|
||||||
37
koch.nim
37
koch.nim
|
|
@ -131,28 +131,29 @@ proc findStartNimrod: string =
|
||||||
proc safeRemove(filename: string) =
|
proc safeRemove(filename: string) =
|
||||||
if existsFile(filename): removeFile(filename)
|
if existsFile(filename): removeFile(filename)
|
||||||
|
|
||||||
proc bootIteration(args: string): bool =
|
proc thVersion(i: int): string =
|
||||||
var nimrod1 = "rod" / "nimrod1".exe
|
result = ("rod" / "nimrod" & $i).exe
|
||||||
safeRemove(nimrod1)
|
|
||||||
moveFile(dest=nimrod1, source="rod" / "nimrod".exe)
|
proc copyExe(source, dest: string) =
|
||||||
exec "rod" / "nimrod1 cc $# $# rod/nimrod.nim" % [bootOptions, args]
|
|
||||||
# Nimrod does not produce an executable again if nothing changed. That's ok:
|
|
||||||
result = sameFileContent("rod" / "nimrod".exe, nimrod1)
|
|
||||||
var dest = "bin" / "nimrod".exe
|
|
||||||
safeRemove(dest)
|
safeRemove(dest)
|
||||||
copyFile(dest=dest, source="rod" / "nimrod".exe)
|
copyFile(dest=dest, source=source)
|
||||||
inclFilePermissions(dest, {fpUserExec})
|
inclFilePermissions(dest, {fpUserExec})
|
||||||
safeRemove(nimrod1)
|
|
||||||
if result: echo "executables are equal: SUCCESS!"
|
|
||||||
|
|
||||||
proc boot(args: string) =
|
proc boot(args: string) =
|
||||||
echo "iteration: 1"
|
var output = "rod" / "nimrod".exe
|
||||||
exec findStartNimrod() & " cc $# $# rod" / "nimrod.nim" % [bootOptions, args]
|
var finalDest = "bin" / "nimrod".exe
|
||||||
echo "iteration: 2"
|
|
||||||
if not bootIteration(args):
|
copyExe(findStartNimrod(), 0.thVersion)
|
||||||
echo "executables are not equal: compile once again..."
|
for i in 0..2:
|
||||||
if not bootIteration(args):
|
echo "iteration: ", i+1
|
||||||
echo "[Warning] executables are still not equal"
|
exec i.thVersion & " cc $# $# rod" / "nimrod.nim" % [bootOptions, args]
|
||||||
|
if sameFileContent(output, i.thVersion):
|
||||||
|
copyExe(output, finalDest)
|
||||||
|
echo "executables are equal: SUCCESS!"
|
||||||
|
return
|
||||||
|
copyExe(output, (i+1).thVersion)
|
||||||
|
copyExe(output, finalDest)
|
||||||
|
echo "[Warning] executables are still not equal"
|
||||||
|
|
||||||
# -------------- clean --------------------------------------------------------
|
# -------------- clean --------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
0
lib/impure/rdstdin.nim
Normal file → Executable file
0
lib/impure/rdstdin.nim
Normal file → Executable file
0
lib/pure/algorithm.nim
Normal file → Executable file
0
lib/pure/algorithm.nim
Normal file → Executable file
192
lib/pure/gentabs.nim
Executable file
192
lib/pure/gentabs.nim
Executable file
|
|
@ -0,0 +1,192 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Nimrod's Runtime Library
|
||||||
|
# (c) Copyright 2010 Andreas Rumpf
|
||||||
|
#
|
||||||
|
# See the file "copying.txt", included in this
|
||||||
|
# distribution, for details about the copyright.
|
||||||
|
#
|
||||||
|
|
||||||
|
## The ``gentabs`` module implements an efficient hash table that is a
|
||||||
|
## key-value mapping. The keys are required to be strings, but the values
|
||||||
|
## may be any Nimrod or user defined type. This module supports matching
|
||||||
|
## of keys in case-sensitive, case-insensitive and style-insensitive modes.
|
||||||
|
|
||||||
|
import
|
||||||
|
os, hashes, strutils
|
||||||
|
|
||||||
|
type
|
||||||
|
TGenTableMode* = enum ## describes the table's key matching mode
|
||||||
|
modeCaseSensitive, ## case sensitive matching of keys
|
||||||
|
modeCaseInsensitive, ## case insensitive matching of keys
|
||||||
|
modeStyleInsensitive ## style sensitive matching of keys
|
||||||
|
|
||||||
|
TGenKeyValuePair[T] = tuple[key: string, val: T]
|
||||||
|
TGenKeyValuePairSeq[T] = seq[TGenKeyValuePair[T]]
|
||||||
|
TGenTable*[T] = object of TObject
|
||||||
|
counter: int
|
||||||
|
data: TGenKeyValuePairSeq[T]
|
||||||
|
mode: TGenTableMode
|
||||||
|
|
||||||
|
PGenTable*[T] = ref TGenTable[T] ## use this type to declare hash tables
|
||||||
|
|
||||||
|
|
||||||
|
const
|
||||||
|
growthFactor = 2
|
||||||
|
startSize = 64
|
||||||
|
|
||||||
|
|
||||||
|
proc len*[T](tbl: PGenTable[T]): int {.inline.} =
|
||||||
|
## returns the number of keys in `tbl`.
|
||||||
|
result = tbl.counter
|
||||||
|
|
||||||
|
iterator pairs*[T](tbl: PGenTable[T]): tuple[key: string, value: T] =
|
||||||
|
## iterates over any (key, value) pair in the table `tbl`.
|
||||||
|
for h in 0..high(tbl.data):
|
||||||
|
if not isNil(tbl.data[h].key):
|
||||||
|
yield (tbl.data[h].key, tbl.data[h].val)
|
||||||
|
|
||||||
|
proc myhash[T](tbl: PGenTable[T], key: string): THash =
|
||||||
|
case tbl.mode
|
||||||
|
of modeCaseSensitive: result = hashes.hash(key)
|
||||||
|
of modeCaseInsensitive: result = hashes.hashIgnoreCase(key)
|
||||||
|
of modeStyleInsensitive: result = hashes.hashIgnoreStyle(key)
|
||||||
|
|
||||||
|
proc myCmp[T](tbl: PGenTable[T], a, b: string): bool =
|
||||||
|
case tbl.mode
|
||||||
|
of modeCaseSensitive: result = cmp(a, b) == 0
|
||||||
|
of modeCaseInsensitive: result = cmpIgnoreCase(a, b) == 0
|
||||||
|
of modeStyleInsensitive: result = cmpIgnoreStyle(a, b) == 0
|
||||||
|
|
||||||
|
proc mustRehash(length, counter: int): bool =
|
||||||
|
assert(length > counter)
|
||||||
|
result = (length * 2 < counter * 3) or (length - counter < 4)
|
||||||
|
|
||||||
|
proc newGenTable*[T](mode: TGenTableMode): PGenTable[T] =
|
||||||
|
## creates a new generic hash table that is empty.
|
||||||
|
new(result)
|
||||||
|
result.mode = mode
|
||||||
|
result.counter = 0
|
||||||
|
newSeq(result.data, startSize)
|
||||||
|
|
||||||
|
proc nextTry(h, maxHash: THash): THash {.inline.} =
|
||||||
|
result = ((5 * h) + 1) and maxHash
|
||||||
|
|
||||||
|
proc RawGet[T](tbl: PGenTable[T], key: string): int =
|
||||||
|
var h: THash
|
||||||
|
h = myhash(tbl, key) and high(tbl.data) # start with real hash value
|
||||||
|
while not isNil(tbl.data[h].key):
|
||||||
|
if mycmp(tbl, tbl.data[h].key, key):
|
||||||
|
return h
|
||||||
|
h = nextTry(h, high(tbl.data))
|
||||||
|
result = - 1
|
||||||
|
|
||||||
|
proc RawInsert[T](tbl: PGenTable[T], data: var TGenKeyValuePairSeq[T],
|
||||||
|
key: string, val: T) =
|
||||||
|
var h: THash
|
||||||
|
h = myhash(tbl, key) and high(data)
|
||||||
|
while not isNil(data[h].key):
|
||||||
|
h = nextTry(h, high(data))
|
||||||
|
data[h].key = key
|
||||||
|
data[h].val = val
|
||||||
|
|
||||||
|
proc Enlarge[T](tbl: PGenTable[T]) =
|
||||||
|
var n: TGenKeyValuePairSeq[T]
|
||||||
|
newSeq(n, len(tbl.data) * growthFactor)
|
||||||
|
for i in countup(0, high(tbl.data)):
|
||||||
|
if not isNil(tbl.data[i].key):
|
||||||
|
RawInsert[T](tbl, n, tbl.data[i].key, tbl.data[i].val)
|
||||||
|
swap(tbl.data, n)
|
||||||
|
|
||||||
|
proc hasKey*[T](tbl: PGenTable[T], key: string): bool =
|
||||||
|
## returns true iff `key` is in the table `tbl`.
|
||||||
|
result = rawGet(tbl, key) >= 0
|
||||||
|
|
||||||
|
proc `[]`*[T](tbl: PGenTable[T], key: string): T =
|
||||||
|
## retrieves the value at ``tbl[key]``. If `key` is not in `tbl`,
|
||||||
|
## "" is returned and no exception is raised. One can check
|
||||||
|
## with ``hasKey`` whether the key exists.
|
||||||
|
var index: int
|
||||||
|
index = RawGet(tbl, key)
|
||||||
|
if index >= 0: result = tbl.data[index].val
|
||||||
|
#else: result = "" ### Not sure what to do here
|
||||||
|
|
||||||
|
proc `[]=`*[T](tbl: PGenTable[T], key: string, val: T) =
|
||||||
|
## puts a (key, value)-pair into `tbl`.
|
||||||
|
var index = RawGet(tbl, key)
|
||||||
|
if index >= 0:
|
||||||
|
tbl.data[index].val = val
|
||||||
|
else:
|
||||||
|
if mustRehash(len(tbl.data), tbl.counter): Enlarge(tbl)
|
||||||
|
RawInsert(tbl, tbl.data, key, val)
|
||||||
|
inc(tbl.counter)
|
||||||
|
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
#
|
||||||
|
# Verify tables of integer values (string keys)
|
||||||
|
#
|
||||||
|
var x = newGenTable[int](modeCaseInsensitive)
|
||||||
|
x["one"] = 1
|
||||||
|
x["two"] = 2
|
||||||
|
x["three"] = 3
|
||||||
|
x["four"] = 4
|
||||||
|
x["five"] = 5
|
||||||
|
assert(len(x) == 5) # length procedure works
|
||||||
|
assert(x["one"] == 1) # case-sensitive lookup works
|
||||||
|
assert(x["ONE"] == 1) # case-insensitive should work for this table
|
||||||
|
assert(x["one"]+x["two"] == 3) # make sure we're getting back ints
|
||||||
|
assert(x.hasKey("one")) # hasKey should return 'true' for a key
|
||||||
|
# of "one"...
|
||||||
|
assert(not x.hasKey("NOPE")) # ...but key "NOPE" is not in the table.
|
||||||
|
for k,v in pairs(x): # make sure the 'pairs' iterator works
|
||||||
|
assert(x[k]==v)
|
||||||
|
echo()
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify a table of user-defined types
|
||||||
|
#
|
||||||
|
type
|
||||||
|
TMyType = tuple[first, second: string] # a pair of strings
|
||||||
|
|
||||||
|
var y = newGenTable[TMyType](modeCaseInsensitive) # hash table where each
|
||||||
|
# value is TMyType tuple
|
||||||
|
|
||||||
|
#var junk: TMyType = ("OK", "Here")
|
||||||
|
y["Hello"] = ("Hello", "World")
|
||||||
|
y["Goodbye"] = ("Goodbye", "Everyone")
|
||||||
|
#y["Hello"] = TMyType( ("Hello", "World") )
|
||||||
|
#y["Goodbye"] = TMyType( ("Goodbye", "Everyone") )
|
||||||
|
|
||||||
|
assert( y["Hello"].first == "Hello" )
|
||||||
|
assert( y["Hello"].second == "World" )
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify table of tables
|
||||||
|
#
|
||||||
|
var z: PGenTable[ PGenTable[int] ] # hash table where each value is
|
||||||
|
# a hash table of ints
|
||||||
|
|
||||||
|
z = newGenTable[PGenTable[int]](modeCaseInsensitive)
|
||||||
|
z["first"] = newGenTable[int](modeCaseInsensitive)
|
||||||
|
z["first"]["one"] = 1
|
||||||
|
z["first"]["two"] = 2
|
||||||
|
z["first"]["three"] = 3
|
||||||
|
|
||||||
|
z["second"] = newGenTable[int](modeCaseInsensitive)
|
||||||
|
z["second"]["red"] = 10
|
||||||
|
z["second"]["blue"] = 20
|
||||||
|
|
||||||
|
assert(len(z) == 2) # length of outer table
|
||||||
|
assert(len(z["first"]) == 3) # length of "first" table
|
||||||
|
assert(len(z["second"]) == 2) # length of "second" table
|
||||||
|
assert( z["first"]["one"] == 1) # retrieve from first inner table
|
||||||
|
assert( z["second"]["red"] == 10) # retrieve from second inner table
|
||||||
|
|
||||||
|
for k,v in pairs(z):
|
||||||
|
echo( "$# ($#) ->" % [k,$len(v)] )
|
||||||
|
#for k2,v2 in pairs(v):
|
||||||
|
# echo( " $# <-> $#" % [k2,$v2] )
|
||||||
|
echo()
|
||||||
|
|
@ -708,7 +708,7 @@ else:
|
||||||
# environ is needed, the _NSGetEnviron() routine, defined in
|
# environ is needed, the _NSGetEnviron() routine, defined in
|
||||||
# <crt_externs.h>, can be used to retrieve the address of environ
|
# <crt_externs.h>, can be used to retrieve the address of environ
|
||||||
# at runtime.
|
# at runtime.
|
||||||
proc NSGetEnviron(): cstringArray {.
|
proc NSGetEnviron(): ptr cstringArray {.
|
||||||
importc: "_NSGetEnviron", header: "<crt_externs.h>".}
|
importc: "_NSGetEnviron", header: "<crt_externs.h>".}
|
||||||
else:
|
else:
|
||||||
var gEnv {.importc: "environ".}: cstringArray
|
var gEnv {.importc: "environ".}: cstringArray
|
||||||
|
|
@ -717,7 +717,7 @@ else:
|
||||||
# retrieves the variables of char** env of C's main proc
|
# retrieves the variables of char** env of C's main proc
|
||||||
if not envComputed:
|
if not envComputed:
|
||||||
when defined(macosx):
|
when defined(macosx):
|
||||||
var gEnv = NSGetEnviron()
|
var gEnv = NSGetEnviron()^
|
||||||
var i = 0
|
var i = 0
|
||||||
while True:
|
while True:
|
||||||
if gEnv[i] == nil: break
|
if gEnv[i] == nil: break
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ type
|
||||||
col: int ## column the symbol has been declared/used in
|
col: int ## column the symbol has been declared/used in
|
||||||
flags: set[TNonTerminalFlag] ## the nonterminal's flags
|
flags: set[TNonTerminalFlag] ## the nonterminal's flags
|
||||||
rule: TNode ## the rule that the symbol refers to
|
rule: TNode ## the rule that the symbol refers to
|
||||||
TNode {.final.} = object
|
TNode {.final, shallow.} = object
|
||||||
case kind: TPegKind
|
case kind: TPegKind
|
||||||
of pkEmpty..pkWhitespace: nil
|
of pkEmpty..pkWhitespace: nil
|
||||||
of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle: term: string
|
of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle: term: string
|
||||||
|
|
@ -128,10 +128,12 @@ proc add(d: var TPeg, s: TPeg) {.inline.} = add(d.sons, s)
|
||||||
proc addChoice(dest: var TPeg, elem: TPeg) =
|
proc addChoice(dest: var TPeg, elem: TPeg) =
|
||||||
var L = dest.len-1
|
var L = dest.len-1
|
||||||
if L >= 0 and dest.sons[L].kind == pkCharChoice:
|
if L >= 0 and dest.sons[L].kind == pkCharChoice:
|
||||||
|
# caution! Do not introduce false aliasing here!
|
||||||
case elem.kind
|
case elem.kind
|
||||||
of pkCharChoice:
|
of pkCharChoice:
|
||||||
dest.sons[L].charChoice^ = dest.sons[L].charChoice^ + elem.charChoice^
|
dest.sons[L] = charSet(dest.sons[L].charChoice^ + elem.charChoice^)
|
||||||
of pkChar: incl(dest.sons[L].charChoice^, elem.ch)
|
of pkChar:
|
||||||
|
dest.sons[L] = charSet(dest.sons[L].charChoice^ + {elem.ch})
|
||||||
else: add(dest, elem)
|
else: add(dest, elem)
|
||||||
else: add(dest, elem)
|
else: add(dest, elem)
|
||||||
|
|
||||||
|
|
@ -155,9 +157,12 @@ proc `/`*(a: openArray[TPeg]): TPeg {.
|
||||||
proc addSequence(dest: var TPeg, elem: TPeg) =
|
proc addSequence(dest: var TPeg, elem: TPeg) =
|
||||||
var L = dest.len-1
|
var L = dest.len-1
|
||||||
if L >= 0 and dest.sons[L].kind == pkTerminal:
|
if L >= 0 and dest.sons[L].kind == pkTerminal:
|
||||||
|
# caution! Do not introduce false aliasing here!
|
||||||
case elem.kind
|
case elem.kind
|
||||||
of pkTerminal: add(dest.sons[L].term, elem.term)
|
of pkTerminal:
|
||||||
of pkChar: add(dest.sons[L].term, elem.ch)
|
dest.sons[L] = term(dest.sons[L].term & elem.term)
|
||||||
|
of pkChar:
|
||||||
|
dest.sons[L] = term(dest.sons[L].term & elem.ch)
|
||||||
else: add(dest, elem)
|
else: add(dest, elem)
|
||||||
else: add(dest, elem)
|
else: add(dest, elem)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nimrod's Runtime Library
|
# Nimrod's Runtime Library
|
||||||
# (c) Copyright 2009 Andreas Rumpf
|
# (c) Copyright 2011 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
proc genericAssignAux(dest, src: Pointer, mt: PNimType)
|
proc genericAssignAux(dest, src: Pointer, mt: PNimType, shallow: bool)
|
||||||
proc genericAssignAux(dest, src: Pointer, n: ptr TNimNode) =
|
proc genericAssignAux(dest, src: Pointer, n: ptr TNimNode, shallow: bool) =
|
||||||
var
|
var
|
||||||
d = cast[TAddress](dest)
|
d = cast[TAddress](dest)
|
||||||
s = cast[TAddress](src)
|
s = cast[TAddress](src)
|
||||||
|
|
@ -16,66 +16,69 @@ proc genericAssignAux(dest, src: Pointer, n: ptr TNimNode) =
|
||||||
of nkNone: assert(false)
|
of nkNone: assert(false)
|
||||||
of nkSlot:
|
of nkSlot:
|
||||||
genericAssignAux(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
|
genericAssignAux(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
|
||||||
n.typ)
|
n.typ, shallow)
|
||||||
of nkList:
|
of nkList:
|
||||||
for i in 0..n.len-1:
|
for i in 0..n.len-1:
|
||||||
genericAssignAux(dest, src, n.sons[i])
|
genericAssignAux(dest, src, n.sons[i], shallow)
|
||||||
of nkCase:
|
of nkCase:
|
||||||
copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
|
copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
|
||||||
n.typ.size)
|
n.typ.size)
|
||||||
var m = selectBranch(src, n)
|
var m = selectBranch(src, n)
|
||||||
if m != nil: genericAssignAux(dest, src, m)
|
if m != nil: genericAssignAux(dest, src, m, shallow)
|
||||||
|
|
||||||
proc genericAssignAux(dest, src: Pointer, mt: PNimType) =
|
proc genericAssignAux(dest, src: Pointer, mt: PNimType, shallow: bool) =
|
||||||
var
|
var
|
||||||
d = cast[TAddress](dest)
|
d = cast[TAddress](dest)
|
||||||
s = cast[TAddress](src)
|
s = cast[TAddress](src)
|
||||||
|
|
||||||
assert(mt != nil)
|
assert(mt != nil)
|
||||||
case mt.Kind
|
case mt.Kind
|
||||||
|
of tyString:
|
||||||
|
var x = cast[ppointer](dest)
|
||||||
|
var s2 = cast[ppointer](s)^
|
||||||
|
if s2 == nil or shallow:
|
||||||
|
unsureAsgnRef(x, s2)
|
||||||
|
else:
|
||||||
|
unsureAsgnRef(x, copyString(cast[NimString](s2)))
|
||||||
of tySequence:
|
of tySequence:
|
||||||
var s2 = cast[ppointer](src)^
|
var s2 = cast[ppointer](src)^
|
||||||
var seq = cast[PGenericSeq](s2)
|
var seq = cast[PGenericSeq](s2)
|
||||||
if s2 == nil: # this can happen! nil sequences are allowed
|
var x = cast[ppointer](dest)
|
||||||
var x = cast[ppointer](dest)
|
if s2 == nil or shallow:
|
||||||
x^ = nil
|
# this can happen! nil sequences are allowed
|
||||||
|
unsureAsgnRef(x, s2)
|
||||||
return
|
return
|
||||||
assert(dest != nil)
|
assert(dest != nil)
|
||||||
unsureAsgnRef(cast[ppointer](dest),
|
unsureAsgnRef(x, newObj(mt, seq.len * mt.base.size + GenericSeqSize))
|
||||||
newObj(mt, seq.len * mt.base.size + GenericSeqSize))
|
|
||||||
var dst = cast[taddress](cast[ppointer](dest)^)
|
var dst = cast[taddress](cast[ppointer](dest)^)
|
||||||
for i in 0..seq.len-1:
|
for i in 0..seq.len-1:
|
||||||
genericAssignAux(
|
genericAssignAux(
|
||||||
cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
|
cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
|
||||||
cast[pointer](cast[taddress](s2) +% i *% mt.base.size +%
|
cast[pointer](cast[taddress](s2) +% i *% mt.base.size +%
|
||||||
GenericSeqSize),
|
GenericSeqSize),
|
||||||
mt.Base)
|
mt.Base, shallow)
|
||||||
var dstseq = cast[PGenericSeq](dst)
|
var dstseq = cast[PGenericSeq](dst)
|
||||||
dstseq.len = seq.len
|
dstseq.len = seq.len
|
||||||
dstseq.space = seq.len
|
dstseq.space = seq.len
|
||||||
of tyObject, tyTuple, tyPureObject:
|
of tyObject, tyTuple, tyPureObject:
|
||||||
# we don't need to copy m_type field for tyObject, as they are equal anyway
|
# we don't need to copy m_type field for tyObject, as they are equal anyway
|
||||||
genericAssignAux(dest, src, mt.node)
|
genericAssignAux(dest, src, mt.node, shallow)
|
||||||
of tyArray, tyArrayConstr:
|
of tyArray, tyArrayConstr:
|
||||||
for i in 0..(mt.size div mt.base.size)-1:
|
for i in 0..(mt.size div mt.base.size)-1:
|
||||||
genericAssignAux(cast[pointer](d +% i*% mt.base.size),
|
genericAssignAux(cast[pointer](d +% i*% mt.base.size),
|
||||||
cast[pointer](s +% i*% mt.base.size), mt.base)
|
cast[pointer](s +% i*% mt.base.size), mt.base, shallow)
|
||||||
of tyString: # a leaf
|
of tyRef:
|
||||||
var s2 = cast[ppointer](s)^
|
|
||||||
if s2 != nil: # nil strings are possible!
|
|
||||||
unsureAsgnRef(cast[ppointer](dest), copyString(cast[NimString](s2)))
|
|
||||||
else:
|
|
||||||
var x = cast[ppointer](dest)
|
|
||||||
x^ = nil
|
|
||||||
return
|
|
||||||
of tyRef: # BUGFIX: a long time this has been forgotten!
|
|
||||||
unsureAsgnRef(cast[ppointer](dest), cast[ppointer](s)^)
|
unsureAsgnRef(cast[ppointer](dest), cast[ppointer](s)^)
|
||||||
else:
|
else:
|
||||||
copyMem(dest, src, mt.size) # copy raw bits
|
copyMem(dest, src, mt.size) # copy raw bits
|
||||||
|
|
||||||
proc genericAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} =
|
proc genericAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} =
|
||||||
GC_disable()
|
GC_disable()
|
||||||
genericAssignAux(dest, src, mt)
|
genericAssignAux(dest, src, mt, false)
|
||||||
|
GC_enable()
|
||||||
|
|
||||||
|
proc genericShallowAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} =
|
||||||
|
GC_disable()
|
||||||
|
genericAssignAux(dest, src, mt, true)
|
||||||
GC_enable()
|
GC_enable()
|
||||||
|
|
||||||
proc genericSeqAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} =
|
proc genericSeqAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} =
|
||||||
|
|
@ -152,3 +155,19 @@ proc genericReset(dest: Pointer, mt: PNimType) =
|
||||||
else:
|
else:
|
||||||
zeroMem(dest, mt.size) # set raw bits to zero
|
zeroMem(dest, mt.size) # set raw bits to zero
|
||||||
|
|
||||||
|
proc selectBranch(discVal, L: int,
|
||||||
|
a: ptr array [0..0x7fff, ptr TNimNode]): ptr TNimNode =
|
||||||
|
result = a[L] # a[L] contains the ``else`` part (but may be nil)
|
||||||
|
if discVal <% L:
|
||||||
|
var x = a[discVal]
|
||||||
|
if x != nil: result = x
|
||||||
|
|
||||||
|
proc FieldDiscriminantCheck(oldDiscVal, newDiscVal: int,
|
||||||
|
a: ptr array [0..0x7fff, ptr TNimNode],
|
||||||
|
L: int) {.compilerProc.} =
|
||||||
|
var oldBranch = selectBranch(oldDiscVal, L, a)
|
||||||
|
var newBranch = selectBranch(newDiscVal, L, a)
|
||||||
|
if newBranch != oldBranch and oldDiscVal != 0:
|
||||||
|
raise newException(EInvalidField,
|
||||||
|
"assignment to discriminant changes object branch")
|
||||||
|
|
||||||
|
|
|
||||||
0
lib/wrappers/readline/history.nim
Normal file → Executable file
0
lib/wrappers/readline/history.nim
Normal file → Executable file
0
lib/wrappers/readline/readline.nim
Normal file → Executable file
0
lib/wrappers/readline/readline.nim
Normal file → Executable file
0
lib/wrappers/readline/rltypedefs.nim
Normal file → Executable file
0
lib/wrappers/readline/rltypedefs.nim
Normal file → Executable file
0
lib/wrappers/readline/tweaked/history.h
Normal file → Executable file
0
lib/wrappers/readline/tweaked/history.h
Normal file → Executable file
0
lib/wrappers/readline/tweaked/readline.h
Normal file → Executable file
0
lib/wrappers/readline/tweaked/readline.h
Normal file → Executable file
0
lib/wrappers/readline/tweaked/rltypedefs.h
Normal file → Executable file
0
lib/wrappers/readline/tweaked/rltypedefs.h
Normal file → Executable file
0
lib/wrappers/readline/tweaked/tilde.h
Normal file → Executable file
0
lib/wrappers/readline/tweaked/tilde.h
Normal file → Executable file
120
rod/ccgexprs.nim
120
rod/ccgexprs.nim
|
|
@ -184,6 +184,26 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
appcg(p.module, p.s[cpsStmts], "#unsureAsgnRef((void**) $1, $2);$n",
|
appcg(p.module, p.s[cpsStmts], "#unsureAsgnRef((void**) $1, $2);$n",
|
||||||
[addrLoc(dest), rdLoc(src)])
|
[addrLoc(dest), rdLoc(src)])
|
||||||
|
|
||||||
|
proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
|
# Consider:
|
||||||
|
# type TMyFastString {.shallow.} = string
|
||||||
|
# Due to the implementation of pragmas this would end up to set the
|
||||||
|
# tfShallow flag for the built-in string type too! So we check only
|
||||||
|
# here for this flag, where it is reasonably safe to do so
|
||||||
|
# (for objects, etc.):
|
||||||
|
if needToCopy notin flags or
|
||||||
|
tfShallow in skipTypes(dest.t, abstractVarRange).flags:
|
||||||
|
if (dest.s == OnStack) or not (optRefcGC in gGlobalOptions):
|
||||||
|
appcg(p, cpsStmts,
|
||||||
|
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
|
||||||
|
[addrLoc(dest), addrLoc(src), rdLoc(dest)])
|
||||||
|
else:
|
||||||
|
appcg(p, cpsStmts, "#genericShallowAssign((void*)$1, (void*)$2, $3);$n",
|
||||||
|
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
|
||||||
|
else:
|
||||||
|
appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
|
||||||
|
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
|
||||||
|
|
||||||
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
# This function replaces all other methods for generating
|
# This function replaces all other methods for generating
|
||||||
# the assignment operation in C.
|
# the assignment operation in C.
|
||||||
|
|
@ -192,13 +212,13 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
of tyRef:
|
of tyRef:
|
||||||
genRefAssign(p, dest, src, flags)
|
genRefAssign(p, dest, src, flags)
|
||||||
of tySequence:
|
of tySequence:
|
||||||
if not (needToCopy in flags):
|
if needToCopy notin flags:
|
||||||
genRefAssign(p, dest, src, flags)
|
genRefAssign(p, dest, src, flags)
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
|
appcg(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
|
||||||
[addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t)])
|
[addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t)])
|
||||||
of tyString:
|
of tyString:
|
||||||
if not (needToCopy in flags):
|
if needToCopy notin flags:
|
||||||
genRefAssign(p, dest, src, flags)
|
genRefAssign(p, dest, src, flags)
|
||||||
else:
|
else:
|
||||||
if (dest.s == OnStack) or not (optRefcGC in gGlobalOptions):
|
if (dest.s == OnStack) or not (optRefcGC in gGlobalOptions):
|
||||||
|
|
@ -209,23 +229,15 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
|
appcg(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
|
||||||
[addrLoc(dest), rdLoc(src)])
|
[addrLoc(dest), rdLoc(src)])
|
||||||
of tyTuple:
|
of tyTuple, tyObject:
|
||||||
if needsComplexAssignment(dest.t):
|
|
||||||
appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
|
|
||||||
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
|
|
||||||
else:
|
|
||||||
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
|
||||||
of tyObject:
|
|
||||||
# XXX: check for subtyping?
|
# XXX: check for subtyping?
|
||||||
if needsComplexAssignment(dest.t):
|
if needsComplexAssignment(dest.t):
|
||||||
appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
|
genGenericAsgn(p, dest, src, flags)
|
||||||
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
|
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||||
of tyArray, tyArrayConstr:
|
of tyArray, tyArrayConstr:
|
||||||
if needsComplexAssignment(dest.t):
|
if needsComplexAssignment(dest.t):
|
||||||
appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
|
genGenericAsgn(p, dest, src, flags)
|
||||||
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
|
|
||||||
else:
|
else:
|
||||||
appcg(p, cpsStmts,
|
appcg(p, cpsStmts,
|
||||||
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n",
|
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n",
|
||||||
|
|
@ -363,10 +375,11 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||||
|
|
||||||
proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||||
const
|
const
|
||||||
opr: array[mUnaryMinusI..mAbsI64, string] = ["((NI$2)-($1))", # UnaryMinusI
|
opr: array[mUnaryMinusI..mAbsI64, string] = [
|
||||||
"-($1)", # UnaryMinusI64
|
mUnaryMinusI: "((NI$2)-($1))",
|
||||||
"(NI$2)abs($1)", # AbsI
|
mUnaryMinusI64: "-($1)",
|
||||||
"($1 > 0? ($1) : -($1))"] # AbsI64
|
mAbsI: "(NI$2)abs($1)",
|
||||||
|
mAbsI64: "($1 > 0? ($1) : -($1))"]
|
||||||
var
|
var
|
||||||
a: TLoc
|
a: TLoc
|
||||||
t: PType
|
t: PType
|
||||||
|
|
@ -760,48 +773,69 @@ proc genEcho(p: BProc, n: PNode) =
|
||||||
appcg(p, cpsStmts, "#rawEchoNL();$n")
|
appcg(p, cpsStmts, "#rawEchoNL();$n")
|
||||||
|
|
||||||
proc genCall(p: BProc, t: PNode, d: var TLoc) =
|
proc genCall(p: BProc, t: PNode, d: var TLoc) =
|
||||||
var
|
var op, a: TLoc
|
||||||
param: PSym
|
|
||||||
invalidRetType: bool
|
|
||||||
typ: PType
|
|
||||||
pl: PRope # parameter list
|
|
||||||
op, list, a: TLoc
|
|
||||||
length: int
|
|
||||||
# this is a hotspot in the compiler
|
# this is a hotspot in the compiler
|
||||||
initLocExpr(p, t.sons[0], op)
|
initLocExpr(p, t.sons[0], op)
|
||||||
pl = con(op.r, "(") #typ := getUniqueType(t.sons[0].typ);
|
var pl = con(op.r, "(")
|
||||||
typ = t.sons[0].typ # getUniqueType() is too expensive here!
|
var typ = t.sons[0].typ # getUniqueType() is too expensive here!
|
||||||
assert(typ.kind == tyProc)
|
assert(typ.kind == tyProc)
|
||||||
invalidRetType = isInvalidReturnType(typ.sons[0])
|
var invalidRetType = isInvalidReturnType(typ.sons[0])
|
||||||
length = sonsLen(t)
|
var length = sonsLen(t)
|
||||||
for i in countup(1, length - 1):
|
for i in countup(1, length - 1):
|
||||||
initLocExpr(p, t.sons[i], a) # generate expression for param
|
initLocExpr(p, t.sons[i], a) # generate expression for param
|
||||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||||
if (i < sonsLen(typ)):
|
if (i < sonsLen(typ)):
|
||||||
assert(typ.n.sons[i].kind == nkSym)
|
assert(typ.n.sons[i].kind == nkSym)
|
||||||
param = typ.n.sons[i].sym
|
var param = typ.n.sons[i].sym
|
||||||
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
|
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
|
||||||
else: app(pl, rdLoc(a))
|
else: app(pl, rdLoc(a))
|
||||||
else:
|
else:
|
||||||
app(pl, rdLoc(a))
|
app(pl, rdLoc(a))
|
||||||
if (i < length - 1) or (invalidRetType and (typ.sons[0] != nil)):
|
if i < length - 1: app(pl, ", ")
|
||||||
app(pl, ", ")
|
if typ.sons[0] != nil:
|
||||||
if (typ.sons[0] != nil) and invalidRetType:
|
if invalidRetType:
|
||||||
# XXX (detected by pegs module 64bit): p(result, result) is not
|
if length > 1: app(pl, ", ")
|
||||||
# correct here. Thus we always allocate a temporary:
|
# beware of 'result = p(result)'. We always allocate a temporary:
|
||||||
if d.k == locNone: getTemp(p, typ.sons[0], d)
|
if d.k in {locTemp, locNone}:
|
||||||
app(pl, addrLoc(d))
|
# We already got a temp. Great, special case it:
|
||||||
app(pl, ")")
|
if d.k == locNone: getTemp(p, typ.sons[0], d)
|
||||||
if (typ.sons[0] != nil) and not invalidRetType:
|
app(pl, addrLoc(d))
|
||||||
if d.k == locNone: getTemp(p, typ.sons[0], d)
|
app(pl, ")")
|
||||||
assert(d.t != nil) # generate an assignment to d:
|
app(p.s[cpsStmts], pl)
|
||||||
initLoc(list, locCall, nil, OnUnknown)
|
app(p.s[cpsStmts], ';' & tnl)
|
||||||
list.r = pl
|
else:
|
||||||
genAssignment(p, d, list, {}) # no need for deep copying
|
var tmp: TLoc
|
||||||
|
getTemp(p, typ.sons[0], tmp)
|
||||||
|
app(pl, addrLoc(tmp))
|
||||||
|
app(pl, ")")
|
||||||
|
app(p.s[cpsStmts], pl)
|
||||||
|
app(p.s[cpsStmts], ';' & tnl)
|
||||||
|
genAssignment(p, d, tmp, {}) # no need for deep copying
|
||||||
|
else:
|
||||||
|
app(pl, ")")
|
||||||
|
if d.k == locNone: getTemp(p, typ.sons[0], d)
|
||||||
|
assert(d.t != nil) # generate an assignment to d:
|
||||||
|
var list: TLoc
|
||||||
|
initLoc(list, locCall, nil, OnUnknown)
|
||||||
|
list.r = pl
|
||||||
|
genAssignment(p, d, list, {}) # no need for deep copying
|
||||||
else:
|
else:
|
||||||
|
app(pl, ")")
|
||||||
app(p.s[cpsStmts], pl)
|
app(p.s[cpsStmts], pl)
|
||||||
app(p.s[cpsStmts], ';' & tnl)
|
app(p.s[cpsStmts], ';' & tnl)
|
||||||
|
|
||||||
|
when false:
|
||||||
|
app(pl, ")")
|
||||||
|
if (typ.sons[0] != nil) and not invalidRetType:
|
||||||
|
if d.k == locNone: getTemp(p, typ.sons[0], d)
|
||||||
|
assert(d.t != nil) # generate an assignment to d:
|
||||||
|
initLoc(list, locCall, nil, OnUnknown)
|
||||||
|
list.r = pl
|
||||||
|
genAssignment(p, d, list, {}) # no need for deep copying
|
||||||
|
else:
|
||||||
|
app(p.s[cpsStmts], pl)
|
||||||
|
app(p.s[cpsStmts], ';' & tnl)
|
||||||
|
|
||||||
proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
||||||
# <Nimrod code>
|
# <Nimrod code>
|
||||||
# s = 'Hello ' & name & ', how do you feel?' & 'z'
|
# s = 'Hello ' & name & ', how do you feel?' & 'z'
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
|
||||||
a: TLoc
|
a: TLoc
|
||||||
Labl: TLabel
|
Labl: TLabel
|
||||||
length: int
|
length: int
|
||||||
|
inc(p.withinLoop)
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
assert(sonsLen(t) == 2)
|
assert(sonsLen(t) == 2)
|
||||||
inc(p.labels)
|
inc(p.labels)
|
||||||
|
|
@ -179,6 +180,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
|
||||||
if p.blocks[length].id > 0: appf(p.s[cpsStmts], "} $1: ;$n", [Labl])
|
if p.blocks[length].id > 0: appf(p.s[cpsStmts], "} $1: ;$n", [Labl])
|
||||||
else: app(p.s[cpsStmts], '}' & tnl)
|
else: app(p.s[cpsStmts], '}' & tnl)
|
||||||
setlen(p.blocks, len(p.blocks) - 1)
|
setlen(p.blocks, len(p.blocks) - 1)
|
||||||
|
dec(p.withinLoop)
|
||||||
|
|
||||||
proc genBlock(p: BProc, t: PNode, d: var TLoc) =
|
proc genBlock(p: BProc, t: PNode, d: var TLoc) =
|
||||||
inc(p.labels)
|
inc(p.labels)
|
||||||
|
|
@ -620,20 +622,51 @@ proc genPragma(p: BProc, n: PNode) =
|
||||||
addPendingModule(p.module)
|
addPendingModule(p.module)
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
proc genAsgn(p: BProc, e: PNode) =
|
proc FieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool =
|
||||||
var a: TLoc
|
if optFieldCheck in p.options:
|
||||||
genLineDir(p, e) # BUGFIX
|
var le = asgn.sons[0]
|
||||||
InitLocExpr(p, e.sons[0], a)
|
if le.kind == nkCheckedFieldExpr:
|
||||||
assert(a.t != nil)
|
var field = le.sons[0].sons[1].sym
|
||||||
expr(p, e.sons[1], a)
|
result = sfDiscriminant in field.flags
|
||||||
|
elif le.kind == nkDotExpr:
|
||||||
|
var field = le.sons[1].sym
|
||||||
|
result = sfDiscriminant in field.flags
|
||||||
|
|
||||||
proc genFastAsgn(p: BProc, e: PNode) =
|
proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
|
||||||
var a: TLoc
|
field: PSym) =
|
||||||
genLineDir(p, e) # BUGFIX
|
var t = skipTypes(objtype, abstractVar)
|
||||||
|
assert t.kind == tyObject
|
||||||
|
discard genTypeInfo(p.module, t)
|
||||||
|
var L = lengthOrd(field.typ)
|
||||||
|
if not IntSetContainsOrIncl(p.module.declaredThings, field.id):
|
||||||
|
appcg(p.module, cfsVars, "extern $1",
|
||||||
|
discriminatorTableDecl(p.module, t, field))
|
||||||
|
appcg(p, cpsStmts,
|
||||||
|
"#FieldDiscriminantCheck((NI)(NU)($1), (NI)(NU)($2), $3, $4);$n",
|
||||||
|
[rdLoc(a), rdLoc(tmp), discriminatorTableName(p.module, t, field),
|
||||||
|
intLiteral(L+1)])
|
||||||
|
|
||||||
|
proc asgnFieldDiscriminant(p: BProc, e: PNode) =
|
||||||
|
var a, tmp: TLoc
|
||||||
|
var dotExpr = e.sons[0]
|
||||||
|
var d: PSym
|
||||||
|
if dotExpr.kind == nkCheckedFieldExpr: dotExpr = dotExpr.sons[0]
|
||||||
InitLocExpr(p, e.sons[0], a)
|
InitLocExpr(p, e.sons[0], a)
|
||||||
incl(a.flags, lfNoDeepCopy)
|
getTemp(p, a.t, tmp)
|
||||||
assert(a.t != nil)
|
expr(p, e.sons[1], tmp)
|
||||||
expr(p, e.sons[1], a)
|
genDiscriminantCheck(p, a, tmp, dotExpr.sons[0].typ, dotExpr.sons[1].sym)
|
||||||
|
genAssignment(p, a, tmp, {})
|
||||||
|
|
||||||
|
proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
|
||||||
|
genLineDir(p, e)
|
||||||
|
if not FieldDiscriminantCheckNeeded(p, e):
|
||||||
|
var a: TLoc
|
||||||
|
InitLocExpr(p, e.sons[0], a)
|
||||||
|
if fastAsgn: incl(a.flags, lfNoDeepCopy)
|
||||||
|
assert(a.t != nil)
|
||||||
|
expr(p, e.sons[1], a)
|
||||||
|
else:
|
||||||
|
asgnFieldDiscriminant(p, e)
|
||||||
|
|
||||||
proc genStmts(p: BProc, t: PNode) =
|
proc genStmts(p: BProc, t: PNode) =
|
||||||
var
|
var
|
||||||
|
|
@ -657,8 +690,8 @@ proc genStmts(p: BProc, t: PNode) =
|
||||||
nkCallStrLit:
|
nkCallStrLit:
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
initLocExpr(p, t, a)
|
initLocExpr(p, t, a)
|
||||||
of nkAsgn: genAsgn(p, t)
|
of nkAsgn: genAsgn(p, t, fastAsgn=false)
|
||||||
of nkFastAsgn: genFastAsgn(p, t)
|
of nkFastAsgn: genAsgn(p, t, fastAsgn=true)
|
||||||
of nkDiscardStmt:
|
of nkDiscardStmt:
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
initLocExpr(p, t.sons[0], a)
|
initLocExpr(p, t.sons[0], a)
|
||||||
|
|
@ -684,7 +717,7 @@ proc genStmts(p: BProc, t: PNode) =
|
||||||
(sfExportc in prc.flags and lfExportLib in prc.loc.flags) or
|
(sfExportc in prc.flags and lfExportLib in prc.loc.flags) or
|
||||||
(prc.kind == skMethod):
|
(prc.kind == skMethod):
|
||||||
# we have not only the header:
|
# we have not only the header:
|
||||||
if (t.sons[codePos].kind != nkEmpty) or (lfDynamicLib in prc.loc.flags):
|
if t.sons[codePos].kind != nkEmpty or lfDynamicLib in prc.loc.flags:
|
||||||
genProc(p.module, prc)
|
genProc(p.module, prc)
|
||||||
else: internalError(t.info, "genStmts(" & $t.kind & ')')
|
else: internalError(t.info, "genStmts(" & $t.kind & ')')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,6 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
#var
|
|
||||||
# newDummyVar: int # just to check the symbol file mechanism
|
|
||||||
|
|
||||||
# ------------------------- Name Mangling --------------------------------
|
# ------------------------- Name Mangling --------------------------------
|
||||||
|
|
||||||
proc mangle(name: string): string =
|
proc mangle(name: string): string =
|
||||||
|
|
@ -566,46 +563,51 @@ proc genTypeInfoAux(m: BModule, typ: PType, name: PRope) =
|
||||||
base = toRope("0")
|
base = toRope("0")
|
||||||
genTypeInfoAuxBase(m, typ, name, base)
|
genTypeInfoAuxBase(m, typ, name, base)
|
||||||
|
|
||||||
|
proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): PRope =
|
||||||
|
if objType.sym == nil:
|
||||||
|
InternalError(d.info, "anonymous obj with discriminator")
|
||||||
|
result = ropef("NimDT_$1_$2", [
|
||||||
|
toRope(objType.sym.name.s), toRope(d.name.s)])
|
||||||
|
|
||||||
|
proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): PRope =
|
||||||
|
discard cgsym(m, "TNimNode")
|
||||||
|
var tmp = discriminatorTableName(m, objtype, d)
|
||||||
|
result = ropef("TNimNode* $1[$2];$n", [tmp, toRope(lengthOrd(d.typ)+1)])
|
||||||
|
|
||||||
proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
|
proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
|
||||||
var
|
|
||||||
tmp, tmp2: PRope
|
|
||||||
length, x, y: int
|
|
||||||
field: PSym
|
|
||||||
b: PNode
|
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
length = sonsLen(n)
|
var L = sonsLen(n)
|
||||||
if length == 1:
|
if L == 1:
|
||||||
genObjectFields(m, typ, n.sons[0], expr)
|
genObjectFields(m, typ, n.sons[0], expr)
|
||||||
elif length > 0:
|
elif L > 0:
|
||||||
tmp = getTempName()
|
var tmp = getTempName()
|
||||||
appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n",
|
appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", [tmp, toRope(L)])
|
||||||
[tmp, toRope(length)])
|
for i in countup(0, L-1):
|
||||||
for i in countup(0, length - 1):
|
var tmp2 = getNimNode(m)
|
||||||
tmp2 = getNimNode(m)
|
|
||||||
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(i), tmp2])
|
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(i), tmp2])
|
||||||
genObjectFields(m, typ, n.sons[i], tmp2)
|
genObjectFields(m, typ, n.sons[i], tmp2)
|
||||||
appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
|
appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
|
||||||
[expr, toRope(length), tmp])
|
[expr, toRope(L), tmp])
|
||||||
else:
|
else:
|
||||||
appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2;$n",
|
appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2;$n", [expr, toRope(L)])
|
||||||
[expr, toRope(length)])
|
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
length = sonsLen(n)
|
|
||||||
assert(n.sons[0].kind == nkSym)
|
assert(n.sons[0].kind == nkSym)
|
||||||
field = n.sons[0].sym
|
var field = n.sons[0].sym
|
||||||
tmp = getTempName()
|
var tmp = discriminatorTableName(m, typ, field)
|
||||||
|
var L = lengthOrd(field.typ)
|
||||||
|
assert L > 0
|
||||||
appf(m.s[cfsTypeInit3], "$1.kind = 3;$n" &
|
appf(m.s[cfsTypeInit3], "$1.kind = 3;$n" &
|
||||||
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
|
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
|
||||||
"$1.name = $5;$n" & "$1.sons = &$6[0];$n" &
|
"$1.name = $5;$n" & "$1.sons = &$6[0];$n" &
|
||||||
"$1.len = $7;$n", [expr, getTypeDesc(m, typ), field.loc.r,
|
"$1.len = $7;$n", [expr, getTypeDesc(m, typ), field.loc.r,
|
||||||
genTypeInfo(m, field.typ), makeCString(field.name.s),
|
genTypeInfo(m, field.typ),
|
||||||
tmp, toRope(lengthOrd(field.typ))])
|
makeCString(field.name.s),
|
||||||
appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n",
|
tmp, toRope(L)])
|
||||||
[tmp, toRope(lengthOrd(field.typ) + 1)])
|
appf(m.s[cfsData], "TNimNode* $1[$2];$n", [tmp, toRope(L+1)])
|
||||||
for i in countup(1, length - 1):
|
for i in countup(1, sonsLen(n)-1):
|
||||||
b = n.sons[i] # branch
|
var b = n.sons[i] # branch
|
||||||
tmp2 = getNimNode(m)
|
var tmp2 = getNimNode(m)
|
||||||
genObjectFields(m, typ, lastSon(b), tmp2)
|
genObjectFields(m, typ, lastSon(b), tmp2)
|
||||||
case b.kind
|
case b.kind
|
||||||
of nkOfBranch:
|
of nkOfBranch:
|
||||||
|
|
@ -613,8 +615,8 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
|
||||||
internalError(b.info, "genObjectFields; nkOfBranch broken")
|
internalError(b.info, "genObjectFields; nkOfBranch broken")
|
||||||
for j in countup(0, sonsLen(b) - 2):
|
for j in countup(0, sonsLen(b) - 2):
|
||||||
if b.sons[j].kind == nkRange:
|
if b.sons[j].kind == nkRange:
|
||||||
x = int(getOrdValue(b.sons[j].sons[0]))
|
var x = int(getOrdValue(b.sons[j].sons[0]))
|
||||||
y = int(getOrdValue(b.sons[j].sons[1]))
|
var y = int(getOrdValue(b.sons[j].sons[1]))
|
||||||
while x <= y:
|
while x <= y:
|
||||||
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(x), tmp2])
|
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(x), tmp2])
|
||||||
inc(x)
|
inc(x)
|
||||||
|
|
@ -623,10 +625,10 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
|
||||||
[tmp, toRope(getOrdValue(b.sons[j])), tmp2])
|
[tmp, toRope(getOrdValue(b.sons[j])), tmp2])
|
||||||
of nkElse:
|
of nkElse:
|
||||||
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n",
|
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n",
|
||||||
[tmp, toRope(lengthOrd(field.typ)), tmp2])
|
[tmp, toRope(L), tmp2])
|
||||||
else: internalError(n.info, "genObjectFields(nkRecCase)")
|
else: internalError(n.info, "genObjectFields(nkRecCase)")
|
||||||
of nkSym:
|
of nkSym:
|
||||||
field = n.sym
|
var field = n.sym
|
||||||
appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
|
appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
|
||||||
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
|
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
|
||||||
"$1.name = $5;$n", [expr, getTypeDesc(m, typ),
|
"$1.name = $5;$n", [expr, getTypeDesc(m, typ),
|
||||||
|
|
@ -634,10 +636,9 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
|
||||||
else: internalError(n.info, "genObjectFields")
|
else: internalError(n.info, "genObjectFields")
|
||||||
|
|
||||||
proc genObjectInfo(m: BModule, typ: PType, name: PRope) =
|
proc genObjectInfo(m: BModule, typ: PType, name: PRope) =
|
||||||
var tmp: PRope
|
|
||||||
if typ.kind == tyObject: genTypeInfoAux(m, typ, name)
|
if typ.kind == tyObject: genTypeInfoAux(m, typ, name)
|
||||||
else: genTypeInfoAuxBase(m, typ, name, toRope("0"))
|
else: genTypeInfoAuxBase(m, typ, name, toRope("0"))
|
||||||
tmp = getNimNode(m)
|
var tmp = getNimNode(m)
|
||||||
genObjectFields(m, typ, typ.n, tmp)
|
genObjectFields(m, typ, typ.n, tmp)
|
||||||
appf(m.s[cfsTypeInit3], "$1->node = &$2;$n", [name, tmp])
|
appf(m.s[cfsTypeInit3], "$1->node = &$2;$n", [name, tmp])
|
||||||
|
|
||||||
|
|
@ -742,21 +743,15 @@ proc genTypeInfo(m: BModule, typ: PType): PRope =
|
||||||
[result, toRope(typeToString(t))])
|
[result, toRope(typeToString(t))])
|
||||||
if dataGenerated: return
|
if dataGenerated: return
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyEmpty:
|
of tyEmpty: result = toRope("0")
|
||||||
result = toRope("0")
|
|
||||||
of tyPointer, tyProc, tyBool, tyChar, tyCString, tyString, tyInt..tyFloat128,
|
of tyPointer, tyProc, tyBool, tyChar, tyCString, tyString, tyInt..tyFloat128,
|
||||||
tyVar:
|
tyVar:
|
||||||
genTypeInfoAuxBase(gNimDat, t, result, toRope("0"))
|
genTypeInfoAuxBase(gNimDat, t, result, toRope("0"))
|
||||||
of tyRef, tyPtr, tySequence, tyRange:
|
of tyRef, tyPtr, tySequence, tyRange: genTypeInfoAux(gNimDat, t, result)
|
||||||
genTypeInfoAux(gNimDat, t, result)
|
of tyArrayConstr, tyArray: genArrayInfo(gNimDat, t, result)
|
||||||
of tyArrayConstr, tyArray:
|
of tySet: genSetInfo(gNimDat, t, result)
|
||||||
genArrayInfo(gNimDat, t, result)
|
of tyEnum: genEnumInfo(gNimDat, t, result)
|
||||||
of tySet:
|
of tyObject: genObjectInfo(gNimDat, t, result)
|
||||||
genSetInfo(gNimDat, t, result)
|
|
||||||
of tyEnum:
|
|
||||||
genEnumInfo(gNimDat, t, result)
|
|
||||||
of tyObject:
|
|
||||||
genObjectInfo(gNimDat, t, result)
|
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
if t.n != nil: genObjectInfo(gNimDat, t, result)
|
if t.n != nil: genObjectInfo(gNimDat, t, result)
|
||||||
else: genTupleInfo(gNimDat, t, result)
|
else: genTupleInfo(gNimDat, t, result)
|
||||||
|
|
|
||||||
13
rod/cgen.nim
13
rod/cgen.nim
|
|
@ -77,6 +77,7 @@ type
|
||||||
sendClosure: PType # closure record type that we pass
|
sendClosure: PType # closure record type that we pass
|
||||||
receiveClosure: PType # closure record type that we get
|
receiveClosure: PType # closure record type that we get
|
||||||
module: BModule # used to prevent excessive parameter passing
|
module: BModule # used to prevent excessive parameter passing
|
||||||
|
withinLoop: int # > 0 if we are within a loop
|
||||||
|
|
||||||
TTypeSeq = seq[PType]
|
TTypeSeq = seq[PType]
|
||||||
TCGen = object of TPassContext # represents a C source file
|
TCGen = object of TPassContext # represents a C source file
|
||||||
|
|
@ -131,8 +132,7 @@ proc addPendingModule(m: BModule) =
|
||||||
|
|
||||||
proc findPendingModule(m: BModule, s: PSym): BModule =
|
proc findPendingModule(m: BModule, s: PSym): BModule =
|
||||||
var ms = getModule(s)
|
var ms = getModule(s)
|
||||||
if ms.id == m.module.id:
|
if ms.id == m.module.id: return m
|
||||||
return m
|
|
||||||
for i in countup(0, high(gPendingModules)):
|
for i in countup(0, high(gPendingModules)):
|
||||||
result = gPendingModules[i]
|
result = gPendingModules[i]
|
||||||
if result.module.id == ms.id: return
|
if result.module.id == ms.id: return
|
||||||
|
|
@ -231,6 +231,9 @@ proc appcg(m: BModule, c: var PRope, frmt: TFormatStr,
|
||||||
args: openarray[PRope]) =
|
args: openarray[PRope]) =
|
||||||
app(c, ropecg(m, frmt, args))
|
app(c, ropecg(m, frmt, args))
|
||||||
|
|
||||||
|
proc appcg(m: BModule, s: TCFileSection, frmt: TFormatStr,
|
||||||
|
args: openarray[PRope]) =
|
||||||
|
app(m.s[s], ropecg(m, frmt, args))
|
||||||
|
|
||||||
proc appcg(p: BProc, s: TCProcSection, frmt: TFormatStr,
|
proc appcg(p: BProc, s: TCProcSection, frmt: TFormatStr,
|
||||||
args: openarray[PRope]) =
|
args: openarray[PRope]) =
|
||||||
|
|
@ -248,7 +251,7 @@ proc rdLoc(a: TLoc): PRope =
|
||||||
|
|
||||||
proc addrLoc(a: TLoc): PRope =
|
proc addrLoc(a: TLoc): PRope =
|
||||||
result = a.r
|
result = a.r
|
||||||
if not (lfIndirect in a.flags): result = con("&", result)
|
if lfIndirect notin a.flags: result = con("&", result)
|
||||||
|
|
||||||
proc rdCharLoc(a: TLoc): PRope =
|
proc rdCharLoc(a: TLoc): PRope =
|
||||||
# read a location that may need a char-cast:
|
# read a location that may need a char-cast:
|
||||||
|
|
@ -285,7 +288,7 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags)
|
||||||
proc zeroVar(p: BProc, loc: TLoc, containsGCref: bool) =
|
proc zeroVar(p: BProc, loc: TLoc, containsGCref: bool) =
|
||||||
if skipTypes(loc.t, abstractVarRange).Kind notin
|
if skipTypes(loc.t, abstractVarRange).Kind notin
|
||||||
{tyArray, tyArrayConstr, tySet, tyTuple, tyObject}:
|
{tyArray, tyArrayConstr, tySet, tyTuple, tyObject}:
|
||||||
if containsGcref:
|
if containsGcref and p.WithInLoop > 0:
|
||||||
appf(p.s[cpsInit], "$1 = 0;$n", [rdLoc(loc)])
|
appf(p.s[cpsInit], "$1 = 0;$n", [rdLoc(loc)])
|
||||||
var nilLoc: TLoc
|
var nilLoc: TLoc
|
||||||
initLoc(nilLoc, locTemp, loc.t, onStack)
|
initLoc(nilLoc, locTemp, loc.t, onStack)
|
||||||
|
|
@ -295,7 +298,7 @@ proc zeroVar(p: BProc, loc: TLoc, containsGCref: bool) =
|
||||||
else:
|
else:
|
||||||
appf(p.s[cpsStmts], "$1 = 0;$n", [rdLoc(loc)])
|
appf(p.s[cpsStmts], "$1 = 0;$n", [rdLoc(loc)])
|
||||||
else:
|
else:
|
||||||
if containsGcref:
|
if containsGcref and p.WithInLoop > 0:
|
||||||
appf(p.s[cpsInit], "memset((void*)$1, 0, sizeof($2));$n",
|
appf(p.s[cpsInit], "memset((void*)$1, 0, sizeof($2));$n",
|
||||||
[addrLoc(loc), rdLoc(loc)])
|
[addrLoc(loc), rdLoc(loc)])
|
||||||
appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
||||||
|
|
|
||||||
|
|
@ -200,12 +200,12 @@ proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass,
|
||||||
var id = "" # arg = "X]:on|off"
|
var id = "" # arg = "X]:on|off"
|
||||||
var i = 0
|
var i = 0
|
||||||
var n = hintMin
|
var n = hintMin
|
||||||
while (i < len(arg) + 0) and (arg[i] != ']'):
|
while i < len(arg) and (arg[i] != ']'):
|
||||||
add(id, arg[i])
|
add(id, arg[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
if (i < len(arg) + 0) and (arg[i] == ']'): inc(i)
|
if i < len(arg) and (arg[i] == ']'): inc(i)
|
||||||
else: InvalidCmdLineOption(pass, arg, info)
|
else: InvalidCmdLineOption(pass, arg, info)
|
||||||
if (i < len(arg) + 0) and (arg[i] in {':', '='}): inc(i)
|
if i < len(arg) and (arg[i] in {':', '='}): inc(i)
|
||||||
else: InvalidCmdLineOption(pass, arg, info)
|
else: InvalidCmdLineOption(pass, arg, info)
|
||||||
if state == wHint:
|
if state == wHint:
|
||||||
var x = findStr(msgs.HintsToStr, id)
|
var x = findStr(msgs.HintsToStr, id)
|
||||||
|
|
|
||||||
|
|
@ -432,7 +432,7 @@ proc matchesHyperlink(h: PRstNode, filename: string): bool =
|
||||||
result = matchesHyperlink(h.sons[0], filename)
|
result = matchesHyperlink(h.sons[0], filename)
|
||||||
elif h.kind == rnHyperlink:
|
elif h.kind == rnHyperlink:
|
||||||
var s = addNodes(h.sons[1])
|
var s = addNodes(h.sons[1])
|
||||||
if startsWith(s, filename) and (s[len(filename) + 0] == '#'): result = true
|
if startsWith(s, filename) and (s[len(filename)] == '#'): result = true
|
||||||
else: result = false
|
else: result = false
|
||||||
else:
|
else:
|
||||||
result = false
|
result = false
|
||||||
|
|
|
||||||
0
rod/semcall.nim
Normal file → Executable file
0
rod/semcall.nim
Normal file → Executable file
|
|
@ -412,10 +412,8 @@ proc semDirectCallAnalyseEffects(c: PContext, n: PNode,
|
||||||
flags: TExprFlags): PNode =
|
flags: TExprFlags): PNode =
|
||||||
var symflags = {skProc, skMethod, skConverter}
|
var symflags = {skProc, skMethod, skConverter}
|
||||||
if efWantIterator in flags:
|
if efWantIterator in flags:
|
||||||
symflags = {skIterator}
|
|
||||||
elif efAllowType in flags:
|
|
||||||
# for ``type countup(1,3)``, see ``tests/ttoseq``.
|
# for ``type countup(1,3)``, see ``tests/ttoseq``.
|
||||||
symflags.incl(skIterator)
|
symflags = {skIterator}
|
||||||
result = semDirectCall(c, n, symflags)
|
result = semDirectCall(c, n, symflags)
|
||||||
if result != nil:
|
if result != nil:
|
||||||
if result.sons[0].kind != nkSym:
|
if result.sons[0].kind != nkSym:
|
||||||
|
|
@ -571,7 +569,6 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
|
||||||
check: var PNode): PSym =
|
check: var PNode): PSym =
|
||||||
# transform in a node that contains the runtime check for the
|
# transform in a node that contains the runtime check for the
|
||||||
# field, if it is in a case-part...
|
# field, if it is in a case-part...
|
||||||
var s, it, inExpr, notExpr: PNode
|
|
||||||
result = nil
|
result = nil
|
||||||
case r.kind
|
case r.kind
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
|
|
@ -583,9 +580,9 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
|
||||||
if (r.sons[0].kind != nkSym): IllFormedAst(r)
|
if (r.sons[0].kind != nkSym): IllFormedAst(r)
|
||||||
result = lookupInRecordAndBuildCheck(c, n, r.sons[0], field, check)
|
result = lookupInRecordAndBuildCheck(c, n, r.sons[0], field, check)
|
||||||
if result != nil: return
|
if result != nil: return
|
||||||
s = newNodeI(nkCurly, r.info)
|
var s = newNodeI(nkCurly, r.info)
|
||||||
for i in countup(1, sonsLen(r) - 1):
|
for i in countup(1, sonsLen(r) - 1):
|
||||||
it = r.sons[i]
|
var it = r.sons[i]
|
||||||
case it.kind
|
case it.kind
|
||||||
of nkOfBranch:
|
of nkOfBranch:
|
||||||
result = lookupInRecordAndBuildCheck(c, n, lastSon(it), field, check)
|
result = lookupInRecordAndBuildCheck(c, n, lastSon(it), field, check)
|
||||||
|
|
@ -597,7 +594,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
|
||||||
addSon(check, ast.emptyNode) # make space for access node
|
addSon(check, ast.emptyNode) # make space for access node
|
||||||
s = newNodeI(nkCurly, n.info)
|
s = newNodeI(nkCurly, n.info)
|
||||||
for j in countup(0, sonsLen(it) - 2): addSon(s, copyTree(it.sons[j]))
|
for j in countup(0, sonsLen(it) - 2): addSon(s, copyTree(it.sons[j]))
|
||||||
inExpr = newNodeI(nkCall, n.info)
|
var inExpr = newNodeI(nkCall, n.info)
|
||||||
addSon(inExpr, newIdentNode(getIdent("in"), n.info))
|
addSon(inExpr, newIdentNode(getIdent("in"), n.info))
|
||||||
addSon(inExpr, copyTree(r.sons[0]))
|
addSon(inExpr, copyTree(r.sons[0]))
|
||||||
addSon(inExpr, s) #writeln(output, renderTree(inExpr));
|
addSon(inExpr, s) #writeln(output, renderTree(inExpr));
|
||||||
|
|
@ -609,11 +606,11 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
|
||||||
if check == nil:
|
if check == nil:
|
||||||
check = newNodeI(nkCheckedFieldExpr, n.info)
|
check = newNodeI(nkCheckedFieldExpr, n.info)
|
||||||
addSon(check, ast.emptyNode) # make space for access node
|
addSon(check, ast.emptyNode) # make space for access node
|
||||||
inExpr = newNodeI(nkCall, n.info)
|
var inExpr = newNodeI(nkCall, n.info)
|
||||||
addSon(inExpr, newIdentNode(getIdent("in"), n.info))
|
addSon(inExpr, newIdentNode(getIdent("in"), n.info))
|
||||||
addSon(inExpr, copyTree(r.sons[0]))
|
addSon(inExpr, copyTree(r.sons[0]))
|
||||||
addSon(inExpr, s)
|
addSon(inExpr, s)
|
||||||
notExpr = newNodeI(nkCall, n.info)
|
var notExpr = newNodeI(nkCall, n.info)
|
||||||
addSon(notExpr, newIdentNode(getIdent("not"), n.info))
|
addSon(notExpr, newIdentNode(getIdent("not"), n.info))
|
||||||
addSon(notExpr, inExpr)
|
addSon(notExpr, inExpr)
|
||||||
addSon(check, semExpr(c, notExpr))
|
addSon(check, semExpr(c, notExpr))
|
||||||
|
|
|
||||||
|
|
@ -574,8 +574,10 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkEmpty: nil
|
of nkEmpty: nil
|
||||||
of nkTypeOfExpr:
|
of nkTypeOfExpr:
|
||||||
|
# for ``type countup(1,3)``, see ``tests/ttoseq``.
|
||||||
|
# XXX We should find a better solution.
|
||||||
checkSonsLen(n, 1)
|
checkSonsLen(n, 1)
|
||||||
result = semExprWithType(c, n.sons[0], {efAllowType}).typ
|
result = semExprWithType(c, n.sons[0], {efWantIterator}).typ
|
||||||
of nkPar:
|
of nkPar:
|
||||||
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
|
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
|
||||||
else: GlobalError(n.info, errTypeExpected)
|
else: GlobalError(n.info, errTypeExpected)
|
||||||
|
|
|
||||||
0
rod/semtypinst.nim
Normal file → Executable file
0
rod/semtypinst.nim
Normal file → Executable file
0
rod/suggest.nim
Normal file → Executable file
0
rod/suggest.nim
Normal file → Executable file
0
tests/accept/compile/tfib.nim
Normal file → Executable file
0
tests/accept/compile/tfib.nim
Normal file → Executable file
24
tests/accept/compile/tlinearscanend.nim
Executable file
24
tests/accept/compile/tlinearscanend.nim
Executable file
|
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
import strutils
|
||||||
|
|
||||||
|
var x = 343
|
||||||
|
|
||||||
|
case stdin.readline.parseInt
|
||||||
|
of 0:
|
||||||
|
echo "most common case"
|
||||||
|
of 1:
|
||||||
|
{.linearScanEnd.}
|
||||||
|
echo "second most common case"
|
||||||
|
of 2: echo "unlikely: use branch table"
|
||||||
|
else:
|
||||||
|
echo "unlikely too: use branch table"
|
||||||
|
|
||||||
|
|
||||||
|
case x
|
||||||
|
of 23: echo "23"
|
||||||
|
of 343: echo "343"
|
||||||
|
of 21: echo "21"
|
||||||
|
else:
|
||||||
|
{.linearScanEnd.}
|
||||||
|
echo "default"
|
||||||
|
|
||||||
0
tests/accept/compile/tmacro1.nim
Normal file → Executable file
0
tests/accept/compile/tmacro1.nim
Normal file → Executable file
0
tests/accept/compile/tsortdev.nim
Normal file → Executable file
0
tests/accept/compile/tsortdev.nim
Normal file → Executable file
6
tests/accept/compile/ttypeconverter1.nim
Normal file
6
tests/accept/compile/ttypeconverter1.nim
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
converter p(i: int): bool = return i != 0
|
||||||
|
|
||||||
|
if 0:
|
||||||
|
echo "foo"
|
||||||
|
|
||||||
0
tests/accept/run/tmacro2.nim
Normal file → Executable file
0
tests/accept/run/tmacro2.nim
Normal file → Executable file
0
tests/accept/run/tmacro3.nim
Normal file → Executable file
0
tests/accept/run/tmacro3.nim
Normal file → Executable file
0
tests/accept/run/tmacros1.nim
Normal file → Executable file
0
tests/accept/run/tmacros1.nim
Normal file → Executable file
1769
tests/accept/run/tpegs.nim
Executable file
1769
tests/accept/run/tpegs.nim
Executable file
File diff suppressed because it is too large
Load diff
0
tests/accept/run/tsort.nim
Normal file → Executable file
0
tests/accept/run/tsort.nim
Normal file → Executable file
0
tests/accept/run/ttoseq.nim
Normal file → Executable file
0
tests/accept/run/ttoseq.nim
Normal file → Executable file
5
tests/gc/gcleak.nim
Normal file → Executable file
5
tests/gc/gcleak.nim
Normal file → Executable file
|
|
@ -5,7 +5,10 @@ type
|
||||||
proc MakeObj(): TTestObj =
|
proc MakeObj(): TTestObj =
|
||||||
result.x = "Hello"
|
result.x = "Hello"
|
||||||
|
|
||||||
while true:
|
for i in 1 .. 100_000_000:
|
||||||
var obj = MakeObj()
|
var obj = MakeObj()
|
||||||
|
if getOccupiedMem() > 300_000: quit("still a leak!")
|
||||||
# echo GC_getstatistics()
|
# echo GC_getstatistics()
|
||||||
|
|
||||||
|
echo "no leak: ", getOccupiedMem()
|
||||||
|
|
||||||
|
|
|
||||||
9
tests/gc/gcleak2.nim
Normal file → Executable file
9
tests/gc/gcleak2.nim
Normal file → Executable file
|
|
@ -7,14 +7,13 @@ proc MakeObj(): TTestObj =
|
||||||
result.x = "Hello"
|
result.x = "Hello"
|
||||||
result.s = @[1,2,3]
|
result.s = @[1,2,3]
|
||||||
|
|
||||||
#while true:
|
|
||||||
# var obj = MakeObj()
|
|
||||||
# echo GC_getstatistics()
|
|
||||||
|
|
||||||
proc inProc() =
|
proc inProc() =
|
||||||
while true:
|
for i in 1 .. 100_000_000:
|
||||||
var obj: TTestObj
|
var obj: TTestObj
|
||||||
obj = MakeObj()
|
obj = MakeObj()
|
||||||
|
if getOccupiedMem() > 300_000: quit("still a leak!")
|
||||||
|
|
||||||
inProc()
|
inProc()
|
||||||
|
echo "no leak: ", getOccupiedMem()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
0
tests/reject/ttypenoval.nim
Normal file → Executable file
0
tests/reject/ttypenoval.nim
Normal file → Executable file
11
todo.txt
11
todo.txt
|
|
@ -22,11 +22,13 @@ High priority (version 0.9.0)
|
||||||
Bugs
|
Bugs
|
||||||
----
|
----
|
||||||
- proc (x: int) is passable to proc (x: var int) !?
|
- proc (x: int) is passable to proc (x: var int) !?
|
||||||
- detected by pegs module 64bit: p(result, result) should use a temporary!
|
|
||||||
- the parser allows empty object case branches
|
- the parser allows empty object case branches
|
||||||
- Exception matching needs to take subclasses into account
|
- Exception matching needs to take subclasses into account
|
||||||
- pegs: the anchor '^' does not work because many procs use a linear search
|
- pegs: the anchor '^' does not work because many procs use a linear search
|
||||||
and matchLen()
|
and matchLen()
|
||||||
|
- BUG: generic assign still buggy
|
||||||
|
- Optimization: If we use a temporary for the result anyway the code gen
|
||||||
|
should make use of this fact to generate better code...
|
||||||
|
|
||||||
|
|
||||||
To implement
|
To implement
|
||||||
|
|
@ -51,18 +53,13 @@ Low priority
|
||||||
- find a way to reintroduce the cleanup() pass for C code generation: this
|
- find a way to reintroduce the cleanup() pass for C code generation: this
|
||||||
is hard because of partial evaluation --> symbol files will fix this as
|
is hard because of partial evaluation --> symbol files will fix this as
|
||||||
a side effect
|
a side effect
|
||||||
- implement better error handling: errornous top level statements are ignored
|
|
||||||
and not part of the symbal table --> for REPL
|
|
||||||
--> this needs deletion operation for symbol table!
|
|
||||||
- floating point checks for EcmaScript
|
- floating point checks for EcmaScript
|
||||||
- enhance `` notation for identifier concatenation: `concat` a `these`
|
- enhance `` notation for identifier concatenation: `concat` a `these`
|
||||||
- prefer proc in current module over other procs with same overloading result?
|
- prefer proc in current module over other procs with same overloading result?
|
||||||
- real types for template results
|
- real types for template results
|
||||||
- generalized case statement (requires better transf)
|
- generalized case statement (requires better transf)
|
||||||
- normalize for the DOM
|
|
||||||
- tlastmod returns wrong results on BSD (Linux, MacOS X: works)
|
- tlastmod returns wrong results on BSD (Linux, MacOS X: works)
|
||||||
- nested tuple unpacking
|
- nested tuple unpacking; no auto-unpacking in 'for' loops!
|
||||||
- fast assignment optimization for TPeg
|
|
||||||
- better error messages for used keywords as identifiers
|
- better error messages for used keywords as identifiers
|
||||||
- case statement branches should support constant sets
|
- case statement branches should support constant sets
|
||||||
|
|
||||||
|
|
|
||||||
0
tools/nimgrep.cfg
Normal file → Executable file
0
tools/nimgrep.cfg
Normal file → Executable file
|
|
@ -66,7 +66,7 @@ Additions
|
||||||
- Added ``math.floor``.
|
- Added ``math.floor``.
|
||||||
- The *interactive mode* (REPL) has been improved and documented for the
|
- The *interactive mode* (REPL) has been improved and documented for the
|
||||||
first time.
|
first time.
|
||||||
- Added the ``linearScanEnd`` and ``unroll`` pragmas.
|
- Added the ``linearScanEnd``, ``unroll``, ``shallow`` pragmas.
|
||||||
- The compiler now might use a hashing for string case statements depending
|
- The compiler now might use a hashing for string case statements depending
|
||||||
on the number of string literals in the case statement.
|
on the number of string literals in the case statement.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue