new parsing scheme is documented
This commit is contained in:
parent
03764f0aba
commit
8a595b631b
4 changed files with 293 additions and 455 deletions
|
|
@ -30,7 +30,8 @@ import
|
||||||
type
|
type
|
||||||
TParser*{.final.} = object # a TParser object represents a module that
|
TParser*{.final.} = object # a TParser object represents a module that
|
||||||
# is being parsed
|
# is being parsed
|
||||||
currInd: int # current indentation (for skipInd)
|
currInd: int # current indentation
|
||||||
|
firstTok: bool
|
||||||
lex*: TLexer # the lexer that is used for parsing
|
lex*: TLexer # the lexer that is used for parsing
|
||||||
tok*: TToken # the current token
|
tok*: TToken # the current token
|
||||||
|
|
||||||
|
|
@ -78,6 +79,7 @@ proc OpenParser*(p: var TParser, fileIdx: int32, inputStream: PLLStream) =
|
||||||
initToken(p.tok)
|
initToken(p.tok)
|
||||||
OpenLexer(p.lex, fileIdx, inputstream)
|
OpenLexer(p.lex, fileIdx, inputstream)
|
||||||
getTok(p) # read the first token
|
getTok(p) # read the first token
|
||||||
|
p.firstTok = true
|
||||||
|
|
||||||
proc OpenParser*(p: var TParser, filename: string, inputStream: PLLStream) =
|
proc OpenParser*(p: var TParser, filename: string, inputStream: PLLStream) =
|
||||||
openParser(p, filename.fileInfoIdx, inputStream)
|
openParser(p, filename.fileInfoIdx, inputStream)
|
||||||
|
|
@ -129,11 +131,6 @@ proc getTokNoInd(p: var TParser) =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
if p.tok.indent >= 0: parMessage(p, errInvalidIndentation)
|
if p.tok.indent >= 0: parMessage(p, errInvalidIndentation)
|
||||||
|
|
||||||
when false:
|
|
||||||
proc ExpectNl(p: TParser) =
|
|
||||||
if p.tok.tokType notin {tkEof, tkInd, tkComment}:
|
|
||||||
lexMessage(p.lex, errNewlineExpected, prettyTok(p.tok))
|
|
||||||
|
|
||||||
proc expectIdentOrKeyw(p: TParser) =
|
proc expectIdentOrKeyw(p: TParser) =
|
||||||
if p.tok.tokType != tkSymbol and not isKeyword(p.tok.tokType):
|
if p.tok.tokType != tkSymbol and not isKeyword(p.tok.tokType):
|
||||||
lexMessage(p.lex, errIdentifierExpected, prettyTok(p.tok))
|
lexMessage(p.lex, errIdentifierExpected, prettyTok(p.tok))
|
||||||
|
|
@ -225,9 +222,9 @@ proc isOperator(tok: TToken): bool =
|
||||||
|
|
||||||
#| module = stmt ^* (';' / IND{=})
|
#| module = stmt ^* (';' / IND{=})
|
||||||
#|
|
#|
|
||||||
#| comma = ',' COMMENT? IND?
|
#| comma = ',' COMMENT?
|
||||||
#| semicolon = ';' COMMENT IND?
|
#| semicolon = ';' COMMENT?
|
||||||
#| colon = ':' COMMENT? IND?
|
#| colon = ':' COMMENT?
|
||||||
#| colcom = ':' COMMENT?
|
#| colcom = ':' COMMENT?
|
||||||
#|
|
#|
|
||||||
#| operator = OP0 | OP1 | OP2 | OP3 | OP4 | OP5 | OP6 | OP7 | OP8 | OP9
|
#| operator = OP0 | OP1 | OP2 | OP3 | OP4 | OP5 | OP6 | OP7 | OP8 | OP9
|
||||||
|
|
@ -237,10 +234,10 @@ proc isOperator(tok: TToken): bool =
|
||||||
#|
|
#|
|
||||||
#| prefixOperator = operator
|
#| prefixOperator = operator
|
||||||
#|
|
#|
|
||||||
#| optInd = COMMENT? IND?
|
#| optInd = COMMENT?
|
||||||
#| optPar = IND{>} | IND{=}
|
#| optPar = (IND{>} | IND{=})?
|
||||||
#|
|
#|
|
||||||
#| lowestExpr = assignExpr (OP0 optInd assignExpr)*
|
#| simpleExpr = assignExpr (OP0 optInd assignExpr)*
|
||||||
#| assignExpr = orExpr (OP1 optInd orExpr)*
|
#| assignExpr = orExpr (OP1 optInd orExpr)*
|
||||||
#| orExpr = andExpr (OP2 optInd andExpr)*
|
#| orExpr = andExpr (OP2 optInd andExpr)*
|
||||||
#| andExpr = cmpExpr (OP3 optInd cmpExpr)*
|
#| andExpr = cmpExpr (OP3 optInd cmpExpr)*
|
||||||
|
|
@ -591,7 +588,7 @@ type
|
||||||
|
|
||||||
proc primary(p: var TParser, mode: TPrimaryMode): PNode
|
proc primary(p: var TParser, mode: TPrimaryMode): PNode
|
||||||
|
|
||||||
proc lowestExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode =
|
proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode =
|
||||||
result = primary(p, mode)
|
result = primary(p, mode)
|
||||||
# expand while operators have priorities higher than 'limit'
|
# expand while operators have priorities higher than 'limit'
|
||||||
var opPrec = getPrecedence(p.tok)
|
var opPrec = getPrecedence(p.tok)
|
||||||
|
|
@ -604,15 +601,15 @@ proc lowestExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, opNode)
|
optInd(p, opNode)
|
||||||
# read sub-expression with higher priority:
|
# read sub-expression with higher priority:
|
||||||
var b = lowestExprAux(p, opPrec + leftAssoc, modeB)
|
var b = simpleExprAux(p, opPrec + leftAssoc, modeB)
|
||||||
addSon(a, opNode)
|
addSon(a, opNode)
|
||||||
addSon(a, result)
|
addSon(a, result)
|
||||||
addSon(a, b)
|
addSon(a, b)
|
||||||
result = a
|
result = a
|
||||||
opPrec = getPrecedence(p.tok)
|
opPrec = getPrecedence(p.tok)
|
||||||
|
|
||||||
proc lowestExpr(p: var TParser, mode = pmNormal): PNode =
|
proc simpleExpr(p: var TParser, mode = pmNormal): PNode =
|
||||||
result = lowestExprAux(p, -1, mode)
|
result = simpleExprAux(p, -1, mode)
|
||||||
|
|
||||||
proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
|
proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
|
||||||
#| condExpr = expr colcom expr optInd
|
#| condExpr = expr colcom expr optInd
|
||||||
|
|
@ -844,12 +841,12 @@ proc parseExpr(p: var TParser): PNode =
|
||||||
#| expr = (ifExpr
|
#| expr = (ifExpr
|
||||||
#| | whenExpr
|
#| | whenExpr
|
||||||
#| | caseExpr)
|
#| | caseExpr)
|
||||||
#| / lowestExpr
|
#| / simpleExpr
|
||||||
case p.tok.tokType:
|
case p.tok.tokType:
|
||||||
of tkIf: result = parseIfExpr(p, nkIfExpr)
|
of tkIf: result = parseIfExpr(p, nkIfExpr)
|
||||||
of tkWhen: result = parseIfExpr(p, nkWhenExpr)
|
of tkWhen: result = parseIfExpr(p, nkWhenExpr)
|
||||||
of tkCase: result = parseCase(p)
|
of tkCase: result = parseCase(p)
|
||||||
else: result = lowestExpr(p)
|
else: result = simpleExpr(p)
|
||||||
# XXX needs proper support:
|
# XXX needs proper support:
|
||||||
#of tkTry: result = parseTry(p)
|
#of tkTry: result = parseTry(p)
|
||||||
|
|
||||||
|
|
@ -934,12 +931,12 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
|
||||||
result = primarySuffix(p, result)
|
result = primarySuffix(p, result)
|
||||||
|
|
||||||
proc parseTypeDesc(p: var TParser): PNode =
|
proc parseTypeDesc(p: var TParser): PNode =
|
||||||
#| typeDesc = lowestExpr
|
#| typeDesc = simpleExpr
|
||||||
result = lowestExpr(p, pmTypeDesc)
|
result = simpleExpr(p, pmTypeDesc)
|
||||||
|
|
||||||
proc parseTypeDefAux(p: var TParser): PNode =
|
proc parseTypeDefAux(p: var TParser): PNode =
|
||||||
#| typeDefAux = lowestExpr
|
#| typeDefAux = simpleExpr
|
||||||
result = lowestExpr(p, pmTypeDef)
|
result = simpleExpr(p, pmTypeDef)
|
||||||
|
|
||||||
proc makeCall(n: PNode): PNode =
|
proc makeCall(n: PNode): PNode =
|
||||||
if n.kind in nkCallKinds:
|
if n.kind in nkCallKinds:
|
||||||
|
|
@ -949,7 +946,7 @@ proc makeCall(n: PNode): PNode =
|
||||||
result.add n
|
result.add n
|
||||||
|
|
||||||
proc parseExprStmt(p: var TParser): PNode =
|
proc parseExprStmt(p: var TParser): PNode =
|
||||||
#| exprStmt = lowestExpr
|
#| exprStmt = simpleExpr
|
||||||
#| (( '=' optInd expr )
|
#| (( '=' optInd expr )
|
||||||
#| / ( expr ^+ comma
|
#| / ( expr ^+ comma
|
||||||
#| doBlocks
|
#| doBlocks
|
||||||
|
|
@ -958,7 +955,7 @@ proc parseExprStmt(p: var TParser): PNode =
|
||||||
#| | IND{=} 'except' exprList ':' stmt
|
#| | IND{=} 'except' exprList ':' stmt
|
||||||
#| | IND{=} 'else' ':' stmt )*
|
#| | IND{=} 'else' ':' stmt )*
|
||||||
#| ))?
|
#| ))?
|
||||||
var a = lowestExpr(p)
|
var a = simpleExpr(p)
|
||||||
if p.tok.tokType == tkEquals:
|
if p.tok.tokType == tkEquals:
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
|
|
@ -1131,7 +1128,7 @@ proc parseCase(p: var TParser): PNode =
|
||||||
#| (IND{=} 'elif' expr colcom stmt)*
|
#| (IND{=} 'elif' expr colcom stmt)*
|
||||||
#| (IND{=} 'else' colcom stmt)?
|
#| (IND{=} 'else' colcom stmt)?
|
||||||
#| caseStmt = 'case' expr ':'? COMMENT?
|
#| caseStmt = 'case' expr ':'? COMMENT?
|
||||||
#| (IND{>} ofBranches
|
#| (IND{>} ofBranches DED
|
||||||
#| | IND{=} ofBranches)
|
#| | IND{=} ofBranches)
|
||||||
var
|
var
|
||||||
b: PNode
|
b: PNode
|
||||||
|
|
@ -1447,7 +1444,7 @@ proc parseObjectCase(p: var TParser): PNode =
|
||||||
#| (IND{=} 'elif' expr colcom objectPart)*
|
#| (IND{=} 'elif' expr colcom objectPart)*
|
||||||
#| (IND{=} 'else' colcom objectPart)?
|
#| (IND{=} 'else' colcom objectPart)?
|
||||||
#| objectCase = 'case' identWithPragma ':' typeDesc ':'? COMMENT?
|
#| objectCase = 'case' identWithPragma ':' typeDesc ':'? COMMENT?
|
||||||
#| (IND{>} objectBranches
|
#| (IND{>} objectBranches DED
|
||||||
#| | IND{=} objectBranches)
|
#| | IND{=} objectBranches)
|
||||||
result = newNodeP(nkRecCase, p)
|
result = newNodeP(nkRecCase, p)
|
||||||
getTokNoInd(p)
|
getTokNoInd(p)
|
||||||
|
|
@ -1724,7 +1721,10 @@ proc parseAll(p: var TParser): PNode =
|
||||||
proc parseTopLevelStmt(p: var TParser): PNode =
|
proc parseTopLevelStmt(p: var TParser): PNode =
|
||||||
result = ast.emptyNode
|
result = ast.emptyNode
|
||||||
while true:
|
while true:
|
||||||
if p.tok.indent > 0: parMessage(p, errInvalidIndentation)
|
if p.tok.indent != 0:
|
||||||
|
if p.firstTok and p.tok.indent < 0: nil
|
||||||
|
else: parMessage(p, errInvalidIndentation)
|
||||||
|
p.firstTok = false
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkSemicolon: getTok(p)
|
of tkSemicolon: getTok(p)
|
||||||
of tkEof: break
|
of tkEof: break
|
||||||
|
|
|
||||||
375
doc/grammar.txt
375
doc/grammar.txt
|
|
@ -1,204 +1,181 @@
|
||||||
module ::= ([COMMENT] [SAD] stmt)*
|
module = stmt ^* (';' / IND{=})
|
||||||
|
comma = ',' COMMENT?
|
||||||
|
semicolon = ';' COMMENT?
|
||||||
|
colon = ':' COMMENT?
|
||||||
|
colcom = ':' COMMENT?
|
||||||
|
|
||||||
comma ::= ',' [COMMENT] [IND]
|
operator = OP0 | OP1 | OP2 | OP3 | OP4 | OP5 | OP6 | OP7 | OP8 | OP9
|
||||||
semicolon ::= ';' [COMMENT] [IND]
|
| 'or' | 'xor' | 'and'
|
||||||
|
| 'is' | 'isnot' | 'in' | 'notin' | 'of'
|
||||||
|
| 'div' | 'mod' | 'shl' | 'shr' | 'not' | 'addr' | 'static' | '..'
|
||||||
|
|
||||||
operator ::= OP0 | OP1 | OP2 | OP3 | OP4 | OP5 | OP6 | OP7 | OP8 | OP9
|
prefixOperator = operator
|
||||||
| 'or' | 'xor' | 'and'
|
|
||||||
| 'is' | 'isnot' | 'in' | 'notin' | 'of'
|
|
||||||
| 'div' | 'mod' | 'shl' | 'shr' | 'not' | 'addr' | 'static' | '..'
|
|
||||||
|
|
||||||
prefixOperator ::= operator
|
optInd = COMMENT?
|
||||||
|
optPar = (IND{>} | IND{=})?
|
||||||
optInd ::= [COMMENT] [IND]
|
|
||||||
optPar ::= [IND] | [SAD]
|
|
||||||
|
|
||||||
lowestExpr ::= assignExpr (OP0 optInd assignExpr)*
|
|
||||||
assignExpr ::= orExpr (OP1 optInd orExpr)*
|
|
||||||
orExpr ::= andExpr (OP2 optInd andExpr)*
|
|
||||||
andExpr ::= cmpExpr (OP3 optInd cmpExpr)*
|
|
||||||
cmpExpr ::= sliceExpr (OP4 optInd sliceExpr)*
|
|
||||||
sliceExpr ::= ampExpr (OP5 optInd ampExpr)*
|
|
||||||
ampExpr ::= plusExpr (OP6 optInd plusExpr)*
|
|
||||||
plusExpr ::= mulExpr (OP7 optInd mulExpr)*
|
|
||||||
mulExpr ::= dollarExpr (OP8 optInd dollarExpr)*
|
|
||||||
dollarExpr ::= primary (OP9 optInd primary)*
|
|
||||||
|
|
||||||
indexExpr ::= expr
|
|
||||||
|
|
||||||
castExpr ::= 'cast' '[' optInd typeDesc optPar ']' '(' optInd expr optPar ')'
|
|
||||||
symbol ::= '`' (KEYWORD | IDENT | operator | '(' ')' | '[' ']' | '{' '}'
|
|
||||||
| '=' | literal)+ '`'
|
|
||||||
| IDENT
|
|
||||||
|
|
||||||
primaryPrefix ::= (prefixOperator | 'bind') optInd
|
|
||||||
primarySuffix ::= '.' optInd symbol [generalizedLit]
|
|
||||||
| '(' optInd namedExprList optPar ')'
|
|
||||||
| '[' optInd [indexExpr (comma indexExpr)* [comma]] optPar ']'
|
|
||||||
| '{' optInd [indexExpr (comma indexExpr)* [comma]] optPar '}'
|
|
||||||
|
|
||||||
primary ::= primaryPrefix* (symbol [generalizedLit] |
|
|
||||||
constructor | castExpr)
|
|
||||||
primarySuffix*
|
|
||||||
|
|
||||||
|
simpleExpr = assignExpr (OP0 optInd assignExpr)*
|
||||||
|
assignExpr = orExpr (OP1 optInd orExpr)*
|
||||||
|
orExpr = andExpr (OP2 optInd andExpr)*
|
||||||
|
andExpr = cmpExpr (OP3 optInd cmpExpr)*
|
||||||
|
cmpExpr = sliceExpr (OP4 optInd sliceExpr)*
|
||||||
|
sliceExpr = ampExpr (OP5 optInd ampExpr)*
|
||||||
|
ampExpr = plusExpr (OP6 optInd plusExpr)*
|
||||||
|
plusExpr = mulExpr (OP7 optInd mulExpr)*
|
||||||
|
mulExpr = dollarExpr (OP8 optInd dollarExpr)*
|
||||||
|
dollarExpr = primary (OP9 optInd primary)*
|
||||||
|
symbol = '`' (KEYW|IDENT|operator|'(' ')'|'[' ']'|'{' '}'|'='|literal)+ '`'
|
||||||
|
| IDENT
|
||||||
|
indexExpr = expr
|
||||||
|
indexExprList = indexExpr ^+ comma
|
||||||
|
exprColonEqExpr = expr (':'|'=' expr)?
|
||||||
|
exprList = expr ^+ comma
|
||||||
|
dotExpr = expr '.' optInd ('type' | 'addr' | symbol)
|
||||||
|
qualifiedIdent = symbol ('.' optInd ('type' | 'addr' | symbol))?
|
||||||
|
exprColonEqExprList = exprColonEqExpr (comma exprColonEqExpr)* (comma)?
|
||||||
|
setOrTableConstr = '{' ((exprColonEqExpr comma)* | ':' ) '}'
|
||||||
|
castExpr = 'cast' '[' optInd typeDesc optPar ']' '(' optInd expr optPar ')'
|
||||||
generalizedLit ::= GENERALIZED_STR_LIT | GENERALIZED_TRIPLESTR_LIT
|
generalizedLit ::= GENERALIZED_STR_LIT | GENERALIZED_TRIPLESTR_LIT
|
||||||
|
identOrLiteral = generalizedLit | symbol
|
||||||
literal ::= INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
|
| INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
|
||||||
| UINT_LIT | UINT8_LIT | UINT16_LIT | UINT32_LIT | UINT64_LIT
|
| UINT_LIT | UINT8_LIT | UINT16_LIT | UINT32_LIT | UINT64_LIT
|
||||||
| FLOAT_LIT | FLOAT32_LIT | FLOAT64_LIT
|
| FLOAT_LIT | FLOAT32_LIT | FLOAT64_LIT
|
||||||
| STR_LIT | RSTR_LIT | TRIPLESTR_LIT
|
| STR_LIT | RSTR_LIT | TRIPLESTR_LIT
|
||||||
| CHAR_LIT
|
| CHAR_LIT
|
||||||
| NIL
|
| NIL
|
||||||
|
| tupleConstr | arrayConstr | setOrTableConstr
|
||||||
constructor ::= literal
|
| castExpr
|
||||||
| '[' optInd colonExprList optPar ']'
|
tupleConstr = '(' optInd (exprColonEqExpr comma?)* optPar ')'
|
||||||
| '{' optInd ':' | colonExprList optPar '}'
|
arrayConstr = '[' optInd (exprColonEqExpr comma?)* optPar ']'
|
||||||
| '(' optInd colonExprList optPar ')'
|
primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
|
||||||
|
| doBlocks
|
||||||
colonExpr ::= expr [':' expr]
|
| '.' optInd ('type' | 'addr' | symbol) generalizedLit?
|
||||||
colonExprList ::= [colonExpr (comma colonExpr)* [comma]]
|
| '[' optInd indexExprList optPar ']'
|
||||||
|
| '{' optInd indexExprList optPar '}'
|
||||||
namedExpr ::= expr ['=' expr]
|
condExpr = expr colcom expr optInd
|
||||||
namedExprList ::= [namedExpr (comma namedExpr)* [comma]]
|
('elif' expr colcom expr optInd)*
|
||||||
|
'else' colcom expr
|
||||||
exprOrType ::= lowestExpr
|
ifExpr = 'if' condExpr
|
||||||
| 'if' expr ':' expr ('elif' expr ':' expr)* 'else' ':' expr
|
whenExpr = 'when' condExpr
|
||||||
| 'var' exprOrType
|
pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}')
|
||||||
| 'ref' exprOrType
|
identVis = symbol opr? # postfix position
|
||||||
| 'ptr' exprOrType
|
identWithPragma = identVis pragma?
|
||||||
| 'type' exprOrType
|
declColonEquals = identWithPragma (comma identWithPragma)* comma?
|
||||||
| 'tuple' tupleDesc
|
(':' optInd typeDesc)? ('=' optInd expr)?
|
||||||
|
identColonEquals = ident (comma ident)* comma?
|
||||||
expr ::= exprOrType
|
(':' optInd typeDesc)? ('=' optInd expr)?)
|
||||||
| 'proc' paramList [pragma] ['=' stmt]
|
inlTupleDecl = 'tuple'
|
||||||
| 'iterator' paramList [pragma] ['=' stmt]
|
[' optInd (identColonEquals (comma/semicolon)?)* optPar ']'
|
||||||
|
extTupleDecl = 'tuple'
|
||||||
exprList ::= [expr (comma expr)* [comma]]
|
COMMENT? (IND{>} identColonEquals (IND{=} identColonEquals)*)?
|
||||||
|
paramList = '(' identColonEquals ^* (comma/semicolon) ')'
|
||||||
|
paramListArrow = paramList? ('->' optInd typeDesc)?
|
||||||
qualifiedIdent ::= symbol ['.' symbol]
|
paramListColon = paramList? (':' optInd typeDesc)?
|
||||||
|
doBlock = 'do' paramListArrow pragmas? colcom stmt
|
||||||
typeDesc ::= (exprOrType
|
doBlocks = doBlock ^* IND{=}
|
||||||
| 'proc' paramList [pragma]
|
procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)?
|
||||||
| 'iterator' paramList [pragma] )
|
expr = (ifExpr
|
||||||
['not' expr] # for now only 'not nil' suffix is supported
|
| whenExpr
|
||||||
|
| caseExpr)
|
||||||
macroStmt ::= ':' [stmt] ('of' [exprList] ':' stmt
|
/ simpleExpr
|
||||||
|'elif' expr ':' stmt
|
typeKeyw = 'var' | 'ref' | 'ptr' | 'shared' | 'type' | 'tuple'
|
||||||
|'except' exceptList ':' stmt )*
|
| 'proc' | 'iterator' | 'distinct' | 'object' | 'enum'
|
||||||
['else' ':' stmt]
|
primary = typeKeyw typeDescK
|
||||||
|
/ prefixOperator* identOrLiteral primarySuffix*
|
||||||
pragmaBlock ::= pragma [':' stmt]
|
/ 'addr' primary
|
||||||
|
/ 'static' primary
|
||||||
simpleStmt ::= returnStmt
|
/ 'bind' primary
|
||||||
| yieldStmt
|
typeDesc = simpleExpr
|
||||||
| discardStmt
|
typeDefAux = simpleExpr
|
||||||
| raiseStmt
|
exprStmt = simpleExpr
|
||||||
| breakStmt
|
(( '=' optInd expr )
|
||||||
| continueStmt
|
/ ( expr ^+ comma
|
||||||
| pragmaBlock
|
doBlocks
|
||||||
| importStmt
|
/ ':' stmt? ( IND{=} 'of' exprList ':' stmt
|
||||||
| fromStmt
|
| IND{=} 'elif' expr ':' stmt
|
||||||
| includeStmt
|
| IND{=} 'except' exprList ':' stmt
|
||||||
| exprStmt
|
| IND{=} 'else' ':' stmt )*
|
||||||
complexStmt ::= ifStmt | whileStmt | caseStmt | tryStmt | forStmt
|
))?
|
||||||
| blockStmt | staticStmt | asmStmt
|
importStmt = 'import' optInd expr
|
||||||
| procDecl | iteratorDecl | macroDecl | templateDecl | methodDecl
|
((comma expr)*
|
||||||
| constSection | letSection | varSection
|
/ 'except' optInd (expr ^+ comma))
|
||||||
| typeSection | whenStmt | bindStmt
|
includeStmt = 'include' optInd expr ^+ comma
|
||||||
|
fromStmt = 'from' expr 'import' optInd expr (comma expr)*
|
||||||
indPush ::= IND # and push indentation onto the stack
|
returnStmt = 'return' optInd expr?
|
||||||
indPop ::= # pop indentation from the stack
|
raiseStmt = 'raise' optInd expr?
|
||||||
|
yieldStmt = 'yield' optInd expr?
|
||||||
stmt ::= simpleStmt [SAD]
|
discardStmt = 'discard' optInd expr?
|
||||||
| indPush (complexStmt | simpleStmt)
|
breakStmt = 'break' optInd expr?
|
||||||
([SAD] (complexStmt | simpleStmt))*
|
continueStmt = 'break' optInd expr?
|
||||||
DED indPop
|
condStmt = expr colcom stmt COMMENT?
|
||||||
|
(IND{=} 'elif' expr colcom stmt)*
|
||||||
exprStmt ::= lowestExpr ['=' expr | [expr (comma expr)*] [macroStmt]]
|
(IND{=} 'else' colcom stmt)?
|
||||||
returnStmt ::= 'return' [expr]
|
ifStmt = 'if' condStmt
|
||||||
yieldStmt ::= 'yield' expr
|
whenStmt = 'when' condStmt
|
||||||
discardStmt ::= 'discard' expr
|
whileStmt = 'while' expr colcom stmt
|
||||||
raiseStmt ::= 'raise' [expr]
|
ofBranch = 'of' exprList colcom stmt
|
||||||
breakStmt ::= 'break' [symbol]
|
ofBranches = ofBranch (IND{=} ofBranch)*
|
||||||
continueStmt ::= 'continue'
|
(IND{=} 'elif' expr colcom stmt)*
|
||||||
ifStmt ::= 'if' expr ':' stmt ('elif' expr ':' stmt)* ['else' ':' stmt]
|
(IND{=} 'else' colcom stmt)?
|
||||||
whenStmt ::= 'when' expr ':' stmt ('elif' expr ':' stmt)* ['else' ':' stmt]
|
caseStmt = 'case' expr ':'? COMMENT?
|
||||||
caseStmt ::= 'case' expr [':'] ('of' exprList ':' stmt)*
|
(IND{>} ofBranches DED
|
||||||
('elif' expr ':' stmt)*
|
| IND{=} ofBranches)
|
||||||
['else' ':' stmt]
|
tryStmt = 'try' colcom stmt &(IND{=}? 'except'|'finally')
|
||||||
whileStmt ::= 'while' expr ':' stmt
|
(IND{=}? 'except' exprList colcom stmt)*
|
||||||
forStmt ::= 'for' symbol (comma symbol)* 'in' expr ':' stmt
|
(IND{=}? 'finally' colcom stmt)?
|
||||||
exceptList ::= [qualifiedIdent (comma qualifiedIdent)*]
|
exceptBlock = 'except' colcom stmt
|
||||||
|
forStmt = 'for' symbol (comma symbol)* 'in' expr colcom stmt
|
||||||
tryStmt ::= 'try' ':' stmt
|
blockStmt = 'block' symbol? colcom stmt
|
||||||
('except' exceptList ':' stmt)*
|
staticStmt = 'static' colcom stmt
|
||||||
['finally' ':' stmt]
|
asmStmt = 'asm' pragma? (STR_LIT | RSTR_LIT | TRIPLE_STR_LIT)
|
||||||
asmStmt ::= 'asm' [pragma] (STR_LIT | RSTR_LIT | TRIPLESTR_LIT)
|
genericParam = symbol (comma symbol)* (colon expr)? ('=' optInd expr)?
|
||||||
blockStmt ::= 'block' [symbol] ':' stmt
|
genericParamList = '[' optInd
|
||||||
staticStmt ::= 'static' ':' stmt
|
genericParam ^* (comma/semicolon) optPar ']'
|
||||||
filename ::= symbol | STR_LIT | RSTR_LIT | TRIPLESTR_LIT
|
pattern = '{' stmt '}'
|
||||||
importStmt ::= 'import' filename (comma filename)*
|
indAndComment = (IND{>} COMMENT)? | COMMENT?
|
||||||
includeStmt ::= 'include' filename (comma filename)*
|
routine = optInd identVis pattern? genericParamList?
|
||||||
bindStmt ::= 'bind' qualifiedIdent (comma qualifiedIdent)*
|
paramListColon pragma? ('=' COMMENT? stmt)? indAndComment
|
||||||
fromStmt ::= 'from' filename 'import' symbol (comma symbol)*
|
commentStmt = COMMENT
|
||||||
|
section(p) = COMMENT? p / (IND{>} (p / COMMENT)^+IND{=} DED)
|
||||||
pragma ::= '{.' optInd (colonExpr [comma])* optPar ('.}' | '}')
|
constant = identWithPragma (colon typedesc)? '=' optInd expr indAndComment
|
||||||
|
enum = 'enum' optInd (symbol optInd ('=' optInd expr COMMENT?)? comma?)+
|
||||||
param ::= symbol (comma symbol)* (':' typeDesc ['=' expr] | '=' expr)
|
objectWhen = 'when' expr colcom objectPart COMMENT?
|
||||||
paramList ::= ['(' [param (comma|semicolon param)*] optPar ')'] [':' typeDesc]
|
('elif' expr colcom objectPart COMMENT?)*
|
||||||
|
('else' colcom objectPart COMMENT?)?
|
||||||
genericConstraint ::= 'object' | 'tuple' | 'enum' | 'proc' | 'ref' | 'ptr'
|
objectBranch = 'of' exprList colcom objectPart
|
||||||
| 'var' | 'distinct' | 'iterator' | primary
|
objectBranches = objectBranch (IND{=} objectBranch)*
|
||||||
genericConstraints ::= genericConstraint ( '|' optInd genericConstraint )*
|
(IND{=} 'elif' expr colcom objectPart)*
|
||||||
|
(IND{=} 'else' colcom objectPart)?
|
||||||
genericParam ::= symbol [':' genericConstraints] ['=' expr]
|
objectCase = 'case' identWithPragma ':' typeDesc ':'? COMMENT?
|
||||||
genericParams ::= '[' genericParam (comma|semicolon genericParam)* optPar ']'
|
(IND{>} objectBranches DED
|
||||||
|
| IND{=} objectBranches)
|
||||||
|
objectPart = IND{>} objectPart^+IND{=} DED
|
||||||
routineDecl := symbol ['*'] [genericParams] paramList [pragma] ['=' stmt]
|
/ objectWhen / objectCase / 'nil' / declColonEquals
|
||||||
procDecl ::= 'proc' routineDecl
|
object = 'object' pragma? ('of' typeDesc)? COMMENT? objectPart
|
||||||
macroDecl ::= 'macro' routineDecl
|
distinct = 'distinct' optInd typeDesc
|
||||||
iteratorDecl ::= 'iterator' routineDecl
|
typeDef = identWithPragma genericParamList? '=' optInd typeDefAux
|
||||||
templateDecl ::= 'template' routineDecl
|
indAndComment?
|
||||||
methodDecl ::= 'method' routineDecl
|
varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr
|
||||||
|
variable = (varTuple / identColonEquals) indAndComment
|
||||||
colonAndEquals ::= [':' typeDesc] '=' expr
|
bindStmt = 'bind' optInd qualifiedIdent ^+ comma
|
||||||
|
mixinStmt = 'mixin' optInd qualifiedIdent ^+ comma
|
||||||
constDecl ::= symbol ['*'] [pragma] colonAndEquals [COMMENT | IND COMMENT]
|
pragmaStmt = pragma (':' COMMENT? stmt)?
|
||||||
| COMMENT
|
simpleStmt = ((returnStmt | raiseStmt | yieldStmt | discardStmt | breakStmt
|
||||||
constSection ::= 'const' indPush constDecl (SAD constDecl)* DED indPop
|
| continueStmt | pragmaStmt | importStmt | exportStmt | fromStmt
|
||||||
letSection ::= 'let' indPush constDecl (SAD constDecl)* DED indPop
|
| includeStmt | commentStmt) / exprStmt) COMMENT?
|
||||||
|
complexOrSimpleStmt = (ifStmt | whenStmt | whileStmt
|
||||||
typeDef ::= typeDesc | objectDef | enumDef | 'distinct' typeDesc
|
| tryStmt | finallyStmt | exceptStmt | forStmt
|
||||||
|
| blockStmt | staticStmt | asmStmt
|
||||||
objectField ::= symbol ['*'] [pragma]
|
| 'proc' routine
|
||||||
objectIdentPart ::= objectField (comma objectField)* ':' typeDesc
|
| 'method' routine
|
||||||
[COMMENT|IND COMMENT]
|
| 'iterator' routine
|
||||||
|
| 'macro' routine
|
||||||
objectWhen ::= 'when' expr ':' [COMMENT] objectPart
|
| 'template' routine
|
||||||
('elif' expr ':' [COMMENT] objectPart)*
|
| 'converter' routine
|
||||||
['else' ':' [COMMENT] objectPart]
|
| 'type' section(typeDef)
|
||||||
objectCase ::= 'case' expr ':' typeDesc [COMMENT]
|
| 'const' section(constant)
|
||||||
('of' exprList ':' [COMMENT] objectPart)*
|
| ('let' | 'var') section(variable)
|
||||||
['else' ':' [COMMENT] objectPart]
|
| bindStmt | mixinStmt)
|
||||||
|
/ simpleStmt
|
||||||
objectPart ::= objectWhen | objectCase | objectIdentPart | 'nil'
|
stmt = (IND{>} complexOrSimpleStmt^+(IND{=} / ';') DED)
|
||||||
| indPush objectPart (SAD objectPart)* DED indPop
|
/ simpleStmt
|
||||||
tupleDesc ::= '[' optInd [param (comma|semicolon param)*] optPar ']'
|
|
||||||
|
|
||||||
objectDef ::= 'object' [pragma] ['of' typeDesc] objectPart
|
|
||||||
enumField ::= symbol ['=' expr]
|
|
||||||
enumDef ::= 'enum' (enumField [comma] [COMMENT | IND COMMENT])+
|
|
||||||
|
|
||||||
typeDecl ::= COMMENT
|
|
||||||
| symbol ['*'] [genericParams] ['=' typeDef] [COMMENT | IND COMMENT]
|
|
||||||
|
|
||||||
typeSection ::= 'type' indPush typeDecl (SAD typeDecl)* DED indPop
|
|
||||||
|
|
||||||
colonOrEquals ::= ':' typeDesc ['=' expr] | '=' expr
|
|
||||||
varField ::= symbol ['*'] [pragma]
|
|
||||||
varPart ::= symbol (comma symbol)* colonOrEquals [COMMENT | IND COMMENT]
|
|
||||||
varSection ::= 'var' (varPart
|
|
||||||
| indPush (COMMENT|varPart)
|
|
||||||
(SAD (COMMENT|varPart))* DED indPop)
|
|
||||||
|
|
|
||||||
300
doc/manual.txt
300
doc/manual.txt
|
|
@ -23,14 +23,25 @@ This document describes the lexis, the syntax, and the semantics of Nimrod.
|
||||||
|
|
||||||
The language constructs are explained using an extended BNF, in
|
The language constructs are explained using an extended BNF, in
|
||||||
which ``(a)*`` means 0 or more ``a``'s, ``a+`` means 1 or more ``a``'s, and
|
which ``(a)*`` means 0 or more ``a``'s, ``a+`` means 1 or more ``a``'s, and
|
||||||
``(a)?`` means an optional *a*; an alternative spelling for optional parts is
|
``(a)?`` means an optional *a*. Parentheses may be used to group elements.
|
||||||
``[a]``. The ``|`` symbol is used to mark alternatives
|
|
||||||
and has the lowest precedence. Parentheses may be used to group elements.
|
The ``|``, ``/`` symbols are used to mark alternatives and have the lowest
|
||||||
|
precedence. ``/`` is the ordered choice that requires the parser to try the
|
||||||
|
alternatives in the given order. ``/`` is often used to ensure the grammar
|
||||||
|
is not ambiguous.
|
||||||
|
|
||||||
Non-terminals start with a lowercase letter, abstract terminal symbols are in
|
Non-terminals start with a lowercase letter, abstract terminal symbols are in
|
||||||
UPPERCASE. Verbatim terminal symbols (including keywords) are quoted
|
UPPERCASE. Verbatim terminal symbols (including keywords) are quoted
|
||||||
with ``'``. An example::
|
with ``'``. An example::
|
||||||
|
|
||||||
ifStmt ::= 'if' expr ':' stmts ('elif' expr ':' stmts)* ['else' stmts]
|
ifStmt = 'if' expr ':' stmts ('elif' expr ':' stmts)* ('else' stmts)?
|
||||||
|
|
||||||
|
The binary ``^*`` operator is used as a shorthand for 0 or more occurances
|
||||||
|
separated by its second argument; likewise ``^+`` means 1 or more
|
||||||
|
occurances: ``a ^+ b`` is short for ``a (b a)*``
|
||||||
|
and ``a ^* b`` is short for ``(a (b a)*)?``. Example::
|
||||||
|
|
||||||
|
arrayConstructor = '[' expr ^* ',' ']'
|
||||||
|
|
||||||
Other parts of Nimrod - like scoping rules or runtime semantics are only
|
Other parts of Nimrod - like scoping rules or runtime semantics are only
|
||||||
described in an informal manner for now.
|
described in an informal manner for now.
|
||||||
|
|
@ -50,7 +61,7 @@ An `identifier`:idx: is a symbol declared as a name for a variable, type,
|
||||||
procedure, etc. The region of the program over which a declaration applies is
|
procedure, etc. The region of the program over which a declaration applies is
|
||||||
called the `scope`:idx: of the declaration. Scopes can be nested. The meaning
|
called the `scope`:idx: of the declaration. Scopes can be nested. The meaning
|
||||||
of an identifier is determined by the smallest enclosing scope in which the
|
of an identifier is determined by the smallest enclosing scope in which the
|
||||||
identifier is declared.
|
identifier is declared unless overloading resolution rules suggest otherwise.
|
||||||
|
|
||||||
An expression specifies a computation that produces a value or location.
|
An expression specifies a computation that produces a value or location.
|
||||||
Expressions that produce locations are called `l-values`:idx:. An l-value
|
Expressions that produce locations are called `l-values`:idx:. An l-value
|
||||||
|
|
@ -93,28 +104,31 @@ Nimrod's standard grammar describes an `indentation sensitive`:idx: language.
|
||||||
This means that all the control structures are recognized by indentation.
|
This means that all the control structures are recognized by indentation.
|
||||||
Indentation consists only of spaces; tabulators are not allowed.
|
Indentation consists only of spaces; tabulators are not allowed.
|
||||||
|
|
||||||
The terminals ``IND`` (indentation), ``DED`` (dedentation) and ``SAD``
|
The indentation handling is implemented as follows: The lexer annotates the
|
||||||
(same indentation) are generated by the scanner, denoting an indentation.
|
following token with the preceeding number of spaces; indentation is not
|
||||||
|
a separate token. This trick allows parsing of Nimrod with only 1 token of
|
||||||
|
lookahead.
|
||||||
|
|
||||||
These terminals are only generated for lines that are not empty.
|
The parser uses a stack of indentation levels: the stack consists of integers
|
||||||
|
counting the spaces. The indentation information is queried at strategic
|
||||||
|
places in the parser but ignored otherwise: The pseudo terminal ``IND{>}``
|
||||||
|
denotes an indentation that consists of more spaces than the entry at the top
|
||||||
|
of the stack; IND{=} an indentation that has the same number of spaces. ``DED``
|
||||||
|
is another pseudo terminal that describes the *action* of popping a value
|
||||||
|
from the stack, ``IND{>}`` then implies to push onto the stack.
|
||||||
|
|
||||||
The parser and the scanner communicate over a stack which indentation terminal
|
With this notation we can now easily define the core of the grammar: A block of
|
||||||
should be generated: the stack consists of integers counting the spaces. The
|
statements (simplified example)::
|
||||||
stack is initialized with a zero on its top. The scanner reads from the stack:
|
|
||||||
If the current indentation token consists of more spaces than the entry at the
|
ifStmt = 'if' expr ':' stmt
|
||||||
top of the stack, a ``IND`` token is generated, else if it consists of the same
|
(IND{=} 'elif' expr ':' stmt)*
|
||||||
number of spaces, a ``SAD`` token is generated. If it consists of fewer spaces,
|
(IND{=} 'else' ':' stmt)?
|
||||||
a ``DED`` token is generated for any item on the stack that is greater than the
|
|
||||||
current. These items are later popped from the stack by the parser. At the end
|
simpleStmt = ifStmt / ...
|
||||||
of the file, a ``DED`` token is generated for each number remaining on the
|
|
||||||
stack that is larger than zero.
|
stmt = IND{>} stmt ^+ IND{=} DED # list of statements
|
||||||
|
/ simpleStmt # or a simple statement
|
||||||
|
|
||||||
Because the grammar contains some optional ``IND`` tokens, the scanner cannot
|
|
||||||
push new indentation levels. This has to be done by the parser. The symbol
|
|
||||||
``indPush`` indicates that an ``IND`` token is expected; the current number of
|
|
||||||
leading spaces is pushed onto the stack by the parser. The symbol ``indPop``
|
|
||||||
denotes that the parser pops an item from the indentation stack. No token is
|
|
||||||
consumed by ``indPop``.
|
|
||||||
|
|
||||||
|
|
||||||
Comments
|
Comments
|
||||||
|
|
@ -416,8 +430,8 @@ and not the two tokens `{.`:tok:, `.}`:tok:.
|
||||||
Syntax
|
Syntax
|
||||||
======
|
======
|
||||||
|
|
||||||
This section lists Nimrod's standard syntax in ENBF. How the parser receives
|
This section lists Nimrod's standard syntax. How the parser handles
|
||||||
indentation tokens is already described in the `Lexical Analysis`_ section.
|
the indentation is already described in the `Lexical Analysis`_ section.
|
||||||
|
|
||||||
Nimrod allows user-definable operators.
|
Nimrod allows user-definable operators.
|
||||||
Binary operators have 10 different levels of precedence.
|
Binary operators have 10 different levels of precedence.
|
||||||
|
|
@ -1040,7 +1054,7 @@ an ``object`` type or a ``ref object`` type:
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
var student = TStudent(name: "Anton", age: 5, id: 3)
|
var student = TStudent(name: "Anton", age: 5, id: 3)
|
||||||
|
|
||||||
For a ``ref object`` type ``new`` is invoked implicitly.
|
For a ``ref object`` type ``system.new`` is invoked implicitly.
|
||||||
|
|
||||||
|
|
||||||
Object variants
|
Object variants
|
||||||
|
|
@ -1701,44 +1715,20 @@ Statements and expressions
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
Nimrod uses the common statement/expression paradigm: `Statements`:idx: do not
|
Nimrod uses the common statement/expression paradigm: `Statements`:idx: do not
|
||||||
produce a value in contrast to expressions. Call expressions are statements.
|
produce a value in contrast to expressions. However, some expressions are
|
||||||
If the called procedure returns a value, it is not a valid statement
|
statements.
|
||||||
as statements do not produce values. To evaluate an expression for
|
|
||||||
side-effects and throw its value away, one can use the ``discard`` statement.
|
|
||||||
|
|
||||||
Statements are separated into `simple statements`:idx: and
|
Statements are separated into `simple statements`:idx: and
|
||||||
`complex statements`:idx:.
|
`complex statements`:idx:.
|
||||||
Simple statements are statements that cannot contain other statements like
|
Simple statements are statements that cannot contain other statements like
|
||||||
assignments, calls or the ``return`` statement; complex statements can
|
assignments, calls or the ``return`` statement; complex statements can
|
||||||
contain other statements. To avoid the `dangling else problem`:idx:, complex
|
contain other statements. To avoid the `dangling else problem`:idx:, complex
|
||||||
statements always have to be intended::
|
statements always have to be intended. The details can be found in the grammar.
|
||||||
|
|
||||||
simpleStmt ::= returnStmt
|
|
||||||
| yieldStmt
|
|
||||||
| discardStmt
|
|
||||||
| raiseStmt
|
|
||||||
| breakStmt
|
|
||||||
| continueStmt
|
|
||||||
| pragma
|
|
||||||
| importStmt
|
|
||||||
| fromStmt
|
|
||||||
| includeStmt
|
|
||||||
| exprStmt
|
|
||||||
complexStmt ::= ifStmt | whileStmt | caseStmt | tryStmt | forStmt
|
|
||||||
| blockStmt | asmStmt
|
|
||||||
| procDecl | iteratorDecl | macroDecl | templateDecl
|
|
||||||
| constSection | letSection
|
|
||||||
| typeSection | whenStmt | varSection
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Discard statement
|
Discard statement
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
discardStmt ::= 'discard' expr
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
@ -1766,16 +1756,6 @@ been declared with the `discardable`:idx: pragma:
|
||||||
Var statement
|
Var statement
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
colonOrEquals ::= ':' typeDesc ['=' expr] | '=' expr
|
|
||||||
varField ::= symbol ['*'] [pragma]
|
|
||||||
varPart ::= symbol (comma symbol)* [comma] colonOrEquals [COMMENT | IND COMMENT]
|
|
||||||
varSection ::= 'var' (varPart
|
|
||||||
| indPush (COMMENT|varPart)
|
|
||||||
(SAD (COMMENT|varPart))* DED indPop)
|
|
||||||
|
|
||||||
|
|
||||||
`Var`:idx: statements declare new local and global variables and
|
`Var`:idx: statements declare new local and global variables and
|
||||||
initialize them. A comma separated list of variables can be used to specify
|
initialize them. A comma separated list of variables can be used to specify
|
||||||
variables of the same type:
|
variables of the same type:
|
||||||
|
|
@ -1839,14 +1819,6 @@ For let variables the same pragmas are available as for ordinary variables.
|
||||||
Const section
|
Const section
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
colonAndEquals ::= [':' typeDesc] '=' expr
|
|
||||||
|
|
||||||
constDecl ::= symbol ['*'] [pragma] colonAndEquals [COMMENT | IND COMMENT]
|
|
||||||
| COMMENT
|
|
||||||
constSection ::= 'const' indPush constDecl (SAD constDecl)* DED indPop
|
|
||||||
|
|
||||||
`Constants`:idx: are symbols which are bound to a value. The constant's value
|
`Constants`:idx: are symbols which are bound to a value. The constant's value
|
||||||
cannot change. The compiler must be able to evaluate the expression in a
|
cannot change. The compiler must be able to evaluate the expression in a
|
||||||
constant declaration at compile time.
|
constant declaration at compile time.
|
||||||
|
|
@ -1877,10 +1849,6 @@ they contain such a type.
|
||||||
Static statement/expression
|
Static statement/expression
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
staticExpr ::= 'static' '(' optInd expr optPar ')'
|
|
||||||
staticStmt ::= 'static' ':' stmt
|
|
||||||
|
|
||||||
A `static`:idx: statement/expression can be used to enforce compile
|
A `static`:idx: statement/expression can be used to enforce compile
|
||||||
time evaluation explicitly. Enforced compile time evaluation can even evaluate
|
time evaluation explicitly. Enforced compile time evaluation can even evaluate
|
||||||
code that has side effects:
|
code that has side effects:
|
||||||
|
|
@ -1902,10 +1870,6 @@ support the FFI at compile time.
|
||||||
If statement
|
If statement
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
ifStmt ::= 'if' expr ':' stmt ('elif' expr ':' stmt)* ['else' ':' stmt]
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
@ -1932,12 +1896,6 @@ part, execution continues with the statement after the ``if`` statement.
|
||||||
Case statement
|
Case statement
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
caseStmt ::= 'case' expr [':'] ('of' sliceExprList ':' stmt)*
|
|
||||||
('elif' expr ':' stmt)*
|
|
||||||
['else' ':' stmt]
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
@ -1998,10 +1956,6 @@ a list of its elements:
|
||||||
When statement
|
When statement
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
whenStmt ::= 'when' expr ':' stmt ('elif' expr ':' stmt)* ['else' ':' stmt]
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
@ -2032,10 +1986,6 @@ within ``object`` definitions.
|
||||||
Return statement
|
Return statement
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
returnStmt ::= 'return' [expr]
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
@ -2063,10 +2013,6 @@ variables, ``result`` is initialized to (binary) zero:
|
||||||
Yield statement
|
Yield statement
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
yieldStmt ::= 'yield' expr
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
@ -2083,10 +2029,6 @@ for further information.
|
||||||
Block statement
|
Block statement
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
blockStmt ::= 'block' [symbol] ':' stmt
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
@ -2108,10 +2050,6 @@ block to specify which block is to leave.
|
||||||
Break statement
|
Break statement
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
breakStmt ::= 'break' [symbol]
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
@ -2125,10 +2063,6 @@ absent, the innermost block is left.
|
||||||
While statement
|
While statement
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
whileStmt ::= 'while' expr ':' stmt
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
@ -2147,10 +2081,6 @@ so that they can be left with a ``break`` statement.
|
||||||
Continue statement
|
Continue statement
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
continueStmt ::= 'continue'
|
|
||||||
|
|
||||||
A `continue`:idx: statement leads to the immediate next iteration of the
|
A `continue`:idx: statement leads to the immediate next iteration of the
|
||||||
surrounding loop construct. It is only allowed within a loop. A continue
|
surrounding loop construct. It is only allowed within a loop. A continue
|
||||||
statement is syntactic sugar for a nested block:
|
statement is syntactic sugar for a nested block:
|
||||||
|
|
@ -2173,9 +2103,6 @@ Is equivalent to:
|
||||||
|
|
||||||
Assembler statement
|
Assembler statement
|
||||||
-------------------
|
-------------------
|
||||||
Syntax::
|
|
||||||
|
|
||||||
asmStmt ::= 'asm' [pragma] (STR_LIT | RSTR_LIT | TRIPLESTR_LIT)
|
|
||||||
|
|
||||||
The direct embedding of `assembler`:idx: code into Nimrod code is supported
|
The direct embedding of `assembler`:idx: code into Nimrod code is supported
|
||||||
by the unsafe ``asm`` statement. Identifiers in the assembler code that refer to
|
by the unsafe ``asm`` statement. Identifiers in the assembler code that refer to
|
||||||
|
|
@ -2203,8 +2130,7 @@ Example:
|
||||||
var y = if x > 8: 9 else: 10
|
var y = if x > 8: 9 else: 10
|
||||||
|
|
||||||
An if expression always results in a value, so the ``else`` part is
|
An if expression always results in a value, so the ``else`` part is
|
||||||
required. ``Elif`` parts are also allowed (but unlikely to be good
|
required. ``Elif`` parts are also allowed.
|
||||||
style).
|
|
||||||
|
|
||||||
When expression
|
When expression
|
||||||
---------------
|
---------------
|
||||||
|
|
@ -2311,18 +2237,8 @@ procedure declaration defines an identifier and associates it with a block
|
||||||
of code.
|
of code.
|
||||||
A procedure may call itself recursively. A parameter may be given a default
|
A procedure may call itself recursively. A parameter may be given a default
|
||||||
value that is used if the caller does not provide a value for this parameter.
|
value that is used if the caller does not provide a value for this parameter.
|
||||||
The syntax is::
|
|
||||||
|
|
||||||
param ::= symbol (comma symbol)* (':' typeDesc ['=' expr] | '=' expr)
|
If the proc declaration has no body, it is a `forward`:idx: declaration. If
|
||||||
paramList ::= ['(' [param (comma param)*] [SAD] ')'] [':' typeDesc]
|
|
||||||
|
|
||||||
genericParam ::= symbol [':' typeDesc] ['=' expr]
|
|
||||||
genericParams ::= '[' genericParam (comma genericParam)* [SAD] ']'
|
|
||||||
|
|
||||||
procDecl ::= 'proc' symbol ['*'] [genericParams] paramList [pragma]
|
|
||||||
['=' stmt]
|
|
||||||
|
|
||||||
If the ``= stmt`` part is missing, it is a `forward`:idx: declaration. If
|
|
||||||
the proc returns a value, the procedure body can access an implicitly declared
|
the proc returns a value, the procedure body can access an implicitly declared
|
||||||
variable named `result`:idx: that represents the return value. Procs can be
|
variable named `result`:idx: that represents the return value. Procs can be
|
||||||
overloaded. The overloading resolution algorithm tries to find the proc that is
|
overloaded. The overloading resolution algorithm tries to find the proc that is
|
||||||
|
|
@ -2417,24 +2333,14 @@ Do notation
|
||||||
As a special more convenient notation, proc expressions involved in procedure
|
As a special more convenient notation, proc expressions involved in procedure
|
||||||
calls can use the ``do`` keyword:
|
calls can use the ``do`` keyword:
|
||||||
|
|
||||||
Syntax::
|
|
||||||
primarySuffix ::= 'do' ['(' namedExprList ')'] ['->' typeDesc] ':'
|
|
||||||
|
|
||||||
As a start, let's repeat the example from the previous section:
|
|
||||||
|
|
||||||
.. code-block:: nimrod
|
|
||||||
cities.sort do (x,y: string) -> int:
|
|
||||||
cmp(x.len, y.len)
|
|
||||||
|
|
||||||
``do`` is written after the parentheses enclosing the regular proc params.
|
|
||||||
The proc expression represented by the do block is appended to them.
|
|
||||||
Again, let's see the equivalent of the previous example:
|
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
sort(cities) do (x,y: string) -> int:
|
sort(cities) do (x,y: string) -> int:
|
||||||
cmp(x.len, y.len)
|
cmp(x.len, y.len)
|
||||||
|
|
||||||
Finally, more than one ``do`` block can appear in a single call:
|
``do`` is written after the parentheses enclosing the regular proc params.
|
||||||
|
The proc expression represented by the do block is appended to them.
|
||||||
|
|
||||||
|
More than one ``do`` block can appear in a single call:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
proc performWithUndo(task: proc(), undo: proc()) = ...
|
proc performWithUndo(task: proc(), undo: proc()) = ...
|
||||||
|
|
@ -2635,30 +2541,16 @@ evaluation or dead code elimination do not work with methods.
|
||||||
Iterators and the for statement
|
Iterators and the for statement
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
forStmt ::= 'for' symbol (comma symbol)* [comma] 'in' expr ':' stmt
|
|
||||||
|
|
||||||
param ::= symbol (comma symbol)* [comma] ':' typeDesc
|
|
||||||
paramList ::= ['(' [param (comma param)* [comma]] ')'] [':' typeDesc]
|
|
||||||
|
|
||||||
genericParam ::= symbol [':' typeDesc]
|
|
||||||
genericParams ::= '[' genericParam (comma genericParam)* [comma] ']'
|
|
||||||
|
|
||||||
iteratorDecl ::= 'iterator' symbol ['*'] [genericParams] paramList [pragma]
|
|
||||||
['=' stmt]
|
|
||||||
|
|
||||||
The `for`:idx: statement is an abstract mechanism to iterate over the elements
|
The `for`:idx: statement is an abstract mechanism to iterate over the elements
|
||||||
of a container. It relies on an `iterator`:idx: to do so. Like ``while``
|
of a container. It relies on an `iterator`:idx: to do so. Like ``while``
|
||||||
statements, ``for`` statements open an `implicit block`:idx:, so that they
|
statements, ``for`` statements open an `implicit block`:idx:, so that they
|
||||||
can be left with a ``break`` statement.
|
can be left with a ``break`` statement.
|
||||||
|
|
||||||
The ``for`` loop declares
|
The ``for`` loop declares iteration variables - their scope reaches until the
|
||||||
iteration variables (``x`` in the example) - their scope reaches until the
|
|
||||||
end of the loop body. The iteration variables' types are inferred by the
|
end of the loop body. The iteration variables' types are inferred by the
|
||||||
return type of the iterator.
|
return type of the iterator.
|
||||||
|
|
||||||
An iterator is similar to a procedure, except that it is always called in the
|
An iterator is similar to a procedure, except that it can be called in the
|
||||||
context of a ``for`` loop. Iterators provide a way to specify the iteration over
|
context of a ``for`` loop. Iterators provide a way to specify the iteration over
|
||||||
an abstract type. A key role in the execution of a ``for`` loop plays the
|
an abstract type. A key role in the execution of a ``for`` loop plays the
|
||||||
``yield`` statement in the called iterator. Whenever a ``yield`` statement is
|
``yield`` statement in the called iterator. Whenever a ``yield`` statement is
|
||||||
|
|
@ -2686,9 +2578,10 @@ The compiler generates code as if the programmer would have written this:
|
||||||
echo(ch)
|
echo(ch)
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
||||||
If the iterator yields a tuple, there have to be as many iteration variables
|
If the iterator yields a tuple, there can be as many iteration variables
|
||||||
as there are components in the tuple. The i'th iteration variable's type is
|
as there are components in the tuple. The i'th iteration variable's type is
|
||||||
the type of the i'th component.
|
the type of the i'th component. In other words, implicit tuple unpacking in a
|
||||||
|
for loop context is supported.
|
||||||
|
|
||||||
|
|
||||||
Implict items/pairs invocations
|
Implict items/pairs invocations
|
||||||
|
|
@ -2792,23 +2685,10 @@ iterator that has already finished its work.
|
||||||
Type sections
|
Type sections
|
||||||
=============
|
=============
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
typeDef ::= typeDesc | objectDef | enumDef
|
|
||||||
|
|
||||||
genericParam ::= symbol [':' typeDesc]
|
|
||||||
genericParams ::= '[' genericParam (comma genericParam)* [comma] ']'
|
|
||||||
|
|
||||||
typeDecl ::= COMMENT
|
|
||||||
| symbol ['*'] [genericParams] ['=' typeDef] [COMMENT|IND COMMENT]
|
|
||||||
|
|
||||||
typeSection ::= 'type' indPush typeDecl (SAD typeDecl)* DED indPop
|
|
||||||
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
type # example demonstrates mutually recursive types
|
type # example demonstrating mutually recursive types
|
||||||
PNode = ref TNode # a traced pointer to a TNode
|
PNode = ref TNode # a traced pointer to a TNode
|
||||||
TNode = object
|
TNode = object
|
||||||
le, ri: PNode # left and right subtrees
|
le, ri: PNode # left and right subtrees
|
||||||
|
|
@ -2822,7 +2702,8 @@ Example:
|
||||||
A `type`:idx: section begins with the ``type`` keyword. It contains multiple
|
A `type`:idx: section begins with the ``type`` keyword. It contains multiple
|
||||||
type definitions. A type definition binds a type to a name. Type definitions
|
type definitions. A type definition binds a type to a name. Type definitions
|
||||||
can be recursive or even mutually recursive. Mutually recursive types are only
|
can be recursive or even mutually recursive. Mutually recursive types are only
|
||||||
possible within a single ``type`` section.
|
possible within a single ``type`` section. Nominal types like ``objects``
|
||||||
|
or ``enums`` can only be defined in a ``type`` section.
|
||||||
|
|
||||||
|
|
||||||
Exception handling
|
Exception handling
|
||||||
|
|
@ -2831,14 +2712,6 @@ Exception handling
|
||||||
Try statement
|
Try statement
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
qualifiedIdent ::= symbol ['.' symbol]
|
|
||||||
exceptList ::= [qualifiedIdent (comma qualifiedIdent)* [comma]]
|
|
||||||
tryStmt ::= 'try' ':' stmt
|
|
||||||
('except' exceptList ':' stmt)*
|
|
||||||
['finally' ':' stmt]
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
@ -2863,15 +2736,14 @@ Example:
|
||||||
close(f)
|
close(f)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
The statements after the `try`:idx: are executed in sequential order unless
|
The statements after the `try`:idx: are executed in sequential order unless
|
||||||
an exception ``e`` is raised. If the exception type of ``e`` matches any
|
an exception ``e`` is raised. If the exception type of ``e`` matches any
|
||||||
of the list ``exceptlist`` the corresponding statements are executed.
|
listed in an ``except`` clause the corresponding statements are executed.
|
||||||
The statements following the ``except`` clauses are called
|
The statements following the ``except`` clauses are called
|
||||||
`exception handlers`:idx:.
|
`exception handlers`:idx:.
|
||||||
|
|
||||||
The empty `except`:idx: clause is executed if there is an exception that is
|
The empty `except`:idx: clause is executed if there is an exception that is
|
||||||
in no list. It is similar to an ``else`` clause in ``if`` statements.
|
not listed otherwise. It is similar to an ``else`` clause in ``if`` statements.
|
||||||
|
|
||||||
If there is a `finally`:idx: clause, it is always executed after the
|
If there is a `finally`:idx: clause, it is always executed after the
|
||||||
exception handlers.
|
exception handlers.
|
||||||
|
|
@ -2916,10 +2788,6 @@ statements. Example:
|
||||||
Raise statement
|
Raise statement
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
raiseStmt ::= 'raise' [expr]
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
@ -2948,17 +2816,21 @@ This allows for a Lisp-like `condition system`:idx:\:
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
var myFile = open("broken.txt", fmWrite)
|
var myFile = open("broken.txt", fmWrite)
|
||||||
try:
|
try:
|
||||||
onRaise(proc (e: ref E_Base): bool =
|
onRaise do (e: ref E_Base)-> bool:
|
||||||
if e of EIO:
|
if e of EIO:
|
||||||
stdout.writeln "ok, writing to stdout instead"
|
stdout.writeln "ok, writing to stdout instead"
|
||||||
else:
|
else:
|
||||||
# do raise other exceptions:
|
# do raise other exceptions:
|
||||||
result = true
|
result = true
|
||||||
)
|
|
||||||
myFile.writeln "writing to broken file"
|
myFile.writeln "writing to broken file"
|
||||||
finally:
|
finally:
|
||||||
myFile.close()
|
myFile.close()
|
||||||
|
|
||||||
|
``OnRaise`` can only *filter* raised exceptions, it cannot transform one
|
||||||
|
exception into another. (Nor should ``onRaise`` raise an exception though
|
||||||
|
this is currently not enforced.) This restriction keeps the exception tracking
|
||||||
|
analysis sound.
|
||||||
|
|
||||||
|
|
||||||
Effect system
|
Effect system
|
||||||
=============
|
=============
|
||||||
|
|
@ -3447,10 +3319,6 @@ Symbol binding within templates happens after template instantiation:
|
||||||
Bind statement
|
Bind statement
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
bindStmt ::= 'bind' IDENT (comma IDENT)*
|
|
||||||
|
|
||||||
Exporting a template is a often a leaky abstraction as it can depend on
|
Exporting a template is a often a leaky abstraction as it can depend on
|
||||||
symbols that are not visible from a client module. However, to compensate for
|
symbols that are not visible from a client module. However, to compensate for
|
||||||
this case, a `bind`:idx: statement can be used: It declares all identifiers
|
this case, a `bind`:idx: statement can be used: It declares all identifiers
|
||||||
|
|
@ -3715,18 +3583,11 @@ Statement Macros
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Statement macros are defined just as expression macros. However, they are
|
Statement macros are defined just as expression macros. However, they are
|
||||||
invoked by an expression following a colon::
|
invoked by an expression following a colon.
|
||||||
|
|
||||||
exprStmt ::= lowestExpr ['=' expr | [expr (comma expr)* [comma]] [macroStmt]]
|
|
||||||
macroStmt ::= ':' [stmt] ('of' [sliceExprList] ':' stmt
|
|
||||||
| 'elif' expr ':' stmt
|
|
||||||
| 'except' exceptList ':' stmt )*
|
|
||||||
['else' ':' stmt]
|
|
||||||
|
|
||||||
The following example outlines a macro that generates a lexical analyzer from
|
The following example outlines a macro that generates a lexical analyzer from
|
||||||
regular expressions:
|
regular expressions:
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
import macros
|
import macros
|
||||||
|
|
||||||
|
|
@ -3799,7 +3660,7 @@ instantiation type using the param name:
|
||||||
var tree = new(TBinaryTree[int])
|
var tree = new(TBinaryTree[int])
|
||||||
|
|
||||||
When used with macros and .compileTime. procs on the other hand, the compiler
|
When used with macros and .compileTime. procs on the other hand, the compiler
|
||||||
don't need to instantiate the code multiple times, because types then can be
|
does not need to instantiate the code multiple times, because types then can be
|
||||||
manipulated using the unified internal symbol representation. In such context
|
manipulated using the unified internal symbol representation. In such context
|
||||||
typedesc acts as any other type. One can create variables, store typedesc
|
typedesc acts as any other type. One can create variables, store typedesc
|
||||||
values inside containers and so on. For example, here is how one can create
|
values inside containers and so on. For example, here is how one can create
|
||||||
|
|
@ -4358,13 +4219,6 @@ the compiler encounters any static error.
|
||||||
Pragmas
|
Pragmas
|
||||||
=======
|
=======
|
||||||
|
|
||||||
Syntax::
|
|
||||||
|
|
||||||
colonExpr ::= expr [':' expr]
|
|
||||||
colonExprList ::= [colonExpr (comma colonExpr)* [comma]]
|
|
||||||
|
|
||||||
pragma ::= '{.' optInd (colonExpr [comma])* [SAD] ('.}' | '}')
|
|
||||||
|
|
||||||
Pragmas are Nimrod's method to give the compiler additional information /
|
Pragmas are Nimrod's method to give the compiler additional information /
|
||||||
commands without introducing a massive number of new keywords. Pragmas are
|
commands without introducing a massive number of new keywords. Pragmas are
|
||||||
processed on the fly during semantic checking. Pragmas are enclosed in the
|
processed on the fly during semantic checking. Pragmas are enclosed in the
|
||||||
|
|
@ -4411,7 +4265,7 @@ calls to any base class destructors in both user-defined and generated
|
||||||
destructors.
|
destructors.
|
||||||
|
|
||||||
A destructor is attached to the type it destructs; expressions of this type
|
A destructor is attached to the type it destructs; expressions of this type
|
||||||
can then only be used in *destructible contexts*:
|
can then only be used in *destructible contexts* and as parameters:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
type
|
type
|
||||||
|
|
@ -4425,9 +4279,15 @@ can then only be used in *destructible contexts*:
|
||||||
proc open: TMyObj =
|
proc open: TMyObj =
|
||||||
result = TMyObj(x: 1, y: 2, p: alloc(3))
|
result = TMyObj(x: 1, y: 2, p: alloc(3))
|
||||||
|
|
||||||
|
proc work(o: TMyObj) =
|
||||||
|
echo o.x
|
||||||
|
# No destructor invoked here for 'o' as 'o' is a parameter.
|
||||||
|
|
||||||
proc main() =
|
proc main() =
|
||||||
# destructor automatically invoked at the end of the scope:
|
# destructor automatically invoked at the end of the scope:
|
||||||
var x = open()
|
var x = open()
|
||||||
|
# valid: pass 'x' to some other proc:
|
||||||
|
work(x)
|
||||||
|
|
||||||
# Error: usage of a type with a destructor in a non destructible context
|
# Error: usage of a type with a destructor in a non destructible context
|
||||||
echo open()
|
echo open()
|
||||||
|
|
@ -4849,8 +4709,8 @@ a dynamic library (``.dll`` files for Windows, ``lib*.so`` files for UNIX).
|
||||||
The non-optional argument has to be the name of the dynamic library:
|
The non-optional argument has to be the name of the dynamic library:
|
||||||
|
|
||||||
.. code-block:: Nimrod
|
.. code-block:: Nimrod
|
||||||
proc gtk_image_new(): PGtkWidget {.
|
proc gtk_image_new(): PGtkWidget
|
||||||
cdecl, dynlib: "libgtk-x11-2.0.so", importc.}
|
{.cdecl, dynlib: "libgtk-x11-2.0.so", importc.}
|
||||||
|
|
||||||
In general, importing a dynamic library does not require any special linker
|
In general, importing a dynamic library does not require any special linker
|
||||||
options or linking with import libraries. This also implies that no *devel*
|
options or linking with import libraries. This also implies that no *devel*
|
||||||
|
|
@ -4894,6 +4754,10 @@ strings, because they are precompiled.
|
||||||
**Note**: Passing variables to the ``dynlib`` pragma will fail at runtime
|
**Note**: Passing variables to the ``dynlib`` pragma will fail at runtime
|
||||||
because of order of initialization problems.
|
because of order of initialization problems.
|
||||||
|
|
||||||
|
**Note**: A ``dynlib`` import can be overriden with
|
||||||
|
the ``--dynlibOverride:name`` command line option. The Compiler User Guide
|
||||||
|
contains further information.
|
||||||
|
|
||||||
|
|
||||||
Dynlib pragma for export
|
Dynlib pragma for export
|
||||||
------------------------
|
------------------------
|
||||||
|
|
@ -4971,7 +4835,7 @@ Nimrod supports the `actor model`:idx: of concurrency natively:
|
||||||
type
|
type
|
||||||
TMsgKind = enum
|
TMsgKind = enum
|
||||||
mLine, mEof
|
mLine, mEof
|
||||||
TMsg = object {.pure, final.}
|
TMsg = object
|
||||||
case k: TMsgKind
|
case k: TMsgKind
|
||||||
of mEof: nil
|
of mEof: nil
|
||||||
of mLine: data: string
|
of mLine: data: string
|
||||||
|
|
|
||||||
15
todo.txt
15
todo.txt
|
|
@ -10,10 +10,8 @@ version 0.9.2
|
||||||
- parser/grammar: enforce 'simpleExpr' more often --> doesn't work; tkProc is
|
- parser/grammar: enforce 'simpleExpr' more often --> doesn't work; tkProc is
|
||||||
part of primary!
|
part of primary!
|
||||||
* check that of branches can only receive even simpler expressions, don't
|
* check that of branches can only receive even simpler expressions, don't
|
||||||
allow of (var x = 23; nkIdent)
|
allow 'of (var x = 23; nkIdent)'
|
||||||
* document the new grammar: ^+ ^* operators; indentation handling
|
* bugfix: 'import x var y = 0' compiles
|
||||||
* remove rules in the manual as it's too hard to keep it up to date
|
|
||||||
* improve rules to contain the AST structure
|
|
||||||
* the typeDesc/expr unification is weird and only necessary because of
|
* the typeDesc/expr unification is weird and only necessary because of
|
||||||
the ambiguous a[T] construct: It would be easy to support a[expr] for
|
the ambiguous a[T] construct: It would be easy to support a[expr] for
|
||||||
generics but require a[.typeDesc] if that's required; this would also
|
generics but require a[.typeDesc] if that's required; this would also
|
||||||
|
|
@ -48,7 +46,7 @@ version 0.9.4
|
||||||
- implement full 'not nil' checking
|
- implement full 'not nil' checking
|
||||||
- make 'bind' default for templates and introduce 'mixin';
|
- make 'bind' default for templates and introduce 'mixin';
|
||||||
special rule for ``[]=``
|
special rule for ``[]=``
|
||||||
- implicit deref for parameter matching; overloading based on 'var T'
|
- implicit deref for parameter matching
|
||||||
- ``=`` should be overloadable; requires specialization for ``=``; general
|
- ``=`` should be overloadable; requires specialization for ``=``; general
|
||||||
lift mechanism in the compiler is already implemented for 'fields'
|
lift mechanism in the compiler is already implemented for 'fields'
|
||||||
- lazy overloading resolution:
|
- lazy overloading resolution:
|
||||||
|
|
@ -66,9 +64,7 @@ version 0.9.X
|
||||||
- improve the compiler as a service
|
- improve the compiler as a service
|
||||||
- better support for macros that rewrite procs
|
- better support for macros that rewrite procs
|
||||||
- macros need access to types and symbols (partially implemented)
|
- macros need access to types and symbols (partially implemented)
|
||||||
- rethink the syntax/grammar:
|
- perhaps: change comment handling in the AST
|
||||||
* parser is not strict enough with newlines
|
|
||||||
* change comment handling in the AST
|
|
||||||
|
|
||||||
|
|
||||||
Concurrency
|
Concurrency
|
||||||
|
|
@ -108,7 +104,8 @@ Not essential for 1.0.0
|
||||||
- mocking support with ``tyProxy`` that does: fallback for ``.`` operator
|
- mocking support with ``tyProxy`` that does: fallback for ``.`` operator
|
||||||
- overloading of ``.``? Special case ``.=``?
|
- overloading of ``.``? Special case ``.=``?
|
||||||
- allow implicit forward declarations of procs via a pragma (so that the
|
- allow implicit forward declarations of procs via a pragma (so that the
|
||||||
wrappers can deactivate it)
|
wrappers can deactivate it): better solution: introduce the notion of a
|
||||||
|
'proc section' that is similar to a type section.
|
||||||
- implement the "snoopResult" pragma; no, make a strutils with string append
|
- implement the "snoopResult" pragma; no, make a strutils with string append
|
||||||
semantics instead ...
|
semantics instead ...
|
||||||
- implement "closure tuple consists of a single 'ref'" optimization
|
- implement "closure tuple consists of a single 'ref'" optimization
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue