summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2013-08-31 19:40:36 +0300
committerZahary Karadjov <zahary@gmail.com>2013-08-31 19:40:36 +0300
commitb5d833b329191cf99718e2ea6dc08895c47dd8f9 (patch)
tree488ce125246a461db19ef4f03ab91890393771cf
parent01ccb52a00ec4b41b0be3ebb6bafb2a44eba8f26 (diff)
downloadNim-b5d833b329191cf99718e2ea6dc08895c47dd8f9.tar.gz
implemented the using statement
-rw-r--r--compiler/ast.nim2
-rw-r--r--compiler/lexer.nim4
-rw-r--r--compiler/msgs.nim3
-rw-r--r--compiler/parser.nim1
-rw-r--r--compiler/semcall.nim23
-rw-r--r--compiler/semexprs.nim17
-rw-r--r--compiler/wordrecg.nim10
-rw-r--r--doc/keywords.txt2
-rw-r--r--lib/core/macros.nim2
9 files changed, 53 insertions, 11 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 4ed44a8fe..6e0cafd74 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -178,6 +178,7 @@ type
     nkIncludeStmt,        # an include statement
     nkBindStmt,           # a bind statement
     nkMixinStmt,          # a mixin statement
+    nkUsingStmt,          # an using statement
     nkCommentStmt,        # a comment statement
     nkStmtListExpr,       # a statement list followed by an expr; this is used
                           # to allow powerful multi-line templates
@@ -619,6 +620,7 @@ type
   TScope* = object
     depthLevel*: int
     symbols*: TStrTable
+    usingSyms*: seq[PNode]
     parent*: PScope
 
   PScope* = ref TScope
diff --git a/compiler/lexer.nim b/compiler/lexer.nim
index 9e5f4e9d7..1d34c59ab 100644
--- a/compiler/lexer.nim
+++ b/compiler/lexer.nim
@@ -41,7 +41,7 @@ type
     tkGeneric, tkIf, tkImport, tkIn, tkInclude, tkInterface, 
     tkIs, tkIsnot, tkIterator,
     tkLambda, tkLet,
-    tkMacro, tkMethod, tkMixin, tkMod, tkNil, tkNot, tkNotin, 
+    tkMacro, tkMethod, tkMixin, tkUsing, tkMod, tkNil, tkNot, tkNotin, 
     tkObject, tkOf, tkOr, tkOut, 
     tkProc, tkPtr, tkRaise, tkRef, tkReturn, tkShared, tkShl, tkShr, tkStatic,
     tkTemplate, 
@@ -75,7 +75,7 @@ const
     "finally", "for", "from", "generic", "if", 
     "import", "in", "include", "interface", "is", "isnot", "iterator",
     "lambda", "let", 
-    "macro", "method", "mixin", "mod", 
+    "macro", "method", "mixin", "using", "mod", 
     "nil", "not", "notin", "object", "of", "or", 
     "out", "proc", "ptr", "raise", "ref", "return", 
     "shared", "shl", "shr", "static",
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 47a4d284b..c0b1221ef 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -89,7 +89,7 @@ type
     errInvalidSectionStart, errGridTableNotImplemented, errGeneralParseError, 
     errNewSectionExpected, errWhitespaceExpected, errXisNoValidIndexFile, 
     errCannotRenderX, errVarVarTypeNotAllowed, errInstantiateXExplicitely,
-    errOnlyACallOpCanBeDelegator,
+    errOnlyACallOpCanBeDelegator, errUsingNoSymbol,
     
     errXExpectsTwoArguments, 
     errXExpectsObjectTypes, errXcanNeverBeOfThisSubtype, errTooManyIterations, 
@@ -318,6 +318,7 @@ const
     errVarVarTypeNotAllowed: "type \'var var\' is not allowed",
     errInstantiateXExplicitely: "instantiate '$1' explicitely",
     errOnlyACallOpCanBeDelegator: "only a call operator can be a delegator",
+    errUsingNoSymbol: "'$1' is not a variable, constant or a proc name",
     errXExpectsTwoArguments: "\'$1\' expects two arguments", 
     errXExpectsObjectTypes: "\'$1\' expects object types",
     errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype", 
diff --git a/compiler/parser.nim b/compiler/parser.nim
index ae9ec6105..d19149073 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -1775,6 +1775,7 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
   of tkVar: result = parseSection(p, nkVarSection, parseVariable)
   of tkBind: result = parseBind(p, nkBindStmt)
   of tkMixin: result = parseBind(p, nkMixinStmt)
+  of tkUsing: result = parseBind(p, nkUsingStmt)
   else: result = simpleStmt(p)
   
 proc parseStmt(p: var TParser): PNode =
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 8c20d0faa..b2f41d509 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -96,6 +96,11 @@ proc NotFoundError*(c: PContext, n: PNode, errors: seq[string]) =
 
   LocalError(n.Info, errGenerated, result)
 
+proc gatherUsedSyms(c: PContext, usedSyms: var seq[PNode]) =
+  for scope in walkScopes(c.currentScope):
+    if scope.usingSyms != nil:
+      for s in scope.usingSyms: usedSyms.safeAdd(s)
+
 proc resolveOverloads(c: PContext, n, orig: PNode,
                       filter: TSymKinds): TCandidate =
   var initialBinding: PNode
@@ -109,11 +114,27 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
     initialBinding = nil
 
   var errors: seq[string]
-
+  var usedSyms: seq[PNode]
+ 
   template pickBest(headSymbol: expr) =
     pickBestCandidate(c, headSymbol, n, orig, initialBinding,
                       filter, result, alt, errors)
 
+  gatherUsedSyms(c, usedSyms)
+  if usedSyms != nil:
+    var hiddenArg = if usedSyms.len > 1: newNode(nkClosedSymChoice, n.info, usedSyms)
+                    else: usedSyms[0]
+
+    n.sons.insert(hiddenArg, 1)
+    orig.sons.insert(hiddenArg, 1)
+    
+    pickBest(f)
+ 
+    if result.state != csMatch:
+      n.sons.delete(1)
+      orig.sons.delete(1)
+    else: return
+
   pickBest(f)
 
   let overloadsState = result.state
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index b9df29d39..30b28a35d 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1329,6 +1329,22 @@ proc newAnonSym(kind: TSymKind, info: TLineInfo,
   result = newSym(kind, idAnon, owner, info)
   result.flags = {sfGenSym}
 
+proc semUsing(c: PContext, n: PNode): PNode =
+  result = newNodeI(nkEmpty, n.info)
+  for e in n.sons:
+    let usedSym = semExpr(c, e)
+    if usedSym.kind == nkSym:
+      case usedSym.sym.kind
+      of skLocalVars + {skConst}:
+        c.currentScope.usingSyms.safeAdd(usedSym)
+        continue
+      of skProcKinds:
+        addDeclAt(c.currentScope, usedSym.sym)
+        continue
+      else: nil
+
+    LocalError(e.info, errUsingNoSymbol, e.renderTree)
+
 proc semExpandToAst(c: PContext, n: PNode): PNode =
   var macroCall = n[1]
   var expandedSym = expectMacroOrTemplateCall(c, macroCall)
@@ -1967,6 +1983,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   of nkForStmt, nkParForStmt: result = semFor(c, n)
   of nkCaseStmt: result = semCase(c, n)
   of nkReturnStmt: result = semReturn(c, n)
+  of nkUsingStmt: result = semUsing(c, n)
   of nkAsmStmt: result = semAsm(c, n)
   of nkYieldStmt: result = semYield(c, n)
   of nkPragma: pragma(c, c.p.owner, n, stmtPragmas)
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index f8a19ae19..b37a7bb4f 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -28,7 +28,7 @@ type
     wElif, wElse, wEnd, wEnum, wExcept, wExport,
     wFinally, wFor, wFrom, wGeneric, wIf, wImport, wIn, 
     wInclude, wInterface, wIs, wIsnot, wIterator, wLambda, wLet,
-    wMacro, wMethod, wMixin, wMod, wNil, 
+    wMacro, wMethod, wMixin, wUsing, wMod, wNil, 
     wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn, 
     wShared, wShl, wShr, wStatic, wTemplate, wTry, wTuple, wType, wVar, 
     wWhen, wWhile, wWith, wWithout, wXor, wYield,
@@ -72,7 +72,7 @@ type
     wPrivate, wProtected, wPublic, wRegister, wReinterpret_cast,
     wShort, wSigned, wSizeof, wStatic_cast, wStruct, wSwitch,
     wThis, wThrow, wTrue, wTypedef, wTypeid, wTypename,
-    wUnion, wUnsigned, wUsing, wVirtual, wVoid, wVolatile, wWchar_t,
+    wUnion, wUnsigned, wVirtual, wVoid, wVolatile, wWchar_t,
 
     wAlignas, wAlignof, wConstexpr, wDecltype, wNullptr, wNoexcept,
     wThread_local, wStatic_assert, wChar16_t, wChar32_t,
@@ -95,7 +95,7 @@ const
   
   cppNimSharedKeywords* = {
     wAsm, wBreak, wCase, wConst, wContinue, wDo, wElse, wEnum, wExport,
-    wFor, wIf, wReturn, wStatic, wTemplate, wTry, wWhile}
+    wFor, wIf, wReturn, wStatic, wTemplate, wTry, wWhile, wUsing }
 
   specialWords*: array[low(TSpecialWord)..high(TSpecialWord), string] = ["", 
     
@@ -107,7 +107,7 @@ const
     "finally", "for", "from", "generic", "if", 
     "import", "in", "include", "interface", "is", "isnot", "iterator",
     "lambda", "let",
-    "macro", "method", "mixin", "mod", "nil", "not", "notin", 
+    "macro", "method", "mixin", "using", "mod", "nil", "not", "notin",
     "object", "of", "or", 
     "out", "proc", "ptr", "raise", "ref", "return",
     "shared", "shl", "shr", "static",
@@ -154,7 +154,7 @@ const
     "private", "protected", "public", "register", "reinterpret_cast",
     "short", "signed", "sizeof", "static_cast", "struct", "switch",
     "this", "throw", "true", "typedef", "typeid",
-    "typename", "union", "unsigned", "using", "virtual", "void", "volatile",
+    "typename", "union", "unsigned", "virtual", "void", "volatile",
     "wchar_t",
 
     "alignas", "alignof", "constexpr", "decltype", "nullptr", "noexcept",
diff --git a/doc/keywords.txt b/doc/keywords.txt
index 2a775cd94..fa3ce4786 100644
--- a/doc/keywords.txt
+++ b/doc/keywords.txt
@@ -7,7 +7,7 @@ finally for from
 generic
 if import in include interface is isnot iterator
 lambda let
-macro method mixin mod
+macro method mixin using mod
 nil not notin
 object of or out
 proc ptr
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index 362e670e6..9ac6b0082 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -56,7 +56,7 @@ type
     nnkFromStmt,
     nnkIncludeStmt,
     
-    nnkBindStmt, nnkMixinStmt,
+    nnkBindStmt, nnkMixinStmt, nnkUsingStmt,
     nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr,
     nnkStmtListType, nnkBlockType, nnkTypeOfExpr, nnkObjectTy,
     nnkTupleTy, nnkTypeClassTy, nnkRecList, nnkRecCase, nnkRecWhen,