glu

package module
v2.0.5 Latest Latest
Warning

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

Go to latest
Published: Oct 3, 2023 License: MIT Imports: 8 Imported by: 0

README

GLU (glucose) - gopher-lua module extensions

Summary

requires
  • go 1.17 (as gopher-lua required): under branch g17 with uri "github.com/ZenLiuCN/glu"
  • go 1.18 (with Generic): current master with uri "github.com/ZenLiuCN/glu/v2"

Packages

  1. glu the core module:
    1. Define helper Module and Type for easier register user library and user type;
    2. Define global LState pool for reuse;
    3. Define Registry for Modulars, with optional auto-injection;
    4. Support Help(string?) for help information;
  2. json dynamic json library base on Jeffail/gabs
  3. http http server and client library base on gorilla/mux, depends on json
  4. sqlx sqlx base on jmoiron/sqlx, depends on json, new in version v2.0.2

Samples

  1. use
package sample

import (
	"fmt"
	"github.com/ZenLiuCN/glu/v2"
	lua "github.com/yuin/gopher-lua"
)

func main() {
	fmt.Println(DoSomeScript("1+2") == 3.0)
}
func DoSomeScript(script string) float64 {
	vm := glu.Get()
	defer glu.Put(vm)
	if err := vm.DoString(script); err != nil {
		panic(err)
	}
	return float64(vm.Pop().(lua.LNumber))
}
  1. print help
       local http=require('http')
       local json=require('json')
       print(json.Help()) --will print comma split keyword list
       print(http.Help('?')) --will print module help
       print(http.Server.Help('?')) --will print type constructor help
       for word in string.gmatch(http.Server.Help(), '([^,]+)') do
          print(http.Server.Help(word)) --will print method constructor help
       end
       print(http.Ctx.Help('?'))
       for word in string.gmatch(http.Ctx.Help(), '([^,]+)') do
          print(http.Ctx.Help(word))
       end
    
  2. http server
    local http=require('http')
    local server=http.Server.new(':8081') --new Server with listen address
    server:get('/',chunk([[                -- the handler is string lua script
                local c=...                --only parameter is http.Ctx
                c:sendString(c:query('p')) --query should legal JSON string
            ]]))
    server:start(false)
    while (true) do	end
    
  3. http client
     local res,err=require('http').Client.new(5):get('http://github.com')
     print(err)
     if res:size()>0 then
     local txt=res:body()  
     print(txt)
     end 
    

Support this project

  1. offer your ideas

  2. fork and pull

License

MIT as gopher-lua did

Changes

Those are record start at version 2.0.2

  1. v2.0.2 :
    • add module sqlx with sqlx.DB,sqlx.Result
    • add function of(jsonString):Json in module json
  2. v2.0.3 :
    • adding sqlx.Tx,sqlx.Stmt,sqlx.NamedStmt to module sqlx
  3. v2.0.4 :
    • add Json:get(string|number) to module json, which will replace Json:at
    • add x:execMany and x:queryMany to module sqlx
    • add sqlx.encB64 and sqlx.decB64 to module sqlx for numeric issue
      • when use pgx for postgresql there will no such needs.
  4. v2.0.5 :
    • add sqlx:to_num and sqlx:from_num to module sqlx, which convert json array of objects numeric fields from|to binary

Documentation

Overview

Package glu support yuin/gopher-lua with easy modular definition and other enchantments. glu.Modular and gua.BaseType will inject mod.Help(name string?) method to output HelpCache information. glu.Get: Pool function to get a lua.LState. glu.Put: Pool function to return a lua.LState. glu.registry: shared module registry. glu.Auto: config for autoload modules in registry into lua.LState.

Example
// fetch an instance
vm := Get()
err := vm.DoString(`print('hello lua')`)
if err != nil {
	return
}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	FmtErrMissing = "required value at %d"
	FmtErrType    = "required type not match at %d"
)

generic functions

View Source
var (
	//HelpKey the module HelpCache key
	HelpKey = "?"
	//HelpFunc the help function name
	HelpFunc = "help"
	//HelpPrompt the prompt for no value supply for HelpCache
	HelpPrompt       = "show Help with those key word: "
	HelpChunk        = `chunk(code,name string)(Chunk?,string?) ==> pre compile string into bytecode`
	HelpHelp         = HelpFunc + `(topic string?)string? => fetch Help of topic,'?' show topics,without topic show loadable modules`
	HelpTopic        = `?,chunk`
	EagerHelpPrepare = false
)
View Source
var (
	ErrAlreadyExists            = errors.New("element already exists")
	ErrIndexOverrideWithMethods = errors.New("element both have methods and index overrides")
	ErrIsTop                    = errors.New("element is top module")
)
View Source
var (
	//Option LState configuration
	Option      = Options{}
	InitialSize = 4
)
View Source
var (
	//OpNone operator do nothing, better to use nil
	OpNone = func(s *Vm) error { return nil }
	//OpPush operator to push N value
	OpPush = func(n ...LValue) Operator {
		return func(s *Vm) error {
			for _, value := range n {
				s.Push(value)
			}
			return nil
		}
	}
	//OpPushUserData operator to push N UserDate
	OpPushUserData = func(n ...any) Operator {
		return func(s *Vm) error {
			for _, i := range n {
				ud := s.NewUserData()
				ud.Value = i
				s.Push(ud)
			}
			return nil
		}
	}
	//OpSafe operator to wrap as none error will happen
	OpSafe = func(fn func(s *Vm)) Operator {
		return func(s *Vm) error {
			fn(s)
			return nil
		}
	}
	//OpPop operator to pop and consume N value from start,then pop to n
	OpPop = func(fn func(value ...LValue), start, count int) Operator {
		if start < 0 || count <= 0 {
			panic("start must greater than 0 and count must greater than 0")
		}
		t := start + count
		return func(s *Vm) error {
			v := make([]LValue, 0, count)
			for i := start; i < t; i++ {
				v = append(v, s.Get(i))
			}
			s.Pop(t - 1)
			fn(v...)
			return nil
		}
	}
	//OpPopN operator to pop n value (Reset stack)
	OpPopN = func(count int) Operator {
		if count < 1 {
			panic("count must greater than 0")
		}
		return func(s *Vm) error {
			s.Pop(count)
			return nil
		}
	}
)
View Source
var (
	//Auto if true, will autoload modules in registry
	Auto = true
)
View Source
var (
	//BaseMod the global module
	BaseMod = glu(map[string]string{})
)
View Source
var (
	//ErrorSuppress not raise error ,use for SafeFunc
	ErrorSuppress = errors.New("")
)
View Source
var (

	// ExistNode is placeholder for a map set
	ExistNode = struct{}{}
)

Functions

func Check

func Check[T any](s *lua.LState, n int, def T, cast func(v lua.LValue) (val T, ok bool)) (T, bool)

func CheckBool

func CheckBool(s *lua.LState, n int) (bool, bool)

CheckBool return value and true only when value exists and is bool. Otherwise, an error raised.

func CheckFloat32

func CheckFloat32(s *lua.LState, n int) (float32, bool)

CheckFloat32 return value and true only when value exists and is exactly equals to the wanted number type. Returns converted number and false when value is number

func CheckFloat64

func CheckFloat64(s *lua.LState, n int) (float64, bool)

CheckFloat64 return value and true only when value exists and is exactly equals to the wanted number type.

func CheckInt

func CheckInt(s *lua.LState, n int) (int, bool)

CheckInt return value and true only when value exists and is exactly equals to the wanted number type. Returns converted number and false when value is number

func CheckInt16

func CheckInt16(s *lua.LState, n int) (int16, bool)

CheckInt16 return value and true only when value exists and is exactly equals to the wanted number type. Returns converted number and false when value is number

func CheckInt32

func CheckInt32(s *lua.LState, n int) (int32, bool)

CheckInt32 return value and true only when value exists and is exactly equals to the wanted number type. Returns converted number and false when value is number

func CheckInt64

func CheckInt64(s *lua.LState, n int) (int64, bool)

CheckInt64 return value and true only when value exists and is exactly equals to the wanted number type. Returns converted number and false when value is number

func CheckRecUserData

func CheckRecUserData[T any](s *lua.LState, ud *lua.LUserData, def T, cast func(v any) (val T, ok bool)) (T, bool)

CheckRecUserData check the receiver as userdata of wanted type.

func CheckString

func CheckString(s *lua.LState, n int) (string, bool)

CheckString return value and true only when value exists and is string. Otherwise, an error raised.

func CheckUserData

func CheckUserData[T any](s *lua.LState, n int, def T, cast func(v any) (val T, ok bool)) (T, bool)

CheckUserData return value and true only when value exists and can cast to the wanted type. Otherwise, an error raised.

func CompileChunk

func CompileChunk(code string, source string) (*FunctionProto, error)

CompileChunk compile code to FunctionProto

func ExecuteChunk

func ExecuteChunk(code *FunctionProto, argN, retN int, before Operator, after Operator) (err error)

ExecuteChunk execute pre complied FunctionProto

func ExecuteCode

func ExecuteCode(code string, argsN, retN int, before Operator, after Operator) error

ExecuteCode run code in LState, use before to push args, after to extract return value

func Failed

func Failed(err error)

Failed must have error or-else throw

func MakePool

func MakePool()

MakePool manual create statePool , when need to change Option, should invoke once before use Get and Put

func Pack

func Pack(v any, s *LState) LValue

Pack any to LValue.

1. nil, bool, numbers and other Lua value packed as normal LValue

2. array, slice,map[string]any packed into LTable (the elements also packed)

3. others are packed into LUserData

func Put

func Put(s *Vm)

Put LState back to statePool

func Raise added in v2.0.2

func Raise(s *lua.LState, act func() int) (ret int)

Raise recover panic and raise error to Lua

func Raw

func Raw(v LValue) any

Raw extract raw LValue: nil bool float64 string *LUserData *LState *LTable *LChannel

func Recover

func Recover(act func()) (err error)

Recover warp a callable func with recover

func RecoverErr

func RecoverErr(act func() error) (err error)

RecoverErr warp an error supplier func with recover

func Register

func Register(m ...Modular) (err error)

Register modular into registry

func SafeFunc

func SafeFunc(fn func(state *LState) int) LGFunction

SafeFunc no panic func

func SafeOpt

func SafeOpt(s *LState, at int, t LValueType) any

SafeOpt opt param with SafeFunc

func SafeParam

func SafeParam(s *LState, start int, types ...LValueType) (r []any)

SafeParam extra parameter must match type or panic,use with SafeFunc.

func Success

func Success(err error)

Success must have no error or-else throw

func TableToMap

func TableToMap(s *LTable) (r map[LValue]LValue)

TableToMap convert LTable to a Map with all key values

func TableToSlice

func TableToSlice(s *LTable) (r []LValue)

TableToSlice convert LTable to a Slice with all Number index values

func TableUnpack

func TableUnpack(s *LTable, noLua bool, history map[LValue]any) (r map[any]any, keys []any)

TableUnpack convert LTable to a Map with all key values

All keys and values may be:

LTNumber: float64

LTBool: bool

LTTable: map[any]any

LTString: string

(those type will not output with noLua=true )

LTFunction: *LFunction

LTUserData: *LUserData

LChannel: LChannel

Types

type BaseType

type BaseType[T any] struct {
	Mod      *Mod
	HelpCtor string
	// contains filtered or unexported fields
}

BaseType define a LTable with MetaTable, which mimicry class like action in Lua

func NewSimpleType

func NewSimpleType[T any](name string, help string, top bool) *BaseType[T]

NewSimpleType create new BaseType without ctor

func NewType

func NewType[T any](name string, help string, top bool, ctorHelp string, ctor func(*LState) (T, bool)) *BaseType[T]

NewType create new BaseType

func NewTypeCast

func NewTypeCast[T any](caster func(a any) (v T, ok bool), name string, help string, top bool, ctorHelp string, ctor func(s *LState) (v T, ok bool)) *BaseType[T]

NewTypeCast create new BaseType with reflect Signature

func (*BaseType[T]) AddField

func (m *BaseType[T]) AddField(name string, help string, value LValue) Type[T]

AddField add value field to this Modular

@name the field name

@HelpCache HelpCache string, if empty will not generate into HelpCache

@value the field value

func (*BaseType[T]) AddFunc

func (m *BaseType[T]) AddFunc(name string, help string, fn LGFunction) Type[T]

AddFunc add function to this Modular

@name function name, must match lua limitation

@HelpCache HelpCache string, if empty will not generate into HelpCache

@fn the LGFunction

func (*BaseType[T]) AddMethod

func (m *BaseType[T]) AddMethod(name string, help string, value LGFunction) Type[T]

AddMethod add method to this type which means instance method.

func (*BaseType[T]) AddMethodCast

func (m *BaseType[T]) AddMethodCast(name string, help string, act func(s *LState, data T) int) Type[T]

AddMethodCast prechecked type (only create with NewTypeCast).

func (*BaseType[T]) AddMethodUserData

func (m *BaseType[T]) AddMethodUserData(name string, help string, act func(s *LState, data *LUserData) int) Type[T]

AddMethodUserData add method to this type which means instance method, with auto extract first argument.

func (*BaseType[T]) AddModule

func (m *BaseType[T]) AddModule(mod Modular) Type[T]

AddModule add sub-module to this Modular

@mod the Mod **Note** must with TopLevel false.

func (BaseType[T]) CanCast

func (m BaseType[T]) CanCast() bool

CanCast check the type can use cast (when construct with NewTypeCast)

func (BaseType[T]) Cast

func (m BaseType[T]) Cast(s *LState) (T, bool)

func (BaseType[T]) CastUserData

func (m BaseType[T]) CastUserData(ud *LUserData, s *LState) (T, bool)

func (BaseType[T]) CastVar

func (m BaseType[T]) CastVar(s *LState, n int) (T, bool)

CastVar cast value on stack

func (*BaseType[T]) Caster

func (m *BaseType[T]) Caster() func(any) (T, bool)

func (*BaseType[T]) GetHelp

func (m *BaseType[T]) GetHelp() string

func (*BaseType[T]) GetName

func (m *BaseType[T]) GetName() string

func (BaseType[T]) New

func (m BaseType[T]) New(l *LState, val T) int

New wrap an instance into LState

func (BaseType[T]) NewValue

func (m BaseType[T]) NewValue(l *LState, val T) *LUserData

NewValue create new LValue

func (*BaseType[T]) Override

func (m *BaseType[T]) Override(op Operate, help string, fn LGFunction) Type[T]

Override operators an operator

func (*BaseType[T]) OverrideCast

func (m *BaseType[T]) OverrideCast(op Operate, help string, act func(s *LState, data T) int) Type[T]

OverrideCast see Override and AddMethodCast

func (*BaseType[T]) OverrideUserData

func (m *BaseType[T]) OverrideUserData(op Operate, help string, act func(s *LState, data *LUserData) int) Type[T]

OverrideUserData see Override and AddMethodUserData

func (*BaseType[T]) PreLoad

func (m *BaseType[T]) PreLoad(l *LState)

func (*BaseType[T]) PreloadSubModule

func (m *BaseType[T]) PreloadSubModule(l *LState, t *LTable)

func (*BaseType[T]) SafeFun

func (m *BaseType[T]) SafeFun(name string, help string, fn LGFunction) Type[T]

SafeFun warp with SafeFunc

func (*BaseType[T]) SafeMethod

func (m *BaseType[T]) SafeMethod(name string, help string, value LGFunction) Type[T]

SafeMethod warp with SafeFunc

func (*BaseType[T]) SafeOverride

func (m *BaseType[T]) SafeOverride(op Operate, help string, fn LGFunction) Type[T]

SafeOverride wrap with SafeFunc

func (*BaseType[T]) TopLevel

func (m *BaseType[T]) TopLevel() bool

type Chunk

type Chunk = *FunctionProto

type Mod

type Mod struct {
	Name string //Name of Modular
	Top  bool   //is top level
	Help string //Help information of this Modular

	Submodules []Modular //registered sub modules

	HelpCache map[string]string //exported helps for better use
	// contains filtered or unexported fields
}

Mod define a Mod only contains Functions and value fields,maybe with Submodules

func NewModule

func NewModule(name string, help string, top bool) *Mod

NewModule create New Mod

func (*Mod) AddField

func (m *Mod) AddField(name string, help string, value LValue) Module

AddField add value field to this Modular

@name the field name

@HelpCache HelpCache string, if empty will not generate into HelpCache

@value the field value

func (*Mod) AddFunc

func (m *Mod) AddFunc(name string, help string, fn LGFunction) Module

AddFunc add function to this Modular

@name function name, must match lua limitation

@HelpCache HelpCache string, if empty will not generate into HelpCache

@fn the LGFunction

func (*Mod) AddModule

func (m *Mod) AddModule(mod Modular) Module

AddModule add sub-module to this Modular

@mod the Mod **Note** must with TopLevel false.

func (*Mod) GetHelp

func (m *Mod) GetHelp() string

func (*Mod) GetName

func (m *Mod) GetName() string

func (*Mod) PreLoad

func (m *Mod) PreLoad(l *LState)

func (*Mod) PreloadSubModule

func (m *Mod) PreloadSubModule(l *LState, t *LTable)

func (*Mod) SafeFun

func (m *Mod) SafeFun(name string, help string, fn LGFunction) Module

SafeFun warp with SafeFunc

func (*Mod) TopLevel

func (m *Mod) TopLevel() bool

type Modular

type Modular interface {
	//TopLevel dose this Mod is top level,means should not be submodule
	TopLevel() bool
	//PreLoad load as global Mod
	PreLoad(l *lua.LState)
	//PreloadSubModule use for submodule loading, Should NOT invoke manually
	PreloadSubModule(l *lua.LState, t *lua.LTable)
	//GetName the unique name (if is a Top Level Modular)
	GetName() string
	//GetHelp Modular HelpCache info
	GetHelp() string
}

Modular shared methods make it a Modular

type Module

type Module interface {
	Modular
	// AddFunc add function to this Module
	//
	// @name function name, must match lua limitation
	//
	// @HelpCache HelpCache string, if empty will generate just Module.Function as HelpCache
	//
	// @fn the LGFunction
	AddFunc(name string, help string, fn LGFunction) Module

	//SafeFun warp with SafeFunc,see AddFunc for detail
	SafeFun(name string, help string, value LGFunction) Module

	// AddField add value field to this Module (static value)
	AddField(name string, help string, value LValue) Module
	// AddModule add submodule to this Module
	//
	// @mod the Mod , requires Mod.TopLevel is false.
	AddModule(mod Modular) Module
}

type Operate

type Operate int
const (
	OPERATE_INVALID   Operate = iota
	OPERATE_ADD               // +
	OPERATE_SUB               // -
	OPERATE_MUL               // *
	OPERATE_DIV               // /
	OPERATE_UNM               // -
	OPERATE_MOD               // %
	OPERATE_POW               // ^
	OPERATE_CONCAT            // ..
	OPERATE_EQ                // ==
	OPERATE_LT                // <
	OPERATE_LE                // <=
	OPERATE_LEN               // #
	OPERATE_INDEX             // []
	OPERATE_NEWINDEX          // []=
	OPERATE_TO_STRING         // tostring
	OPERATE_CALL              // ()
)

noinspection GoSnakeCaseUsage,GoUnusedConst

type Operator

type Operator = func(s *Vm) error

Operator operate stored state

type Prepare

type Prepare interface {
	// contains filtered or unexported methods
}

type Type

type Type[T any] interface {
	Modular

	// New create new instance and push on stack
	New(l *LState, val T) int
	// NewValue create new LValue
	NewValue(l *LState, val T) *LUserData
	// CanCast check the type can use cast (when construct with NewTypeCast)
	CanCast() bool
	// CastVar  cast value on stack (already have error processed)
	CastVar(s *LState, n int) (T, bool)
	// Cast  receiver on stack (already have error processed)
	Cast(s *LState) (T, bool)
	// CastUserData cast UserData (already have error processed)
	CastUserData(ud *LUserData, s *LState) (T, bool)
	// Caster  cast value
	Caster() func(any) (T, bool)

	// AddFunc static function
	AddFunc(name string, help string, fn LGFunction) Type[T]
	//SafeFun warp with SafeFunc
	SafeFun(name string, help string, value LGFunction) Type[T]

	// AddField static field
	AddField(name string, help string, value LValue) Type[T]
	//SafeMethod warp with SafeFunc
	SafeMethod(name string, help string, value LGFunction) Type[T]
	// AddMethod add method to this type which means instance method.
	AddMethod(name string, help string, value LGFunction) Type[T]

	// AddMethodUserData add method to this type which means instance method, with auto extract first argument.
	AddMethodUserData(name string, help string, act func(s *LState, u *LUserData) int) Type[T]

	// AddMethodCast prechecked type (only create with NewTypeCast).
	AddMethodCast(name string, help string, act func(s *LState, i T) int) Type[T]

	// Override operators an operator
	Override(op Operate, help string, fn LGFunction) Type[T]

	//SafeOverride warp with SafeFunc
	SafeOverride(op Operate, help string, value LGFunction) Type[T]

	// OverrideUserData see Override and AddMethodUserData
	OverrideUserData(op Operate, help string, act func(s *LState, u *LUserData) int) Type[T]

	// OverrideCast see Override and AddMethodCast
	OverrideCast(op Operate, help string, act func(s *LState, i T) int) Type[T]
}

type Vm

type Vm struct {
	*LState
	// contains filtered or unexported fields
}

Vm take Env Snapshot to protect from Global pollution

func Get

func Get() *Vm

Get LState from statePool

func (*Vm) OpenLibsWithout

func (s *Vm) OpenLibsWithout(names ...string) *Vm

OpenLibsWithout open gopher-lua libs but filter some by name @fluent

func (*Vm) Polluted

func (s *Vm) Polluted() (r bool)

Polluted check if the Env is polluted

func (*Vm) Reset

func (s *Vm) Reset() (r *Vm)

Reset reset Env @fluent

func (*Vm) Snapshot

func (s *Vm) Snapshot() *Vm

Snapshot take snapshot for Env

func (*Vm) TabChildEqualTo

func (s *Vm) TabChildEqualTo(t1 *LTable, t2 *LTable, keys ...string) (r bool)

func (*Vm) TabCopyChildNew

func (s *Vm) TabCopyChildNew(f *LTable, keys ...string) *LTable

func (*Vm) TabCopyNew

func (s *Vm) TabCopyNew(f *LTable) *LTable

func (*Vm) TabEqualTo

func (s *Vm) TabEqualTo(t1 *LTable, t2 *LTable) (r bool)

type VmPool

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

VmPool threadsafe LState Pool

func CreatePool

func CreatePool() *VmPool

func CreatePoolWith

func CreatePoolWith(ctor func() *LState) *VmPool

CreatePoolWith create pool with user defined constructor

BaseMod will auto registered

func (*VmPool) Get

func (pl *VmPool) Get() *Vm

func (*VmPool) Put

func (pl *VmPool) Put(L *Vm)

func (*VmPool) Recycle

func (pl *VmPool) Recycle(max int)

Recycle the pool space to max size

func (*VmPool) Shutdown

func (pl *VmPool) Shutdown()

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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