Skip to content

Commit

Permalink
feat: 添加了NativeObject; 为字典类型增加keys() values() items()方法
Browse files Browse the repository at this point in the history
  • Loading branch information
fy0 committed Sep 16, 2023
1 parent d55dd13 commit 8bafd5a
Show file tree
Hide file tree
Showing 15 changed files with 380 additions and 159 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ DiceScript将使用和RollVM相同的技术栈,但会有更好的接口设计

## 更新记录

#### 2023.9.15

* NativeObject 一种用于绑定Go对象的类型,行为类似于dict
* 为字典类型增加了 keys() values() items() 方法
* dir 函数,和python的dir函数类似,用于获取对象的所有属性

#### 2022.11.29

* 逻辑与/逻辑或/按位与/按位或
Expand Down
148 changes: 148 additions & 0 deletions builtin_functions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package dicescript

import (
"errors"
"math"
"strconv"
)

func funcCeil(ctx *Context, this *VMValue, params []*VMValue) *VMValue {
v, ok := params[0].ReadFloat()
if ok {
return VMValueNewInt(int64(math.Ceil(v)))
} else {
ctx.Error = errors.New("类型错误: 只能是float")
}
return nil
}

func funcRound(ctx *Context, this *VMValue, params []*VMValue) *VMValue {
v, ok := params[0].ReadFloat()
if ok {
return VMValueNewInt(int64(math.Round(v)))
} else {
ctx.Error = errors.New("类型错误: 只能是float")
}
return nil
}

func funcFloor(ctx *Context, this *VMValue, params []*VMValue) *VMValue {
v, ok := params[0].ReadFloat()
if ok {
return VMValueNewInt(int64(math.Floor(v)))
} else {
ctx.Error = errors.New("类型错误: 只能是float")
}
return nil
}

func funcAbs(ctx *Context, this *VMValue, params []*VMValue) *VMValue {
v := params[0]
switch v.TypeId {
case VMTypeInt:
val := v.MustReadInt()
if val < 0 {
return VMValueNewInt(-val)
}
return v
case VMTypeFloat:
val := v.MustReadFloat()
if val < 0 {
return VMValueNewFloat(-val)
}
return v
}

ctx.Error = errors.New("类型错误: 参数必须为int或float")
return nil
}

func funcInt(ctx *Context, this *VMValue, params []*VMValue) *VMValue {
switch params[0].TypeId {
case VMTypeInt:
return params[0]
case VMTypeFloat:
v, _ := params[0].ReadFloat()
return VMValueNewInt(int64(v))
case VMTypeString:
s, _ := params[0].ReadString()
val, err := strconv.ParseInt(s, 10, 64)
if err == nil {
return VMValueNewInt(val)
} else {
ctx.Error = errors.New("值错误: 无法进行 int() 转换: " + s)
}
default:
ctx.Error = errors.New("类型错误: 只能是数字类型")
}
return nil
}

func funcFloat(ctx *Context, this *VMValue, params []*VMValue) *VMValue {
switch params[0].TypeId {
case VMTypeInt:
v, _ := params[0].ReadInt()
return VMValueNewFloat(float64(v))
case VMTypeFloat:
return params[0]
case VMTypeString:
s, _ := params[0].ReadString()
val, err := strconv.ParseFloat(s, 64)
if err == nil {
return VMValueNewFloat(val)
} else {
ctx.Error = errors.New("值错误: 无法进行 float() 转换: " + s)
}
default:
ctx.Error = errors.New("类型错误: 只能是数字类型")
}
return nil
}

func funcStr(ctx *Context, this *VMValue, params []*VMValue) *VMValue {
return VMValueNewStr(params[0].ToString())
}

func funcDir(ctx *Context, this *VMValue, params []*VMValue) *VMValue {
typeId := params[0].TypeId
var arr []*VMValue
if v, ok := builtinProto[typeId]; ok {
v.Range(func(key string, value *VMValue) bool {
arr = append(arr, VMValueNewStr(key))
return true
})
}
if typeId == VMTypeNativeObject {
v := params[0]
d, _ := v.ReadNativeObjectData()
if d.DirFunc != nil {
arr = append(arr, d.DirFunc(ctx)...)
}
}
return VMValueNewArrayRaw(arr)
}

//
//func funcHelp(ctx *Context, this *VMValue, params []*VMValue) *VMValue {
// // 函数名,参数,说明
// return VMValueNewStr(params[0].ToString())
//}

var nnf = VMValueNewNativeFunction

type ndf = NativeFunctionData

var builtinValues = map[string]*VMValue{
"ceil": nnf(&ndf{"ceil", []string{"value"}, nil, nil, funcCeil}),
"floor": nnf(&ndf{"floor", []string{"value"}, nil, nil, funcFloor}),
"round": nnf(&ndf{"round", []string{"value"}, nil, nil, funcRound}),
"int": nnf(&ndf{"int", []string{"value"}, nil, nil, funcInt}),
"float": nnf(&ndf{"float", []string{"value"}, nil, nil, funcFloat}),
"str": nnf(&ndf{"str", []string{"value"}, nil, nil, funcStr}),
"abs": nnf(&ndf{"abs", []string{"value"}, nil, nil, funcAbs}),
// TODO: roll()

// 要不要进行权限隔绝?
"dir": nnf(&ndf{"dir", []string{"value"}, nil, nil, funcDir}),
//"help": nnf(&ndf{"help", []string{"value"}, nil, nil, funcHelp}),
}
File renamed without changes.
2 changes: 1 addition & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func main() {

re := regexp.MustCompile(`^(\D+)(\d+)$`)

vm.ValueLoadFunc = func(name string) *dice.VMValue {
vm.GlobalValueLoadFunc = func(name string) *dice.VMValue {
m := re.FindStringSubmatch(name)
if len(m) > 1 {
val, _ := strconv.ParseInt(m[2], 10, 64)
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/mattn/go-runewidth v0.0.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/sys v0.12.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
4 changes: 2 additions & 2 deletions jsport/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ func newVM(name string) *js.Object {
scope["player"] = player.V()

vm := dice.NewVM()
//vm.ValueStoreFunc = func(name string, v *dice.VMValue) {
//vm.GlobalValueStoreFunc = func(name string, v *dice.VMValue) {
// scope[name] = v
//}

re := regexp.MustCompile(`^_(\D+)(\d+)$`)
vm.ValueLoadFunc = func(name string) *dice.VMValue {
vm.GlobalValueLoadFunc = func(name string) *dice.VMValue {
m := re.FindStringSubmatch(name)
if len(m) > 1 {
val, _ := strconv.ParseInt(m[2], 10, 64)
Expand Down
4 changes: 2 additions & 2 deletions rollvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ func (e *Parser) Evaluate() {
}
stackPush(ret)
} else {
ctx.Error = errors.New("无法调用")
ctx.Error = errors.New("类型错误: 无法调用,必须是一个函数")
}

case TypeItemGet:
Expand All @@ -426,7 +426,7 @@ func (e *Parser) Evaluate() {
attrVal, obj := stackPop2()
attrName := code.Value.(string)

ret := obj.AttrSet(attrName, attrVal)
ret := obj.AttrSet(ctx, attrName, attrVal)
if ctx.Error == nil && ret == nil {
ctx.Error = errors.New("不支持的类型:当前变量无法用.来设置属性")
}
Expand Down
Loading

0 comments on commit 8bafd5a

Please sign in to comment.