gijit / gi

gijit is a just-in-time trace-compiled golang REPL. Standing on the shoulders of giants (GopherJS and LuaJIT).
Other
320 stars 17 forks source link

slices, append and copy #3

Closed glycerine closed 6 years ago

glycerine commented 6 years ago

look at using the FFI for this.

append needs to be implemented

a := []int{1}
a = append(a, 23)

copy needs to be implemented

The Lua table that backs slices (and will eventually back maps and structs) is implemented here https://github.com/gijit/gi/blob/master/pkg/compiler/luaUtil.go#L28

and the operations simply need to be defined in Lua.

compare to:

https://github.com/neomantra/lds : STL-like containers such as Vector and Queue (hashes and trees planned)

see also:

https://github.com/justincormack/slice

"This is a simple Luajit ffi array slice library, loosely based on he Go slice API"
This requires Luajit head is it uses the new parameterized types http://www.freelists.org/post/luajit/ffi-type-of-pointer-to,4

The Go API is documented here http://blog.golang.org/2011/01/go-slices-usage-and-internals.html and http://golang.org/ref/spec#Slice_types

Justin Cormack wrote:
> On Tue, Jun 12, 2012 at 3:27 PM, Mike Pall <mike-1206@xxxxxxxxxx> wrote:
> > Well, it's not that difficult to do for the pointer case. But I'd
> > rather go for parameterized types, e.g.
> >
> >  ffi.typeof("$ *", foo_t)
> >  ffi.typeof("struct { $ k; $ v; }[?]", foo_t, bar_t)
> >
> > But I'm not sure whether the complexity is really worth it.
> >
> Not sure about that either - never really needed anything like that in a C
> context.

That's because C is statically typed. C++ added templates to
overcome this limitation (somewhat). We can certainly do better in
Lua. ;-)

Actually, it wasn't that difficult to add parameterized types to
the FFI. The feature is now in git HEAD. No docs, yet, but you can
already play with it:

The '$' character is the marker to be replaced with parameters in
a C type declaration:

* A ctype or a cdata parameter is interpreted like an anonymous
  typedef. You can use that to construct derived types, e.g.
    ffi.typeof("$*", ct) is a pointer to ct, or "$[10]" is a 10
      element array. Unlike simplistic string concatenation, this
        works for all cases (e.g. pointers to function pointers).

* A string parameter is treated like an identifier or keyword,
  except the string is _not_ parsed again or split into words
    (this isn't simple textual substitution). You can use that for
      field names, function names, argument names etc.

  [I'm pondering whether I should drop the keyword and type lookup
    on the string. That would allow you to use arbitrary names for
      fields, even when they collide with keywords or typedefs. I may
        change that before writing the docs.]

* A number parameter is treated as an integer. You can use that
  to construct fixed size arrays. In some contexts you may prefer
    this over VLAs. It works for multi-dimensional types, too. E.g.:

    local matrix_t = ffi.typeof("uint8_t[$][$]", width, height)
        ...
            local m = matrix_t()

Only ffi.typeof() and ffi.cdef() parse parameterized types. The
other functions, e.g. ffi.new(), don't do that, because they
already take other arguments (e.g. initializers). I guess it would
be too confusing to mix two kinds of arguments.

Anyway, parameterized types are a nice tool, but you'll want to
use it sparingly!

The typical scenarios where you'd use templates in C++ come to
mind: e.g. construct a stack or a queue of an arbitrary type.
These need to create an array of the element type, which is now
really easy to do. [Justin's use case]

Another example are derived types of anonymous structs. This
avoids pollution of the struct namespace. [Henk's use case]

I'm sure you'll come up with a lot more use cases.

--Mike
glycerine commented 6 years ago

I'm working on this. Going to wrap regular Go slices in Lua full-userdata, and proxy the method calls through using a metatable on the userdata.

glycerine commented 6 years ago

append works for slices in e231bee4204f805d1343e6b558e159a728a8e844

However, that's in Lua. copy needs to write into the appropriate place in the underlying array, so for fidelity we need to use Go arrays and slices.

glycerine commented 6 years ago

working for native Lua slices, as of v0.7.9.