Changes by: Jason Hickey (jyh at cs.caltech.edu)
Date: 2005-08-30 20:35:58 -0700 (Tue, 30 Aug 2005)
Revision: 1440
Log message:

      This is a solution to the "export problem."
      
      So here was the problem.  Suppose you take a higher-order function (that
      part is no big deal), but the function ends in an export.
      
      In the non-higher-order case, there is no problem.
      
          X. =
              Z = 1
              f() =
                  Z = $(add $Z, 1)
                  export
      
          # This redefines X as a new object with Z=2
          X.f()
      
      But suppose the method escapes.
      
          X. = ...same as before...
          # Create a closure
          g = $(X.f)
          # Call the function, but it exports...
          g()
      
      Well, what does the export in g() mean?  X isn't mentioned, so it would
      be a sad thing to redefine X.  It would be even worse (as it is on the
      trunk) if the export meant that now Z is defined after the call g().
      
      It could be prevented by disallowing exports from higher-order functions
      entirely.  But we also have cases where we expect the export to be
      effective.
      
          text[] =
          foreach(x => a b c)
              text[] += $(x)
              export
          # We expect this to print "a b c"
          println($(text))
      
      This commit is permissive about exports.  Each scope is assigned an identifier,
      and exports are allowed only in identical scopes.
      
      File-level variables are no problem, they are always exported.  Object
      public/protected variables are exported only within the same object.
      Private variables are exported only within the same scope/function body.
      
      This means that the export in the g() above is ineffective.
      
      It also means that private exports also work as expected.
      
          f() =
              private.text =
              foreach(x => a b c)
                  text += $(x)
                  export
              # Prints "a b c"
              println($(x))
      
      In the next example, the export is ineffective.
      
          g() =
              private.x = 1
              export
      
          f() =
              g()
              # This is a link error
              println($(x))
      
      Private variables are lexically scoped, as usual.  Protected/public have
      the usual late-binding meaning.  File variables (that is, top-level
      variables in a file) are dynamically scoped.
      
      The program in this file will print "2", then "1".
      
         X = 1
         g() =
             println($(X))
         f() =
             X = 2
             # Prints "2"
             g()
         # Prints "1"
         g()
      
      The program in this file will print "1", then "1".
      
         private.X = 1
         g() =
             println($(X))
         f() =
             X = 2
             # Prints "1" (private variables are lexically scoped)
             g()
         # Prints "1"
         g()
      
      New definitions in a function body are private by default (so are
      the parameters).
      
         File1.om:
             X = 1
             g() =
                 println($(X))
      
         File2.om:
             import File1
             f() =
                 X = 2      # This new definition is for private.X in f()
                 File1.g()  # This prints "1"
      
         File3.om:
             open File1
             f() =
                 X = 2      # This refers to File1.X
                 g()        # This prints "2"
      

Changes  Path
+94 -77 omake-branches/omake_0_9_7_pre5/lib/parse/C/Dll.om
+0 -1 omake-branches/omake_0_9_7_pre5/lib/parse/C/Parse.om
+2 -1 omake-branches/omake_0_9_7_pre5/src/build/omake_builtin.ml
+4 -2 omake-branches/omake_0_9_7_pre5/src/build/omake_builtin_io_fun.ml
+203 -210 omake-branches/omake_0_9_7_pre5/src/build/omake_builtin_object.ml
+1 -1 omake-branches/omake_0_9_7_pre5/src/build/omake_builtin_target.ml
+60 -63 omake-branches/omake_0_9_7_pre5/src/clib/lm_dll.c
+13 -8 omake-branches/omake_0_9_7_pre5/src/clib/lm_dll.h
+4 -4 omake-branches/omake_0_9_7_pre5/src/clib/lm_dll_hooks.h
+12 -10 omake-branches/omake_0_9_7_pre5/src/env/omake_command_digest.ml
+83 -46 omake-branches/omake_0_9_7_pre5/src/env/omake_env.ml
+18 -14 omake-branches/omake_0_9_7_pre5/src/env/omake_env.mli
+108 -77 omake-branches/omake_0_9_7_pre5/src/env/omake_ir_ast.ml
+4 -5 omake-branches/omake_0_9_7_pre5/src/env/omake_ir_free_vars.ml
+8 -8 omake-branches/omake_0_9_7_pre5/src/env/omake_ir_semant.ml
+78 -30 omake-branches/omake_0_9_7_pre5/src/eval/omake_eval.ml
+1 -0 omake-branches/omake_0_9_7_pre5/src/eval/omake_eval.mli
+19 -12 omake-branches/omake_0_9_7_pre5/src/eval/omake_value.ml
+8 -7 omake-branches/omake_0_9_7_pre5/src/ir/omake_ir.ml
+14 -11 omake-branches/omake_0_9_7_pre5/src/ir/omake_ir_print.ml
+4 -4 omake-branches/omake_0_9_7_pre5/src/ir/omake_ir_util.ml
Properties omake-branches/omake_0_9_7_pre5/src/main
+2 -0 omake-branches/omake_0_9_7_pre5/src/main/.cvsignore
+7 -0 omake-branches/omake_0_9_7_pre5/tests/dll/simple/Test.om
+10 -110 omake-branches/omake_0_9_7_pre5/tests/dll/simple/dll.c
+10 -0 omake-branches/omake_0_9_7_pre5/tests/dll/simple/dll.h
+1 -11 omake-branches/omake_0_9_7_pre5/tests/dll/simple/lib.c
+1 -0 omake-branches/omake_0_9_7_pre5/tests/dll/simple/values.export