From 2eaf48d2662ae124e9f76f33dc74059c4c9a38e8 Mon Sep 17 00:00:00 2001 From: timholy Date: Wed, 10 Sep 2014 09:14:00 -0500 Subject: [PATCH] Add inline macro via :meta expressions --- base/cartesian.jl | 6 ++++++ base/exports.jl | 3 ++- base/expr.jl | 41 +++++++++++++++++++++++++++++++++++++++++ base/inference.jl | 7 +++---- src/alloc.c | 2 +- src/interpreter.c | 3 +++ src/jltypes.c | 1 + src/julia.h | 2 +- 8 files changed, 58 insertions(+), 7 deletions(-) diff --git a/base/cartesian.jl b/base/cartesian.jl index 9fd9abd0ef382..4c4f6d9bc9b12 100644 --- a/base/cartesian.jl +++ b/base/cartesian.jl @@ -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 @@ -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] diff --git a/base/exports.jl b/base/exports.jl index d6bfb42a36596..d46ceecaba98c 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1384,4 +1384,5 @@ export @inbounds, @simd, @label, - @goto + @goto, + @inline diff --git a/base/expr.jl b/base/expr.jl index f5c297ab9f468..66db044c240aa 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -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, {}) @@ -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 diff --git a/base/inference.jl b/base/inference.jl index b589538e8c976..834d9d0d94799 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -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: 0head == 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; } diff --git a/src/jltypes.c b/src/jltypes.c index 26d6226d811aa..70875ea48a72d 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -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 diff --git a/src/julia.h b/src/julia.h index b95c9e91d2c1a..13a04464728a5 100644 --- a/src/julia.h +++ b/src/julia.h @@ -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 -----------------------------------------------------------