documented object constrs; endb works again

This commit is contained in:
Araq 2013-03-09 20:43:56 +01:00
commit a64d4dc35c
11 changed files with 152 additions and 143 deletions

View file

@ -709,12 +709,12 @@ proc genFieldCheck(p: BProc, e: PNode, obj: PRope, field: PSym) =
rdLoc(test), strLit) rdLoc(test), strLit)
proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) = proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
if optFieldCheck in p.options:
var var
a: TLoc a: TLoc
f, field: PSym f, field: PSym
ty: PType ty: PType
r: PRope r: PRope
if optFieldCheck in p.options:
ty = genRecordFieldAux(p, e.sons[0], d, a) ty = genRecordFieldAux(p, e.sons[0], d, a)
r = rdLoc(a) r = rdLoc(a)
f = e.sons[0].sons[1].sym f = e.sons[0].sons[1].sym
@ -729,31 +729,6 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
if field.loc.r == nil: if field.loc.r == nil:
InternalError(e.info, "genCheckedRecordField") # generate the checks: InternalError(e.info, "genCheckedRecordField") # generate the checks:
genFieldCheck(p, e, r, field) genFieldCheck(p, e, r, field)
when false:
for i in countup(1, sonsLen(e) - 1):
it = e.sons[i]
assert(it.kind in nkCallKinds)
assert(it.sons[0].kind == nkSym)
op = it.sons[0].sym
if op.magic == mNot: it = it.sons[1]
assert(it.sons[2].kind == nkSym)
initLoc(test, locNone, it.typ, OnStack)
InitLocExpr(p, it.sons[1], u)
initLoc(v, locExpr, it.sons[2].typ, OnUnknown)
v.r = ropef("$1.$2", [r, it.sons[2].sym.loc.r])
genInExprAux(p, it, u, v, test)
id = NodeTableTestOrSet(p.module.dataCache,
newStrNode(nkStrLit, field.name.s), gBackendId)
if id == gBackendId: strLit = getStrLit(p.module, field.name.s)
else: strLit = con("TMP", toRope(id))
if op.magic == mNot:
linefmt(p, cpsStmts,
"if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n",
rdLoc(test), strLit)
else:
linefmt(p, cpsStmts,
"if (!($1)) #raiseFieldError(((#NimStringDesc*) &$2));$n",
rdLoc(test), strLit)
app(r, rfmt(nil, ".$1", field.loc.r)) app(r, rfmt(nil, ".$1", field.loc.r))
putIntoDest(p, d, field.typ, r) putIntoDest(p, d, field.typ, r)
else: else:

View file

@ -45,7 +45,7 @@ proc genVarTuple(p: BProc, n: PNode) =
if t.kind == tyTuple: if t.kind == tyTuple:
field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)]) field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)])
else: else:
if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genVarTuple") if t.n.sons[i].kind != nkSym: InternalError(n.info, "genVarTuple")
field.r = ropef("$1.$2", field.r = ropef("$1.$2",
[rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)]) [rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)])
putLocIntoDest(p, v.loc, field) putLocIntoDest(p, v.loc, field)
@ -64,19 +64,23 @@ proc startBlock(p: BProc, start: TFormatStr = "{$n",
result = len(p.blocks) result = len(p.blocks)
setlen(p.blocks, result + 1) setlen(p.blocks, result + 1)
p.blocks[result].id = p.labels p.blocks[result].id = p.labels
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16
proc assignLabel(b: var TBlock): PRope {.inline.} = proc assignLabel(b: var TBlock): PRope {.inline.} =
b.label = con("LA", b.id.toRope) b.label = con("LA", b.id.toRope)
result = b.label result = b.label
proc blockBody(b: var TBlock): PRope {.inline.} = proc blockBody(b: var TBlock): PRope =
return b.sections[cpsLocals].con(b.sections[cpsInit]).con(b.sections[cpsStmts]) result = b.sections[cpsLocals]
if b.frameLen > 0:
result.appf("F.len+=$1;$n", b.frameLen.toRope)
result.app(b.sections[cpsInit])
result.app(b.sections[cpsStmts])
proc endBlock(p: BProc, blockEnd: PRope) = proc endBlock(p: BProc, blockEnd: PRope) =
let topBlock = p.blocks.len - 1 let topBlock = p.blocks.len-1
# the block is merged into the parent block # the block is merged into the parent block
app(p.blocks[topBlock - 1].sections[cpsStmts], p.blocks[topBlock].blockBody) app(p.blocks[topBlock-1].sections[cpsStmts], p.blocks[topBlock].blockBody)
setlen(p.blocks, topBlock) setlen(p.blocks, topBlock)
# this is done after the block is popped so $n is # this is done after the block is popped so $n is
# properly indented when pretty printing is enabled # properly indented when pretty printing is enabled
@ -84,10 +88,13 @@ proc endBlock(p: BProc, blockEnd: PRope) =
proc endBlock(p: BProc) = proc endBlock(p: BProc) =
let topBlock = p.blocks.len - 1 let topBlock = p.blocks.len - 1
let blockEnd = if p.blocks[topBlock].label != nil: var blockEnd = if p.blocks[topBlock].label != nil:
rfmt(nil, "} $1: ;$n", p.blocks[topBlock].label) rfmt(nil, "} $1: ;$n", p.blocks[topBlock].label)
else: else:
~"}$n" ~"}$n"
let frameLen = p.blocks[topBlock].frameLen
if frameLen > 0:
blockEnd.appf("F.len-=$1;$n", frameLen.toRope)
endBlock(p, blockEnd) endBlock(p, blockEnd)
proc genSimpleBlock(p: BProc, stmts: PNode) {.inline.} = proc genSimpleBlock(p: BProc, stmts: PNode) {.inline.} =
@ -800,12 +807,9 @@ proc genPragma(p: BProc, n: PNode) =
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var it = n.sons[i] var it = n.sons[i]
case whichPragma(it) case whichPragma(it)
of wEmit: of wEmit: genEmit(p, it)
genEmit(p, it) of wBreakpoint: genBreakPoint(p, it)
of wBreakpoint: of wWatchpoint: genWatchpoint(p, it)
genBreakPoint(p, it)
of wWatchpoint:
genWatchpoint(p, it)
else: nil else: nil
proc FieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool = proc FieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool =

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2012 Andreas Rumpf # (c) Copyright 2013 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.
@ -276,11 +276,11 @@ proc genLineDir(p: BProc, t: PNode) =
genCLineDir(p.s(cpsStmts), t.info.toFullPath, line) genCLineDir(p.s(cpsStmts), t.info.toFullPath, line)
if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
(p.prc == nil or sfPure notin p.prc.flags): (p.prc == nil or sfPure notin p.prc.flags):
linefmt(p, cpsStmts, "#endb($1);$n", toRope(line)) linefmt(p, cpsStmts, "#endb($1, $2);$n",
line.toRope, makeCString(toFilename(t.info)))
elif ({optLineTrace, optStackTrace} * p.Options == elif ({optLineTrace, optStackTrace} * p.Options ==
{optLineTrace, optStackTrace}) and {optLineTrace, optStackTrace}) and
(p.prc == nil or sfPure notin p.prc.flags): (p.prc == nil or sfPure notin p.prc.flags):
linefmt(p, cpsStmts, "nimln($1, $2);$n", linefmt(p, cpsStmts, "nimln($1, $2);$n",
line.toRope, t.info.quotedFilename) line.toRope, t.info.quotedFilename)
@ -470,12 +470,13 @@ proc localDebugInfo(p: BProc, s: PSym) =
# XXX work around a bug: No type information for open arrays possible: # XXX work around a bug: No type information for open arrays possible:
if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return
var a = con("&", s.loc.r) var a = con("&", s.loc.r)
if (s.kind == skParam) and ccgIntroducedPtr(s): a = s.loc.r if s.kind == skParam and ccgIntroducedPtr(s): a = s.loc.r
lineF(p, cpsInit, lineF(p, cpsInit,
"F.s[$1].address = (void*)$3; F.s[$1].typ = $4; F.s[$1].name = $2;$n", "F.s[$1].address = (void*)$3; F.s[$1].typ = $4; F.s[$1].name = $2;$n",
[toRope(p.frameLen), makeCString(normalize(s.name.s)), a, [p.maxFrameLen.toRope, makeCString(normalize(s.name.s)), a,
genTypeInfo(p.module, s.loc.t)]) genTypeInfo(p.module, s.loc.t)])
inc(p.frameLen) inc(p.maxFrameLen)
inc p.blocks[p.blocks.len-1].frameLen
proc assignLocalVar(p: BProc, s: PSym) = proc assignLocalVar(p: BProc, s: PSym) =
#assert(s.loc.k == locNone) // not yet assigned #assert(s.loc.k == locNone) // not yet assigned
@ -488,7 +489,7 @@ proc assignLocalVar(p: BProc, s: PSym) =
if sfRegister in s.flags: app(decl, " register") if sfRegister in s.flags: app(decl, " register")
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds: #elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
# app(decl, " GC_GUARD") # app(decl, " GC_GUARD")
if (sfVolatile in s.flags) or (p.nestedTryStmts.len > 0): if sfVolatile in s.flags or p.nestedTryStmts.len > 0:
app(decl, " volatile") app(decl, " volatile")
appf(decl, " $1;$n", [s.loc.r]) appf(decl, " $1;$n", [s.loc.r])
line(p, cpsLocals, decl) line(p, cpsLocals, decl)
@ -693,10 +694,11 @@ proc retIsNotVoid(s: PSym): bool =
proc initFrame(p: BProc, procname, filename: PRope): PRope = proc initFrame(p: BProc, procname, filename: PRope): PRope =
discard cgsym(p.module, "pushFrame") discard cgsym(p.module, "pushFrame")
if p.frameLen > 0: if p.maxFrameLen > 0:
discard cgsym(p.module, "TVarSlot") discard cgsym(p.module, "TVarSlot")
result = rfmt(nil, "\tnimfrs($1, $2, $3)$N", result = rfmt(nil, "\tnimfrs($1, $2, $3, $4)$N",
procname, filename, p.frameLen.toRope) procname, filename, p.maxFrameLen.toRope,
p.blocks[0].frameLen.toRope)
else: else:
result = rfmt(nil, "\tnimfr($1, $2)$N", procname, filename) result = rfmt(nil, "\tnimfr($1, $2)$N", procname, filename)

View file

@ -54,9 +54,10 @@ type
id*: int # the ID of the label; positive means that it id*: int # the ID of the label; positive means that it
label*: PRope # generated text for the label label*: PRope # generated text for the label
# nil if label is not used # nil if label is not used
nestedTryStmts*: int # how many try statements is it nested into
sections*: TCProcSections # the code beloging sections*: TCProcSections # the code beloging
isLoop*: bool # whether block is a loop isLoop*: bool # whether block is a loop
nestedTryStmts*: int16 # how many try statements is it nested into
frameLen*: int16
TCProc{.final.} = object # represents C proc that is currently generated TCProc{.final.} = object # represents C proc that is currently generated
prc*: PSym # the Nimrod proc that this C proc belongs to prc*: PSym # the Nimrod proc that this C proc belongs to
@ -74,9 +75,7 @@ type
options*: TOptions # options that should be used for code options*: TOptions # options that should be used for code
# generation; this is the same as prc.options # generation; this is the same as prc.options
# unless prc == nil # unless prc == nil
frameLen*: int # current length of frame descriptor maxFrameLen*: int # max length of frame descriptor
sendClosure*: PType # closure record type that we pass
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 withinLoop*: int # > 0 if we are within a loop
gcFrameId*: natural # for the GC stack marking gcFrameId*: natural # for the GC stack marking

View file

@ -984,7 +984,7 @@ in future versions of the compiler.
.. code-block:: nimrod .. code-block:: nimrod
type type
TPerson = tuple[name: string, age: int] # type representing a person TPerson = tuple[name: string, age: int] # type representing a person:
# a person consists of a name # a person consists of a name
# and an age # and an age
var var
@ -1000,7 +1000,6 @@ For consistency with ``object`` declarations, tuples in a ``type`` section
can also be defined with indentation instead of ``[]``: can also be defined with indentation instead of ``[]``:
.. code-block:: nimrod .. code-block:: nimrod
type type
TPerson = tuple # type representing a person TPerson = tuple # type representing a person
name: string # a person consists of a name name: string # a person consists of a name
@ -1011,7 +1010,6 @@ and information hiding. Objects have access to their type at runtime, so that
the ``of`` operator can be used to determine the object's type. the ``of`` operator can be used to determine the object's type.
.. code-block:: nimrod .. code-block:: nimrod
type type
TPerson {.inheritable.} = object TPerson {.inheritable.} = object
name*: string # the * means that `name` is accessible from other modules name*: string # the * means that `name` is accessible from other modules
@ -1032,6 +1030,19 @@ and thus have no hidden type field. One can use the ``inheritable`` pragma to
introduce new object roots apart from ``system.TObject``. introduce new object roots apart from ``system.TObject``.
Object construction
-------------------
Objects can also be created with an `object construction expression`:idx: that
has the syntax ``T(fieldA: valueA, fieldB: valueB, ...)`` where ``T`` is
an ``object`` type or a ``ref object`` type:
.. code-block:: nimrod
var student = TStudent(name: "Anton", age: 5, id: 3)
For a ``ref object`` type ``new`` is invoked implicitly.
Object variants Object variants
--------------- ---------------
Often an object hierarchy is overkill in certain situations where simple Often an object hierarchy is overkill in certain situations where simple
@ -1061,16 +1072,23 @@ An example:
of nkIf: of nkIf:
condition, thenPart, elsePart: PNode condition, thenPart, elsePart: PNode
var # create a new case object:
n: PNode var n = PNode(kind: nkIf, condition: nil)
new(n) # creates a new node # accessing n.thenPart is valid because the ``nkIf`` branch is active:
n.kind = nkFloat n.thenPart = PNode(kind: nkFloat, floatVal: 2.0)
n.floatVal = 0.0 # valid, because ``n.kind==nkFloat``, so that it fits
# the following statement raises an `EInvalidField` exception, because # the following statement raises an `EInvalidField` exception, because
# n.kind's value does not fit: # n.kind's value does not fit and the ``nkString`` branch is not active:
n.strVal = "" n.strVal = ""
# invalid: would change the active object branch:
n.kind = nkInt
var x = PNode(kind: nkAdd, leftOp: PNode(kind: nkInt, intVal: 4),
rightOp: PNode(kind: nkInt, intVal: 2))
# valid: does not change the active object branch:
x.kind = nkSub
As can been seen from the example, an advantage to an object hierarchy is that As can been seen from the example, an advantage to an object hierarchy is that
no casting between different object types is needed. Yet, access to invalid no casting between different object types is needed. Yet, access to invalid
object fields raises an exception. object fields raises an exception.
@ -1078,6 +1096,11 @@ object fields raises an exception.
The syntax of ``case`` in an object declaration follows closely the syntax of The syntax of ``case`` in an object declaration follows closely the syntax of
the ``case`` statement: The branches in a ``case`` section may be indented too. the ``case`` statement: The branches in a ``case`` section may be indented too.
In the example the ``kind`` field is called the `discriminator`:idx:\: For
safety its address cannot be taken and assignments to it are restricted: The
new value must not lead to a change of the active object branch. For an object
branch switch ``system.reset`` has to be used.
Set type Set type
-------- --------
@ -2387,6 +2410,7 @@ the proc's name.
Procs as expressions can appear both as nested procs and inside top level Procs as expressions can appear both as nested procs and inside top level
executable code. executable code.
Do notation Do notation
----------- -----------
@ -2410,7 +2434,7 @@ Again, let's see the equivalent of the previous example:
sort(cities) do (x,y: string) -> int: sort(cities) do (x,y: string) -> int:
cmp(x.len, y.len) cmp(x.len, y.len)
Finally, more than one ``do`` blocks can appear in a single call: Finally, more than one ``do`` block can appear in a single call:
.. code-block:: nimrod .. code-block:: nimrod
proc performWithUndo(task: proc(), undo: proc()) = ... proc performWithUndo(task: proc(), undo: proc()) = ...
@ -2426,6 +2450,7 @@ omitted if the supplied proc doesn't have any parameters and return value.
The compatibility works in the other direction too as the ``do`` syntax can be The compatibility works in the other direction too as the ``do`` syntax can be
used with macros and templates expecting ``stmt`` blocks. used with macros and templates expecting ``stmt`` blocks.
Nonoverloadable builtins Nonoverloadable builtins
------------------------ ------------------------
@ -2987,8 +3012,7 @@ possibly raised exceptions; the algorithm operates on ``p``'s call graph:
raise ``system.E_Base`` unless ``q`` has an explicit ``raises`` list. raise ``system.E_Base`` unless ``q`` has an explicit ``raises`` list.
3. Every call to a method ``m`` is assumed to 3. Every call to a method ``m`` is assumed to
raise ``system.E_Base`` unless ``m`` has an explicit ``raises`` list. raise ``system.E_Base`` unless ``m`` has an explicit ``raises`` list.
4. For every other call the analysis can determine an 4. For every other call the analysis can determine an exact ``raises`` list.
exact ``raises`` list.
5. For determining a ``raises`` list, the ``raise`` and ``try`` statements 5. For determining a ``raises`` list, the ``raise`` and ``try`` statements
of ``p`` are taken into consideration. of ``p`` are taken into consideration.
@ -3259,7 +3283,7 @@ Symbol lookup in generics
The symbol binding rules in generics are slightly subtle: There are "open" and The symbol binding rules in generics are slightly subtle: There are "open" and
"closed" symbols. A "closed" symbol cannot be re-bound in the instantiation "closed" symbols. A "closed" symbol cannot be re-bound in the instantiation
context, an "open" symbol can be. Per default overloaded symbols are open context, an "open" symbol can. Per default overloaded symbols are open
and every other symbol is closed. and every other symbol is closed.
Open symbols are looked up in two different contexts: Both the context Open symbols are looked up in two different contexts: Both the context
@ -4106,8 +4130,8 @@ implemented with term rewriting:
proc p(x, y: int; cond: bool): int = proc p(x, y: int; cond: bool): int =
result = if cond: x + y else: x - y result = if cond: x + y else: x - y
template optP{p(x, y, true)}(x, y: expr): expr = x + y template optP1{p(x, y, true)}(x, y: expr): expr = x + y
template optP{p(x, y, false)}(x, y: expr): expr = x - y template optP2{p(x, y, false)}(x, y: expr): expr = x - y
Example: hoisting Example: hoisting

View file

@ -46,8 +46,7 @@ Objects
Like tuples, objects are a means to pack different values together in a Like tuples, objects are a means to pack different values together in a
structured way. However, objects provide many features that tuples do not: structured way. However, objects provide many features that tuples do not:
They provide inheritance and information hiding. Because objects encapsulate They provide inheritance and information hiding. Because objects encapsulate
data, the ``()`` tuple constructor cannot be used to construct objects. So data, the ``T()`` object constructor should only be used internally and the
the order of the object's fields is not as important as it is for tuples. The
programmer should provide a proc to initialize the object (this is called programmer should provide a proc to initialize the object (this is called
a *constructor*). a *constructor*).
@ -55,7 +54,6 @@ Objects have access to their type at runtime. There is an
``of`` operator that can be used to check the object's type: ``of`` operator that can be used to check the object's type:
.. code-block:: nimrod .. code-block:: nimrod
type type
TPerson = object of TObject TPerson = object of TObject
name*: string # the * means that `name` is accessible from other modules name*: string # the * means that `name` is accessible from other modules
@ -68,6 +66,8 @@ Objects have access to their type at runtime. There is an
student: TStudent student: TStudent
person: TPerson person: TPerson
assert(student of TStudent) # is true assert(student of TStudent) # is true
# object construction:
student = TStudent(name: "Anton", age: 5, id: 2)
Object fields that should be visible from outside the defining module have to Object fields that should be visible from outside the defining module have to
be marked by ``*``. In contrast to tuples, different object types are be marked by ``*``. In contrast to tuples, different object types are
@ -161,12 +161,7 @@ An example:
of nkIf: of nkIf:
condition, thenPart, elsePart: PNode condition, thenPart, elsePart: PNode
var var n = PNode(kind: nkFloat, floatVal: 1.0)
n: PNode
new(n) # creates a new node
n.kind = nkFloat
n.floatVal = 0.0 # valid, because ``n.kind==nkFloat``
# the following statement raises an `EInvalidField` exception, because # the following statement raises an `EInvalidField` exception, because
# n.kind's value does not fit: # n.kind's value does not fit:
n.strVal = "" n.strVal = ""
@ -288,30 +283,22 @@ Procedures always use static dispatch. For dynamic dispatch replace the
.. code-block:: nimrod .. code-block:: nimrod
type type
TExpr = object of TObject ## abstract base class for an expression PExpr = ref object of TObject ## abstract base class for an expression
TLiteral = object of TExpr PLiteral = ref object of PExpr
x: int x: int
TPlusExpr = object of TExpr PPlusExpr = ref object of PExpr
a, b: ref TExpr a, b: PExpr
method eval(e: ref TExpr): int = # watch out: 'eval' relies on dynamic binding
method eval(e: PExpr): int =
# override this base method # override this base method
quit "to override!" quit "to override!"
method eval(e: ref TLiteral): int = return e.x method eval(e: PLiteral): int = e.x
method eval(e: PPlusExpr): int = eval(e.a) + eval(e.b)
method eval(e: ref TPlusExpr): int = proc newLit(x: int): PLiteral = PLiteral(x: x)
# watch out: relies on dynamic binding proc newPlus(a, b: PExpr): PPlusExpr = PPlusExpr(a: a, b: b)
return eval(e.a) + eval(e.b)
proc newLit(x: int): ref TLiteral =
new(result)
result.x = x
proc newPlus(a, b: ref TExpr): ref TPlusExpr =
new(result)
result.a = a
result.b = b
echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4))) echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))

17
examples/debugging.nim Normal file
View file

@ -0,0 +1,17 @@
# Simple program to test the debugger
# compile with --debugger:on
proc someComp(x, y: int): int =
let a = x+y
if a > 7:
let b = a*90
{.breakpoint.}
result = b
{.breakpoint.}
proc pp() =
var aa = 45
var bb = "abcdef"
echo someComp(23, 45)
pp()

View file

@ -1,7 +1,7 @@
/* /*
Nimrod's Runtime Library Nimrod's Runtime Library
(c) Copyright 2012 Andreas Rumpf (c) Copyright 2013 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.
@ -440,9 +440,9 @@ struct TFrame {
volatile TFrame F; \ volatile TFrame F; \
F.procname = proc; F.filename = file; F.line = 0; F.len = 0; nimFrame(&F); F.procname = proc; F.filename = file; F.line = 0; F.len = 0; nimFrame(&F);
#define nimfrs(proc, file, slots) \ #define nimfrs(proc, file, slots, length) \
volatile struct {TFrame* prev;NCSTRING procname;NI line;NCSTRING filename; NI len; TVarSlot s[slots];} F; \ volatile struct {TFrame* prev;NCSTRING procname;NI line;NCSTRING filename; NI len; TVarSlot s[slots];} F; \
F.procname = proc; F.filename = file; F.line = 0; F.len = slots; nimFrame((TFrame*)&F); F.procname = proc; F.filename = file; F.line = 0; F.len = length; nimFrame((TFrame*)&F);
#define nimln(n, file) \ #define nimln(n, file) \
F.line = n; F.filename = file; F.line = n; F.filename = file;

View file

@ -207,9 +207,8 @@ proc fileMatches(c, bp: cstring): bool =
return false return false
var i = 0 var i = 0
while i < blen: while i < blen:
var x, y: char var x = bp[i]
x = bp[i] var y = c[i+clen-blen]
y = c[i+clen-blen]
when FileSystemCaseInsensitive: when FileSystemCaseInsensitive:
if x >= 'A' and x <= 'Z': x = chr(ord(x) - ord('A') + ord('a')) if x >= 'A' and x <= 'Z': x = chr(ord(x) - ord('A') + ord('a'))
if y >= 'A' and y <= 'Z': y = chr(ord(y) - ord('A') + ord('a')) if y >= 'A' and y <= 'Z': y = chr(ord(y) - ord('A') + ord('a'))
@ -742,7 +741,7 @@ proc checkWatchpoints =
debugOut(Watchpoints[i].name) debugOut(Watchpoints[i].name)
Watchpoints[i].oldValue = newHash Watchpoints[i].oldValue = newHash
proc endb(line: int) {.compilerproc.} = proc endb(line: int, file: cstring) {.compilerproc.} =
# This proc is called before every Nimrod code line! # This proc is called before every Nimrod code line!
# Thus, it must have as few parameters as possible to keep the # Thus, it must have as few parameters as possible to keep the
# code size small! # code size small!
@ -753,6 +752,7 @@ proc endb(line: int) {.compilerproc.} =
#if oldState != dbOff: #if oldState != dbOff:
checkWatchpoints() checkWatchpoints()
framePtr.line = line # this is done here for smaller code size! framePtr.line = line # this is done here for smaller code size!
framePtr.filename = file
if dbgLineHook != nil: dbgLineHook() if dbgLineHook != nil: dbgLineHook()
case oldState case oldState
of dbStepInto: of dbStepInto:
@ -765,7 +765,8 @@ proc endb(line: int) {.compilerproc.} =
CommandPrompt() CommandPrompt()
else: # breakpoints are wanted though (I guess) else: # breakpoints are wanted though (I guess)
checkForBreakpoint() checkForBreakpoint()
of dbBreakpoints: # debugger is only interested in breakpoints of dbBreakpoints:
# debugger is only interested in breakpoints
checkForBreakpoint() checkForBreakpoint()
else: nil else: nil

View file

@ -1,6 +1,9 @@
version 0.9.2 version 0.9.2
============= =============
- fix destructors; don't work yet when used as expression; alternative for
version 1: disallow expressions yielding a type with a destructor that are
not in a 'let/var' context (p(a.openFile, b.openFile) makes no sense anyway)
- lazy overloading resolution: - lazy overloading resolution:
* get rid of ``expr[typ]``, use perhaps ``static[typ]`` instead * get rid of ``expr[typ]``, use perhaps ``static[typ]`` instead
* special case ``tyStmt`` * special case ``tyStmt``
@ -8,16 +11,24 @@ version 0.9.2
* test libffi on windows * test libffi on windows
* test: times.format with the FFI * test: times.format with the FFI
- acyclic vs prunable; introduce GC hints - acyclic vs prunable; introduce GC hints
- implement constructors
- more checks
- document them
- CGEN: ``restrict`` pragma + backend support; computed goto support - CGEN: ``restrict`` pragma + backend support; computed goto support
- fix:
- 'result' is not properly cleaned for NRVO
- document NimMain and check whether it works for threading - document NimMain and check whether it works for threading
- fix destructors; don't work yet when used as expression; alternative for
version 1: disallow expressions yielding a type with a destructor that are
not in a 'let/var' context (p(a.openFile, b.openFile) makes no sense anyway) Bugs
====
- 'result' is not properly cleaned for NRVO
- instantiated generics are listed in error messages
- sneaking with qualifiedLookup() is really broken!
- aporia.nim(968, 5) Error: ambiguous identifier: 'DELETE' --
use a qualifier
- blocks can "export" an identifier but the CCG generates {} for them ...
- JS gen: fix exception handling
- osproc execProcesses can deadlock if all processes fail (as experienced
in c++ mode)
- bootstrapping does not work in C++ mode
- case statement exhaustiveness checking is still wrong
version 0.9.4 version 0.9.4
@ -40,7 +51,7 @@ version 0.9.X
- test&finish first class iterators: - test&finish first class iterators:
* nested iterators * nested iterators
- implement the missing features wrt inheritance - implement the missing features wrt inheritance
- better support for *hard* realtime systems - object pooling support for *hard* realtime systems
- improve the compiler as a service - improve the compiler as a service
- better support for macros that rewrite procs - better support for macros that rewrite procs
- macros need access to types and symbols (partially implemented) - macros need access to types and symbols (partially implemented)
@ -71,8 +82,9 @@ version 0.9.XX
============== ==============
- object branch transitions can't work with the current 'reset'; add a 'reset' - object branch transitions can't work with the current 'reset'; add a 'reset'
with an additional parameter --> re-evaluate this issue after constructors with an additional parameter --> simple:
have been added provide a 'reset(x, TObj(k: nkValue))' instead? why bother? '=' does the
same.
- document nimdoc properly finally - document nimdoc properly finally
- make 'clamp' a magic for the range stuff - make 'clamp' a magic for the range stuff
- better type syntax for functions and tuples: tuple(int, int); (int,int)->int - better type syntax for functions and tuples: tuple(int, int); (int,int)->int
@ -103,6 +115,8 @@ Not essential for 1.0.0
* first version: mark black in write barrier * first version: mark black in write barrier
* second version: introduce fake roots instead of marking black * second version: introduce fake roots instead of marking black
* third version: find some clever heuristic which is preferable * third version: find some clever heuristic which is preferable
- object constructors: static check for fields if discriminator is known at
compile time
GC GC
@ -122,18 +136,3 @@ Optimizations
even further write barrier specialization even further write barrier specialization
- inlining of first class functions - inlining of first class functions
- proc specialization in the code gen for write barrier specialization - proc specialization in the code gen for write barrier specialization
Bugs
====
- instantiated generics are listed in error messages
- sneaking with qualifiedLookup() is really broken!
- aporia.nim(968, 5) Error: ambiguous identifier: 'DELETE' --
use a qualifier
- blocks can "export" an identifier but the CCG generates {} for them ...
- JS gen: fix exception handling
- the better scoping for locals is the wrong default for endb
- osproc execProcesses can deadlock if all processes fail (as experienced
in c++ mode)
- case statement exhaustiveness checking is still wrong

View file

@ -15,17 +15,17 @@ Bugfixes
with ``GC_disableMarkAndSweep`` and run it explicitly at an appropriate time with ``GC_disableMarkAndSweep`` and run it explicitly at an appropriate time
or not at all. There is also a new GC you can activate or not at all. There is also a new GC you can activate
with ``--gc:markAndSweep`` which does not have this problem but is slower in with ``--gc:markAndSweep`` which does not have this problem but is slower in
general. general and has no realtime guarantees.
Library Additions Library Additions
----------------- -----------------
- There is a new experimental mark&sweep GC which can be faster (or much
slower) than the default GC. Enable with ``--gc:markAndSweep``.
- Added ``system.onRaise`` to support a condition system. - Added ``system.onRaise`` to support a condition system.
- Added ``macros.quote`` for AST quasi-quoting. - Added ``macros.quote`` for AST quasi-quoting.
- Added ``system.unsafeNew`` to support hacky variable length objects. - Added ``system.unsafeNew`` to support hacky variable length objects.
- There is a new experimental mark&sweep GC which can be faster (or much
slower) than the default GC. Enable with ``--gc:markAndSweep``.
- ``system.fields`` and ``system.fieldPairs`` support ``object`` too; they - ``system.fields`` and ``system.fieldPairs`` support ``object`` too; they
used to only support tuples. used to only support tuples.
@ -68,6 +68,7 @@ Language Additions
dependencies explicitly. dependencies explicitly.
- Overloading based on ASTs has been implemented. - Overloading based on ASTs has been implemented.
- Generics are now supported for multi methods. - Generics are now supported for multi methods.
- Objects can be initialized via an *object constructor expression*.
2012-09-23 Version 0.9.0 released 2012-09-23 Version 0.9.0 released