Giter Club home page Giter Club logo

mjolnir.jl's People

Contributors

devmotion avatar dhairyalgandhi avatar masonprotter avatar mikeinnes avatar oxinabox avatar pabloferz avatar shashi avatar syxp avatar touchesir avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mjolnir.jl's Issues

Multiple dispatch fails in @trace

Hi there,

Thanks for this very cool library!

I'm trying to use this library in some code involving sparse matrix multiplication and ran into some issues. Since I'm using Julia 1.6, I had to use Mjolnir.jl from PR #34 with IRTools#master as suggested by @pabloferz.

The code

function mymul!(C::Matrix{Float64}, A::SparseMatrixCSC{Float64, Int64}, B::Matrix{Float64})
    nzv = nonzeros(A)
    rv = rowvals(A)
    for k in 1:size(C, 2)
        @inbounds for col in 1:size(A, 2)
            for j in nzrange(A, col)
                C[rv[j], k] += nzv[j]*B[col,k]
            end
        end
    end
    C
end

A = sparse(Matrix{Float64}(I,10,10));
B = rand(10,10);
C = zeros(10, 10);

@trace mymul!(C, A, B)

The error

ERROR: Tracing Error: MethodError: abstract(::Mjolnir.Basic, ::Mjolnir.Const{typeof(getindex)}, ::Mjolnir.Const{Vector{Int64}}, ::Mjolnir.Const{Int64}) is ambiguous. Candidates:
  abstract(::Mjolnir.Basic, var"287"::Union{Mjolnir.Const{typeof(getindex)}, Mjolnir.Node{typeof(getindex)}, Type{typeof(getindex)}, Mjolnir.Partial{typeof(getindex)}, Mjolnir.Shape{typeof(getindex)}}, xs::Mjolnir.Const{var"#s40"} where var"#s40"<:Array, i::Mjolnir.Const...) in Mjolnir at /Users/matthieubulte/.julia/packages/Mjolnir/yjFab/src/macros.jl:55
  abstract(::Mjolnir.Basic, var"301"::Union{Mjolnir.Const{typeof(getindex)}, Mjolnir.Node{typeof(getindex)}, Type{typeof(getindex)}, Mjolnir.Partial{typeof(getindex)}, Mjolnir.Shape{typeof(getindex)}}, xs::Union{Type{var"#s28"}, Mjolnir.Const{var"#s28"}, Mjolnir.Node{var"#s28"}, Mjolnir.Partial{var"#s28"}, Mjolnir.Shape{var"#s28"}} where var"#s28"<:(AbstractArray{T, N} where N), is::Union{Type{var"#s8"}, Mjolnir.Const{var"#s8"}, Mjolnir.Node{var"#s8"}, Mjolnir.Partial{var"#s8"}, Mjolnir.Shape{var"#s8"}} where var"#s8"<:Integer...) where T in Mjolnir at /Users/matthieubulte/.julia/packages/Mjolnir/yjFab/src/macros.jl:55
To resolve the ambiguity, try making one of the methods more specific, or adding a new method more specific than any of the existing applicable methods.
in Tuple{typeof(mymul!), Int64, Matrix{Float64}, SparseMatrixCSC{Float64, Int64}, Matrix{Float64}}
in Tuple{typeof(nzrange), SparseMatrixCSC{Float64, Int64}, Int64}
Stacktrace:
 [1] trace(::Any, ::Any, ::Vararg{Any, N} where N)
   @ Mjolnir ~/.julia/packages/Mjolnir/yjFab/src/trace.jl:268
 [2] top-level scope
   @ REPL[53]:1

I'm not quite sure if this is an issue from the code I'm trying to trace, or if this is a bug, so please let me know if I did something stupid.

Cheers,
Matthieu

Applications

Hello Mike,

In the spirit of your readme, I'm wondering to what extent this package can or is intended to address some common pain points aside from speeding up flux/zygote:

  1. Lightweight static compilation of a useful subset of non ML julia programs, for deployment. (including general binary deployment and also minimal runtime targets- I'm interested in lightweight drone vision and control systems))
  2. non-runtime semantic or correctness analysis. At the least, finding method errors.
  3. non-runtime shape inference/checking for numerical code
  4. ONNX read and write
  5. Dispatching array ops (even on complex nested arrays) to their correct GPU implementations
  6. As a bonus, transpilation to things like WASM

For those that apply, are they planned roadmap items, and if not, how much additional work would they required?

Thanks

Organize test suite

Right now, it's a little difficult to tell exactly what each test is testing for (at least for me, someone who is only slightly familiar with intrinsics + Base).

`@inbounds`

needs support

I tried to do nothing in this case like in :meta but that fails.

julia> g(x) = @inbounds for i=eachindex(x); x[i] += 1; end

julia> @trace g([1,2,3])
ERROR: Tracing Error: Can't trace through inbounds expression
in Tuple{typeof(g),Array{Int64,1}}
Stacktrace:
 [1] trace(::Mjolnir.Multi{Tuple{Mjolnir.Basic,Mjolnir.Numeric}}, ::Mjolnir.Const{typeof(g)}, ::Vararg{Any,N} where N) at /home/shashi/.julia/dev/Mjolnir/src/trace.jl:248
 [2] top-level scope at REPL[30]:1
 [3] run_backend(::REPL.REPLBackend) at /home/shashi/.julia/packages/Revise/MgvIv/src/Revise.jl:1023
 [4] top-level scope at none:0
caused by [exception 1]
Can't trace through inbounds expression
Stacktrace:
 [1] traceblock!(::Mjolnir.Trace, ::Dict{Any,Any}, ::IRTools.Inner.Block) 

simple for loop tries to trace through a dispatch with Union

julia> g(x) = for i=eachindex(x); x[i] += 1; end
g (generic function with 1 method)

julia> @trace g([1,2,3])
ERROR: Tracing Error: No IR for Tuple{typeof(getfield),Union{Nothing, Tuple{Int64,Int64}},Int64}
in Tuple{typeof(g),Array{Int64,1}}
in Tuple{typeof(getfield),Union{Nothing, Tuple{Int64,Int64}},Int64}
Stacktrace:
 [1] trace(::Mjolnir.Multi{Tuple{Mjolnir.Basic,Mjolnir.Numeric}}, ::Mjolnir.Const{typeof(g)}, ::Vararg{Any,N} where N) at /home/shashi/.julia/dev/Mjolnir/src/trace.jl:249
 [2] top-level scope at REPL[26]:1
 [3] run_backend(::REPL.REPLBackend) at /home/shashi/.julia/packages/Revise/MgvIv/src/Revise.jl:1023
 [4] top-level scope at none:0
caused by [exception 1]
No IR for Tuple{typeof(getfield),Union{Nothing, Tuple{Int64,Int64}},Int64}
Stacktrace:
 [1] tracecall!(::Mjolnir.Trace, ::Array{Any,1}, ::Mjolnir.Const{typeof(getfield)}, ::Vararg{Any,N} where N) at /home/shashi/.julia/dev/Mjolnir/src/trace.jl:212
 [2] traceblock!(::Mjolnir.Trace, ::Dict{Any,Any}, ::IRTools.Inner.Block) at /home/shashi/.julia/dev/Mjolnir/src/trace.jl:172

related to #4 (I think).

Maybe this can be fixed by making trace try all the options in the union separately and then trying to do a union of the types.

simple function triggers an unexpected dimension mismatch error

MWE:

using Mjolnir, IRTools

function foo()
    for i in 2:3
        2 + 3
    end
    return
end

ir = @code_ir foo()
Mjolnir.return_type(ir)

I think this should return Nothing or at least trigger the iterate error in #7 but this gives me

ERROR: DimensionMismatch("array could not be broadcast to match destination")

on current master.

inline not defined

My first spin of Mjölner, encountered a mysterious error. Please forgive me if I've been using it wrong

julia> function negsquare(x)
           if x > 0
               return x^2
           else
               return -x^2
           end
       end
negsquare (generic function with 1 method)

julia> using Mjolnir

julia> negsquare(1.0)
1.0

julia> code = @trace negsquare(1.0)
1: (%1 :: const(negsquare), %2 :: const(1.0))
  return 1.0

julia> code = @trace negsquare(::Float64)
ERROR: Tracing Error: UndefVarError: inline not defined
in Tuple{typeof(negsquare),Float64}
Stacktrace:
 [1] trace(::Any, ::Any, ::Vararg{Any,N} where N) at /home/fredrikb/.julia/packages/Mjolnir/WikP6/src/trace.jl:272
 [2] top-level scope at none:1

Infer misses some branches

Example: (_propagate calls trace under the hood).

function burglary_model(x::Float64)
    burglary = trace(:burglary, Bernoulli(0.05))
    burglary ? disabled = trace(:disabled, Bernoulli(0.1)) : disabled = false
    !disabled ? alarm = trace(:alarm, Bernoulli(burglary ? 0.94 : 0.01)) : alarm = false
    call = trace(:call, Bernoulli(alarm ? 0.70 : 0.05))
    return nothing
end

tr = Jaynes._propagate(typeof(burglary_model), (Float64, ), (NoChange(), ))
display(tr)

produces

1: (%1 :: typeof(Main.BurglaryModel.burglary_model), %2 :: Gen.NoChange())
  %3 = (Distributions.Bernoulli)(0.05) :: Gen.NoChange
  %4 = (Main.BurglaryModel.Jaynes.trace)(:burglary, %3) :: Gen.NoChange
  br 3 unless %4
  br 2
2:
  %5 = (Distributions.Bernoulli)(0.1) :: Gen.NoChange
  %6 = (Main.BurglaryModel.Jaynes.trace)(:disabled, %5) :: Gen.NoChange
  br 4 (%6)
3:
  br 4 (false)
4: (%7 :: Union{Gen.NoChange, Bool})
  %8 = (!)(%7) :: Bool
  br 7 unless %8
  br 6 unless %4
  br 5
5:
  %9 = (Distributions.Bernoulli)(0.94) :: Union{}
  %10 = (Main.BurglaryModel.Jaynes.trace)(:alarm, %9) :: Union{}
  br 8
6:
  %11 = (Distributions.Bernoulli)(0.01) :: Union{}
  %12 = (Main.BurglaryModel.Jaynes.trace)(:alarm, %11) :: Union{}
  br 8
7:
  br 8
8:
  %13 = (Distributions.Bernoulli)(0.05) :: Gen.NoChange
  %14 = (Main.BurglaryModel.Jaynes.trace)(:call, %13) :: Gen.NoChange
  return nothing

Completely missing blocks 5 and 6 from burglary ? 0.94 : 0.01.

Recursion and type inference

The following triggers an infinite loop.

function pow(x, n)
    n == one(n)  && return x
    n <= zero(n) && return zero(x)
    return x*pow(x, n-1)
end
using Mjolnir
@trace pow(Float64, Int)

Stabilize Mjolnir use inside of dynamos

This is pretty interesting:

1: (%1, %2)
  %3 = Main.MjolnirUpdate.Normal(%2, 1.0)
  %4 = (IRTools.Inner.Self())(Main.MjolnirUpdate.rand, :m, %3)
  return %4
1: (%1, %2)
  %3 = Main.MjolnirUpdate.Normal(%2, 1.0)
  %4 = (IRTools.Inner.Self())(Main.MjolnirUpdate.rand, :m, %3)
  return %4

Internal error: encountered unexpected error in runtime:
BoundsError(a=Array{Symbol, (2,)}[
  Symbol("#self#"),
  :args], i=(3,))
jl_bounds_error_ints at /buildworker/worker/package_linux64/build/src/rtutils.c:183

I'm dumping out the IR, and I'm able to exactly match the IR from tracing with Mjolnir vs an IRTools dynamo (recurse! applied to both) - but the first segfaults with a BoundsError.

Running tracked code as anon functions

Hi, great package!

Is it possible to run traced code like IRTools.func ?

Sometimes I get an evaluation, but sometimes Julia just crashes:

function pow(x, n)
    r = 1
    while n > 0
         n -= 1
         r *= x
      end
      return r
end

tr = @trace pow(::Int,::Int)

f = IRTools.func(tr)

f(2,10)    # crash

Cheers,
A

@trace broken with some loops

I've found that when I trace a function where the number of iterations of a loop is passed in as an ::Int, things break. for instance;

julia> function m(n)
         for i = 1:n
           nothing
         end
       end
m (generic function with 1 method)

julia> @trace m(::Int)
ERROR: Tracing Error: Unrecognised expression $(QuoteNode(Int64))
in Tuple{typeof(m),Int64}
in Tuple{typeof(iterate),UnitRange{Int64}}
Stacktrace:
 [1] trace(::Any, ::Any, ::Vararg{Any,N} where N) at /Users/zenna/.julia/packages/Mjolnir/7FUVN/src/trace.jl:268
 [2] top-level scope at REPL[51]:1
caused by [exception 1]
Unrecognised expression $(QuoteNode(Int64))
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] step!(::Mjolnir.Inference) at /Users/zenna/.julia/packages/Mjolnir/7FUVN/src/infer.jl:200
 [3] infer!(::Mjolnir.Inference) at /Users/zenna/.julia/packages/Mjolnir/7FUVN/src/infer.jl:225
 [4] abstract!(::Any, ::Any, ::Any) at /Users/zenna/.julia/packages/Mjolnir/7FUVN/src/trace.jl:136
 [5] trace!(::Mjolnir.Trace, ::Any, ::Any) at /Users/zenna/.julia/packages/Mjolnir/7FUVN/src/trace.jl:220
 [6] tracecall!(::Mjolnir.Trace, ::Any, ::Any, ::Vararg{Any,N} where N) at /Users/zenna/.julia/packages/Mjolnir/7FUVN/src/trace.jl:231
 [7] traceblock!(::Mjolnir.Trace, ::Any, ::Any) at /Users/zenna/.julia/packages/Mjolnir/7FUVN/src/trace.jl:189
 [8] trace!(::Mjolnir.Trace, ::Any, ::Any) at /Users/zenna/.julia/packages/Mjolnir/7FUVN/src/trace.jl:213
 [9] tracecall!(::Mjolnir.Trace, ::Any, ::Any, ::Vararg{Any,N} where N) at /Users/zenna/.julia/packages/Mjolnir/7FUVN/src/trace.jl:231
 [10] trace(::Any, ::Any, ::Vararg{Any,N} where N) at /Users/zenna/.julia/packages/Mjolnir/7FUVN/src/trace.jl:263
 [11] top-level scope at REPL[51]:1

self-test fails "Tracing Error: deepcopy of Modules not supported"

julia> versioninfo()
Julia Version 1.6.3
Commit ae8452a9e0 (2021-09-23 17:34 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Xeon(R) CPU E3-1245 v3 @ 3.40GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-11.0.1 (ORCJIT, haswell)
(scratch) pkg> add Mjolnir
    Updating registry at `~/.julia/registries/General`
    Updating git-repo `https://github.com/JuliaRegistries/General.git`
   Resolving package versions...
    Updating `~/Tutorials/Julia/scratch/Project.toml`
  [1154507a] + Mjolnir v0.2.1
    Updating `~/Tutorials/Julia/scratch/Manifest.toml`
  [7869d1d1] + IRTools v0.4.4
  [1914dd2f] + MacroTools v0.5.9
  [1154507a] + Mjolnir v0.2.1
  [2a0f44e3] + Base64
  [b77e0a4c] + InteractiveUtils
  [56ddb016] + Logging
  [d6f4376e] + Markdown
  [9a3f8284] + Random
  [9e88b42a] + Serialization
  [8dfed614] + Test
(scratch) pkg> test Mjolnir
(scratch) pkg> test Mjolnir
     Testing Mjolnir
      Status `/tmp/jl_Nclk2z/Project.toml`
  [7869d1d1] IRTools v0.4.4
  [1914dd2f] MacroTools v0.5.9
  [1154507a] Mjolnir v0.2.1
  [8dfed614] Test `@stdlib/Test`
      Status `/tmp/jl_Nclk2z/Manifest.toml`
  [7869d1d1] IRTools v0.4.4
  [1914dd2f] MacroTools v0.5.9
  [1154507a] Mjolnir v0.2.1
  [2a0f44e3] Base64 `@stdlib/Base64`
  [b77e0a4c] InteractiveUtils `@stdlib/InteractiveUtils`
  [56ddb016] Logging `@stdlib/Logging`
  [d6f4376e] Markdown `@stdlib/Markdown`
  [9a3f8284] Random `@stdlib/Random`
  [9e88b42a] Serialization `@stdlib/Serialization`
  [8dfed614] Test `@stdlib/Test`
     Testing Running tests...
Trace: Error During Test at /home/<me>/.julia/packages/Mjolnir/7FUVN/test/runtests.jl:5
  Got exception outside of a @test
  LoadError: Tracing Error: deepcopy of Modules not supported
  in Tuple{typeof(f), Int64, Int64}
  Stacktrace:

Dynamic dispatch and Union type situations

Tracing may not be possible in situations where there is no unique next method to pick to trace. But this situation should occur way less with Mjolnir as opposed to using the standard Julia type inference as can be seen in this example

For example, if you have Dict{Any,Any} – we can see all the set and getindexes, so we can infer keys of the dictionary as if they were local variables

But should document when exactly it won't work, and provide reasonable suggestions to avoid those cases.

Coverage of intrinsics and builtins

Currently the Defaults (both Basic and Numeric put together) don't cover all the built-ins. We should try and support all of these, so other rules can build on top of a solid default tracer (basically the whole language).

It seems like the @abstract definitions are currently provided at a higher level than builtins and intrinsics, so we can check off those that the higher level defs cover in a reasonable way.

Builtins

  • Core.IntrinsicFunction
  • Core.var"##invoke" #unsure what this is
  • <:
  • ===
  • Core._apply
  • Core._apply_iterate
  • Core._apply_latest
  • Core._apply_pure
  • Core._expr
  • Core._typevar
  • Core.apply_type
  • Core.arrayref
  • Core.arrayset
  • Core.arraysize
  • Core.const_arrayref
  • Core.sizeof
  • Core.svec
  • applicable
  • fieldtype
  • getfield
  • ifelse
  • invoke
  • isa
  • isdefined
  • nfields
  • setfield!
  • throw
  • tuple
  • typeassert
  • typeof

Intrinsics

  • abs_float
  • add_float
  • add_float_fast
  • add_int
  • add_ptr
  • and_int
  • arraylen
  • ashr_int
  • bitcast
  • bswap_int
  • ceil_llvm
  • cglobal
  • checked_sadd_int
  • checked_sdiv_int
  • checked_smul_int
  • checked_srem_int
  • checked_ssub_int
  • checked_uadd_int
  • checked_udiv_int
  • checked_umul_int
  • checked_urem_int
  • checked_usub_int
  • copysign_float
  • ctlz_int
  • ctpop_int
  • cttz_int
  • div_float
  • div_float_fast
  • eq_float
  • eq_float_fast
  • eq_int
  • flipsign_int
  • floor_llvm
  • fma_float
  • fpext
  • fpiseq
  • fpislt
  • fptosi
  • fptoui
  • fptrunc
  • le_float
  • le_float_fast
  • llvmcall
  • lshr_int
  • lt_float
  • lt_float_fast
  • mul_float
  • mul_float_fast
  • mul_int
  • muladd_float
  • ne_float
  • ne_float_fast
  • ne_int
  • neg_float
  • neg_float_fast
  • neg_int
  • not_int
  • or_int
  • pointerref
  • pointerset
  • rem_float
  • rem_float_fast
  • rint_llvm
  • sdiv_int
  • sext_int
  • shl_int
  • sitofp
  • sle_int
  • slt_int
  • sqrt_llvm
  • sqrt_llvm_fast
  • srem_int
  • sub_float
  • sub_float_fast
  • sub_int
  • sub_ptr
  • trunc_int
  • trunc_llvm
  • udiv_int
  • uitofp
  • ule_int
  • ult_int
  • urem_int
  • xor_int
  • zext_int

Misc

  • print
  • println

Macro Hygiene issue?

This is pretty quickly encountered when tracing with symbolic arrays.

julia> Mjolnir.abstract(Mjolnir.Basic(), Mjolnir.Const(typeof), Mjolnir.Node{AbstractArray{Float64,2}}(Mjolnir.var(0)))
ERROR: UndefVarError: T not defined
Stacktrace:
 [1] #74#f(::Union{Type{#s36}, Mjolnir.Const{#s36}, Mjolnir.Node{#s36}, Mjolnir.Partial{#s36}, Mjolnir.Shape{#s36}} where #s36<:typeof(typeof), ::Mjolnir.Node{AbstractArray{Float64,2}}) at /home/shashi/.julia/dev/Mjolnir/src/lib/base.jl:15
 [2] abstract(::Mjolnir.Basic, ::Union{Mjolnir.Const{typeof(typeof)}, Mjolnir.Node{typeof(typeof)}, Type{typeof(typeof)}, Mjolnir.Partial{typeof(typeof)}, Mjolnir.Shape{typeof(typeof)}}, ::Mjolnir.Node{AbstractArray{Float64,2}}) at /home/shashi/.julia/dev/Mjolnir/src/macros.jl:58
 [3] top-level scope at REPL[21]:1
 [4] run_backend(::REPL.REPLBackend) at /home/shashi/.julia/packages/Revise/tV8FE/src/Revise.jl:1165
 [5] top-level scope at none:0

`return_type` behavior

julia> ir = @code_ir 1+2                                                                             [3/281]
1: (%1, %2, %3)  %4 = Base.add_int(%2, %3)
  return %4

julia> Mjolnir.return_type(ir, Nothing, Int, Int)
ERROR: No IR for Tuple{Core.IntrinsicFunction,Int64,Int64}
Stacktrace:
 [1] infercall!(::Mjolnir.Inference, ::Tuple{Mjolnir.Frame,Int64,Int64,Int64}, ::IRTools.Inner.Block, ::Expr
) at /home/shashi/.julia/dev/Mjolnir/src/infer.jl:130
 [2] step!(::Mjolnir.Inference) at /home/shashi/.julia/dev/Mjolnir/src/infer.jl:168
 [3] infer!(::Mjolnir.Inference) at /home/shashi/.julia/dev/Mjolnir/src/infer.jl:197
 [4] return_type(::IRTools.Inner.IR, ::Type{T} where T, ::Vararg{Type{T} where T,N} where N) at /home/shashi
/.julia/dev/Mjolnir/src/infer.jl:226
 [5] top-level scope at REPL[13]:1
 [6] run_backend(::REPL.REPLBackend) at /home/shashi/.julia/packages/Revise/Pcs5V/src/Revise.jl:1073

I have 2 questions here:

  1. why does the test create add(a,b) = a+b and infer on that.
  2. why is the first argument to return_type Nothing?

deepcopy of Modules not supported


g(x, y) = x * 2 + y * 3

jjulia> @trace g(::Int, ::Int)
ERROR: Tracing Error: deepcopy of Modules not supported
in Tuple{typeof(g), Int64, Int64}
Stacktrace:
 [1] trace(::Any, ::Any, ::Vararg{Any, N} where N)
   @ Mjolnir ~/repos/Mjolnir.jl/src/trace.jl:268
 [2] top-level scope
   @ REPL[16]:1

caused by: deepcopy of Modules not supported
Stacktrace:
  [1] error(s::String)
    @ Base ./error.jl:33
  [2] deepcopy_internal(x::Module, stackdict::IdDict{Any, Any})
    @ Base ./deepcopy.jl:33
  [3] deepcopy_internal(x::Any, stackdict::IdDict{Any, Any})
    @ Base ./deepcopy.jl:76
  [4] _deepcopy_array_t(x::Array, T::Type, stackdict::IdDict{Any, Any})
    @ Base ./deepcopy.jl:105
  [5] deepcopy_internal(x::Vector{Core.LineInfoNode}, stackdict::IdDict{Any, Any})
    @ Base ./deepcopy.jl:92
  [6] deepcopy_internal(x::Any, stackdict::IdDict{Any, Any})
    @ Base ./deepcopy.jl:76
  [7] deepcopy(x::IRTools.Inner.IR)
    @ Base ./deepcopy.jl:26
  [8] getir(::Mjolnir.Trace, ::Any, ::Vararg{Any, N} where N)
    @ Mjolnir ~/repos/Mjolnir.jl/src/trace.jl:18
  [9] tracecall!(::Mjolnir.Trace, ::Any, ::Any, ::Vararg{Any, N} where N)
    @ Mjolnir ~/repos/Mjolnir.jl/src/trace.jl:228
 [10] trace(::Any, ::Any, ::Vararg{Any, N} where N)
    @ Mjolnir ~/repos/Mjolnir.jl/src/trace.jl:263
 [11] top-level scope
    @ REPL[16]:1

Missing Key

julia> function f(x)
         if x > 0
           k = 0
           while k < 10
             k += 1
             x = x * 4
           end
         else
           j = 0
           while j < 5
             j += 1
             x = x + 4
           end
         end
         x
       end
f (generic function with 1 method)

julia> @trace f(::Int)
ERROR: Tracing Error: KeyError: key %58 not found
Stacktrace:
 [1] trace(::Any, ::Any, ::Vararg{Any,N} where N) at /home/zenna/.julia/packages/Mjolnir/7FUVN/src/trace.jl:268
 [2] top-level scope at REPL[29]:1
caused by [exception 1]
KeyError: key %58 not found
Stacktrace:
 [1] getindex at ./dict.jl:467 [inlined]
 [2] substitute at /home/zenna/.julia/packages/IRTools/GVPoj/src/ir/ir.jl:853 [inlined]
 [3] _broadcast_getindex_evalf(::typeof(IRTools.Inner.substitute), ::IRTools.Inner.Pipe, ::IRTools.Inner.Variable) at ./broadcast.jl:648
 [4] _broadcast_getindex(::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(IRTools.Inner.substitute),Tuple{Tuple{IRTools.Inner.Pipe},Base.Broadcast.Extruded{Array{Any,1},Tuple{Bool},Tuple{Int64}}}}, ::Int64) at ./broadcast.jl:621
 [5] getindex at ./broadcast.jl:575 [inlined]
 [6] copyto_nonleaf!(::Array{typeof(<),1}, ::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(IRTools.Inner.substitute),Tuple{Tuple{IRTools.Inner.Pipe},Base.Broadcast.Extruded{Array{Any,1},Tuple{Bool},Tuple{Int64}}}}, ::Base.OneTo{Int64}, ::Int64, ::Int64) at ./broadcast.jl:1026
 [7] copy(::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(IRTools.Inner.substitute),Tuple{Tuple{IRTools.Inner.Pipe},Array{Any,1}}}) at ./broadcast.jl:880
 [8] materialize(::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(IRTools.Inner.substitute),Tuple{Tuple{IRTools.Inner.Pipe},Array{Any,1}}}) at ./broadcast.jl:837
 [9] substitute(::IRTools.Inner.Pipe, ::Expr) at /home/zenna/.julia/packages/IRTools/GVPoj/src/ir/ir.jl:856
 [10] substitute(::IRTools.Inner.Pipe, ::IRTools.Inner.Statement) at /home/zenna/.julia/packages/IRTools/GVPoj/src/ir/ir.jl:855
 [11] iterate(::IRTools.Inner.Pipe, ::Any) at /home/zenna/.julia/packages/IRTools/GVPoj/src/ir/ir.jl:892
 [12] iterate(::IRTools.Inner.Pipe, ::Any) at /home/zenna/.julia/packages/IRTools/GVPoj/src/ir/ir.jl:888
 [13] renumber(::Any) at /home/zenna/.julia/packages/IRTools/GVPoj/src/passes/passes.jl:124
 [14] |> at ./operators.jl:834 [inlined]
 [15] cleanup!(::Any) at /home/zenna/.julia/packages/Mjolnir/7FUVN/src/cleanup.jl:91
 [16] trace(::Any, ::Any, ::Vararg{Any,N} where N) at /home/zenna/.julia/packages/Mjolnir/7FUVN/src/trace.jl:266
 [17] top-level scope at REPL[29]:1

Minimum example of transpiling

I'm interested in using Mjolnir to transpile Julia to GLSL shaders. Since JSExpr implements a javascript AST I though it would be a good stepping stone to create a minimal example of transpiling to javascript first. How would I transpile the following julia code

function adder(x, y)
    x + y
end

function multiplier(x, y)
    x * y
end

function nested(x, y)
    multiplier(x, adder(x, y))
end

into the equivalent javascript?

function adder(x, y){
    return x+y;
}

function multiplier(x, y){
    return x * y;
}

function nested(x, y){
    return multiplier(x, adder(x, y));
}

Thus far I've come up with this:

using Mjolnir
using JSExpr
using IRTools.Inner: IR, BasicBlock, Statement

import JSExpr: crawl

function JSEpr.crawl(trace::IR)
    crawl.(blocks)
end
function JSEpr.crawl(block::BasicBlock)
    statements = crawl.(block.stmts)
end
function JSEpr.crawl(statement::Statement)
    crawl(statement.expr)
end

Ambiguous meaning of @trace f(Int)

Current, it seems that @trace f(Int) means the same thing as @trace f(x::Int), but that seems to be kind of ambiguous. What if I meant for f(T) to be a function that takes in a type (in this case, Int) and I wanted to trace f with Int as a Const?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.