p[] instead of p^

This commit is contained in:
Araq 2011-04-11 21:42:28 +02:00
commit 3d696c3da5
12 changed files with 64 additions and 52 deletions

View file

@ -932,8 +932,9 @@ untraced references are *unsafe*. However for certain low-level operations
Traced references are declared with the **ref** keyword, untraced references Traced references are declared with the **ref** keyword, untraced references
are declared with the **ptr** keyword. are declared with the **ptr** keyword.
The ``^`` operator can be used to derefer a reference, the ``addr`` procedure An empty subscript ``[]`` notation can be used to derefer a reference,
returns the address of an item. An address is always an untraced reference. the ``addr`` procedure returns the address of an item. An address is always
an untraced reference.
Thus the usage of ``addr`` is an *unsafe* feature. Thus the usage of ``addr`` is an *unsafe* feature.
The ``.`` (access a tuple/object field operator) The ``.`` (access a tuple/object field operator)
@ -951,7 +952,8 @@ dereferencing operations for reference types:
var var
n: PNode n: PNode
new(n) new(n)
n.data = 9 # no need to write n^ .data n.data = 9
# no need to write n[].data; in fact n[].data is highly discouraged!
To allocate a new traced object, the built-in procedure ``new`` has to be used. To allocate a new traced object, the built-in procedure ``new`` has to be used.
To deal with untraced memory, the procedures ``alloc``, ``dealloc`` and To deal with untraced memory, the procedures ``alloc``, ``dealloc`` and
@ -1941,8 +1943,8 @@ above example is equivalent to:
.. code-block:: nimrod .. code-block:: nimrod
proc divmod(a, b: int, proc divmod(a, b: int,
res, remainder: ptr int) = res, remainder: ptr int) =
res^ = a div b res[] = a div b
remainder^ = a mod b remainder[] = a mod b
var var
x, y: int x, y: int
@ -2070,6 +2072,7 @@ The `for`:idx: statement is an abstract mechanism to iterate over the elements
of a container. It relies on an `iterator`:idx: to do so. Like ``while`` of a container. It relies on an `iterator`:idx: to do so. Like ``while``
statements, ``for`` statements open an `implicit block`:idx:, so that they statements, ``for`` statements open an `implicit block`:idx:, so that they
can be left with a ``break`` statement. The ``for`` loop declares can be left with a ``break`` statement. The ``for`` loop declares
iteration variables (``x`` in the example) - their scope reaches until the iteration variables (``x`` in the example) - their scope reaches until the
end of the loop body. The iteration variables' types are inferred by the end of the loop body. The iteration variables' types are inferred by the
return type of the iterator. return type of the iterator.
@ -2581,6 +2584,7 @@ The `procvar`:idx: pragma is used to mark a proc that it can be passed to a
procedural variable. procedural variable.
compileTime pragma compileTime pragma
------------------ ------------------
The `compileTime`:idx: pragma is used to mark a proc to be used at compile The `compileTime`:idx: pragma is used to mark a proc to be used at compile

View file

@ -1183,9 +1183,9 @@ untraced references are *unsafe*. However for certain low-level operations
Traced references are declared with the **ref** keyword, untraced references Traced references are declared with the **ref** keyword, untraced references
are declared with the **ptr** keyword. are declared with the **ptr** keyword.
The ``^`` operator can be used to *derefer* a reference, meaning to retrieve The empty ``[]`` subscript notation can be used to *derefer* a reference,
the item the reference points to. The ``addr`` procedure returns the address meaning to retrieve the item the reference points to. The ``addr`` procedure
of an item. An address is always an untraced reference: returns the address of an item. An address is always an untraced reference:
``addr`` is an *unsafe* feature. ``addr`` is an *unsafe* feature.
The ``.`` (access a tuple/object field operator) The ``.`` (access a tuple/object field operator)
@ -1200,7 +1200,8 @@ dereferencing operations for reference types:
var var
n: PNode n: PNode
new(n) new(n)
n.data = 9 # no need to write n^ .data n.data = 9
# no need to write n[].data; in fact n[].data is highly discouraged!
(As a convention, reference types use a 'P' prefix.) (As a convention, reference types use a 'P' prefix.)

View file

@ -1204,7 +1204,7 @@ proc unaryExpression(p: var TParser): PNode =
of pxPlusPlus: result = incdec(p, "inc") of pxPlusPlus: result = incdec(p, "inc")
of pxMinusMinus: result = incdec(p, "dec") of pxMinusMinus: result = incdec(p, "dec")
of pxAmp: result = unaryOp(p, nkAddr) of pxAmp: result = unaryOp(p, nkAddr)
of pxStar: result = unaryOp(p, nkDerefExpr) of pxStar: result = unaryOp(p, nkBracketExpr)
of pxPlus: result = prefixCall(p, "+") of pxPlus: result = prefixCall(p, "+")
of pxMinus: result = prefixCall(p, "-") of pxMinus: result = prefixCall(p, "-")
of pxTilde: result = prefixCall(p, "not") of pxTilde: result = prefixCall(p, "not")

View file

@ -90,7 +90,9 @@ type
warnCannotWriteMO2, warnCannotReadMO2, warnDeprecated, warnCannotWriteMO2, warnCannotReadMO2, warnDeprecated,
warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel, warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel,
warnUnknownSubstitutionX, warnLanguageXNotSupported, warnCommentXIgnored, warnUnknownSubstitutionX, warnLanguageXNotSupported, warnCommentXIgnored,
warnXisPassedToProcVar, warnUser, hintSuccess, hintSuccessX, warnXisPassedToProcVar, warnDerefDeprecated,
warnUser,
hintSuccess, hintSuccessX,
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded, hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled, hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, hintUser hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, hintUser
@ -319,6 +321,7 @@ const
warnLanguageXNotSupported: "language \'$1\' not supported [LanguageXNotSupported]", warnLanguageXNotSupported: "language \'$1\' not supported [LanguageXNotSupported]",
warnCommentXIgnored: "comment \'$1\' ignored [CommentXIgnored]", warnCommentXIgnored: "comment \'$1\' ignored [CommentXIgnored]",
warnXisPassedToProcVar: "\'$1\' is passed to a procvar; deprecated [XisPassedToProcVar]", warnXisPassedToProcVar: "\'$1\' is passed to a procvar; deprecated [XisPassedToProcVar]",
warnDerefDeprecated: "p^ is deprecated; use p[] instead [DerefDeprecated]",
warnUser: "$1 [User]", warnUser: "$1 [User]",
hintSuccess: "operation successful [Success]", hintSuccess: "operation successful [Success]",
hintSuccessX: "operation successful ($1 lines compiled; $2 sec total) [SuccessX]", hintSuccessX: "operation successful ($1 lines compiled; $2 sec total) [SuccessX]",
@ -336,11 +339,11 @@ const
hintUser: "$1 [User]"] hintUser: "$1 [User]"]
const const
WarningsToStr*: array[0..14, string] = ["CannotOpenFile", "OctalEscape", WarningsToStr*: array[0..15, string] = ["CannotOpenFile", "OctalEscape",
"XIsNeverRead", "XmightNotBeenInit", "CannotWriteMO2", "CannotReadMO2", "XIsNeverRead", "XmightNotBeenInit", "CannotWriteMO2", "CannotReadMO2",
"Deprecated", "SmallLshouldNotBeUsed", "UnknownMagic", "Deprecated", "SmallLshouldNotBeUsed", "UnknownMagic",
"RedefinitionOfLabel", "UnknownSubstitutionX", "LanguageXNotSupported", "RedefinitionOfLabel", "UnknownSubstitutionX", "LanguageXNotSupported",
"CommentXIgnored", "XisPassedToProcVar", "User"] "CommentXIgnored", "XisPassedToProcVar", "DerefDeprecated", "User"]
HintsToStr*: array[0..13, string] = ["Success", "SuccessX", "LineTooLong", HintsToStr*: array[0..13, string] = ["Success", "SuccessX", "LineTooLong",
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",

View file

@ -436,7 +436,7 @@ proc primary(p: var TParser): PNode =
parMessage(p, errIdentifierExpected, $p.tok) parMessage(p, errIdentifierExpected, $p.tok)
of pxHat: of pxHat:
var a = result var a = result
result = newNodeP(nkDerefExpr, p) result = newNodeP(nkBracketExpr, p)
addSon(result, a) addSon(result, a)
getTok(p) getTok(p)
of pxBracketLe: of pxBracketLe:

View file

@ -629,7 +629,7 @@ proc makeDeref(n: PNode): PNode =
t = skipTypes(t.sons[0], {tyGenericInst}) t = skipTypes(t.sons[0], {tyGenericInst})
if t.kind in {tyPtr, tyRef}: if t.kind in {tyPtr, tyRef}:
var a = result var a = result
result = newNodeIT(nkDerefExpr, n.info, t.sons[0]) result = newNodeIT(nkHiddenDeref, n.info, t.sons[0])
addSon(result, a) addSon(result, a)
proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
@ -745,8 +745,23 @@ proc buildOverloadedSubscripts(n: PNode, inAsgn: bool): PNode =
# now we know the operator # now we know the operator
result.sons[0] = newIdentNode(getIdent(opr), n.info) result.sons[0] = newIdentNode(getIdent(opr), n.info)
proc semDeref(c: PContext, n: PNode): PNode =
checkSonsLen(n, 1)
n.sons[0] = semExprWithType(c, n.sons[0])
result = n
var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar})
case t.kind
of tyRef, tyPtr: n.typ = t.sons[0]
else: GlobalError(n.sons[0].info, errCircumNeedsPointer)
result = n
proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode = proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
## returns nil if not a built-in subscript operator; ## returns nil if not a built-in subscript operator;
if sonsLen(n) == 1:
var x = semDeref(c, n)
result = newNodeIT(nkDerefExpr, x.info, x.typ)
result.add(x[0])
return
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2)
n.sons[0] = semExprWithType(c, n.sons[0], flags - {efAllowType}) n.sons[0] = semExprWithType(c, n.sons[0], flags - {efAllowType})
var arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyPtr, tyRef}) var arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyPtr, tyRef})
@ -1041,14 +1056,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkBracket: result = semArrayConstr(c, n) of nkBracket: result = semArrayConstr(c, n)
of nkLambda: result = semLambda(c, n) of nkLambda: result = semLambda(c, n)
of nkDerefExpr: of nkDerefExpr:
checkSonsLen(n, 1) Message(n.info, warnDerefDeprecated)
n.sons[0] = semExprWithType(c, n.sons[0]) result = semDeref(c, n)
result = n
var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar})
case t.kind
of tyRef, tyPtr: n.typ = t.sons[0]
else: GlobalError(n.sons[0].info, errCircumNeedsPointer)
result = n
of nkAddr: of nkAddr:
result = n result = n
checkSonsLen(n, 1) checkSonsLen(n, 1)

View file

@ -535,7 +535,7 @@ proc indirectAccess(a, b: PSym): PNode =
# returns a^ .b as a node # returns a^ .b as a node
var x = newSymNode(a) var x = newSymNode(a)
var y = newSymNode(b) var y = newSymNode(b)
var deref = newNodeI(nkDerefExpr, x.info) var deref = newNodeI(nkHiddenDeref, x.info)
deref.typ = x.typ.sons[0] deref.typ = x.typ.sons[0]
addSon(deref, x) addSon(deref, x)
result = newNodeI(nkDotExpr, x.info) result = newNodeI(nkDotExpr, x.info)

View file

@ -1,24 +1,5 @@
This directory contains the test cases. This directory contains the test cases.
Each test must have a filename of the form: ``t*.nim`` Each test must have a filename of the form: ``t*.nim``
The testcases may contain the directives ``#ERROR``, ``#ERROR_IN``, Each test can contain a spec in ``"""``.
``#ERROR_MSG`` or ``#OUT``.
``#ERROR`` is used to indicate that the compiler should report
an error in the marked line (the line that contains the ``#ERROR``
directive.)
The format for ``#ERROR_IN`` is::
#ERROR_IN filename linenumber
You can omit the extension of the filename (``.nim`` is then assumed).
The format for ``#ERROR_MSG`` is::
#ERROR_MSG message
This directive specifies the error message Nimrod shall produce.
Tests which contain none of the ``#ERROR*`` directives should compile.
Thus they are executed after successful compilation and their output
is compared to the expected results (specified with the ``#OUT``
directive). Tests which require user interaction are currently not
possible.

View file

@ -17,8 +17,11 @@ const
resultsFile = "testresults.html" resultsFile = "testresults.html"
type type
TTestAction = enum
actionCompile, actionRun, actionReject
TSpec {.pure.} = object TSpec {.pure.} = object
file: string action: TTestAction
file, cmd: string
outp: string outp: string
line: int line: int
msg: string msg: string
@ -72,13 +75,21 @@ proc parseSpec(filename: string): TSpec =
result.err = true result.err = true
result.msg = "" result.msg = ""
result.outp = "" result.outp = ""
result.cmd = cmdTemplate
parseSpecAux: parseSpecAux:
case normalize(e.key) case normalize(e.key)
of "action":
case e.value.normalize
of "compile": result.action = actionCompile
of "run": result.action = actionRun
of "reject": result.action = actionReject
else: echo ignoreMsg(p, e)
of "file": result.file = e.value of "file": result.file = e.value
of "line": discard parseInt(e.value, result.line) of "line": discard parseInt(e.value, result.line)
of "output": result.outp = e.value of "output": result.outp = e.value
of "errormsg", "msg": result.msg = e.value of "errormsg", "msg": result.msg = e.value
of "disabled": result.disabled = parseCfgBool(e.value) of "disabled": result.disabled = parseCfgBool(e.value)
of "cmd": result.cmd = e.value
else: echo ignoreMsg(p, e) else: echo ignoreMsg(p, e)
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
@ -92,7 +103,7 @@ var
pegSuccess = peg"'Hint: operation successful'.*" pegSuccess = peg"'Hint: operation successful'.*"
pegOfInterest = pegLineError / pegOtherError / pegSuccess pegOfInterest = pegLineError / pegOtherError / pegSuccess
proc callCompiler(filename, options: string): TSpec = proc callCompiler(cmdTemplate, filename, options: string): TSpec =
var c = parseCmdLine(cmdTemplate % [options, filename]) var c = parseCmdLine(cmdTemplate % [options, filename])
var a: seq[string] = @[] # slicing is not yet implemented :-( var a: seq[string] = @[] # slicing is not yet implemented :-(
for i in 1 .. c.len-1: add(a, c[i]) for i in 1 .. c.len-1: add(a, c[i])
@ -192,7 +203,7 @@ proc reject(r: var TResults, dir, options: string) =
r.addResult(t, "", "", reIgnored) r.addResult(t, "", "", reIgnored)
inc(r.skipped) inc(r.skipped)
else: else:
var given = callCompiler(test, options) var given = callCompiler(expected.cmd, test, options)
cmpMsgs(r, expected, given, t) cmpMsgs(r, expected, given, t)
proc compile(r: var TResults, pattern, options: string) = proc compile(r: var TResults, pattern, options: string) =
@ -200,7 +211,7 @@ proc compile(r: var TResults, pattern, options: string) =
var t = extractFilename(test) var t = extractFilename(test)
inc(r.total) inc(r.total)
echo t echo t
var given = callCompiler(test, options) var given = callCompiler(cmdTemplate, test, options)
r.addResult(t, given.msg, if given.err: reFailure else: reSuccess) r.addResult(t, given.msg, if given.err: reFailure else: reSuccess)
if not given.err: inc(r.passed) if not given.err: inc(r.passed)
@ -214,7 +225,7 @@ proc run(r: var TResults, dir, options: string) =
r.addResult(t, "", "", reIgnored) r.addResult(t, "", "", reIgnored)
inc(r.skipped) inc(r.skipped)
else: else:
var given = callCompiler(test, options) var given = callCompiler(expected.cmd, test, options)
if given.err: if given.err:
r.addResult(t, "", given.msg, reFailure) r.addResult(t, "", given.msg, reFailure)
else: else:

View file

@ -4,8 +4,6 @@
add --deadlock_prevention:on|off switch add --deadlock_prevention:on|off switch
- built-in serialization - built-in serialization
- deprecate ^ and make it available as operator
High priority (version 0.9.0) High priority (version 0.9.0)
============================= =============================
@ -14,6 +12,7 @@ High priority (version 0.9.0)
- fix the streams implementation so that it uses methods - fix the streams implementation so that it uses methods
- fix overloading resolution - fix overloading resolution
- wrong co-/contravariance - wrong co-/contravariance
- deprecate ^ and make it available as operator; new other notation: p[]
Bugs Bugs

View file

@ -37,6 +37,10 @@ Changes affecting backwards compatibility
if both ``$#`` and ``$i`` are involved. if both ``$#`` and ``$i`` are involved.
- The ``pegs`` and ``re`` modules distinguish between ``replace`` - The ``pegs`` and ``re`` modules distinguish between ``replace``
and ``replacef`` operations. and ``replacef`` operations.
- The pointer dereference operation ``p^`` is deprecated and might become
``^p`` in later versions or be dropped entirely since it is rarely used.
Use the new notation ``p[]`` to dereference a pointer.
Additions Additions
--------- ---------