Skip to content

Commit

Permalink
Merge pull request JuliaLang#8297 from JuliaLang/teh/inline_meta
Browse files Browse the repository at this point in the history
Add inline macro via :meta expressions
  • Loading branch information
timholy committed Sep 20, 2014
2 parents 6a0eec6 + 106e4f7 commit c9c563c
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 9 deletions.
6 changes: 6 additions & 0 deletions base/cartesian.jl
Expand Up @@ -30,6 +30,9 @@ const CARTESIAN_DIMS = 4
# myfunction(A::AbstractArray, I::Int...N)
# where N can be an integer or symbol. Currently T...N generates a parser error.
macro ngenerate(itersym, returntypeexpr, funcexpr)
if isa(funcexpr, Expr) && funcexpr.head == :macrocall && funcexpr.args[1] == symbol("@inline")
funcexpr = Base._inline(funcexpr.args[2])
end
isfuncexpr(funcexpr) || error("Requires a function expression")
esc(ngenerate(itersym, returntypeexpr, funcexpr.args[1], N->sreplace!(copy(funcexpr.args[2]), itersym, N)))
end
Expand Down Expand Up @@ -57,6 +60,9 @@ macro nsplat(itersym, args...)
else
error("Wrong number of arguments")
end
if isa(funcexpr, Expr) && funcexpr.head == :macrocall && funcexpr.args[1] == symbol("@inline")
funcexpr = Base._inline(funcexpr.args[2])
end
isfuncexpr(funcexpr) || error("Second argument must be a function expression")
prototype = funcexpr.args[1]
body = funcexpr.args[2]
Expand Down
3 changes: 2 additions & 1 deletion base/exports.jl
Expand Up @@ -1384,4 +1384,5 @@ export
@inbounds,
@simd,
@label,
@goto
@goto,
@inline
41 changes: 41 additions & 0 deletions base/expr.jl
Expand Up @@ -63,6 +63,13 @@ macro eval(x)
:($(esc(:eval))($(Expr(:quote,x))))
end

macro inline(ex)
esc(_inline(ex))
end

_inline(ex::Expr) = pushmeta!(ex, :inline)
_inline(arg) = arg

## some macro utilities ##

find_vars(e) = find_vars(e, {})
Expand Down Expand Up @@ -95,3 +102,37 @@ function localize_vars(expr, esca)
end
Expr(:localize, :(()->($expr)), v...)
end

function pushmeta!(ex::Expr, sym::Symbol)
if ex.head == :function
body::Expr = ex.args[2]
if !isempty(body.args) && isa(body.args[1], Expr) && (body.args[1]::Expr).head == :meta
push!((body.args[1]::Expr).args, sym)
else
unshift!(body.args, Expr(:meta, sym))
end
elseif (ex.head == :(=) && typeof(ex.args[1]) == Expr && ex.args[1].head == :call)
ex = Expr(:function, ex.args[1], Expr(:block, Expr(:meta, sym), ex.args[2]))
# else
# ex = Expr(:withmeta, ex, sym)
end
ex
end

function popmeta!(body::Expr, sym::Symbol)
if isa(body.args[1],Expr) && (body.args[1]::Expr).head === :meta
metaargs = (body.args[1]::Expr).args
for i = 1:length(metaargs)
if metaargs[i] == sym
if length(metaargs) == 1
shift!(body.args) # get rid of :meta Expr
else
deleteat!(metaargs, i) # delete this portion of the metadata
end
return true
end
end
end
false
end
popmeta!(arg, sym) = false
7 changes: 3 additions & 4 deletions base/inference.jl
Expand Up @@ -2496,10 +2496,9 @@ const inline_incompletematch_allowed = false

inline_worthy(body, cost::Real) = true
function inline_worthy(body::Expr, cost::Real=1.0) # precondition: 0<cost
# if isa(body.args[1],QuoteNode) && (body.args[1]::QuoteNode).value === :inline
# shift!(body.args)
# return true
# end
if popmeta!(body, :inline)
return true
end
symlim = 1+5/cost
if length(body.args) < symlim
symlim *= 16
Expand Down
2 changes: 1 addition & 1 deletion src/alloc.c
Expand Up @@ -91,7 +91,7 @@ jl_sym_t *compositetype_sym; jl_sym_t *type_goto_sym;
jl_sym_t *global_sym; jl_sym_t *tuple_sym;
jl_sym_t *dot_sym; jl_sym_t *newvar_sym;
jl_sym_t *boundscheck_sym; jl_sym_t *copyast_sym;
jl_sym_t *simdloop_sym;
jl_sym_t *simdloop_sym; jl_sym_t *meta_sym;

typedef struct {
int64_t a;
Expand Down
3 changes: 3 additions & 0 deletions src/codegen.cpp
Expand Up @@ -3006,6 +3006,9 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed,
"Warning: could not attach metadata for @simd loop.\n");
return NULL;
}
else if (head == meta_sym) {
return literal_pointer_val((jl_value_t*)jl_nothing); // will change as new metadata gets added
}
else {
if (!strcmp(head->name, "$"))
jl_error("syntax: prefix $ in non-quoted expression");
Expand Down
3 changes: 3 additions & 0 deletions src/interpreter.c
Expand Up @@ -455,6 +455,9 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl)
else if (ex->head == simdloop_sym) {
return (jl_value_t*)jl_nothing;
}
else if (ex->head == meta_sym) {
return (jl_value_t*)jl_nothing;
}
jl_errorf("unsupported or misplaced expression %s", ex->head->name);
return (jl_value_t*)jl_nothing;
}
Expand Down
1 change: 1 addition & 0 deletions src/jltypes.c
Expand Up @@ -3261,6 +3261,7 @@ void jl_init_types(void)
newvar_sym = jl_symbol("newvar");
copyast_sym = jl_symbol("copyast");
simdloop_sym = jl_symbol("simdloop");
meta_sym = jl_symbol("meta");
}

#ifdef __cplusplus
Expand Down
2 changes: 1 addition & 1 deletion src/julia.h
Expand Up @@ -421,7 +421,7 @@ extern jl_sym_t *abstracttype_sym; extern jl_sym_t *bitstype_sym;
extern jl_sym_t *compositetype_sym; extern jl_sym_t *type_goto_sym;
extern jl_sym_t *global_sym; extern jl_sym_t *tuple_sym;
extern jl_sym_t *boundscheck_sym; extern jl_sym_t *copyast_sym;
extern jl_sym_t *simdloop_sym;
extern jl_sym_t *simdloop_sym; extern jl_sym_t *meta_sym;


// object accessors -----------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion test/Makefile
Expand Up @@ -8,7 +8,7 @@ TESTS = all core keywordargs numbers strings unicode collections hashing \
suitesparse complex version pollfd mpfr broadcast socket floatapprox \
priorityqueue readdlm reflection regex float16 combinatorics dates \
sysinfo rounding ranges mod2pi euler show lineedit replcompletions \
backtrace repl test examples goto llvmcall grisu
backtrace repl test examples goto llvmcall grisu meta

default: all

Expand Down
27 changes: 27 additions & 0 deletions test/meta.jl
@@ -0,0 +1,27 @@
# test meta-expressions that annotate blocks of code

module MetaTest

using Base.Test

function f(x)
y = x+5
z = y*y
q = z/y
m = q-3
end

@inline function f_inlined(x)
y = x+5
z = y*y
q = z/y
m = q-3
end

g(x) = f(2x)
g_inlined(x) = f_inlined(2x)

@test g(3) == g_inlined(3)
@test f(3) == f_inlined(3)

end
2 changes: 1 addition & 1 deletion test/runtests.jl
Expand Up @@ -9,7 +9,7 @@ testnames = [
"floatapprox", "readdlm", "reflection", "regex", "float16", "combinatorics",
"sysinfo", "rounding", "ranges", "mod2pi", "euler", "show",
"lineedit", "replcompletions", "repl", "test", "examples", "goto",
"llvmcall", "grisu", "nullable"
"llvmcall", "grisu", "nullable", "meta"
]
@unix_only push!(testnames, "unicode")

Expand Down

0 comments on commit c9c563c

Please sign in to comment.