next steps towards term rewriting macros; simple examples work

This commit is contained in:
Araq 2012-08-30 22:55:32 +02:00
commit 1d14cb1ad8
17 changed files with 124 additions and 56 deletions

View file

@ -176,7 +176,7 @@ type
nkFromStmt, # a from * import statement nkFromStmt, # a from * import statement
nkIncludeStmt, # an include statement nkIncludeStmt, # an include statement
nkBindStmt, # a bind statement nkBindStmt, # a bind statement
nkPatternStmt, # a pattern statement ('as' statement) nkPattern, # a pattern statement ('as' statement)
nkCommentStmt, # a comment statement nkCommentStmt, # a comment statement
nkStmtListExpr, # a statement list followed by an expr; this is used nkStmtListExpr, # a statement list followed by an expr; this is used
# to allow powerful multi-line templates # to allow powerful multi-line templates
@ -687,13 +687,14 @@ const
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub} skMacro, skTemplate, skConverter, skEnumField, skLet, skStub}
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16, nfAllConst} PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16, nfAllConst}
namePos* = 0 namePos* = 0
genericParamsPos* = 1 patternPos* = 1 # empty except for term rewriting macros
paramsPos* = 2 genericParamsPos* = 2
pragmasPos* = 3 paramsPos* = 3
patternPos* = 4 # empty except for term rewriting macros pragmasPos* = 4
bodyPos* = 5 # position of body; use rodread.getBody() instead! exceptionPos* = 5 # will be used for exception tracking
resultPos* = 6 bodyPos* = 6 # position of body; use rodread.getBody() instead!
dispatcherPos* = 7 # caution: if method has no 'result' it can be position 5! resultPos* = 7
dispatcherPos* = 8 # caution: if method has no 'result' it can be position 5!
nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix, nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
nkCommand, nkCallStrLit} nkCommand, nkCallStrLit}

View file

@ -184,6 +184,7 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
of "taintmode": result = contains(gGlobalOptions, optTaintMode) of "taintmode": result = contains(gGlobalOptions, optTaintMode)
of "tlsemulation": result = contains(gGlobalOptions, optTlsEmulation) of "tlsemulation": result = contains(gGlobalOptions, optTlsEmulation)
of "implicitstatic": result = contains(gOptions, optImplicitStatic) of "implicitstatic": result = contains(gOptions, optImplicitStatic)
of "patterns": result = contains(gOptions, optPatterns)
else: InvalidCmdLineOption(passCmd1, switch, info) else: InvalidCmdLineOption(passCmd1, switch, info)
proc processPath(path: string): string = proc processPath(path: string): string =
@ -315,6 +316,8 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
of "taintmode": ProcessOnOffSwitchG({optTaintMode}, arg, pass, info) of "taintmode": ProcessOnOffSwitchG({optTaintMode}, arg, pass, info)
of "implicitstatic": of "implicitstatic":
ProcessOnOffSwitch({optImplicitStatic}, arg, pass, info) ProcessOnOffSwitch({optImplicitStatic}, arg, pass, info)
of "patterns":
ProcessOnOffSwitch({optPatterns}, arg, pass, info)
of "opt": of "opt":
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
case arg.normalize case arg.normalize

View file

@ -26,8 +26,9 @@ type # please make sure we have under 32 options
optByRef, # use pass by ref for objects optByRef, # use pass by ref for objects
# (for interfacing with C) # (for interfacing with C)
optProfiler, # profiler turned on optProfiler, # profiler turned on
optImplicitStatic # optimization: implicit at compile time optImplicitStatic, # optimization: implicit at compile time
# evaluation # evaluation
optPatterns # en/disable pattern matching
TOptions* = set[TOption] TOptions* = set[TOption]
TGlobalOption* = enum # **keep binary compatible** TGlobalOption* = enum # **keep binary compatible**
gloptNone, optForceFullMake, optBoehmGC, optRefcGC, optDeadCodeElim, gloptNone, optForceFullMake, optBoehmGC, optRefcGC, optDeadCodeElim,
@ -82,7 +83,8 @@ const
var var
gOptions*: TOptions = {optObjCheck, optFieldCheck, optRangeCheck, gOptions*: TOptions = {optObjCheck, optFieldCheck, optRangeCheck,
optBoundsCheck, optOverflowCheck, optAssert, optWarns, optBoundsCheck, optOverflowCheck, optAssert, optWarns,
optHints, optStackTrace, optLineTrace} optHints, optStackTrace, optLineTrace,
optPatterns}
gGlobalOptions*: TGlobalOptions = {optRefcGC, optThreadAnalysis} gGlobalOptions*: TGlobalOptions = {optRefcGC, optThreadAnalysis}
gExitcode*: int8 gExitcode*: int8
searchPaths*: TLinkedList searchPaths*: TLinkedList

View file

@ -700,10 +700,12 @@ proc parseDoBlock(p: var TParser): PNode =
eat(p, tkColon) eat(p, tkColon)
result = newNodeI(nkDo, info) result = newNodeI(nkDo, info)
addSon(result, ast.emptyNode) # no name part addSon(result, ast.emptyNode) # no name part
addSon(result, ast.emptyNode) # no pattern part
addSon(result, ast.emptyNode) # no generic parameters addSon(result, ast.emptyNode) # no generic parameters
addSon(result, params) addSon(result, params)
addSon(result, pragmas) addSon(result, pragmas)
skipComment(p, result) skipComment(p, result)
addSon(result, ast.emptyNode) # no exception list
addSon(result, parseStmt(p)) addSon(result, parseStmt(p))
proc parseDoBlocks(p: var TParser, call: PNode) = proc parseDoBlocks(p: var TParser, call: PNode) =
@ -720,14 +722,16 @@ proc parseProcExpr(p: var TParser, isExpr: bool): PNode =
let hasSignature = p.tok.tokType in {tkParLe, tkColon} let hasSignature = p.tok.tokType in {tkParLe, tkColon}
params = parseParamList(p) params = parseParamList(p)
pragmas = optPragmas(p) pragmas = optPragmas(p)
if (p.tok.tokType == tkEquals) and isExpr: if p.tok.tokType == tkEquals and isExpr:
result = newNodeI(nkLambda, info) result = newNodeI(nkLambda, info)
addSon(result, ast.emptyNode) # no name part addSon(result, ast.emptyNode) # no name part
addSon(result, ast.emptyNode) # no pattern
addSon(result, ast.emptyNode) # no generic parameters addSon(result, ast.emptyNode) # no generic parameters
addSon(result, params) addSon(result, params)
addSon(result, pragmas) addSon(result, pragmas)
getTok(p) getTok(p)
skipComment(p, result) skipComment(p, result)
addSon(result, ast.emptyNode) # no exception list
addSon(result, parseStmt(p)) addSon(result, parseStmt(p))
else: else:
result = newNodeI(nkProcTy, info) result = newNodeI(nkProcTy, info)
@ -961,23 +965,14 @@ proc parseYieldOrDiscard(p: var TParser, kind: TNodeKind): PNode =
optInd(p, result) optInd(p, result)
addSon(result, parseExpr(p)) addSon(result, parseExpr(p))
proc parseBreakOrContinue(p: var TParser, kind: TNodeKind): PNode = proc parseBreakOrContinue(p: var TParser, kind: TNodeKind): PNode =
result = newNodeP(kind, p) result = newNodeP(kind, p)
getTok(p) getTok(p)
optInd(p, result) optInd(p, result)
case p.tok.tokType case p.tok.tokType
of tkEof, tkSad, tkDed: addSon(result, ast.emptyNode) of tkEof, tkSad, tkDed: addSon(result, ast.emptyNode)
else: addSon(result, parseSymbol(p)) else: addSon(result, parseSymbol(p))
proc parseAs(p: var TParser): PNode =
result = newNodeP(nkPatternStmt, p)
getTok(p) # skip `as`
if p.tok.tokType == tkColon:
eat(p, tkColon)
addSon(result, parseStmt(p))
else:
addSon(result, parseExpr(p))
proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode = proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode =
result = newNodeP(kind, p) result = newNodeP(kind, p)
while true: while true:
@ -1175,17 +1170,24 @@ proc parseGenericParamList(p: var TParser): PNode =
optPar(p) optPar(p)
eat(p, tkBracketRi) eat(p, tkBracketRi)
proc parsePattern(p: var TParser): PNode =
eat(p, tkCurlyLe)
result = parseStmt(p)
eat(p, tkCurlyRi)
proc parseRoutine(p: var TParser, kind: TNodeKind): PNode = proc parseRoutine(p: var TParser, kind: TNodeKind): PNode =
result = newNodeP(kind, p) result = newNodeP(kind, p)
getTok(p) getTok(p)
optInd(p, result) optInd(p, result)
addSon(result, identVis(p)) addSon(result, identVis(p))
if p.tok.tokType == tkCurlyLe: addSon(result, parsePattern(p))
else: addSon(result, ast.emptyNode)
if p.tok.tokType == tkBracketLe: addSon(result, parseGenericParamList(p)) if p.tok.tokType == tkBracketLe: addSon(result, parseGenericParamList(p))
else: addSon(result, ast.emptyNode) else: addSon(result, ast.emptyNode)
addSon(result, parseParamList(p)) addSon(result, parseParamList(p))
if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p)) if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
else: addSon(result, ast.emptyNode) else: addSon(result, ast.emptyNode)
# empty pattern: # empty exception tracking:
addSon(result, ast.emptyNode) addSon(result, ast.emptyNode)
if p.tok.tokType == tkEquals: if p.tok.tokType == tkEquals:
getTok(p) getTok(p)
@ -1522,7 +1524,6 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
of tkWhen: result = parseIfOrWhen(p, nkWhenStmt) of tkWhen: result = parseIfOrWhen(p, nkWhenStmt)
of tkVar: result = parseSection(p, nkVarSection, parseVariable) of tkVar: result = parseSection(p, nkVarSection, parseVariable)
of tkBind: result = parseBind(p) of tkBind: result = parseBind(p)
of tkAs: result = parseAs(p)
else: result = simpleStmt(p) else: result = simpleStmt(p)
proc parseStmt(p: var TParser): PNode = proc parseStmt(p: var TParser): PNode =

View file

@ -92,7 +92,15 @@ proc matches(c: PPatternContext, p, n: PNode): bool =
of nkCharLit..nkInt64Lit: result = p.intVal == n.intVal of nkCharLit..nkInt64Lit: result = p.intVal == n.intVal
of nkFloatLit..nkFloat64Lit: result = p.floatVal == n.floatVal of nkFloatLit..nkFloat64Lit: result = p.floatVal == n.floatVal
of nkStrLit..nkTripleStrLit: result = p.strVal == n.strVal of nkStrLit..nkTripleStrLit: result = p.strVal == n.strVal
of nkEmpty, nkNilLit, nkType: result = true of nkEmpty, nkNilLit, nkType:
result = true
# of nkStmtList:
# both are statement lists; we need to ignore comment statements and
# 'nil' statements and check whether p <: n which is however trivially
# checked as 'applyRule' is checked after every created statement
# already; We need to ensure that the matching span is passed to the
# macro and NOT simply 'n'!
# XXX
else: else:
if sonsLen(p) == sonsLen(n): if sonsLen(p) == sonsLen(n):
for i in countup(0, sonsLen(p) - 1): for i in countup(0, sonsLen(p) - 1):
@ -121,8 +129,6 @@ proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
let param = params.sons[i].sym let param = params.sons[i].sym
let x = IdNodeTableGetLazy(ctx.mapping, param) let x = IdNodeTableGetLazy(ctx.mapping, param)
# couldn't bind parameter: # couldn't bind parameter:
if isNil(x): if isNil(x): return nil
echo "couldn't bind ", param.name.s
return nil
result.add(x) result.add(x)
markUsed(n, s)

View file

@ -41,7 +41,7 @@ const
wFatal, wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop, wFatal, wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop,
wBreakpoint, wWatchpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated, wBreakpoint, wWatchpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated,
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
wLinearScanEnd} wLinearScanEnd, wPatterns}
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
wDeprecated, wExtern, wThread, wImportcpp, wImportobjc, wNoStackFrame} wDeprecated, wExtern, wThread, wImportcpp, wImportobjc, wNoStackFrame}
@ -302,6 +302,7 @@ proc processOption(c: PContext, n: PNode) =
excl(gOptions, optOptimizeSize) excl(gOptions, optOptimizeSize)
else: LocalError(n.info, errNoneSpeedOrSizeExpected) else: LocalError(n.info, errNoneSpeedOrSizeExpected)
of wImplicitStatic: OnOff(c, n, {optImplicitStatic}) of wImplicitStatic: OnOff(c, n, {optImplicitStatic})
of wPatterns: OnOff(c, n, {optPatterns})
else: LocalError(n.info, errOptionExpected) else: LocalError(n.info, errOptionExpected)
proc processPush(c: PContext, n: PNode, start: int) = proc processPush(c: PContext, n: PNode, start: int) =
@ -643,7 +644,8 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
wLinedir, wStacktrace, wLinetrace, wOptimization, wLinedir, wStacktrace, wLinetrace, wOptimization,
wCallConv, wCallConv,
wDebugger, wProfiler, wFloatChecks, wNanChecks, wInfChecks: wDebugger, wProfiler, wFloatChecks, wNanChecks, wInfChecks,
wPatterns:
processOption(c, it) # calling conventions (boring...): processOption(c, it) # calling conventions (boring...):
of firstCallConv..lastCallConv: of firstCallConv..lastCallConv:
assert(sym != nil) assert(sym != nil)

View file

@ -588,13 +588,13 @@ proc gwhile(g: var TSrcGen, n: PNode) =
proc gpattern(g: var TSrcGen, n: PNode) = proc gpattern(g: var TSrcGen, n: PNode) =
var c: TContext var c: TContext
put(g, tkAs, "as") put(g, tkCurlyLe, "{")
putWithSpace(g, tkColon, ":")
initContext(c) initContext(c)
if longMode(n) or (lsub(n.sons[0]) + g.lineLen > maxLineLen): if longMode(n) or (lsub(n.sons[0]) + g.lineLen > maxLineLen):
incl(c.flags, rfLongMode) incl(c.flags, rfLongMode)
gcoms(g) # a good place for comments gcoms(g) # a good place for comments
gstmts(g, n.sons[0], c) gstmts(g, n.sons[0], c)
put(g, tkCurlyRi, "}")
proc gpragmaBlock(g: var TSrcGen, n: PNode) = proc gpragmaBlock(g: var TSrcGen, n: PNode) =
var c: TContext var c: TContext
@ -666,6 +666,7 @@ proc gproc(g: var TSrcGen, n: PNode) =
put(g, tkSymbol, renderDefinitionName(n.sons[namePos].sym)) put(g, tkSymbol, renderDefinitionName(n.sons[namePos].sym))
else: else:
gsub(g, n.sons[namePos]) gsub(g, n.sons[namePos])
gsub(g, n.sons[patternPos])
gsub(g, n.sons[genericParamsPos]) gsub(g, n.sons[genericParamsPos])
gsub(g, n.sons[paramsPos]) gsub(g, n.sons[paramsPos])
gsub(g, n.sons[pragmasPos]) gsub(g, n.sons[pragmasPos])
@ -1045,7 +1046,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
of nkCaseStmt, nkRecCase: gcase(g, n) of nkCaseStmt, nkRecCase: gcase(g, n)
of nkMacroStmt: gmacro(g, n) of nkMacroStmt: gmacro(g, n)
of nkTryStmt: gtry(g, n) of nkTryStmt: gtry(g, n)
of nkPatternStmt: gpattern(g, n) of nkPattern: gpattern(g, n)
of nkForStmt, nkParForStmt: gfor(g, n) of nkForStmt, nkParForStmt: gfor(g, n)
of nkBlockStmt, nkBlockExpr: gblock(g, n) of nkBlockStmt, nkBlockExpr: gblock(g, n)
of nkStaticStmt: gstaticStmt(g, n) of nkStaticStmt: gstaticStmt(g, n)

View file

@ -104,7 +104,7 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
proc applyPatterns(c: PContext, n: PNode): PNode = proc applyPatterns(c: PContext, n: PNode): PNode =
# fast exit: # fast exit:
if c.patterns.len == 0: return n if c.patterns.len == 0 or optPatterns notin gOptions: return n
result = n result = n
# we apply the last pattern first, so that pattern overriding is possible; # we apply the last pattern first, so that pattern overriding is possible;
# however the resulting AST would better not trigger the old rule then # however the resulting AST would better not trigger the old rule then
@ -113,7 +113,11 @@ proc applyPatterns(c: PContext, n: PNode): PNode =
let x = applyRule(c, c.patterns[i], result) let x = applyRule(c, c.patterns[i], result)
if not isNil(x): if not isNil(x):
assert x.kind == nkCall assert x.kind == nkCall
inc(evalTemplateCounter)
if evalTemplateCounter > 100:
GlobalError(n.info, errTemplateInstantiationTooNested)
result = semExpr(c, x) result = semExpr(c, x)
dec(evalTemplateCounter)
include seminst, semcall include seminst, semcall

View file

@ -770,6 +770,10 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
else: else:
s.typ = newTypeS(tyProc, c) s.typ = newTypeS(tyProc, c)
rawAddSon(s.typ, nil) rawAddSon(s.typ, nil)
if n.sons[patternPos].kind != nkEmpty:
n.sons[patternPos] = semPattern(c, n.sons[patternPos])
c.patterns.add(s)
var proto = SearchForProc(c, s, c.tab.tos-2) # -2 because we have a scope var proto = SearchForProc(c, s, c.tab.tos-2) # -2 because we have a scope
# open for parameters # open for parameters
if proto == nil: if proto == nil:
@ -1202,17 +1206,7 @@ proc SemStmt(c: PContext, n: PNode): PNode =
result = semPragmaBlock(c, n) result = semPragmaBlock(c, n)
of nkStaticStmt: of nkStaticStmt:
result = semStaticStmt(c, n) result = semStaticStmt(c, n)
of nkPatternStmt: else:
let pat = semPatternStmt(c, n)
let s = getCurrOwner()
if s.kind in routineKinds and s.ast.sons[patternPos].kind == nkEmpty:
s.ast.sons[patternPos] = pat
c.patterns.add(s)
else:
LocalError(n.info, errXNotAllowedHere, "'as'")
# replace by an empty statement:
result = newNodeI(nkNilLit, n.info)
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:
result = buildEchoStmt(c, semExpr(c, n)) result = buildEchoStmt(c, semExpr(c, n))

View file

@ -172,10 +172,11 @@ proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
else: else:
n.sons[namePos] = semTemplBody(c, n.sons[namePos]) n.sons[namePos] = semTemplBody(c, n.sons[namePos])
openScope(c) openScope(c)
for i in genericParamsPos..bodyPos: for i in patternPos..bodyPos:
n.sons[i] = semTemplBody(c, n.sons[i]) n.sons[i] = semTemplBody(c, n.sons[i])
closeScope(c) closeScope(c)
proc semPattern(c: PContext, n: PNode): PNode
proc semTemplBody(c: var TemplCtx, n: PNode): PNode = proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
result = n result = n
case n.kind case n.kind
@ -396,7 +397,10 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
s.typ.n = newNodeI(nkFormalParams, n.info) s.typ.n = newNodeI(nkFormalParams, n.info)
rawAddSon(s.typ, newTypeS(tyStmt, c)) rawAddSon(s.typ, newTypeS(tyStmt, c))
addSon(s.typ.n, newNodeIT(nkType, n.info, s.typ.sons[0])) addSon(s.typ.n, newNodeIT(nkType, n.info, s.typ.sons[0]))
if n.sons[patternPos].kind != nkEmpty:
n.sons[patternPos] = semPattern(c, n.sons[patternPos])
c.patterns.add(s)
var ctx: TemplCtx var ctx: TemplCtx
ctx.toBind = initIntSet() ctx.toBind = initIntSet()
ctx.c = c ctx.c = c
@ -422,7 +426,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
else: else:
SymTabReplace(c.tab.stack[curScope], proto, s) SymTabReplace(c.tab.stack[curScope], proto, s)
proc semPatternStmt(c: PContext, n: PNode): PNode = proc semPattern(c: PContext, n: PNode): PNode =
# not much to do here: We don't replace operators ``$``, ``*``, ``+``, # not much to do here: We don't replace operators ``$``, ``*``, ``+``,
# ``|``, ``~`` as meta operators and strip the leading ``\`` of all # ``|``, ``~`` as meta operators and strip the leading ``\`` of all
# operators. # operators.
@ -432,5 +436,7 @@ proc semPatternStmt(c: PContext, n: PNode): PNode =
ctx.c = c ctx.c = c
ctx.owner = getCurrOwner() ctx.owner = getCurrOwner()
ctx.bodyKind = bkPattern ctx.bodyKind = bkPattern
result = semTemplBody(ctx, n.sons[0]) result = semTemplBody(ctx, n)
if result.kind in {nkStmtList, nkStmtListExpr} and result.len == 1:
result = result.sons[0]
closeScope(c.tab) closeScope(c.tab)

View file

@ -51,7 +51,7 @@ type
wFastcall, wClosure, wNoconv, wOn, wOff, wChecks, wRangechecks, wFastcall, wClosure, wNoconv, wOn, wOff, wChecks, wRangechecks,
wBoundchecks, wOverflowchecks, wNilchecks, wBoundchecks, wOverflowchecks, wNilchecks,
wFloatchecks, wNanChecks, wInfChecks, wFloatchecks, wNanChecks, wInfChecks,
wAssertions, wWarnings, wAssertions, wPatterns, wWarnings,
wHints, wOptimization, wSpeed, wSize, wNone, wHints, wOptimization, wSpeed, wSize, wNone,
wDeadCodeElim, wSafecode, wDeadCodeElim, wSafecode,
wPragma, wPragma,
@ -131,7 +131,7 @@ const
"overflowchecks", "nilchecks", "overflowchecks", "nilchecks",
"floatchecks", "nanchecks", "infchecks", "floatchecks", "nanchecks", "infchecks",
"assertions", "warnings", "hints", "assertions", "patterns", "warnings", "hints",
"optimization", "speed", "size", "none", "optimization", "speed", "size", "none",
"deadcodeelim", "safecode", "deadcodeelim", "safecode",
"pragma", "pragma",

View file

@ -55,6 +55,7 @@ Advanced options:
--taintMode:on|off turn taint mode on|off --taintMode:on|off turn taint mode on|off
--symbolFiles:on|off turn symbol files on|off (experimental) --symbolFiles:on|off turn symbol files on|off (experimental)
--implicitStatic:on|off turn implicit compile time evaluation on|off --implicitStatic:on|off turn implicit compile time evaluation on|off
--patterns:on|off turn pattern matching on|off
--skipCfg do not read the general configuration file --skipCfg do not read the general configuration file
--skipUserCfg do not read the user's configuration file --skipUserCfg do not read the user's configuration file
--skipParentCfg do not read the parent dirs' configuration files --skipParentCfg do not read the parent dirs' configuration files

View file

@ -46,7 +46,7 @@ type
nnkYieldStmt, nnkTryStmt, nnkFinally, nnkRaiseStmt, nnkYieldStmt, nnkTryStmt, nnkFinally, nnkRaiseStmt,
nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkStaticStmt, nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkStaticStmt,
nnkDiscardStmt, nnkStmtList, nnkImportStmt, nnkFromStmt, nnkDiscardStmt, nnkStmtList, nnkImportStmt, nnkFromStmt,
nnkIncludeStmt, nnkBindStmt, nnkPatternStmt, nnkIncludeStmt, nnkBindStmt, nnkPattern,
nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr, nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr,
nnkStmtListType, nnkBlockType, nnkTypeOfExpr, nnkObjectTy, nnkStmtListType, nnkBlockType, nnkTypeOfExpr, nnkObjectTy,
nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen, nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen,

View file

@ -92,7 +92,9 @@ template fail* =
TestStatusIMPL = FAILED TestStatusIMPL = FAILED
checkpoints = @[] checkpoints = @[]
macro check*(conditions: stmt): stmt = macro check*(conditions: stmt): stmt =
let conditions = callsite()
proc standardRewrite(e: PNimrodNode): PNimrodNode = proc standardRewrite(e: PNimrodNode): PNimrodNode =
template rewrite(Exp, lineInfoLit: expr, expLit: string): stmt = template rewrite(Exp, lineInfoLit: expr, expLit: string): stmt =
if not Exp: if not Exp:

View file

@ -0,0 +1,28 @@
discard """
line: 24
errormsg: "usage of 'disallowIf' is a user-defined error"
"""
template optZero{x+x}(x: int): int = x*3
template andthen{x*3}(x: int): int = x*4
template optSubstr1{x = substr(x, a, b)}(x: string, a, b: int) = setlen(x, b+1)
template disallowIf{
if cond: action
else: action2
}(cond: bool, action, action2: stmt) {.error.} = action
var y = 12
echo y+y
var s: array[0..2, string]
s[0] = "hello"
s[0] = substr(s[0], 0, 2)
echo s[0]
if true:
echo "do it"
echo "more branches"
else:
nil

17
tests/run/tpatterns.nim Normal file
View file

@ -0,0 +1,17 @@
discard """
output: '''48
hel'''
"""
template optZero{x+x}(x: int): int = x*3
template andthen{x*3}(x: int): int = x*4
template optSubstr1{x = substr(x, a, b)}(x: string, a, b: int) = setlen(x, b+1)
var y = 12
echo y+y
var s: array[0..2, string]
s[0] = "hello"
s[0] = substr(s[0], 0, 2)
echo s[0]

View file

@ -3,7 +3,7 @@ version 0.9.0
- make 'm: stmt' use overloading resolution - make 'm: stmt' use overloading resolution
- implement the high level optimizer - improve pattern matching: introduce meta operators, statement list support
- make 'bind' default for templates and introduce 'mixin' - make 'bind' default for templates and introduce 'mixin'
- implement "closure tuple consists of a single 'ref'" optimization - implement "closure tuple consists of a single 'ref'" optimization