Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge master in devel #49

Merged
merged 2 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading