Skip to content

Commit

Permalink
implemented procCall builtin
Browse files Browse the repository at this point in the history
  • Loading branch information
Araq committed Nov 28, 2014
1 parent d456b88 commit 105a061
Show file tree
Hide file tree
Showing 11 changed files with 63 additions and 52 deletions.
4 changes: 2 additions & 2 deletions compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -566,8 +566,8 @@ type
mBool, mChar, mString, mCstring,
mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc,
mVoidType, mPNimrodNode, mShared, mGuarded, mLock, mSpawn, mDeepCopy,
mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor,
mNimrodMinor, mNimrodPatch, mCpuEndian, mHostOS, mHostCPU, mAppType,
mIsMainModule, mCompileDate, mCompileTime, mProcCall,
mCpuEndian, mHostOS, mHostCPU, mAppType,
mNaN, mInf, mNegInf,
mCompileOption, mCompileOptionArg,
mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, mNKind,
Expand Down
6 changes: 1 addition & 5 deletions compiler/nversion.nim
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@

const
MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets?
VersionMajor* = 0
VersionMinor* = 10
VersionPatch* = 1
VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch

VersionAsString* = system.NimVersion
RodFileVersion* = "1215" # modify this if the rod-format changes!

4 changes: 4 additions & 0 deletions compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1649,6 +1649,10 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
else:
result.typ = result[1].typ
result.add instantiateCreateFlowVarCall(c, result[1].typ, n.info).newSymNode
of mProcCall:
result = setMs(n, s)
result.sons[1] = semExpr(c, n.sons[1])
result.typ = n[1].typ
else: result = semDirectOp(c, n, flags)

proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
Expand Down
4 changes: 0 additions & 4 deletions compiler/semfold.nim
Original file line number Diff line number Diff line change
Expand Up @@ -613,10 +613,6 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
of mIsMainModule: result = newIntNodeT(ord(sfMainModule in m.flags), n)
of mCompileDate: result = newStrNodeT(times.getDateStr(), n)
of mCompileTime: result = newStrNodeT(times.getClockStr(), n)
of mNimrodVersion: result = newStrNodeT(VersionAsString, n)
of mNimrodMajor: result = newIntNodeT(VersionMajor, n)
of mNimrodMinor: result = newIntNodeT(VersionMinor, n)
of mNimrodPatch: result = newIntNodeT(VersionPatch, n)
of mCpuEndian: result = newIntNodeT(ord(CPU[targetCPU].endian), n)
of mHostOS: result = newStrNodeT(toLower(platform.OS[targetOS].name), n)
of mHostCPU: result = newStrNodeT(platform.CPU[targetCPU].name.toLower, n)
Expand Down
3 changes: 3 additions & 0 deletions compiler/semmagic.nim
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
of mShallowCopy: result = semShallowCopy(c, n, flags)
of mNBindSym: result = semBindSym(c, n)
of mLocals: result = semLocals(c, n)
of mProcCall:
result = n
result.typ = n[1].typ
else: result = n
14 changes: 9 additions & 5 deletions compiler/transf.nim
Original file line number Diff line number Diff line change
Expand Up @@ -582,15 +582,15 @@ proc getMergeOp(n: PNode): PSym =
else: discard

proc flattenTreeAux(d, a: PNode, op: PSym) =
var op2 = getMergeOp(a)
let op2 = getMergeOp(a)
if op2 != nil and
(op2.id == op.id or op.magic != mNone and op2.magic == op.magic):
for i in countup(1, sonsLen(a)-1): flattenTreeAux(d, a.sons[i], op)
else:
addSon(d, copyTree(a))

proc flattenTree(root: PNode): PNode =
var op = getMergeOp(root)
let op = getMergeOp(root)
if op != nil:
result = copyNode(root)
addSon(result, copyTree(root.sons[0]))
Expand All @@ -600,8 +600,9 @@ proc flattenTree(root: PNode): PNode =

proc transformCall(c: PTransf, n: PNode): PTransNode =
var n = flattenTree(n)
var op = getMergeOp(n)
if (op != nil) and (op.magic != mNone) and (sonsLen(n) >= 3):
let op = getMergeOp(n)
let magic = getMagic(n)
if op != nil and op.magic != mNone and n.len >= 3:
result = newTransNode(nkCall, n, 0)
add(result, transform(c, n.sons[0]))
var j = 1
Expand All @@ -616,9 +617,12 @@ proc transformCall(c: PTransf, n: PNode): PTransNode =
inc(j)
add(result, a.PTransNode)
if len(result) == 2: result = result[1]
elif getMagic(n) == mNBindSym:
elif magic == mNBindSym:
# for bindSym(myconst) we MUST NOT perform constant folding:
result = n.PTransNode
elif magic == mProcCall:
# but do not change to its dispatcher:
result = transformSons(c, n[1])
else:
let s = transformSons(c, n).PNode
# bugfix: check after 'transformSons' if it's still a method call:
Expand Down
8 changes: 4 additions & 4 deletions doc/manual/procs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ the best match for the arguments. Example:

.. code-block:: nim

proc toLower(c: Char): Char = # toLower for characters
proc toLower(c: char): char = # toLower for characters
if c in {'A'..'Z'}:
result = chr(ord(c) + (ord('a') - ord('A')))
else:
Expand Down Expand Up @@ -150,8 +150,8 @@ means ``echo f 1, f 2`` is parsed as ``echo(f(1), f(2))`` and not as
more argument in this case:

.. code-block:: nim
proc optarg(x:int, y:int = 0):int = x + y
proc singlearg(x:int):int = 20*x
proc optarg(x: int, y: int = 0): int = x + y
proc singlearg(x: int): int = 20*x

echo optarg 1, " ", singlearg 2 # prints "1 40"

Expand Down Expand Up @@ -237,7 +237,7 @@ The following builtin procs cannot be overloaded for reasons of implementation
simplicity (they require specialized semantic checking)::

declared, defined, definedInScope, compiles, low, high, sizeOf,
is, of, shallowCopy, getAst, astToStr, spawn
is, of, shallowCopy, getAst, astToStr, spawn, procCall

Thus they act more like keywords than like ordinary identifiers; unlike a
keyword however, a redefinition may `shadow`:idx: the definition in
Expand Down
48 changes: 26 additions & 22 deletions lib/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1016,22 +1016,6 @@ const
## is the time of compilation as a string of the form
## ``HH:MM:SS``. This works thanks to compiler magic.

NimVersion* {.magic: "NimrodVersion"}: string = "0.0.0"
## is the version of Nim as a string.
## This works thanks to compiler magic.

NimMajor* {.magic: "NimrodMajor"}: int = 0
## is the major number of Nim's version.
## This works thanks to compiler magic.

NimMinor* {.magic: "NimrodMinor"}: int = 0
## is the minor number of Nim's version.
## This works thanks to compiler magic.

NimPatch* {.magic: "NimrodPatch"}: int = 0
## is the patch number of Nim's version.
## This works thanks to compiler magic.

cpuEndian* {.magic: "CpuEndian"}: Endianness = littleEndian
## is the endianness of the target CPU. This is a valuable piece of
## information for low-level code only. This works thanks to compiler
Expand All @@ -1048,9 +1032,6 @@ const

seqShallowFlag = low(int)

{.deprecated: [TEndian: Endianness, NimrodVersion: NimVersion,
NimrodMajor: NimMajor, NimrodMinor: NimMinor, NimrodPatch: NimPatch].}

proc compileOption*(option: string): bool {.
magic: "CompileOption", noSideEffect.}
## can be used to determine an on|off compile-time option. Example:
Expand Down Expand Up @@ -1470,11 +1451,11 @@ template `>%` *(x, y: expr): expr {.immediate.} = y <% x
## treats `x` and `y` as unsigned and compares them.
## Returns true iff ``unsigned(x) > unsigned(y)``.

proc `$` *(x: int): string {.magic: "IntToStr", noSideEffect.}
proc `$`*(x: int): string {.magic: "IntToStr", noSideEffect.}
## The stringify operator for an integer argument. Returns `x`
## converted to a decimal string.

proc `$` *(x: int64): string {.magic: "Int64ToStr", noSideEffect.}
proc `$`*(x: int64): string {.magic: "Int64ToStr", noSideEffect.}
## The stringify operator for an integer argument. Returns `x`
## converted to a decimal string.

Expand Down Expand Up @@ -1529,6 +1510,20 @@ const
## that you cannot compare a floating point value to this value
## and expect a reasonable result - use the `classify` procedure
## in the module ``math`` for checking for NaN.
NimMajor*: int = 0
## is the major number of Nim's version.

NimMinor*: int = 10
## is the minor number of Nim's version.

NimPatch*: int = 1
## is the patch number of Nim's version.

NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch
## is the version of Nim as a string.

{.deprecated: [TEndian: Endianness, NimrodVersion: NimVersion,
NimrodMajor: NimMajor, NimrodMinor: NimMinor, NimrodPatch: NimPatch].}

# GC interface:

Expand Down Expand Up @@ -3104,7 +3099,7 @@ proc locals*(): RootObj {.magic: "Locals", noSideEffect.} =
## generates a tuple constructor expression listing all the local variables
## in the current scope. This is quite fast as it does not rely
## on any debug or runtime information. Note that in constrast to what
## the official signature says, the return type is not ``TObject`` but a
## the official signature says, the return type is not ``RootObj`` but a
## tuple of a structure that depends on the current scope. Example:
##
## .. code-block:: nim
Expand Down Expand Up @@ -3132,4 +3127,13 @@ when hostOS != "standalone" and not defined(NimrodVM) and not defined(JS):

include "system/deepcopy"

proc procCall*(x: expr) {.magic: "ProcCall".} =
## special magic to prohibit dynamic binding for `method`:idx: calls.
## This is similar to `super`:idx: in ordinary OO languages.
##
## .. code-block:: nim
## # 'someMethod' will be resolved fully statically:
## procCall someMethod(a, b)
discard

{.pop.} #{.push warning[GcMem]: off.}
21 changes: 12 additions & 9 deletions tests/method/tmultim2.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
discard """
file: "tmultim2.nim"
output: "collide: unit, thing collide: unit, thing collide: thing, unit"
output: '''collide: unit, thing
collide: unit, thing
collide: thing, unit
collide: thing, thing'''
"""
# Test multi methods

Expand All @@ -12,25 +15,25 @@ type
a, b: int

method collide(a, b: TThing) {.inline.} =
quit "to override!"
echo "collide: thing, thing"

method collide(a: TThing, b: TUnit) {.inline.} =
write stdout, "collide: thing, unit "
echo "collide: thing, unit"

method collide(a: TUnit, b: TThing) {.inline.} =
write stdout, "collide: unit, thing "
echo "collide: unit, thing"

proc test(a, b: TThing) {.inline.} =
collide(a, b)

proc staticCollide(a, b: TThing) {.inline.} =
procCall collide(a, b)


var
a: TThing
b, c: TUnit
collide(b, c) # ambiguous (unit, thing) or (thing, unit)? -> prefer unit, thing!
test(b, c)
collide(a, b)
#OUT collide: unit, thing collide: unit, thing collide: thing, unit




staticCollide(a, b)
1 change: 0 additions & 1 deletion todo.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ version 0.10
============

- make nimble part of the distribution
- implement 'procCall'
- split idetools into separate tool
- split docgen into separate tool

Expand Down
2 changes: 2 additions & 0 deletions web/news.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ News
lock levels and object field ``guards``.
- The ``parallel`` statement has been implemented.
- ``deepCopy`` has been added to the language.
- The builtin ``procCall`` can be used to get ``super``-like functionality
for multi methods.


Compiler Additions
Expand Down

0 comments on commit 105a061

Please sign in to comment.