mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-18 21:40:32 +00:00
implemented 'static'; macros do not work anymore
This commit is contained in:
@@ -105,6 +105,7 @@ type
|
||||
nkHiddenCallConv, # an implicit type conversion via a type converter
|
||||
nkConv, # a type conversion
|
||||
nkCast, # a type cast
|
||||
nkStaticExpr, # a static expr
|
||||
nkAddr, # a addr expression
|
||||
nkHiddenAddr, # implicit address operator
|
||||
nkHiddenDeref, # implicit ^ operator
|
||||
@@ -160,6 +161,7 @@ type
|
||||
nkBreakStmt, # a break statement
|
||||
nkContinueStmt, # a continue statement
|
||||
nkBlockStmt, # a block statement
|
||||
nkStaticStmt, # a static statement
|
||||
nkDiscardStmt, # a discard statement
|
||||
nkStmtList, # a list of statements
|
||||
nkImportStmt, # an import statement
|
||||
@@ -384,7 +386,7 @@ type
|
||||
mOrdinal, mInt, mInt8, mInt16, mInt32,
|
||||
mInt64, mFloat, mFloat32, mFloat64, mBool, mChar, mString, mCstring,
|
||||
mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc,
|
||||
mVoidType,
|
||||
mVoidType, mPNimrodNode,
|
||||
mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor,
|
||||
mNimrodMinor, mNimrodPatch, mCpuEndian, mHostOS, mHostCPU, mAppType,
|
||||
mNaN, mInf, mNegInf,
|
||||
|
||||
@@ -39,7 +39,8 @@ type
|
||||
tkGeneric, tkIf, tkImport, tkIn, tkInclude, tkIs, tkIsnot, tkIterator,
|
||||
tkLambda, tkLet,
|
||||
tkMacro, tkMethod, tkMod, tkNil, tkNot, tkNotin, tkObject, tkOf, tkOr,
|
||||
tkOut, tkProc, tkPtr, tkRaise, tkRef, tkReturn, tkShl, tkShr, tkTemplate,
|
||||
tkOut, tkProc, tkPtr, tkRaise, tkRef, tkReturn, tkShl, tkShr, tkStatic,
|
||||
tkTemplate,
|
||||
tkTry, tkTuple, tkType, tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor,
|
||||
tkYield, # end of keywords
|
||||
tkIntLit, tkInt8Lit, tkInt16Lit, tkInt32Lit, tkInt64Lit, tkFloatLit,
|
||||
@@ -70,7 +71,8 @@ const
|
||||
"import", "in", "include", "is", "isnot", "iterator",
|
||||
"lambda", "let",
|
||||
"macro", "method", "mod", "nil", "not", "notin", "object", "of", "or",
|
||||
"out", "proc", "ptr", "raise", "ref", "return", "shl", "shr", "template",
|
||||
"out", "proc", "ptr", "raise", "ref", "return", "shl", "shr", "static",
|
||||
"template",
|
||||
"try", "tuple", "type", "var", "when", "while", "with", "without", "xor",
|
||||
"yield",
|
||||
"tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit",
|
||||
|
||||
@@ -436,8 +436,6 @@ proc identOrLiteral(p: var TParser): PNode =
|
||||
tkColon)
|
||||
of tkCast:
|
||||
result = parseCast(p)
|
||||
of tkAddr:
|
||||
result = parseAddr(p)
|
||||
else:
|
||||
parMessage(p, errExprExpected, p.tok)
|
||||
getTok(p) # we must consume a token here to prevend endless loops!
|
||||
@@ -453,6 +451,16 @@ proc primary(p: var TParser): PNode =
|
||||
optInd(p, a)
|
||||
addSon(result, primary(p))
|
||||
return
|
||||
elif p.tok.tokType == tkAddr:
|
||||
result = newNodeP(nkAddr, p)
|
||||
getTok(p)
|
||||
addSon(result, primary(p))
|
||||
return
|
||||
elif p.tok.tokType == tkStatic:
|
||||
result = newNodeP(nkStaticExpr, p)
|
||||
getTok(p)
|
||||
addSon(result, primary(p))
|
||||
return
|
||||
elif p.tok.tokType == tkBind:
|
||||
result = newNodeP(nkBind, p)
|
||||
getTok(p)
|
||||
@@ -980,6 +988,14 @@ proc parseBlock(p: var TParser): PNode =
|
||||
skipComment(p, result)
|
||||
addSon(result, parseStmt(p))
|
||||
|
||||
proc parseStatic(p: var TParser): PNode =
|
||||
result = newNodeP(nkStaticStmt, p)
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
eat(p, tkColon)
|
||||
skipComment(p, result)
|
||||
addSon(result, parseStmt(p))
|
||||
|
||||
proc parseAsm(p: var TParser): PNode =
|
||||
result = newNodeP(nkAsmStmt, p)
|
||||
getTok(p)
|
||||
@@ -1379,6 +1395,7 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
|
||||
of tkTry: result = parseTry(p)
|
||||
of tkFor: result = parseFor(p)
|
||||
of tkBlock: result = parseBlock(p)
|
||||
of tkStatic: result = parseStatic(p)
|
||||
of tkAsm: result = parseAsm(p)
|
||||
of tkProc: result = parseRoutine(p, nkProcDef)
|
||||
of tkMethod: result = parseRoutine(p, nkMethodDef)
|
||||
|
||||
@@ -336,6 +336,7 @@ proc lsub(n: PNode): int =
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: result = lsub(n[1])
|
||||
of nkCast: result = lsub(n.sons[0]) + lsub(n.sons[1]) + len("cast[]()")
|
||||
of nkAddr: result = lsub(n.sons[0]) + len("addr()")
|
||||
of nkStaticExpr: result = lsub(n.sons[0]) + len("static_")
|
||||
of nkHiddenAddr, nkHiddenDeref: result = lsub(n.sons[0])
|
||||
of nkCommand: result = lsub(n.sons[0]) + lcomma(n, 1) + 1
|
||||
of nkExprEqExpr, nkAsgn, nkFastAsgn: result = lsons(n) + 3
|
||||
@@ -640,6 +641,16 @@ proc gblock(g: var TSrcGen, n: PNode) =
|
||||
gstmts(g, n.sons[1], c)
|
||||
dedent(g)
|
||||
|
||||
proc gstaticStmt(g: var TSrcGen, n: PNode) =
|
||||
var c: TContext
|
||||
putWithSpace(g, tkStatic, "static")
|
||||
putWithSpace(g, tkColon, ":")
|
||||
initContext(c)
|
||||
if longMode(n) or (lsub(n.sons[0]) + g.lineLen > maxLineLen):
|
||||
incl(c.flags, rfLongMode)
|
||||
gcoms(g) # a good place for comments
|
||||
gstmts(g, n.sons[0], c)
|
||||
|
||||
proc gasm(g: var TSrcGen, n: PNode) =
|
||||
putWithSpace(g, tkAsm, "asm")
|
||||
gsub(g, n.sons[0])
|
||||
@@ -711,6 +722,10 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
put(g, tkParLe, "(")
|
||||
gsub(g, n.sons[0])
|
||||
put(g, tkParRi, ")")
|
||||
of nkStaticExpr:
|
||||
put(g, tkStatic, "static")
|
||||
put(g, tkSpaces, space)
|
||||
gsub(g, n.sons[0])
|
||||
of nkBracketExpr:
|
||||
gsub(g, n.sons[0])
|
||||
put(g, tkBracketLe, "[")
|
||||
@@ -951,6 +966,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
of nkTryStmt: gtry(g, n)
|
||||
of nkForStmt: gfor(g, n)
|
||||
of nkBlockStmt, nkBlockExpr: gblock(g, n)
|
||||
of nkStaticStmt: gstaticStmt(g, n)
|
||||
of nkAsmStmt: gasm(g, n)
|
||||
of nkProcDef:
|
||||
putWithSpace(g, tkProc, "proc")
|
||||
|
||||
@@ -483,7 +483,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
||||
if {sfNoSideEffect, sfCompileTime} * callee.flags != {} and
|
||||
{sfForward, sfImportc} * callee.flags == {}:
|
||||
if sfCompileTime notin callee.flags and
|
||||
optImplicitCompileTime notin gOptions: return
|
||||
optImplicitStatic notin gOptions: return
|
||||
|
||||
if callee.magic notin ctfeWhitelist: return
|
||||
if callee.kind notin {skProc, skConverter} or callee.isGenericRoutine:
|
||||
@@ -508,6 +508,12 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
||||
#if result != n:
|
||||
# echo "SUCCESS evaluated at compile time: ", call.renderTree
|
||||
|
||||
proc semStaticExpr(c: PContext, n: PNode): PNode =
|
||||
let a = semExpr(c, n.sons[0])
|
||||
result = evalStaticExpr(c.module, a)
|
||||
if result.isNil:
|
||||
LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
|
||||
|
||||
proc semDirectCallAnalyseEffects(c: PContext, n: PNode,
|
||||
flags: TExprFlags): PNode =
|
||||
if efWantIterator in flags:
|
||||
@@ -1342,6 +1348,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
result = semTableConstr(c, n)
|
||||
of nkSymChoice:
|
||||
GlobalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
|
||||
of nkStaticExpr:
|
||||
result = semStaticExpr(c, n)
|
||||
else:
|
||||
GlobalError(n.info, errInvalidExpressionX,
|
||||
renderTree(n, {renderNoComments}))
|
||||
|
||||
@@ -840,6 +840,12 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode =
|
||||
if whichPragma(pragmaList.sons[i]) == wLine:
|
||||
setLine(result, pragmaList.sons[i].info)
|
||||
|
||||
proc semStaticStmt(c: PContext, n: PNode): PNode =
|
||||
let a = semStmt(c, n.sons[0])
|
||||
result = evalStaticExpr(c.module, a)
|
||||
if result.isNil:
|
||||
LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
|
||||
|
||||
proc SemStmt(c: PContext, n: PNode): PNode =
|
||||
const # must be last statements in a block:
|
||||
LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
|
||||
@@ -896,6 +902,8 @@ proc SemStmt(c: PContext, n: PNode): PNode =
|
||||
result = evalInclude(c, n)
|
||||
of nkPragmaBlock:
|
||||
result = semPragmaBlock(c, n)
|
||||
of nkStaticStmt:
|
||||
result = semStaticStmt(c, n)
|
||||
else:
|
||||
# in interactive mode, we embed the expression in an 'echo':
|
||||
if gCmd == cmdInteractive:
|
||||
|
||||
@@ -4,7 +4,7 @@ comma ::= ',' [COMMENT] [IND]
|
||||
operator ::= OP0 | OP1 | OP2 | OP3 | OP4 | OP5 | OP6 | OP7 | OP8 | OP9
|
||||
| 'or' | 'xor' | 'and'
|
||||
| 'is' | 'isnot' | 'in' | 'notin' | 'of'
|
||||
| 'div' | 'mod' | 'shl' | 'shr' | 'not' | '..'
|
||||
| 'div' | 'mod' | 'shl' | 'shr' | 'not' | 'addr' | 'static' | '..'
|
||||
|
||||
prefixOperator ::= operator
|
||||
|
||||
@@ -25,8 +25,6 @@ dollarExpr ::= primary (OP9 optInd primary)*
|
||||
indexExpr ::= expr
|
||||
|
||||
castExpr ::= 'cast' '[' optInd typeDesc optPar ']' '(' optInd expr optPar ')'
|
||||
addrExpr ::= 'addr' '(' optInd expr optPar ')'
|
||||
staticExpr ::= 'static' '(' optInd expr optPar ')'
|
||||
symbol ::= '`' (KEYWORD | IDENT | operator | '(' ')' | '[' ']' | '{' '}'
|
||||
| '=' | literal)+ '`'
|
||||
| IDENT
|
||||
@@ -38,7 +36,7 @@ primarySuffix ::= '.' optInd symbol [generalizedLit]
|
||||
| '{' optInd [indexExpr (comma indexExpr)* [comma]] optPar '}'
|
||||
|
||||
primary ::= primaryPrefix* (symbol [generalizedLit] |
|
||||
constructor | castExpr | addrExpr | staticExpr)
|
||||
constructor | castExpr)
|
||||
primarySuffix*
|
||||
|
||||
generalizedLit ::= GENERALIZED_STR_LIT | GENERALIZED_TRIPLESTR_LIT
|
||||
|
||||
@@ -27,7 +27,7 @@ type
|
||||
nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
|
||||
nnkElifExpr, nnkElseExpr, nnkLambda, nnkDo, nnkAccQuoted,
|
||||
nnkTableConstr, nnkBind, nnkSymChoice, nnkHiddenStdConv,
|
||||
nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast,
|
||||
nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast, nnkStaticExpr,
|
||||
nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv,
|
||||
nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange,
|
||||
nnkStringToCString, nnkCStringToString, nnkAsgn,
|
||||
@@ -40,7 +40,7 @@ type
|
||||
nnkTypeSection, nnkVarSection, nnkLetSection, nnkConstSection,
|
||||
nnkConstDef, nnkTypeDef,
|
||||
nnkYieldStmt, nnkTryStmt, nnkFinally, nnkRaiseStmt,
|
||||
nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt,
|
||||
nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkStaticStmt,
|
||||
nnkDiscardStmt, nnkStmtList, nnkImportStmt, nnkFromStmt,
|
||||
nnkIncludeStmt, nnkBindStmt,
|
||||
nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr,
|
||||
@@ -88,7 +88,7 @@ type
|
||||
## *ident*.
|
||||
|
||||
TNimrodNode {.final.} = object
|
||||
PNimrodNode* = ref TNimrodNode
|
||||
PNimrodNode* {.magic: "PNimrodNode".} = ref TNimrodNode
|
||||
## represents a Nimrod AST node. Macros operate on this type.
|
||||
|
||||
const
|
||||
@@ -263,7 +263,7 @@ proc newCall*(theProc: string,
|
||||
proc nestList*(theProc: TNimrodIdent,
|
||||
x: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
## nests the list `x` into a tree of call expressions:
|
||||
## ``[a, b, c]`` is transformed into ``theProc(a, theProc(c, d))``
|
||||
## ``[a, b, c]`` is transformed into ``theProc(a, theProc(c, d))``.
|
||||
var L = x.len
|
||||
result = newCall(theProc, x[L-2], x[L-1])
|
||||
var a = result
|
||||
@@ -271,9 +271,9 @@ proc nestList*(theProc: TNimrodIdent,
|
||||
a = newCall(theProc, x[i], copyNimTree(a))
|
||||
|
||||
proc treeRepr*(n: PNimrodNode): string {.compileTime.} =
|
||||
## Convert the AST `n` to a human-readable tree-like string
|
||||
## Convert the AST `n` to a human-readable tree-like string.
|
||||
##
|
||||
## see also `repr` and `lispRepr`
|
||||
## See also `repr` and `lispRepr`.
|
||||
|
||||
proc traverse(res: var string, level: int, n: PNimrodNode) =
|
||||
for i in 0..level-1: res.add " "
|
||||
@@ -300,9 +300,9 @@ proc treeRepr*(n: PNimrodNode): string {.compileTime.} =
|
||||
traverse(result, 0, n)
|
||||
|
||||
proc lispRepr*(n: PNimrodNode): string {.compileTime.} =
|
||||
## Convert the AST `n` to a human-readable lisp-like string
|
||||
## Convert the AST `n` to a human-readable lisp-like string,
|
||||
##
|
||||
## see also `repr` and `treeRepr`
|
||||
## See also `repr` and `treeRepr`.
|
||||
|
||||
if n == nil: return "nil"
|
||||
|
||||
@@ -331,11 +331,11 @@ macro dumpTree*(s: stmt): stmt = echo s[1].treeRepr
|
||||
##
|
||||
## You can use this as a tool to explore the Nimrod's abstract syntax
|
||||
## tree and to discover what kind of nodes must be created to represent
|
||||
## a certain expression/statement
|
||||
## a certain expression/statement.
|
||||
|
||||
macro dumpLisp*(s: stmt): stmt = echo s[1].lispRepr
|
||||
## Accepts a block of nimrod code and prints the parsed abstract syntax
|
||||
## tree using the `toLisp` function.
|
||||
##
|
||||
## see `dumpTree`
|
||||
## See `dumpTree`.
|
||||
|
||||
|
||||
3
todo.txt
3
todo.txt
@@ -1,8 +1,7 @@
|
||||
version 0.9.0
|
||||
=============
|
||||
|
||||
- implement 'static' vs. 'const';
|
||||
clear separation between tyExpr and PNimrodNode
|
||||
- clean separation between tyExpr and PNimrodNode
|
||||
|
||||
- ``=`` should be overloadable; requires specialization for ``=``
|
||||
- fix remaining generics bugs
|
||||
|
||||
@@ -48,6 +48,7 @@ Language Additions
|
||||
------------------
|
||||
|
||||
- Added explicit ``static`` sections for enforced compile time evaluation.
|
||||
- ``addr`` is now treated like a prefix operator syntactically.
|
||||
|
||||
|
||||
2012-02-09 Version 0.8.14 released
|
||||
|
||||
Reference in New Issue
Block a user