In [1]:
using SemanticModels
using SemanticModels.ModelTools
using SemanticModels.ModelTools.SimpleModels
In [2]:
import SemanticModels.ModelTools.SimpleModels: entrypoint, entryname, body
expr = quote
    module StatsMod
    using Statistics
    function foo(x)
        return x.^2
    end
    function bar(x,y)
        ρ = foo(x.-y)./(foo(x) .+ foo(y))
        return ρ
    end
    function main(n)
        x = rand(Float64, n)
        μ = mean(x)
        ρ = bar(x,μ)
        return x, ρ
    end
    end
end
Out[2]:
quote
    #= In[2]:3 =#
    module StatsMod
    #= In[2]:3 =#
    #= In[2]:4 =#
    using Statistics
    #= In[2]:5 =#
    function foo(x)
        #= In[2]:6 =#
        return x .^ 2
    end
    #= In[2]:8 =#
    function bar(x, y)
        #= In[2]:9 =#
        ρ = foo(x .- y) ./ (foo(x) .+ foo(y))
        #= In[2]:10 =#
        return ρ
    end
    #= In[2]:12 =#
    function main(n)
        #= In[2]:13 =#
        x = rand(Float64, n)
        #= In[2]:14 =#
        μ = mean(x)
        #= In[2]:15 =#
        ρ = bar(x, μ)
        #= In[2]:16 =#
        return (x, ρ)
    end
    end
end
In [3]:
m = model(SimpleModel, deepcopy(expr), :(main(n::Int)))
Out[3]:
SimpleModel(
  imports=Any[:(using Statistics)],
  blocks=Expr[:(function foo(x)
      #= In[2]:6 =#
      return x .^ 2
  end), :(function bar(x, y)
      #= In[2]:9 =#
      ρ = foo(x .- y) ./ (foo(x) .+ foo(y))
      #= In[2]:10 =#
      return ρ
  end), :(function main(n)
      #= In[2]:13 =#
      x = rand(Float64, n)
      #= In[2]:14 =#
      μ = mean(x)
      #= In[2]:15 =#
      ρ = bar(x, μ)
      #= In[2]:16 =#
      return (x, ρ)
  end)],
  functions=Symbol[:foo, :bar, :main]
  entry=:(main(n::Int))
In [4]:
StatsMod = eval(m.expr)
StatsMod.main(10)
Out[4]:
([0.0916578, 0.0244927, 0.0132468, 0.193066, 0.567456, 0.651201, 0.0457356, 0.449039, 0.784998, 0.900616], [0.535587, 0.86894, 0.9289, 0.182461, 0.0828315, 0.138419, 0.757866, 0.0173809, 0.225836, 0.294096])
In [5]:
macro model(class, args...)
    expr = args[end]
    if expr.head == :block
        expr = expr.args[end]
    end
    
    ex = Expr(:nothing)
    expr = quote $expr end
    if length(args) > 1
        additional_args = args[1:end-1]
        ex = :(model($class, $expr, $additional_args...))
    else
        ex = :(model($class, $expr ))
    end
    return ex
end
Out[5]:
@model (macro with 1 method)
In [6]:
m = @model SimpleModel main(n::Int64) quote
    module StatsMod
    using Statistics
    function foo(x)
        return x.^2
    end
    function bar(x,y)
        ρ = foo(x.-y)./(foo(x) .+ foo(y))
        return ρ
    end
    function main(n)
        x = rand(Float64, n)
        μ = mean(x)
        ρ = bar(x,μ)
        return x, ρ
    end
    end
end
Out[6]:
SimpleModel(
  imports=Any[:(using Statistics)],
  blocks=Expr[:(function foo(x)
      #= In[6]:5 =#
      return x .^ 2
  end), :(function bar(x, y)
      #= In[6]:8 =#
      ρ = foo(x .- y) ./ (foo(x) .+ foo(y))
      #= In[6]:9 =#
      return ρ
  end), :(function main(n)
      #= In[6]:12 =#
      x = rand(Float64, n)
      #= In[6]:13 =#
      μ = mean(x)
      #= In[6]:14 =#
      ρ = bar(x, μ)
      #= In[6]:15 =#
      return (x, ρ)
  end)],
  functions=Symbol[:foo, :bar, :main]
  entry=:(main(n::Int64))
In [7]:
m.expr
Out[7]:
:(module StatsMod
  #= In[6]:2 =#
  #= In[6]:3 =#
  using Statistics
  #= In[6]:4 =#
  function foo(x)
      #= In[6]:5 =#
      return x .^ 2
  end
  #= In[6]:7 =#
  function bar(x, y)
      #= In[6]:8 =#
      ρ = foo(x .- y) ./ (foo(x) .+ foo(y))
      #= In[6]:9 =#
      return ρ
  end
  #= In[6]:11 =#
  function main(n)
      #= In[6]:12 =#
      x = rand(Float64, n)
      #= In[6]:13 =#
      μ = mean(x)
      #= In[6]:14 =#
      ρ = bar(x, μ)
      #= In[6]:15 =#
      return (x, ρ)
  end
  end)
In [8]:
m.functions
Out[8]:
3-element Array{Expr,1}:
 :(function foo(x)
      #= In[6]:5 =#
      return x .^ 2
  end)                                                                                                                                  
 :(function bar(x, y)
      #= In[6]:8 =#
      ρ = foo(x .- y) ./ (foo(x) .+ foo(y))
      #= In[6]:9 =#
      return ρ
  end)                                                                    
 :(function main(n)
      #= In[6]:12 =#
      x = rand(Float64, n)
      #= In[6]:13 =#
      μ = mean(x)
      #= In[6]:14 =#
      ρ = bar(x, μ)
      #= In[6]:15 =#
      return (x, ρ)
  end)
In [9]:
m.entry
Out[9]:
:(main(n::Int64))
In [10]:
Mod = eval(m.expr)
getfield(Mod, entryname(m))(10)
WARNING: replacing module StatsMod.
Out[10]:
([0.931255, 0.582112, 0.719251, 0.743775, 0.130082, 0.295205, 0.37241, 0.954441, 0.639295, 0.0138841], [0.133564, 0.00307213, 0.0406346, 0.0501563, 0.543262, 0.156679, 0.0641507, 0.14433, 0.0146437, 0.948437])