summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim28
-rw-r--r--compiler/semexprs.nim3
-rw-r--r--compiler/semmagic.nim30
-rw-r--r--lib/system.nim7
-rw-r--r--tests/run/tlocals.nim11
-rw-r--r--todo.txt2
-rw-r--r--web/news.txt1
7 files changed, 64 insertions, 18 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 5d420c6d2..b59c93950 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -455,12 +455,12 @@ type
     mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr, 
     mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet, 
     mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT, 
-    mConTArr, mConTT, mSlice, 
+    mConTArr, mConTT, mSlice,
     mFields, mFieldPairs, mOmpParFor,
-    mAppendStrCh, mAppendStrStr, mAppendSeqElem, 
-    mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq, 
-    mIsPartOf, mAstToStr, mRand, 
-    mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast, 
+    mAppendStrCh, mAppendStrStr, mAppendSeqElem,
+    mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq,
+    mIsPartOf, mAstToStr, mRand,
+    mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast,
     mNewString, mNewStringOfCap,
     mReset,
     mArray, mOpenArray, mRange, mSet, mSeq, mVarargs,
@@ -469,18 +469,18 @@ type
     mUInt, mUInt8, mUInt16, mUInt32, mUInt64,
     mFloat, mFloat32, mFloat64, mFloat128,
     mBool, mChar, mString, mCstring,
-    mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc, 
+    mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc,
     mVoidType, mPNimrodNode,
-    mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor, 
-    mNimrodMinor, mNimrodPatch, mCpuEndian, mHostOS, mHostCPU, mAppType, 
-    mNaN, mInf, mNegInf, 
+    mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor,
+    mNimrodMinor, mNimrodPatch, mCpuEndian, mHostOS, mHostCPU, mAppType,
+    mNaN, mInf, mNegInf,
     mCompileOption, mCompileOptionArg,
-    mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, mNKind, 
-    mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal, 
+    mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, mNKind,
+    mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal,
     mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, mNLineInfo,
-    mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mIdentToStr, 
-    mNBindSym, mNCallSite,
-    mEqIdent, mEqNimrodNode, mNHint, mNWarning, mNError, 
+    mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mIdentToStr,
+    mNBindSym, mLocals, mNCallSite,
+    mEqIdent, mEqNimrodNode, mNHint, mNWarning, mNError,
     mInstantiationInfo, mGetTypeInfo
 
 # things that we can evaluate safely at compile time, even if not asked for it:
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 2cc0de371..7d5fdc4f2 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -25,7 +25,8 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     # do not produce another redundant error message:
     #raiseRecoverableError("")
     result = errorNode(c, n)
-  if result.typ != nil: 
+  if result.typ != nil:
+    # XXX tyGenericInst here?
     if result.typ.kind == tyVar: result = newDeref(result)
   else:
     LocalError(n.info, errExprXHasNoType, 
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 119e1ef19..31eb7a9d5 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2012 Andreas Rumpf
+#        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -73,6 +73,33 @@ proc semBindSym(c: PContext, n: PNode): PNode =
   else:
     LocalError(n.sons[1].info, errUndeclaredIdentifier, sl.strVal)
 
+proc semLocals(c: PContext, n: PNode): PNode =
+  var counter = 0
+  var tupleType = newTypeS(tyTuple, c)
+  result = newNodeIT(nkPar, n.info, tupleType)
+  tupleType.n = newNodeI(nkRecList, n.info)
+  # for now we skip openarrays ...
+  for i in countdown(c.tab.tos-1, ModuleTablePos+1):
+    for it in items(c.tab.stack[i]):
+      # XXX parameters' owners are wrong for generics; this caused some pain
+      # for closures too; we should finally fix it.
+      #if it.owner != c.p.owner: return result
+      if it.kind in skLocalVars and
+          it.typ.skipTypes({tyGenericInst, tyVar}).kind notin
+              {tyVarargs, tyOpenArray, tyTypeDesc, tyExpr, tyStmt, tyEmpty}:
+
+        var field = newSym(skField, it.name, getCurrOwner(), n.info)
+        field.typ = it.typ.skipTypes({tyGenericInst, tyVar})
+        field.position = counter
+        inc(counter)
+
+        addSon(tupleType.n, newSymNode(field))
+        addSonSkipIntLit(tupleType, field.typ)
+        
+        var a = newSymNode(it, result.info)
+        if it.typ.skipTypes({tyGenericInst}).kind == tyVar: a = newDeref(a)
+        result.add(a)
+
 proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode
 proc magicsAfterOverloadResolution(c: PContext, n: PNode, 
                                    flags: TExprFlags): PNode =
@@ -86,5 +113,6 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
   of mOrd: result = semOrd(c, n)
   of mShallowCopy: result = semShallowCopy(c, n, flags)
   of mNBindSym: result = semBindSym(c, n)
+  of mLocals: result = semLocals(c, n)
   else: result = n
 
diff --git a/lib/system.nim b/lib/system.nim
index 5bcd7b02d..08de426c4 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -2548,3 +2548,10 @@ proc safeAdd*(x: var string, y: string) =
   if x == nil: x = y
   else: x.add(y)
 
+proc locals*(): TObject {.magic: "Locals", noSideEffect.} =
+  ## generates a tuple constructor expression listing all the local variables
+  ## in the current scope. This is quite fast as it does not rely
+  ## on any debug or runtime information. Note that in constrast to what
+  ## the official signature says, the return type is not ``TObject`` but a
+  ## tuple of a structure that depends on the current scope.
+  nil
diff --git a/tests/run/tlocals.nim b/tests/run/tlocals.nim
new file mode 100644
index 000000000..94a34139b
--- /dev/null
+++ b/tests/run/tlocals.nim
@@ -0,0 +1,11 @@
+discard """
+  output: "(x: string here, a: 1, b: 3)"
+"""
+
+proc simple[T](a, b: T) = 
+  var
+    x = "string here"
+  echo locals()
+  
+simple(1, 3)
+
diff --git a/todo.txt b/todo.txt
index d159728e3..9b1082a81 100644
--- a/todo.txt
+++ b/todo.txt
@@ -13,7 +13,6 @@ version 0.9.2
 - acyclic vs prunable; introduce GC hints
 - CGEN: ``restrict`` pragma + backend support; computed goto support
 - document NimMain and check whether it works for threading
-- implement ``system.locals`` magic iterator
 
 
 Bugs
@@ -27,7 +26,6 @@ Bugs
 - aporia.nim(968, 5) Error: ambiguous identifier: 'DELETE' -- 
   use a qualifier
 - blocks can "export" an identifier but the CCG generates {} for them ...
-- JS gen: fix exception handling
 - osproc execProcesses can deadlock if all processes fail (as experienced
   in c++ mode)
 - bootstrapping does not work in C++ mode
diff --git a/web/news.txt b/web/news.txt
index 7bd0e4f4f..2add6aefa 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -24,6 +24,7 @@ Library Additions
 - There is a new experimental mark&sweep GC which can be faster (or much 
   slower) than the default GC. Enable with ``--gc:markAndSweep``.
 - Added ``system.onRaise`` to support a condition system.
+- Added ``system.locals`` that provides access to a proc's locals.
 - Added ``macros.quote`` for AST quasi-quoting.
 - Added ``system.unsafeNew`` to support hacky variable length objects.
 - ``system.fields`` and ``system.fieldPairs`` support ``object`` too; they