mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-25 04:15:09 +00:00
documented object constrs; endb works again
This commit is contained in:
@@ -709,12 +709,12 @@ proc genFieldCheck(p: BProc, e: PNode, obj: PRope, field: PSym) =
|
||||
rdLoc(test), strLit)
|
||||
|
||||
proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||
var
|
||||
a: TLoc
|
||||
f, field: PSym
|
||||
ty: PType
|
||||
r: PRope
|
||||
if optFieldCheck in p.options:
|
||||
var
|
||||
a: TLoc
|
||||
f, field: PSym
|
||||
ty: PType
|
||||
r: PRope
|
||||
ty = genRecordFieldAux(p, e.sons[0], d, a)
|
||||
r = rdLoc(a)
|
||||
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:
|
||||
InternalError(e.info, "genCheckedRecordField") # generate the checks:
|
||||
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))
|
||||
putIntoDest(p, d, field.typ, r)
|
||||
else:
|
||||
|
||||
@@ -45,7 +45,7 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||
if t.kind == tyTuple:
|
||||
field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)])
|
||||
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",
|
||||
[rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)])
|
||||
putLocIntoDest(p, v.loc, field)
|
||||
@@ -64,19 +64,23 @@ proc startBlock(p: BProc, start: TFormatStr = "{$n",
|
||||
result = len(p.blocks)
|
||||
setlen(p.blocks, result + 1)
|
||||
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.} =
|
||||
b.label = con("LA", b.id.toRope)
|
||||
result = b.label
|
||||
|
||||
proc blockBody(b: var TBlock): PRope {.inline.} =
|
||||
return b.sections[cpsLocals].con(b.sections[cpsInit]).con(b.sections[cpsStmts])
|
||||
proc blockBody(b: var TBlock): PRope =
|
||||
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) =
|
||||
let topBlock = p.blocks.len - 1
|
||||
let topBlock = p.blocks.len-1
|
||||
# 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)
|
||||
# this is done after the block is popped so $n is
|
||||
# properly indented when pretty printing is enabled
|
||||
@@ -84,10 +88,13 @@ proc endBlock(p: BProc, blockEnd: PRope) =
|
||||
|
||||
proc endBlock(p: BProc) =
|
||||
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)
|
||||
else:
|
||||
~"}$n"
|
||||
let frameLen = p.blocks[topBlock].frameLen
|
||||
if frameLen > 0:
|
||||
blockEnd.appf("F.len-=$1;$n", frameLen.toRope)
|
||||
endBlock(p, blockEnd)
|
||||
|
||||
proc genSimpleBlock(p: BProc, stmts: PNode) {.inline.} =
|
||||
@@ -774,7 +781,7 @@ var
|
||||
|
||||
proc genBreakPoint(p: BProc, t: PNode) =
|
||||
var name: string
|
||||
if optEndb in p.Options:
|
||||
if optEndb in p.Options:
|
||||
if t.kind == nkExprColonExpr:
|
||||
assert(t.sons[1].kind in {nkStrLit..nkTripleStrLit})
|
||||
name = normalize(t.sons[1].strVal)
|
||||
@@ -784,7 +791,7 @@ proc genBreakPoint(p: BProc, t: PNode) =
|
||||
genLineDir(p, t) # BUGFIX
|
||||
appcg(p.module, gBreakpoints,
|
||||
"#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [
|
||||
toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)),
|
||||
toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)),
|
||||
makeCString(name)])
|
||||
|
||||
proc genWatchpoint(p: BProc, n: PNode) =
|
||||
@@ -796,16 +803,13 @@ proc genWatchpoint(p: BProc, n: PNode) =
|
||||
[a.addrLoc, makeCString(renderTree(n.sons[1])),
|
||||
genTypeInfo(p.module, typ)])
|
||||
|
||||
proc genPragma(p: BProc, n: PNode) =
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
proc genPragma(p: BProc, n: PNode) =
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var it = n.sons[i]
|
||||
case whichPragma(it)
|
||||
of wEmit:
|
||||
genEmit(p, it)
|
||||
of wBreakpoint:
|
||||
genBreakPoint(p, it)
|
||||
of wWatchpoint:
|
||||
genWatchpoint(p, it)
|
||||
of wEmit: genEmit(p, it)
|
||||
of wBreakpoint: genBreakPoint(p, it)
|
||||
of wWatchpoint: genWatchpoint(p, it)
|
||||
else: nil
|
||||
|
||||
proc FieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool =
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -269,18 +269,18 @@ proc genCLineDir(r: var PRope, filename: string, line: int) =
|
||||
proc genCLineDir(r: var PRope, info: TLineInfo) =
|
||||
genCLineDir(r, info.toFullPath, info.safeLineNm)
|
||||
|
||||
proc genLineDir(p: BProc, t: PNode) =
|
||||
proc genLineDir(p: BProc, t: PNode) =
|
||||
var line = t.info.safeLineNm
|
||||
if optEmbedOrigSrc in gGlobalOptions:
|
||||
app(p.s(cpsStmts), con(~"//", t.info.sourceLine, rnl))
|
||||
genCLineDir(p.s(cpsStmts), t.info.toFullPath, line)
|
||||
if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
|
||||
(p.prc == nil or sfPure notin p.prc.flags):
|
||||
linefmt(p, cpsStmts, "#endb($1);$n", toRope(line))
|
||||
(p.prc == nil or sfPure notin p.prc.flags):
|
||||
linefmt(p, cpsStmts, "#endb($1, $2);$n",
|
||||
line.toRope, makeCString(toFilename(t.info)))
|
||||
elif ({optLineTrace, optStackTrace} * p.Options ==
|
||||
{optLineTrace, optStackTrace}) and
|
||||
(p.prc == nil or sfPure notin p.prc.flags):
|
||||
|
||||
linefmt(p, cpsStmts, "nimln($1, $2);$n",
|
||||
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:
|
||||
if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return
|
||||
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,
|
||||
"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)])
|
||||
inc(p.frameLen)
|
||||
inc(p.maxFrameLen)
|
||||
inc p.blocks[p.blocks.len-1].frameLen
|
||||
|
||||
proc assignLocalVar(p: BProc, s: PSym) =
|
||||
#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")
|
||||
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
|
||||
# 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")
|
||||
appf(decl, " $1;$n", [s.loc.r])
|
||||
line(p, cpsLocals, decl)
|
||||
@@ -693,10 +694,11 @@ proc retIsNotVoid(s: PSym): bool =
|
||||
|
||||
proc initFrame(p: BProc, procname, filename: PRope): PRope =
|
||||
discard cgsym(p.module, "pushFrame")
|
||||
if p.frameLen > 0:
|
||||
if p.maxFrameLen > 0:
|
||||
discard cgsym(p.module, "TVarSlot")
|
||||
result = rfmt(nil, "\tnimfrs($1, $2, $3)$N",
|
||||
procname, filename, p.frameLen.toRope)
|
||||
result = rfmt(nil, "\tnimfrs($1, $2, $3, $4)$N",
|
||||
procname, filename, p.maxFrameLen.toRope,
|
||||
p.blocks[0].frameLen.toRope)
|
||||
else:
|
||||
result = rfmt(nil, "\tnimfr($1, $2)$N", procname, filename)
|
||||
|
||||
|
||||
@@ -54,9 +54,10 @@ type
|
||||
id*: int # the ID of the label; positive means that it
|
||||
label*: PRope # generated text for the label
|
||||
# nil if label is not used
|
||||
nestedTryStmts*: int # how many try statements is it nested into
|
||||
sections*: TCProcSections # the code beloging
|
||||
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
|
||||
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
|
||||
# generation; this is the same as prc.options
|
||||
# unless prc == nil
|
||||
frameLen*: int # current length of frame descriptor
|
||||
sendClosure*: PType # closure record type that we pass
|
||||
receiveClosure*: PType # closure record type that we get
|
||||
maxFrameLen*: int # max length of frame descriptor
|
||||
module*: BModule # used to prevent excessive parameter passing
|
||||
withinLoop*: int # > 0 if we are within a loop
|
||||
gcFrameId*: natural # for the GC stack marking
|
||||
|
||||
@@ -984,7 +984,7 @@ in future versions of the compiler.
|
||||
.. code-block:: nimrod
|
||||
|
||||
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
|
||||
# and an age
|
||||
var
|
||||
@@ -1000,7 +1000,6 @@ For consistency with ``object`` declarations, tuples in a ``type`` section
|
||||
can also be defined with indentation instead of ``[]``:
|
||||
|
||||
.. code-block:: nimrod
|
||||
|
||||
type
|
||||
TPerson = tuple # type representing a person
|
||||
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.
|
||||
|
||||
.. code-block:: nimrod
|
||||
|
||||
type
|
||||
TPerson {.inheritable.} = object
|
||||
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``.
|
||||
|
||||
|
||||
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
|
||||
---------------
|
||||
Often an object hierarchy is overkill in certain situations where simple
|
||||
@@ -1061,15 +1072,22 @@ An example:
|
||||
of nkIf:
|
||||
condition, thenPart, elsePart: PNode
|
||||
|
||||
var
|
||||
n: PNode
|
||||
new(n) # creates a new node
|
||||
n.kind = nkFloat
|
||||
n.floatVal = 0.0 # valid, because ``n.kind==nkFloat``, so that it fits
|
||||
# create a new case object:
|
||||
var n = PNode(kind: nkIf, condition: nil)
|
||||
# accessing n.thenPart is valid because the ``nkIf`` branch is active:
|
||||
n.thenPart = PNode(kind: nkFloat, floatVal: 2.0)
|
||||
|
||||
# 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 = ""
|
||||
|
||||
# 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
|
||||
no casting between different object types is needed. Yet, access to invalid
|
||||
@@ -1078,6 +1096,11 @@ object fields raises an exception.
|
||||
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.
|
||||
|
||||
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
|
||||
--------
|
||||
@@ -2387,6 +2410,7 @@ the proc's name.
|
||||
Procs as expressions can appear both as nested procs and inside top level
|
||||
executable code.
|
||||
|
||||
|
||||
Do notation
|
||||
-----------
|
||||
|
||||
@@ -2410,7 +2434,7 @@ Again, let's see the equivalent of the previous example:
|
||||
sort(cities) do (x,y: string) -> int:
|
||||
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
|
||||
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
|
||||
used with macros and templates expecting ``stmt`` blocks.
|
||||
|
||||
|
||||
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.
|
||||
3. Every call to a method ``m`` is assumed to
|
||||
raise ``system.E_Base`` unless ``m`` has an explicit ``raises`` list.
|
||||
4. For every other call the analysis can determine an
|
||||
exact ``raises`` list.
|
||||
4. For every other call the analysis can determine an exact ``raises`` list.
|
||||
5. For determining a ``raises`` list, the ``raise`` and ``try`` statements
|
||||
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
|
||||
"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.
|
||||
|
||||
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 =
|
||||
result = if cond: x + y else: x - y
|
||||
|
||||
template optP{p(x, y, true)}(x, y: expr): expr = x + y
|
||||
template optP{p(x, y, false)}(x, y: expr): expr = x - y
|
||||
template optP1{p(x, y, true)}(x, y: expr): expr = x + y
|
||||
template optP2{p(x, y, false)}(x, y: expr): expr = x - y
|
||||
|
||||
|
||||
Example: hoisting
|
||||
|
||||
43
doc/tut2.txt
43
doc/tut2.txt
@@ -46,8 +46,7 @@ Objects
|
||||
Like tuples, objects are a means to pack different values together in a
|
||||
structured way. However, objects provide many features that tuples do not:
|
||||
They provide inheritance and information hiding. Because objects encapsulate
|
||||
data, the ``()`` tuple constructor cannot be used to construct objects. So
|
||||
the order of the object's fields is not as important as it is for tuples. The
|
||||
data, the ``T()`` object constructor should only be used internally and the
|
||||
programmer should provide a proc to initialize the object (this is called
|
||||
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:
|
||||
|
||||
.. code-block:: nimrod
|
||||
|
||||
type
|
||||
TPerson = object of TObject
|
||||
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
|
||||
person: TPerson
|
||||
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
|
||||
be marked by ``*``. In contrast to tuples, different object types are
|
||||
@@ -161,12 +161,7 @@ An example:
|
||||
of nkIf:
|
||||
condition, thenPart, elsePart: PNode
|
||||
|
||||
var
|
||||
n: PNode
|
||||
new(n) # creates a new node
|
||||
n.kind = nkFloat
|
||||
n.floatVal = 0.0 # valid, because ``n.kind==nkFloat``
|
||||
|
||||
var n = PNode(kind: nkFloat, floatVal: 1.0)
|
||||
# the following statement raises an `EInvalidField` exception, because
|
||||
# n.kind's value does not fit:
|
||||
n.strVal = ""
|
||||
@@ -288,30 +283,22 @@ Procedures always use static dispatch. For dynamic dispatch replace the
|
||||
|
||||
.. code-block:: nimrod
|
||||
type
|
||||
TExpr = object of TObject ## abstract base class for an expression
|
||||
TLiteral = object of TExpr
|
||||
PExpr = ref object of TObject ## abstract base class for an expression
|
||||
PLiteral = ref object of PExpr
|
||||
x: int
|
||||
TPlusExpr = object of TExpr
|
||||
a, b: ref TExpr
|
||||
|
||||
method eval(e: ref TExpr): int =
|
||||
PPlusExpr = ref object of PExpr
|
||||
a, b: PExpr
|
||||
|
||||
# watch out: 'eval' relies on dynamic binding
|
||||
method eval(e: PExpr): int =
|
||||
# override this base method
|
||||
quit "to override!"
|
||||
|
||||
method eval(e: ref TLiteral): int = return e.x
|
||||
|
||||
method eval(e: ref TPlusExpr): int =
|
||||
# watch out: relies on dynamic binding
|
||||
return eval(e.a) + eval(e.b)
|
||||
method eval(e: PLiteral): int = e.x
|
||||
method eval(e: PPlusExpr): int = 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
|
||||
proc newLit(x: int): PLiteral = PLiteral(x: x)
|
||||
proc newPlus(a, b: PExpr): PPlusExpr = PPlusExpr(a: a, b: b)
|
||||
|
||||
echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))
|
||||
|
||||
|
||||
17
examples/debugging.nim
Normal file
17
examples/debugging.nim
Normal 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()
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
Nimrod's Runtime Library
|
||||
(c) Copyright 2012 Andreas Rumpf
|
||||
(c) Copyright 2013 Andreas Rumpf
|
||||
|
||||
See the file "copying.txt", included in this
|
||||
distribution, for details about the copyright.
|
||||
@@ -440,9 +440,9 @@ struct TFrame {
|
||||
volatile TFrame 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; \
|
||||
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) \
|
||||
F.line = n; F.filename = file;
|
||||
|
||||
@@ -207,9 +207,8 @@ proc fileMatches(c, bp: cstring): bool =
|
||||
return false
|
||||
var i = 0
|
||||
while i < blen:
|
||||
var x, y: char
|
||||
x = bp[i]
|
||||
y = c[i+clen-blen]
|
||||
var x = bp[i]
|
||||
var y = c[i+clen-blen]
|
||||
when FileSystemCaseInsensitive:
|
||||
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'))
|
||||
@@ -742,7 +741,7 @@ proc checkWatchpoints =
|
||||
debugOut(Watchpoints[i].name)
|
||||
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!
|
||||
# Thus, it must have as few parameters as possible to keep the
|
||||
# code size small!
|
||||
@@ -753,6 +752,7 @@ proc endb(line: int) {.compilerproc.} =
|
||||
#if oldState != dbOff:
|
||||
checkWatchpoints()
|
||||
framePtr.line = line # this is done here for smaller code size!
|
||||
framePtr.filename = file
|
||||
if dbgLineHook != nil: dbgLineHook()
|
||||
case oldState
|
||||
of dbStepInto:
|
||||
@@ -765,7 +765,8 @@ proc endb(line: int) {.compilerproc.} =
|
||||
CommandPrompt()
|
||||
else: # breakpoints are wanted though (I guess)
|
||||
checkForBreakpoint()
|
||||
of dbBreakpoints: # debugger is only interested in breakpoints
|
||||
of dbBreakpoints:
|
||||
# debugger is only interested in breakpoints
|
||||
checkForBreakpoint()
|
||||
else: nil
|
||||
|
||||
|
||||
51
todo.txt
51
todo.txt
@@ -1,6 +1,9 @@
|
||||
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:
|
||||
* get rid of ``expr[typ]``, use perhaps ``static[typ]`` instead
|
||||
* special case ``tyStmt``
|
||||
@@ -8,16 +11,24 @@ version 0.9.2
|
||||
* test libffi on windows
|
||||
* test: times.format with the FFI
|
||||
- acyclic vs prunable; introduce GC hints
|
||||
- implement constructors
|
||||
- more checks
|
||||
- document them
|
||||
- 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
|
||||
- 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
|
||||
@@ -40,7 +51,7 @@ version 0.9.X
|
||||
- test&finish first class iterators:
|
||||
* nested iterators
|
||||
- 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
|
||||
- better support for macros that rewrite procs
|
||||
- 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'
|
||||
with an additional parameter --> re-evaluate this issue after constructors
|
||||
have been added
|
||||
with an additional parameter --> simple:
|
||||
provide a 'reset(x, TObj(k: nkValue))' instead? why bother? '=' does the
|
||||
same.
|
||||
- document nimdoc properly finally
|
||||
- make 'clamp' a magic for the range stuff
|
||||
- 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
|
||||
* second version: introduce fake roots instead of marking black
|
||||
* third version: find some clever heuristic which is preferable
|
||||
- object constructors: static check for fields if discriminator is known at
|
||||
compile time
|
||||
|
||||
|
||||
GC
|
||||
@@ -122,18 +136,3 @@ Optimizations
|
||||
even further write barrier specialization
|
||||
- inlining of first class functions
|
||||
- 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
|
||||
|
||||
@@ -15,17 +15,17 @@ Bugfixes
|
||||
with ``GC_disableMarkAndSweep`` and run it explicitly at an appropriate time
|
||||
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
|
||||
general.
|
||||
general and has no realtime guarantees.
|
||||
|
||||
|
||||
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 ``macros.quote`` for AST quasi-quoting.
|
||||
- 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
|
||||
used to only support tuples.
|
||||
|
||||
@@ -68,6 +68,7 @@ Language Additions
|
||||
dependencies explicitly.
|
||||
- Overloading based on ASTs has been implemented.
|
||||
- Generics are now supported for multi methods.
|
||||
- Objects can be initialized via an *object constructor expression*.
|
||||
|
||||
|
||||
2012-09-23 Version 0.9.0 released
|
||||
|
||||
Reference in New Issue
Block a user