Allow full commands and blocks in type sections (#19181)
* allow full commands and blocks in type sections * update grammar * fix changelog [skip ci] * more tests * even more tests
This commit is contained in:
parent
ef634cc251
commit
61d682e733
8 changed files with 393 additions and 11 deletions
|
|
@ -61,6 +61,9 @@
|
||||||
```
|
```
|
||||||
- [Case statement macros](manual.html#macros-case-statement-macros) are no longer experimental,
|
- [Case statement macros](manual.html#macros-case-statement-macros) are no longer experimental,
|
||||||
meaning you no longer need to enable the experimental switch `caseStmtMacros` to use them.
|
meaning you no longer need to enable the experimental switch `caseStmtMacros` to use them.
|
||||||
|
- Full command syntax and block arguments i.e. `foo a, b: c` are now allowed
|
||||||
|
for the right-hand side of type definitions in type sections. Previously
|
||||||
|
they would error with "invalid indentation".
|
||||||
|
|
||||||
## Compiler changes
|
## Compiler changes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -811,7 +811,7 @@ proc primarySuffix(p: var Parser, r: PNode,
|
||||||
#| | DOTLIKEOP optInd symbol generalizedLit?
|
#| | DOTLIKEOP optInd symbol generalizedLit?
|
||||||
#| | '[' optInd exprColonEqExprList optPar ']'
|
#| | '[' optInd exprColonEqExprList optPar ']'
|
||||||
#| | '{' optInd exprColonEqExprList optPar '}'
|
#| | '{' optInd exprColonEqExprList optPar '}'
|
||||||
#| | &( '`'|IDENT|literal|'cast'|'addr'|'type') expr # command syntax
|
#| | &( '`'|IDENT|literal|'cast'|'addr'|'type') expr (comma expr)* # command syntax
|
||||||
result = r
|
result = r
|
||||||
|
|
||||||
# progress guaranteed
|
# progress guaranteed
|
||||||
|
|
@ -821,14 +821,14 @@ proc primarySuffix(p: var Parser, r: PNode,
|
||||||
of tkParLe:
|
of tkParLe:
|
||||||
# progress guaranteed
|
# progress guaranteed
|
||||||
if p.tok.strongSpaceA > 0:
|
if p.tok.strongSpaceA > 0:
|
||||||
# inside type sections, expressions such as `ref (int, bar)`
|
result = commandExpr(p, result, mode)
|
||||||
# are parsed as a nkCommand with a single tuple argument (nkPar)
|
# type sections allow full command syntax
|
||||||
if mode == pmTypeDef:
|
if mode == pmTypeDef:
|
||||||
result = newNodeP(nkCommand, p)
|
var isFirstParam = false
|
||||||
result.add r
|
while p.tok.tokType == tkComma:
|
||||||
result.add primary(p, pmNormal)
|
getTok(p)
|
||||||
else:
|
optInd(p, result)
|
||||||
result = commandExpr(p, result, mode)
|
result.add(commandParam(p, isFirstParam, mode))
|
||||||
break
|
break
|
||||||
result = namedParams(p, result, nkCall, tkParRi)
|
result = namedParams(p, result, nkCall, tkParRi)
|
||||||
if result.len > 1 and result[1].kind == nkExprColonExpr:
|
if result.len > 1 and result[1].kind == nkExprColonExpr:
|
||||||
|
|
@ -869,9 +869,18 @@ proc primarySuffix(p: var Parser, r: PNode,
|
||||||
# actually parsing {.push hints:off.} as {.push(hints:off).} is a sweet
|
# actually parsing {.push hints:off.} as {.push(hints:off).} is a sweet
|
||||||
# solution, but pragmas.nim can't handle that
|
# solution, but pragmas.nim can't handle that
|
||||||
result = commandExpr(p, result, mode)
|
result = commandExpr(p, result, mode)
|
||||||
|
if mode == pmTypeDef:
|
||||||
|
var isFirstParam = false
|
||||||
|
while p.tok.tokType == tkComma:
|
||||||
|
getTok(p)
|
||||||
|
optInd(p, result)
|
||||||
|
result.add(commandParam(p, isFirstParam, mode))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
# type sections allow post-expr blocks
|
||||||
|
if mode == pmTypeDef:
|
||||||
|
result = postExprBlocks(p, result)
|
||||||
|
|
||||||
proc parseOperators(p: var Parser, headNode: PNode,
|
proc parseOperators(p: var Parser, headNode: PNode,
|
||||||
limit: int, mode: PrimaryMode): PNode =
|
limit: int, mode: PrimaryMode): PNode =
|
||||||
|
|
@ -1342,7 +1351,8 @@ proc parseTypeDesc(p: var Parser): PNode =
|
||||||
result = binaryNot(p, result)
|
result = binaryNot(p, result)
|
||||||
|
|
||||||
proc parseTypeDefAux(p: var Parser): PNode =
|
proc parseTypeDefAux(p: var Parser): PNode =
|
||||||
#| typeDefAux = simpleExpr ('not' expr)?
|
#| typeDefAux = simpleExpr ('not' expr
|
||||||
|
#| | postExprBlocks)?
|
||||||
result = simpleExpr(p, pmTypeDef)
|
result = simpleExpr(p, pmTypeDef)
|
||||||
result = binaryNot(p, result)
|
result = binaryNot(p, result)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ primarySuffix = '(' (exprColonEqExpr comma?)* ')'
|
||||||
| DOTLIKEOP optInd symbol generalizedLit?
|
| DOTLIKEOP optInd symbol generalizedLit?
|
||||||
| '[' optInd exprColonEqExprList optPar ']'
|
| '[' optInd exprColonEqExprList optPar ']'
|
||||||
| '{' optInd exprColonEqExprList optPar '}'
|
| '{' optInd exprColonEqExprList optPar '}'
|
||||||
| &( '`'|IDENT|literal|'cast'|'addr'|'type') expr # command syntax
|
| &( '`'|IDENT|literal|'cast'|'addr'|'type') expr (comma expr)* # command syntax
|
||||||
pragma = '{.' optInd (exprColonEqExpr comma?)* optPar ('.}' | '}')
|
pragma = '{.' optInd (exprColonEqExpr comma?)* optPar ('.}' | '}')
|
||||||
identVis = symbol OPR? # postfix position
|
identVis = symbol OPR? # postfix position
|
||||||
identVisDot = symbol '.' optInd symbol OPR?
|
identVisDot = symbol '.' optInd symbol OPR?
|
||||||
|
|
@ -93,7 +93,8 @@ primary = operatorB primary primarySuffix* |
|
||||||
('var' | 'out' | 'ref' | 'ptr' | 'distinct') primary
|
('var' | 'out' | 'ref' | 'ptr' | 'distinct') primary
|
||||||
/ prefixOperator* identOrLiteral primarySuffix*
|
/ prefixOperator* identOrLiteral primarySuffix*
|
||||||
typeDesc = simpleExpr ('not' expr)?
|
typeDesc = simpleExpr ('not' expr)?
|
||||||
typeDefAux = simpleExpr ('not' expr)?
|
typeDefAux = simpleExpr ('not' expr
|
||||||
|
| postExprBlocks)?
|
||||||
postExprBlocks = ':' stmt? ( IND{=} doBlock
|
postExprBlocks = ':' stmt? ( IND{=} doBlock
|
||||||
| IND{=} 'of' exprList ':' stmt
|
| IND{=} 'of' exprList ':' stmt
|
||||||
| IND{=} 'elif' expr ':' stmt
|
| IND{=} 'elif' expr ':' stmt
|
||||||
|
|
|
||||||
9
tests/parser/ttypecommandcomma.nim
Normal file
9
tests/parser/ttypecommandcomma.nim
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "invalid indentation"
|
||||||
|
line: 8
|
||||||
|
column: 19
|
||||||
|
"""
|
||||||
|
|
||||||
|
type
|
||||||
|
Foo = call(1, 2), 3:
|
||||||
|
4
|
||||||
9
tests/parser/ttypecommandindent1.nim
Normal file
9
tests/parser/ttypecommandindent1.nim
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "invalid indentation"
|
||||||
|
line: 9
|
||||||
|
column: 3
|
||||||
|
"""
|
||||||
|
|
||||||
|
type
|
||||||
|
Foo = call x, y, z:
|
||||||
|
abc
|
||||||
11
tests/parser/ttypecommandindent2.nim
Normal file
11
tests/parser/ttypecommandindent2.nim
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "invalid indentation"
|
||||||
|
line: 10
|
||||||
|
column: 5
|
||||||
|
"""
|
||||||
|
|
||||||
|
type
|
||||||
|
Foo = call x, y, z:
|
||||||
|
abc
|
||||||
|
do:
|
||||||
|
def
|
||||||
11
tests/parser/ttypecommandindent3.nim
Normal file
11
tests/parser/ttypecommandindent3.nim
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "expression expected, but found 'keyword do'"
|
||||||
|
line: 10
|
||||||
|
column: 1
|
||||||
|
"""
|
||||||
|
|
||||||
|
type
|
||||||
|
Foo = call x, y, z:
|
||||||
|
abc
|
||||||
|
do:
|
||||||
|
def
|
||||||
328
tests/parser/ttypesectioncalls.nim
Normal file
328
tests/parser/ttypesectioncalls.nim
Normal file
|
|
@ -0,0 +1,328 @@
|
||||||
|
discard """
|
||||||
|
nimout: '''
|
||||||
|
StmtList
|
||||||
|
TypeSection
|
||||||
|
TypeDef
|
||||||
|
Ident "A"
|
||||||
|
Empty
|
||||||
|
Call
|
||||||
|
Ident "call"
|
||||||
|
IntLit 1
|
||||||
|
TypeSection
|
||||||
|
TypeDef
|
||||||
|
Ident "B"
|
||||||
|
Empty
|
||||||
|
Command
|
||||||
|
Ident "call"
|
||||||
|
IntLit 2
|
||||||
|
TypeDef
|
||||||
|
Ident "C"
|
||||||
|
Empty
|
||||||
|
Call
|
||||||
|
Ident "call"
|
||||||
|
StmtList
|
||||||
|
IntLit 3
|
||||||
|
TypeDef
|
||||||
|
Ident "D"
|
||||||
|
Empty
|
||||||
|
Call
|
||||||
|
Ident "call"
|
||||||
|
StmtList
|
||||||
|
IntLit 4
|
||||||
|
TypeSection
|
||||||
|
TypeDef
|
||||||
|
Ident "E"
|
||||||
|
Empty
|
||||||
|
Call
|
||||||
|
Ident "call"
|
||||||
|
IntLit 5
|
||||||
|
IntLit 6
|
||||||
|
TypeDef
|
||||||
|
Ident "F"
|
||||||
|
Empty
|
||||||
|
Command
|
||||||
|
Ident "call"
|
||||||
|
IntLit 7
|
||||||
|
IntLit 8
|
||||||
|
TypeDef
|
||||||
|
Ident "G"
|
||||||
|
Empty
|
||||||
|
Call
|
||||||
|
Ident "call"
|
||||||
|
IntLit 9
|
||||||
|
StmtList
|
||||||
|
IntLit 10
|
||||||
|
TypeDef
|
||||||
|
Ident "H"
|
||||||
|
Empty
|
||||||
|
Call
|
||||||
|
Ident "call"
|
||||||
|
IntLit 11
|
||||||
|
StmtList
|
||||||
|
IntLit 12
|
||||||
|
TypeDef
|
||||||
|
Ident "I"
|
||||||
|
Empty
|
||||||
|
Command
|
||||||
|
Ident "call"
|
||||||
|
IntLit 13
|
||||||
|
StmtList
|
||||||
|
IntLit 14
|
||||||
|
TypeDef
|
||||||
|
Ident "J"
|
||||||
|
Empty
|
||||||
|
Command
|
||||||
|
Ident "call"
|
||||||
|
IntLit 15
|
||||||
|
StmtList
|
||||||
|
IntLit 16
|
||||||
|
TypeSection
|
||||||
|
TypeDef
|
||||||
|
Ident "K"
|
||||||
|
Empty
|
||||||
|
Call
|
||||||
|
Ident "call"
|
||||||
|
IntLit 17
|
||||||
|
IntLit 18
|
||||||
|
IntLit 19
|
||||||
|
TypeDef
|
||||||
|
Ident "L"
|
||||||
|
Empty
|
||||||
|
Command
|
||||||
|
Ident "call"
|
||||||
|
IntLit 20
|
||||||
|
IntLit 21
|
||||||
|
IntLit 22
|
||||||
|
TypeDef
|
||||||
|
Ident "M"
|
||||||
|
Empty
|
||||||
|
Call
|
||||||
|
Ident "call"
|
||||||
|
IntLit 23
|
||||||
|
IntLit 24
|
||||||
|
StmtList
|
||||||
|
IntLit 25
|
||||||
|
TypeDef
|
||||||
|
Ident "N"
|
||||||
|
Empty
|
||||||
|
Command
|
||||||
|
Ident "call"
|
||||||
|
IntLit 26
|
||||||
|
IntLit 27
|
||||||
|
StmtList
|
||||||
|
IntLit 28
|
||||||
|
TypeDef
|
||||||
|
Ident "O"
|
||||||
|
Empty
|
||||||
|
Command
|
||||||
|
Ident "call"
|
||||||
|
IntLit 29
|
||||||
|
IntLit 30
|
||||||
|
StmtList
|
||||||
|
IntLit 31
|
||||||
|
TypeSection
|
||||||
|
TypeDef
|
||||||
|
Ident "P"
|
||||||
|
Empty
|
||||||
|
Command
|
||||||
|
Ident "call"
|
||||||
|
TupleConstr
|
||||||
|
IntLit 32
|
||||||
|
IntLit 33
|
||||||
|
Infix
|
||||||
|
Ident "+"
|
||||||
|
Infix
|
||||||
|
Ident "*"
|
||||||
|
IntLit 34
|
||||||
|
IntLit 35
|
||||||
|
IntLit 36
|
||||||
|
StmtList
|
||||||
|
IntLit 37
|
||||||
|
TypeDef
|
||||||
|
Ident "R"
|
||||||
|
Empty
|
||||||
|
Command
|
||||||
|
Ident "call"
|
||||||
|
Infix
|
||||||
|
Ident "@"
|
||||||
|
TupleConstr
|
||||||
|
IntLit 38
|
||||||
|
IntLit 39
|
||||||
|
Infix
|
||||||
|
Ident "shl"
|
||||||
|
IntLit 40
|
||||||
|
IntLit 41
|
||||||
|
Infix
|
||||||
|
Ident "-"
|
||||||
|
Infix
|
||||||
|
Ident "*"
|
||||||
|
IntLit 42
|
||||||
|
IntLit 43
|
||||||
|
IntLit 44
|
||||||
|
StmtList
|
||||||
|
IntLit 45
|
||||||
|
TypeDef
|
||||||
|
Ident "S"
|
||||||
|
Empty
|
||||||
|
Command
|
||||||
|
Ident "call"
|
||||||
|
IntLit 46
|
||||||
|
StmtList
|
||||||
|
IntLit 47
|
||||||
|
StmtList
|
||||||
|
IntLit 48
|
||||||
|
TypeDef
|
||||||
|
Ident "T"
|
||||||
|
Empty
|
||||||
|
Call
|
||||||
|
Ident "call"
|
||||||
|
StmtList
|
||||||
|
IntLit 49
|
||||||
|
StmtList
|
||||||
|
IntLit 50
|
||||||
|
StmtList
|
||||||
|
IntLit 51
|
||||||
|
a: IntLit 1
|
||||||
|
a: IntLit 2
|
||||||
|
a: StmtList
|
||||||
|
IntLit 3
|
||||||
|
a: StmtList
|
||||||
|
IntLit 4
|
||||||
|
a: IntLit 5
|
||||||
|
b: IntLit 6
|
||||||
|
a: IntLit 7
|
||||||
|
b: IntLit 8
|
||||||
|
a: IntLit 9
|
||||||
|
b: StmtList
|
||||||
|
IntLit 10
|
||||||
|
a: IntLit 11
|
||||||
|
b: StmtList
|
||||||
|
IntLit 12
|
||||||
|
a: IntLit 13
|
||||||
|
b: StmtList
|
||||||
|
IntLit 14
|
||||||
|
a: IntLit 15
|
||||||
|
b: StmtList
|
||||||
|
IntLit 16
|
||||||
|
a: IntLit 17
|
||||||
|
b: IntLit 18
|
||||||
|
c: IntLit 19
|
||||||
|
a: IntLit 20
|
||||||
|
b: IntLit 21
|
||||||
|
c: IntLit 22
|
||||||
|
a: IntLit 23
|
||||||
|
b: IntLit 24
|
||||||
|
c: StmtList
|
||||||
|
IntLit 25
|
||||||
|
a: IntLit 26
|
||||||
|
b: IntLit 27
|
||||||
|
c: StmtList
|
||||||
|
IntLit 28
|
||||||
|
a: IntLit 29
|
||||||
|
b: IntLit 30
|
||||||
|
c: StmtList
|
||||||
|
IntLit 31
|
||||||
|
a: TupleConstr
|
||||||
|
IntLit 32
|
||||||
|
IntLit 33
|
||||||
|
b: Infix
|
||||||
|
Ident "+"
|
||||||
|
Infix
|
||||||
|
Ident "*"
|
||||||
|
IntLit 34
|
||||||
|
IntLit 35
|
||||||
|
IntLit 36
|
||||||
|
c: StmtList
|
||||||
|
IntLit 37
|
||||||
|
a: Infix
|
||||||
|
Ident "@"
|
||||||
|
TupleConstr
|
||||||
|
IntLit 38
|
||||||
|
IntLit 39
|
||||||
|
Infix
|
||||||
|
Ident "shl"
|
||||||
|
IntLit 40
|
||||||
|
IntLit 41
|
||||||
|
b: Infix
|
||||||
|
Ident "-"
|
||||||
|
Infix
|
||||||
|
Ident "*"
|
||||||
|
IntLit 42
|
||||||
|
IntLit 43
|
||||||
|
IntLit 44
|
||||||
|
c: StmtList
|
||||||
|
IntLit 45
|
||||||
|
a: IntLit 46
|
||||||
|
b: StmtList
|
||||||
|
IntLit 47
|
||||||
|
c: StmtList
|
||||||
|
IntLit 48
|
||||||
|
a: StmtList
|
||||||
|
IntLit 49
|
||||||
|
b: StmtList
|
||||||
|
IntLit 50
|
||||||
|
c: StmtList
|
||||||
|
IntLit 51
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
import macros
|
||||||
|
|
||||||
|
macro call(a): untyped =
|
||||||
|
echo "a: ", a.treeRepr
|
||||||
|
result = ident"int"
|
||||||
|
macro call(a, b): untyped =
|
||||||
|
echo "a: ", a.treeRepr
|
||||||
|
echo "b: ", b.treeRepr
|
||||||
|
result = ident"int"
|
||||||
|
macro call(a, b, c): untyped =
|
||||||
|
echo "a: ", a.treeRepr
|
||||||
|
echo "b: ", b.treeRepr
|
||||||
|
echo "c: ", c.treeRepr
|
||||||
|
result = ident"int"
|
||||||
|
|
||||||
|
macro sections(x): untyped =
|
||||||
|
echo x.treeRepr
|
||||||
|
result = newStmtList(x)
|
||||||
|
for ts in x:
|
||||||
|
for td in ts:
|
||||||
|
let t = td[0]
|
||||||
|
result.add quote do:
|
||||||
|
doAssert `t` is int
|
||||||
|
|
||||||
|
sections:
|
||||||
|
type A = call(1)
|
||||||
|
type
|
||||||
|
B = call 2
|
||||||
|
C = call: 3
|
||||||
|
D = call(): 4
|
||||||
|
type
|
||||||
|
E = call(5, 6)
|
||||||
|
F = call 7, 8
|
||||||
|
G = call(9): 10
|
||||||
|
H = call(11):
|
||||||
|
12
|
||||||
|
I = call 13: 14
|
||||||
|
J = call 15:
|
||||||
|
16
|
||||||
|
type
|
||||||
|
K = call(17, 18, 19)
|
||||||
|
L = call 20, 21, 22
|
||||||
|
M = call(23, 24): 25
|
||||||
|
N = call 26, 27: 28
|
||||||
|
O = call 29, 30:
|
||||||
|
31
|
||||||
|
type
|
||||||
|
P = call (32, 33), 34 * 35 + 36:
|
||||||
|
37
|
||||||
|
R = call (38, 39) @ 40 shl 41, 42 * 43 - 44:
|
||||||
|
45
|
||||||
|
S = call 46:
|
||||||
|
47
|
||||||
|
do:
|
||||||
|
48
|
||||||
|
T = call:
|
||||||
|
49
|
||||||
|
do:
|
||||||
|
50
|
||||||
|
do:
|
||||||
|
51
|
||||||
Loading…
Add table
Add a link
Reference in a new issue