mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-03 11:42:33 +00:00
syntax compatibility between do blocks and stmt blocks
See the section `do notation` in the manual for more info. * nkMacroStmt has been removed Macro statements are now mapped to regular nkCall nodes. The support for additional clauses (such as else, except, of, etc) have been restored - they will now appear as additional arguments for the nkCall node (as nkElse, nkExcept, etc nodes) * fixed some regressions in the `is` operator and semCompiles
This commit is contained in:
@@ -145,7 +145,6 @@ type
|
||||
nkElifBranch, # used in if statements
|
||||
nkExceptBranch, # an except section
|
||||
nkElse, # an else part
|
||||
nkMacroStmt, # a macro statement
|
||||
nkAsmStmt, # an assembler block
|
||||
nkPragma, # a pragma statement
|
||||
nkPragmaBlock, # a pragma with a block
|
||||
@@ -911,6 +910,18 @@ proc newMetaNodeIT*(tree: PNode, info: TLineInfo, typ: PType): PNode =
|
||||
result = newNodeIT(nkMetaNode, info, typ)
|
||||
result.add(tree)
|
||||
|
||||
var emptyParams = newNode(nkFormalParams)
|
||||
emptyParams.addSon(emptyNode)
|
||||
|
||||
proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
|
||||
params = emptyParams,
|
||||
name, pattern, genericParams,
|
||||
pragmas, exceptions = ast.emptyNode): PNode =
|
||||
result = newNodeI(kind, info)
|
||||
result.sons = @[name, pattern, genericParams, params,
|
||||
pragmas, exceptions, body]
|
||||
|
||||
|
||||
proc NewType(kind: TTypeKind, owner: PSym): PType =
|
||||
new(result)
|
||||
result.kind = kind
|
||||
|
||||
@@ -1382,7 +1382,7 @@ proc nestedStatement(p: var TParser): PNode =
|
||||
# Nimrod requires complex statements to be nested in whitespace!
|
||||
const
|
||||
complexStmt = {nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef,
|
||||
nkTemplateDef, nkIteratorDef, nkMacroStmt, nkIfStmt,
|
||||
nkTemplateDef, nkIteratorDef, nkIfStmt,
|
||||
nkWhenStmt, nkForStmt, nkWhileStmt, nkCaseStmt, nkVarSection,
|
||||
nkConstSection, nkTypeSection, nkTryStmt, nkBlockStmt, nkStmtList,
|
||||
nkCommentStmt, nkStmtListExpr, nkBlockExpr, nkStmtListType, nkBlockType}
|
||||
|
||||
@@ -1296,7 +1296,7 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||
of nkEmpty: result = n
|
||||
of nkSym: result = evalSym(c, n, flags)
|
||||
of nkType..nkNilLit: result = copyNode(n) # end of atoms
|
||||
of nkCall, nkHiddenCallConv, nkMacroStmt, nkCommand, nkCallStrLit, nkInfix,
|
||||
of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit, nkInfix,
|
||||
nkPrefix, nkPostfix:
|
||||
result = evalMagicOrCall(c, n)
|
||||
of nkCurly, nkBracket, nkRange:
|
||||
|
||||
@@ -101,4 +101,6 @@ proc getIdent*(identifier: string, h: THash): PIdent =
|
||||
|
||||
proc IdentEq*(id: PIdent, name: string): bool =
|
||||
result = id.id == getIdent(name).id
|
||||
|
||||
|
||||
let idAnon* = getIdent":anonymous"
|
||||
|
||||
|
||||
@@ -585,22 +585,25 @@ proc inCheckpoint*(current: TLineInfo): TCheckPointResult =
|
||||
type
|
||||
TErrorHandling = enum doNothing, doAbort, doRaise
|
||||
|
||||
proc handleError(msg: TMsgKind, eh: TErrorHandling, s: string) =
|
||||
if msg == errInternal:
|
||||
assert(false) # we want a stack trace here
|
||||
proc handleError(msg: TMsgKind, eh: TErrorHandling, s: string) =
|
||||
template maybeTrace =
|
||||
if defined(debug) or gVerbosity >= 3:
|
||||
writeStackTrace()
|
||||
|
||||
if msg == errInternal:
|
||||
writeStackTrace() # we always want a stack trace here
|
||||
if msg >= fatalMin and msg <= fatalMax:
|
||||
if gVerbosity >= 3: assert(false)
|
||||
maybeTrace()
|
||||
quit(1)
|
||||
if msg >= errMin and msg <= errMax:
|
||||
if gVerbosity >= 3: assert(false)
|
||||
maybeTrace()
|
||||
inc(gErrorCounter)
|
||||
options.gExitcode = 1'i8
|
||||
if gErrorCounter >= gErrorMax or eh == doAbort:
|
||||
if gVerbosity >= 3: assert(false)
|
||||
quit(1) # one error stops the compiler
|
||||
quit(1) # one error stops the compiler
|
||||
elif eh == doRaise:
|
||||
raiseRecoverableError(s)
|
||||
|
||||
|
||||
proc `==`*(a, b: TLineInfo): bool =
|
||||
result = a.line == b.line and a.fileIndex == b.fileIndex
|
||||
|
||||
|
||||
@@ -227,5 +227,7 @@ proc binaryStrSearch*(x: openarray[string], y: string): int =
|
||||
result = - 1
|
||||
|
||||
# Can we keep this? I'm using it all the time
|
||||
template nimdbg*: expr = c.filename.endsWith"nimdbg.nim"
|
||||
template cnimdbg*: expr = p.module.filename.endsWith"nimdbg.nim"
|
||||
template nimdbg*: expr = c.filename.endsWith"hallo.nim"
|
||||
template cnimdbg*: expr = p.module.filename.endsWith"hallo.nim"
|
||||
template enimdbg*: expr = c.module.name.s == "hallo"
|
||||
template pnimdbg*: expr = p.lex.fileIdx.ToFilename.endsWith"hallo.nim"
|
||||
|
||||
@@ -693,20 +693,15 @@ proc optPragmas(p: var TParser): PNode =
|
||||
else: result = ast.emptyNode
|
||||
|
||||
proc parseDoBlock(p: var TParser): PNode =
|
||||
var info = parLineInfo(p)
|
||||
let info = parLineInfo(p)
|
||||
getTok(p)
|
||||
var params = parseParamList(p, retColon=false)
|
||||
var pragmas = optPragmas(p)
|
||||
let params = parseParamList(p, retColon=false)
|
||||
let pragmas = optPragmas(p)
|
||||
eat(p, tkColon)
|
||||
result = newNodeI(nkDo, info)
|
||||
addSon(result, ast.emptyNode) # no name part
|
||||
addSon(result, ast.emptyNode) # no pattern part
|
||||
addSon(result, ast.emptyNode) # no generic parameters
|
||||
addSon(result, params)
|
||||
addSon(result, pragmas)
|
||||
skipComment(p, result)
|
||||
addSon(result, ast.emptyNode) # no exception list
|
||||
addSon(result, parseStmt(p))
|
||||
result = newProcNode(nkDo, info, parseStmt(p),
|
||||
params = params,
|
||||
pragmas = pragmas)
|
||||
|
||||
proc parseDoBlocks(p: var TParser, call: PNode) =
|
||||
while p.tok.tokType == tkDo:
|
||||
@@ -723,16 +718,11 @@ proc parseProcExpr(p: var TParser, isExpr: bool): PNode =
|
||||
params = parseParamList(p)
|
||||
pragmas = optPragmas(p)
|
||||
if p.tok.tokType == tkEquals and isExpr:
|
||||
result = newNodeI(nkLambda, info)
|
||||
addSon(result, ast.emptyNode) # no name part
|
||||
addSon(result, ast.emptyNode) # no pattern
|
||||
addSon(result, ast.emptyNode) # no generic parameters
|
||||
addSon(result, params)
|
||||
addSon(result, pragmas)
|
||||
getTok(p)
|
||||
skipComment(p, result)
|
||||
addSon(result, ast.emptyNode) # no exception list
|
||||
addSon(result, parseStmt(p))
|
||||
result = newProcNode(nkLambda, info, parseStmt(p),
|
||||
params = params,
|
||||
pragmas = pragmas)
|
||||
else:
|
||||
result = newNodeI(nkProcTy, info)
|
||||
if hasSignature:
|
||||
@@ -822,7 +812,7 @@ proc primary(p: var TParser, skipSuffix = false): PNode =
|
||||
proc parseTypeDesc(p: var TParser): PNode =
|
||||
if p.tok.toktype == tkProc: result = parseProcExpr(p, false)
|
||||
else: result = parseExpr(p)
|
||||
|
||||
|
||||
proc parseExprStmt(p: var TParser): PNode =
|
||||
var a = lowestExpr(p)
|
||||
if p.tok.tokType == tkEquals:
|
||||
@@ -832,32 +822,29 @@ proc parseExprStmt(p: var TParser): PNode =
|
||||
result = newNodeI(nkAsgn, a.info)
|
||||
addSon(result, a)
|
||||
addSon(result, b)
|
||||
else:
|
||||
result = newNodeP(nkCommand, p)
|
||||
result.info = a.info
|
||||
addSon(result, a)
|
||||
while true:
|
||||
else:
|
||||
var call = if a.kind == nkCall: a
|
||||
else: newNode(nkCommand, a.info, @[a])
|
||||
while true:
|
||||
if not isExprStart(p): break
|
||||
var e = parseExpr(p)
|
||||
addSon(result, e)
|
||||
addSon(call, e)
|
||||
if p.tok.tokType != tkComma: break
|
||||
getTok(p)
|
||||
optInd(p, a)
|
||||
if p.tok.tokType == tkDo:
|
||||
parseDoBlocks(p, result)
|
||||
parseDoBlocks(p, call)
|
||||
return
|
||||
if sonsLen(result) <= 1: result = a
|
||||
else: a = result
|
||||
result = if call.sonsLen <= 1: a
|
||||
else: call
|
||||
if p.tok.tokType == tkColon:
|
||||
# macro statement
|
||||
result = newNodeP(nkMacroStmt, p)
|
||||
result.info = a.info
|
||||
addSon(result, a)
|
||||
result = call
|
||||
getTok(p)
|
||||
skipComment(p, result)
|
||||
if p.tok.tokType == tkSad: getTok(p)
|
||||
if not (p.tok.TokType in {tkOf, tkElif, tkElse, tkExcept}):
|
||||
addSon(result, parseStmt(p))
|
||||
if not (p.tok.TokType in {tkOf, tkElif, tkElse, tkExcept}):
|
||||
let body = parseStmt(p)
|
||||
addSon(result, newProcNode(nkDo, body.info, body))
|
||||
while true:
|
||||
if p.tok.tokType == tkSad: getTok(p)
|
||||
var b: PNode
|
||||
@@ -882,7 +869,7 @@ proc parseExprStmt(p: var TParser): PNode =
|
||||
else: break
|
||||
addSon(b, parseStmt(p))
|
||||
addSon(result, b)
|
||||
if b.kind == nkElse: break
|
||||
if b.kind == nkElse: break
|
||||
|
||||
proc parseImportOrIncludeStmt(p: var TParser, kind: TNodeKind): PNode =
|
||||
var a: PNode
|
||||
|
||||
@@ -1051,7 +1051,6 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
of nkWhileStmt: gwhile(g, n)
|
||||
of nkPragmaBlock: gpragmaBlock(g, n)
|
||||
of nkCaseStmt, nkRecCase: gcase(g, n)
|
||||
of nkMacroStmt: gmacro(g, n)
|
||||
of nkTryStmt: gtry(g, n)
|
||||
of nkForStmt, nkParForStmt: gfor(g, n)
|
||||
of nkBlockStmt, nkBlockExpr: gblock(g, n)
|
||||
|
||||
@@ -22,8 +22,7 @@ proc semPass*(): TPass
|
||||
|
||||
type
|
||||
TExprFlag = enum
|
||||
efLValue, efWantIterator, efInTypeof, efWantStmt,
|
||||
efMacroStmt # expr to semcheck is a macro statement
|
||||
efLValue, efWantIterator, efInTypeof, efWantStmt, efDetermineType
|
||||
TExprFlags = set[TExprFlag]
|
||||
|
||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||
@@ -35,7 +34,7 @@ proc semProcBody(c: PContext, n: PNode): PNode
|
||||
proc fitNode(c: PContext, formal: PType, arg: PNode): PNode
|
||||
proc changeType(n: PNode, newType: PType)
|
||||
|
||||
proc semLambda(c: PContext, n: PNode): PNode
|
||||
proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType
|
||||
proc semStmt(c: PContext, n: PNode): PNode
|
||||
proc semParamList(c: PContext, n, genericParams: PNode, s: PSym)
|
||||
@@ -44,6 +43,8 @@ proc addResult(c: PContext, t: PType, info: TLineInfo, owner: TSymKind)
|
||||
proc addResultNode(c: PContext, n: PNode)
|
||||
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
|
||||
proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||
proc fixImmediateParams(n: PNode): PNode
|
||||
proc activate(c: PContext, n: PNode)
|
||||
|
||||
proc typeMismatch(n: PNode, formal, actual: PType) =
|
||||
if formal.kind != tyError and actual.kind != tyError:
|
||||
@@ -91,8 +92,6 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode
|
||||
|
||||
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||
semCheck: bool = true): PNode
|
||||
proc semMacroStmt(c: PContext, n: PNode, flags: TExprFlags,
|
||||
semCheck = true): PNode
|
||||
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||
|
||||
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
|
||||
|
||||
@@ -304,16 +304,17 @@ proc semIs(c: PContext, n: PNode): PNode =
|
||||
# BUGFIX: don't evaluate this too early: ``T is void``
|
||||
if not containsGenericType(t1): result = evalIsOp(n)
|
||||
|
||||
proc semOpAux(c: PContext, n: PNode, tailToExclude = 1) =
|
||||
for i in countup(1, sonsLen(n) - tailToExclude):
|
||||
proc semOpAux(c: PContext, n: PNode) =
|
||||
let flags = {efDetermineType}
|
||||
for i in countup(1, n.sonsLen- 1):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkExprEqExpr and sonsLen(a) == 2:
|
||||
var info = a.sons[0].info
|
||||
a.sons[0] = newIdentNode(considerAcc(a.sons[0]), info)
|
||||
a.sons[1] = semExprWithType(c, a.sons[1])
|
||||
a.sons[1] = semExprWithType(c, a.sons[1], flags)
|
||||
a.typ = a.sons[1].typ
|
||||
else:
|
||||
n.sons[i] = semExprWithType(c, a)
|
||||
n.sons[i] = semExprWithType(c, a, flags)
|
||||
|
||||
proc overloadedCallOpr(c: PContext, n: PNode): PNode =
|
||||
# quick check if there is *any* () operator overloaded:
|
||||
@@ -668,8 +669,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
# this seems to be a hotspot in the compiler!
|
||||
let nOrig = n.copyTree
|
||||
semOpAux(c, n, 1 + ord(efMacroStmt in flags))
|
||||
let flags = flags - {efMacroStmt}
|
||||
semOpAux(c, n)
|
||||
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
|
||||
if result == nil:
|
||||
result = overloadedCallOpr(c, n)
|
||||
@@ -679,8 +679,9 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
let callee = result.sons[0].sym
|
||||
case callee.kind
|
||||
of skMacro: result = semMacroExpr(c, result, nOrig, callee)
|
||||
of skTemplate: result = semTemplateExpr(c, nOrig, callee)
|
||||
of skTemplate: result = semTemplateExpr(c, result, callee)
|
||||
else:
|
||||
activate(c, n)
|
||||
fixAbstractType(c, result)
|
||||
analyseIfAddressTakenInCall(c, result)
|
||||
if callee.magic != mNone:
|
||||
@@ -1281,7 +1282,7 @@ proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
# we replace this node by a 'true' or 'false' node:
|
||||
if sonsLen(n) != 2: return semDirectOp(c, n, flags)
|
||||
|
||||
result = newIntNode(nkIntLit, ord(tryExpr(c, n, flags) != nil))
|
||||
result = newIntNode(nkIntLit, ord(tryExpr(c, n[1], flags) != nil))
|
||||
result.info = n.info
|
||||
result.typ = getSysType(tyBool)
|
||||
|
||||
@@ -1496,52 +1497,6 @@ proc buildCall(n: PNode): PNode =
|
||||
else:
|
||||
result = n
|
||||
|
||||
proc semMacroStmt(c: PContext, n: PNode, flags: TExprFlags,
|
||||
semCheck = true): PNode =
|
||||
checkMinSonsLen(n, 2)
|
||||
var a: PNode
|
||||
if isCallExpr(n.sons[0]): a = n.sons[0].sons[0]
|
||||
else: a = n.sons[0]
|
||||
var s = qualifiedLookup(c, a, {checkUndeclared})
|
||||
if s != nil:
|
||||
# transform
|
||||
# nkMacroStmt(nkCall(a...), stmt, b...)
|
||||
# to
|
||||
# nkCall(a..., stmt, b...)
|
||||
result = newNodeI(nkCall, n.info)
|
||||
addSon(result, a)
|
||||
if isCallExpr(n.sons[0]):
|
||||
for i in countup(1, sonsLen(n.sons[0]) - 1):
|
||||
addSon(result, n.sons[0].sons[i])
|
||||
# for sigmatch this need to have a type; we use 'void':
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
n.sons[i].typ = newTypeS(tyEmpty, c)
|
||||
addSon(result, n.sons[i])
|
||||
|
||||
case s.kind
|
||||
of skMacro:
|
||||
if sfImmediate notin s.flags:
|
||||
result = semDirectOp(c, result, flags+{efMacroStmt})
|
||||
else:
|
||||
result = semMacroExpr(c, result, n, s, semCheck)
|
||||
of skTemplate:
|
||||
if sfImmediate notin s.flags:
|
||||
result = semDirectOp(c, result, flags+{efMacroStmt})
|
||||
else:
|
||||
result = semTemplateExpr(c, result, s, semCheck)
|
||||
else:
|
||||
LocalError(n.info, errXisNoMacroOrTemplate, s.name.s)
|
||||
result = errorNode(c, n)
|
||||
elif a.kind == nkDotExpr:
|
||||
# 'x.m(y): stmt' == nkMacroStmt(nkCall(nkDotExpr(x, m), y), stmt)
|
||||
# --> nkMacroStmt(nkCall(m, x, y), stmt)
|
||||
n.sons[0] = buildCall(n.sons[0])
|
||||
result = semMacroStmt(c, n, flags, semCheck)
|
||||
else:
|
||||
LocalError(n.info, errInvalidExpressionX,
|
||||
renderTree(a, {renderNoComments}))
|
||||
result = errorNode(c, n)
|
||||
|
||||
proc semCaseExpr(c: PContext, caseStmt: PNode): PNode =
|
||||
# The case expression is simply rewritten to a StmtListExpr:
|
||||
# var res {.noInit, genSym.}: type(values)
|
||||
@@ -1553,7 +1508,7 @@ proc semCaseExpr(c: PContext, caseStmt: PNode): PNode =
|
||||
# res
|
||||
var
|
||||
info = caseStmt.info
|
||||
resVar = newSym(skVar, getIdent":res", getCurrOwner(), info)
|
||||
resVar = newSym(skVar, idAnon, getCurrOwner(), info)
|
||||
resNode = newSymNode(resVar, info)
|
||||
resType: PType
|
||||
|
||||
@@ -1592,7 +1547,15 @@ proc semCaseExpr(c: PContext, caseStmt: PNode): PNode =
|
||||
resNode])
|
||||
|
||||
result = semStmtListExpr(c, result)
|
||||
|
||||
|
||||
proc fixImmediateParams(n: PNode): PNode =
|
||||
# XXX: Temporary work-around until we carry out
|
||||
# the planned overload resolution reforms
|
||||
for i in 1 .. <n.len:
|
||||
if n[i].kind == nkDo: n.sons[i] = n[i][bodyPos]
|
||||
|
||||
result = n
|
||||
|
||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
result = n
|
||||
if gCmd == cmdIdeTools: suggestExpr(c, n)
|
||||
@@ -1670,12 +1633,14 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
if sfImmediate notin s.flags:
|
||||
result = semDirectOp(c, n, flags)
|
||||
else:
|
||||
result = semMacroExpr(c, n, n, s)
|
||||
var p = fixImmediateParams(n)
|
||||
result = semMacroExpr(c, p, p, s)
|
||||
of skTemplate:
|
||||
if sfImmediate notin s.flags:
|
||||
result = semDirectOp(c, n, flags)
|
||||
else:
|
||||
result = semTemplateExpr(c, n, s)
|
||||
var p = fixImmediateParams(n)
|
||||
result = semTemplateExpr(c, p, s)
|
||||
of skType:
|
||||
# XXX think about this more (``set`` procs)
|
||||
if n.len == 2:
|
||||
@@ -1695,8 +1660,6 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
result = semDirectOp(c, n, flags)
|
||||
else:
|
||||
result = semIndirectOp(c, n, flags)
|
||||
of nkMacroStmt:
|
||||
result = semMacroStmt(c, n, flags)
|
||||
of nkWhen:
|
||||
if efWantStmt in flags:
|
||||
result = semWhen(c, n, true)
|
||||
@@ -1725,7 +1688,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
of paSingle: result = semExpr(c, n.sons[0], flags)
|
||||
of nkCurly: result = semSetConstr(c, n)
|
||||
of nkBracket: result = semArrayConstr(c, n)
|
||||
of nkLambdaKinds: result = semLambda(c, n)
|
||||
of nkLambdaKinds: result = semLambda(c, n, flags)
|
||||
of nkDerefExpr: result = semDeref(c, n)
|
||||
of nkAddr:
|
||||
result = n
|
||||
|
||||
@@ -53,6 +53,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode =
|
||||
result = symChoice(c, n, s, scOpen)
|
||||
of skTemplate:
|
||||
if macroToExpand(s):
|
||||
let n = fixImmediateParams(n)
|
||||
result = semTemplateExpr(c, n, s, false)
|
||||
else:
|
||||
result = symChoice(c, n, s, scOpen)
|
||||
@@ -123,6 +124,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
result = n
|
||||
of skTemplate:
|
||||
if macroToExpand(s):
|
||||
let n = fixImmediateParams(n)
|
||||
result = semTemplateExpr(c, n, s, false)
|
||||
else:
|
||||
n.sons[0] = symChoice(c, n.sons[0], s, scOpen)
|
||||
@@ -151,17 +153,6 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
let flags = if isDefinedMagic: flags+{withinMixin} else: flags
|
||||
for i in countup(first, sonsLen(result) - 1):
|
||||
result.sons[i] = semGenericStmt(c, result.sons[i], flags, toBind)
|
||||
of nkMacroStmt:
|
||||
checkMinSonsLen(n, 2)
|
||||
var a: PNode
|
||||
if isCallExpr(n.sons[0]): a = n.sons[0].sons[0]
|
||||
else: a = n.sons[0]
|
||||
let luf = if withinMixin notin flags: {checkUndeclared} else: {}
|
||||
var s = qualifiedLookup(c, a, luf)
|
||||
if s != nil and macroToExpand(s):
|
||||
result = semMacroStmt(c, n, {}, false)
|
||||
for i in countup(0, sonsLen(result)-1):
|
||||
result.sons[i] = semGenericStmt(c, result.sons[i], flags, toBind)
|
||||
of nkIfStmt:
|
||||
for i in countup(0, sonsLen(n)-1):
|
||||
n.sons[i] = semGenericStmtScope(c, n.sons[i], flags, toBind)
|
||||
|
||||
@@ -623,9 +623,9 @@ proc semProcAnnotation(c: PContext, prc: PNode): PNode =
|
||||
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
|
||||
let m = lookupMacro(c, key)
|
||||
if m == nil: continue
|
||||
# we transform ``proc p {.m, rest.}`` into ``m: proc p {.rest.}`` and
|
||||
# we transform ``proc p {.m, rest.}`` into ``m(proc p {.rest.})`` and
|
||||
# let the semantic checker deal with it:
|
||||
var x = newNodeI(nkMacroStmt, n.info)
|
||||
var x = newNodeI(nkCall, n.info)
|
||||
x.add(newSymNode(m))
|
||||
prc.sons[pragmasPos] = copyExcept(n, i)
|
||||
if it.kind == nkExprColonExpr:
|
||||
@@ -634,15 +634,19 @@ proc semProcAnnotation(c: PContext, prc: PNode): PNode =
|
||||
x.add(prc)
|
||||
# recursion assures that this works for multiple macro annotations too:
|
||||
return semStmt(c, x)
|
||||
|
||||
proc semLambda(c: PContext, n: PNode): PNode =
|
||||
|
||||
proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = semProcAnnotation(c, n)
|
||||
if result != nil: return result
|
||||
result = n
|
||||
checkSonsLen(n, bodyPos + 1)
|
||||
var s = newSym(skProc, getIdent":anonymous", getCurrOwner(), n.info)
|
||||
s.ast = n
|
||||
n.sons[namePos] = newSymNode(s)
|
||||
var s: PSym
|
||||
if n[namePos].kind != nkSym:
|
||||
s = newSym(skProc, idAnon, getCurrOwner(), n.info)
|
||||
s.ast = n
|
||||
n.sons[namePos] = newSymNode(s)
|
||||
else:
|
||||
s = n[namePos].sym
|
||||
pushOwner(s)
|
||||
openScope(c.tab)
|
||||
if n.sons[genericParamsPos].kind != nkEmpty:
|
||||
@@ -659,19 +663,31 @@ proc semLambda(c: PContext, n: PNode): PNode =
|
||||
if n.sons[bodyPos].kind != nkEmpty:
|
||||
if sfImportc in s.flags:
|
||||
LocalError(n.sons[bodyPos].info, errImplOfXNotAllowed, s.name.s)
|
||||
pushProcCon(c, s)
|
||||
addResult(c, s.typ.sons[0], n.info, skProc)
|
||||
let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
|
||||
n.sons[bodyPos] = transformBody(c.module, semBody, s)
|
||||
addResultNode(c, n)
|
||||
popProcCon(c)
|
||||
if efDetermineType notin flags:
|
||||
pushProcCon(c, s)
|
||||
addResult(c, s.typ.sons[0], n.info, skProc)
|
||||
let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
|
||||
n.sons[bodyPos] = transformBody(c.module, semBody, s)
|
||||
addResultNode(c, n)
|
||||
popProcCon(c)
|
||||
sideEffectsCheck(c, s)
|
||||
else:
|
||||
LocalError(n.info, errImplOfXexpected, s.name.s)
|
||||
sideEffectsCheck(c, s)
|
||||
closeScope(c.tab) # close scope for parameters
|
||||
popOwner()
|
||||
result.typ = s.typ
|
||||
|
||||
proc activate(c: PContext, n: PNode) =
|
||||
# XXX: This proc is part of my plan for getting rid of
|
||||
# forward declarations. stay tuned.
|
||||
case n.kind
|
||||
of nkLambdaKinds:
|
||||
discard semLambda(c, n, {})
|
||||
of nkCallKinds:
|
||||
for i in 1 .. <n.len: activate(c, n[i])
|
||||
else:
|
||||
nil
|
||||
|
||||
proc instantiateDestructor*(c: PContext, typ: PType): bool
|
||||
|
||||
proc doDestructorStuff(c: PContext, s: PSym, n: PNode) =
|
||||
|
||||
@@ -64,10 +64,11 @@ proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode
|
||||
proc prepareNode(cl: var TReplTypeVars, n: PNode): PNode =
|
||||
result = copyNode(n)
|
||||
result.typ = ReplaceTypeVarsT(cl, n.typ)
|
||||
if result.kind == nkSym: result.sym = ReplaceTypeVarsS(cl, n.sym)
|
||||
for i in 0 .. safeLen(n)-1:
|
||||
# XXX HACK: ``f(a, b)``, avoid to instantiate `f`
|
||||
if i == 0: result.add(n[i])
|
||||
else: result.add(ReplaceTypeVarsN(cl, n[i]))
|
||||
else: result.add(prepareNode(cl, n[i]))
|
||||
|
||||
proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
|
||||
if n == nil: return
|
||||
|
||||
@@ -637,8 +637,12 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
|
||||
of isGeneric:
|
||||
inc(m.genericMatches)
|
||||
if m.calleeSym != nil and m.calleeSym.kind in {skMacro, skTemplate}:
|
||||
if f.kind == tyTypeDesc: result = arg
|
||||
else: result = argOrig
|
||||
if f.kind == tyStmt and argOrig.kind == nkDo:
|
||||
result = argOrig[bodyPos]
|
||||
elif f.kind == tyTypeDesc:
|
||||
result = arg
|
||||
else:
|
||||
result = argOrig
|
||||
else:
|
||||
result = copyTree(arg)
|
||||
result.typ = getInstantiatedType(c, arg, m, f)
|
||||
|
||||
@@ -175,8 +175,7 @@ proc findClosestDot(n: PNode): PNode =
|
||||
if result != nil: return
|
||||
|
||||
const
|
||||
CallNodes = {nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit,
|
||||
nkMacroStmt}
|
||||
CallNodes = {nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit}
|
||||
|
||||
proc findClosestCall(n: PNode): PNode =
|
||||
if n.kind in callNodes and msgs.inCheckpoint(n.info) == cpExact:
|
||||
|
||||
@@ -38,7 +38,7 @@ type
|
||||
nnkFastAsgn, nnkGenericParams, nnkFormalParams, nnkOfInherit,
|
||||
nnkModule, nnkProcDef, nnkMethodDef, nnkConverterDef,
|
||||
nnkMacroDef, nnkTemplateDef, nnkIteratorDef, nnkOfBranch,
|
||||
nnkElifBranch, nnkExceptBranch, nnkElse, nnkMacroStmt,
|
||||
nnkElifBranch, nnkExceptBranch, nnkElse,
|
||||
nnkAsmStmt, nnkPragma, nnkPragmaBlock, nnkIfStmt, nnkWhenStmt,
|
||||
nnkForStmt, nnkParForStmt, nnkWhileStmt, nnkCaseStmt,
|
||||
nnkTypeSection, nnkVarSection, nnkLetSection, nnkConstSection,
|
||||
|
||||
@@ -22,7 +22,7 @@ type
|
||||
|
||||
PSurface* = ref TSurface ## a surface to draw onto
|
||||
TSurface* {.pure, final.} = object
|
||||
w*, h*: int
|
||||
w*, h*: Natural
|
||||
s*: sdl.PSurface
|
||||
|
||||
EGraphics* = object of EIO
|
||||
|
||||
@@ -940,7 +940,7 @@ proc readIntoBuf(socket: TSocket, flags: int32): int =
|
||||
socket.currPos = 0
|
||||
|
||||
template retRead(flags, readBytes: int) =
|
||||
let res = socket.readIntoBuf(flags)
|
||||
let res = socket.readIntoBuf(flags.int32)
|
||||
if res <= 0:
|
||||
if readBytes > 0:
|
||||
return readBytes
|
||||
|
||||
@@ -151,7 +151,7 @@ template require*(conditions: stmt): stmt {.immediate, dirty.} =
|
||||
const AbortOnError {.inject.} = true
|
||||
check conditions
|
||||
|
||||
macro expect*(exp: stmt): stmt {.immediate.} =
|
||||
macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} =
|
||||
let exp = callsite()
|
||||
template expectBody(errorTypes, lineInfoLit: expr,
|
||||
body: stmt): PNimrodNode {.dirty.} =
|
||||
@@ -162,12 +162,11 @@ macro expect*(exp: stmt): stmt {.immediate.} =
|
||||
except errorTypes:
|
||||
nil
|
||||
|
||||
var expectCall = exp[0]
|
||||
var body = exp[1]
|
||||
|
||||
var body = exp[exp.len - 1]
|
||||
|
||||
var errorTypes = newNimNode(nnkBracket)
|
||||
for i in countup(1, expectCall.len - 1):
|
||||
errorTypes.add(expectCall[i])
|
||||
for i in countup(1, exp.len - 2):
|
||||
errorTypes.add(exp[i])
|
||||
|
||||
result = getAst(expectBody(errorTypes, exp.lineinfo, body))
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
output: "Got: 'nnkMacroStmt' hi"
|
||||
output: "Got: 'nnkCall' hi"
|
||||
"""
|
||||
|
||||
import
|
||||
@@ -11,17 +11,15 @@ macro outterMacro*(n: stmt): stmt {.immediate.} =
|
||||
proc innerProc(i: int): string =
|
||||
echo "Using arg ! " & n.repr
|
||||
result = "Got: '" & $n.kind & "' " & $j
|
||||
if n.kind != TNimrodNodeKind.nnkMacroStmt:
|
||||
error("Macro " & n[0].repr & " requires a block.")
|
||||
var callNode = n[0]
|
||||
expectKind(callNode, TNimrodNodeKind.nnkCall)
|
||||
if callNode.len != 2 or callNode[1].kind != TNimrodNodeKind.nnkIdent:
|
||||
expectKind(n, TNimrodNodeKind.nnkCall)
|
||||
if n.len != 3 or n[1].kind != TNimrodNodeKind.nnkIdent:
|
||||
error("Macro " & callNode.repr &
|
||||
" requires the ident passed as parameter (eg: " & callNode.repr &
|
||||
"(the_name_you_want)): statements.")
|
||||
result = newNimNode(TNimrodNodeKind.nnkStmtList)
|
||||
var ass : PNimrodNode = newNimNode(TNimrodNodeKind.nnkAsgn)
|
||||
ass.add(newIdentNode(callNode[1].ident))
|
||||
var ass : PNimrodNode = newNimNode(nnkAsgn)
|
||||
ass.add(newIdentNode(n[1].ident))
|
||||
ass.add(newStrLitNode(innerProc(4)))
|
||||
result.add(ass)
|
||||
|
||||
|
||||
@@ -28,12 +28,12 @@ import
|
||||
# `opened` is defined to `optional.hasValue`
|
||||
macro using(e: expr): stmt {.immediate.} =
|
||||
let e = callsite()
|
||||
if e.len != 2:
|
||||
if e.len != 3:
|
||||
error "Using statement: unexpected number of arguments. Got " &
|
||||
$e.len & ", expected: 1 or more variable assignments and a block"
|
||||
|
||||
var args = e[0]
|
||||
var body = e[1]
|
||||
var args = e
|
||||
var body = e[2]
|
||||
|
||||
var
|
||||
variables : seq[PNimrodNode]
|
||||
@@ -41,8 +41,8 @@ macro using(e: expr): stmt {.immediate.} =
|
||||
|
||||
newSeq(variables, 0)
|
||||
newSeq(closingCalls, 0)
|
||||
|
||||
for i in countup(1, args.len-1):
|
||||
|
||||
for i in countup(1, args.len-2):
|
||||
if args[i].kind == nnkExprEqExpr:
|
||||
var varName = args[i][0]
|
||||
var varValue = args[i][1]
|
||||
|
||||
Reference in New Issue
Block a user