diff options
author | Araq <rumpf_a@web.de> | 2012-08-02 23:14:38 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-08-02 23:14:38 +0200 |
commit | 7d6500f1de19379cdfc9c6f8a05d43781cf32291 (patch) | |
tree | 010e7c625639b3bb3a0f397c19f4d7d06bf76120 | |
parent | 559980c8901fe56aa8b410c6427fd1467dd69794 (diff) | |
download | Nim-7d6500f1de19379cdfc9c6f8a05d43781cf32291.tar.gz |
idetools improvements; preparation of first class iterators; fixes #183
-rwxr-xr-x | compiler/ast.nim | 4 | ||||
-rwxr-xr-x | compiler/ccgstmts.nim | 21 | ||||
-rw-r--r-- | compiler/ccgtrav.nim | 9 | ||||
-rwxr-xr-x | compiler/ecmasgen.nim | 2 | ||||
-rwxr-xr-x | compiler/importer.nim | 25 | ||||
-rw-r--r-- | compiler/lambdalifting.nim | 28 | ||||
-rwxr-xr-x | compiler/msgs.nim | 2 | ||||
-rwxr-xr-x | compiler/parser.nim | 8 | ||||
-rwxr-xr-x | compiler/semstmts.nim | 21 | ||||
-rwxr-xr-x | compiler/semtypes.nim | 8 | ||||
-rwxr-xr-x | compiler/sigmatch.nim | 2 | ||||
-rwxr-xr-x | compiler/suggest.nim | 1 |
12 files changed, 95 insertions, 36 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index ff493e563..071318992 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -200,7 +200,9 @@ type nkEnumTy, # enum body nkEnumFieldDef, # `ident = expr` in an enumeration nkReturnToken, # token used for interpretation - nkClosure # (prc, env)-pair (internally used for code gen) + nkClosure, # (prc, env)-pair (internally used for code gen) + nkGotoState, # used for the state machine (for iterators) + nkState # give a label to a code section (for iterators) TNodeKinds* = set[TNodeKind] type diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 591dd7089..1f480f024 100755 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -92,6 +92,25 @@ template preserveBreakIdx(body: stmt): stmt = body p.breakIdx = oldBreakIdx +proc genState(p: BProc, n: PNode) = + internalAssert n.len == 2 and n.sons[0].kind == nkIntLit + let idx = n.sons[0].intVal + lineCg(p, cpsStmts, "STATE$1: ;$n", [idx.toRope]) + genStmts(p, n.sons[1]) + +proc genGotoState(p: BProc, n: PNode) = + # we resist the temptation to translate it into duff's device as it later + # will be translated into computed gotos anyway for GCC at least: + # switch (x.state) { + # case 0: goto STATE0; + # ... + var a: TLoc + initLocExpr(p, n.sons[0], a) + lineF(p, cpsStmts, "switch ($1) {$n", [rdLoc(a)]) + for i in 0 .. lastOrd(n.sons[0].typ): + lineF(p, cpsStmts, "case $1: goto STATE$1;$n", [toRope(i)]) + lineF(p, cpsStmts, "}$n", []) + proc genSingleVar(p: BProc, a: PNode) = var v = a.sons[0].sym if sfCompileTime in v.flags: return @@ -863,5 +882,7 @@ proc genStmts(p: BProc, t: PNode) = if prc.getBody.kind != nkEmpty or lfDynamicLib in prc.loc.flags: genProc(p.module, prc) of nkParForStmt: genParForStmt(p, t) + of nkState: genState(p, t) + of nkGotoState: genGotoState(p, t) else: internalError(t.info, "genStmts(" & $t.kind & ')') diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim index 1ff6346f6..5f6f14548 100644 --- a/compiler/ccgtrav.nim +++ b/compiler/ccgtrav.nim @@ -44,6 +44,8 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, n: PNode) = lineF(p, cpsStmts, "} $n") of nkSym: let field = n.sym + if field.loc.t == nil: + internalError(n.info, "genTraverseProc()") genTraverseProc(c, ropef("$1.$2", accessor, field.loc.r), field.loc.t) else: internalError(n.info, "genTraverseProc()") @@ -73,11 +75,8 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) = if typ.n != nil: genTraverseProc(c, accessor, typ.n) of tyTuple: let typ = GetUniqueType(typ) - if typ.n != nil: - genTraverseProc(c, accessor, typ.n) - else: - for i in countup(0, sonsLen(typ) - 1): - genTraverseProc(c, ropef("$1.Field$2", accessor, i.toRope), typ.sons[i]) + for i in countup(0, sonsLen(typ) - 1): + genTraverseProc(c, ropef("$1.Field$2", accessor, i.toRope), typ.sons[i]) of tyRef, tyString, tySequence: lineCg(p, cpsStmts, c.visitorFrmt, accessor) of tyProc: diff --git a/compiler/ecmasgen.nim b/compiler/ecmasgen.nim index 1ae80c74c..615386a32 100755 --- a/compiler/ecmasgen.nim +++ b/compiler/ecmasgen.nim @@ -1468,6 +1468,8 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) = if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}: var r2: TCompRes genSym(p, n.sons[namePos], r2) + of nkGotoState, nkState: + internalError(n.info, "first class iterators not implemented") else: genLineDir(p, n, r) gen(p, n, r) diff --git a/compiler/importer.nim b/compiler/importer.nim index 19f0574b8..24f7cb5c6 100755 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -37,7 +37,7 @@ proc checkModuleName*(n: PNode): string = var modulename = n.getModuleName result = findModule(modulename) if result.len == 0: - Fatal(n.info, errCannotOpenFile, modulename) + LocalError(n.info, errCannotOpenFile, modulename) proc rawImportSymbol(c: PContext, s: PSym) = # This does not handle stubs, because otherwise loading on demand would be @@ -109,19 +109,20 @@ proc evalImport(c: PContext, n: PNode): PNode = result = n for i in countup(0, sonsLen(n) - 1): var f = checkModuleName(n.sons[i]) - var m = gImportModule(f) - if sfDeprecated in m.flags: - Message(n.sons[i].info, warnDeprecated, m.name.s) - # ``addDecl`` needs to be done before ``importAllSymbols``! - addDecl(c, m) # add symbol to symbol table of module - importAllSymbols(c, m) + if f.len > 0: + var m = gImportModule(f) + if sfDeprecated in m.flags: + Message(n.sons[i].info, warnDeprecated, m.name.s) + # ``addDecl`` needs to be done before ``importAllSymbols``! + addDecl(c, m) # add symbol to symbol table of module + importAllSymbols(c, m) proc evalFrom(c: PContext, n: PNode): PNode = result = n checkMinSonsLen(n, 2) var f = checkModuleName(n.sons[0]) - var m = gImportModule(f) - n.sons[0] = newSymNode(m) - addDecl(c, m) # add symbol to symbol table of module - for i in countup(1, sonsLen(n) - 1): importSymbol(c, n.sons[i], m) - + if f.len > 0: + var m = gImportModule(f) + n.sons[0] = newSymNode(m) + addDecl(c, m) # add symbol to symbol table of module + for i in countup(1, sonsLen(n) - 1): importSymbol(c, n.sons[i], m) diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 647daca85..aaba47c70 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -8,7 +8,6 @@ # # This include file implements lambda lifting for the transformator. -# included from transf.nim import intsets, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os, @@ -517,3 +516,30 @@ proc liftLambdas*(n: PNode): PNode = var s = n.sons[namePos].sym if gCmd == cmdCompileToEcmaScript: return s.getBody result = liftLambdas(s, s.getBody) + +proc transformIterator*(fn: PSym, body: PNode): PNode = + if body.kind == nkEmpty: + # ignore forward declaration: + result = body + # it(a, b) --> (it(a, b), createClosure()) + # it(a, b) --> ? + discard """ + let c = chain(f, g) + + for x in c: echo x + + iterator chain[S, T](a, b: *S->T, args: *S): T = + for x in a(args): yield x + for x in b(args): yield x + + # translated to: + + + + let c = chain( (f, newClosure(f)), (g, newClosure(g)), newClosure(chain)) + + +""" + + + diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 714b6f51f..eb427954a 100755 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -344,7 +344,7 @@ const warnLanguageXNotSupported: "language \'$1\' not supported [LanguageXNotSupported]", warnCommentXIgnored: "comment \'$1\' ignored [CommentXIgnored]", warnXisPassedToProcVar: "\'$1\' is passed to a procvar; deprecated [XisPassedToProcVar]", - warnAnalysisLoophole: "thread analysis incomplete due to unkown call '$1' [AnalysisLoophole]", + warnAnalysisLoophole: "thread analysis incomplete due to unknown call '$1' [AnalysisLoophole]", warnDifferentHeaps: "possible inconsistency of thread local heaps [DifferentHeaps]", warnWriteToForeignHeap: "write to foreign heap [WriteToForeignHeap]", warnImplicitClosure: "implicit closure convention: '$1' [ImplicitClosure]", diff --git a/compiler/parser.nim b/compiler/parser.nim index 3d8fc1f7c..f78f07325 100755 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -275,6 +275,7 @@ proc exprList(p: var TParser, endTok: TTokType, result: PNode) = proc dotExpr(p: var TParser, a: PNode): PNode = getTok(p) + var info = p.lex.getlineInfo optInd(p, a) case p.tok.tokType of tkType: @@ -286,7 +287,7 @@ proc dotExpr(p: var TParser, a: PNode): PNode = getTok(p) addSon(result, a) else: - result = newNodeI(nkDotExpr, a.info) + result = newNodeI(nkDotExpr, info) addSon(result, a) addSon(result, parseSymbol(p)) @@ -758,9 +759,10 @@ proc parseExpr(p: var TParser): PNode = case p.tok.tokType: of tkIf: result = parseIfExpr(p, nkIfExpr) of tkWhen: result = parseIfExpr(p, nkWhenExpr) - of tkTry: result = parseTry(p) - of tkCase: result = parseCase(p) else: result = lowestExpr(p) + # XXX needs proper support: + #of tkCase: result = parseCase(p) + #of tkTry: result = parseTry(p) proc primary(p: var TParser, skipSuffix = false): PNode = # prefix operator? diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index c82e7d8de..0e882c076 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -835,13 +835,15 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, closeScope(c.tab) # close scope for parameters popOwner() -proc semIterator(c: PContext, n: PNode): PNode = +proc semIterator(c: PContext, n: PNode): PNode = result = semProcAux(c, n, skIterator, iteratorPragmas) var s = result.sons[namePos].sym var t = s.typ - if t.sons[0] == nil: + if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "iterator") - if n.sons[bodyPos].kind == nkEmpty and s.magic == mNone: + # iterators are either 'inline' or 'closure': + if s.typ.callConv != ccInline: s.typ.callConv = ccClosure + if n.sons[bodyPos].kind == nkEmpty and s.magic == mNone: LocalError(n.info, errImplOfXexpected, s.name.s) proc semProc(c: PContext, n: PNode): PNode = @@ -894,12 +896,13 @@ proc evalInclude(c: PContext, n: PNode): PNode = addSon(result, n) for i in countup(0, sonsLen(n) - 1): var f = checkModuleName(n.sons[i]) - var fileIndex = f.fileInfoIdx - if ContainsOrIncl(c.includedFiles, fileIndex): - LocalError(n.info, errRecursiveDependencyX, f.extractFilename) - else: - addSon(result, semStmt(c, gIncludeFile(f))) - Excl(c.includedFiles, fileIndex) + if f.len > 0: + var fileIndex = f.fileInfoIdx + if ContainsOrIncl(c.includedFiles, fileIndex): + LocalError(n.info, errRecursiveDependencyX, f.extractFilename) + else: + addSon(result, semStmt(c, gIncludeFile(f))) + Excl(c.includedFiles, fileIndex) proc setLine(n: PNode, info: TLineInfo) = for i in 0 .. <safeLen(n): setLine(n.sons[i], info) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index a0e2283a3..8e3a4dda4 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -870,9 +870,13 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = of nkType: result = n.typ of nkStmtListType: result = semStmtListType(c, n, prev) of nkBlockType: result = semBlockType(c, n, prev) - else: + else: LocalError(n.info, errTypeExpected) - result = errorType(c) + if prev != nil and prev.kind == tyForward: + prev.kind = tyProxy + result = prev + else: + result = errorType(c) proc setMagicType(m: PSym, kind: TTypeKind, size: int) = m.typ.kind = kind diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index ba0cba749..9273d5add 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -70,7 +70,7 @@ proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode, c.calleeSym = callee c.calleeScope = calleeScope initIdTable(c.bindings) - if binding != nil: + if binding != nil and callee.kind in RoutineKinds: var typeParams = callee.ast[genericParamsPos] for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1): var formalTypeParam = typeParams.sons[i-1].typ diff --git a/compiler/suggest.nim b/compiler/suggest.nim index 240316cec..10d50a6b7 100755 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -214,7 +214,6 @@ proc suggestExpr*(c: PContext, node: PNode) = var n = findClosestDot(node) if n == nil: n = node else: cp = cpExact - if n.kind == nkDotExpr and cp == cpExact: var obj = safeSemExpr(c, n.sons[0]) suggestFieldAccess(c, obj, outputs) |