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 Side-by-Side Diffs Ignore Whitespace Patch

Changes to CMakeLists.txt.

    46     46   target_link_libraries(genconf ${LUA_LIBRARIES})
    47     47   
    48     48   add_custom_command(
    49     49     OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/luaf_conf.fi
    50     50     COMMAND genconf > luaf_conf.fi
    51     51     DEPENDS genconf
    52     52     )
           53  +
           54  +add_custom_command(
           55  +  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/l2f_testmodule.f90
           56  +  COMMAND lua l2f.lua testmod.lua ${CMAKE_CURRENT_BINARY_DIR}/l2f_testmodule.f90 testmodule
           57  +  DEPENDS l2f.lua testmod.lua
           58  +	WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
           59  +  )
    53     60   
    54     61   set (src_lib
    55     62     ftnlf.f90
    56     63     ftnlf_fxcore.f90
    57     64     luaf/luaf.f90
    58     65     luaf/luafe.f90
    59     66     ${CMAKE_CURRENT_BINARY_DIR}/luaf_conf.fi
................................................................................
    66     73     ${CMAKE_CURRENT_BINARY_DIR}/luaf_conf.fi
    67     74     # export everything
    68     75     # ftnlf_fxcore.def
    69     76     )
    70     77   
    71     78   set (src_test
    72     79     test.f90
           80  +  ${CMAKE_CURRENT_BINARY_DIR}/l2f_testmodule.f90
    73     81     )
    74     82   
    75     83   add_library(ftnlf STATIC ${src_lib})
    76     84   set_target_properties(ftnlf PROPERTIES COMPILE_FLAGS "${FCFLAGS90}")
    77     85   if(CMAKE_BUILD_TYPE STREQUAL "Release" AND CMAKE_Fortran_COMPILER_ID STREQUAL "Intel")
    78     86     set_target_properties(ftnlf PROPERTIES INTERPROCEDURAL_OPTIMIZATION 1)
    79     87   endif()

Added l2f.lua.

            1  +-- encode lua module as a Fortran module for 
            2  +-- LuaF binding/ftnlf framework
            3  +
            4  +local mod_template = [[
            5  +! Autogenerated module, please do not edit
            6  +module l2f_@NAME@
            7  +    use LuaF
            8  +    use, intrinsic :: iso_c_binding, only: c_ptr, c_int, & 
            9  +        & c_intptr_t, c_size_t
           10  +    implicit none
           11  +    private
           12  +    public ldr_@NAME@
           13  +
           14  +contains
           15  +    function ldr_@NAME@(L) bind(C, name="luaopen_@NAME@") result(r)
           16  +        type(c_ptr), value, intent(in) :: L
           17  +        integer(c_int) :: r
           18  +
           19  +        integer(c_int) :: res
           20  +        character(len=1), parameter :: c = ' '
           21  +        integer(1) :: AR(@LEN@)
           22  +
           23  +        ! Chunk
           24  +@DATA@
           25  +
           26  +        ! Load chunk
           27  +        res = luaL_loadbuffer(L, transfer(AR, c, @LEN@), &
           28  +            & @LEN@_C_SIZE_T, F_C_STR('@NAME@'))
           29  +
           30  +        if (res /= 0) then
           31  +            ! rethrow error
           32  +            r = lua_error(L)
           33  +        else
           34  +            ! Execute chunk
           35  +            ! Move chunk to the 1st position
           36  +            call lua_insert(L, 1_C_INT)
           37  +            ! nargs
           38  +            res = lua_gettop(L) - 1
           39  +            call lua_call(L, res, LUA_MULTRET)
           40  +            ! nresults
           41  +            r = lua_gettop(L)
           42  +        endif
           43  +
           44  +    end function ldr_@NAME@
           45  +
           46  +end module l2f_@NAME@
           47  +]]
           48  +
           49  +local function subs(tmpl, defs)
           50  +   return (tmpl:gsub('@(%w+)@', defs))
           51  +end
           52  +
           53  +local function dump_string_as_fortran(s, arr_name)
           54  +   local res = {}
           55  +   -- output DATA operators
           56  +   local ofs, len = 0, #s
           57  +   
           58  +   while len > 0 do
           59  +      local linelen = math.min(len, 8)
           60  +      local tblline = {}
           61  +      for k = 1, linelen do
           62  +         local c = s:byte(ofs+k)
           63  +         -- convert to signed integer*1 (wraparound)
           64  +         if c >= 128 then
           65  +            c = c - 256
           66  +         end
           67  +         -- table.insert(tblline, string.format("Z'%02X'", ))
           68  +         table.insert(tblline, string.format("%d", c))
           69  +      end
           70  +      table.insert(res, 
           71  +                   string.format(
           72  +                      'data %s(%u:%u) /%s/',
           73  +                      arr_name,
           74  +                      ofs+1,
           75  +                      ofs+linelen,
           76  +                      table.concat(tblline, ', ')))
           77  +      len = len - linelen
           78  +      ofs = ofs + linelen
           79  +   end
           80  +   
           81  +   return table.concat(res, '\n')
           82  +end
           83  +
           84  +local function write_module(f, s, modname)
           85  +   local defs = {
           86  +      NAME = modname,
           87  +      LEN = #s,
           88  +      DATA = dump_string_as_fortran(s, 'AR')
           89  +   }
           90  +   f:write(subs(mod_template, defs))
           91  +end
           92  +
           93  +if #arg < 3 then
           94  +   io.stderr:write('Usage lua l2f.lua <module.lua> <fortran_module_file> <fortran_module_name>\n')
           95  +   os.exit(1)
           96  +end
           97  +
           98  +local dump = string.dump(loadfile(arg[1]))
           99  +local modname = arg[3]
          100  +local ofile = io.open(arg[2], 'w')
          101  +write_module(ofile, dump, modname)
          102  +ofile:close()

Changes to test.f90.

    57     57   end module testmod
    58     58   
    59     59   program test
    60     60       ! Mockup for ftnlf
    61     61       use ftnlf
    62     62       use luaFE, only: luaFE_FunctionEntry
    63     63       use testmod
           64  +    use l2f_testmodule
    64     65       implicit none
    65     66       
    66         -    type(luaFE_FunctionEntry) :: ldr(1)
           67  +    type(luaFE_FunctionEntry) :: ldr(2)
    67     68       logical :: r
    68     69       real(8) :: fval
    69     70       real(8) :: fvals(10), arr_m(1), arr_o(10)
    70     71       
    71     72       ! Initialize
    72     73       ldr(1)%name='FX.Test'
    73     74       ldr(1)%f => ldr_fx_test
           75  +    ldr(2)%name='TestModule'
           76  +    ldr(2)%f => ldr_testmodule
    74     77       r = ftnlf_init('testdb.lua', ldr)
    75     78       if (.not. r) stop 99
    76     79   
    77     80       ! Simplified iface
    78     81       r = luafun_s('val1', [1.d0,-3.5d0], fval, tblname='tbl1')
    79     82       write (*,'(L2,1X,1PE11.4)') r, fval
    80     83   

Changes to testdb.lua.

    21     21      {},
    22     22      { v5b = function(x,y) return x-y+1 end },
    23     23      tbl1 = { v5 = function(x,y) return x-y end },
    24     24      tbl2 = { v6 = FXC.interp({-10,1,10,70}), v7 = -29.3e-4},
    25     25   
    26     26   }
    27     27   
    28         -if false then
           28  +if true then
    29     29   
    30     30   local T = require('FX.Test')
    31     31   print(T.testfun(-1.4))
    32     32   
    33     33   A = FXC.array(10)
    34     34   for k = 1, #A do
    35     35      A[k] = k
................................................................................
    39     39   print('OUT: ')
    40     40   for k = 1, #A do
    41     41      print(A[k])
    42     42   end
    43     43   
    44     44   end
    45     45   
           46  +local T2 = require('TestModule')
           47  +T2.printme()

Added testmod.lua.

            1  +local modtbl = { ... }
            2  +
            3  +local function printme()
            4  +   for k, v in pairs(modtbl) do
            5  +      print(k,  '-> ', v)
            6  +   end
            7  +end
            8  +
            9  +return {
           10  +   printme = printme,
           11  +}