breaking change: 'concept' is now a keyword and used instead of 'generic'

This commit is contained in:
Araq 2015-03-23 00:51:04 +01:00
commit f6ff01572e
15 changed files with 462 additions and 475 deletions

View file

@ -35,7 +35,7 @@ type
tkSymbol, # keywords:
tkAddr, tkAnd, tkAs, tkAsm, tkAtomic,
tkBind, tkBlock, tkBreak, tkCase, tkCast,
tkConst, tkContinue, tkConverter,
tkConcept, tkConst, tkContinue, tkConverter,
tkDefer, tkDiscard, tkDistinct, tkDiv, tkDo,
tkElif, tkElse, tkEnd, tkEnum, tkExcept, tkExport,
tkFinally, tkFor, tkFrom, tkFunc,
@ -72,7 +72,7 @@ const
"tkSymbol",
"addr", "and", "as", "asm", "atomic",
"bind", "block", "break", "case", "cast",
"const", "continue", "converter",
"concept", "const", "continue", "converter",
"defer", "discard", "distinct", "div", "do",
"elif", "else", "end", "enum", "except", "export",
"finally", "for", "from", "func", "generic", "if",

View file

@ -1073,8 +1073,10 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
else:
result = newNodeP(nkObjectTy, p)
getTok(p)
of tkGeneric:
of tkGeneric, tkConcept:
if mode == pmTypeDef:
if p.tok.tokType == tkGeneric:
parMessage(p, warnDeprecated, "use 'concept' instead; 'generic'")
result = parseTypeClass(p)
else:
parMessage(p, errInvalidToken, p.tok)
@ -1107,7 +1109,7 @@ proc parseTypeDesc(p: var TParser): PNode =
proc parseTypeDefAux(p: var TParser): PNode =
#| typeDefAux = simpleExpr
#| | 'generic' typeClass
#| | 'concept' typeClass
result = simpleExpr(p, pmTypeDef)
proc makeCall(n: PNode): PNode =

View file

@ -725,7 +725,7 @@ proc gproc(g: var TSrcGen, n: PNode) =
proc gTypeClassTy(g: var TSrcGen, n: PNode) =
var c: TContext
initContext(c)
putWithSpace(g, tkGeneric, "generic")
putWithSpace(g, tkConcept, "concept")
gsons(g, n[0], c) # arglist
gsub(g, n[1]) # pragmas
gsub(g, n[2]) # of

View file

@ -23,7 +23,7 @@ type
wInvalid,
wAddr, wAnd, wAs, wAsm, wAtomic,
wBind, wBlock, wBreak, wCase, wCast, wConst,
wBind, wBlock, wBreak, wCase, wCast, wConcept, wConst,
wContinue, wConverter, wDefer, wDiscard, wDistinct, wDiv, wDo,
wElif, wElse, wEnd, wEnum, wExcept, wExport,
wFinally, wFor, wFrom, wFunc, wGeneric, wIf, wImport, wIn,
@ -103,7 +103,7 @@ const
"addr", "and", "as", "asm", "atomic",
"bind", "block", "break", "case", "cast",
"const", "continue", "converter",
"concept", "const", "continue", "converter",
"defer", "discard", "distinct", "div", "do",
"elif", "else", "end", "enum", "except", "export",
"finally", "for", "from", "func", "generic", "if",

View file

@ -52,11 +52,11 @@ identOrLiteral = generalizedLit | symbol | literal
tupleConstr = '(' optInd (exprColonEqExpr comma?)* optPar ')'
arrayConstr = '[' optInd (exprColonEqExpr comma?)* optPar ']'
primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
| doBlocks
| '.' optInd symbol generalizedLit?
| '[' optInd indexExprList optPar ']'
| '{' optInd indexExprList optPar '}'
| &( '`'|IDENT|literal|'cast') expr # command syntax
| doBlocks
| '.' optInd symbol generalizedLit?
| '[' optInd indexExprList optPar ']'
| '{' optInd indexExprList optPar '}'
| &( '`'|IDENT|literal|'cast'|'addr'|'type') expr # command syntax
condExpr = expr colcom expr optInd
('elif' expr colcom expr optInd)*
'else' colcom expr
@ -94,7 +94,7 @@ primary = typeKeyw typeDescK
/ 'bind' primary
typeDesc = simpleExpr
typeDefAux = simpleExpr
| 'generic' typeClass
| 'concept' typeClass
macroColon = ':' stmt? ( IND{=} 'of' exprList ':' stmt
| IND{=} 'elif' expr ':' stmt
| IND{=} 'except' exprList ':' stmt

View file

@ -1,6 +1,6 @@
addr and as asm atomic
bind block break
case cast const continue converter
case cast concept const continue converter
defer discard distinct div do
elif else end enum except export
finally for from func

View file

@ -203,34 +203,34 @@ be inferred to have the equivalent of the `any` type class and thus they will
match anything without discrimination.
User defined type classes
-------------------------
Concepts
--------
**Note**: User defined type classes are still in development.
**Note**: Concepts are still in development.
The user-defined type classes are available in two flavours - declarative and
imperative. Both are used to specify an arbitrary set of requirements that the
matched type must satisfy.
Concepts, also known as "user-defined type classes", are available in two
flavours - declarative and imperative. Both are used to specify an arbitrary
set of requirements that the matched type must satisfy.
Declarative type classes are written in the following form:
.. code-block:: nim
type
Comparable = generic x, y
Comparable = concept x, y
(x < y) is bool
Container[T] = generic c
Container[T] = concept c
c.len is ordinal
items(c) is iterator
for value in c:
type(value) is T
The type class will be matched if:
The concept will be matched if:
a) all of the expressions within the body can be compiled for the tested type
b) all statically evaluatable boolean expressions in the body must be true
The identifiers following the `generic` keyword represent instances of the
The identifiers following the ``concept`` keyword represent instances of the
currently matched type. These instances can act both as variables of the type,
when used in contexts where a value is expected, and as the type itself when
used in contexts where a type is expected.
@ -240,18 +240,18 @@ type signatures of the required operations, but since type inference and
default parameters are still applied in the provided block, it's also possible
to encode usage protocols that do not reveal implementation details.
As a special rule providing further convenience when writing type classes, any
As a special rule providing further convenience when writing concepts, any
type value appearing in a callable expression will be treated as a variable of
the designated type for overload resolution purposes, unless the type value was
passed in its explicit ``typedesc[T]`` form:
.. code-block:: nim
type
OutputStream = generic S
OutputStream = concept S
write(var S, string)
Much like generics, the user defined type classes will be instantiated exactly
once for each tested type and any static code included within them will also be
Much like generics, concepts are instantiated exactly
once for each tested type and any static code included within them is also
executed once.

View file

@ -6,7 +6,7 @@ static[T]
**Note**: static[T] is still in development.
As their name suggests, static params must be known at compile-time:
As their name suggests, static parameters must be known at compile-time:
.. code-block:: nim
@ -25,22 +25,6 @@ For the purposes of code generation, all static params are treated as
generic params - the proc will be compiled separately for each unique
supplied value (or combination of values).
Furthermore, the system module defines a `semistatic[T]` type that can be
used to declare procs accepting both static and run-time values, which can
optimize their body according to the supplied param using the `isStatic(p)`
predicate:
.. code-block:: nim
# The following proc will be compiled once for each unique static
# value and also once for the case handling all run-time values:
proc re(pattern: semistatic[string]): RegEx =
when isStatic(pattern):
result = precompiledRegex(pattern)
else:
result = compile(pattern)
Static params can also appear in the signatures of generic types:
.. code-block:: nim

View file

@ -47,7 +47,7 @@ const
# The following list comes from doc/keywords.txt, make sure it is
# synchronized with this array by running the module itself as a test case.
nimKeywords = ["addr", "and", "as", "asm", "atomic", "bind", "block",
"break", "case", "cast", "const", "continue", "converter",
"break", "case", "cast", "concept", "const", "continue", "converter",
"defer", "discard", "distinct", "div", "do",
"elif", "else", "end", "enum", "except", "export",
"finally", "for", "from", "func",
@ -554,10 +554,12 @@ when isMainModule:
var keywords: seq[string]
# Try to work running in both the subdir or at the root.
for filename in ["doc/keywords.txt", "../../../doc/keywords.txt"]:
except: echo filename, " not found"
let input = string(readFile(filename))
keywords = input.split()
break
try:
let input = string(readFile(filename))
keywords = input.split()
break
except:
echo filename, " not found"
doAssert(not keywords.isNil, "Couldn't read any keywords.txt file!")
doAssert keywords.len == nimKeywords.len, "No matching lengths"
for i in 0..keywords.len-1:

View file

@ -22,7 +22,7 @@ template reject(e: expr) =
static: assert(not compiles(e))
type
Container[T] = generic C
Container[T] = concept C
C.len is Ordinal
items(c) is iterator
for value in C:

View file

@ -40,7 +40,7 @@ proc isSwizzle(s: string): bool {.compileTime.} =
return false
type
StringIsSwizzle = generic value
StringIsSwizzle = concept value
value.isSwizzle
SwizzleStr = static[string] and StringIsSwizzle

View file

@ -16,10 +16,10 @@ type
TObj = object
x: int
Sortable = generic x, y
Sortable = concept x, y
(x < y) is bool
ObjectContainer = generic C
ObjectContainer = concept C
C.len is Ordinal
for v in items(C):
v.type is tuple|object
@ -38,7 +38,7 @@ proc intval(x: int): int = 10
# check real and virtual fields
type
TFoo = generic T
TFoo = concept T
T.x
y(T)
intval T.y
@ -50,7 +50,7 @@ proc testFoo(x: TFoo) = discard
testFoo(TObj(x: 10))
type
Matrix[Rows, Cols: static[int]; T] = generic M
Matrix[Rows, Cols: static[int]; T] = concept M
M.M == Rows
M.N == Cols
M.T is T

View file

@ -1,5 +1,5 @@
type
hasFieldX = generic z
hasFieldX = concept z
z.x is int
obj_x = object

View file

@ -5,6 +5,7 @@ version 0.10.4
- improve GC-unsafety warnings
- make 'nil' work for 'add' and 'len'
- add "all threads are blocked" detection to 'spawn'
- overloading of '='
version 1.0
@ -17,8 +18,6 @@ version 1.0
- The bitwise 'not' operator will be renamed to 'bnot' to
prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs!
- iterators always require a return type
- overloading of '='
- make nimble part of the distribution
- split docgen into separate tool
- special rule for ``[]=``, items, pairs

View file

@ -41,7 +41,7 @@ News
and not as ``type((x).name)``. Note that this also affects the AST
structure; for immediate macro parameters ``nkCall('addr', 'x')`` is
produced instead of ``nkAddr('x')``.
- ``concept`` is now a keyword and is used instead of ``generic``.
Language Additions