This is a proof of concept of the idea of parsing the Compile expression, extracting Symbols, finding dependent definitions, and inserting them back into Compile.
First a HoldFirst variation of heldCases:
makeHeld[(L_ -> R_) | (L_ :> R_)] := L :> HoldComplete[R];
makeHeld[pat_] := x : pat :> HoldComplete[x];
Attributes[heldCases] = {HoldFirst};
heldCases[expr_, rule_, args___] :=
Join @@ Cases[Unevaluated @ expr, makeHeld @ rule, args]
Then the main definition:
Attributes[inject] = {HoldFirst};
inject[all : Compile[var_, body_, opts___]] :=
Complement[
heldCases[body, s_Symbol /; Context[s] =!= "System`", {-1}, Heads -> True],
heldCases[var, s_Symbol | {s_Symbol, __} :> s, {2}]
] //
Apply[FullDefinition] //
InputForm // ToString // ToHeldExpression //
Cases[(Set | SetDelayed)[s_Symbol, RHS_] :> (HoldPattern[s] :> RHS)] //
( Unevaluated[all] //. # & )
Usage :
Compile[{{x, _Real, 1}}, f /@ x,
CompilationOptions -> {"InlineExternalDefinitions" -> True}] // inject
Replacing Unevaluated with Hold in the last line of inject shows the intermediate output:
Hold[Compile[{{x, _Real, 1}}, ((#1 - 1 &)[#1]^2 &) /@ x,
CompilationOptions -> {"InlineExternalDefinitions" -> True}]]
Notes
This is rather verbose for what is conceptually a fairly simple operation.
I am not happy with the ToString conversion and back. Possibly I should have extracted Symbols only and used OwnValues as you did, but since I resorted to pulling the definitions with FullDefinition using that information directly seemed a natural approach.
The replacements should really only be done on the body rather than the entire Compile, but the latter was expedient for a proof of concept.
"InlineExternalDefinitions" -> Trueseems opaque, that is I cannot find any information about how it is implemented usingTrace. Would it be useful to you simply to programmatically extractfandgfrom yourCompileexpression for use in your own method? – Mr.Wizard Jul 21 '16 at 10:28finsideCompileand the derived symbols likeg, the problem is solved. But I don't know how to do that. – vapor Jul 21 '16 at 11:35System`Symbols or do you prefer to restrict it toGlobal`Symbols? – Mr.Wizard Jul 21 '16 at 11:37Compileand local variable inModuleinside compile which hasGlobalcontext) – vapor Jul 21 '16 at 11:42