implemented 'static'; macros do not work anymore

This commit is contained in:
Araq
2012-03-15 00:28:28 +01:00
parent c25ffbf262
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
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,

View File

@@ -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",

View File

@@ -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)

View File

@@ -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")

View File

@@ -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}))

View File

@@ -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:

View File

@@ -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

View File

@@ -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`.

View File

@@ -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

View File

@@ -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