mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-08 14:03:23 +00:00
implemented procCall builtin
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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!
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.}
|
||||
|
||||
@@ -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)
|
||||
|
||||
1
todo.txt
1
todo.txt
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user