Merge branch 'devel' of https://github.com/Araq/Nim into devel

This commit is contained in:
Araq 2015-04-20 11:44:54 +02:00
commit 2b4e233510
18 changed files with 192 additions and 54 deletions

View file

@ -796,8 +796,8 @@ type
# for enum types a list of symbols # for enum types a list of symbols
# for tyInt it can be the int literal # for tyInt it can be the int literal
# for procs and tyGenericBody, it's the # for procs and tyGenericBody, it's the
# the body of the user-defined type class
# formal param list # formal param list
# for concepts, the concept body
# else: unused # else: unused
owner*: PSym # the 'owner' of the type owner*: PSym # the 'owner' of the type
sym*: PSym # types have the sym associated with them sym*: PSym # types have the sym associated with them

View file

@ -385,18 +385,11 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): Rope =
inc j inc j
inc i inc i
of '\'': of '\'':
inc i var idx, stars: int
let stars = i if scanCppGenericSlot(pat, i, idx, stars):
while pat[i] == '*': inc i var t = resolveStarsInCppType(typ, idx, stars)
if pat[i] in Digits:
let j = pat[i].ord - '0'.ord
var t = typ.sons[j]
for k in 1..i-stars:
if t != nil and t.len > 0:
t = if t.kind == tyGenericInst: t.sons[1] else: t.elemType
if t == nil: result.add(~"void") if t == nil: result.add(~"void")
else: result.add(getTypeDesc(p.module, t)) else: result.add(getTypeDesc(p.module, t))
inc i
else: else:
let start = i let start = i
while i < pat.len: while i < pat.len:

View file

@ -495,6 +495,33 @@ proc getTupleDesc(m: BModule, typ: PType, name: Rope,
else: add(result, desc) else: add(result, desc)
add(result, "};" & tnl) add(result, "};" & tnl)
proc scanCppGenericSlot(pat: string, cursor, outIdx, outStars: var int): bool =
# A helper proc for handling cppimport patterns, involving numeric
# placeholders for generic types (e.g. '0, '**2, etc).
# pre: the cursor must be placed at the ' symbol
# post: the cursor will be placed after the final digit
# false will returned if the input is not recognized as a placeholder
inc cursor
let begin = cursor
while pat[cursor] == '*': inc cursor
if pat[cursor] in Digits:
outIdx = pat[cursor].ord - '0'.ord
outStars = cursor - begin
inc cursor
return true
else:
return false
proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
# XXX: we should catch this earlier and report it as a semantic error
if idx >= typ.len: internalError "invalid apostrophe type parameter index"
result = typ.sons[idx]
for i in 1..stars:
if result != nil and result.len > 0:
result = if result.kind == tyGenericInst: result.sons[1]
else: result.elemType
proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope = proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
# returns only the type's name # returns only the type's name
var t = getUniqueType(typ) var t = getUniqueType(typ)
@ -597,11 +624,33 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
if isImportedCppType(t) and typ.kind == tyGenericInst: if isImportedCppType(t) and typ.kind == tyGenericInst:
# for instantiated templates we do not go through the type cache as the # for instantiated templates we do not go through the type cache as the
# the type cache is not aware of 'tyGenericInst'. # the type cache is not aware of 'tyGenericInst'.
result = getTypeName(t) & "<" let cppName = getTypeName(t)
for i in 1 .. typ.len-2: var i = 0
if i > 1: result.add(", ") var chunkStart = 0
result.add(getTypeDescAux(m, typ.sons[i], check)) while i < cppName.data.len:
result.add("> ") if cppName.data[i] == '\'':
var chunkEnd = <i
var idx, stars: int
if scanCppGenericSlot(cppName.data, i, idx, stars):
result.add cppName.data.substr(chunkStart, chunkEnd)
chunkStart = i
let typeInSlot = resolveStarsInCppType(typ, idx + 1, stars)
if typeInSlot == nil or typeInSlot.kind == tyEmpty:
result.add(~"void")
else:
result.add getTypeDescAux(m, typeInSlot, check)
else:
inc i
if chunkStart != 0:
result.add cppName.data.substr(chunkStart)
else:
result = cppName & "<"
for i in 1 .. typ.len-2:
if i > 1: result.add(", ")
result.add(getTypeDescAux(m, typ.sons[i], check))
result.add("> ")
# always call for sideeffects: # always call for sideeffects:
assert t.kind != tyTuple assert t.kind != tyTuple
discard getRecordDesc(m, t, result, check) discard getRecordDesc(m, t, result, check)

View file

@ -827,6 +827,9 @@ proc localError*(info: TLineInfo, msg: TMsgKind, arg = "") =
proc localError*(info: TLineInfo, arg: string) = proc localError*(info: TLineInfo, arg: string) =
liMessage(info, errGenerated, arg, doNothing) liMessage(info, errGenerated, arg, doNothing)
proc localError*(info: TLineInfo, format: string, params: openarray[string]) =
localError(info, format % params)
proc message*(info: TLineInfo, msg: TMsgKind, arg = "") = proc message*(info: TLineInfo, msg: TMsgKind, arg = "") =
liMessage(info, msg, arg, doNothing) liMessage(info, msg, arg, doNothing)

View file

@ -212,7 +212,8 @@ proc getPrecedence(tok: TToken, strongSpaces: bool): int =
let relevantChar = tok.ident.s[0] let relevantChar = tok.ident.s[0]
# arrow like? # arrow like?
if L > 1 and tok.ident.s[L-1] == '>': return considerStrongSpaces(1) if L > 1 and tok.ident.s[L-1] == '>' and
tok.ident.s[L-2] in {'-', '~', '='}: return considerStrongSpaces(1)
template considerAsgn(value: expr) = template considerAsgn(value: expr) =
result = if tok.ident.s[L-1] == '=': 1 else: value result = if tok.ident.s[L-1] == '=': 1 else: value

View file

@ -144,7 +144,9 @@ proc mapTypeToAst(t: PType, info: TLineInfo; allowRecursion=false): PNode =
of tyIter: result = mapTypeToBracket("iter", t, info) of tyIter: result = mapTypeToBracket("iter", t, info)
of tyProxy: result = atomicType"error" of tyProxy: result = atomicType"error"
of tyBuiltInTypeClass: result = mapTypeToBracket("builtinTypeClass", t, info) of tyBuiltInTypeClass: result = mapTypeToBracket("builtinTypeClass", t, info)
of tyUserTypeClass: result = mapTypeToBracket("userTypeClass", t, info) of tyUserTypeClass:
result = mapTypeToBracket("concept", t, info)
result.add t.n.copyTree
of tyCompositeTypeClass: result = mapTypeToBracket("compositeTypeClass", t, info) of tyCompositeTypeClass: result = mapTypeToBracket("compositeTypeClass", t, info)
of tyAnd: result = mapTypeToBracket("and", t, info) of tyAnd: result = mapTypeToBracket("and", t, info)
of tyOr: result = mapTypeToBracket("or", t, info) of tyOr: result = mapTypeToBracket("or", t, info)

View file

@ -289,7 +289,7 @@ Numerical constants are of a single type and have the form::
INT32_LIT = INT_LIT ['\''] ('i' | 'I') '32' INT32_LIT = INT_LIT ['\''] ('i' | 'I') '32'
INT64_LIT = INT_LIT ['\''] ('i' | 'I') '64' INT64_LIT = INT_LIT ['\''] ('i' | 'I') '64'
UINT8_LIT = INT_LIT ['\''] ('u' | 'U') UINT_LIT = INT_LIT ['\''] ('u' | 'U')
UINT8_LIT = INT_LIT ['\''] ('u' | 'U') '8' UINT8_LIT = INT_LIT ['\''] ('u' | 'U') '8'
UINT16_LIT = INT_LIT ['\''] ('u' | 'U') '16' UINT16_LIT = INT_LIT ['\''] ('u' | 'U') '16'
UINT32_LIT = INT_LIT ['\''] ('u' | 'U') '32' UINT32_LIT = INT_LIT ['\''] ('u' | 'U') '32'

View file

@ -15,8 +15,6 @@ Associativity
Binary operators whose first character is ``^`` are right-associative, all Binary operators whose first character is ``^`` are right-associative, all
other binary operators are left-associative. other binary operators are left-associative.
Operators ending in ``>`` but longer than a single character are
called `arrow like`:idx:.
Precedence Precedence
@ -33,9 +31,12 @@ as ``(@x).abc`` whereas ``$x.abc`` is parsed as ``$(x.abc)``.
For binary operators that are not keywords the precedence is determined by the For binary operators that are not keywords the precedence is determined by the
following rules: following rules:
Operators ending in either ``->``, ``~>`` or ``=>`` are called
`arrow like`:idx:, and have the lowest precedence of all operators.
If the operator ends with ``=`` and its first character is none of If the operator ends with ``=`` and its first character is none of
``<``, ``>``, ``!``, ``=``, ``~``, ``?``, it is an *assignment operator* which ``<``, ``>``, ``!``, ``=``, ``~``, ``?``, it is an *assignment operator* which
has the lowest precedence. has the second lowest precedence.
Otherwise precedence is determined by the first character. Otherwise precedence is determined by the first character.
@ -43,14 +44,14 @@ Otherwise precedence is determined by the first character.
Precedence level Operators First character Terminal symbol Precedence level Operators First character Terminal symbol
================ =============================================== ================== =============== ================ =============================================== ================== ===============
10 (highest) ``$ ^`` OP10 10 (highest) ``$ ^`` OP10
9 ``* / div mod shl shr %`` ``* % \ /`` OP9 9 ``* / div mod shl shr %`` ``* % \ /`` OP9
8 ``+ -`` ``+ ~ |`` OP8 8 ``+ -`` ``+ - ~ |`` OP8
7 ``&`` ``&`` OP7 7 ``&`` ``&`` OP7
6 ``..`` ``.`` OP6 6 ``..`` ``.`` OP6
5 ``== <= < >= > != in notin is isnot not of`` ``= < > !`` OP5 5 ``== <= < >= > != in notin is isnot not of`` ``= < > !`` OP5
4 ``and`` OP4 4 ``and`` OP4
3 ``or xor`` OP3 3 ``or xor`` OP3
2 ``@ : ?`` OP2 2 ``@ : ?`` OP2
1 *assignment operator* (like ``+=``, ``*=``) OP1 1 *assignment operator* (like ``+=``, ``*=``) OP1
0 (lowest) *arrow like operator* (like ``->``, ``=>``) OP0 0 (lowest) *arrow like operator* (like ``->``, ``=>``) OP0
================ =============================================== ================== =============== ================ =============================================== ================== ===============
@ -67,7 +68,7 @@ is still parsed as ``1 + (3 * 4)``, but ``1+3 * 4`` is parsed as ``(1+3) * 4``:
.. code-block:: nim .. code-block:: nim
#! strongSpaces #! strongSpaces
if foo+4 * 4 == 8 and b&c | 9 ++ if foo+4 * 4 == 8 and b&c | 9 ++
bar: bar:
echo "" echo ""
# is parsed as # is parsed as

View file

@ -506,7 +506,7 @@ For example:
.. code-block:: nim .. code-block:: nim
type Input {.importcpp: "System::Input".} = object type Input {.importcpp: "System::Input".} = object
proc getSubsystem*[T](): ptr T {.importcpp: "SystemManager::getSubsystem<'*0>()".} proc getSubsystem*[T](): ptr T {.importcpp: "SystemManager::getSubsystem<'*0>()", nodecl.}
let x: ptr Input = getSubsystem[Input]() let x: ptr Input = getSubsystem[Input]()
@ -596,6 +596,25 @@ Produces:
x[6] = 91.4; x[6] = 91.4;
- If more precise control is needed, the apostrophe ``'`` can be used in the
supplied pattern to denote the concrete type parameters of the generic type.
See the usage of the apostrophe operator in proc patterns for more details.
.. code-block:: nim
type
VectorIterator {.importcpp: "std::vector<'0>::iterator".} [T] = object
var x: VectorIterator[cint]
Produces:
.. code-block:: C
std::vector<int>::iterator x;
ImportObjC pragma ImportObjC pragma
----------------- -----------------
Similar to the `importc pragma for C <manual.html#importc-pragma>`_, the Similar to the `importc pragma for C <manual.html#importc-pragma>`_, the

View file

@ -88,7 +88,9 @@ type
ntyBigNum, ntyBigNum,
ntyConst, ntyMutable, ntyVarargs, ntyConst, ntyMutable, ntyVarargs,
ntyIter, ntyIter,
ntyError ntyError,
ntyBuiltinTypeClass, ntyConcept, ntyConceptInst, ntyComposite,
ntyAnd, ntyOr, ntyNot
TNimTypeKinds* {.deprecated.} = set[NimTypeKind] TNimTypeKinds* {.deprecated.} = set[NimTypeKind]
NimSymKind* = enum NimSymKind* = enum

View file

@ -7,8 +7,11 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
## Regular expression support for Nim. Consider using the pegs module ## Regular expression support for Nim. Consider using the pegs module instead.
## instead. ##
## There is an alternative regular expressions library with a more unified API:
## `nre <https://github.com/flaviut/nre>`_. It may be added to the standard
## library in the future, instead of `re`.
## ##
## **Note:** The 're' proc defaults to the **extended regular expression ## **Note:** The 're' proc defaults to the **extended regular expression
## syntax** which lets you use whitespace freely to make your regexes readable. ## syntax** which lets you use whitespace freely to make your regexes readable.
@ -413,22 +416,28 @@ proc escapeRe*(s: string): string =
result.add(toHex(ord(c), 2)) result.add(toHex(ord(c), 2))
const ## common regular expressions const ## common regular expressions
reIdentifier* = r"\b[a-zA-Z_]+[a-zA-Z_0-9]*\b" ## describes an identifier reIdentifier* {.deprecated.} = r"\b[a-zA-Z_]+[a-zA-Z_0-9]*\b"
reNatural* = r"\b\d+\b" ## describes a natural number ## describes an identifier
reInteger* = r"\b[-+]?\d+\b" ## describes an integer reNatural* {.deprecated.} = r"\b\d+\b"
reHex* = r"\b0[xX][0-9a-fA-F]+\b" ## describes a hexadecimal number ## describes a natural number
reBinary* = r"\b0[bB][01]+\b" ## describes a binary number (example: 0b11101) reInteger* {.deprecated.} = r"\b[-+]?\d+\b"
reOctal* = r"\b0[oO][0-7]+\b" ## describes an octal number (example: 0o777) ## describes an integer
reFloat* = r"\b[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\b" reHex* {.deprecated.} = r"\b0[xX][0-9a-fA-F]+\b"
## describes a hexadecimal number
reBinary* {.deprecated.} = r"\b0[bB][01]+\b"
## describes a binary number (example: 0b11101)
reOctal* {.deprecated.} = r"\b0[oO][0-7]+\b"
## describes an octal number (example: 0o777)
reFloat* {.deprecated.} = r"\b[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\b"
## describes a floating point number ## describes a floating point number
reEmail* = r"\b[a-zA-Z0-9!#$%&'*+/=?^_`{|}~\-]+(?:\. &" & reEmail* {.deprecated.} = r"\b[a-zA-Z0-9!#$%&'*+/=?^_`{|}~\-]+(?:\. &" &
r"[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)" & r"[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@" &
r"*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+" & r"(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+" &
r"(?:[a-zA-Z]{2}|com|org|" & r"(?:[a-zA-Z]{2}|com|org|net|gov|mil|biz|" &
r"net|gov|mil|biz|info|mobi|name|aero|jobs|museum)\b" r"info|mobi|name|aero|jobs|museum)\b"
## describes a common email address ## describes a common email address
reURL* = r"\b(http(s)?|ftp|gopher|telnet|file|notes|ms\-help):" & reURL* {.deprecated.} = r"\b(http(s)?|ftp|gopher|telnet|file|notes|ms-help)" &
r"((//)|(\\\\))+[\w\d:#@%/;$()~_?\+\-\=\\\.\&]*\b" r":((//)|(\\\\))+[\w\d:#@%/;$()~_?\+\-\=\\\.\&]*\b"
## describes an URL ## describes an URL
when isMainModule: when isMainModule:

View file

@ -564,7 +564,7 @@ proc fixupEmbeddedRef(n, a, b: PRstNode) =
proc parsePostfix(p: var TRstParser, n: PRstNode): PRstNode = proc parsePostfix(p: var TRstParser, n: PRstNode): PRstNode =
result = n result = n
if isInlineMarkupEnd(p, "_"): if isInlineMarkupEnd(p, "_") or isInlineMarkupEnd(p, "__"):
inc(p.idx) inc(p.idx)
if p.tok[p.idx-2].symbol == "`" and p.tok[p.idx-3].symbol == ">": if p.tok[p.idx-2].symbol == "`" and p.tok[p.idx-3].symbol == ">":
var a = newRstNode(rnInner) var a = newRstNode(rnInner)

View file

@ -883,7 +883,7 @@ elif not defined(useNimRtl):
var ret = waitpid(p.id, p.exitCode, WNOHANG) var ret = waitpid(p.id, p.exitCode, WNOHANG)
var b = ret == int(p.id) var b = ret == int(p.id)
if b: result = -1 if b: result = -1
if p.exitCode == -3: result = -1 if not WIFEXITED(p.exitCode): result = -1
else: result = p.exitCode.int shr 8 else: result = p.exitCode.int shr 8
proc createStream(stream: var Stream, handle: var FileHandle, proc createStream(stream: var Stream, handle: var FileHandle,

View file

@ -87,7 +87,7 @@ when someGcc and hasThreadSupport:
proc atomicCompareExchange*[T: TAtomType](p, expected, desired: ptr T, proc atomicCompareExchange*[T: TAtomType](p, expected, desired: ptr T,
weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {. weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {.
importc: "__atomic_compare_exchange_n ", nodecl.} importc: "__atomic_compare_exchange", nodecl.}
## This proc implements the generic version of atomic_compare_exchange. ## This proc implements the generic version of atomic_compare_exchange.
## The proc is virtually identical to atomic_compare_exchange_n, except the desired ## The proc is virtually identical to atomic_compare_exchange_n, except the desired
## value is also a pointer. ## value is also a pointer.

View file

@ -0,0 +1,22 @@
discard """
cmd: "nim cpp $file"
"""
{.emit: """
namespace System {
struct Input {};
}
struct SystemManager {
template <class T>
static T* getSubsystem() { return new T; }
};
""".}
type Input {.importcpp: "System::Input".} = object
proc getSubsystem*[T](): ptr T {.importcpp: "SystemManager::getSubsystem<'*0>()".}
let input: ptr Input = getSubsystem[Input]()

View file

@ -0,0 +1,19 @@
discard """
cmd: "nim cpp $file"
"""
{.emit: """
template <class T>
struct Vector {
struct Iterator {};
};
""".}
type
Vector {.importcpp: "Vector".} [T] = object
VectorIterator {.importcpp: "Vector<'0>::Iterator".} [T] = object
var x: VectorIterator[void]

View file

@ -15,6 +15,10 @@ true
tester args tester args
all all
all args all args
19
-3
false
-2
''' '''
""" """
@ -67,3 +71,13 @@ const
echo tester & " " & args|"all" echo tester & " " & args|"all"
echo "all" | tester & " " & args echo "all" | tester & " " & args
echo "all"|tester & " " & args echo "all"|tester & " " & args
# Test arrow like operators. See also tests/macros/tclosuremacro.nim
proc `+->`(a, b: int): int = a + b*4
template `===>`(a, b: int): expr = a - b shr 1
echo 3 +-> 2 + 2 and 4
var arrowed = 3+->2 + 2 and 4 # arrowed = 4
echo arrowed ===> 15
echo (2 * 3+->2) == (2*3 +-> 2)
echo arrowed ===> 2 + 3+->2

View file

@ -34,6 +34,10 @@ News
should be used instead. should be used instead.
- ``nim idetools`` has been replaced by a separate tool `nimsuggest`_. - ``nim idetools`` has been replaced by a separate tool `nimsuggest`_.
- *arrow like* operators are not right associative anymore. - *arrow like* operators are not right associative anymore.
- *arrow like* operators are now required to end with either ``->``, ``~>`` or
``=>``, not just ``>``. Examples of operators still considered arrow like:
``->``, ``==>``, ``+=>``. On the other hand, the following operators are now
considered regular operators again: ``|>``, ``-+>``, etc.
- Typeless parameters are now only allowed in templates and macros. The old - Typeless parameters are now only allowed in templates and macros. The old
way turned out to be too error-prone. way turned out to be too error-prone.
- The 'addr' and 'type' operators are now parsed as unary function - The 'addr' and 'type' operators are now parsed as unary function