mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
improvements for TR macros
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# 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:
|
||||
Message(orig.info, hintPattern, rule & " --> '" &
|
||||
renderTree(result, {renderNoComments}) & "'")
|
||||
# check the resulting AST for optimization rules again:
|
||||
result = hlo(c, result)
|
||||
|
||||
proc applyPatterns(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
@@ -44,11 +42,12 @@ proc applyPatterns(c: PContext, n: PNode): PNode =
|
||||
let x = applyRule(c, pattern, result)
|
||||
if not isNil(x):
|
||||
assert x.kind in {nkStmtList, nkCall}
|
||||
# better be safe than sorry, so check evalTemplateCounter too:
|
||||
inc(evalTemplateCounter)
|
||||
if evalTemplateCounter > 100:
|
||||
GlobalError(n.info, errTemplateInstantiationTooNested)
|
||||
# deactivate this pattern:
|
||||
c.patterns[i] = nil
|
||||
#c.patterns[i] = nil
|
||||
if x.kind == nkStmtList:
|
||||
assert x.len == 3
|
||||
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)
|
||||
dec(evalTemplateCounter)
|
||||
# activate this pattern again:
|
||||
c.patterns[i] = pattern
|
||||
#c.patterns[i] = pattern
|
||||
|
||||
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
|
||||
of nkMacroDef, nkTemplateDef, procDefs:
|
||||
# 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
|
||||
else:
|
||||
# perform type checking, so that the replacement still fits:
|
||||
if n.typ == nil and (result.typ == nil or
|
||||
result.typ.kind in {tyStmt, tyEmpty}):
|
||||
if isEmptyType(n.typ) and isEmptyType(result.typ):
|
||||
nil
|
||||
else:
|
||||
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 =
|
||||
# fast exit:
|
||||
if c.patterns.len == 0 or optPatterns notin gOptions: return n
|
||||
c.hloLoopDetector = 0
|
||||
result = hlo(c, n)
|
||||
|
||||
proc hloStmt(c: PContext, n: PNode): PNode =
|
||||
# fast exit:
|
||||
if c.patterns.len == 0 or optPatterns notin gOptions: return n
|
||||
c.hloLoopDetector = 0
|
||||
result = hlo(c, n)
|
||||
|
||||
@@ -237,15 +237,6 @@ proc addToArgList(result, n: PNode) =
|
||||
else:
|
||||
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 =
|
||||
## returns a tree to semcheck if the rule triggered; nil otherwise
|
||||
var ctx: TPatternContext
|
||||
|
||||
@@ -85,6 +85,7 @@ type
|
||||
# naming it multiple times
|
||||
generics*: seq[TInstantiationPair] # pending list of instantiated generics to compile
|
||||
lastGenericIdx*: int # used for the generics stack
|
||||
hloLoopDetector*: int # used to prevent endless loops in the HLO
|
||||
|
||||
proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair =
|
||||
result.genericSym = s
|
||||
|
||||
@@ -574,9 +574,14 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
||||
fc.c = c
|
||||
semForObjectFields(fc, tupleTypeA.n, n, stmts)
|
||||
Dec(c.p.nestedLoopCounter)
|
||||
var b = newNodeI(nkBreakStmt, n.info)
|
||||
b.add(ast.emptyNode)
|
||||
stmts.add(b)
|
||||
# for TR macros this 'while true: ...; break' loop is pretty bad, so
|
||||
# we avoid it now if we can:
|
||||
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) =
|
||||
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
|
||||
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 =
|
||||
case n.kind
|
||||
of nkSym:
|
||||
|
||||
2
todo.txt
2
todo.txt
@@ -12,8 +12,6 @@ version 0.9.4
|
||||
- special rule for ``[]=``
|
||||
- ``=`` should be overloadable; requires specialization for ``=``; general
|
||||
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'
|
||||
- optimize 'genericReset'; 'newException' leads to code bloat
|
||||
- stack-less GC
|
||||
|
||||
Reference in New Issue
Block a user