Permalink
Browse files

module-local eval(). fixes #1651

also add doc for baremodule
  • Loading branch information...
JeffBezanson committed Dec 5, 2012
1 parent dfad04a commit 9ecd2074c318ee1ffdc1ce19e2596b4d361b9794
Showing with 77 additions and 39 deletions.
  1. +6 −1 base/abstractarray.jl
  2. +1 −1 base/boot.jl
  3. +5 −5 base/client.jl
  4. +1 −1 base/expr.jl
  5. +1 −1 base/multi.jl
  6. +1 −1 base/show.jl
  7. +3 −0 base/sysimg.jl
  8. +1 −1 base/util.jl
  9. +27 −9 doc/manual/modules.rst
  10. +15 −16 src/builtins.c
  11. +2 −0 src/init.c
  12. +14 −3 src/julia-parser.scm
View
@@ -233,6 +233,11 @@ end
function gen_cartesian_map(cache, genbodies, ranges, exargnames, exargs...)
N = length(ranges)
if !has(cache,N)
+ if isdefined(genbodies,:code)
+ mod = genbodies.code.module
+ else
+ mod = Main
+ end
dimargnames = { symbol(string("_d",i)) for i=1:N }
ivars = { symbol(string("_i",i)) for i=1:N }
bodies = genbodies(ivars)
@@ -269,7 +274,7 @@ function gen_cartesian_map(cache, genbodies, ranges, exargnames, exargs...)
end
_F_
end
- f = eval(fexpr)
+ f = eval(mod,fexpr)
cache[N] = f
else
f = cache[N]
View
@@ -133,7 +133,7 @@ export ..., ANY, ASCIIString, AbstractArray, AbstractKind, Any, Array,
GetfieldNode,
# functions
setfield, applicable, apply, apply_type, arraylen, arrayref, arrayset,
- arraysize, convert_default, convert_tuple, eval, fieldtype, getfield,
+ arraysize, convert_default, convert_tuple, fieldtype, getfield,
include, invoke, is, ===, isa, isdefined, method_exists,
subtype, throw, tuple, tuplelen, tupleref, typeassert, typeof, yieldto,
# constants
View
@@ -67,7 +67,7 @@ function _jl_eval_user_input(ast::ANY, show_value)
println()
iserr, lasterr = false, ()
else
- value = eval(ast)
+ value = eval(Main,ast)
global ans = value
if !is(value,nothing) && show_value
if _jl_have_color
@@ -143,7 +143,7 @@ function process_options(args::Array{Any,1})
repl = true
startup = true
if has(ENV, "JL_POST_BOOT")
- eval(parse_input_line(ENV["JL_POST_BOOT"]))
+ eval(Main,parse_input_line(ENV["JL_POST_BOOT"]))
end
i = 1
while i <= length(args)
@@ -157,18 +157,18 @@ function process_options(args::Array{Any,1})
repl = false
i+=1
ARGS = args[i+1:end]
- eval(parse_input_line(args[i]))
+ eval(Main,parse_input_line(args[i]))
break
elseif args[i]=="-E"
repl = false
i+=1
ARGS = args[i+1:end]
- show(eval(parse_input_line(args[i])))
+ show(eval(Main,parse_input_line(args[i])))
println()
break
elseif args[i]=="-P"
i+=1
- eval(parse_input_line(args[i]))
+ eval(Main,parse_input_line(args[i]))
elseif args[i]=="-L"
i+=1
load(args[i])
View
@@ -60,5 +60,5 @@ macroexpand(x) = ccall(:jl_macroexpand, Any, (Any,), x)
## misc syntax ##
macro eval(x)
- :(eval($(expr(:quote,x))))
+ :($(esc(:eval))($(expr(:quote,x))))
end
View
@@ -1185,7 +1185,7 @@ end
macro everywhere(ex)
quote
@sync begin
- at_each(()->eval($(expr(:quote,ex))))
+ at_each(()->eval(Main,$(expr(:quote,ex))))
end
end
end
View
@@ -776,7 +776,7 @@ function whos(m::Module, pattern::Regex)
for s in sort(map(string, names(m)))
v = symbol(s)
if isdefined(m,v) && ismatch(pattern, s)
- println(rpad(v, 30), summary(eval(m,v)))
+ println(rpad(s, 30), summary(eval(m,v)))
end
end
end
View
@@ -1,5 +1,8 @@
baremodule Base
+eval(x) = Core.eval(Base,x)
+eval(m,x) = Core.eval(m,x)
+
include("export.jl")
if false
View
@@ -262,7 +262,7 @@ function remote_load(dict)
end
end
-evalfile(fname::String) = eval(parse(readall(fname))[1])
+evalfile(fname::String) = eval(Main,parse(readall(fname))[1])
# help
View
@@ -14,7 +14,7 @@ and specify which of your names are intended to be public (via exporting).
The following example illustrates the major features of modules::
module MyModule
- using Base
+ using Lib
export MyType, foo
@@ -38,13 +38,13 @@ and type ``MyType`` are
exported, and so will be available for importing into other modules.
Function ``bar`` is private to ``MyModule``.
-The statement ``using Base`` means that the ``Base`` module (which contains
-the standard library definitions) will be available for resolving names
+The statement ``using Lib`` means that a module called ``Lib``
+will be available for resolving names
as needed. When a global variable is encountered that has no definition in
-the current module, the system will search for it in ``Base`` and import it
+the current module, the system will search for it in ``Lib`` and import it
if it is found there.
This means that all uses of that global within the current module will
-resolve to the definition of that variable in ``Base``.
+resolve to the definition of that variable in ``Lib``.
Once a variable is imported this way (or, equivalently, with the ``import``
keyword), a module may not create its own variable with the same name.
@@ -78,7 +78,6 @@ for example testing code by running it with "safe" versions of some
operators::
module Normal
- using Base
include("mycode.jl")
end
@@ -96,15 +95,34 @@ There are three important standard modules: Main, Core, and Base.
Main is the top-level module, and Julia starts with Main set as the
current module.
Variables defined at the prompt go in Main, and ``whos()`` lists variables
-in Main. Main implicitly contains ``using Base``.
+in Main.
Core contains all identifiers considered "built in" to the language, i.e.
part of the core language and not libraries. Every module implicitly
specifies ``using Core``, since you can't do anything without those
definitions.
-Base is the standard library (the contents of base/). This is not imported
-by default, so most modules will want to start with ``using Base``.
+Base is the standard library (the contents of base/). All modules implicitly
+contain ``using Base``, since this is needed in the vast majority of cases.
+
+
+Default top-level definitions and bare modules
+----------------------------------------------
+
+In addition to ``using Base``, a module automatically contains a definition
+of the ``eval`` function, which evaluates expressions within the context of
+that module.
+
+If these definitions are not wanted, modules can be defined using the
+keyword ``baremodule`` instead. In terms of ``baremodule``, a standard
+``module`` looks like this:
+
+ baremodule Mod
+ using Base
+ eval(x) = Core.eval(Mod, x)
+ eval(m,x) = Core.eval(m, x)
+ ...
+ end
Miscellaneous details
View
@@ -263,30 +263,29 @@ JL_CALLABLE(jl_f_apply)
JL_CALLABLE(jl_f_top_eval)
{
+ jl_module_t *m;
+ jl_value_t *ex;
if (nargs == 1) {
- jl_expr_t *ex = (jl_expr_t*)args[0];
- /*
- if (jl_is_expr(ex) && (ex->head == export_sym ||
- ex->head == import_sym ||
- ex->head == using_sym)) {
- jl_errorf("unsupported or misplaced expression %s", ex->head->name);
- }
- */
- return jl_toplevel_eval((jl_value_t*)ex);
+ m = jl_main_module;
+ ex = args[0];
}
- if (nargs != 2) {
- JL_NARGS(eval, 1, 1);
+ else {
+ JL_NARGS(eval, 2, 2);
+ JL_TYPECHK(eval, module, args[0]);
+ m = (jl_module_t*)args[0];
+ ex = args[1];
+ }
+ if (jl_is_symbol(ex)) {
+ return jl_eval_global_var(m, (jl_sym_t*)ex);
}
- JL_TYPECHK(eval, module, args[0]);
- jl_module_t *m = (jl_module_t*)args[0];
- if (jl_is_symbol(args[1])) {
- return jl_eval_global_var(m, (jl_sym_t*)args[1]);
+ if (m == jl_current_module) {
+ return jl_toplevel_eval(ex);
}
jl_value_t *v=NULL;
jl_module_t *last_m = jl_current_module;
JL_TRY {
jl_current_module = m;
- v = jl_toplevel_eval(args[1]);
+ v = jl_toplevel_eval(ex);
}
JL_CATCH {
jl_current_module = last_m;
View
@@ -210,6 +210,8 @@ void julia_init(char *imageFile)
// it does "using Base" if Base is available.
if (jl_base_module != NULL)
jl_module_using(jl_main_module, jl_base_module);
+ // eval() uses Main by default, so Main.eval === Core.eval
+ jl_module_import(jl_main_module, jl_core_module, jl_symbol("eval"));
jl_current_module = jl_main_module;
#ifndef __WIN32__
View
@@ -965,9 +965,20 @@
(error "expected assignment after const")
`(const ,assgn))))
((module baremodule)
- (let ((name (parse-atom s)))
- (begin0 (list 'module (eq? word 'module) name (parse-block s))
- (expect-end s))))
+ (let* ((name (parse-atom s))
+ (body (parse-block s)))
+ (expect-end s)
+ (list 'module (eq? word 'module) name
+ (if (eq? word 'module)
+ (list* 'block
+ ;; add definitions for module-local eval
+ (let ((x (gensym)))
+ `(= (call eval ,x)
+ (call (|.| Core 'eval) ,name ,x)))
+ `(= (call eval m x)
+ (call (|.| Core 'eval) m x))
+ (cdr body))
+ body))))
((export)
(let ((es (map macrocall-to-atsym
(parse-comma-separated-assignments s))))

0 comments on commit 9ecd207

Please sign in to comment.