merged branch overloading-for-macros

This commit is contained in:
Zahary Karadjov
2012-03-19 12:06:38 +02:00
39 changed files with 366 additions and 218 deletions

View File

@@ -8,6 +8,7 @@
#
# this module does the semantic checking for expressions
# included from sem.nim
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode =
markUsed(n, s)
@@ -103,7 +104,8 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
if s.ast == nil: InternalError(n.info, "no default for")
result = semExpr(c, s.ast)
of skType:
if efAllowType notin flags: GlobalError(n.info, errATypeHasNoValue)
if efAllowType notin flags:
GlobalError(n.info, errATypeHasNoValue)
markUsed(n, s)
result = newSymNode(s, n.info)
else:
@@ -245,17 +247,17 @@ proc semIs(c: PContext, n: PNode): PNode =
else:
GlobalError(n.info, errXExpectsTwoArguments, "is")
proc semOpAux(c: PContext, n: PNode) =
for i in countup(1, sonsLen(n) - 1):
proc semOpAux(c: PContext, n: PNode) =
for i in countup(1, sonsLen(n) - 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], {efAllowType})
a.typ = a.sons[1].typ
else:
n.sons[i] = semExprWithType(c, a)
else:
n.sons[i] = semExprWithType(c, a, {efAllowType})
proc overloadedCallOpr(c: PContext, n: PNode): PNode =
# quick check if there is *any* () operator overloaded:
var par = getIdent("()")
@@ -514,25 +516,32 @@ proc semStaticExpr(c: PContext, n: PNode): PNode =
if result.isNil:
LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
proc semDirectCallAnalyseEffects(c: PContext, n: PNode,
flags: TExprFlags): PNode =
proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
flags: TExprFlags): PNode =
if efWantIterator in flags:
result = semDirectCall(c, n, {skIterator})
result = semOverloadedCall(c, n, nOrig, {skIterator})
elif efInTypeOf in flags:
# for ``type(countup(1,3))``, see ``tests/ttoseq``.
result = semDirectCall(c, n, {skIterator, skProc, skMethod, skConverter})
result = semOverloadedCall(c, n, nOrig, {skIterator, skProc, skMethod, skConverter, skMacro, skTemplate})
else:
result = semDirectCall(c, n, {skProc, skMethod, skConverter})
result = semOverloadedCall(c, n, nOrig, {skProc, skMethod, skConverter, skMacro, skTemplate})
if result != nil:
if result.sons[0].kind != nkSym:
InternalError("semDirectCallAnalyseEffects")
var callee = result.sons[0].sym
if (callee.kind == skIterator) and (callee.id == c.p.owner.id):
GlobalError(n.info, errRecursiveDependencyX, callee.name.s)
if sfNoSideEffect notin callee.flags:
if {sfImportc, sfSideEffect} * callee.flags != {}:
incl(c.p.owner.flags, sfSideEffect)
let callee = result.sons[0].sym
case callee.kind
of skMacro, skTemplate: nil
else:
if (callee.kind == skIterator) and (callee.id == c.p.owner.id):
GlobalError(n.info, errRecursiveDependencyX, callee.name.s)
if sfNoSideEffect notin callee.flags:
if {sfImportc, sfSideEffect} * callee.flags != {}:
incl(c.p.owner.flags, sfSideEffect)
proc semDirectCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
flags: TExprFlags): PNode =
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = nil
var prc = n.sons[0]
@@ -548,13 +557,14 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
return semExpr(c, result, flags)
else:
n.sons[0] = semExpr(c, n.sons[0])
let nOrig = n.copyTree
semOpAux(c, n)
var t: PType = nil
if (n.sons[0].typ != nil): t = skipTypes(n.sons[0].typ, abstractInst)
if (t != nil) and (t.kind == tyProc):
var m: TCandidate
initCandidate(m, t)
matches(c, n, m)
matches(c, n, nOrig, m)
if m.state != csMatch:
var msg = msgKindToString(errTypeMismatch)
for i in countup(1, sonsLen(n) - 1):
@@ -575,7 +585,8 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
# the old ``prc`` (which is likely an nkIdent) has to be restored:
if result == nil:
n.sons[0] = prc
result = semDirectCallAnalyseEffects(c, n, flags)
nOrig.sons[0] = prc
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
if result == nil:
GlobalError(n.info, errExprXCannotBeCalled,
renderTree(n, {renderNoComments}))
@@ -587,15 +598,21 @@ 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)
result = semDirectCallAnalyseEffects(c, n, flags)
if result == nil:
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
if result == nil:
result = overloadedCallOpr(c, n)
if result == nil: GlobalError(n.Info, errGenerated, getNotFoundError(c, n))
fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result)
if result.sons[0].sym.magic != mNone:
result = magicsAfterOverloadResolution(c, result, flags)
let callee = result.sons[0].sym
case callee.kind
of skMacro: result = semMacroExpr(c, nOrig, callee)
of skTemplate: result = semTemplateExpr(c, nOrig, callee)
else:
fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result)
if callee.magic != mNone:
result = magicsAfterOverloadResolution(c, result, flags)
result = evalAtCompileTime(c, result)
proc buildStringify(c: PContext, arg: PNode): PNode =
@@ -734,7 +751,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
result.typ = ty
markUsed(n, f)
return
elif efAllowType notin flags:
elif efAllowType notin flags:
GlobalError(n.sons[0].info, errATypeHasNoValue)
return
# reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim":
@@ -852,16 +869,16 @@ proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
# overloaded [] operator:
result = semExpr(c, buildOverloadedSubscripts(n, getIdent"[]"))
proc propertyWriteAccess(c: PContext, n, a: PNode): PNode =
proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
var id = considerAcc(a[1])
result = newNodeI(nkCall, n.info)
addSon(result, newIdentNode(getIdent(id.s & '='), n.info))
let setterId = newIdentNode(getIdent(id.s & '='), n.info)
# a[0] is already checked for semantics, that does ``builtinFieldAccess``
# this is ugly. XXX Semantic checking should use the ``nfSem`` flag for
# nodes?
addSon(result, a[0])
addSon(result, semExpr(c, n[1]))
result = semDirectCallAnalyseEffects(c, result, {})
let aOrig = nOrig[0]
result = newNode(nkCall, n.info, sons = @[setterId, a[0], semExpr(c, n[1])])
let orig = newNode(nkCall, n.info, sons = @[setterId, aOrig[0], nOrig[1]])
result = semDirectCallAnalyseEffects(c, result, orig, {})
if result != nil:
fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result)
@@ -898,9 +915,10 @@ proc semAsgn(c: PContext, n: PNode): PNode =
of nkDotExpr:
# r.f = x
# --> `f=` (r, x)
let nOrig = n.copyTree
a = builtinFieldAccess(c, a, {efLValue})
if a == nil:
return propertyWriteAccess(c, n, n[0])
return propertyWriteAccess(c, n, nOrig, a)
of nkBracketExpr:
# a[i] = x
# --> `[]=`(a, i, x)
@@ -1275,8 +1293,16 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
var s = qualifiedLookup(c, n.sons[0], {checkUndeclared})
if s != nil:
case s.kind
of skMacro: result = semMacroExpr(c, n, s)
of skTemplate: result = semTemplateExpr(c, n, s)
of skMacro:
if false and sfImmediate notin s.flags: # XXX not yet enabled
result = semDirectOp(c, n, flags)
else:
result = semMacroExpr(c, n, s)
of skTemplate:
if sfImmediate notin s.flags:
result = semDirectOp(c, n, flags)
else:
result = semTemplateExpr(c, n, s)
of skType:
# XXX think about this more (``set`` procs)
if n.len == 2: