mruby

package module
v0.0.0-...-207cedc Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 15, 2020 License: MIT Imports: 10 Imported by: 27

README

mruby Library for Go Build Status

go-mruby provides mruby bindings for Go. This allows Go applications to run a lightweight embedded Ruby VM. Using the mruby library, Go applications can call Ruby code, and Ruby code can call Go code (that is properly exposed)!

At the time of writing, this is the most comprehensive mruby library for Go by far. It is also the only mruby library for Go that enables exposing Go functions to Ruby as well as being able to generically convert complex Ruby types into Go types. Our goal is to implement all of the mruby API.

Project Status: The major portions of the mruby API are implemented, but the mruby API is huge. If there is something that is missing, please issue a pull request and I'd be happy to add it! We're also not yet ready to promise API backwards compatibility on a Go-level, but we're getting there.

Installation

Installation is a little trickier than a standard Go library, but not by much. You can't simply go get this library, unfortunately. This is because mruby must first be built. We don't ship a pre-built version of mruby because the build step of mruby is important in customizing what aspects of the standard library you want available, as well as any other extensions.

To build mruby, we've made it very easy. You will need the following packages available on your host operating system:

  • bison
  • flex
  • ruby 2.x

Then just type:

$ make

This will download mruby, compile it, and run the tests for go-mruby, verifying that your build is functional. By default, go-mruby will download and build a default version of mruby, but this is customizable.

Compiling/installing the go-mruby library should work on Linux, Mac OS X, and Windows. On Windows, msys is the only supported build toolchain (same as Go itself).

Due to this linking, it is strongly recommended that you vendor this repository and bake our build system into your process.

Customizing the mruby Compilation

You can customize the mruby compilation by setting a couple environmental variables prior to calling make:

  • MRUBY_COMMIT is the git ref that will be checked out for mruby. This defaults to to a recently tagged version. Many versions before 1.2.0 do not work with go-mruby. It is recommend you explicitly set this to a ref that works for you to avoid any changes in this library later.

  • MRUBY_CONFIG is the path to a build_config.rb file used to configure how mruby is built. If this is not set, go-mruby will use the default build config that comes with mruby. You can learn more about configuring the mruby build here.

Usage

go-mruby exposes the mruby API in a way that is idiomatic Go, so that it is comfortable to use by a standard Go programmer without having intimate knowledge of how mruby works.

For usage examples and documentation, please see the go-mruby GoDoc, which we keep up to date and full of examples.

For a quick taste of what using go-mruby looks like, though, we provide an example below:

package main

import (
	"fmt"
	"github.com/mitchellh/go-mruby"
)

func main() {
	mrb := mruby.NewMrb()
	defer mrb.Close()

	// Our custom function we'll expose to Ruby. The first return
	// value is what to return from the func and the second is an
	// exception to raise (if any).
	addFunc := func(m *mruby.Mrb, self *mruby.MrbValue) (mruby.Value, mruby.Value) {
		args := m.GetArgs()
		return mruby.Int(args[0].Fixnum() + args[1].Fixnum()), nil
	}

	// Lets define a custom class and a class method we can call.
	class := mrb.DefineClass("Example", nil)
	class.DefineClassMethod("add", addFunc, mruby.ArgsReq(2))

	// Let's call it and inspect the result
	result, err := mrb.LoadString(`Example.add(12, 30)`)
	if err != nil {
		panic(err.Error())
	}

	// This will output "Result: 42"
	fmt.Printf("Result: %s\n", result.String())
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Decode

func Decode(out interface{}, v *MrbValue) error

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"`
}

Types

type ArenaIndex

type ArenaIndex int

ArenaIndex represents the index into the arena portion of the GC.

See ArenaSave for more information.

type ArgSpec

type ArgSpec C.mrb_aspec

ArgSpec defines how many arguments a function should take and what kind. Multiple ArgSpecs can be combined using the "|" operator.

func ArgsAny

func ArgsAny() ArgSpec

ArgsAny allows any number of arguments.

func ArgsArg

func ArgsArg(r, o int) ArgSpec

ArgsArg says the given number of arguments are required and the second number is optional.

func ArgsBlock

func ArgsBlock() ArgSpec

ArgsBlock says it takes a block argument.

func ArgsNone

func ArgsNone() ArgSpec

ArgsNone says it takes no arguments.

func ArgsOpt

func ArgsOpt(n int) ArgSpec

ArgsOpt says that the given number of arguments are optional.

func ArgsReq

func ArgsReq(n int) ArgSpec

ArgsReq says that the given number of arguments are required.

type Array

type Array struct {
	*MrbValue
}

Array represents an MrbValue that is a Array in Ruby.

A Array can be obtained by calling the Array function on MrbValue.

func (*Array) Get

func (v *Array) Get(idx int) (*MrbValue, error)

Get gets an element form the Array by index.

This does not copy the element. This is a pointer/reference directly to the element in the array.

func (*Array) Len

func (v *Array) Len() int

Len returns the length of the array.

type Class

type Class struct {
	// contains filtered or unexported fields
}

Class is a class in mruby. To obtain a Class, use DefineClass or one of the variants on the Mrb structure.

func (*Class) DefineClassMethod

func (c *Class) DefineClassMethod(name string, cb Func, as ArgSpec)

DefineClassMethod defines a class-level method on the given class.

func (*Class) DefineConst

func (c *Class) DefineConst(name string, value Value)

DefineConst defines a constant within this class.

func (*Class) DefineMethod

func (c *Class) DefineMethod(name string, cb Func, as ArgSpec)

DefineMethod defines an instance method on the class.

func (*Class) MrbValue

func (c *Class) MrbValue(m *Mrb) *MrbValue

MrbValue returns a *Value for this Class. *Values are sometimes required as arguments where classes should be valid.

func (*Class) New

func (c *Class) New(args ...Value) (*MrbValue, error)

New instantiates the class with the given args.

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.

func NewCompileContext

func NewCompileContext(m *Mrb) *CompileContext

NewCompileContext constructs a *CompileContext from a *Mrb.

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 Exception

type Exception struct {
	*MrbValue
	File      string
	Line      int
	Message   string
	Backtrace []string
}

Exception is a special type of value that represents an error and implements the Error interface.

func (*Exception) Error

func (e *Exception) Error() string

func (*Exception) String

func (e *Exception) String() string

type Func

type Func func(m *Mrb, self *MrbValue) (Value, Value)

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 Hash

type Hash struct {
	*MrbValue
}

Hash represents an MrbValue that is a Hash in Ruby.

A Hash can be obtained by calling the Hash function on MrbValue.

func (*Hash) Delete

func (h *Hash) Delete(key Value) (*MrbValue, error)

Delete deletes a key from the hash, returning its existing value, or nil if there wasn't a value.

func (*Hash) Get

func (h *Hash) Get(key Value) (*MrbValue, error)

Get reads a value from the hash.

func (*Hash) Keys

func (h *Hash) Keys() (*MrbValue, error)

Keys returns the array of keys that the Hash has. This is returned as an *MrbValue since this is a Ruby array. You can iterate over it as you see fit.

func (*Hash) Set

func (h *Hash) Set(key, val Value) error

Set sets a value on the hash

type Int

type Int int

Int is the basic ruby Integer type.

func (Int) MrbValue

func (i Int) MrbValue(m *Mrb) *MrbValue

MrbValue returns the native MRB value

type Mrb

type Mrb struct {
	// contains filtered or unexported fields
}

Mrb represents a single instance of mruby.

func NewMrb

func NewMrb() *Mrb

NewMrb creates a new instance of Mrb, representing the state of a single Ruby VM.

When you're finished with the VM, clean up all resources it is using by calling the Close method.

func (*Mrb) ArenaRestore

func (m *Mrb) 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 (*Mrb) ArenaSave

func (m *Mrb) 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 (*Mrb) Class

func (m *Mrb) Class(name string, super *Class) *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 (*Mrb) Close

func (m *Mrb) Close()

Close a Mrb, this must be called to properly free resources, and should only be called once.

func (*Mrb) ConstDefined

func (m *Mrb) ConstDefined(name string, scope Value) bool

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 (*Mrb) DefineClass

func (m *Mrb) DefineClass(name string, super *Class) *Class

DefineClass defines a new top-level class.

If super is nil, the class will be defined under Object.

func (*Mrb) DefineClassUnder

func (m *Mrb) DefineClassUnder(name string, super *Class, outer *Class) *Class

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 (*Mrb) DefineModule

func (m *Mrb) DefineModule(name string) *Class

DefineModule defines a top-level module.

func (*Mrb) DefineModuleUnder

func (m *Mrb) DefineModuleUnder(name string, outer *Class) *Class

DefineModuleUnder defines a module under another class/module.

func (*Mrb) DisableGC

func (m *Mrb) DisableGC()

DisableGC disables the garbage collector for this mruby instance. It returns true if it was previously disabled.

func (*Mrb) EnableGC

func (m *Mrb) EnableGC()

EnableGC enables the garbage collector for this mruby instance. It returns true if garbage collection was previously disabled.

func (*Mrb) FalseValue

func (m *Mrb) FalseValue() *MrbValue

FalseValue returns a Value for "false"

func (*Mrb) FixnumValue

func (m *Mrb) FixnumValue(v int) *MrbValue

FixnumValue returns a Value for a fixed number.

func (*Mrb) FullGC

func (m *Mrb) FullGC()

FullGC executes a complete GC cycle on the VM.

func (*Mrb) GetArgs

func (m *Mrb) GetArgs() []*MrbValue

GetArgs returns all the arguments that were given to the currnetly called function (currently on the stack).

func (*Mrb) GetGlobalVariable

func (m *Mrb) GetGlobalVariable(name string) *MrbValue

GetGlobalVariable returns the value of the global variable by the given name.

func (*Mrb) IncrementalGC

func (m *Mrb) 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 (*Mrb) KernelModule

func (m *Mrb) KernelModule() *Class

KernelModule returns the Kernel top-level module.

func (*Mrb) LiveObjectCount

func (m *Mrb) LiveObjectCount() int

LiveObjectCount returns the number of objects that have not been collected (aka, alive).

func (*Mrb) LoadString

func (m *Mrb) LoadString(code string) (*MrbValue, error)

LoadString loads the given code, executes it, and returns its final value that it might return.

func (*Mrb) Module

func (m *Mrb) Module(name string) *Class

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 (*Mrb) NilValue

func (m *Mrb) NilValue() *MrbValue

NilValue returns "nil"

func (*Mrb) ObjectClass

func (m *Mrb) ObjectClass() *Class

ObjectClass returns the Object top-level class.

func (*Mrb) Run

func (m *Mrb) Run(v Value, self Value) (*MrbValue, error)

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 (*Mrb) RunWithContext

func (m *Mrb) RunWithContext(v Value, self Value, stackKeep int) (int, *MrbValue, error)

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 (*Mrb) SetGlobalVariable

func (m *Mrb) SetGlobalVariable(name string, value Value)

SetGlobalVariable sets the value of the global variable by the given name.

func (*Mrb) StringValue

func (m *Mrb) StringValue(s string) *MrbValue

StringValue returns a Value for a string.

func (*Mrb) TopSelf

func (m *Mrb) TopSelf() *MrbValue

TopSelf returns the top-level `self` value.

func (*Mrb) TrueValue

func (m *Mrb) TrueValue() *MrbValue

TrueValue returns a Value for "true"

func (*Mrb) Yield

func (m *Mrb) Yield(block Value, args ...Value) (*MrbValue, error)

Yield yields to a block with the given arguments.

This should be called within the context of a Func.

type MrbValue

type MrbValue struct {
	// contains filtered or unexported fields
}

MrbValue is a "value" internally in mruby. A "value" is what mruby calls basically anything in Ruby: a class, an object (instance), a variable, etc.

func (*MrbValue) Array

func (v *MrbValue) Array() *Array

Array returns the Array value of this value. If the Type of the MrbValue is not a TypeArray, then this will panic. If the MrbValue has a `to_a` function, you must call that manually prior to calling this method.

func (*MrbValue) Call

func (v *MrbValue) Call(method string, args ...Value) (*MrbValue, error)

Call calls a method with the given name and arguments on this value.

func (*MrbValue) CallBlock

func (v *MrbValue) CallBlock(method string, args ...Value) (*MrbValue, error)

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 (*MrbValue) Class

func (v *MrbValue) Class() *Class

Class returns the *Class of a value.

func (*MrbValue) Fixnum

func (v *MrbValue) Fixnum() int

Fixnum returns the numeric value of this object if the Type() is TypeFixnum. Calling this with any other type will result in undefined behavior.

func (*MrbValue) Float

func (v *MrbValue) Float() float64

Float returns the numeric value of this object if the Type() is TypeFloat. Calling this with any other type will result in undefined behavior.

func (*MrbValue) GCProtect

func (v *MrbValue) GCProtect()

GCProtect protects this value from being garbage collected.

func (*MrbValue) GetInstanceVariable

func (v *MrbValue) GetInstanceVariable(variable string) *MrbValue

GetInstanceVariable gets an instance variable on this value.

func (*MrbValue) Hash

func (v *MrbValue) Hash() *Hash

Hash returns the Hash value of this value. If the Type of the MrbValue is not a ValueTypeHash, then this will panic. If the MrbValue has a `to_h` function, you must call that manually prior to calling this method.

func (*MrbValue) IsDead

func (v *MrbValue) IsDead() bool

IsDead tells you if an object has been collected by the GC or not.

func (*MrbValue) Mrb

func (v *MrbValue) Mrb() *Mrb

Mrb returns the Mrb state for this value.

func (*MrbValue) MrbValue

func (v *MrbValue) MrbValue(*Mrb) *MrbValue

MrbValue so that *MrbValue implements the "Value" interface.

func (*MrbValue) SetInstanceVariable

func (v *MrbValue) SetInstanceVariable(variable string, value *MrbValue)

SetInstanceVariable sets an instance variable on this value.

func (*MrbValue) SetProcTargetClass

func (v *MrbValue) SetProcTargetClass(c *Class)

SetProcTargetClass sets the target class where a proc will be executed when this value is a proc.

func (*MrbValue) SingletonClass

func (v *MrbValue) SingletonClass() *Class

SingletonClass returns the singleton class (a class isolated just for the scope of the object) for the given value.

func (*MrbValue) String

func (v *MrbValue) String() string

String returns the "to_s" result of this value.

func (*MrbValue) Type

func (v *MrbValue) Type() ValueType

Type returns the ValueType of the MrbValue. See the constants table.

type NilType

type NilType [0]byte

NilType is the object representation of NilClass

var Nil NilType

Nil is a constant that can be used as a Nil Value

func (NilType) MrbValue

func (NilType) MrbValue(m *Mrb) *MrbValue

MrbValue returns the native MRB value

type Parser

type Parser struct {
	// contains filtered or unexported fields
}

Parser is a parser for Ruby code.

func NewParser

func NewParser(m *Mrb) *Parser

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

func (p *Parser) GenerateCode() *MrbValue

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, c *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

type ParserMessage struct {
	Col     int
	Line    int
	Message string
}

ParserMessage represents a message from parsing code: a warning or error.

type String

type String string

String is objects of the type String.

func (String) MrbValue

func (s String) MrbValue(m *Mrb) *MrbValue

MrbValue returns the native MRB value

type Value

type Value interface {
	MrbValue(*Mrb) *MrbValue
}

Value is an interface that should be implemented by anything that can be represents as an mruby value.

type ValueType

type ValueType uint32

ValueType is an enum of types that a Value can be and is returned by Value.Type().

const (
	// TypeFalse is `false`
	TypeFalse ValueType = iota
	// TypeFree is ?
	TypeFree
	// TypeTrue is `true`
	TypeTrue
	// TypeFixnum is fixnums, or integers for this case.
	TypeFixnum
	// TypeSymbol is for entities in ruby that look like `:this`
	TypeSymbol
	// TypeUndef is a value internal to ruby for uninstantiated vars.
	TypeUndef
	// TypeFloat is any floating point number such as 1.2, etc.
	TypeFloat
	// TypeCptr is a void*
	TypeCptr
	// TypeObject is a standard ruby object, base class of most instantiated objects.
	TypeObject
	// TypeClass is the base class of all classes.
	TypeClass
	// TypeModule is the base class of all Modules.
	TypeModule
	// TypeIClass is ?
	TypeIClass
	// TypeSClass is ?
	TypeSClass
	// TypeProc are procs (concrete block definitons)
	TypeProc
	// TypeArray is []
	TypeArray
	// TypeHash is { }
	TypeHash
	// TypeString is ""
	TypeString
	// TypeRange is (0..x)
	TypeRange
	// TypeException is raised when using the raise keyword
	TypeException
	// TypeFile is for objects of the File class
	TypeFile
	// TypeEnv is for getenv/setenv etc
	TypeEnv
	// TypeData is ?
	TypeData
	// TypeFiber is for members of the Fiber class
	TypeFiber
	// TypeMaxDefine is ?
	TypeMaxDefine
	// TypeNil is nil
	TypeNil ValueType = 0xffffffff
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL