implemented 'static'; macros do not work anymore

This commit is contained in:
Araq 2012-03-15 00:28:28 +01:00
commit 4da067691e
10 changed files with 73 additions and 22 deletions

View file

@ -105,6 +105,7 @@ type
nkHiddenCallConv, # an implicit type conversion via a type converter nkHiddenCallConv, # an implicit type conversion via a type converter
nkConv, # a type conversion nkConv, # a type conversion
nkCast, # a type cast nkCast, # a type cast
nkStaticExpr, # a static expr
nkAddr, # a addr expression nkAddr, # a addr expression
nkHiddenAddr, # implicit address operator nkHiddenAddr, # implicit address operator
nkHiddenDeref, # implicit ^ operator nkHiddenDeref, # implicit ^ operator
@ -160,6 +161,7 @@ type
nkBreakStmt, # a break statement nkBreakStmt, # a break statement
nkContinueStmt, # a continue statement nkContinueStmt, # a continue statement
nkBlockStmt, # a block statement nkBlockStmt, # a block statement
nkStaticStmt, # a static statement
nkDiscardStmt, # a discard statement nkDiscardStmt, # a discard statement
nkStmtList, # a list of statements nkStmtList, # a list of statements
nkImportStmt, # an import statement nkImportStmt, # an import statement
@ -384,7 +386,7 @@ type
mOrdinal, mInt, mInt8, mInt16, mInt32, mOrdinal, mInt, mInt8, mInt16, mInt32,
mInt64, mFloat, mFloat32, mFloat64, mBool, mChar, mString, mCstring, mInt64, mFloat, mFloat32, mFloat64, mBool, mChar, mString, mCstring,
mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc, mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc,
mVoidType, mVoidType, mPNimrodNode,
mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor, mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor,
mNimrodMinor, mNimrodPatch, mCpuEndian, mHostOS, mHostCPU, mAppType, mNimrodMinor, mNimrodPatch, mCpuEndian, mHostOS, mHostCPU, mAppType,
mNaN, mInf, mNegInf, mNaN, mInf, mNegInf,

View file

@ -39,7 +39,8 @@ type
tkGeneric, tkIf, tkImport, tkIn, tkInclude, tkIs, tkIsnot, tkIterator, tkGeneric, tkIf, tkImport, tkIn, tkInclude, tkIs, tkIsnot, tkIterator,
tkLambda, tkLet, tkLambda, tkLet,
tkMacro, tkMethod, tkMod, tkNil, tkNot, tkNotin, tkObject, tkOf, tkOr, 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, tkTry, tkTuple, tkType, tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor,
tkYield, # end of keywords tkYield, # end of keywords
tkIntLit, tkInt8Lit, tkInt16Lit, tkInt32Lit, tkInt64Lit, tkFloatLit, tkIntLit, tkInt8Lit, tkInt16Lit, tkInt32Lit, tkInt64Lit, tkFloatLit,
@ -70,7 +71,8 @@ const
"import", "in", "include", "is", "isnot", "iterator", "import", "in", "include", "is", "isnot", "iterator",
"lambda", "let", "lambda", "let",
"macro", "method", "mod", "nil", "not", "notin", "object", "of", "or", "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", "try", "tuple", "type", "var", "when", "while", "with", "without", "xor",
"yield", "yield",
"tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit", "tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit",

View file

@ -436,8 +436,6 @@ proc identOrLiteral(p: var TParser): PNode =
tkColon) tkColon)
of tkCast: of tkCast:
result = parseCast(p) result = parseCast(p)
of tkAddr:
result = parseAddr(p)
else: else:
parMessage(p, errExprExpected, p.tok) parMessage(p, errExprExpected, p.tok)
getTok(p) # we must consume a token here to prevend endless loops! 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) optInd(p, a)
addSon(result, primary(p)) addSon(result, primary(p))
return 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: elif p.tok.tokType == tkBind:
result = newNodeP(nkBind, p) result = newNodeP(nkBind, p)
getTok(p) getTok(p)
@ -980,6 +988,14 @@ proc parseBlock(p: var TParser): PNode =
skipComment(p, result) skipComment(p, result)
addSon(result, parseStmt(p)) 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 = proc parseAsm(p: var TParser): PNode =
result = newNodeP(nkAsmStmt, p) result = newNodeP(nkAsmStmt, p)
getTok(p) getTok(p)
@ -1379,6 +1395,7 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
of tkTry: result = parseTry(p) of tkTry: result = parseTry(p)
of tkFor: result = parseFor(p) of tkFor: result = parseFor(p)
of tkBlock: result = parseBlock(p) of tkBlock: result = parseBlock(p)
of tkStatic: result = parseStatic(p)
of tkAsm: result = parseAsm(p) of tkAsm: result = parseAsm(p)
of tkProc: result = parseRoutine(p, nkProcDef) of tkProc: result = parseRoutine(p, nkProcDef)
of tkMethod: result = parseRoutine(p, nkMethodDef) of tkMethod: result = parseRoutine(p, nkMethodDef)

View file

@ -336,6 +336,7 @@ proc lsub(n: PNode): int =
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: result = lsub(n[1]) of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: result = lsub(n[1])
of nkCast: result = lsub(n.sons[0]) + lsub(n.sons[1]) + len("cast[]()") of nkCast: result = lsub(n.sons[0]) + lsub(n.sons[1]) + len("cast[]()")
of nkAddr: result = lsub(n.sons[0]) + len("addr()") 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 nkHiddenAddr, nkHiddenDeref: result = lsub(n.sons[0])
of nkCommand: result = lsub(n.sons[0]) + lcomma(n, 1) + 1 of nkCommand: result = lsub(n.sons[0]) + lcomma(n, 1) + 1
of nkExprEqExpr, nkAsgn, nkFastAsgn: result = lsons(n) + 3 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) gstmts(g, n.sons[1], c)
dedent(g) 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) = proc gasm(g: var TSrcGen, n: PNode) =
putWithSpace(g, tkAsm, "asm") putWithSpace(g, tkAsm, "asm")
gsub(g, n.sons[0]) gsub(g, n.sons[0])
@ -711,6 +722,10 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
put(g, tkParLe, "(") put(g, tkParLe, "(")
gsub(g, n.sons[0]) gsub(g, n.sons[0])
put(g, tkParRi, ")") put(g, tkParRi, ")")
of nkStaticExpr:
put(g, tkStatic, "static")
put(g, tkSpaces, space)
gsub(g, n.sons[0])
of nkBracketExpr: of nkBracketExpr:
gsub(g, n.sons[0]) gsub(g, n.sons[0])
put(g, tkBracketLe, "[") put(g, tkBracketLe, "[")
@ -951,6 +966,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
of nkTryStmt: gtry(g, n) of nkTryStmt: gtry(g, n)
of nkForStmt: gfor(g, n) of nkForStmt: gfor(g, n)
of nkBlockStmt, nkBlockExpr: gblock(g, n) of nkBlockStmt, nkBlockExpr: gblock(g, n)
of nkStaticStmt: gstaticStmt(g, n)
of nkAsmStmt: gasm(g, n) of nkAsmStmt: gasm(g, n)
of nkProcDef: of nkProcDef:
putWithSpace(g, tkProc, "proc") putWithSpace(g, tkProc, "proc")

View file

@ -483,7 +483,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
if {sfNoSideEffect, sfCompileTime} * callee.flags != {} and if {sfNoSideEffect, sfCompileTime} * callee.flags != {} and
{sfForward, sfImportc} * callee.flags == {}: {sfForward, sfImportc} * callee.flags == {}:
if sfCompileTime notin callee.flags and if sfCompileTime notin callee.flags and
optImplicitCompileTime notin gOptions: return optImplicitStatic notin gOptions: return
if callee.magic notin ctfeWhitelist: return if callee.magic notin ctfeWhitelist: return
if callee.kind notin {skProc, skConverter} or callee.isGenericRoutine: if callee.kind notin {skProc, skConverter} or callee.isGenericRoutine:
@ -508,6 +508,12 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
#if result != n: #if result != n:
# echo "SUCCESS evaluated at compile time: ", call.renderTree # 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, proc semDirectCallAnalyseEffects(c: PContext, n: PNode,
flags: TExprFlags): PNode = flags: TExprFlags): PNode =
if efWantIterator in flags: if efWantIterator in flags:
@ -1342,6 +1348,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = semTableConstr(c, n) result = semTableConstr(c, n)
of nkSymChoice: of nkSymChoice:
GlobalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments})) GlobalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
of nkStaticExpr:
result = semStaticExpr(c, n)
else: else:
GlobalError(n.info, errInvalidExpressionX, GlobalError(n.info, errInvalidExpressionX,
renderTree(n, {renderNoComments})) renderTree(n, {renderNoComments}))

View file

@ -840,6 +840,12 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode =
if whichPragma(pragmaList.sons[i]) == wLine: if whichPragma(pragmaList.sons[i]) == wLine:
setLine(result, pragmaList.sons[i].info) 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 = proc SemStmt(c: PContext, n: PNode): PNode =
const # must be last statements in a block: const # must be last statements in a block:
LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt} LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
@ -896,6 +902,8 @@ proc SemStmt(c: PContext, n: PNode): PNode =
result = evalInclude(c, n) result = evalInclude(c, n)
of nkPragmaBlock: of nkPragmaBlock:
result = semPragmaBlock(c, n) result = semPragmaBlock(c, n)
of nkStaticStmt:
result = semStaticStmt(c, n)
else: else:
# in interactive mode, we embed the expression in an 'echo': # in interactive mode, we embed the expression in an 'echo':
if gCmd == cmdInteractive: if gCmd == cmdInteractive:

View file

@ -4,7 +4,7 @@ comma ::= ',' [COMMENT] [IND]
operator ::= OP0 | OP1 | OP2 | OP3 | OP4 | OP5 | OP6 | OP7 | OP8 | OP9 operator ::= OP0 | OP1 | OP2 | OP3 | OP4 | OP5 | OP6 | OP7 | OP8 | OP9
| 'or' | 'xor' | 'and' | 'or' | 'xor' | 'and'
| 'is' | 'isnot' | 'in' | 'notin' | 'of' | 'is' | 'isnot' | 'in' | 'notin' | 'of'
| 'div' | 'mod' | 'shl' | 'shr' | 'not' | '..' | 'div' | 'mod' | 'shl' | 'shr' | 'not' | 'addr' | 'static' | '..'
prefixOperator ::= operator prefixOperator ::= operator
@ -25,8 +25,6 @@ dollarExpr ::= primary (OP9 optInd primary)*
indexExpr ::= expr indexExpr ::= expr
castExpr ::= 'cast' '[' optInd typeDesc optPar ']' '(' optInd expr optPar ')' castExpr ::= 'cast' '[' optInd typeDesc optPar ']' '(' optInd expr optPar ')'
addrExpr ::= 'addr' '(' optInd expr optPar ')'
staticExpr ::= 'static' '(' optInd expr optPar ')'
symbol ::= '`' (KEYWORD | IDENT | operator | '(' ')' | '[' ']' | '{' '}' symbol ::= '`' (KEYWORD | IDENT | operator | '(' ')' | '[' ']' | '{' '}'
| '=' | literal)+ '`' | '=' | literal)+ '`'
| IDENT | IDENT
@ -38,7 +36,7 @@ primarySuffix ::= '.' optInd symbol [generalizedLit]
| '{' optInd [indexExpr (comma indexExpr)* [comma]] optPar '}' | '{' optInd [indexExpr (comma indexExpr)* [comma]] optPar '}'
primary ::= primaryPrefix* (symbol [generalizedLit] | primary ::= primaryPrefix* (symbol [generalizedLit] |
constructor | castExpr | addrExpr | staticExpr) constructor | castExpr)
primarySuffix* primarySuffix*
generalizedLit ::= GENERALIZED_STR_LIT | GENERALIZED_TRIPLESTR_LIT generalizedLit ::= GENERALIZED_STR_LIT | GENERALIZED_TRIPLESTR_LIT

View file

@ -27,7 +27,7 @@ type
nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr, nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
nnkElifExpr, nnkElseExpr, nnkLambda, nnkDo, nnkAccQuoted, nnkElifExpr, nnkElseExpr, nnkLambda, nnkDo, nnkAccQuoted,
nnkTableConstr, nnkBind, nnkSymChoice, nnkHiddenStdConv, nnkTableConstr, nnkBind, nnkSymChoice, nnkHiddenStdConv,
nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast, nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast, nnkStaticExpr,
nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv, nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv,
nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange, nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange,
nnkStringToCString, nnkCStringToString, nnkAsgn, nnkStringToCString, nnkCStringToString, nnkAsgn,
@ -40,7 +40,7 @@ type
nnkTypeSection, nnkVarSection, nnkLetSection, nnkConstSection, nnkTypeSection, nnkVarSection, nnkLetSection, nnkConstSection,
nnkConstDef, nnkTypeDef, nnkConstDef, nnkTypeDef,
nnkYieldStmt, nnkTryStmt, nnkFinally, nnkRaiseStmt, nnkYieldStmt, nnkTryStmt, nnkFinally, nnkRaiseStmt,
nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkStaticStmt,
nnkDiscardStmt, nnkStmtList, nnkImportStmt, nnkFromStmt, nnkDiscardStmt, nnkStmtList, nnkImportStmt, nnkFromStmt,
nnkIncludeStmt, nnkBindStmt, nnkIncludeStmt, nnkBindStmt,
nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr, nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr,
@ -88,7 +88,7 @@ type
## *ident*. ## *ident*.
TNimrodNode {.final.} = object TNimrodNode {.final.} = object
PNimrodNode* = ref TNimrodNode PNimrodNode* {.magic: "PNimrodNode".} = ref TNimrodNode
## represents a Nimrod AST node. Macros operate on this type. ## represents a Nimrod AST node. Macros operate on this type.
const const
@ -263,7 +263,7 @@ proc newCall*(theProc: string,
proc nestList*(theProc: TNimrodIdent, proc nestList*(theProc: TNimrodIdent,
x: PNimrodNode): PNimrodNode {.compileTime.} = x: PNimrodNode): PNimrodNode {.compileTime.} =
## nests the list `x` into a tree of call expressions: ## 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 var L = x.len
result = newCall(theProc, x[L-2], x[L-1]) result = newCall(theProc, x[L-2], x[L-1])
var a = result var a = result
@ -271,9 +271,9 @@ proc nestList*(theProc: TNimrodIdent,
a = newCall(theProc, x[i], copyNimTree(a)) a = newCall(theProc, x[i], copyNimTree(a))
proc treeRepr*(n: PNimrodNode): string {.compileTime.} = 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) = proc traverse(res: var string, level: int, n: PNimrodNode) =
for i in 0..level-1: res.add " " for i in 0..level-1: res.add " "
@ -300,9 +300,9 @@ proc treeRepr*(n: PNimrodNode): string {.compileTime.} =
traverse(result, 0, n) traverse(result, 0, n)
proc lispRepr*(n: PNimrodNode): string {.compileTime.} = 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" 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 ## 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 ## 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 macro dumpLisp*(s: stmt): stmt = echo s[1].lispRepr
## Accepts a block of nimrod code and prints the parsed abstract syntax ## Accepts a block of nimrod code and prints the parsed abstract syntax
## tree using the `toLisp` function. ## tree using the `toLisp` function.
## ##
## see `dumpTree` ## See `dumpTree`.

View file

@ -1,8 +1,7 @@
version 0.9.0 version 0.9.0
============= =============
- implement 'static' vs. 'const'; - clean separation between tyExpr and PNimrodNode
clear separation between tyExpr and PNimrodNode
- ``=`` should be overloadable; requires specialization for ``=`` - ``=`` should be overloadable; requires specialization for ``=``
- fix remaining generics bugs - fix remaining generics bugs

View file

@ -48,6 +48,7 @@ Language Additions
------------------ ------------------
- Added explicit ``static`` sections for enforced compile time evaluation. - 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 2012-02-09 Version 0.8.14 released