Skip to content

Commit c696629

Browse files
committed
make (top x) node always refer to Base.x
consistently wrap all calls generated by the front end in (top ). this makes them behave like macros defined in Base, which is reasonable. related to #1484. this at least prevents such collisions for now, but it may not be the final behavior we settle on. we may want some names (like ref) evaluated in the context where they occur.
1 parent c4d199d commit c696629

9 files changed

+94
-44
lines changed

base/inference.jl

+40-18
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,18 @@ _ieval(x) = eval((inference_stack::CallStack).mod, x)
7373
_iisdefined(x) = isdefined((inference_stack::CallStack).mod, x)
7474

7575
_iisconst(s::SymbolNode) = _iisconst(s.name)
76-
_iisconst(s::TopNode) = _iisconst(s.name)
76+
_iisconst(s::TopNode) = isconst(_basemod(), s.name)
7777
_iisconst(x::Expr) = false
7878
_iisconst(x) = true
7979

80+
function _basemod()
81+
m = (inference_stack::CallStack).mod
82+
if m === Core || m === Base
83+
return m
84+
end
85+
return Main.Base
86+
end
87+
8088
cmp_tfunc = (x,y)->Bool
8189

8290
isType(t::ANY) = isa(t,AbstractKind) && is((t::AbstractKind).name,Type.name)
@@ -397,7 +405,8 @@ end
397405

398406
function isconstantfunc(f, sv::StaticVarInfo)
399407
if isa(f,TopNode)
400-
return _iisconst(f.name) && f.name
408+
m = _basemod()
409+
return isconst(m, f.name) && isdefined(m, f.name) && f
401410
end
402411
if isa(f,GetfieldNode) && isa(f.value,Module)
403412
M = f.value; s = f.name
@@ -710,7 +719,7 @@ function abstract_eval(e::QuoteNode, vtypes, sv::StaticVarInfo)
710719
end
711720

712721
function abstract_eval(e::TopNode, vtypes, sv::StaticVarInfo)
713-
return abstract_eval_global(e.name)
722+
return abstract_eval_global(_basemod(), e.name)
714723
end
715724

716725
const _jl_Type_Array = Type{Array}
@@ -732,11 +741,14 @@ end
732741
# type Undef, only None.
733742
# typealias Top Union(Any,Undef)
734743

735-
function abstract_eval_global(s::Symbol)
736-
if _iisconst(s)
737-
return abstract_eval_constant(_ieval(s))
744+
abstract_eval_global(s::Symbol) =
745+
abstract_eval_global((inference_stack::CallStack).mod, s)
746+
747+
function abstract_eval_global(M, s::Symbol)
748+
if isconst(M,s)
749+
return abstract_eval_constant(eval(M,s))
738750
end
739-
if !_iisdefined(s)
751+
if !isdefined(M,s)
740752
return Top
741753
end
742754
# TODO: change to Undef if there's a way to clear variables
@@ -1359,14 +1371,23 @@ end
13591371

13601372
sym_replace(x, from1, from2, to1, to2) = x
13611373

1362-
# see if a symbol resolves the same in two modules
1363-
function resolves_same(sym, from, to)
1374+
# return an expr to evaluate "from.sym" in module "to"
1375+
function resolve_relative(sym, from, to, typ, orig)
13641376
if is(from,to)
1365-
return true
1377+
return orig
1378+
end
1379+
const_from = (isconst(from,sym) && isdefined(from,sym))
1380+
const_to = (isconst(to,sym) && isdefined(to,sym))
1381+
if const_from
1382+
if const_to && is(eval(from,sym), eval(to,sym))
1383+
return orig
1384+
end
1385+
m = _basemod()
1386+
if is(from,m) || is(from,Core)
1387+
return _jl_tn(sym)
1388+
end
13661389
end
1367-
# todo: better
1368-
return (isconst(from,sym) && isconst(to,sym) && isdefined(from,sym) &&
1369-
isdefined(to,sym) && is(eval(from,sym),eval(to,sym)))
1390+
return GetfieldNode(from, sym, typ)
13701391
end
13711392

13721393
# annotate symbols with their original module for inlining
@@ -1383,14 +1404,15 @@ function resolve_globals(s::Symbol, from, to, env1, env2)
13831404
if contains_is(env1, s) || contains_is(env2, s)
13841405
return s
13851406
end
1386-
resolves_same(s, from, to) ? s : GetfieldNode(from, s, Any)
1407+
resolve_relative(s, from, to, Any, s)
13871408
end
13881409

13891410
function resolve_globals(s::SymbolNode, from, to, env1, env2)
1390-
if contains_is(env1, s.name) || contains_is(env2, s.name)
1411+
name = s.name
1412+
if contains_is(env1, name) || contains_is(env2, name)
13911413
return s
13921414
end
1393-
resolves_same(s.name, from, to) ? s : GetfieldNode(from, s.name, s.typ)
1415+
resolve_relative(name, from, to, s.typ, s)
13941416
end
13951417

13961418
resolve_globals(x, from, to, env1, env2) = x
@@ -1416,7 +1438,7 @@ function exprtype(x::ANY)
14161438
elseif isa(x,SymbolNode)
14171439
return x.typ
14181440
elseif isa(x,TopNode)
1419-
return abstract_eval_global(x.name)
1441+
return abstract_eval_global(_basemod(), x.name)
14201442
elseif isa(x,Symbol)
14211443
sv = inference_stack.sv
14221444
if is_local(sv, x)
@@ -1763,7 +1785,7 @@ function is_known_call(e::Expr, func, sv)
17631785
return false
17641786
end
17651787
f = isconstantfunc(e.args[1], sv)
1766-
return isa(f,Symbol) && is(_ieval(f), func)
1788+
return !is(f,false) && is(_ieval(f), func)
17671789
end
17681790

17691791
# compute set of vars assigned once

src/cgutils.cpp

+19-3
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,11 @@ static Value *julia_bool(Value *cond)
423423

424424
static jl_value_t *static_eval(jl_value_t *ex, jl_codectx_t *ctx, bool sparams=true);
425425

426+
static inline jl_module_t *topmod(jl_codectx_t *ctx)
427+
{
428+
return jl_base_relative_to(ctx->module);
429+
}
430+
426431
static jl_value_t *expr_type(jl_value_t *e, jl_codectx_t *ctx)
427432
{
428433
if (jl_is_expr(e))
@@ -440,7 +445,20 @@ static jl_value_t *expr_type(jl_value_t *e, jl_codectx_t *ctx)
440445
e = v;
441446
goto type_of_constant;
442447
}
443-
if (jl_is_topnode(e) || jl_is_symbol(e)) {
448+
if (jl_is_topnode(e)) {
449+
e = jl_fieldref(e,0);
450+
jl_binding_t *b = jl_get_binding(topmod(ctx), (jl_sym_t*)e);
451+
if (!b || !b->value)
452+
return jl_top_type;
453+
if (b->constp) {
454+
e = b->value;
455+
goto type_of_constant;
456+
}
457+
else {
458+
return (jl_value_t*)jl_any_type;
459+
}
460+
}
461+
if (jl_is_symbol(e)) {
444462
if (jl_is_symbol(e)) {
445463
if (is_global((jl_sym_t*)e, ctx)) {
446464
// look for static parameter
@@ -456,8 +474,6 @@ static jl_value_t *expr_type(jl_value_t *e, jl_codectx_t *ctx)
456474
return (jl_value_t*)jl_any_type;
457475
}
458476
}
459-
if (jl_is_topnode(e))
460-
e = jl_fieldref(e,0);
461477
jl_binding_t *b = jl_get_binding(ctx->module, (jl_sym_t*)e);
462478
if (!b || !b->value)
463479
return jl_top_type;

src/codegen.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ static jl_value_t *static_eval(jl_value_t *ex, jl_codectx_t *ctx, bool sparams)
375375
return NULL;
376376
}
377377
if (jl_is_topnode(ex)) {
378-
jl_binding_t *b = jl_get_binding(ctx->module,
378+
jl_binding_t *b = jl_get_binding(topmod(ctx),
379379
(jl_sym_t*)jl_fieldref(ex,0));
380380
if (b == NULL) return NULL;
381381
if (b->constp)
@@ -428,8 +428,7 @@ static bool is_constant(jl_value_t *ex, jl_codectx_t *ctx, bool sparams=true)
428428
static bool symbol_eq(jl_value_t *e, jl_sym_t *sym)
429429
{
430430
return ((jl_is_symbol(e) && ((jl_sym_t*)e)==sym) ||
431-
(jl_is_symbolnode(e) && jl_symbolnode_sym(e)==sym) ||
432-
(jl_is_topnode(e) && ((jl_sym_t*)jl_fieldref(e,0))==sym));
431+
(jl_is_symbolnode(e) && jl_symbolnode_sym(e)==sym));
433432
}
434433

435434
// --- find volatile variables ---
@@ -1486,9 +1485,10 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed,
14861485
else if (jl_is_topnode(expr)) {
14871486
jl_sym_t *var = (jl_sym_t*)jl_fieldref(expr,0);
14881487
jl_value_t *etype = expr_type(expr, ctx);
1489-
jl_binding_t *b = jl_get_binding(ctx->module, var);
1488+
jl_module_t *mod = topmod(ctx);
1489+
jl_binding_t *b = jl_get_binding(mod, var);
14901490
if (b == NULL)
1491-
b = jl_get_binding_wr(ctx->module, var);
1491+
b = jl_get_binding_wr(mod, var);
14921492
Value *bp = literal_pointer_val(&b->value, jl_ppvalue_llvmt);
14931493
if ((b->constp && b->value!=NULL) ||
14941494
(etype!=(jl_value_t*)jl_any_type &&

src/init.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ void julia_init(char *imageFile)
207207

208208
// the Main module is the one which is always open, and set as the
209209
// current module for bare (non-module-wrapped) toplevel expressions.
210-
// it does import Base.* if Base is available.
210+
// it does "using Base" if Base is available.
211211
if (jl_base_module != NULL)
212212
jl_module_using(jl_main_module, jl_base_module);
213213
jl_current_module = jl_main_module;

src/interpreter.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,10 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl)
9494
return jl_fieldref(e,0);
9595
}
9696
if (jl_is_topnode(e)) {
97-
jl_value_t *v = jl_get_global(jl_current_module,
98-
(jl_sym_t*)jl_fieldref(e,0));
97+
jl_sym_t *s = (jl_sym_t*)jl_fieldref(e,0);
98+
jl_value_t *v = jl_get_global(jl_base_relative_to(jl_current_module),s);
9999
if (v == NULL)
100-
jl_errorf("%s not defined", ((jl_sym_t*)jl_fieldref(e,0))->name);
100+
jl_errorf("%s not defined", s->name);
101101
return v;
102102
}
103103
if (!jl_is_expr(e)) {

src/julia-syntax.scm

+7-7
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,7 @@
836836
(cadr x)
837837
(tuple-wrap (cdr a) '())))
838838
(tuple-wrap (cdr a) (cons x run))))))
839-
`(call apply ,f ,@(tuple-wrap argl '()))))
839+
`(call (top apply) ,f ,@(tuple-wrap argl '()))))
840840

841841
; tuple syntax (a, b...)
842842
; note, directly inside tuple ... means sequence type
@@ -958,14 +958,14 @@
958958
(= ,cnt ,a)
959959
,@(if (eq? lim b) '() `((= ,lim ,b)))
960960
(break-block loop-exit
961-
(_while (call <= ,cnt ,lim)
961+
(_while (call (top <=) ,cnt ,lim)
962962
(block
963963
(= ,lhs ,cnt)
964964
(break-block loop-cont
965965
,body)
966966
(= ,cnt (call (top convert)
967967
(call (top typeof) ,cnt)
968-
(call + 1 ,cnt)))))))))))
968+
(call (top +) 1 ,cnt)))))))))))
969969

970970
; for loop over arbitrary vectors
971971
(pattern-lambda
@@ -1093,9 +1093,9 @@
10931093
(if (null? ranges)
10941094
(list)
10951095
(if (eq? (car ranges) `:)
1096-
(cons `(call size ,oneresult ,oneresult-dim)
1096+
(cons `(call (top size) ,oneresult ,oneresult-dim)
10971097
(compute-dims (cdr ranges) (+ oneresult-dim 1)))
1098-
(cons `(call length ,(caddr (car ranges)))
1098+
(cons `(call (top length) ,(caddr (car ranges)))
10991099
(compute-dims (cdr ranges) oneresult-dim)) )))
11001100

11011101
;; construct loops to cycle over all dimensions of an n-d comprehension
@@ -1108,7 +1108,7 @@
11081108
(+= ,ri 1)) )
11091109
(if (eq? (car ranges) `:)
11101110
(let ((i (gensy)))
1111-
`(for (= ,i (: 1 (call size ,oneresult ,oneresult-dim)))
1111+
`(for (= ,i (: 1 (call (top size) ,oneresult ,oneresult-dim)))
11121112
,(construct-loops (cdr ranges) (cons i iters) (+ oneresult-dim 1)) ))
11131113
`(for ,(car ranges)
11141114
,(construct-loops (cdr ranges) iters oneresult-dim) ))))
@@ -1150,7 +1150,7 @@
11501150

11511151
;; compute the dimensions of the result
11521152
(define (compute-dims ranges)
1153-
(map (lambda (r) `(call length ,(caddr r)))
1153+
(map (lambda (r) `(call (top length) ,(caddr r)))
11541154
ranges))
11551155

11561156
;; construct loops to cycle over all dimensions of an n-d comprehension

src/julia.h

+1
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,7 @@ jl_value_t *jl_interpret_toplevel_expr_with(jl_value_t *e,
858858
jl_value_t **locals, size_t nl);
859859
jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e,
860860
jl_value_t **locals, size_t nl);
861+
jl_module_t *jl_base_relative_to(jl_module_t *m);
861862
void jl_type_infer(jl_lambda_info_t *li, jl_tuple_t *argtypes,
862863
jl_lambda_info_t *def);
863864

src/task.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ static jl_value_t *build_backtrace(void)
508508

509509
unw_getcontext(&uc);
510510
unw_init_local(&cursor, &uc);
511-
while (unw_step(&cursor) && n < 10000) {
511+
while (unw_step(&cursor) && n < 80000) {
512512
unw_get_reg(&cursor, UNW_REG_IP, &ip);
513513
push_frame_info_from_ip(a, ip);
514514
n++;

src/toplevel.c

+17-6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ DLLEXPORT char *julia_home = NULL;
2323
// current line number in a file
2424
int jl_lineno = 0;
2525

26+
jl_module_t *jl_old_base_module = NULL;
27+
2628
jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast);
2729

2830
jl_value_t *jl_eval_module_expr(jl_expr_t *ex)
@@ -42,8 +44,8 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex)
4244
jl_module_t *newm = jl_new_module(name);
4345
newm->parent = parent_module;
4446
b->value = (jl_value_t*)newm;
45-
if (parent_module == jl_main_module && name == jl_symbol("Base") &&
46-
jl_base_module == NULL) {
47+
if (parent_module == jl_main_module && name == jl_symbol("Base")) {
48+
jl_old_base_module = jl_base_module;
4749
// pick up Base module during bootstrap
4850
jl_base_module = newm;
4951
}
@@ -88,21 +90,30 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex)
8890
return jl_nothing;
8991
}
9092

91-
static int is_intrinsic(jl_sym_t *s)
93+
static int is_intrinsic(jl_module_t *m, jl_sym_t *s)
9294
{
93-
jl_value_t *v = jl_get_global(jl_current_module, s);
95+
jl_value_t *v = jl_get_global(m, s);
9496
return (v != NULL && jl_typeof(v)==(jl_type_t*)jl_intrinsic_type);
9597
}
9698

99+
// module referenced by TopNode from within m
100+
// this is only needed because of the bootstrapping process:
101+
// - initially Base doesn't exist and top === Core
102+
// - later, it refers to either old Base or new Base
103+
jl_module_t *jl_base_relative_to(jl_module_t *m)
104+
{
105+
return (m==jl_core_module||m==jl_old_base_module||jl_base_module==NULL) ? m : jl_base_module;
106+
}
107+
97108
static int has_intrinsics(jl_expr_t *e)
98109
{
99110
if (e->args->length == 0)
100111
return 0;
101112
if (e->head == static_typeof_sym) return 1;
102113
jl_value_t *e0 = jl_exprarg(e,0);
103114
if (e->head == call_sym &&
104-
((jl_is_symbol(e0) && is_intrinsic((jl_sym_t*)e0)) ||
105-
(jl_is_topnode(e0) && is_intrinsic((jl_sym_t*)jl_fieldref(e0,0)))))
115+
((jl_is_symbol(e0) && is_intrinsic(jl_current_module,(jl_sym_t*)e0)) ||
116+
(jl_is_topnode(e0) && is_intrinsic(jl_base_relative_to(jl_current_module),(jl_sym_t*)jl_fieldref(e0,0)))))
106117
return 1;
107118
int i;
108119
for(i=0; i < e->args->length; i++) {

0 commit comments

Comments
 (0)