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
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) nkGotoState, # used for the state machine (for iterators)
nkState, # give a label to a code section (for iterators) nkState, # give a label to a code section (for iterators)
nkBreakState, # special break statement for easier code generation nkBreakState, # special break statement for easier code generation
nkSigSection
TNodeKinds* = set[TNodeKind] TNodeKinds* = set[TNodeKind]
type type

View file

@ -45,7 +45,7 @@ type
tkMacro, tkMethod, tkMixin, tkMod, tkNil, tkNot, tkNotin, tkMacro, tkMethod, tkMixin, tkMod, tkNil, tkNot, tkNotin,
tkObject, tkOf, tkOr, tkOut, tkObject, tkOf, tkOr, tkOut,
tkProc, tkPtr, tkRaise, tkRef, tkReturn, tkProc, tkPtr, tkRaise, tkRef, tkReturn,
tkShl, tkShr, tkSig, tkStatic, tkShl, tkShr, tkStatic,
tkTemplate, tkTemplate,
tkTry, tkTuple, tkType, tkUsing, tkTry, tkTuple, tkType, tkUsing,
tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor, tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor,
@ -82,7 +82,7 @@ const
"macro", "method", "mixin", "mod", "macro", "method", "mixin", "mod",
"nil", "not", "notin", "object", "of", "or", "nil", "not", "notin", "object", "of", "or",
"out", "proc", "ptr", "raise", "ref", "return", "out", "proc", "ptr", "raise", "ref", "return",
"shl", "shr", "sig", "static", "shl", "shr", "static",
"template", "template",
"try", "tuple", "type", "using", "try", "tuple", "type", "using",
"var", "when", "while", "with", "without", "xor", "var", "when", "while", "with", "without", "xor",

View file

@ -1908,7 +1908,7 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
#| | 'converter' routine #| | 'converter' routine
#| | 'type' section(typeDef) #| | 'type' section(typeDef)
#| | 'const' section(constant) #| | 'const' section(constant)
#| | ('let' | 'var') section(variable) #| | ('let' | 'var' | 'using') section(variable)
#| | bindStmt | mixinStmt) #| | bindStmt | mixinStmt)
#| / simpleStmt #| / simpleStmt
case p.tok.tokType case p.tok.tokType
@ -1943,10 +1943,9 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
of tkLet: result = parseSection(p, nkLetSection, parseVariable) of tkLet: result = parseSection(p, nkLetSection, parseVariable)
of tkWhen: result = parseIfOrWhen(p, nkWhenStmt) of tkWhen: result = parseIfOrWhen(p, nkWhenStmt)
of tkVar: result = parseSection(p, nkVarSection, parseVariable) of tkVar: result = parseSection(p, nkVarSection, parseVariable)
of tkSig: result = parseSection(p, nkSigSection, parseVariable)
of tkBind: result = parseBind(p, nkBindStmt) of tkBind: result = parseBind(p, nkBindStmt)
of tkMixin: result = parseBind(p, nkMixinStmt) of tkMixin: result = parseBind(p, nkMixinStmt)
of tkUsing: result = parseBind(p, nkUsingStmt) of tkUsing: result = parseSection(p, nkUsingStmt, parseVariable)
else: result = simpleStmt(p) else: result = simpleStmt(p)
proc parseStmt(p: var TParser): PNode = proc parseStmt(p: var TParser): PNode =

View file

@ -460,9 +460,12 @@ proc lsub(n: PNode): int =
else: else:
result = len("enum") result = len("enum")
of nkEnumFieldDef: result = lsons(n) + 3 of nkEnumFieldDef: result = lsons(n) + 3
of nkVarSection, nkLetSection, nkSigSection: of nkVarSection, nkLetSection:
if sonsLen(n) > 1: result = MaxLineLen + 1 if sonsLen(n) > 1: result = MaxLineLen + 1
else: result = lsons(n) + len("var_") 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 nkReturnStmt: result = lsub(n.sons[0]) + len("return_")
of nkRaiseStmt: result = lsub(n.sons[0]) + len("raise_") of nkRaiseStmt: result = lsub(n.sons[0]) + len("raise_")
of nkYieldStmt: result = lsub(n.sons[0]) + len("yield_") of nkYieldStmt: result = lsub(n.sons[0]) + len("yield_")
@ -1173,12 +1176,12 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
initContext(a) initContext(a)
incl(a.flags, rfInConstExpr) incl(a.flags, rfInConstExpr)
gsection(g, n, a, tkConst, "const") gsection(g, n, a, tkConst, "const")
of nkVarSection, nkLetSection, nkSigSection: of nkVarSection, nkLetSection, nkUsingStmt:
var L = sonsLen(n) var L = sonsLen(n)
if L == 0: return if L == 0: return
if n.kind == nkVarSection: putWithSpace(g, tkVar, "var") if n.kind == nkVarSection: putWithSpace(g, tkVar, "var")
elif n.kind == nkLetSection: putWithSpace(g, tkLet, "let") elif n.kind == nkLetSection: putWithSpace(g, tkLet, "let")
else: putWithSpace(g, tkSig, "sig") else: putWithSpace(g, tkUsing, "using")
if L > 1: if L > 1:
gcoms(g) gcoms(g)
indentNL(g) indentNL(g)

View file

@ -1556,10 +1556,6 @@ proc newAnonSym(kind: TSymKind, info: TLineInfo,
result = newSym(kind, idAnon, owner, info) result = newSym(kind, idAnon, owner, info)
result.flags = {sfGenSym} 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 = proc semExpandToAst(c: PContext, n: PNode): PNode =
var macroCall = n[1] var macroCall = n[1]
var expandedSym = expectMacroOrTemplateCall(c, macroCall) 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]): 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' takes a 'void' expression")
#localError(n.info, errGenerated, "'defer' not allowed in this context") #localError(n.info, errGenerated, "'defer' not allowed in this context")
of nkSigSection: result = semSigSection(c, n)
else: else:
localError(n.info, errInvalidExpressionX, localError(n.info, errInvalidExpressionX,
renderTree(n, {renderNoComments})) renderTree(n, {renderNoComments}))

View file

@ -386,8 +386,11 @@ proc isDiscardUnderscore(v: PSym): bool =
v.flags.incl(sfGenSym) v.flags.incl(sfGenSym)
result = true result = true
proc semSigSection(c: PContext; n: PNode): PNode = proc semUsing(c: PContext; n: PNode): PNode =
result = ast.emptyNode 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): for i in countup(0, sonsLen(n)-1):
var a = n.sons[i] var a = n.sons[i]
if gCmd == cmdIdeTools: suggestStmt(c, a) if gCmd == cmdIdeTools: suggestStmt(c, a)
@ -402,10 +405,10 @@ proc semSigSection(c: PContext; n: PNode): PNode =
v.typ = typ v.typ = typ
strTableIncl(c.signatures, v) strTableIncl(c.signatures, v)
else: else:
localError(a.info, "'sig' section must have a type") localError(a.info, "'using' section must have a type")
var def: PNode var def: PNode
if a.sons[length-1].kind != nkEmpty: 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 = proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
var b: PNode var b: PNode

View file

@ -30,7 +30,7 @@ type
wInclude, wInterface, wIs, wIsnot, wIterator, wLet, wInclude, wInterface, wIs, wIsnot, wIterator, wLet,
wMacro, wMethod, wMixin, wMod, wNil, wMacro, wMethod, wMixin, wMod, wNil,
wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn, 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, wWhen, wWhile, wWith, wWithout, wXor, wYield,
wColon, wColonColon, wEquals, wDot, wDotDot, wColon, wColonColon, wEquals, wDot, wDotDot,
@ -114,7 +114,7 @@ const
"macro", "method", "mixin", "mod", "nil", "not", "notin", "macro", "method", "mixin", "mod", "nil", "not", "notin",
"object", "of", "or", "object", "of", "or",
"out", "proc", "ptr", "raise", "ref", "return", "out", "proc", "ptr", "raise", "ref", "return",
"shl", "shr", "sig", "static", "shl", "shr", "static",
"template", "try", "tuple", "type", "using", "var", "template", "try", "tuple", "type", "using", "var",
"when", "while", "with", "without", "xor", "when", "while", "with", "without", "xor",
"yield", "yield",

View file

@ -547,55 +547,36 @@ Instead of:
Using statement 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! explicitly enabled with the `experimental`:idx: pragma or command line option!
The using statement provides syntactic convenience for procs that The using statement provides syntactic convenience in modules where
heavily use a single contextual parameter. When applied to a variable or a the same parameter names and types are used over and over. Instead of:
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.
.. code-block:: nim .. 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() One can tell the compiler about the convention that a parameter of
using s name ``c`` should default to type ``Context``, ``n`` should default to
``Node`` etc.:
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.
.. code-block:: nim .. code-block:: nim
import windows, sdl {.experimental.}
using sdl.SetTimer using
c: Context
n: Node
counter: int
Note that ``using`` only *adds* to the current context, it doesn't remove or proc foo(c, n) = ...
replace, **neither** does it create a new scope. What this means is that if one proc bar(c, n, counter) = ...
applies this to multiple variables the compiler will find conflicts in what proc baz(c, n) = ...
variable to use:
.. 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 The ``using`` section uses the same indentation based grouping syntax as
be used with the proc, so one gets ``Error: expression '(a|b)' has no type (or a ``var`` or ``let``` section.
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.
If expression If expression
------------- -------------

View file

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

View file

@ -56,7 +56,7 @@ const
"generic", "if", "import", "in", "include", "generic", "if", "import", "in", "include",
"interface", "is", "isnot", "iterator", "let", "macro", "method", "interface", "is", "isnot", "iterator", "let", "macro", "method",
"mixin", "mod", "nil", "not", "notin", "object", "of", "or", "out", "proc", "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", "template", "try", "tuple", "type", "using", "var", "when", "while", "with",
"without", "xor", "yield"] "without", "xor", "yield"]

View file

@ -11,7 +11,7 @@ discard """
type type
E = enum A, B, C E = enum A, B, C
proc foo(x): auto = proc foo(x: int): auto =
return case x return case x
of 1..9: "digit" of 1..9: "digit"
else: "number" else: "number"

View file

@ -3,5 +3,5 @@ discard """
line: 6 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 #bug #1366
proc reversed(x) = proc reversed(x: auto) =
for i in countdown(x.low, x.high): for i in countdown(x.low, x.high):
echo i echo i

View file

@ -5,15 +5,15 @@ discard """
proc test(x: proc (a, b: int): int) = proc test(x: proc (a, b: int): int) =
echo x(5, 5) 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)) = proc foreach[T](s: seq[T], body: proc(x: T)) =
for e in s: for e in s:
body(e) body(e)
foreach(@[1,2,3]) do (x): foreach(@[1,2,3]) do (x: auto):
echo x echo x
proc foo = proc foo =

View file

@ -26,7 +26,7 @@ proc noReturn(x: () -> void) =
proc doWithOneAndTwo(f: (int, int) -> int): int = proc doWithOneAndTwo(f: (int, int) -> int): int =
f(1,2) 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 twoParams((x, y) => x + y)
echo oneParam(x => x+5) 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 var it {.inject.} = 0
pred pred
proc aProc(n) = proc aProc(n: auto) =
n.someIt(echo(it)) n.someIt(echo(it))
aProc(89) aProc(89)

View file

@ -5,8 +5,8 @@ discard """
import typetraits import typetraits
proc plus(a, b): auto = a + b proc plus(a, b: auto): auto = a + b
proc makePair(a, b): auto = (first: a, second: b) proc makePair(a, b: auto): auto = (first: a, second: b)
proc `+`(a, b: string): seq[string] = @[a, 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 i.type.name
echo s.type.name echo s.type.name
proc inst(a): auto = proc inst(a: auto): auto =
static: echo "instantiated for ", a.type.name static: echo "instantiated for ", a.type.name
result = a result = a

View file

@ -1,6 +1,9 @@
nim c --gc:v2 -r -d:useSysAssert -d:useGcAssert -d:smokeCycles -d:useRealtimeGc tests/gc/gcbench 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 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 ``table.mpairs`` iterator only the returned values can be modified, no
longer the keys. longer the keys.
- The deprecated Nim shebang notation ``#!`` was removed from the language. Use ``#?`` instead. - 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 Library Additions
----------------- -----------------
- The rlocks module has been added providing reentrant lock synchronization - The rlocks module has been added providing reentrant lock synchronization
primitive primitive.
Compiler Additions Compiler Additions
------------------ ------------------
- Added a new ``--noCppExceptions`` switch that allows to use default exception - Added a new ``--noCppExceptions`` switch that allows to use default exception
handling (no ``throw`` or ``try``/``catch`` generated) when compiling to C++ 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! 2016-01-27 Nim in Action is now available!
========================================== ==========================================