summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-11-30 02:09:04 +0100
committerAraq <rumpf_a@web.de>2012-11-30 02:09:04 +0100
commitda5ba6ce622d8a3fa7c0b6c1f234bd01dfa573a4 (patch)
treeebccc4340f244c6b5c54652b36265f1078974076
parent9483606d5bc074b5c820c3ca8b73c9507139c48a (diff)
parent92e10e4b182f4b106db79f4be228e19b2720d043 (diff)
downloadNim-da5ba6ce622d8a3fa7c0b6c1f234bd01dfa573a4.tar.gz
resolved conflicts
-rwxr-xr-xcompiler/ast.nim5
-rwxr-xr-xcompiler/ccgstmts.nim3
-rwxr-xr-xcompiler/depends.nim2
-rwxr-xr-xcompiler/docgen.nim2
-rwxr-xr-xcompiler/ecmasgen.nim3
-rwxr-xr-xcompiler/importer.nim33
-rwxr-xr-xcompiler/parser.nim102
-rwxr-xr-xcompiler/renderer.nim33
-rwxr-xr-xcompiler/semexprs.nim5
-rwxr-xr-xcompiler/semtypes.nim1
-rwxr-xr-xdoc/manual.txt13
-rwxr-xr-xlib/core/macros.nim8
-rw-r--r--tests/compile/titerovl.nim21
-rw-r--r--tests/reject/timportexcept.nim10
-rwxr-xr-xtodo.txt32
15 files changed, 160 insertions, 113 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 77f8723e2..f4ba1ef70 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -172,10 +172,11 @@ type
     nkDiscardStmt,        # a discard statement
     nkStmtList,           # a list of statements
     nkImportStmt,         # an import statement
-    nkFromStmt,           # a from * import statement
     nkImportExceptStmt,   # an import x except a statement
-    nkIncludeStmt,        # an include statement
     nkExportStmt,         # an export statement
+    nkExportExceptStmt,   # an 'export except' statement
+    nkFromStmt,           # a from * import statement
+    nkIncludeStmt,        # an include statement
     nkBindStmt,           # a bind statement
     nkMixinStmt,          # a mixin statement
     nkCommentStmt,        # a comment statement
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index a950c62df..089f7fb83 100755
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -880,7 +880,8 @@ proc genStmts(p: BProc, t: PNode) =
     # we have to emit the type information for object types here to support
     # separate compilation:
     genTypeSection(p.module, t)
-  of nkCommentStmt, nkNilLit, nkIteratorDef, nkIncludeStmt, nkImportStmt, 
+  of nkCommentStmt, nkNilLit, nkIteratorDef, nkIncludeStmt, 
+     nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt, 
      nkFromStmt, nkTemplateDef, nkMacroDef: 
     nil
   of nkPragma: genPragma(p, t)
diff --git a/compiler/depends.nim b/compiler/depends.nim
index 4fde24ab4..b9d38236b 100755
--- a/compiler/depends.nim
+++ b/compiler/depends.nim
@@ -35,7 +35,7 @@ proc addDotDependency(c: PPassContext, n: PNode): PNode =
     for i in countup(0, sonsLen(n) - 1): 
       var imported = getModuleName(n.sons[i])
       addDependencyAux(g.module.name.s, imported)
-  of nkFromStmt: 
+  of nkFromStmt, nkImportExceptStmt: 
     var imported = getModuleName(n.sons[0])
     addDependencyAux(g.module.name.s, imported)
   of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr: 
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index 8bbc53b74..5d46be874 100755
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -273,7 +273,7 @@ proc generateDoc*(d: PDoc, n: PNode) =
       generateDoc(d, lastSon(n.sons[0]))
   of nkImportStmt:
     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
 
 proc genSection(d: PDoc, kind: TSymKind) = 
diff --git a/compiler/ecmasgen.nim b/compiler/ecmasgen.nim
index cff4cc1dd..770e6a4a7 100755
--- a/compiler/ecmasgen.nim
+++ b/compiler/ecmasgen.nim
@@ -1465,7 +1465,8 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
   of nkAsmStmt: genAsmStmt(p, n, r)
   of nkTryStmt: genTryStmt(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
   of nkProcDef, nkMethodDef, nkConverterDef:
     var s = n.sons[namePos].sym
diff --git a/compiler/importer.nim b/compiler/importer.nim
index f96377915..b3821746c 100755
--- a/compiler/importer.nim
+++ b/compiler/importer.nim
@@ -11,7 +11,7 @@
 
 import 
   intsets, strutils, os, ast, astalgo, msgs, options, idents, rodread, lookups,
-  semdata, passes
+  semdata, passes, renderer
 
 proc evalImport*(c: PContext, n: PNode): PNode
 proc evalFrom*(c: PContext, n: PNode): PNode
@@ -29,7 +29,8 @@ proc getModuleName*(n: PNode): string =
   of nkSym:
     result = n.sym.name.s
   else:
-    internalError(n.info, "getModuleName")
+    localError(n.info, errGenerated,
+      "invalide module name: '$1'" % renderTree(n))
     result = ""
 
 proc checkModuleName*(n: PNode): string =
@@ -102,11 +103,23 @@ proc importAllSymbols(c: PContext, fromMod: PSym) =
   while s != nil: 
     if s.kind != skModule: 
       if s.kind != skEnumField: 
-        if not (s.Kind in ExportableSymKinds): 
+        if s.Kind notin ExportableSymKinds:
           InternalError(s.info, "importAllSymbols: " & $s.kind)
         rawImportSymbol(c, s) # this is correct!
     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 = 
   result = n
   for i in countup(0, sonsLen(n) - 1): 
@@ -128,3 +141,17 @@ proc evalFrom(c: PContext, n: PNode): PNode =
     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)
+
+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)
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 7ab87804e..bfc6b3b65 100755
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -872,10 +872,10 @@ proc parseExprStmt(p: var TParser): PNode =
       getTok(p)
       skipComment(p, result)
       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)
         addSon(result, newProcNode(nkDo, body.info, body))
-      while true: 
+      while true:
         if p.tok.tokType == tkSad: getTok(p)
         var b: PNode
         case p.tok.tokType
@@ -900,33 +900,34 @@ proc parseExprStmt(p: var TParser): PNode =
         addSon(b, parseStmt(p))
         addSon(result, b)
         if b.kind == nkElse: break
-    
-proc parseModuleName(p: var TParser): PNode {.inline.} =
-  result = parseExpr(p)
 
-proc parseImportOrIncludeStmt(p: var TParser, kind: TNodeKind): PNode =
-  var a: PNode
+proc parseImport(p: var TParser, kind: TNodeKind): PNode =
   result = newNodeP(kind, p)
-  getTok(p)                   # skip `import` or `include`
+  getTok(p)                   # skip `import` or `export`
   optInd(p, result)
-  while true:
-    case p.tok.tokType
-    of tkEof, tkSad, tkDed:
-      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)
+  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)
-    else:
-      parMessage(p, errIdentifierExpected, p.tok)
-      break 
+      optInd(p, a)
+  expectNl(p)
+
+proc parseIncludeStmt(p: var TParser): PNode =
+  result = newNodeP(nkIncludeStmt, p)
+  getTok(p)                   # skip `import` or `include`
+  optInd(p, result)
+  while p.tok.tokType notin {tkEof, tkSad, tkDed}:
+    var a = parseExpr(p)
+    if a.kind == nkEmpty: break
     addSon(result, a)
     if p.tok.tokType != tkComma: break 
     getTok(p)
@@ -937,19 +938,13 @@ proc parseFromStmt(p: var TParser): PNode =
   result = newNodeP(nkFromStmt, p)
   getTok(p)                   # skip `from`
   optInd(p, result)
-  var a = parseModuleName(p)
+  var a = parseExpr(p)
   addSon(result, a)           #optInd(p, a);
   eat(p, tkImport)
   optInd(p, result)
-  while true: 
-    case p.tok.tokType        #optInd(p, a);
-    of tkEof, tkSad, tkDed: 
-      break 
-    of tkSymbol, tkAccent: 
-      a = parseSymbol(p)
-    else: 
-      parMessage(p, errIdentifierExpected, p.tok)
-      break 
+  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)
@@ -1264,14 +1259,7 @@ proc parseEnum(p: var TParser): PNode =
   result = newNodeP(nkEnumTy, p)
   a = nil
   getTok(p)
-  if false and p.tok.tokType == tkOf: 
-    a = newNodeP(nkOfInherit, p)
-    getTok(p)
-    optInd(p, a)
-    addSon(a, parseTypeDesc(p))
-    addSon(result, a)
-  else: 
-    addSon(result, ast.emptyNode)
+  addSon(result, ast.emptyNode)
   optInd(p, result)
   while true: 
     case p.tok.tokType
@@ -1410,18 +1398,6 @@ proc parseDistinct(p: var TParser): PNode =
   optInd(p, result)
   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 = 
   result = newNodeP(nkTypeDef, p)
   addSon(result, identWithPragma(p))
@@ -1430,15 +1406,6 @@ proc parseTypeDef(p: var TParser): PNode =
   if p.tok.tokType == tkEquals: 
     getTok(p)
     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))
   else:
     addSon(result, ast.emptyNode)
@@ -1496,11 +1463,12 @@ proc simpleStmt(p: var TParser): PNode =
   of tkBreak: result = parseBreakOrContinue(p, nkBreakStmt)
   of tkContinue: result = parseBreakOrContinue(p, nkContinueStmt)
   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 tkInclude: result = parseImportOrIncludeStmt(p, nkIncludeStmt)
+  of tkInclude: result = parseIncludeStmt(p)
   of tkComment: result = newCommentStmt(p)
-  else: 
+  else:
     if isExprStart(p): result = parseExprStmt(p)
     else: result = ast.emptyNode
   if result.kind != nkEmpty: skipComment(p, result)
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 4444f2ab0..c8ee66e03 100755
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -1134,13 +1134,27 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
       put(g, tkCurlyDotLe, "{.")
       gcomma(g, n, emptyContext)
       put(g, tkCurlyDotRi, ".}")
-  of nkImportStmt: 
-    putWithSpace(g, tkImport, "import")
+  of nkImportStmt, nkExportStmt:
+    if n.kind == nkImportStmt:
+      putWithSpace(g, tkImport, "import")
+    else:
+      putWithSpace(g, tkExport, "export")
     gcoms(g)
     indentNL(g)
     gcommaAux(g, n, g.indent)
     dedent(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: 
     putWithSpace(g, tkFrom, "from")
     gsub(g, n.sons[0])
@@ -1148,14 +1162,6 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     putWithSpace(g, tkImport, "import")
     gcomma(g, n, emptyContext, 1)
     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: 
     putWithSpace(g, tkInclude, "include")
     gcoms(g)
@@ -1163,13 +1169,6 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     gcommaAux(g, n, g.indent)
     dedent(g)
     putNL(g)
-  of nkExportStmt:
-    putWithSpace(g, tkExport, "export")
-    gcoms(g)
-    indentNL(g)
-    gcommaAux(g, n, g.indent)
-    dedent(g)
-    putNL(g)
   of nkCommentStmt: 
     gcoms(g)
     optNL(g)
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index cf0e8f4dd..c5e3fdc1e 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -594,7 +594,7 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
     # to 'skIterator' anymore; skIterator is preferred in sigmatch already for
     # typeof support.
     # for ``type(countup(1,3))``, see ``tests/ttoseq``.
-    result = semOverloadedCall(c, n, nOrig, 
+    result = semOverloadedCall(c, n, nOrig,
       {skProc, skMethod, skConverter, skMacro, skTemplate, skIterator})
   else:
     result = semOverloadedCall(c, n, nOrig, 
@@ -1852,6 +1852,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   of nkImportStmt: 
     if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "import")
     result = evalImport(c, n)
+  of nkImportExceptStmt:
+    if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "import")
+    result = evalImportExcept(c, n)
   of nkFromStmt: 
     if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "from")
     result = evalFrom(c, n)
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index f644683f5..9efeba5b7 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -825,6 +825,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
         checkSonsLen(n, 3)
         result = semTypeNode(c, n.sons[1], prev)
         if result.kind in NilableTypes and n.sons[2].kind == nkNilLit:
+          # XXX this is wrong for tyString at least
           result.flags.incl(tfNotNil)
         else:
           LocalError(n.info, errGenerated, "invalid type")
diff --git a/doc/manual.txt b/doc/manual.txt
index f6ff576bf..a5bce775b 100755
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -3741,6 +3741,19 @@ This is best illustrated by an example:
     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
 -----------
 Identifiers are valid from the point of their declaration until the end of
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index d2d842025..bf7510a92 100755
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -47,10 +47,12 @@ type
     nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkStaticStmt,
     nnkDiscardStmt, nnkStmtList, 
     
-    nnkImportStmt, nnkFromStmt,
-    nkImportExceptStmt,
-    nnkIncludeStmt,
+    nnkImportStmt,
+    nnkImportExceptStmt,
     nnkExportStmt,
+    nnkExportExceptStmt,
+    nnkFromStmt,
+    nnkIncludeStmt,
     
     nnkBindStmt, nnkMixinStmt,
     nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr,
diff --git a/tests/compile/titerovl.nim b/tests/compile/titerovl.nim
new file mode 100644
index 000000000..be665b2b7
--- /dev/null
+++ b/tests/compile/titerovl.nim
@@ -0,0 +1,21 @@
+discard """
+  output: '''9
+1
+2
+3
+'''
+"""
+
+# Test the new overloading rules for iterators:
+
+# test that iterator 'p' is preferred:
+proc p(): seq[int] = @[1, 2, 3]
+iterator p(): int = yield 9
+
+for x in p(): echo x
+
+# test that 'q' works in this position:
+proc q(): seq[int] = @[1, 2, 3]
+
+for x in q(): echo x
+
diff --git a/tests/reject/timportexcept.nim b/tests/reject/timportexcept.nim
new file mode 100644
index 000000000..93a7fd642
--- /dev/null
+++ b/tests/reject/timportexcept.nim
@@ -0,0 +1,10 @@
+discard """
+  line: 9
+  errormsg: "undeclared identifier: '%'"
+"""
+
+import strutils except `%`
+
+# doesn't work
+echo "$1" % "abc"
+
diff --git a/todo.txt b/todo.txt
index 79b3cb529..804f6e5f6 100755
--- a/todo.txt
+++ b/todo.txt
@@ -1,7 +1,7 @@
 version 0.9.2
 =============
 
-- 'export' feature; from buggymodule import * except optBroken, optBroken2
+- 'export' feature
 - test&finish first class iterators:
   * nested iterators
   * test generic iterators
@@ -53,35 +53,27 @@ Concurrency
 - use the effect system to for static deadlock prevention
 
 
-GC
-==
-
-- precise stack marking; embrace C++ code generation for that
-- marker procs for Boehm GC
-- implement 'mixed' GC mode
-
-
 version 0.9.XX
 ==============
 
-- implement the "snoopResult" pragma; no, make a strutils with string append
-  semantics instead ...
-- implement "closure tuple consists of a single 'ref'" optimization
 - object branch transitions can't work with the current 'reset'; add a 'reset'
   with an additional parameter --> re-evaluate this issue after constructors
   have been added
-- allow implicit forward declarations of procs via a pragma (so that the
-  wrappers can deactivate it)
 - fix destructors; don't work yet when used as expression
 - document nimdoc properly finally
 - make 'clamp' a magic for the range stuff
-- 'const' objects including case objects
-- mocking support with ``tyProxy`` that does: fallback for ``.`` operator
 
 
 Not essential for 1.0.0
 =======================
 
+- 'const' objects including case objects
+- mocking support with ``tyProxy`` that does: fallback for ``.`` operator
+- allow implicit forward declarations of procs via a pragma (so that the
+  wrappers can deactivate it)
+- implement the "snoopResult" pragma; no, make a strutils with string append
+  semantics instead ...
+- implement "closure tuple consists of a single 'ref'" optimization
 - optimize method dispatchers
 - ``with proc `+`(x, y: T): T`` for generic code
 - new feature: ``distinct T with operations``
@@ -94,6 +86,14 @@ Not essential for 1.0.0
 - implement closures that support nesting of *procs* > 1
 
 
+GC
+==
+
+- precise stack marking; embrace C++ code generation for that
+- marker procs for Boehm GC
+- implement 'mixed' GC mode
+
+
 Optimizations
 =============