Skip to content

Commit

Permalink
Make GAP.jl usable as a Julia module with precompilation
Browse files Browse the repository at this point in the history
* Move *.jl files from JuliaInterface to module itself
* Add GAPTypes.jl package as dependency
* Replaced MPtr by GapObj
* Removed unnecessary libgap.jl
* Removed unnecessary True and False constants
* Moved MPtr call definition into init, eval into Main
  to not eval into a closed module
  • Loading branch information
sebasguts committed Jun 14, 2019
1 parent 8413a5a commit c8e491f
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 89 deletions.
7 changes: 4 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ authors = ["Thomas Breuer <[email protected]>", "Sebastian Gutsche <gutsch
version = "0.1.0"

[deps]
GAPTypes = "cd4130c4-8d21-11e9-2a29-61e008680c2d"
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[compat]
julia = "1.1"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test"]

[compat]
julia = "1.1"
18 changes: 0 additions & 18 deletions pkg/GAPJulia/JuliaInterface/julia/libgap.jl

This file was deleted.

1 change: 0 additions & 1 deletion pkg/GAPJulia/JuliaInterface/read.g
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ dirs_julia := DirectoriesPackageLibrary( "JuliaInterface", "julia" );

JuliaIncludeFile( Filename( dirs_julia, "gaptypes.jl" ) );

JuliaEvalString( Concatenation( "__JULIAGAPMODULE.include( \"", Filename( dirs_julia, "libgap.jl" ), "\")" ) );

_JULIAINTERFACE_INTERNAL_INIT();

Expand Down
26 changes: 26 additions & 0 deletions src/GAP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ import Base: length, convert, finalize

import Libdl

using GAPTypes

export GapObj

#
# This is a very hacky prototype calling libgap from julia
#
# It is intended to be a low level interface to the C functions
# the higher level API can be found in gap.jl
#

import Base: length, convert

sysinfo = missing

read_sysinfo_gap = function(dir::String)
Expand Down Expand Up @@ -107,6 +120,19 @@ function __init__()
if ! isdefined(Main, :__GAPINTERNAL_LOADED_FROM_GAP) || Main.__GAPINTERNAL_LOADED_FROM_GAP != true
run_it(GAPROOT, error_handler_func)
end

## FIXME: Hack because abstract types cannot be endowed with methods in Julia 1.1.
## With Julia 1.2, this will be possible and this hack could then be replaced with the
## corresponding line in ccalls.jl
MPtr = Base.MainInclude.eval(:(ForeignGAP.MPtr))
Base.MainInclude.eval(:(
(func::$MPtr)(args...; kwargs...) = call_gap_func(func, args...; kwargs...)
))
end

include( "ccalls.jl" )
include( "gap2.jl" )
include( "gap_to_julia.jl" )
include( "julia_to_gap.jl" )

end
48 changes: 25 additions & 23 deletions pkg/GAPJulia/JuliaInterface/julia/ccalls.jl → src/ccalls.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ function GET_FROM_GAP(ptr::Ptr{Cvoid})::Any
end

function EvalStringEx( cmd :: String )
res = ccall( :GAP_EvalString, MPtr,
res = ccall( :GAP_EvalString, Any,
(Ptr{UInt8},),
cmd );
return res
Expand All @@ -29,42 +29,42 @@ function CanAssignGlobalVariable(name::String)
(Ptr{UInt8},), name)
end

function AssignGlobalVariable(name::String, value::MPtr)
function AssignGlobalVariable(name::String, value::Obj)
if ! CanAssignGlobalVariable(name)
error("cannot assing to $name in GAP")
end
ccall(:GAP_AssignGlobalVariable, Cvoid,
(Ptr{UInt8}, MPtr), name, value)
(Ptr{UInt8}, Any), name, value)
end

function MakeString( val::String )::MPtr
string = ccall( :GAP_MakeString, MPtr,
function MakeString( val::String )::GapObj
string = ccall( :GAP_MakeString, Any,
( Ptr{UInt8}, ),
val )
return string
end

function CSTR_STRING( val::MPtr )::String
function CSTR_STRING( val::GapObj )::String
char_ptr = ccall( :GAP_CSTR_STRING, Ptr{UInt8},
( MPtr, ),
( Any, ),
val )
return deepcopy(unsafe_string(char_ptr))
end

function UNSAFE_CSTR_STRING( val::MPtr )::Array{UInt8,1}
function UNSAFE_CSTR_STRING( val::GapObj )::Array{UInt8,1}
string_len = Int64( ccall( :GAP_LenString, Cuint,
( MPtr, ),
( Any, ),
val ) )
char_ptr = ccall( :GAP_CSTR_STRING, Ptr{UInt8},
( MPtr, ),
( Any, ),
val )
return unsafe_wrap( Array{UInt8,1}, char_ptr, string_len )
end


function NewPlist(length :: Int64)
o = ccall( :GAP_NewPlist,
MPtr,
Any,
(Int64,),
length )
return o
Expand All @@ -80,54 +80,56 @@ end

function NEW_MACFLOAT(x::Float64)
o = ccall( :NEW_MACFLOAT,
MPtr,
Any,
(Cdouble,),
x )
return o
end

function ValueMacFloat(x::MPtr)
function ValueMacFloat(x::GapObj)
o = ccall( :GAP_ValueMacFloat,
Cdouble,
(MPtr,),
(Any,),
x )
return o
end

function CharWithValue(x::Cuchar)
o = ccall( :GAP_CharWithValue,
MPtr,
Any,
(Cuchar,),
x )
return o
end

function ElmList(x::MPtr,position)
function ElmList(x::GapObj,position)
o = ccall( :GAP_ElmList,
Ptr{Cvoid},
(MPtr,Culong),
(Any,Culong),
x,Culong(position))
return GET_FROM_GAP(o)
end

function NewJuliaFunc(x::Function)
o = ccall( :NewJuliaFunc,
MPtr,
Any,
(Any,),
x )
return o
end

"""
(func::MPtr)(args...)
(func::GapObj)(args...)
> This function makes it possible to call MPtr objects as functions.
> This function makes it possible to call GapObjs as functions.
> There is no argument number checking here, all checks on the arguments
> are done by GAP itself.
"""
(func::MPtr)(args...; kwargs...) = call_gap_func(func, args...; kwargs...)
# This needs to be instantiated for `MPtr` and is therefore moved to the init function
# (func::GapObj)(args...; kwargs...) where T <: GapObj = call_gap_func(func, args...; kwargs...)


function call_gap_func(func::MPtr, args...; kwargs...)
function call_gap_func(func::GapObj, args...; kwargs...)
global Globals
options = false
if length(kwargs) > 0
Expand All @@ -138,7 +140,7 @@ function call_gap_func(func::MPtr, args...; kwargs...)
end
result = nothing
try
result = ccall(:call_gap_func, Any, (MPtr, Any), func, args)
result = ccall(:call_gap_func, Any, (Any, Any), func, args)
catch e
if options
Globals.ResetOptionsStack()
Expand Down
33 changes: 15 additions & 18 deletions pkg/GAPJulia/JuliaInterface/julia/gap.jl → src/gap2.jl
Original file line number Diff line number Diff line change
@@ -1,44 +1,41 @@
import Base: convert, getindex, setindex!, length, show

const True = Globals.ReturnTrue()
const False = Globals.ReturnFalse()

const GAPInputType_internal = Union{MPtr,FFE}
const GAPInputType_internal = Union{GapObj,FFE}
const GAPInputType = Union{GAPInputType_internal,Int64,Bool}

const Obj = Union{GAPInputType,Nothing}

function Base.show( io::IO, obj::Union{MPtr,FFE} )
function Base.show( io::IO, obj::Union{GapObj,FFE} )
str = Globals.String( obj )
stri = CSTR_STRING( str )
print(io,"GAP: $stri")
end

function Base.string( obj::Union{MPtr,FFE} )
function Base.string( obj::Union{GapObj,FFE} )
str = Globals.String( obj )
return CSTR_STRING( str )
end

## implement indexing interface
Base.getindex(x::MPtr, i::Int64) = Globals.ELM_LIST(x, i)
Base.setindex!(x::MPtr, v::Any, i::Int64 ) = Globals.ASS_LIST( x, i, v )
Base.length(x::MPtr) = Globals.Length(x)
Base.firstindex(x::MPtr) = 1
Base.lastindex(x::MPtr) = Globals.Length(x)
Base.getindex(x::GapObj, i::Int64) = Globals.ELM_LIST(x, i)
Base.setindex!(x::GapObj, v::Any, i::Int64 ) = Globals.ASS_LIST( x, i, v )
Base.length(x::GapObj) = Globals.Length(x)
Base.firstindex(x::GapObj) = 1
Base.lastindex(x::GapObj) = Globals.Length(x)

# matrix
Base.getindex(x::MPtr, i::Int64, j::Int64) = Globals.ELM_LIST(x, i, j)
Base.setindex!(x::MPtr, v::Any, i::Int64, j::Int64) = Globals.ASS_LIST(x, i, j, v)
Base.getindex(x::GapObj, i::Int64, j::Int64) = Globals.ELM_LIST(x, i, j)
Base.setindex!(x::GapObj, v::Any, i::Int64, j::Int64) = Globals.ASS_LIST(x, i, j, v)

# records
RNamObj(f::Union{Symbol,Int64,AbstractString}) = Globals.RNamObj(MakeString(string(f)))
# note: we don't use Union{Symbol,Int64,AbstractString} below to avoid
# ambiguity between these methods and method `getproperty(x, f::Symbol)`
# from Julia's Base module
Base.getproperty(x::MPtr, f::Symbol) = Globals.ELM_REC(x, RNamObj(f))
Base.getproperty(x::MPtr, f::Union{AbstractString,Int64}) = Globals.ELM_REC(x, RNamObj(f))
Base.setproperty!(x::MPtr, f::Symbol, v) = Globals.ASS_REC(x, RNamObj(f), v)
Base.setproperty!(x::MPtr, f::Union{AbstractString,Int64}, v) = Globals.ASS_REC(x, RNamObj(f), v)
Base.getproperty(x::GapObj, f::Symbol) = Globals.ELM_REC(x, RNamObj(f))
Base.getproperty(x::GapObj, f::Union{AbstractString,Int64}) = Globals.ELM_REC(x, RNamObj(f))
Base.setproperty!(x::GapObj, f::Symbol, v) = Globals.ASS_REC(x, RNamObj(f), v)
Base.setproperty!(x::GapObj, f::Union{AbstractString,Int64}, v) = Globals.ASS_REC(x, RNamObj(f), v)

#
Base.zero(x::GAPInputType_internal) = Globals.ZERO(x)
Expand Down Expand Up @@ -157,7 +154,7 @@ end

export LoadPackageAndExposeGlobals

function Display(x::MPtr)
function Display(x::GapObj)
## FIXME: Get rid of this horrible hack
## once GAP offers a consistent
## DisplayString function
Expand Down
Loading

0 comments on commit c8e491f

Please sign in to comment.