implemented 'import except'

This commit is contained in:
Araq 2012-11-28 23:54:23 +01:00
commit 92e10e4b18
14 changed files with 120 additions and 95 deletions

View file

@ -172,10 +172,11 @@ type
nkDiscardStmt, # a discard statement nkDiscardStmt, # a discard statement
nkStmtList, # a list of statements nkStmtList, # a list of statements
nkImportStmt, # an import statement nkImportStmt, # an import statement
nkFromStmt, # a from * import statement
nkImportExceptStmt, # an import x except a statement nkImportExceptStmt, # an import x except a statement
nkIncludeStmt, # an include statement
nkExportStmt, # an export statement nkExportStmt, # an export statement
nkExportExceptStmt, # an 'export except' statement
nkFromStmt, # a from * import statement
nkIncludeStmt, # an include statement
nkBindStmt, # a bind statement nkBindStmt, # a bind statement
nkMixinStmt, # a mixin statement nkMixinStmt, # a mixin statement
nkCommentStmt, # a comment statement nkCommentStmt, # a comment statement

View file

@ -880,7 +880,8 @@ proc genStmts(p: BProc, t: PNode) =
# we have to emit the type information for object types here to support # we have to emit the type information for object types here to support
# separate compilation: # separate compilation:
genTypeSection(p.module, t) genTypeSection(p.module, t)
of nkCommentStmt, nkNilLit, nkIteratorDef, nkIncludeStmt, nkImportStmt, of nkCommentStmt, nkNilLit, nkIteratorDef, nkIncludeStmt,
nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt,
nkFromStmt, nkTemplateDef, nkMacroDef: nkFromStmt, nkTemplateDef, nkMacroDef:
nil nil
of nkPragma: genPragma(p, t) of nkPragma: genPragma(p, t)

View file

@ -35,7 +35,7 @@ proc addDotDependency(c: PPassContext, n: PNode): PNode =
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var imported = getModuleName(n.sons[i]) var imported = getModuleName(n.sons[i])
addDependencyAux(g.module.name.s, imported) addDependencyAux(g.module.name.s, imported)
of nkFromStmt: of nkFromStmt, nkImportExceptStmt:
var imported = getModuleName(n.sons[0]) var imported = getModuleName(n.sons[0])
addDependencyAux(g.module.name.s, imported) addDependencyAux(g.module.name.s, imported)
of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr: of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr:

View file

@ -273,7 +273,7 @@ proc generateDoc*(d: PDoc, n: PNode) =
generateDoc(d, lastSon(n.sons[0])) generateDoc(d, lastSon(n.sons[0]))
of nkImportStmt: of nkImportStmt:
for i in 0 .. sonsLen(n)-1: traceDeps(d, n.sons[i]) for i in 0 .. sonsLen(n)-1: traceDeps(d, n.sons[i])
of nkFromStmt: traceDeps(d, n.sons[0]) of nkFromStmt, nkImportExceptStmt: traceDeps(d, n.sons[0])
else: nil else: nil
proc genSection(d: PDoc, kind: TSymKind) = proc genSection(d: PDoc, kind: TSymKind) =

View file

@ -1465,7 +1465,8 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
of nkAsmStmt: genAsmStmt(p, n, r) of nkAsmStmt: genAsmStmt(p, n, r)
of nkTryStmt: genTryStmt(p, n, r) of nkTryStmt: genTryStmt(p, n, r)
of nkRaiseStmt: genRaiseStmt(p, n, r) of nkRaiseStmt: genRaiseStmt(p, n, r)
of nkTypeSection, nkCommentStmt, nkIteratorDef, nkIncludeStmt, nkImportStmt, of nkTypeSection, nkCommentStmt, nkIteratorDef, nkIncludeStmt,
nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt,
nkFromStmt, nkTemplateDef, nkMacroDef, nkPragma: nil nkFromStmt, nkTemplateDef, nkMacroDef, nkPragma: nil
of nkProcDef, nkMethodDef, nkConverterDef: of nkProcDef, nkMethodDef, nkConverterDef:
var s = n.sons[namePos].sym var s = n.sons[namePos].sym

View file

@ -103,11 +103,23 @@ proc importAllSymbols(c: PContext, fromMod: PSym) =
while s != nil: while s != nil:
if s.kind != skModule: if s.kind != skModule:
if s.kind != skEnumField: if s.kind != skEnumField:
if not (s.Kind in ExportableSymKinds): if s.Kind notin ExportableSymKinds:
InternalError(s.info, "importAllSymbols: " & $s.kind) InternalError(s.info, "importAllSymbols: " & $s.kind)
rawImportSymbol(c, s) # this is correct! rawImportSymbol(c, s) # this is correct!
s = NextIter(i, fromMod.tab) s = NextIter(i, fromMod.tab)
proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: TIntSet) =
var i: TTabIter
var s = InitTabIter(i, fromMod.tab)
while s != nil:
if s.kind != skModule:
if s.kind != skEnumField:
if s.Kind notin ExportableSymKinds:
InternalError(s.info, "importAllSymbols: " & $s.kind)
if s.name.id notin exceptSet:
rawImportSymbol(c, s)
s = NextIter(i, fromMod.tab)
proc evalImport(c: PContext, n: PNode): PNode = proc evalImport(c: PContext, n: PNode): PNode =
result = n result = n
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
@ -129,3 +141,17 @@ proc evalFrom(c: PContext, n: PNode): PNode =
n.sons[0] = newSymNode(m) n.sons[0] = newSymNode(m)
addDecl(c, m) # add symbol to symbol table of module addDecl(c, m) # add symbol to symbol table of module
for i in countup(1, sonsLen(n) - 1): importSymbol(c, n.sons[i], m) for i in countup(1, sonsLen(n) - 1): importSymbol(c, n.sons[i], m)
proc evalImportExcept*(c: PContext, n: PNode): PNode =
result = n
checkMinSonsLen(n, 2)
var f = checkModuleName(n.sons[0])
if f.len > 0:
var m = gImportModule(f)
n.sons[0] = newSymNode(m)
addDecl(c, m) # add symbol to symbol table of module
var exceptSet = initIntSet()
for i in countup(1, sonsLen(n) - 1):
let ident = lookups.considerAcc(n.sons[i])
exceptSet.incl(ident.id)
importAllSymbolsExcept(c, m, exceptSet)

View file

@ -872,10 +872,10 @@ proc parseExprStmt(p: var TParser): PNode =
getTok(p) getTok(p)
skipComment(p, result) skipComment(p, result)
if p.tok.tokType == tkSad: getTok(p) if p.tok.tokType == tkSad: getTok(p)
if not (p.tok.TokType in {tkOf, tkElif, tkElse, tkExcept}): if p.tok.TokType notin {tkOf, tkElif, tkElse, tkExcept}:
let body = parseStmt(p) let body = parseStmt(p)
addSon(result, newProcNode(nkDo, body.info, body)) addSon(result, newProcNode(nkDo, body.info, body))
while true: while true:
if p.tok.tokType == tkSad: getTok(p) if p.tok.tokType == tkSad: getTok(p)
var b: PNode var b: PNode
case p.tok.tokType case p.tok.tokType
@ -900,33 +900,34 @@ proc parseExprStmt(p: var TParser): PNode =
addSon(b, parseStmt(p)) addSon(b, parseStmt(p))
addSon(result, b) addSon(result, b)
if b.kind == nkElse: break if b.kind == nkElse: break
proc parseModuleName(p: var TParser): PNode {.inline.} =
result = parseExpr(p)
proc parseImportOrIncludeStmt(p: var TParser, kind: TNodeKind): PNode = proc parseImport(p: var TParser, kind: TNodeKind): PNode =
var a: PNode
result = newNodeP(kind, p) result = newNodeP(kind, p)
getTok(p) # skip `import` or `export`
optInd(p, result)
var a = parseExpr(p)
addSon(result, a)
if p.tok.tokType in {tkComma, tkExcept}:
if p.tok.tokType == tkExcept:
result.kind = succ(kind)
getTok(p)
optInd(p, result)
while p.tok.tokType notin {tkEof, tkSad, tkDed}:
a = parseExpr(p)
if a.kind == nkEmpty: break
addSon(result, a)
if p.tok.tokType != tkComma: break
getTok(p)
optInd(p, a)
expectNl(p)
proc parseIncludeStmt(p: var TParser): PNode =
result = newNodeP(nkIncludeStmt, p)
getTok(p) # skip `import` or `include` getTok(p) # skip `import` or `include`
optInd(p, result) optInd(p, result)
while true: while p.tok.tokType notin {tkEof, tkSad, tkDed}:
case p.tok.tokType var a = parseExpr(p)
of tkEof, tkSad, tkDed: if a.kind == nkEmpty: break
break
of tkSymbol, tkAccent:
a = parseSymbol(p)
of tkRStrLit:
a = newStrNodeP(nkRStrLit, p.tok.literal, p)
getTok(p)
of tkStrLit:
a = newStrNodeP(nkStrLit, p.tok.literal, p)
getTok(p)
of tkTripleStrLit:
a = newStrNodeP(nkTripleStrLit, p.tok.literal, p)
getTok(p)
else:
parMessage(p, errIdentifierExpected, p.tok)
break
addSon(result, a) addSon(result, a)
if p.tok.tokType != tkComma: break if p.tok.tokType != tkComma: break
getTok(p) getTok(p)
@ -937,19 +938,13 @@ proc parseFromStmt(p: var TParser): PNode =
result = newNodeP(nkFromStmt, p) result = newNodeP(nkFromStmt, p)
getTok(p) # skip `from` getTok(p) # skip `from`
optInd(p, result) optInd(p, result)
var a = parseModuleName(p) var a = parseExpr(p)
addSon(result, a) #optInd(p, a); addSon(result, a) #optInd(p, a);
eat(p, tkImport) eat(p, tkImport)
optInd(p, result) optInd(p, result)
while true: while p.tok.tokType notin {tkEof, tkSad, tkDed}:
case p.tok.tokType #optInd(p, a); a = parseExpr(p)
of tkEof, tkSad, tkDed: if a.kind == nkEmpty: break
break
of tkSymbol, tkAccent:
a = parseSymbol(p)
else:
parMessage(p, errIdentifierExpected, p.tok)
break
addSon(result, a) addSon(result, a)
if p.tok.tokType != tkComma: break if p.tok.tokType != tkComma: break
getTok(p) getTok(p)
@ -1264,14 +1259,7 @@ proc parseEnum(p: var TParser): PNode =
result = newNodeP(nkEnumTy, p) result = newNodeP(nkEnumTy, p)
a = nil a = nil
getTok(p) getTok(p)
if false and p.tok.tokType == tkOf: addSon(result, ast.emptyNode)
a = newNodeP(nkOfInherit, p)
getTok(p)
optInd(p, a)
addSon(a, parseTypeDesc(p))
addSon(result, a)
else:
addSon(result, ast.emptyNode)
optInd(p, result) optInd(p, result)
while true: while true:
case p.tok.tokType case p.tok.tokType
@ -1410,18 +1398,6 @@ proc parseDistinct(p: var TParser): PNode =
optInd(p, result) optInd(p, result)
addSon(result, parseTypeDesc(p)) addSon(result, parseTypeDesc(p))
proc parsePointerInTypeSection(p: var TParser, kind: TNodeKind): PNode =
result = newNodeP(kind, p)
getTok(p)
optInd(p, result)
if not isOperator(p.tok):
case p.tok.tokType
of tkObject: addSon(result, parseObject(p))
of tkTuple: addSon(result, parseTuple(p, true))
else:
if isExprStart(p):
addSon(result, parseTypeDesc(p))
proc parseTypeDef(p: var TParser): PNode = proc parseTypeDef(p: var TParser): PNode =
result = newNodeP(nkTypeDef, p) result = newNodeP(nkTypeDef, p)
addSon(result, identWithPragma(p)) addSon(result, identWithPragma(p))
@ -1430,15 +1406,6 @@ proc parseTypeDef(p: var TParser): PNode =
if p.tok.tokType == tkEquals: if p.tok.tokType == tkEquals:
getTok(p) getTok(p)
optInd(p, result) optInd(p, result)
#var a: PNode
#case p.tok.tokType
#of tkObject: a = parseObject(p)
#of tkEnum: a = parseEnum(p)
#of tkDistinct: a = parseDistinct(p)
#of tkTuple: a = parseTuple(p, true)
#of tkRef: a = parsePointerInTypeSection(p, nkRefTy)
#of tkPtr: a = parsePointerInTypeSection(p, nkPtrTy)
#else: a = parseTypeDesc(p)
addSon(result, parseTypeDefAux(p)) addSon(result, parseTypeDefAux(p))
else: else:
addSon(result, ast.emptyNode) addSon(result, ast.emptyNode)
@ -1496,11 +1463,12 @@ proc simpleStmt(p: var TParser): PNode =
of tkBreak: result = parseBreakOrContinue(p, nkBreakStmt) of tkBreak: result = parseBreakOrContinue(p, nkBreakStmt)
of tkContinue: result = parseBreakOrContinue(p, nkContinueStmt) of tkContinue: result = parseBreakOrContinue(p, nkContinueStmt)
of tkCurlyDotLe: result = parseStmtPragma(p) of tkCurlyDotLe: result = parseStmtPragma(p)
of tkImport: result = parseImportOrIncludeStmt(p, nkImportStmt) of tkImport: result = parseImport(p, nkImportStmt)
of tkExport: result = parseImport(p, nkExportStmt)
of tkFrom: result = parseFromStmt(p) of tkFrom: result = parseFromStmt(p)
of tkInclude: result = parseImportOrIncludeStmt(p, nkIncludeStmt) of tkInclude: result = parseIncludeStmt(p)
of tkComment: result = newCommentStmt(p) of tkComment: result = newCommentStmt(p)
else: else:
if isExprStart(p): result = parseExprStmt(p) if isExprStart(p): result = parseExprStmt(p)
else: result = ast.emptyNode else: result = ast.emptyNode
if result.kind != nkEmpty: skipComment(p, result) if result.kind != nkEmpty: skipComment(p, result)

View file

@ -1134,13 +1134,27 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
put(g, tkCurlyDotLe, "{.") put(g, tkCurlyDotLe, "{.")
gcomma(g, n, emptyContext) gcomma(g, n, emptyContext)
put(g, tkCurlyDotRi, ".}") put(g, tkCurlyDotRi, ".}")
of nkImportStmt: of nkImportStmt, nkExportStmt:
putWithSpace(g, tkImport, "import") if n.kind == nkImportStmt:
putWithSpace(g, tkImport, "import")
else:
putWithSpace(g, tkExport, "export")
gcoms(g) gcoms(g)
indentNL(g) indentNL(g)
gcommaAux(g, n, g.indent) gcommaAux(g, n, g.indent)
dedent(g) dedent(g)
putNL(g) putNL(g)
of nkImportExceptStmt, nkExportExceptStmt:
if n.kind == nkImportExceptStmt:
putWithSpace(g, tkImport, "import")
else:
putWithSpace(g, tkExport, "export")
gsub(g, n.sons[0])
put(g, tkSpaces, Space)
putWithSpace(g, tkExcept, "except")
gcommaAux(g, n, g.indent, 1)
gcoms(g)
putNL(g)
of nkFromStmt: of nkFromStmt:
putWithSpace(g, tkFrom, "from") putWithSpace(g, tkFrom, "from")
gsub(g, n.sons[0]) gsub(g, n.sons[0])
@ -1148,14 +1162,6 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
putWithSpace(g, tkImport, "import") putWithSpace(g, tkImport, "import")
gcomma(g, n, emptyContext, 1) gcomma(g, n, emptyContext, 1)
putNL(g) putNL(g)
of nkImportExceptStmt:
putWithSpace(g, tkImport, "import")
gsub(g, n.sons[0])
put(g, tkSpaces, Space)
putWithSpace(g, tkExcept, "except")
gcommaAux(g, n, g.indent, 1)
gcoms(g)
putNL(g)
of nkIncludeStmt: of nkIncludeStmt:
putWithSpace(g, tkInclude, "include") putWithSpace(g, tkInclude, "include")
gcoms(g) gcoms(g)
@ -1163,13 +1169,6 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
gcommaAux(g, n, g.indent) gcommaAux(g, n, g.indent)
dedent(g) dedent(g)
putNL(g) putNL(g)
of nkExportStmt:
putWithSpace(g, tkExport, "export")
gcoms(g)
indentNL(g)
gcommaAux(g, n, g.indent)
dedent(g)
putNL(g)
of nkCommentStmt: of nkCommentStmt:
gcoms(g) gcoms(g)
optNL(g) optNL(g)

View file

@ -1850,6 +1850,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkImportStmt: of nkImportStmt:
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "import") if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "import")
result = evalImport(c, n) result = evalImport(c, n)
of nkImportExceptStmt:
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "import")
result = evalImportExcept(c, n)
of nkFromStmt: of nkFromStmt:
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "from") if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "from")
result = evalFrom(c, n) result = evalFrom(c, n)

View file

@ -825,6 +825,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
checkSonsLen(n, 3) checkSonsLen(n, 3)
result = semTypeNode(c, n.sons[1], prev) result = semTypeNode(c, n.sons[1], prev)
if result.kind in NilableTypes and n.sons[2].kind == nkNilLit: if result.kind in NilableTypes and n.sons[2].kind == nkNilLit:
# XXX this is wrong for tyString at least
result.flags.incl(tfNotNil) result.flags.incl(tfNotNil)
else: else:
LocalError(n.info, errGenerated, "invalid type") LocalError(n.info, errGenerated, "invalid type")

View file

@ -3741,6 +3741,19 @@ This is best illustrated by an example:
return x + 1 return x + 1
Import statement
~~~~~~~~~~~~~~~~
After the import statement a list of module names can follow or a single
module name followed by an ``except`` to prevent some symbols to be imported:
.. code-block:: nimrod
import strutils except `%`
# doesn't work then:
echo "$1" % "abc"
Scope rules Scope rules
----------- -----------
Identifiers are valid from the point of their declaration until the end of Identifiers are valid from the point of their declaration until the end of

View file

@ -47,10 +47,12 @@ type
nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkStaticStmt, nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkStaticStmt,
nnkDiscardStmt, nnkStmtList, nnkDiscardStmt, nnkStmtList,
nnkImportStmt, nnkFromStmt, nnkImportStmt,
nkImportExceptStmt, nnkImportExceptStmt,
nnkIncludeStmt,
nnkExportStmt, nnkExportStmt,
nnkExportExceptStmt,
nnkFromStmt,
nnkIncludeStmt,
nnkBindStmt, nnkMixinStmt, nnkBindStmt, nnkMixinStmt,
nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr, nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr,

View file

@ -0,0 +1,10 @@
discard """
line: 9
errormsg: "undeclared identifier: '%'"
"""
import strutils except `%`
# doesn't work
echo "$1" % "abc"

View file

@ -1,7 +1,7 @@
version 0.9.2 version 0.9.2
============= =============
- 'export' feature; from buggymodule import * except optBroken, optBroken2 - 'export' feature
- test&finish first class iterators: - test&finish first class iterators:
* nested iterators * nested iterators
* test generic iterators * test generic iterators