diff options
author | Araq <rumpf_a@web.de> | 2013-03-02 20:23:56 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-03-02 20:23:56 +0100 |
commit | eebee0eff2360219d02d4cf40675734f3361090a (patch) | |
tree | 2d53a720b7a17854e1d1d23f7a8ce7d270687080 /compiler | |
parent | dc07732daa71d0868dd4c5901fa1a23c0dcd382d (diff) | |
download | Nim-eebee0eff2360219d02d4cf40675734f3361090a.tar.gz |
lazy operand sem'checking (beware)
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/sem.nim | 16 | ||||
-rwxr-xr-x | compiler/semdata.nim | 7 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 22 | ||||
-rwxr-xr-x | compiler/semstmts.nim | 16 | ||||
-rwxr-xr-x | compiler/sigmatch.nim | 63 |
5 files changed, 81 insertions, 43 deletions
diff --git a/compiler/sem.nim b/compiler/sem.nim index 555f5e7b7..f20ab9a05 100755 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -19,13 +19,9 @@ import # implementation -type - TExprFlag = enum - efLValue, efWantIterator, efInTypeof, efWantStmt, efDetermineType - TExprFlags = set[TExprFlag] - -proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode -proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode +proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.procvar.} +proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode {. + procvar.} proc semExprNoType(c: PContext, n: PNode): PNode proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode proc semProcBody(c: PContext, n: PNode): PNode @@ -200,14 +196,12 @@ proc addCodeForGenerics(c: PContext, n: PNode) = addSon(n, prc.ast) c.lastGenericIdx = c.generics.len -proc semExprNoFlags(c: PContext, n: PNode): PNode {.procvar.} = - result = semExpr(c, n, {}) - proc myOpen(module: PSym): PPassContext = var c = newContext(module) if c.p != nil: InternalError(module.info, "sem.myOpen") c.semConstExpr = semConstExpr - c.semExpr = semExprNoFlags + c.semExpr = semExpr + c.semExprWithType = semExprWithType c.semConstBoolExpr = semConstBoolExpr c.semOverloadedCall = semOverloadedCall c.semTypeNode = semTypeNode diff --git a/compiler/semdata.nim b/compiler/semdata.nim index f5d5a9604..dd5f76172 100755 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -39,6 +39,10 @@ type TInstantiationPair* = object genericSym*: PSym inst*: PInstantiation + + TExprFlag* = enum + efLValue, efWantIterator, efInTypeof, efWantStmt, efDetermineType + TExprFlags* = set[TExprFlag] PContext* = ref TContext TContext* = object of TPassContext # a context represents a module @@ -64,7 +68,8 @@ type # to some new symbol in a generic instantiation libs*: TLinkedList # all libs used by this module semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas - semExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas + semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.} + semExprWithType*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.} semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet semOverloadedCall*: proc (c: PContext, n, nOrig: PNode, filter: TSymKinds): PNode {.nimcall.} diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 1fcd7105d..b6e328926 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -31,10 +31,6 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode = proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode -proc newDeref(n: PNode): PNode {.inline.} = - result = newNodeIT(nkHiddenDeref, n.info, n.typ.sons[0]) - addSon(result, n) - proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = result = semExpr(c, n, flags) if result.kind == nkEmpty: @@ -319,7 +315,7 @@ proc semIs(c: PContext, n: PNode): PNode = proc semOpAux(c: PContext, n: PNode) = const flags = {efDetermineType} - for i in countup(1, n.sonsLen- 1): + for i in countup(1, n.sonsLen-1): var a = n.sons[i] if a.kind == nkExprEqExpr and sonsLen(a) == 2: var info = a.sons[0].info @@ -328,7 +324,7 @@ proc semOpAux(c: PContext, n: PNode) = a.typ = a.sons[1].typ else: n.sons[i] = semExprWithType(c, a, flags) - + proc overloadedCallOpr(c: PContext, n: PNode): PNode = # quick check if there is *any* () operator overloaded: var par = getIdent("()") @@ -694,7 +690,7 @@ 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) + #semLazyOpAux(c, n) result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags) if result == nil: result = overloadedCallOpr(c, n) @@ -706,6 +702,7 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = of skMacro: result = semMacroExpr(c, result, nOrig, callee) of skTemplate: result = semTemplateExpr(c, result, callee) else: + semFinishOperands(c, n) activate(c, n) fixAbstractType(c, result) analyseIfAddressTakenInCall(c, result) @@ -845,16 +842,17 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = return semSym(c, n, s, flags) n.sons[0] = semExprWithType(c, n.sons[0], flags) - restoreOldStyleType(n.sons[0]) + #restoreOldStyleType(n.sons[0]) var i = considerAcc(n.sons[1]) var ty = n.sons[0].typ var f: PSym = nil result = nil - if isTypeExpr(n.sons[0]): + if isTypeExpr(n.sons[0]) or ty.kind == tyTypeDesc and ty.len == 1: + if ty.kind == tyTypeDesc: ty = ty.sons[0] case ty.kind - of tyEnum: + of tyEnum: # look up if the identifier belongs to the enum: - while ty != nil: + while ty != nil: f = getSymFromList(ty.n, i) if f != nil: break ty = ty.sons[0] # enum inheritance @@ -881,7 +879,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = # XXX: This is probably not relevant any more # reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim": ty = n.sons[0].Typ - + ty = skipTypes(ty, {tyGenericInst, tyVar, tyPtr, tyRef}) var check: PNode = nil if ty.kind == tyObject: diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 63e632eca..dacd397a2 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -484,10 +484,17 @@ proc semForVars(c: PContext, n: PNode): PNode = n.sons[length-1] = SemStmt(c, n.sons[length-1]) Dec(c.p.nestedLoopCounter) +proc newDeref(n: PNode): PNode {.inline.} = + result = newNodeIT(nkHiddenDeref, n.info, n.typ.sons[0]) + addSon(result, n) + proc implicitIterator(c: PContext, it: string, arg: PNode): PNode = result = newNodeI(nkCall, arg.info) result.add(newIdentNode(it.getIdent, arg.info)) - result.add(arg) + if arg.typ != nil and arg.typ.kind == tyVar: + result.add newDeref(arg) + else: + result.add arg result = semExprNoDeref(c, result, {efWantIterator}) proc semFor(c: PContext, n: PNode): PNode = @@ -776,8 +783,7 @@ proc activate(c: PContext, n: PNode) = # XXX: This proc is part of my plan for getting rid of # forward declarations. stay tuned. when false: - # well for now it breaks code ... I added the test case in main.nim of the - # compiler itself to break bootstrapping :P + # well for now it breaks code ... case n.kind of nkLambdaKinds: discard semLambda(c, n, {}) @@ -1142,8 +1148,8 @@ proc instantiateDestructor*(c: PContext, typ: PType): bool = else: return false -proc insertDestructors(c: PContext, varSection: PNode): - tuple[outer: PNode, inner: PNode] = +proc insertDestructors(c: PContext, + varSection: PNode): tuple[outer, inner: PNode] = # Accepts a var or let section. # # When a var section has variables with destructors diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 2159abecd..896d08665 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -799,6 +799,28 @@ proc setSon(father: PNode, at: int, son: PNode) = if sonsLen(father) <= at: setlen(father.sons, at + 1) father.sons[at] = son +# we are allowed to modify the calling node in the 'prepare*' procs: +proc prepareOperand(c: PContext; formal: PType; a: PNode): PNode = + if formal.kind == tyExpr and formal.len != 1: + # {tyTypeDesc, tyExpr, tyStmt, tyProxy}: + # a.typ == nil is valid + result = a + elif a.typ.isNil: + result = c.semExprWithType(c, a, {efDetermineType}) + else: + result = a + +proc prepareOperand(c: PContext; a: PNode): PNode = + if a.typ.isNil: + result = c.semExprWithType(c, a, {efDetermineType}) + else: + result = a + +proc prepareNamedParam(a: PNode) = + if a.sons[0].kind != nkIdent: + var info = a.sons[0].info + a.sons[0] = newIdentNode(considerAcc(a.sons[0]), info) + proc matchesAux(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var TIntSet) = template checkConstraint(n: expr) {.immediate, dirty.} = @@ -823,6 +845,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode, if n.sons[a].kind == nkExprEqExpr: # named param # check if m.callee has such a param: + prepareNamedParam(n.sons[a]) if n.sons[a].sons[0].kind != nkIdent: LocalError(n.sons[a].info, errNamedParamHasToBeIdent) m.state = csNoMatch @@ -838,9 +861,11 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m.state = csNoMatch return m.baseTypeMatch = false + n.sons[a].sons[1] = prepareOperand(c, formal.typ, n.sons[a].sons[1]) + n.sons[a].typ = n.sons[a].sons[1].typ var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ, n.sons[a].sons[1], nOrig.sons[a].sons[1]) - if arg == nil: + if arg == nil: m.state = csNoMatch return checkConstraint(n.sons[a].sons[1]) @@ -852,30 +877,33 @@ proc matchesAux(c: PContext, n, nOrig: PNode, if f != formalLen - 1: container = nil else: setSon(m.call, formal.position + 1, arg) - else: + else: # unnamed param - if f >= formalLen: + if f >= formalLen: # too many arguments? - if tfVarArgs in m.callee.flags: + if tfVarArgs in m.callee.flags: # is ok... but don't increment any counters... - if skipTypes(n.sons[a].typ, abstractVar).kind == tyString: - addSon(m.call, implicitConv(nkHiddenStdConv, getSysType(tyCString), + # we have no formal here to snoop at: + n.sons[a] = prepareOperand(c, n.sons[a]) + if skipTypes(n.sons[a].typ, abstractVar).kind == tyString: + addSon(m.call, implicitConv(nkHiddenStdConv, getSysType(tyCString), copyTree(n.sons[a]), m, c)) - else: + else: addSon(m.call, copyTree(n.sons[a])) elif formal != nil: m.baseTypeMatch = false + n.sons[a] = prepareOperand(c, formal.typ, n.sons[a]) var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ, n.sons[a], nOrig.sons[a]) - if (arg != nil) and m.baseTypeMatch and (container != nil): + if (arg != nil) and m.baseTypeMatch and (container != nil): addSon(container, arg) - else: + else: m.state = csNoMatch - return - else: + return + else: m.state = csNoMatch - return - else: + return + else: if m.callee.n.sons[f].kind != nkSym: InternalError(n.sons[a].info, "matches") return @@ -886,6 +914,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m.state = csNoMatch return m.baseTypeMatch = false + n.sons[a] = prepareOperand(c, formal.typ, n.sons[a]) var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ, n.sons[a], nOrig.sons[a]) if arg == nil: @@ -898,12 +927,18 @@ proc matchesAux(c: PContext, n, nOrig: PNode, setSon(m.call, formal.position + 1, implicitConv(nkHiddenStdConv, formal.typ, container, m, c)) if f != formalLen - 1: container = nil - else: + else: setSon(m.call, formal.position + 1, arg) checkConstraint(n.sons[a]) inc(a) inc(f) +proc semFinishOperands*(c: PContext, n: PNode) = + # this needs to be called to ensure that after overloading resolution every + # argument has been sem'checked: + for i in 1 .. <n.len: + n.sons[i] = prepareOperand(c, n.sons[i]) + proc partialMatch*(c: PContext, n, nOrig: PNode, m: var TCandidate) = # for 'suggest' support: var marker = initIntSet() |