implemented procCall builtin
This commit is contained in:
parent
d456b882b1
commit
105a0616a9
11 changed files with 63 additions and 52 deletions
|
|
@ -566,8 +566,8 @@ type
|
||||||
mBool, mChar, mString, mCstring,
|
mBool, mChar, mString, mCstring,
|
||||||
mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc,
|
mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc,
|
||||||
mVoidType, mPNimrodNode, mShared, mGuarded, mLock, mSpawn, mDeepCopy,
|
mVoidType, mPNimrodNode, mShared, mGuarded, mLock, mSpawn, mDeepCopy,
|
||||||
mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor,
|
mIsMainModule, mCompileDate, mCompileTime, mProcCall,
|
||||||
mNimrodMinor, mNimrodPatch, mCpuEndian, mHostOS, mHostCPU, mAppType,
|
mCpuEndian, mHostOS, mHostCPU, mAppType,
|
||||||
mNaN, mInf, mNegInf,
|
mNaN, mInf, mNegInf,
|
||||||
mCompileOption, mCompileOptionArg,
|
mCompileOption, mCompileOptionArg,
|
||||||
mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, mNKind,
|
mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, mNKind,
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,6 @@
|
||||||
|
|
||||||
const
|
const
|
||||||
MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets?
|
MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets?
|
||||||
VersionMajor* = 0
|
VersionAsString* = system.NimVersion
|
||||||
VersionMinor* = 10
|
|
||||||
VersionPatch* = 1
|
|
||||||
VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
|
|
||||||
|
|
||||||
RodFileVersion* = "1215" # modify this if the rod-format changes!
|
RodFileVersion* = "1215" # modify this if the rod-format changes!
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1649,6 +1649,10 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
else:
|
else:
|
||||||
result.typ = result[1].typ
|
result.typ = result[1].typ
|
||||||
result.add instantiateCreateFlowVarCall(c, result[1].typ, n.info).newSymNode
|
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)
|
else: result = semDirectOp(c, n, flags)
|
||||||
|
|
||||||
proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||||
|
|
|
||||||
|
|
@ -613,10 +613,6 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
of mIsMainModule: result = newIntNodeT(ord(sfMainModule in m.flags), n)
|
of mIsMainModule: result = newIntNodeT(ord(sfMainModule in m.flags), n)
|
||||||
of mCompileDate: result = newStrNodeT(times.getDateStr(), n)
|
of mCompileDate: result = newStrNodeT(times.getDateStr(), n)
|
||||||
of mCompileTime: result = newStrNodeT(times.getClockStr(), 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 mCpuEndian: result = newIntNodeT(ord(CPU[targetCPU].endian), n)
|
||||||
of mHostOS: result = newStrNodeT(toLower(platform.OS[targetOS].name), n)
|
of mHostOS: result = newStrNodeT(toLower(platform.OS[targetOS].name), n)
|
||||||
of mHostCPU: result = newStrNodeT(platform.CPU[targetCPU].name.toLower, n)
|
of mHostCPU: result = newStrNodeT(platform.CPU[targetCPU].name.toLower, n)
|
||||||
|
|
|
||||||
|
|
@ -130,4 +130,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||||
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
||||||
of mNBindSym: result = semBindSym(c, n)
|
of mNBindSym: result = semBindSym(c, n)
|
||||||
of mLocals: result = semLocals(c, n)
|
of mLocals: result = semLocals(c, n)
|
||||||
|
of mProcCall:
|
||||||
|
result = n
|
||||||
|
result.typ = n[1].typ
|
||||||
else: result = n
|
else: result = n
|
||||||
|
|
|
||||||
|
|
@ -582,7 +582,7 @@ proc getMergeOp(n: PNode): PSym =
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc flattenTreeAux(d, a: PNode, op: PSym) =
|
proc flattenTreeAux(d, a: PNode, op: PSym) =
|
||||||
var op2 = getMergeOp(a)
|
let op2 = getMergeOp(a)
|
||||||
if op2 != nil and
|
if op2 != nil and
|
||||||
(op2.id == op.id or op.magic != mNone and op2.magic == op.magic):
|
(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)
|
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))
|
addSon(d, copyTree(a))
|
||||||
|
|
||||||
proc flattenTree(root: PNode): PNode =
|
proc flattenTree(root: PNode): PNode =
|
||||||
var op = getMergeOp(root)
|
let op = getMergeOp(root)
|
||||||
if op != nil:
|
if op != nil:
|
||||||
result = copyNode(root)
|
result = copyNode(root)
|
||||||
addSon(result, copyTree(root.sons[0]))
|
addSon(result, copyTree(root.sons[0]))
|
||||||
|
|
@ -600,8 +600,9 @@ proc flattenTree(root: PNode): PNode =
|
||||||
|
|
||||||
proc transformCall(c: PTransf, n: PNode): PTransNode =
|
proc transformCall(c: PTransf, n: PNode): PTransNode =
|
||||||
var n = flattenTree(n)
|
var n = flattenTree(n)
|
||||||
var op = getMergeOp(n)
|
let op = getMergeOp(n)
|
||||||
if (op != nil) and (op.magic != mNone) and (sonsLen(n) >= 3):
|
let magic = getMagic(n)
|
||||||
|
if op != nil and op.magic != mNone and n.len >= 3:
|
||||||
result = newTransNode(nkCall, n, 0)
|
result = newTransNode(nkCall, n, 0)
|
||||||
add(result, transform(c, n.sons[0]))
|
add(result, transform(c, n.sons[0]))
|
||||||
var j = 1
|
var j = 1
|
||||||
|
|
@ -616,9 +617,12 @@ proc transformCall(c: PTransf, n: PNode): PTransNode =
|
||||||
inc(j)
|
inc(j)
|
||||||
add(result, a.PTransNode)
|
add(result, a.PTransNode)
|
||||||
if len(result) == 2: result = result[1]
|
if len(result) == 2: result = result[1]
|
||||||
elif getMagic(n) == mNBindSym:
|
elif magic == mNBindSym:
|
||||||
# for bindSym(myconst) we MUST NOT perform constant folding:
|
# for bindSym(myconst) we MUST NOT perform constant folding:
|
||||||
result = n.PTransNode
|
result = n.PTransNode
|
||||||
|
elif magic == mProcCall:
|
||||||
|
# but do not change to its dispatcher:
|
||||||
|
result = transformSons(c, n[1])
|
||||||
else:
|
else:
|
||||||
let s = transformSons(c, n).PNode
|
let s = transformSons(c, n).PNode
|
||||||
# bugfix: check after 'transformSons' if it's still a method call:
|
# bugfix: check after 'transformSons' if it's still a method call:
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ the best match for the arguments. Example:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
proc toLower(c: Char): Char = # toLower for characters
|
proc toLower(c: char): char = # toLower for characters
|
||||||
if c in {'A'..'Z'}:
|
if c in {'A'..'Z'}:
|
||||||
result = chr(ord(c) + (ord('a') - ord('A')))
|
result = chr(ord(c) + (ord('a') - ord('A')))
|
||||||
else:
|
else:
|
||||||
|
|
@ -237,7 +237,7 @@ The following builtin procs cannot be overloaded for reasons of implementation
|
||||||
simplicity (they require specialized semantic checking)::
|
simplicity (they require specialized semantic checking)::
|
||||||
|
|
||||||
declared, defined, definedInScope, compiles, low, high, sizeOf,
|
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
|
Thus they act more like keywords than like ordinary identifiers; unlike a
|
||||||
keyword however, a redefinition may `shadow`:idx: the definition in
|
keyword however, a redefinition may `shadow`:idx: the definition in
|
||||||
|
|
|
||||||
|
|
@ -1016,22 +1016,6 @@ const
|
||||||
## is the time of compilation as a string of the form
|
## is the time of compilation as a string of the form
|
||||||
## ``HH:MM:SS``. This works thanks to compiler magic.
|
## ``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
|
cpuEndian* {.magic: "CpuEndian"}: Endianness = littleEndian
|
||||||
## is the endianness of the target CPU. This is a valuable piece of
|
## is the endianness of the target CPU. This is a valuable piece of
|
||||||
## information for low-level code only. This works thanks to compiler
|
## information for low-level code only. This works thanks to compiler
|
||||||
|
|
@ -1048,9 +1032,6 @@ const
|
||||||
|
|
||||||
seqShallowFlag = low(int)
|
seqShallowFlag = low(int)
|
||||||
|
|
||||||
{.deprecated: [TEndian: Endianness, NimrodVersion: NimVersion,
|
|
||||||
NimrodMajor: NimMajor, NimrodMinor: NimMinor, NimrodPatch: NimPatch].}
|
|
||||||
|
|
||||||
proc compileOption*(option: string): bool {.
|
proc compileOption*(option: string): bool {.
|
||||||
magic: "CompileOption", noSideEffect.}
|
magic: "CompileOption", noSideEffect.}
|
||||||
## can be used to determine an on|off compile-time option. Example:
|
## can be used to determine an on|off compile-time option. Example:
|
||||||
|
|
@ -1529,6 +1510,20 @@ const
|
||||||
## that you cannot compare a floating point value to this value
|
## that you cannot compare a floating point value to this value
|
||||||
## and expect a reasonable result - use the `classify` procedure
|
## and expect a reasonable result - use the `classify` procedure
|
||||||
## in the module ``math`` for checking for NaN.
|
## 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:
|
# GC interface:
|
||||||
|
|
||||||
|
|
@ -3104,7 +3099,7 @@ proc locals*(): RootObj {.magic: "Locals", noSideEffect.} =
|
||||||
## generates a tuple constructor expression listing all the local variables
|
## generates a tuple constructor expression listing all the local variables
|
||||||
## in the current scope. This is quite fast as it does not rely
|
## 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
|
## 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:
|
## tuple of a structure that depends on the current scope. Example:
|
||||||
##
|
##
|
||||||
## .. code-block:: nim
|
## .. code-block:: nim
|
||||||
|
|
@ -3132,4 +3127,13 @@ when hostOS != "standalone" and not defined(NimrodVM) and not defined(JS):
|
||||||
|
|
||||||
include "system/deepcopy"
|
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.}
|
{.pop.} #{.push warning[GcMem]: off.}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
discard """
|
discard """
|
||||||
file: "tmultim2.nim"
|
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
|
# Test multi methods
|
||||||
|
|
||||||
|
|
@ -12,25 +15,25 @@ type
|
||||||
a, b: int
|
a, b: int
|
||||||
|
|
||||||
method collide(a, b: TThing) {.inline.} =
|
method collide(a, b: TThing) {.inline.} =
|
||||||
quit "to override!"
|
echo "collide: thing, thing"
|
||||||
|
|
||||||
method collide(a: TThing, b: TUnit) {.inline.} =
|
method collide(a: TThing, b: TUnit) {.inline.} =
|
||||||
write stdout, "collide: thing, unit "
|
echo "collide: thing, unit"
|
||||||
|
|
||||||
method collide(a: TUnit, b: TThing) {.inline.} =
|
method collide(a: TUnit, b: TThing) {.inline.} =
|
||||||
write stdout, "collide: unit, thing "
|
echo "collide: unit, thing"
|
||||||
|
|
||||||
proc test(a, b: TThing) {.inline.} =
|
proc test(a, b: TThing) {.inline.} =
|
||||||
collide(a, b)
|
collide(a, b)
|
||||||
|
|
||||||
|
proc staticCollide(a, b: TThing) {.inline.} =
|
||||||
|
procCall collide(a, b)
|
||||||
|
|
||||||
|
|
||||||
var
|
var
|
||||||
a: TThing
|
a: TThing
|
||||||
b, c: TUnit
|
b, c: TUnit
|
||||||
collide(b, c) # ambiguous (unit, thing) or (thing, unit)? -> prefer unit, thing!
|
collide(b, c) # ambiguous (unit, thing) or (thing, unit)? -> prefer unit, thing!
|
||||||
test(b, c)
|
test(b, c)
|
||||||
collide(a, b)
|
collide(a, b)
|
||||||
#OUT collide: unit, thing collide: unit, thing collide: thing, unit
|
staticCollide(a, b)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -2,7 +2,6 @@ version 0.10
|
||||||
============
|
============
|
||||||
|
|
||||||
- make nimble part of the distribution
|
- make nimble part of the distribution
|
||||||
- implement 'procCall'
|
|
||||||
- split idetools into separate tool
|
- split idetools into separate tool
|
||||||
- split docgen into separate tool
|
- split docgen into separate tool
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ News
|
||||||
lock levels and object field ``guards``.
|
lock levels and object field ``guards``.
|
||||||
- The ``parallel`` statement has been implemented.
|
- The ``parallel`` statement has been implemented.
|
||||||
- ``deepCopy`` has been added to the language.
|
- ``deepCopy`` has been added to the language.
|
||||||
|
- The builtin ``procCall`` can be used to get ``super``-like functionality
|
||||||
|
for multi methods.
|
||||||
|
|
||||||
|
|
||||||
Compiler Additions
|
Compiler Additions
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue