use 'using' instead of 'sig' keyword; cleans up new features a bit

This commit is contained in:
Andreas Rumpf
2016-02-29 12:19:54 +01:00
parent 554a3e9335
commit c9966a3e17
20 changed files with 109 additions and 74 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -75,8 +75,7 @@ type
nnkClosure,
nnkGotoState,
nnkState,
nnkBreakState,
nnkSigSection
nnkBreakState
NimNodeKinds* = set[NimNodeKind]
NimTypeKind* = enum

View File

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

View File

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

View File

@@ -3,5 +3,5 @@ discard """
line: 6
"""
let x = proc (x, y): auto = x + y
let x = proc (x, y: auto): auto = x + y

View File

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

View File

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

View File

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

View 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"

View File

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

View File

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

View File

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

View File

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