improvements for TR macros
This commit is contained in:
parent
823cb494a5
commit
9de3bc8ef6
6 changed files with 53 additions and 21 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2012 Andreas Rumpf
|
# (c) Copyright 2013 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -30,8 +30,6 @@ proc evalPattern(c: PContext, n, orig: PNode): PNode =
|
||||||
if optHints in gOptions and hintPattern in gNotes:
|
if optHints in gOptions and hintPattern in gNotes:
|
||||||
Message(orig.info, hintPattern, rule & " --> '" &
|
Message(orig.info, hintPattern, rule & " --> '" &
|
||||||
renderTree(result, {renderNoComments}) & "'")
|
renderTree(result, {renderNoComments}) & "'")
|
||||||
# check the resulting AST for optimization rules again:
|
|
||||||
result = hlo(c, result)
|
|
||||||
|
|
||||||
proc applyPatterns(c: PContext, n: PNode): PNode =
|
proc applyPatterns(c: PContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
|
|
@ -44,11 +42,12 @@ proc applyPatterns(c: PContext, n: PNode): PNode =
|
||||||
let x = applyRule(c, pattern, result)
|
let x = applyRule(c, pattern, result)
|
||||||
if not isNil(x):
|
if not isNil(x):
|
||||||
assert x.kind in {nkStmtList, nkCall}
|
assert x.kind in {nkStmtList, nkCall}
|
||||||
|
# better be safe than sorry, so check evalTemplateCounter too:
|
||||||
inc(evalTemplateCounter)
|
inc(evalTemplateCounter)
|
||||||
if evalTemplateCounter > 100:
|
if evalTemplateCounter > 100:
|
||||||
GlobalError(n.info, errTemplateInstantiationTooNested)
|
GlobalError(n.info, errTemplateInstantiationTooNested)
|
||||||
# deactivate this pattern:
|
# deactivate this pattern:
|
||||||
c.patterns[i] = nil
|
#c.patterns[i] = nil
|
||||||
if x.kind == nkStmtList:
|
if x.kind == nkStmtList:
|
||||||
assert x.len == 3
|
assert x.len == 3
|
||||||
x.sons[1] = evalPattern(c, x.sons[1], result)
|
x.sons[1] = evalPattern(c, x.sons[1], result)
|
||||||
|
|
@ -57,9 +56,12 @@ proc applyPatterns(c: PContext, n: PNode): PNode =
|
||||||
result = evalPattern(c, x, result)
|
result = evalPattern(c, x, result)
|
||||||
dec(evalTemplateCounter)
|
dec(evalTemplateCounter)
|
||||||
# activate this pattern again:
|
# activate this pattern again:
|
||||||
c.patterns[i] = pattern
|
#c.patterns[i] = pattern
|
||||||
|
|
||||||
proc hlo(c: PContext, n: PNode): PNode =
|
proc hlo(c: PContext, n: PNode): PNode =
|
||||||
|
inc(c.hloLoopDetector)
|
||||||
|
# simply stop and do not perform any further transformations:
|
||||||
|
if c.hloLoopDetector > 300: result = n
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkMacroDef, nkTemplateDef, procDefs:
|
of nkMacroDef, nkTemplateDef, procDefs:
|
||||||
# already processed (special cases in semstmts.nim)
|
# already processed (special cases in semstmts.nim)
|
||||||
|
|
@ -74,18 +76,23 @@ proc hlo(c: PContext, n: PNode): PNode =
|
||||||
if h != a: result.sons[i] = h
|
if h != a: result.sons[i] = h
|
||||||
else:
|
else:
|
||||||
# perform type checking, so that the replacement still fits:
|
# perform type checking, so that the replacement still fits:
|
||||||
if n.typ == nil and (result.typ == nil or
|
if isEmptyType(n.typ) and isEmptyType(result.typ):
|
||||||
result.typ.kind in {tyStmt, tyEmpty}):
|
|
||||||
nil
|
nil
|
||||||
else:
|
else:
|
||||||
result = fitNode(c, n.typ, result)
|
result = fitNode(c, n.typ, result)
|
||||||
|
# optimization has been applied so check again:
|
||||||
|
result = commonOptimizations(c.module, result)
|
||||||
|
result = hlo(c, result)
|
||||||
|
result = commonOptimizations(c.module, result)
|
||||||
|
|
||||||
proc hloBody(c: PContext, n: PNode): PNode =
|
proc hloBody(c: PContext, n: PNode): PNode =
|
||||||
# fast exit:
|
# fast exit:
|
||||||
if c.patterns.len == 0 or optPatterns notin gOptions: return n
|
if c.patterns.len == 0 or optPatterns notin gOptions: return n
|
||||||
|
c.hloLoopDetector = 0
|
||||||
result = hlo(c, n)
|
result = hlo(c, n)
|
||||||
|
|
||||||
proc hloStmt(c: PContext, n: PNode): PNode =
|
proc hloStmt(c: PContext, n: PNode): PNode =
|
||||||
# fast exit:
|
# fast exit:
|
||||||
if c.patterns.len == 0 or optPatterns notin gOptions: return n
|
if c.patterns.len == 0 or optPatterns notin gOptions: return n
|
||||||
|
c.hloLoopDetector = 0
|
||||||
result = hlo(c, n)
|
result = hlo(c, n)
|
||||||
|
|
|
||||||
|
|
@ -237,15 +237,6 @@ proc addToArgList(result, n: PNode) =
|
||||||
else:
|
else:
|
||||||
for i in 0 .. <n.len: result.add(n.sons[i])
|
for i in 0 .. <n.len: result.add(n.sons[i])
|
||||||
|
|
||||||
when false:
|
|
||||||
proc procPatternMatches*(c: PContext, s: PSym, n: PNode): bool =
|
|
||||||
## for AST-based overloading:
|
|
||||||
var ctx: TPatternContext
|
|
||||||
ctx.owner = s
|
|
||||||
ctx.c = c
|
|
||||||
ctx.formals = sonsLen(s.typ)-1
|
|
||||||
result = matches(ctx, s.ast.sons[patternPos], n)
|
|
||||||
|
|
||||||
proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
|
proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
|
||||||
## returns a tree to semcheck if the rule triggered; nil otherwise
|
## returns a tree to semcheck if the rule triggered; nil otherwise
|
||||||
var ctx: TPatternContext
|
var ctx: TPatternContext
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,7 @@ type
|
||||||
# naming it multiple times
|
# naming it multiple times
|
||||||
generics*: seq[TInstantiationPair] # pending list of instantiated generics to compile
|
generics*: seq[TInstantiationPair] # pending list of instantiated generics to compile
|
||||||
lastGenericIdx*: int # used for the generics stack
|
lastGenericIdx*: int # used for the generics stack
|
||||||
|
hloLoopDetector*: int # used to prevent endless loops in the HLO
|
||||||
|
|
||||||
proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair =
|
proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair =
|
||||||
result.genericSym = s
|
result.genericSym = s
|
||||||
|
|
|
||||||
|
|
@ -574,9 +574,14 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
||||||
fc.c = c
|
fc.c = c
|
||||||
semForObjectFields(fc, tupleTypeA.n, n, stmts)
|
semForObjectFields(fc, tupleTypeA.n, n, stmts)
|
||||||
Dec(c.p.nestedLoopCounter)
|
Dec(c.p.nestedLoopCounter)
|
||||||
var b = newNodeI(nkBreakStmt, n.info)
|
# for TR macros this 'while true: ...; break' loop is pretty bad, so
|
||||||
b.add(ast.emptyNode)
|
# we avoid it now if we can:
|
||||||
stmts.add(b)
|
if hasSonWith(stmts, nkBreakStmt):
|
||||||
|
var b = newNodeI(nkBreakStmt, n.info)
|
||||||
|
b.add(ast.emptyNode)
|
||||||
|
stmts.add(b)
|
||||||
|
else:
|
||||||
|
result = stmts
|
||||||
|
|
||||||
proc addForVarDecl(c: PContext, v: PSym) =
|
proc addForVarDecl(c: PContext, v: PSym) =
|
||||||
if warnShadowIdent in gNotes:
|
if warnShadowIdent in gNotes:
|
||||||
|
|
|
||||||
|
|
@ -588,6 +588,36 @@ proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} =
|
||||||
result = orig.kind == nkSym and cnst.kind in {nkCurly, nkPar, nkBracket} and
|
result = orig.kind == nkSym and cnst.kind in {nkCurly, nkPar, nkBracket} and
|
||||||
cnst.len != 0
|
cnst.len != 0
|
||||||
|
|
||||||
|
proc commonOptimizations*(c: PSym, n: PNode): PNode =
|
||||||
|
result = n
|
||||||
|
for i in 0 .. < n.safeLen:
|
||||||
|
result.sons[i] = commonOptimizations(c, n.sons[i])
|
||||||
|
var op = getMergeOp(n)
|
||||||
|
if (op != nil) and (op.magic != mNone) and (sonsLen(n) >= 3):
|
||||||
|
result = newNodeIT(nkCall, n.info, n.typ)
|
||||||
|
add(result, n.sons[0])
|
||||||
|
var args = newNode(nkArgList)
|
||||||
|
flattenTreeAux(args, n, op)
|
||||||
|
var j = 0
|
||||||
|
while j < sonsLen(args):
|
||||||
|
var a = args.sons[j]
|
||||||
|
inc(j)
|
||||||
|
if isConstExpr(a):
|
||||||
|
while j < sonsLen(args):
|
||||||
|
let b = args.sons[j]
|
||||||
|
if not isConstExpr(b): break
|
||||||
|
a = evalOp(op.magic, result, a, b, nil)
|
||||||
|
inc(j)
|
||||||
|
add(result, a)
|
||||||
|
if len(result) == 2: result = result[1]
|
||||||
|
else:
|
||||||
|
var cnst = getConstExpr(c, n)
|
||||||
|
# we inline constants if they are not complex constants:
|
||||||
|
if cnst != nil and not dontInlineConstant(n, cnst):
|
||||||
|
result = cnst
|
||||||
|
else:
|
||||||
|
result = n
|
||||||
|
|
||||||
proc transform(c: PTransf, n: PNode): PTransNode =
|
proc transform(c: PTransf, n: PNode): PTransNode =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkSym:
|
of nkSym:
|
||||||
|
|
|
||||||
2
todo.txt
2
todo.txt
|
|
@ -12,8 +12,6 @@ version 0.9.4
|
||||||
- special rule for ``[]=``
|
- special rule for ``[]=``
|
||||||
- ``=`` should be overloadable; requires specialization for ``=``; general
|
- ``=`` should be overloadable; requires specialization for ``=``; general
|
||||||
lift mechanism in the compiler is already implemented for 'fields'
|
lift mechanism in the compiler is already implemented for 'fields'
|
||||||
- mocking support with ``tyProxy`` that does: fallback for ``.`` operator
|
|
||||||
- overloading of ``.``? Special case ``.=``?
|
|
||||||
- built-in 'getImpl'
|
- built-in 'getImpl'
|
||||||
- optimize 'genericReset'; 'newException' leads to code bloat
|
- optimize 'genericReset'; 'newException' leads to code bloat
|
||||||
- stack-less GC
|
- stack-less GC
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue