Skip to content

Commit

Permalink
improved init_phase and use ordered table in code eval so the order o…
Browse files Browse the repository at this point in the history
…f the files included matters
  • Loading branch information
Clonkk committed Mar 26, 2024
1 parent 6ab5e95 commit da5f633
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 150 deletions.
29 changes: 23 additions & 6 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
Changelog for Nimjl. Date in format YYYY_MM_DD

Release v0.8.1 - 2024_03_23
===========================
* Repo moved to SciNim
* Added activate option in init to start-up Julia in a virtual environment
* Added Hook function at init to execute code : BEFORE jl_init() is called; AFTER jl_init() and Pkg.activate() is called but BEFORE Pkg.add calls and BEFORE the embedded code is passed through ``eval`` function.
* Order of update is now relevant

Release v0.8.0 - 2023_09_30
===========================
* Clean-up some code
* Added more type in evaluation of Dict and Tuples
* Improve loading a Package at init when the Package is already present (speed up init phase)

Release v0.7.6 - 2023_02_22
===========================
* Small CI change

Release v0.7.5 - 2022_07_07
===========================
* Fixed https://github.com/Clonkk/nimjl/issues/18
Expand Down Expand Up @@ -34,15 +51,15 @@ Release v0.7.1 - 2022_01_04
Release v0.7.0 - 2022_01_04
===========================
* Add Julia.useModule alias for jlUseModule
* Add Julia.includeFile (include is reserved keyword) alias for jlInclude
* Add Julia.includeFile (include is reserved keyword) alias for jlInclude
* Add mechanism to embed julia files at compile-time and run the code at init for an easy way to distribute binary with Julia code contained
* Add Pkg template to easily install new Julia package during init ; it is also compatible with the embedding stuff :
* See ex09
```nim
Julia.init:
Pkg:
Julia.init:
Pkg:
add("LinearAlgebra")
Embed:
Embed:
file("myfile.jl")
```

Expand All @@ -60,7 +77,7 @@ Release v0.6.1 - 2021_10_14

Release v0.6.0 - 2021_10_08
===========================
* Add --gc:orc to CI
* Add --gc:orc to CI

Release v0.5.9 - 2021_10_05
===========================
Expand Down Expand Up @@ -157,4 +174,4 @@ Release v0.4.0 - 2021_03_08
* Add ``toJlVal`` / ``to`` proc to make conversion betwen Julia types and Nim types "smooth"
* Added Julia exception handler from Nim
* Examples in the examples folder
* Tess suite and memory leak suite
* Test suite and memory leak suite
23 changes: 13 additions & 10 deletions examples/ex01_helloworld.nim
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import nimjl

Julia.init() # Initialize Julia VM. This should be done once in the lifetime of your program.
proc main() =
Julia.init() # Initialize Julia VM. This should be done once in the lifetime of your program.

# Calling Julia function from Nim will always return a JlValue
# This JlValue can be "nothing"
# Therefore, Julia function who do not return a value can be discarded
var res = Julia.println("Hello world")
echo res # nothing
# Check that res is actually nothing
if res == JlNothing:
echo "Julia.println returned nothing"
# Calling Julia function from Nim will always return a JlValue
# This JlValue can be "nothing"
# Therefore, Julia function who do not return a value can be discarded
var res = Julia.println("Hello world")
echo res # nothing
# Check that res is actually nothing
if res == JlNothing:
echo "Julia.println returned nothing"

discard Julia.println("This also works")
discard Julia.println("This also works")

when isMainModule:
main()
19 changes: 11 additions & 8 deletions examples/ex02_sqrt.nim
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import nimjl
import std/math

jlVmInit() # Initialize Julia VM. This should be done once in the lifetime of your program.
proc main() =
jlVmInit() # Initialize Julia VM. This should be done once in the lifetime of your program.

var myval = 4.0'f64
# Call Julia function "sqrt" and convert the result to a float
# This syntax also works to call a function directly from a Julia modfule
var res = JlBase.sqrt(myval).to(float64)
# Echo on JlValue calls println from Julia
echo res # 2.0
doAssert res == sqrt(myval)
var myval = 4.0'f64
# Call Julia function "sqrt" and convert the result to a float
# This syntax also works to call a function directly from a Julia modfule
var res = JlBase.sqrt(myval).to(float64)
# Echo on JlValue calls println from Julia
echo res # 2.0
doAssert res == sqrt(myval)

when isMainModule:
main()
25 changes: 14 additions & 11 deletions examples/ex03_sugar.nim
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import nimjl
import std/sequtils

Julia.init()
# Use Module handle
discard JlMain.println(@[1, 2, 3])
discard Julia.println(toSeq(0..5))
proc main =
Julia.init()
# Use Module handle
discard JlMain.println(@[1, 2, 3])
discard Julia.println(toSeq(0..5))

let arr = [1.0, 2.0, 3.0].toJlArray()
# You can now use echo to call println for you on Julia type !
echo jltypeof(arr)
echo arr
let arr = [1.0, 2.0, 3.0].toJlArray()
# You can now use echo to call println for you on Julia type !
echo jltypeof(arr)
echo arr

# You can also call proc from the value directly
echo arr.stride(1)
echo arr.strides()
# You can also call proc from the value directly
echo arr.stride(1)
echo arr.strides()

when isMainModule:
main()
54 changes: 28 additions & 26 deletions examples/ex04_dict.nim
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,31 @@ proc popMe[U, V](tab: var JlValue, key: U): V =
# Therefore "pop!" function will not modify tab
result = jlCall("pop!", tab, key).to(V)


jlVmInit() # Initialize Julia VM. This should be done once in the lifetime of your program.

var mytab: Table[int64, float64] = {1'i64: 0.90'f64, 2'i64: 0.80'f64, 3'i64: 0.70'f64}.toTable
block:
let key = 1
var poppedValue = popMe(mytab, key)
# mytab has not been changed due to copy when passing value to Julia
doAssert key in mytab
doAssert poppedValue == mytab[key]

block:
var myJlTab = toJlVal(mytab) # Convert myJlTab to JlValue
let key = 1
var poppedValue = popMe[int64, float64](myJlTab, key)
doAssert not myJlTab.to(Table[int64, float64]).contains(key) # Value was removed from myJlTab
doAssert poppedValue == mytab[key]

block:
# You can use [] on Julia dict as well
var jldict = toJlVal({"alpha": 1.1, "beta": 2.2}.toTable)
doAssert jldict["alpha"].to(float) == 1.1
doAssert jldict["beta"].to(float) == 2.2
jldict["alpha"] = 3.3
doAssert jldict["alpha"].to(float) == 3.3

proc main() =
jlVmInit() # Initialize Julia VM. This should be done once in the lifetime of your program.

var mytab: Table[int64, float64] = {1'i64: 0.90'f64, 2'i64: 0.80'f64, 3'i64: 0.70'f64}.toTable
block:
let key = 1
var poppedValue = popMe(mytab, key)
# mytab has not been changed due to copy when passing value to Julia
doAssert key in mytab
doAssert poppedValue == mytab[key]

block:
var myJlTab = toJlVal(mytab) # Convert myJlTab to JlValue
let key = 1
var poppedValue = popMe[int64, float64](myJlTab, key)
doAssert not myJlTab.to(Table[int64, float64]).contains(key) # Value was removed from myJlTab
doAssert poppedValue == mytab[key]

block:
# You can use [] on Julia dict as well
var jldict = toJlVal({"alpha": 1.1, "beta": 2.2}.toTable)
doAssert jldict["alpha"].to(float) == 1.1
doAssert jldict["beta"].to(float) == 2.2
jldict["alpha"] = 3.3
doAssert jldict["alpha"].to(float) == 3.3

when isMainModule:
main()
105 changes: 54 additions & 51 deletions examples/ex05_module.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,63 +7,66 @@ type
y: float
z: string

Julia.init() # Initialize Julia VM. This should be done once in the lifetime of your program.
# Include Julia file
jlInclude("localmodule.jl")
# Use the module. If you're confused by the syntax, go and read through Julia's Manual where module usage is explained
jlUseModule(".nimjlExample")
proc main() =
Julia.init() # Initialize Julia VM. This should be done once in the lifetime of your program.
# Include Julia file
jlInclude("localmodule.jl")
# Use the module. If you're confused by the syntax, go and read through Julia's Manual where module usage is explained
jlUseModule(".nimjlExample")

block: # Tuple handling
# Look, you can pass Nim tuple to Julia
var mytup: MyTuple = (nimTupKey1: 1, nimTupKey2: 2)
# Convert Nim tuple to Julia tuple automatically
var res = Julia.customFunction(mytup)
# Convert Julia tuple to Nim tuple
var nimres = res.to(MyTuple)
block: # Tuple handling
# Look, you can pass Nim tuple to Julia
var mytup: MyTuple = (nimTupKey1: 1, nimTupKey2: 2)
# Convert Nim tuple to Julia tuple automatically
var res = Julia.customFunction(mytup)
# Convert Julia tuple to Nim tuple
var nimres = res.to(MyTuple)

echo myTup
echo nimres
echo myTup
echo nimres

doAssert myTup.nimTupKey1+1 == nimres.nimTupKey1
doAssert myTup.nimTupKey2+1 == nimres.nimTupKey2
doAssert myTup.nimTupKey1+1 == nimres.nimTupKey1
doAssert myTup.nimTupKey2+1 == nimres.nimTupKey2

block: # Object manipulation
# Call constructor
var foo = Julia.makeFoo()
# Access fields with dot syntax
# Calls getproperty in Julia side
echo foo.x
echo foo.y
echo foo.z
# Modify fields with .= syntax
# Calls setproperty! on Julia side
foo.x = 2
foo.y = 3.14
foo.z = "General Kenobi !"
# Yay this has been modified
echo foo
block: # Object manipulation
# Call constructor
var foo = Julia.makeFoo()
# Access fields with dot syntax
# Calls getproperty in Julia side
echo foo.x
echo foo.y
echo foo.z
# Modify fields with .= syntax
# Calls setproperty! on Julia side
foo.x = 2
foo.y = 3.14
foo.z = "General Kenobi !"
# Yay this has been modified
echo foo

# You can use dot syntax on Julia value to call proc as well
discard foo.applyToFoo()
echo foo
# You can use dot syntax on Julia value to call proc as well
discard foo.applyToFoo()
echo foo

block:
var foo = Foo(x: 12, y: 15, z: "This string comes from Nim")
# You can convert Nim to Julia object if :
# * fields have the same name and type (fieldName becomdes Julia symbol)
# * The Julia type have an empty constructor -- Nim needs to initialize the Julia variable before calling setproperty! providing a default empty constructor is the easiest way of doing it
var jlfoo = toJlVal(foo)
echo jlfoo
echo jltypeof(jlfoo) # This echo "Foo" -> Julia sees this as a Foo mutable struct type
block:
var foo = Foo(x: 12, y: 15, z: "This string comes from Nim")
# You can convert Nim to Julia object if :
# * fields have the same name and type (fieldName becomdes Julia symbol)
# * The Julia type have an empty constructor -- Nim needs to initialize the Julia variable before calling setproperty! providing a default empty constructor is the easiest way of doing it
var jlfoo = toJlVal(foo)
echo jlfoo
echo jltypeof(jlfoo) # This echo "Foo" -> Julia sees this as a Foo mutable struct type

discard jlfoo.applyToFoo()
# Object are copid during conversions so modifying jlfoo does not modify foo
# There is an exception to this for Array fields -- see ex_arrays for explanation
echo jlfoo
echo foo
discard jlfoo.applyToFoo()
# Object are copid during conversions so modifying jlfoo does not modify foo
# There is an exception to this for Array fields -- see ex_arrays for explanation
echo jlfoo
echo foo

block:
let res = Julia.returnDoubleValue()
echo res.myint
echo res.mystr
block:
let res = Julia.returnDoubleValue()
echo res.myint
echo res.mystr

when isMainModule:
main()
23 changes: 16 additions & 7 deletions examples/ex11_external_deps.nim
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
import nimjl

## See https://pkgdocs.julialang.org/dev/api/#Pkg.add for more info
Julia.init(1):
Pkg:
add(name="Polynomials", version="3.0.0")
add(name="LinearAlgebra")
add("DSP")
add(name="Wavelets", version="0.9.4")
proc main() =
## See https://pkgdocs.julialang.org/dev/api/#Pkg.add for more info
Julia.init(1):
Pkg:
add(name="Polynomials", version="3.0.0")
add(name="LinearAlgebra")
add("DSP")

Julia.useModule("Pkg")
let jlpkg = Julia.getModule("Pkg")
discard jlpkg.status()

Julia.exit()

when isMainModule:
main()
5 changes: 3 additions & 2 deletions nimjl/cores.nim
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,14 @@ proc jlVmExit*(exit_code: cint = 0.cint) =
# discard jlEval(fmt"exit_save_sysimage({fpath})")

#########################################
var staticContents: Table[string, string]
var staticContents: OrderedTable[string, string]

import std/logging

proc loadJlRessources*() =
for key, content in staticContents.pairs():
info("> Nimjl loading Julia ressource: ", key, ".jl")
info("> Nimjl loading Julia ressource: ", key)
# debugEcho("> Nimjl loading Julia ressource: ", key)
JlCode(content)

# Init & Exit function
Expand Down
Loading

0 comments on commit da5f633

Please sign in to comment.