implemented procCall builtin

This commit is contained in:
Araq
2014-11-28 02:43:41 +01:00
parent d456b882b1
commit 105a0616a9
11 changed files with 63 additions and 52 deletions

View File

@@ -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,

View File

@@ -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!

View File

@@ -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 =

View File

@@ -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)

View File

@@ -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

View File

@@ -582,7 +582,7 @@ 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)
@@ -590,7 +590,7 @@ proc flattenTreeAux(d, a: PNode, op: PSym) =
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]))
@@ -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
@@ -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:

View File

@@ -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:
@@ -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"
@@ -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

View File

@@ -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
@@ -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:
@@ -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.
@@ -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:
@@ -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
@@ -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.}

View File

@@ -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
@@ -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)

View File

@@ -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

View File

@@ -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