Open cvillecsteele opened 8 years ago
100% agree. I've been wanting to put something like this together for a while. Any ideas as to how you'd expect the interface to look?
Imagine a type like so:
type Magician struct { Card string }
func NewMagician(card string) { return Magician{Card: card} }
func (m Magician) PickACard() string { return m.card }
I'd love it if this could be accessible as new Magician("ace of spades")
, and if PickACard
could be accessed as pickACard
.
And then there are non-struct types:
type Counter int
func (c *Counter) Add(n int) { *c += n }
For this, we probably want valueOf
to return the numeric value. And how do we make "Add" available as "add"?
I realise that this isn't exactly what you were talking about, but there are lots of open (and related!) API questions here.
I really like what you posted above. Thinking out loud here, so caveat emptor. More focused (at least at the moment, given my lack of sleep) on my particular problem, not so much on your more generalized solution...
rt := otto.New();
rt.SetUserCallConverter(func(v Value, t reflect.Type) *reflect.Value {
// nifty type conversion code here
});
Then at the end of convertCallParameter()
:
if self.UserCallConverter {
if result := self.UserCallConverter(v, t); result != nil {
return *result;
}
}
But your thinking is mighty interesting. I'd like that too... There's a lot of ceremony right now for accomplishing what you've suggested, and it's really just boilerplate, so I think a good candidate for a "real" Otto API.
Related... one thing that has been a source of irritation using Otto is that golang does not support package-level introspection at runtime. It can be done statically / with generators, and that approach has been used fairly extensively in some of the golang SDKs I've worked with, but the approach is tiresome (to me at least). I have wanted to be able to point at a golang package (say, filepath) and tell Otto (in effect), "export all that to JS-land". No easy way to do that now.
Reluctantly, I observe that the path of least resistance forward in this area seems to point to some sort of IDL. (Blech.)
(See here: https://groups.google.com/forum/#!topic/golang-nuts/M0ORoEU115o)
@cvillecsteele @deoxxa This is something I'd be very interested in as well. I worked around the issue you described in my project (github.com/gen0cide/gscript/compiler) which essentially "links" Go packages into JS land and instruments a custom otto VM with all the glue.
I'd be interested in understanding how we might be able to marry some of these efforts together.
I don't think there's any issue linking pkg.NewMagician("foo")
into the runtime as is. My bigger issue was more around instantiation of new object types. I defined a Create()
function inside of my runtime with pointers to my NativeType
definition which includes a cumbersome, but working Factory
to initialize a new object in memory.
REF: https://github.com/gen0cide/gscript/blob/master/engine/native_package.go#L55
Is there a roadmap or sketch around what's next for Otto? Curious how this work might fit in.
Cheers!
In runtime.go,
convertCallParameter()
does a decent job of doing what it can. But sometimes I need more. I don't want to write silly wrapper functions, say, to convert astring
into anio.Writer
. Let me provide the runtime with a user-defined conversion function, whichconvertCallParameter()
can fall back to if it can't figure out what to do. #