Skip to content

Commit

Permalink
make macros generic functions
Browse files Browse the repository at this point in the history
fix #9627, fix #8846, fix #8701
helps #3377, but additional work is needed there
  • Loading branch information
JeffBezanson committed Jan 5, 2016
1 parent 01df9b1 commit 7de4648
Show file tree
Hide file tree
Showing 12 changed files with 43 additions and 56 deletions.
15 changes: 2 additions & 13 deletions base/docs/Docs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,6 @@ function write_lambda_signature(io::IO, lam::LambdaStaticData)
return io
end

function macrosummary(name::Symbol, func::Function)
if !isdefined(func,:code) || func.code == nothing
return Markdown.parse("\n")
end
io = IOBuffer()
write(io, "```julia\n")
write(io, name)
write_lambda_signature(io, func.code)
write(io, "\n```")
return Markdown.parse(takebuf_string(io))
end

function functionsummary(func::Function)
io = IOBuffer()
write(io, "```julia\n")
Expand Down Expand Up @@ -182,7 +170,8 @@ function doc(b::Binding)
No documentation found.
"""), macrosummary(b.var, v))
`$(qualified_name(b))` is a macro.
"""), functionsummary(v))
elseif isa(v,Function)
d = catdoc(Markdown.parse("""
Expand Down
8 changes: 6 additions & 2 deletions base/methodshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ function show_method_table(io::IO, mt::MethodTable, max::Int=-1, header::Bool=tr
n = length(mt)
if header
m = n==1 ? "method" : "methods"
print(io, "# $n $m for generic function \"$name\":")
ns = string(name)
what = startswith(ns, '@') ? "macro" : "generic function"
print(io, "# $n $m for ", what, " \"", ns, "\":")
end
d = mt.defs
n = rest = 0
Expand Down Expand Up @@ -156,7 +158,9 @@ function writemime(io::IO, mime::MIME"text/html", mt::MethodTable)
name = mt.name
n = length(mt)
meths = n==1 ? "method" : "methods"
print(io, "$n $meths for generic function <b>$name</b>:<ul>")
ns = string(name)
what = startswith(ns, '@') ? "macro" : "generic function"
print(io, "$n $meths for ", what, " <b>$ns</b>:<ul>")
d = mt.defs
while d !== nothing
print(io, "<li> ")
Expand Down
7 changes: 5 additions & 2 deletions base/replutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ writemime(io::IO, ::MIME"text/plain", x::Number) = show(io, x)

function writemime(io::IO, ::MIME"text/plain", f::Function)
if isgeneric(f)
n = length(f.env)
mt = f.env
n = length(mt)
m = n==1 ? "method" : "methods"
print(io, "$(f.env.name) (generic function with $n $m)")
ns = string(mt.name)
what = startswith(ns, '@') ? "macro" : "generic function"
print(io, ns, " (", what, " with $n $m)")
else
show(io, f)
end
Expand Down
2 changes: 1 addition & 1 deletion src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ jl_sym_t *goto_sym; jl_sym_t *goto_ifnot_sym;
jl_sym_t *label_sym; jl_sym_t *return_sym;
jl_sym_t *lambda_sym; jl_sym_t *assign_sym;
jl_sym_t *null_sym; jl_sym_t *body_sym;
jl_sym_t *macro_sym; jl_sym_t *method_sym;
jl_sym_t *method_sym;
jl_sym_t *enter_sym; jl_sym_t *leave_sym;
jl_sym_t *exc_sym; jl_sym_t *error_sym;
jl_sym_t *static_typeof_sym; jl_sym_t *kw_sym;
Expand Down
9 changes: 5 additions & 4 deletions src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ value_t fl_invoke_julia_macro(value_t *args, uint32_t nargs)

JL_TRY {
margs[0] = scm_to_julia(args[0], 1);
f = (jl_function_t*)jl_toplevel_eval(margs[0]);
margs[0] = jl_toplevel_eval(margs[0]);
f = (jl_function_t*)margs[0];
assert(jl_is_func(f));
result = jl_apply(f, &margs[1], nargs-1);
}
Expand All @@ -93,8 +94,8 @@ value_t fl_invoke_julia_macro(value_t *args, uint32_t nargs)
value_t scm = julia_to_scm(result);
fl_gc_handle(&scm);
value_t scmresult;
jl_module_t *defmod = f->linfo->module;
if (defmod == jl_current_module) {
jl_module_t *defmod = jl_gf_mtable(f)->module;
if (defmod == NULL || defmod == jl_current_module) {
scmresult = fl_cons(scm, FL_F);
}
else {
Expand Down Expand Up @@ -1104,7 +1105,7 @@ static jl_value_t *resolve_globals(jl_value_t *expr, jl_lambda_info_t *lam)
}
size_t i = 0;
if (e->head == method_sym || e->head == abstracttype_sym || e->head == compositetype_sym ||
e->head == bitstype_sym || e->head == macro_sym || e->head == module_sym)
e->head == bitstype_sym || e->head == module_sym)
i++;
for(; i < jl_array_len(e->args); i++) {
jl_exprargset(e, i, resolve_globals(jl_exprarg(e,i), lam));
Expand Down
5 changes: 2 additions & 3 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3732,6 +3732,8 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, b
mn = (jl_value_t*)jl_symbolnode_sym(mn);
}
assert(jl_is_symbol(mn));
if (jl_symbol_name((jl_sym_t*)mn)[0] == '@')
jl_errorf("macro definition not allowed inside a local scope");
int last_depth = ctx->gc.argDepth;
Value *name = literal_pointer_val(mn);
jl_binding_t *bnd = NULL;
Expand Down Expand Up @@ -3927,9 +3929,6 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, b
head == bitstype_sym) {
jl_errorf("type definition not allowed inside a local scope");
}
else if (head == macro_sym) {
jl_errorf("macro definition not allowed inside a local scope");
}
else {
jl_errorf("unsupported or misplaced expression \"%s\" in function %s",
jl_symbol_name(head),
Expand Down
3 changes: 2 additions & 1 deletion src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,8 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type,
}
method->linfo->specializations = spe;
jl_gc_wb(method->linfo, method->linfo->specializations);
jl_type_infer(newmeth->linfo, type, method->linfo);
if (jl_symbol_name(newmeth->linfo->name)[0] != '@') // don't bother with typeinf on macros
jl_type_infer(newmeth->linfo, type, method->linfo);
}
JL_GC_POP();
JL_UNLOCK(codegen);
Expand Down
17 changes: 0 additions & 17 deletions src/interpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -454,23 +454,6 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl, size_t ng
JL_GC_POP();
return (jl_value_t*)jl_nothing;
}
else if (ex->head == macro_sym) {
jl_sym_t *nm = (jl_sym_t*)args[0];
assert(jl_is_symbol(nm));
jl_function_t *f = (jl_function_t*)eval(args[1], locals, nl, ngensym);
JL_GC_PUSH1(&f);
assert(jl_is_function(f));
if (jl_boot_file_loaded &&
f->linfo && f->linfo->ast && jl_is_expr(f->linfo->ast)) {
jl_lambda_info_t *li = f->linfo;
li->ast = jl_compress_ast(li, li->ast);
jl_gc_wb(li, li->ast);
li->name = nm;
}
jl_set_global(jl_current_module, nm, (jl_value_t*)f);
JL_GC_POP();
return (jl_value_t*)jl_nothing;
}
else if (ex->head == line_sym) {
jl_lineno = jl_unbox_long(jl_exprarg(ex,0));
return (jl_value_t*)jl_nothing;
Expand Down
1 change: 0 additions & 1 deletion src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3569,7 +3569,6 @@ void jl_init_types(void)
label_sym = jl_symbol("label");
return_sym = jl_symbol("return");
lambda_sym = jl_symbol("lambda");
macro_sym = jl_symbol("macro");
module_sym = jl_symbol("module");
export_sym = jl_symbol("export");
import_sym = jl_symbol("import");
Expand Down
15 changes: 9 additions & 6 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -1182,12 +1182,15 @@
(cond ((and (pair? (cadr e))
(eq? (car (cadr e)) 'call)
(symbol? (cadr (cadr e))))
`(macro ,(symbol (string #\@ (cadr (cadr e))))
,(expand-binding-forms
`(-> (tuple ,@(cddr (cadr e)))
,(caddr e)))))
((symbol? (cadr e)) ;; already expanded
e)
(let ((anames (cddr (cadr e))))
(expand-binding-forms
`(function (call ,(symbol (string #\@ (cadr (cadr e))))
,@(map (lambda (v)
(if (symbol? v)
`(|::| ,v (top ANY))
v))
anames))
,@(cddr e)))))
(else
(error "invalid macro definition"))))

Expand Down
2 changes: 1 addition & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ extern jl_sym_t *goto_sym; extern jl_sym_t *goto_ifnot_sym;
extern jl_sym_t *label_sym; extern jl_sym_t *return_sym;
extern jl_sym_t *lambda_sym; extern jl_sym_t *assign_sym;
extern jl_sym_t *null_sym; extern jl_sym_t *body_sym;
extern jl_sym_t *macro_sym; extern jl_sym_t *method_sym;
extern jl_sym_t *method_sym;
extern jl_sym_t *enter_sym; extern jl_sym_t *leave_sym;
extern jl_sym_t *exc_sym; extern jl_sym_t *new_sym;
extern jl_sym_t *static_typeof_sym; extern jl_sym_t *kw_sym;
Expand Down
15 changes: 10 additions & 5 deletions test/docs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ function docstrings_equal(d1, d2)
takebuf_string(io1) == takebuf_string(io2)
end

function docstring_startswith(d1, d2)
io1 = IOBuffer()
io2 = IOBuffer()
writemime(io1, MIME"text/markdown"(), d1)
writemime(io2, MIME"text/markdown"(), d2)
startswith(takebuf_string(io1), takebuf_string(io2))
end

@test meta(DocsTest)[DocsTest] == doc"DocsTest"

# Check that plain docstrings store a module reference.
Expand Down Expand Up @@ -342,13 +350,10 @@ end
@doc "This should document @m1... since its the result of expansion" @m2_11993
@test (@doc @m1_11993) !== nothing
let d = (@doc @m2_11993)
@test docstrings_equal(d, doc"""
@test docstring_startswith(d, doc"""
No documentation found.
```julia
@m2_11993()
```
""")
`@m2_11993` is a macro.""")
end

@doc "Now @m2... should be documented" :@m2_11993
Expand Down

0 comments on commit 7de4648

Please sign in to comment.