summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xcompiler/ccgstmts.nim4
-rwxr-xr-xcompiler/evals.nim45
-rwxr-xr-xcompiler/sem.nim2
-rwxr-xr-xcompiler/transf.nim2
-rwxr-xr-xtodo.txt8
5 files changed, 40 insertions, 21 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 605440fc3..edda1997c 100755
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -22,7 +22,7 @@ proc genVarTuple(p: BProc, n: PNode) =
   var t = tup.t
   for i in countup(0, L-3): 
     var v = n.sons[i].sym
-    if sfGlobal in v.flags: 
+    if sfGlobal in v.flags and v.kind != skForVar: 
       assignGlobalVar(p, v)
       genObjectInit(p, cpsInit, v.typ, v.loc, true)
     else:
@@ -47,7 +47,7 @@ proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} =
 proc genSingleVar(p: BProc, a: PNode) =
   var v = a.sons[0].sym
   var immediateAsgn = a.sons[2].kind != nkEmpty
-  if sfGlobal in v.flags: 
+  if sfGlobal in v.flags and v.kind != skForVar: 
     assignGlobalVar(p, v)
     genObjectInit(p, cpsInit, v.typ, v.loc, true)
   else:
diff --git a/compiler/evals.nim b/compiler/evals.nim
index 886738704..3519e2e4d 100755
--- a/compiler/evals.nim
+++ b/compiler/evals.nim
@@ -27,11 +27,18 @@ type
     next*: PStackFrame        # for stacking
     params*: TNodeSeq         # parameters passed to the proc
   
+  TEvalMode* = enum           ## reason for evaluation
+    emRepl,                   ## evaluate because in REPL mode
+    emConst,                  ## evaluate for 'const' according to spec
+    emOptimize,               ## evaluate for optimization purposes (same as
+                              ## emConst?)
+    emStatic                  ## evaluate for enforced compile time eval
+                              ## ('static' context)
   TEvalContext* = object of passes.TPassContext
     module*: PSym
     tos*: PStackFrame         # top of stack
     lastException*: PNode
-    optEval*: bool            # evaluation done for optimization purposes
+    mode*: TEvalMode
     globals*: TIdNodeTable    # state of global vars
   
   PEvalContext* = ref TEvalContext
@@ -53,10 +60,10 @@ proc newStackFrame*(): PStackFrame =
   result.params = @[]
 
 proc newEvalContext*(module: PSym, filename: string, 
-                     optEval: bool): PEvalContext = 
+                     mode: TEvalMode): PEvalContext = 
   new(result)
   result.module = module
-  result.optEval = optEval
+  result.mode = mode
   initIdNodeTable(result.globals)
 
 proc pushStackFrame*(c: PEvalContext, t: PStackFrame) {.inline.} = 
@@ -342,18 +349,21 @@ proc evalVariable(c: PStackFrame, sym: PSym, flags: TEvalFlags): PNode =
   #result = emptyNode
 
 proc evalGlobalVar(c: PEvalContext, s: PSym, flags: TEvalFlags): PNode =
-  result = IdNodeTableGet(c.globals, s)
-  if result != nil: 
-    if not aliasNeeded(result, flags): 
-      result = copyTree(result)
-  else:
-    result = s.ast
-    if result == nil or result.kind == nkEmpty:
-      result = getNullValue(s.typ, s.info)
+  if sfCompileTime in s.flags or c.mode == emRepl:
+    result = IdNodeTableGet(c.globals, s)
+    if result != nil: 
+      if not aliasNeeded(result, flags): 
+        result = copyTree(result)
     else:
-      result = evalAux(c, result, {})
-      if isSpecial(result): return
-    IdNodeTablePut(c.globals, s, result)
+      result = s.ast
+      if result == nil or result.kind == nkEmpty:
+        result = getNullValue(s.typ, s.info)
+      else:
+        result = evalAux(c, result, {})
+        if isSpecial(result): return
+      IdNodeTablePut(c.globals, s, result)
+  else:
+    result = raiseCannotEval(nil, s.info)
 
 proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = 
   result = evalAux(c, n.sons[0], flags)
@@ -540,7 +550,8 @@ proc evalAnd(c: PEvalContext, n: PNode): PNode =
   if result.intVal != 0: result = evalAux(c, n.sons[2], {})
   
 proc evalNew(c: PEvalContext, n: PNode): PNode = 
-  if c.optEval: return raiseCannotEval(c, n.info)
+  #if c.mode == emOptimize: return raiseCannotEval(c, n.info)
+  
   # we ignore the finalizer for now and most likely forever :-)
   result = evalAux(c, n.sons[1], {efLValue})
   if isSpecial(result): return 
@@ -1269,7 +1280,7 @@ proc eval*(c: PEvalContext, n: PNode): PNode =
       stackTrace(c, n, errCannotInterpretNodeX, renderTree(n))
 
 proc evalConstExpr*(module: PSym, e: PNode): PNode = 
-  var p = newEvalContext(module, "", true)
+  var p = newEvalContext(module, "", emConst)
   var s = newStackFrame()
   s.call = e
   pushStackFrame(p, s)
@@ -1296,7 +1307,7 @@ proc evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode =
   dec(evalTemplateCounter)
 
 proc myOpen(module: PSym, filename: string): PPassContext = 
-  var c = newEvalContext(module, filename, false)
+  var c = newEvalContext(module, filename, emRepl)
   pushStackFrame(c, newStackFrame())
   result = c
 
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 58a73a3a8..8bb8758b7 100755
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -125,7 +125,7 @@ proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
                   semCheck: bool = true): PNode = 
   markUsed(n, sym)
   if c.evalContext == nil:
-    c.evalContext = newEvalContext(c.module, "", false)
+    c.evalContext = newEvalContext(c.module, "", emStatic)
   result = evalMacroCall(c.evalContext, n, sym)
   if semCheck: result = semAfterMacroCall(c, result, sym)
 
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 986d5311d..ba74323be 100755
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -199,7 +199,7 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode =
     elif it.kind == nkIdentDefs: 
       if it.sons[0].kind != nkSym: InternalError(it.info, "transformVarSection")
       var newVar = copySym(it.sons[0].sym)
-      incl(newVar.flags, sfFromGeneric) 
+      incl(newVar.flags, sfFromGeneric)
       # fixes a strange bug for rodgen:
       #include(it.sons[0].sym.flags, sfFromGeneric);
       newVar.owner = getCurrOwner(c)
diff --git a/todo.txt b/todo.txt
index f7a545e70..50fc080b9 100755
--- a/todo.txt
+++ b/todo.txt
@@ -1,6 +1,7 @@
 version 0.9.0
 =============
 
+- implement 'static' vs. 'const'
 - ``=`` should be overloadable; requires specialization for ``=``
 - fix remaining generics bugs
 - fix remaining closure bugs:
@@ -139,6 +140,13 @@ Low priority
 - implement closures that support nesting > 1
 
 
+Further optimization ideas
+==========================
+
+- To optimize further copies away, you want to gather the additional
+  information inlining would provide, but don't inline for code size reasons.
+
+
 Version 2
 =========
 
class="n">listdir(TESTDIR) assumed_filenames = list(map(lambda str: os.path.join(TESTDIR, str), assumed_filenames)) assumed_filenames.sort() dir.filenames.sort() self.assertTrue(len(dir) > 0) self.assertEqual(dir.filenames, assumed_filenames) # build a file object for each file in the list assumed_filenames # and find exactly one equivalent in dir.files for name in assumed_filenames: f = File(name) f.load() for dirfile in dir.files: if (f.path == dirfile.path and f.stat == dirfile.stat): break else: self.fail("couldn't find file {0}".format(name)) def test_nonexistant_dir(self): dir = Directory(NONEXISTANT_DIR) dir.load_content() self.assertTrue(dir.content_loaded) self.assertFalse(dir.exists) self.assertFalse(dir.accessible) self.assertEqual(dir.filenames, None) self.assertRaises(fsobject.NotLoadedYet, len, dir) self.assertRaises(fsobject.NotLoadedYet, dir.__getitem__, 0) def test_load_if_outdated(self): import os import time # modify the directory. If the time between the last modification # was within the filesystems resolution of mtime, we should have a reload def modify_dir(): open(TESTFILE, 'w').close() os.unlink(TESTFILE) def mtime(): return os.stat(TESTDIR).st_mtime dir = Directory(TESTDIR) dir.load() # If the modification happens to be in the same second as the # last modification, it will result in mtime having the same # integer value. So we wait until the resolution is exceeded # and mtime differs. old_mtime = mtime() for i in range(50): modify_dir() if old_mtime != mtime(): break time.sleep(0.1) else: # fail after 5 seconds of trying self.fail( "Cannot perform test: mtime of TESTDIR is not being updated.") self.assertTrue(dir.load_if_outdated()) if __name__ == '__main__': unittest.main()