Documentation
¶
Index ¶
- Constants
- Variables
- func Decode(out interface{}, v Value) error
- func Must[T any](val T, err error) T
- func MustToGo[T SupportedTypes](value Value) T
- func MustToGoArray[T SupportedTypes](array Values) []T
- func ToGo[T SupportedTypes](value Value) (T, error)
- func ToGoArray[T SupportedTypes](array Values) ([]T, error)
- func ToGoMap[K SupportedComparables, V SupportedTypes](hash Hash) (map[K]V, error)
- type ArenaIndex
- type ArgSpec
- type Class
- type CompileContext
- type ExceptionError
- type Func
- type GRuby
- func (g *GRuby) ArenaRestore(idx ArenaIndex)
- func (g *GRuby) ArenaSave() ArenaIndex
- func (g *GRuby) Backtrace() []string
- func (g *GRuby) CalledFromFile() string
- func (g *GRuby) Class(name string, super *Class) *Class
- func (g *GRuby) Close()
- func (g *GRuby) ConstDefined(name string, scope Value) bool
- func (g *GRuby) DefineClass(name string, super *Class) *Class
- func (g *GRuby) DefineClassUnder(name string, super *Class, outer *Class) *Class
- func (g *GRuby) DefineModule(name string) *Class
- func (g *GRuby) DefineModuleUnder(name string, outer *Class) *Class
- func (g *GRuby) DisableGC()
- func (g *GRuby) EnableGC()
- func (g *GRuby) FalseValue() Value
- func (g *GRuby) FullGC()
- func (g *GRuby) GetArgs() Values
- func (g *GRuby) GetGlobalVariable(name string) Value
- func (g *GRuby) IncrementalGC()
- func (g *GRuby) KernelModule() *Class
- func (g *GRuby) LiveObjectCount() int
- func (g *GRuby) LoadFile(path string, content string) (bool, *CompileContext, error)
- func (g *GRuby) LoadString(code string) (Value, error)
- func (g *GRuby) LoadStringWithContext(code string, ctx *CompileContext) (Value, error)
- func (g *GRuby) Module(name string) *Class
- func (g *GRuby) NilValue() Value
- func (g *GRuby) ObjectClass() *Class
- func (g *GRuby) Run(v Value, self Value) (Value, error)
- func (g *GRuby) RunWithContext(v Value, self Value, stackKeep int) (int, Value, error)
- func (g *GRuby) SetGlobalVariable(name string, value Value)
- func (g *GRuby) TopSelf() Value
- func (g *GRuby) TrueValue() Value
- func (g *GRuby) Yield(block Value, args ...Value) (Value, error)
- type GValue
- func (v *GValue) CValue() C.mrb_value
- func (v *GValue) Call(method string, args ...Value) (Value, error)
- func (v *GValue) CallBlock(method string, args ...Value) (Value, error)
- func (v *GValue) Class() *Class
- func (v *GValue) GCProtect()
- func (v *GValue) GRuby() *GRuby
- func (v *GValue) GetInstanceVariable(variable string) Value
- func (v *GValue) IsDead() bool
- func (v *GValue) SetInstanceVariable(variable string, value Value)
- func (v *GValue) SetProcTargetClass(c *Class)
- func (v *GValue) SingletonClass() *Class
- func (v *GValue) String() string
- func (v *GValue) Type() ValueType
- type Hash
- type MethodType
- type Mutator
- type Parser
- type ParserError
- type ParserMessage
- type SupportedComparables
- type SupportedTypes
- type Value
- type ValueMap
- type ValueType
- type Values
Examples ¶
Constants ¶
const ( MethodTypeInstance = iota MethodTypeClass )
const ( // TypeFalse is `false` TypeFalse = ValueType(C.MRB_TT_FALSE) // TypeTrue is `true` TypeTrue = ValueType(C.MRB_TT_TRUE) // TypeFloat is any floating point number such as 1.2, etc. TypeFloat = ValueType(C.MRB_TT_FLOAT) // TypeFixnum is fixnums, or integers for this case. TypeFixnum = ValueType(C.MRB_TT_FIXNUM) // TypeSymbol is for entities in ruby that look like `:this` TypeSymbol = ValueType(C.MRB_TT_SYMBOL) // TypeUndef is a value internal to ruby for uninstantiated vars. TypeUndef = ValueType(C.MRB_TT_UNDEF) // TypeCptr is a void* TypeCptr = ValueType(C.MRB_TT_CPTR) // TypeFree is ? TypeFree = ValueType(C.MRB_TT_FREE) // TypeClass is the base class of all classes. TypeObject = ValueType(C.MRB_TT_OBJECT) // TypeClass is the base class of all classes. TypeClass = ValueType(C.MRB_TT_CLASS) // TypeModule is the base class of all Modules. TypeModule = ValueType(C.MRB_TT_MODULE) // TypeIClass is ? TypeIClass = ValueType(C.MRB_TT_ICLASS) // TypeSClass is ? TypeSClass = ValueType(C.MRB_TT_SCLASS) // TypeProc are procs (concrete block definitons) TypeProc = ValueType(C.MRB_TT_PROC) // TypeArray is [] TypeArray = ValueType(C.MRB_TT_ARRAY) // TypeHash is { } TypeHash = ValueType(C.MRB_TT_HASH) // TypeString is "" TypeString = ValueType(C.MRB_TT_STRING) // TypeRange is (0..x) TypeRange = ValueType(C.MRB_TT_RANGE) // TypeException is raised when using the raise keyword TypeException = ValueType(C.MRB_TT_EXCEPTION) // TypeEnv is for getenv/setenv etc TypeEnv = ValueType(C.MRB_TT_ENV) // TypeData is ? TypeData = ValueType(C.MRB_TT_DATA) // TypeFiber is for members of the Fiber class TypeFiber = ValueType(C.MRB_TT_FIBER) // TypeIsStruct is ? TypeIsStruct = ValueType(C.MRB_TT_STRUCT) // TypeMaxBreak is ? TypeBreak = ValueType(C.MRB_TT_BREAK) // TypeMaxDefine is ? TypeMaxDefine = ValueType(C.MRB_TT_MAXDEFINE) // TypeNil is nil TypeNil ValueType = 0xffffffff )
Variables ¶
var ( ErrValueMustBePointer = errors.New("result must be a pointer") ErrUnknownType = errors.New("unknown type") ErrNonStringKeys = errors.New("keys must be strings") ErrInvalidField = errors.New("field is not valid") )
var ErrEmptyArgs = errors.New("args must be non-empty and have a proc at the end")
Functions ¶
func Decode ¶
Decode converts the Ruby value to a Go value.
The Decode process may call Ruby code and may generate Ruby garbage, but it collects all of its own garbage. You don't need to GC around this.
See the tests (decode_test.go) for detailed and specific examples of how this function decodes. Basic examples are also available here and in the README.
For primitives, the decoding process is likely what you expect. For Ruby, this is booleans, strings, fixnums, and floats. These map directly to effectively equivalent Go types: bool, string, int, float64. Hash and Arrays can map directly to maps and slices in Go, and Decode will handle this as you expect.
The only remaining data type in Go is a struct. A struct in Go can map to any object in Ruby. If the data in Ruby is a hash, then the struct keys will map directly to the hash keys. If the data in Ruby is an object, then one of two things will be done. First: if the object responds to the `to_gomruby` function, then this will be called and the resulting value is expected to be a Hash and will be used to decode into the struct. If the object does NOT respond to that function, then any struct fields will invoke the corresponding Ruby method to attain the value.
Note that with structs you can use the `mruby` tag to specify the Hash key or method name to call. Example:
type Foo struct {
Field string `mruby:"read_field"`
}
Example ¶
package main
import (
"fmt"
"github.com/zhulik/gruby"
)
func main() {
grb := gruby.Must(gruby.New())
defer grb.Close()
// Our custom function we'll expose to Ruby
var logData interface{}
logFunc := func(grb *gruby.GRuby, self gruby.Value) (gruby.Value, gruby.Value) {
args := grb.GetArgs()
if err := gruby.Decode(&logData, args[0]); err != nil {
panic(err)
}
return nil, nil
}
// Lets define a custom class and a class method we can call.
class := grb.DefineClass("Example", nil)
class.DefineClassMethod("log", logFunc, gruby.ArgsReq(1))
// Let's call it and inspect the result
if _, err := grb.LoadString(`Example.log({"foo" => "bar"})`); err != nil {
panic(err)
}
fmt.Printf("Result: %v\n", logData)
}
Output: Result: map[foo:bar]
func MustToGo ¶
func MustToGo[T SupportedTypes](value Value) T
func MustToGoArray ¶
func MustToGoArray[T SupportedTypes](array Values) []T
func ToGo ¶
func ToGo[T SupportedTypes](value Value) (T, error)
func ToGoMap ¶
func ToGoMap[K SupportedComparables, V SupportedTypes](hash Hash) (map[K]V, error)
TODO: Must version
Types ¶
type ArenaIndex ¶
type ArenaIndex int
ArenaIndex represents the index into the arena portion of the GC.
See ArenaSave for more information.
type ArgSpec ¶
ArgSpec defines how many arguments a function should take and what kind. Multiple ArgSpecs can be combined using the "|" operator.
func ArgsArg ¶
ArgsArg says the given number of arguments are required and the second number is optional.
type Class ¶
type Class struct {
Value
// contains filtered or unexported fields
}
Class is a class in gruby. To obtain a Class, use DefineClass or one of the variants on the GRuby structure.
func (*Class) DefineClassMethod ¶
DefineClassMethod defines a class-level method on the given class.
func (*Class) DefineConst ¶
DefineConst defines a constant within this class.
func (*Class) DefineMethod ¶
DefineMethod defines an instance method on the class.
type CompileContext ¶
type CompileContext struct {
// contains filtered or unexported fields
}
CompileContext represents a context for code compilation.
CompileContexts keep track of things such as filenames, line numbers, as well as some settings for how to parse and execute code.
Example ¶
package main
import (
"fmt"
"github.com/zhulik/gruby"
)
func main() {
grb := gruby.Must(gruby.New())
defer grb.Close()
ctx1 := gruby.NewCompileContext(grb)
defer ctx1.Close()
ctx1.SetFilename("foo.rb")
ctx2 := gruby.NewCompileContext(grb)
defer ctx2.Close()
ctx2.SetFilename("bar.rb")
parser := gruby.NewParser(grb)
defer parser.Close()
if _, err := parser.Parse("def foo; bar; end", ctx1); err != nil {
panic(err)
}
code1 := parser.GenerateCode()
if _, err := parser.Parse("def bar; 42; end", ctx2); err != nil {
panic(err)
}
code2 := parser.GenerateCode()
if _, err := grb.Run(code1, nil); err != nil {
panic(err)
}
if _, err := grb.Run(code2, nil); err != nil {
panic(err)
}
result, err := grb.LoadString("foo")
if err != nil {
panic(err)
}
fmt.Printf("Result: %s\n", result)
}
Output: Result: 42
func NewCompileContext ¶
func NewCompileContext(grb *GRuby) *CompileContext
NewCompileContext constructs a *CompileContext from a *GRuby
func (*CompileContext) CaptureErrors ¶
func (c *CompileContext) CaptureErrors(yes bool)
CaptureErrors toggles the capture errors feature of the parser, which swallows errors. This allows repls and other partial parsing tools (formatters, f.e.) to function.
func (*CompileContext) Close ¶
func (c *CompileContext) Close()
Close the context, freeing any resources associated with it.
This is safe to call once the context has been used for parsing/loading any Ruby code.
func (*CompileContext) Filename ¶
func (c *CompileContext) Filename() string
Filename returns the filename associated with this context.
func (*CompileContext) SetFilename ¶
func (c *CompileContext) SetFilename(f string)
SetFilename sets the filename associated with this compilation context.
Code parsed under this context will be from this file.
type ExceptionError ¶
ExceptionError is a special type of value that represents an error and implements the Error interface.
func (*ExceptionError) Error ¶
func (e *ExceptionError) Error() string
type Func ¶
Func is the signature of a function in Go that you use to expose to Ruby code.
The first return value is the actual return value for the code.
The second return value is an exception, if any. This will be raised.
type GRuby ¶
type GRuby struct {
// contains filtered or unexported fields
}
GRuby represents a single instance of gruby.
func New ¶
New creates a new instance of GRuby, representing the state of a single Ruby VM. Calls mutators one after another against newly created instance. If a mutator fails, closes the mruby instance and returns an error.
When you're finished with the VM, clean up all resources it is using by calling the Close method.
func (*GRuby) ArenaRestore ¶
func (g *GRuby) ArenaRestore(idx ArenaIndex)
ArenaRestore restores the arena index so the objects between the save and this point can be garbage collected in the future.
See ArenaSave for more documentation.
func (*GRuby) ArenaSave ¶
func (g *GRuby) ArenaSave() ArenaIndex
ArenaSave saves the index into the arena.
Restore the arena index later by calling ArenaRestore.
The arena is where objects returned by functions such as LoadString are stored. By saving the index and then later restoring it with ArenaRestore, these objects can be garbage collected. Otherwise, the objects will never be garbage collected.
The recommended usage pattern for memory management is to save the arena index prior to any Ruby execution, to turn the resulting Ruby value into Go values as you see fit, then to restore the arena index so that GC can collect any values.
Of course, when Close() is called, all objects in the arena are garbage collected anyways, so if you're only calling mruby for a short period of time, you might not have to worry about saving/restoring the arena.
func (*GRuby) Backtrace ¶
When called from a instanceMethods defined in Go, returns current ruby backtrace.
func (*GRuby) CalledFromFile ¶
When called from a method defined in Go, returns a full name of a file the method was called from. Currently implemented using the backtrace. TODO: a better way?
func (*GRuby) Class ¶
Class returns the class with the kgiven name and superclass. Note that if you call this with a class that doesn't exist, mruby will abort the application (like a panic, but not a Go panic).
super can be nil, in which case the Object class will be used.
func (*GRuby) Close ¶
func (g *GRuby) Close()
Close a Gruby, this must be called to properly free resources, and should only be called once.
func (*GRuby) ConstDefined ¶
ConstDefined checks if the given constant is defined in the scope.
This should be used, for example, before a call to Class, because a failure in Class will crash your program (by design). You can retrieve the Value of a Class by calling Value().
func (*GRuby) DefineClass ¶
DefineClass defines a new top-level class.
If super is nil, the class will be defined under Object.
Example ¶
package main
import (
"fmt"
"github.com/zhulik/gruby"
)
func main() {
grb := gruby.Must(gruby.New())
defer grb.Close()
// Our custom function we'll expose to Ruby
addFunc := func(grb *gruby.GRuby, self gruby.Value) (gruby.Value, gruby.Value) {
args := grb.GetArgs()
return gruby.MustToRuby(grb, gruby.MustToGo[int](args[0])+gruby.MustToGo[int](args[1])), nil
}
// Lets define a custom class and a class method we can call.
class := grb.DefineClass("Example", nil)
class.DefineClassMethod("add", addFunc, gruby.ArgsReq(2))
// Let's call it and inspect the result
result, err := grb.LoadString(`Example.add(12, 30)`)
if err != nil {
panic(err)
}
fmt.Printf("Result: %s\n", result.String())
}
Output: Result: 42
func (*GRuby) DefineClassUnder ¶
DefineClassUnder defines a new class under another class.
This is, for example, how you would define the World class in `Hello::World` where Hello is the "outer" class.
func (*GRuby) DefineModule ¶
DefineModule defines a top-level module.
func (*GRuby) DefineModuleUnder ¶
DefineModuleUnder defines a module under another class/module.
func (*GRuby) DisableGC ¶
func (g *GRuby) DisableGC()
DisableGC disables the garbage collector for this mruby instance. It returns true if it was previously disabled.
func (*GRuby) EnableGC ¶
func (g *GRuby) EnableGC()
EnableGC enables the garbage collector for this mruby instance. It returns true if garbage collection was previously disabled.
func (*GRuby) FalseValue ¶
FalseValue returns a Value for "false"
func (*GRuby) GetArgs ¶
GetArgs returns all the arguments that were given to the currnetly called function (currently on the stack).
func (*GRuby) GetGlobalVariable ¶
GetGlobalVariable returns the value of the global variable by the given name.
func (*GRuby) IncrementalGC ¶
func (g *GRuby) IncrementalGC()
IncrementalGC runs an incremental GC step. It is much less expensive than a FullGC, but must be called multiple times for GC to actually happen.
This function is best called periodically when executing Ruby in the VM many times (thousands of times).
func (*GRuby) KernelModule ¶
KernelModule returns the Kernel top-level module.
func (*GRuby) LiveObjectCount ¶
LiveObjectCount returns the number of objects that have not been collected (aka, alive).
func (*GRuby) LoadString ¶
LoadString loads the given code, executes it, and returns its final value that it might return.
func (*GRuby) LoadStringWithContext ¶
func (g *GRuby) LoadStringWithContext(code string, ctx *CompileContext) (Value, error)
LoadStringWith loads the given code, executes it within the given context, and returns its final value that it might return.
func (*GRuby) Module ¶
Module returns the named module as a *Class. If the module is invalid, NameError is triggered within your program and SIGABRT is sent to the application.
func (*GRuby) ObjectClass ¶
ObjectClass returns the Object top-level class.
func (*GRuby) Run ¶
Run executes the given value, which should be a proc type.
If you're looking to execute code directly a string, look at LoadString.
If self is nil, it is set to the top-level self.
func (*GRuby) RunWithContext ¶
RunWithContext is a context-aware parser (aka, it does not discard state between runs). It returns a magic integer that describes the stack in place, so that it can be re-used on the next call. This is how local variables can traverse ruby parse invocations.
Otherwise, it is very similar in function to Run()
func (*GRuby) SetGlobalVariable ¶
SetGlobalVariable sets the value of the global variable by the given name.
type GValue ¶
type GValue struct {
// contains filtered or unexported fields
}
GValue is a "value" internally in gruby. A "value" is what mruby calls basically anything in Ruby: a class, an object (instance), a variable, etc.
func (*GValue) CallBlock ¶
CallBlock is the same as call except that it expects the last argument to be a Proc that will be passed into the function call. It is an error if args is empty or if there is no block on the end.
func (*GValue) GCProtect ¶
func (v *GValue) GCProtect()
GCProtect protects this value from being garbage collected.
func (*GValue) GetInstanceVariable ¶
GetInstanceVariable gets an instance variable on this value.
func (*GValue) SetInstanceVariable ¶
SetInstanceVariable sets an instance variable on this value.
func (*GValue) SetProcTargetClass ¶
SetProcTargetClass sets the target class where a proc will be executed when this value is a proc.
func (*GValue) SingletonClass ¶
SingletonClass returns the singleton class (a class isolated just for the scope of the object) for the given value.
type Hash ¶
type Hash struct {
Value
}
Hash represents an GValue that is a Hash in Ruby.
A Hash can be obtained by calling the Hash function on GValue.
func (*Hash) Delete ¶
Delete deletes a key from the hash, returning its existing value, or nil if there wasn't a value.
type MethodType ¶
type MethodType = int
type Mutator ¶
Mutator is function that is supposed to be passed to New. New will call mutators one after another. They can be used to register classes and functions provided by external packages.
type Parser ¶
type Parser struct {
// contains filtered or unexported fields
}
Parser is a parser for Ruby code.
func NewParser ¶
NewParser initializes the resources for a parser.
Make sure to Close the parser when you're done with it.
func (*Parser) Close ¶
func (p *Parser) Close()
Close releases any resources associated with the parser.
func (*Parser) GenerateCode ¶
GenerateCode takes all the internal parser state and generates executable Ruby code, returning the callable proc.
func (*Parser) Parse ¶
func (p *Parser) Parse(code string, cctx *CompileContext) ([]*ParserMessage, error)
Parse parses the code in the given context, and returns any warnings or errors from parsing.
The CompileContext can be nil to not set a context.
type ParserError ¶
type ParserError struct {
Errors []*ParserMessage
}
ParserError is an error from the parser.
func (ParserError) Error ¶
func (p ParserError) Error() string
func (ParserError) String ¶
func (p ParserError) String() string
type ParserMessage ¶
ParserMessage represents a message from parsing code: a warning or error.
type SupportedComparables ¶
type SupportedTypes ¶
type SupportedTypes interface {
SupportedComparables | Hash | Values
}
TODO: make sure all supported types covered in functions.
type Value ¶
type Value interface {
String() string
GRuby() *GRuby
CValue() C.mrb_value
Type() ValueType
IsDead() bool
Class() *Class
SingletonClass() *Class
SetInstanceVariable(variable string, value Value)
GetInstanceVariable(variable string) Value
Call(method string, args ...Value) (Value, error)
CallBlock(method string, args ...Value) (Value, error)
}
Value is an interface that should be implemented by anything that can be represents as an mruby value.
func MustToRuby ¶
func MustToRuby[T SupportedTypes](grb *GRuby, value T) Value