# How to embed Julia in interactive mode

**URL:** https://discourse.julialang.org/t/how-to-embed-julia-in-interactive-mode/112264
**Category:** General Usage
**Tags:** question, embedding
**Created:** [March 29, 2024, 2:22am UTC](https://discourse.julialang.org/t/how-to-embed-julia-in-interactive-mode/112264 "2024-03-29T02:22:51Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![droodman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/droodman/32/26652_2.png) [@droodman](https://discourse.julialang.org/u/droodman)
#### Post date: [March 29, 2024, 2:22am UTC](https://discourse.julialang.org/t/how-to-embed-julia-in-interactive-mode/112264/1 "2024-03-29T02:22:51Z")

</div>

Another in my continuing series of questions about how to embed Julia… @mkitti and @GunnarFarneback have been very helpful in the past.

I am embedding Julia in another program and am trying to approximately simulate the REPL. To this end I would like to launch Julia in interactive mode. My understanding is that this would affect, for example, the behavior of [soft scoping](https://docs.julialang.org/en/v1/manual/variables-and-scoping/#local-scope).

However, when I launch it after passing the `-i` option, `isinteractive()` still returns `false`. Here’s my code, in Windows:

```julia
#include <julia.h>
int main(int argc, char* argv[])
{
    int ac = 2;
    char**av = (char**)malloc(sizeof(char*) * 2);
    av[0] = 0;
    av[1] = (char*)"-i";
    jl_parse_opts(&ac, &av);

    jl_init();

    jl_eval_string("print(isinteractive())");

    jl_atexit_hook(0);
    return 0; 
}

```

Result:

```julia
false

```

Suggests welcome.

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [March 29, 2024, 4:24am UTC](https://discourse.julialang.org/t/how-to-embed-julia-in-interactive-mode/112264/2 "2024-03-29T04:24:30Z")

</div>

I get the sense that wanting to embed Julia and run the REPL is not a fully anticipated scenario. There is no a straightforward API to do just that. However we can trace the initialization of Julia through the normal path.

You can about the initialization of the Julia CLI here:  
[https://docs.julialang.org/en/v1/devdocs/init/](https://docs.julialang.org/en/v1/devdocs/init/)

Basically it goes through the following files:

- See `main` calling `jl_load_repl` in [julia/cli/loader\_exe.c at master · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/blob/master/cli/loader_exe.c)
- See `jl_load_repl` calling `jl_repl_entrypoint` in [julia/cli/loader\_lib.c at master · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/blob/master/cli/loader_lib.c)
- See `jl_repl_entrypoint` call `true_main` [julia/src/jlapi.c at v1.10.2 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/blob/v1.10.2/src/jlapi.c#L570)
- See `true_main` call `Base._start(1)` [julia/src/jlapi.c at bd47eca2c8aacd145b6c5c02e47e2b9ec27ab456 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/blob/bd47eca2c8aacd145b6c5c02e47e2b9ec27ab456/src/jlapi.c#L582)

The simplest approach is just to `Base._start()`.

```julia
#include <julia.h>
int main(int argc, char* argv[])
{
    int ac = 2;
    char**av = (char**)malloc(sizeof(char*) * 2);
    av[0] = 0;
    av[1] = (char*)"-i";
    jl_parse_opts(&ac, &av);

    jl_init();

    jl_eval_string("Base._start()");

    jl_atexit_hook(0);
    return 0;
}

```

I compile the above with `julia usr/share/julia/julia-config.jl --allflags | xargs gcc interactive_embed.c -o interactive_embed`

The more complicated answer is that you may want to emulate `true_main`:

> <https://github.com/JuliaLang/julia/blob/bd47eca2c8aacd145b6c5c02e47e2b9ec27ab456/src/jlapi.c#L570-L589>

The other thing is that the leading underscore suggests we should not call `Base._start()` directly. Perhaps we should call `Base.exec_options(Base.JLOptions())` directly instead?

> <https://github.com/JuliaLang/julia/blob/bd47eca2c8aacd145b6c5c02e47e2b9ec27ab456/base/client.jl#L228-L234>

As you can see on Line 234 that’s where the `Base.is_interactive` global is set which is what `Base.isinteractive()` returns.

---

<div class="post-metadata">

### Author: ![droodman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/droodman/32/26652_2.png) [@droodman](https://discourse.julialang.org/u/droodman)
#### Post date: [March 29, 2024, 1:04pm UTC](https://discourse.julialang.org/t/how-to-embed-julia-in-interactive-mode/112264/3 "2024-03-29T13:04:49Z")

</div>

> [@mkitti](#):
>
> Base.exec\_options(Base.JLOptions())

Thank you for that helpful effort. Passing `Base.exec_options(Base.JLOptions())` after jl\_init() worked well enough for me to learn that this will not do what I want, alas.

I think the MWE for my new problem is:

1. Create “test.jl” with the contents “S=0;for i in 1:4 S+=i; end”
2. Do “julia -i test.jl” in a shell.  
In Windows I get

```julia
┌ Warning: Assignment to `S` in soft scope is ambiguous because a global variable by the same name exists: `S` will be treated as a new local. Disambiguate by using `local S` to suppress this warning or `global S` to assign to the existing global variable.
└ @ D:\OneDrive\Documents\Macros\julia.ado\test.jl:1
ERROR: LoadError: UndefVarError: `S` not defined
Stacktrace:
 [1] top-level scope
   @ D:\OneDrive\Documents\Macros\julia.ado\test.jl:1
in expression starting at D:\OneDrive\Documents\Macros\julia.ado\test.jl:1
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 1.10.2 (2024-03-01)
 _/ |\ __'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |

```

So it runs test.jl non-interactively, gives me an error, and then fires up a REPL. Obviously not what I’m after. And I don’t see a good way to fix this.

I think with effort, in order to create a REPL experience with embedded Julia, I could figure out how to hook more directly into the Julia REPL code. But maybe not now…

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [March 29, 2024, 1:30pm UTC](https://discourse.julialang.org/t/how-to-embed-julia-in-interactive-mode/112264/4 "2024-03-29T13:30:56Z")

</div>

Ah, now I understand your question. You are not interested in the REPL, just the softscope. The softscope is an abstract syntax tree transform (AST) that is in the REPL backend.

```julia-repl
julia> Base.active_repl_backend.ast_transforms[1] softscope (generic function with 1 method)

julia> const softscope = Base.active_repl_backend.ast_transforms[1]
softscope (generic function with 1 method)

julia> @which softscope(:())
softscope(ex)
     @ REPL ~/julia-1.10.0/share/julia/stdlib/v1.10/REPL/src/REPL.jl:105

julia> using REPL

julia> REPL.softscope
softscope (generic function with 1 method)

julia> REPL.softscope == softscope
true

```

So we can `pop` it off the AST transform stack.

```julia-repl
julia> Base.active_repl_backend.ast_transforms |> pop!
softscope (generic function with 1 method)

julia> begin
           b = 0
           for i in 1:10
               b += i
           end
       end
┌ Warning: Assignment to `b` in soft scope is ambiguous because a global variable by the same name exists: `b` will be treated as a new local. Disambiguate by using `local b` to suppress this warning or `global b` to assign to the existing global variable.
└ @ REPL[50]:4
ERROR: UndefVarError: `b` not defined
Stacktrace:
 [1] top-level scope
   @ ./REPL[50]:4

```

If we push it back, then we get softscope again.

```julia-repl
julia> push!(Base.active_repl_backend.ast_transforms, softscope)
1-element Vector{Any}:
 softscope (generic function with 1 method)

julia> begin                                     
           a = 0
           for i in 1:10
               a += i
           end
       end

julia> a
55

```

You can apply the function manually.

```julia-repl
julia> ex = :(begin
           a = 0
           for i in 1:10
               a += i
           end
       end);

julia> REPL.softscope(ex)
quote
    $(Expr(:softscope, true))
    begin
        #= REPL[60]:2 =#
        a = 0
        #= REPL[60]:3 =#
        for i = 1:10
            #= REPL[60]:4 =#
            a += i
            #= REPL[60]:5 =#
        end
    end
end

julia> eval(softscope(ex))

julia> a
55

julia> eval(ex)
┌ Warning: Assignment to `a` in soft scope is ambiguous because a global variable by the same name exists: `a` will be treated as a new local. Disambiguate by using `local a` to suppress this warning or `global a` to assign to the existing global variable.
└ @ REPL[60]:4
ERROR: UndefVarError: `a` not defined
Stacktrace:
 [1] top-level scope
   @ ./REPL[60]:4
 [2] eval
   @ Core ./boot.jl:385 [inlined]
 [3] eval(x::Expr)
   @ Base.MainInclude ./client.jl:491
 [4] top-level scope
   @ REPL[62]:1

```

The source for `softscope` is below.

> <https://github.com/JuliaLang/julia/blob/09b356f0eaf2e0570167b86fb674777cf435cb7e/stdlib/REPL/src/REPL.jl#L186>

---

<div class="post-metadata">

### Author: ![droodman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/droodman/32/26652_2.png) [@droodman](https://discourse.julialang.org/u/droodman)
#### Post date: [March 29, 2024, 1:50pm UTC](https://discourse.julialang.org/t/how-to-embed-julia-in-interactive-mode/112264/5 "2024-03-29T13:50:42Z")

</div>

Amazing! It seems that when embedding, `Base.active_repl_backend` is not defined.

BUT I can use softscope() to do what I need. Behind the scenes I now wrap strings passed to `jl_eval_string()` with `eval(Meta.parse(REPL.softscope(...)))`.Here’s an actual session in Stata using the revised Julia plugin.

```julia
. jl
------------------------------------------------ Julia (type exit() to exit) ----------------------------------------------------------------------------------------------------------------
jl> . S = 0
0
jl> . for i in 1:4
  ... S += i
  ... end
jl> . S
10

```
