mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 08:54:53 +00:00
use 'using' instead of 'sig' keyword; cleans up new features a bit
This commit is contained in:
@@ -221,7 +221,6 @@ type
|
||||
nkGotoState, # used for the state machine (for iterators)
|
||||
nkState, # give a label to a code section (for iterators)
|
||||
nkBreakState, # special break statement for easier code generation
|
||||
nkSigSection
|
||||
TNodeKinds* = set[TNodeKind]
|
||||
|
||||
type
|
||||
|
||||
@@ -45,7 +45,7 @@ type
|
||||
tkMacro, tkMethod, tkMixin, tkMod, tkNil, tkNot, tkNotin,
|
||||
tkObject, tkOf, tkOr, tkOut,
|
||||
tkProc, tkPtr, tkRaise, tkRef, tkReturn,
|
||||
tkShl, tkShr, tkSig, tkStatic,
|
||||
tkShl, tkShr, tkStatic,
|
||||
tkTemplate,
|
||||
tkTry, tkTuple, tkType, tkUsing,
|
||||
tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor,
|
||||
@@ -82,7 +82,7 @@ const
|
||||
"macro", "method", "mixin", "mod",
|
||||
"nil", "not", "notin", "object", "of", "or",
|
||||
"out", "proc", "ptr", "raise", "ref", "return",
|
||||
"shl", "shr", "sig", "static",
|
||||
"shl", "shr", "static",
|
||||
"template",
|
||||
"try", "tuple", "type", "using",
|
||||
"var", "when", "while", "with", "without", "xor",
|
||||
|
||||
@@ -1908,7 +1908,7 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
|
||||
#| | 'converter' routine
|
||||
#| | 'type' section(typeDef)
|
||||
#| | 'const' section(constant)
|
||||
#| | ('let' | 'var') section(variable)
|
||||
#| | ('let' | 'var' | 'using') section(variable)
|
||||
#| | bindStmt | mixinStmt)
|
||||
#| / simpleStmt
|
||||
case p.tok.tokType
|
||||
@@ -1943,10 +1943,9 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
|
||||
of tkLet: result = parseSection(p, nkLetSection, parseVariable)
|
||||
of tkWhen: result = parseIfOrWhen(p, nkWhenStmt)
|
||||
of tkVar: result = parseSection(p, nkVarSection, parseVariable)
|
||||
of tkSig: result = parseSection(p, nkSigSection, parseVariable)
|
||||
of tkBind: result = parseBind(p, nkBindStmt)
|
||||
of tkMixin: result = parseBind(p, nkMixinStmt)
|
||||
of tkUsing: result = parseBind(p, nkUsingStmt)
|
||||
of tkUsing: result = parseSection(p, nkUsingStmt, parseVariable)
|
||||
else: result = simpleStmt(p)
|
||||
|
||||
proc parseStmt(p: var TParser): PNode =
|
||||
|
||||
@@ -460,9 +460,12 @@ proc lsub(n: PNode): int =
|
||||
else:
|
||||
result = len("enum")
|
||||
of nkEnumFieldDef: result = lsons(n) + 3
|
||||
of nkVarSection, nkLetSection, nkSigSection:
|
||||
of nkVarSection, nkLetSection:
|
||||
if sonsLen(n) > 1: result = MaxLineLen + 1
|
||||
else: result = lsons(n) + len("var_")
|
||||
of nkUsingStmt:
|
||||
if sonsLen(n) > 1: result = MaxLineLen + 1
|
||||
else: result = lsons(n) + len("using_")
|
||||
of nkReturnStmt: result = lsub(n.sons[0]) + len("return_")
|
||||
of nkRaiseStmt: result = lsub(n.sons[0]) + len("raise_")
|
||||
of nkYieldStmt: result = lsub(n.sons[0]) + len("yield_")
|
||||
@@ -1173,12 +1176,12 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
initContext(a)
|
||||
incl(a.flags, rfInConstExpr)
|
||||
gsection(g, n, a, tkConst, "const")
|
||||
of nkVarSection, nkLetSection, nkSigSection:
|
||||
of nkVarSection, nkLetSection, nkUsingStmt:
|
||||
var L = sonsLen(n)
|
||||
if L == 0: return
|
||||
if n.kind == nkVarSection: putWithSpace(g, tkVar, "var")
|
||||
elif n.kind == nkLetSection: putWithSpace(g, tkLet, "let")
|
||||
else: putWithSpace(g, tkSig, "sig")
|
||||
else: putWithSpace(g, tkUsing, "using")
|
||||
if L > 1:
|
||||
gcoms(g)
|
||||
indentNL(g)
|
||||
|
||||
@@ -1556,10 +1556,6 @@ proc newAnonSym(kind: TSymKind, info: TLineInfo,
|
||||
result = newSym(kind, idAnon, owner, info)
|
||||
result.flags = {sfGenSym}
|
||||
|
||||
proc semUsing(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
localError(n.info, "'using' statement is obsolete")
|
||||
|
||||
proc semExpandToAst(c: PContext, n: PNode): PNode =
|
||||
var macroCall = n[1]
|
||||
var expandedSym = expectMacroOrTemplateCall(c, macroCall)
|
||||
@@ -2354,7 +2350,6 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
if not n.sons[0].typ.isEmptyType and not implicitlyDiscardable(n.sons[0]):
|
||||
localError(n.info, errGenerated, "'defer' takes a 'void' expression")
|
||||
#localError(n.info, errGenerated, "'defer' not allowed in this context")
|
||||
of nkSigSection: result = semSigSection(c, n)
|
||||
else:
|
||||
localError(n.info, errInvalidExpressionX,
|
||||
renderTree(n, {renderNoComments}))
|
||||
|
||||
@@ -386,8 +386,11 @@ proc isDiscardUnderscore(v: PSym): bool =
|
||||
v.flags.incl(sfGenSym)
|
||||
result = true
|
||||
|
||||
proc semSigSection(c: PContext; n: PNode): PNode =
|
||||
proc semUsing(c: PContext; n: PNode): PNode =
|
||||
result = ast.emptyNode
|
||||
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "using")
|
||||
if not experimentalMode(c):
|
||||
localError(n.info, "use the {.experimental.} pragma to enable 'using'")
|
||||
for i in countup(0, sonsLen(n)-1):
|
||||
var a = n.sons[i]
|
||||
if gCmd == cmdIdeTools: suggestStmt(c, a)
|
||||
@@ -402,10 +405,10 @@ proc semSigSection(c: PContext; n: PNode): PNode =
|
||||
v.typ = typ
|
||||
strTableIncl(c.signatures, v)
|
||||
else:
|
||||
localError(a.info, "'sig' section must have a type")
|
||||
localError(a.info, "'using' section must have a type")
|
||||
var def: PNode
|
||||
if a.sons[length-1].kind != nkEmpty:
|
||||
localError(a.info, "'sig' sections cannot contain assignments")
|
||||
localError(a.info, "'using' sections cannot contain assignments")
|
||||
|
||||
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
var b: PNode
|
||||
|
||||
@@ -30,7 +30,7 @@ type
|
||||
wInclude, wInterface, wIs, wIsnot, wIterator, wLet,
|
||||
wMacro, wMethod, wMixin, wMod, wNil,
|
||||
wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn,
|
||||
wShl, wShr, wSig, wStatic, wTemplate, wTry, wTuple, wType, wUsing, wVar,
|
||||
wShl, wShr, wStatic, wTemplate, wTry, wTuple, wType, wUsing, wVar,
|
||||
wWhen, wWhile, wWith, wWithout, wXor, wYield,
|
||||
|
||||
wColon, wColonColon, wEquals, wDot, wDotDot,
|
||||
@@ -114,7 +114,7 @@ const
|
||||
"macro", "method", "mixin", "mod", "nil", "not", "notin",
|
||||
"object", "of", "or",
|
||||
"out", "proc", "ptr", "raise", "ref", "return",
|
||||
"shl", "shr", "sig", "static",
|
||||
"shl", "shr", "static",
|
||||
"template", "try", "tuple", "type", "using", "var",
|
||||
"when", "while", "with", "without", "xor",
|
||||
"yield",
|
||||
|
||||
@@ -547,55 +547,36 @@ Instead of:
|
||||
Using statement
|
||||
---------------
|
||||
|
||||
**Warning**: The ``using`` statement is highly experimental and has to be
|
||||
**Warning**: The ``using`` statement is experimental and has to be
|
||||
explicitly enabled with the `experimental`:idx: pragma or command line option!
|
||||
|
||||
The using statement provides syntactic convenience for procs that
|
||||
heavily use a single contextual parameter. When applied to a variable or a
|
||||
constant, it will instruct Nim to automatically consider the used symbol as
|
||||
a hidden leading parameter for any procedure calls, following the using
|
||||
statement in the current scope. Thus, it behaves much like the hidden `this`
|
||||
parameter available in some object-oriented programming languages.
|
||||
The using statement provides syntactic convenience in modules where
|
||||
the same parameter names and types are used over and over. Instead of:
|
||||
|
||||
.. code-block:: nim
|
||||
proc foo(c: Context; n: Node) = ...
|
||||
proc bar(c: Context; n: Node, counter: int) = ...
|
||||
proc baz(c: Context; n: Node) = ...
|
||||
|
||||
var s = socket()
|
||||
using s
|
||||
|
||||
connect(host, port)
|
||||
send(data)
|
||||
|
||||
while true:
|
||||
let line = readLine(timeout)
|
||||
...
|
||||
|
||||
|
||||
When applied to a callable symbol, it brings the designated symbol in the
|
||||
current scope. Thus, it can be used to disambiguate between imported symbols
|
||||
from different modules having the same name.
|
||||
One can tell the compiler about the convention that a parameter of
|
||||
name ``c`` should default to type ``Context``, ``n`` should default to
|
||||
``Node`` etc.:
|
||||
|
||||
.. code-block:: nim
|
||||
import windows, sdl
|
||||
using sdl.SetTimer
|
||||
{.experimental.}
|
||||
using
|
||||
c: Context
|
||||
n: Node
|
||||
counter: int
|
||||
|
||||
Note that ``using`` only *adds* to the current context, it doesn't remove or
|
||||
replace, **neither** does it create a new scope. What this means is that if one
|
||||
applies this to multiple variables the compiler will find conflicts in what
|
||||
variable to use:
|
||||
proc foo(c, n) = ...
|
||||
proc bar(c, n, counter) = ...
|
||||
proc baz(c, n) = ...
|
||||
|
||||
.. code-block:: nim
|
||||
var a, b = "kill it"
|
||||
using a
|
||||
add(" with fire")
|
||||
using b
|
||||
add(" with water")
|
||||
echo a
|
||||
echo b
|
||||
|
||||
When the compiler reaches the second ``add`` call, both ``a`` and ``b`` could
|
||||
be used with the proc, so one gets ``Error: expression '(a|b)' has no type (or
|
||||
is ambiguous)``. To solve this one would need to nest ``using`` with a
|
||||
``block`` statement so as to control the reach of the ``using`` statement.
|
||||
The ``using`` section uses the same indentation based grouping syntax as
|
||||
a ``var`` or ``let``` section.
|
||||
|
||||
|
||||
If expression
|
||||
-------------
|
||||
|
||||
@@ -75,8 +75,7 @@ type
|
||||
nnkClosure,
|
||||
nnkGotoState,
|
||||
nnkState,
|
||||
nnkBreakState,
|
||||
nnkSigSection
|
||||
nnkBreakState
|
||||
|
||||
NimNodeKinds* = set[NimNodeKind]
|
||||
NimTypeKind* = enum
|
||||
|
||||
@@ -56,7 +56,7 @@ const
|
||||
"generic", "if", "import", "in", "include",
|
||||
"interface", "is", "isnot", "iterator", "let", "macro", "method",
|
||||
"mixin", "mod", "nil", "not", "notin", "object", "of", "or", "out", "proc",
|
||||
"ptr", "raise", "ref", "return", "shl", "shr", "sig", "static",
|
||||
"ptr", "raise", "ref", "return", "shl", "shr", "static",
|
||||
"template", "try", "tuple", "type", "using", "var", "when", "while", "with",
|
||||
"without", "xor", "yield"]
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ discard """
|
||||
type
|
||||
E = enum A, B, C
|
||||
|
||||
proc foo(x): auto =
|
||||
proc foo(x: int): auto =
|
||||
return case x
|
||||
of 1..9: "digit"
|
||||
else: "number"
|
||||
|
||||
@@ -3,5 +3,5 @@ discard """
|
||||
line: 6
|
||||
"""
|
||||
|
||||
let x = proc (x, y): auto = x + y
|
||||
let x = proc (x, y: auto): auto = x + y
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ proc foo[T](p: TType[T, range[0..2]]) =
|
||||
|
||||
#bug #1366
|
||||
|
||||
proc reversed(x) =
|
||||
proc reversed(x: auto) =
|
||||
for i in countdown(x.low, x.high):
|
||||
echo i
|
||||
|
||||
|
||||
@@ -5,15 +5,15 @@ discard """
|
||||
proc test(x: proc (a, b: int): int) =
|
||||
echo x(5, 5)
|
||||
|
||||
test(proc (a, b): auto = a + b)
|
||||
test(proc (a, b: auto): auto = a + b)
|
||||
|
||||
test do (a, b) -> auto: a + b
|
||||
test do (a, b: auto) -> auto: a + b
|
||||
|
||||
proc foreach[T](s: seq[T], body: proc(x: T)) =
|
||||
for e in s:
|
||||
body(e)
|
||||
|
||||
foreach(@[1,2,3]) do (x):
|
||||
foreach(@[1,2,3]) do (x: auto):
|
||||
echo x
|
||||
|
||||
proc foo =
|
||||
|
||||
@@ -26,7 +26,7 @@ proc noReturn(x: () -> void) =
|
||||
proc doWithOneAndTwo(f: (int, int) -> int): int =
|
||||
f(1,2)
|
||||
|
||||
echo twoParams(proc (a, b): auto = a + b)
|
||||
echo twoParams(proc (a, b: auto): auto = a + b)
|
||||
echo twoParams((x, y) => x + y)
|
||||
|
||||
echo oneParam(x => x+5)
|
||||
|
||||
39
tests/misc/tupcomingfeatures.nim
Normal file
39
tests/misc/tupcomingfeatures.nim
Normal file
@@ -0,0 +1,39 @@
|
||||
discard """
|
||||
output: '''0 -2 0
|
||||
0 -2'''
|
||||
"""
|
||||
|
||||
{.this: self.}
|
||||
|
||||
type
|
||||
Foo {.partial.} = object
|
||||
a, b: int
|
||||
|
||||
type
|
||||
tupcomingfeatures.Foo = object
|
||||
x: int
|
||||
|
||||
proc yay(self: Foo) =
|
||||
echo a, " ", b, " ", x
|
||||
|
||||
proc footest[T](self: var Foo, a: T) =
|
||||
b = 1+a
|
||||
yay()
|
||||
|
||||
proc nongeneric(self: Foo) =
|
||||
echo a, " ", b
|
||||
|
||||
var ff: Foo
|
||||
footest(ff, -3)
|
||||
ff.nongeneric
|
||||
|
||||
{.experimental.}
|
||||
using
|
||||
c: Foo
|
||||
x, y: int
|
||||
|
||||
proc usesSig(c) =
|
||||
echo "yummy"
|
||||
|
||||
proc foobar(c, y) =
|
||||
echo "yay"
|
||||
@@ -5,7 +5,7 @@ template someIt(a, pred: expr): expr =
|
||||
var it {.inject.} = 0
|
||||
pred
|
||||
|
||||
proc aProc(n) =
|
||||
proc aProc(n: auto) =
|
||||
n.someIt(echo(it))
|
||||
|
||||
aProc(89)
|
||||
|
||||
@@ -5,8 +5,8 @@ discard """
|
||||
|
||||
import typetraits
|
||||
|
||||
proc plus(a, b): auto = a + b
|
||||
proc makePair(a, b): auto = (first: a, second: b)
|
||||
proc plus(a, b: auto): auto = a + b
|
||||
proc makePair(a, b: auto): auto = (first: a, second: b)
|
||||
|
||||
proc `+`(a, b: string): seq[string] = @[a, b]
|
||||
|
||||
@@ -19,7 +19,7 @@ static: assert p[0].type is string
|
||||
echo i.type.name
|
||||
echo s.type.name
|
||||
|
||||
proc inst(a): auto =
|
||||
proc inst(a: auto): auto =
|
||||
static: echo "instantiated for ", a.type.name
|
||||
result = a
|
||||
|
||||
|
||||
3
todo.txt
3
todo.txt
@@ -1,6 +1,9 @@
|
||||
|
||||
nim c --gc:v2 -r -d:useSysAssert -d:useGcAssert -d:smokeCycles -d:useRealtimeGc tests/gc/gcbench
|
||||
|
||||
- document ``this`` pragma
|
||||
- document and stress test ``.partial`` object declarations
|
||||
|
||||
essential for 1.0
|
||||
=================
|
||||
|
||||
|
||||
18
web/news.txt
18
web/news.txt
@@ -16,20 +16,34 @@ Changes affecting backwards compatibility
|
||||
``table.mpairs`` iterator only the returned values can be modified, no
|
||||
longer the keys.
|
||||
- The deprecated Nim shebang notation ``#!`` was removed from the language. Use ``#?`` instead.
|
||||
- The ``using`` statement now means something completely different. You can use the
|
||||
new experimental ``this`` pragma to achieve a similar effect to what the old ``using`` statement tried to achieve.
|
||||
- Typeless parameters have been removed from the language since it would
|
||||
clash with ``using``.
|
||||
|
||||
|
||||
Library Additions
|
||||
-----------------
|
||||
|
||||
- The rlocks module has been added providing reentrant lock synchronization
|
||||
primitive
|
||||
primitive.
|
||||
|
||||
Compiler Additions
|
||||
------------------
|
||||
|
||||
- Added a new ``--noCppExceptions`` switch that allows to use default exception
|
||||
handling (no ``throw`` or ``try``/``catch`` generated) when compiling to C++
|
||||
code
|
||||
code.
|
||||
|
||||
Language Additions
|
||||
------------------
|
||||
|
||||
- Nim now supports a ``.this`` pragma for more notational convenience.
|
||||
- Nim now supports a different ``using`` statement for more convenience.
|
||||
- Nim now supports ``partial`` object declarations to mitigate the problems
|
||||
that arise when types are mutually dependent and yet should be kept in
|
||||
different modules.
|
||||
|
||||
|
||||
2016-01-27 Nim in Action is now available!
|
||||
==========================================
|
||||
|
||||
Reference in New Issue
Block a user