Skip to content

Commit 87b3609

Browse files
committed
make macros generic functions
fix #9627, fix #8846, fix #8701 helps #3377, but additional work is needed there
1 parent b8a6c5e commit 87b3609

12 files changed

+43
-56
lines changed

base/docs/Docs.jl

+2-13
Original file line numberDiff line numberDiff line change
@@ -123,18 +123,6 @@ function write_lambda_signature(io::IO, lam::LambdaStaticData)
123123
return io
124124
end
125125

126-
function macrosummary(name::Symbol, func::Function)
127-
if !isdefined(func,:code) || func.code == nothing
128-
return Markdown.parse("\n")
129-
end
130-
io = IOBuffer()
131-
write(io, "```julia\n")
132-
write(io, name)
133-
write_lambda_signature(io, func.code)
134-
write(io, "\n```")
135-
return Markdown.parse(takebuf_string(io))
136-
end
137-
138126
function functionsummary(func::Function)
139127
io = IOBuffer()
140128
write(io, "```julia\n")
@@ -182,7 +170,8 @@ function doc(b::Binding)
182170
183171
No documentation found.
184172
185-
"""), macrosummary(b.var, v))
173+
`$(qualified_name(b))` is a macro.
174+
"""), functionsummary(v))
186175
elseif isa(v,Function)
187176
d = catdoc(Markdown.parse("""
188177

base/methodshow.jl

+6-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ function show_method_table(io::IO, mt::MethodTable, max::Int=-1, header::Bool=tr
6262
n = length(mt)
6363
if header
6464
m = n==1 ? "method" : "methods"
65-
print(io, "# $n $m for generic function \"$name\":")
65+
ns = string(name)
66+
what = startswith(ns, '@') ? "macro" : "generic function"
67+
print(io, "# $n $m for ", what, " \"", ns, "\":")
6668
end
6769
d = mt.defs
6870
n = rest = 0
@@ -156,7 +158,9 @@ function writemime(io::IO, mime::MIME"text/html", mt::MethodTable)
156158
name = mt.name
157159
n = length(mt)
158160
meths = n==1 ? "method" : "methods"
159-
print(io, "$n $meths for generic function <b>$name</b>:<ul>")
161+
ns = string(name)
162+
what = startswith(ns, '@') ? "macro" : "generic function"
163+
print(io, "$n $meths for ", what, " <b>$ns</b>:<ul>")
160164
d = mt.defs
161165
while d !== nothing
162166
print(io, "<li> ")

base/replutil.jl

+5-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ writemime(io::IO, ::MIME"text/plain", x::Number) = show(io, x)
66

77
function writemime(io::IO, ::MIME"text/plain", f::Function)
88
if isgeneric(f)
9-
n = length(f.env)
9+
mt = f.env
10+
n = length(mt)
1011
m = n==1 ? "method" : "methods"
11-
print(io, "$(f.env.name) (generic function with $n $m)")
12+
ns = string(mt.name)
13+
what = startswith(ns, '@') ? "macro" : "generic function"
14+
print(io, ns, " (", what, " with $n $m)")
1215
else
1316
show(io, f)
1417
end

src/alloc.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ jl_sym_t *goto_sym; jl_sym_t *goto_ifnot_sym;
8989
jl_sym_t *label_sym; jl_sym_t *return_sym;
9090
jl_sym_t *lambda_sym; jl_sym_t *assign_sym;
9191
jl_sym_t *null_sym; jl_sym_t *body_sym;
92-
jl_sym_t *macro_sym; jl_sym_t *method_sym;
92+
jl_sym_t *method_sym;
9393
jl_sym_t *enter_sym; jl_sym_t *leave_sym;
9494
jl_sym_t *exc_sym; jl_sym_t *error_sym;
9595
jl_sym_t *static_typeof_sym; jl_sym_t *kw_sym;

src/ast.c

+5-4
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ value_t fl_invoke_julia_macro(value_t *args, uint32_t nargs)
7373

7474
JL_TRY {
7575
margs[0] = scm_to_julia(args[0], 1);
76-
f = (jl_function_t*)jl_toplevel_eval(margs[0]);
76+
margs[0] = jl_toplevel_eval(margs[0]);
77+
f = (jl_function_t*)margs[0];
7778
assert(jl_is_func(f));
7879
result = jl_apply(f, &margs[1], nargs-1);
7980
}
@@ -93,8 +94,8 @@ value_t fl_invoke_julia_macro(value_t *args, uint32_t nargs)
9394
value_t scm = julia_to_scm(result);
9495
fl_gc_handle(&scm);
9596
value_t scmresult;
96-
jl_module_t *defmod = f->linfo->module;
97-
if (defmod == jl_current_module) {
97+
jl_module_t *defmod = jl_gf_mtable(f)->module;
98+
if (defmod == NULL || defmod == jl_current_module) {
9899
scmresult = fl_cons(scm, FL_F);
99100
}
100101
else {
@@ -1104,7 +1105,7 @@ static jl_value_t *resolve_globals(jl_value_t *expr, jl_lambda_info_t *lam)
11041105
}
11051106
size_t i = 0;
11061107
if (e->head == method_sym || e->head == abstracttype_sym || e->head == compositetype_sym ||
1107-
e->head == bitstype_sym || e->head == macro_sym || e->head == module_sym)
1108+
e->head == bitstype_sym || e->head == module_sym)
11081109
i++;
11091110
for(; i < jl_array_len(e->args); i++) {
11101111
jl_exprargset(e, i, resolve_globals(jl_exprarg(e,i), lam));

src/codegen.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -3732,6 +3732,8 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, b
37323732
mn = (jl_value_t*)jl_symbolnode_sym(mn);
37333733
}
37343734
assert(jl_is_symbol(mn));
3735+
if (jl_symbol_name((jl_sym_t*)mn)[0] == '@')
3736+
jl_errorf("macro definition not allowed inside a local scope");
37353737
int last_depth = ctx->gc.argDepth;
37363738
Value *name = literal_pointer_val(mn);
37373739
jl_binding_t *bnd = NULL;
@@ -3927,9 +3929,6 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, b
39273929
head == bitstype_sym) {
39283930
jl_errorf("type definition not allowed inside a local scope");
39293931
}
3930-
else if (head == macro_sym) {
3931-
jl_errorf("macro definition not allowed inside a local scope");
3932-
}
39333932
else {
39343933
jl_errorf("unsupported or misplaced expression \"%s\" in function %s",
39353934
jl_symbol_name(head),

src/gf.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,8 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type,
863863
}
864864
method->linfo->specializations = spe;
865865
jl_gc_wb(method->linfo, method->linfo->specializations);
866-
jl_type_infer(newmeth->linfo, type, method->linfo);
866+
if (jl_symbol_name(newmeth->linfo->name)[0] != '@') // don't bother with typeinf on macros
867+
jl_type_infer(newmeth->linfo, type, method->linfo);
867868
}
868869
JL_GC_POP();
869870
JL_UNLOCK(codegen);

src/interpreter.c

-17
Original file line numberDiff line numberDiff line change
@@ -454,23 +454,6 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl, size_t ng
454454
JL_GC_POP();
455455
return (jl_value_t*)jl_nothing;
456456
}
457-
else if (ex->head == macro_sym) {
458-
jl_sym_t *nm = (jl_sym_t*)args[0];
459-
assert(jl_is_symbol(nm));
460-
jl_function_t *f = (jl_function_t*)eval(args[1], locals, nl, ngensym);
461-
JL_GC_PUSH1(&f);
462-
assert(jl_is_function(f));
463-
if (jl_boot_file_loaded &&
464-
f->linfo && f->linfo->ast && jl_is_expr(f->linfo->ast)) {
465-
jl_lambda_info_t *li = f->linfo;
466-
li->ast = jl_compress_ast(li, li->ast);
467-
jl_gc_wb(li, li->ast);
468-
li->name = nm;
469-
}
470-
jl_set_global(jl_current_module, nm, (jl_value_t*)f);
471-
JL_GC_POP();
472-
return (jl_value_t*)jl_nothing;
473-
}
474457
else if (ex->head == line_sym) {
475458
jl_lineno = jl_unbox_long(jl_exprarg(ex,0));
476459
return (jl_value_t*)jl_nothing;

src/jltypes.c

-1
Original file line numberDiff line numberDiff line change
@@ -3569,7 +3569,6 @@ void jl_init_types(void)
35693569
label_sym = jl_symbol("label");
35703570
return_sym = jl_symbol("return");
35713571
lambda_sym = jl_symbol("lambda");
3572-
macro_sym = jl_symbol("macro");
35733572
module_sym = jl_symbol("module");
35743573
export_sym = jl_symbol("export");
35753574
import_sym = jl_symbol("import");

src/julia-syntax.scm

+9-6
Original file line numberDiff line numberDiff line change
@@ -1005,12 +1005,15 @@
10051005
(cond ((and (pair? (cadr e))
10061006
(eq? (car (cadr e)) 'call)
10071007
(symbol? (cadr (cadr e))))
1008-
`(macro ,(symbol (string #\@ (cadr (cadr e))))
1009-
,(expand-binding-forms
1010-
`(-> (tuple ,@(cddr (cadr e)))
1011-
,(caddr e)))))
1012-
((symbol? (cadr e)) ;; already expanded
1013-
e)
1008+
(let ((anames (cddr (cadr e))))
1009+
(expand-binding-forms
1010+
`(function (call ,(symbol (string #\@ (cadr (cadr e))))
1011+
,@(map (lambda (v)
1012+
(if (symbol? v)
1013+
`(|::| ,v (top ANY))
1014+
v))
1015+
anames))
1016+
,@(cddr e)))))
10141017
(else
10151018
(error "invalid macro definition"))))
10161019

src/julia.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ extern jl_sym_t *goto_sym; extern jl_sym_t *goto_ifnot_sym;
556556
extern jl_sym_t *label_sym; extern jl_sym_t *return_sym;
557557
extern jl_sym_t *lambda_sym; extern jl_sym_t *assign_sym;
558558
extern jl_sym_t *null_sym; extern jl_sym_t *body_sym;
559-
extern jl_sym_t *macro_sym; extern jl_sym_t *method_sym;
559+
extern jl_sym_t *method_sym;
560560
extern jl_sym_t *enter_sym; extern jl_sym_t *leave_sym;
561561
extern jl_sym_t *exc_sym; extern jl_sym_t *new_sym;
562562
extern jl_sym_t *static_typeof_sym; extern jl_sym_t *kw_sym;

test/docs.jl

+10-5
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,14 @@ function docstrings_equal(d1, d2)
138138
takebuf_string(io1) == takebuf_string(io2)
139139
end
140140

141+
function docstring_startswith(d1, d2)
142+
io1 = IOBuffer()
143+
io2 = IOBuffer()
144+
writemime(io1, MIME"text/markdown"(), d1)
145+
writemime(io2, MIME"text/markdown"(), d2)
146+
startswith(takebuf_string(io1), takebuf_string(io2))
147+
end
148+
141149
@test meta(DocsTest)[DocsTest] == doc"DocsTest"
142150

143151
# Check that plain docstrings store a module reference.
@@ -342,13 +350,10 @@ end
342350
@doc "This should document @m1... since its the result of expansion" @m2_11993
343351
@test (@doc @m1_11993) !== nothing
344352
let d = (@doc @m2_11993)
345-
@test docstrings_equal(d, doc"""
353+
@test docstring_startswith(d, doc"""
346354
No documentation found.
347355
348-
```julia
349-
@m2_11993()
350-
```
351-
""")
356+
`@m2_11993` is a macro.""")
352357
end
353358

354359
@doc "Now @m2... should be documented" :@m2_11993

0 commit comments

Comments
 (0)