diff options
Diffstat (limited to 'compiler/semexprs.nim')
-rwxr-xr-x | compiler/semexprs.nim | 100 |
1 files changed, 63 insertions, 37 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index d423acc17..d3b30e24b 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -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: |