ftnlf

Check-in [729c82f64c]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add mechanism for embedding Lua modules into Fortran.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:729c82f64cb29356fd17694b492931b5f5beb64f
User & Date: vadim 2019-01-22 09:38:09
Context
2019-01-23
09:05
Tweak test to check that L2F-generated module can be preloaded under arbitrary name. check-in: a969522261 user: vadim tags: trunk
2019-01-22
09:38
Add mechanism for embedding Lua modules into Fortran. check-in: 729c82f64c user: vadim tags: trunk
2018-12-22
16:42
Checks and tests. check-in: a1d3391317 user: vadim tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to CMakeLists.txt.

46
47
48
49
50
51
52







53
54
55
56
57
58
59
..
66
67
68
69
70
71
72

73
74
75
76
77
78
79
target_link_libraries(genconf ${LUA_LIBRARIES})

add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/luaf_conf.fi
  COMMAND genconf > luaf_conf.fi
  DEPENDS genconf
  )








set (src_lib
  ftnlf.f90
  ftnlf_fxcore.f90
  luaf/luaf.f90
  luaf/luafe.f90
  ${CMAKE_CURRENT_BINARY_DIR}/luaf_conf.fi
................................................................................
  ${CMAKE_CURRENT_BINARY_DIR}/luaf_conf.fi
  # export everything
  # ftnlf_fxcore.def
  )

set (src_test
  test.f90

  )

add_library(ftnlf STATIC ${src_lib})
set_target_properties(ftnlf PROPERTIES COMPILE_FLAGS "${FCFLAGS90}")
if(CMAKE_BUILD_TYPE STREQUAL "Release" AND CMAKE_Fortran_COMPILER_ID STREQUAL "Intel")
  set_target_properties(ftnlf PROPERTIES INTERPROCEDURAL_OPTIMIZATION 1)
endif()







>
>
>
>
>
>
>







 







>







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
..
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
target_link_libraries(genconf ${LUA_LIBRARIES})

add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/luaf_conf.fi
  COMMAND genconf > luaf_conf.fi
  DEPENDS genconf
  )

add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/l2f_testmodule.f90
  COMMAND lua l2f.lua testmod.lua ${CMAKE_CURRENT_BINARY_DIR}/l2f_testmodule.f90 testmodule
  DEPENDS l2f.lua testmod.lua
	WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
  )

set (src_lib
  ftnlf.f90
  ftnlf_fxcore.f90
  luaf/luaf.f90
  luaf/luafe.f90
  ${CMAKE_CURRENT_BINARY_DIR}/luaf_conf.fi
................................................................................
  ${CMAKE_CURRENT_BINARY_DIR}/luaf_conf.fi
  # export everything
  # ftnlf_fxcore.def
  )

set (src_test
  test.f90
  ${CMAKE_CURRENT_BINARY_DIR}/l2f_testmodule.f90
  )

add_library(ftnlf STATIC ${src_lib})
set_target_properties(ftnlf PROPERTIES COMPILE_FLAGS "${FCFLAGS90}")
if(CMAKE_BUILD_TYPE STREQUAL "Release" AND CMAKE_Fortran_COMPILER_ID STREQUAL "Intel")
  set_target_properties(ftnlf PROPERTIES INTERPROCEDURAL_OPTIMIZATION 1)
endif()

Added l2f.lua.













































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
-- encode lua module as a Fortran module for 
-- LuaF binding/ftnlf framework

local mod_template = [[
! Autogenerated module, please do not edit
module l2f_@NAME@
    use LuaF
    use, intrinsic :: iso_c_binding, only: c_ptr, c_int, & 
        & c_intptr_t, c_size_t
    implicit none
    private
    public ldr_@NAME@

contains
    function ldr_@NAME@(L) bind(C, name="luaopen_@NAME@") result(r)
        type(c_ptr), value, intent(in) :: L
        integer(c_int) :: r

        integer(c_int) :: res
        character(len=1), parameter :: c = ' '
        integer(1) :: AR(@LEN@)

        ! Chunk
@DATA@

        ! Load chunk
        res = luaL_loadbuffer(L, transfer(AR, c, @LEN@), &
            & @LEN@_C_SIZE_T, F_C_STR('@NAME@'))

        if (res /= 0) then
            ! rethrow error
            r = lua_error(L)
        else
            ! Execute chunk
            ! Move chunk to the 1st position
            call lua_insert(L, 1_C_INT)
            ! nargs
            res = lua_gettop(L) - 1
            call lua_call(L, res, LUA_MULTRET)
            ! nresults
            r = lua_gettop(L)
        endif

    end function ldr_@NAME@

end module l2f_@NAME@
]]

local function subs(tmpl, defs)
   return (tmpl:gsub('@(%w+)@', defs))
end

local function dump_string_as_fortran(s, arr_name)
   local res = {}
   -- output DATA operators
   local ofs, len = 0, #s
   
   while len > 0 do
      local linelen = math.min(len, 8)
      local tblline = {}
      for k = 1, linelen do
         local c = s:byte(ofs+k)
         -- convert to signed integer*1 (wraparound)
         if c >= 128 then
            c = c - 256
         end
         -- table.insert(tblline, string.format("Z'%02X'", ))
         table.insert(tblline, string.format("%d", c))
      end
      table.insert(res, 
                   string.format(
                      'data %s(%u:%u) /%s/',
                      arr_name,
                      ofs+1,
                      ofs+linelen,
                      table.concat(tblline, ', ')))
      len = len - linelen
      ofs = ofs + linelen
   end
   
   return table.concat(res, '\n')
end

local function write_module(f, s, modname)
   local defs = {
      NAME = modname,
      LEN = #s,
      DATA = dump_string_as_fortran(s, 'AR')
   }
   f:write(subs(mod_template, defs))
end

if #arg < 3 then
   io.stderr:write('Usage lua l2f.lua <module.lua> <fortran_module_file> <fortran_module_name>\n')
   os.exit(1)
end

local dump = string.dump(loadfile(arg[1]))
local modname = arg[3]
local ofile = io.open(arg[2], 'w')
write_module(ofile, dump, modname)
ofile:close()

Changes to test.f90.

57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
73


74
75
76
77
78
79
80
end module testmod

program test
    ! Mockup for ftnlf
    use ftnlf
    use luaFE, only: luaFE_FunctionEntry
    use testmod

    implicit none
    
    type(luaFE_FunctionEntry) :: ldr(1)
    logical :: r
    real(8) :: fval
    real(8) :: fvals(10), arr_m(1), arr_o(10)
    
    ! Initialize
    ldr(1)%name='FX.Test'
    ldr(1)%f => ldr_fx_test


    r = ftnlf_init('testdb.lua', ldr)
    if (.not. r) stop 99

    ! Simplified iface
    r = luafun_s('val1', [1.d0,-3.5d0], fval, tblname='tbl1')
    write (*,'(L2,1X,1PE11.4)') r, fval








>


|







>
>







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
end module testmod

program test
    ! Mockup for ftnlf
    use ftnlf
    use luaFE, only: luaFE_FunctionEntry
    use testmod
    use l2f_testmodule
    implicit none
    
    type(luaFE_FunctionEntry) :: ldr(2)
    logical :: r
    real(8) :: fval
    real(8) :: fvals(10), arr_m(1), arr_o(10)
    
    ! Initialize
    ldr(1)%name='FX.Test'
    ldr(1)%f => ldr_fx_test
    ldr(2)%name='TestModule'
    ldr(2)%f => ldr_testmodule
    r = ftnlf_init('testdb.lua', ldr)
    if (.not. r) stop 99

    ! Simplified iface
    r = luafun_s('val1', [1.d0,-3.5d0], fval, tblname='tbl1')
    write (*,'(L2,1X,1PE11.4)') r, fval

Changes to testdb.lua.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
39
40
41
42
43
44
45


   {},
   { v5b = function(x,y) return x-y+1 end },
   tbl1 = { v5 = function(x,y) return x-y end },
   tbl2 = { v6 = FXC.interp({-10,1,10,70}), v7 = -29.3e-4},

}

if false then

local T = require('FX.Test')
print(T.testfun(-1.4))

A = FXC.array(10)
for k = 1, #A do
   A[k] = k
................................................................................
print('OUT: ')
for k = 1, #A do
   print(A[k])
end

end










|







 







>
>
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
39
40
41
42
43
44
45
46
47
   {},
   { v5b = function(x,y) return x-y+1 end },
   tbl1 = { v5 = function(x,y) return x-y end },
   tbl2 = { v6 = FXC.interp({-10,1,10,70}), v7 = -29.3e-4},

}

if true then

local T = require('FX.Test')
print(T.testfun(-1.4))

A = FXC.array(10)
for k = 1, #A do
   A[k] = k
................................................................................
print('OUT: ')
for k = 1, #A do
   print(A[k])
end

end

local T2 = require('TestModule')
T2.printme()

Added testmod.lua.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
local modtbl = { ... }

local function printme()
   for k, v in pairs(modtbl) do
      print(k,  '-> ', v)
   end
end

return {
   printme = printme,
}