Skip to content

Commit

Permalink
feat: 增加空值合并算符 ??,字典类型增加 len() 方法 (#3)
Browse files Browse the repository at this point in the history
* feat: 增加空值合并算符 `??`

* feat: 字典类型增加 len() 方法
  • Loading branch information
JustAnotherID authored Oct 22, 2023
1 parent 46a8c8b commit 1088217
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 3 deletions.
6 changes: 6 additions & 0 deletions GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,12 @@ val1 = expr1 || expr2
灵视 >= 0 ? '呵,无知之人。'
```

#### 空值合并算符

对于可能为 `undefined``null` 的值,通过该算符 `??` 提供默认值。

`expr1 ?? expr2`:当 `expr1` 不为 `undefined``null` 时取 `expr1`,为空时取 `expr2`


### 内置函数

Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ DiceScript将使用和RollVM相同的技术栈,但会有更好的接口设计
- [x] 一元算符 + -
- [x] 二元算符 +-*/% >,>=,==,!=,<,<=,&,|,&&,||
- [x] 三元算符 ? :
- [x] 空值合并算符 ??
- [x] 骰点运算 流行: d20, 3d20, (4+5)d(20), 2d20k1, 2d20q1
- [x] 骰点运算 - fvtt语法: 2d20kl, 2d20kh, 2d20dl, 2d20dh, d20min10, d20max10
- [x] 骰点运算 - CoC / Fate / WoD / Double Cross
Expand Down Expand Up @@ -86,6 +87,10 @@ DiceScript将使用和RollVM相同的技术栈,但会有更好的接口设计
* 为字典类型增加了 keys() values() items() 方法
* dir 函数,和python的dir函数类似,用于获取对象的所有属性

#### 2023.10.22
* 空值合并算符
* 文档调整

#### 2022.11.29

* 逻辑与/逻辑或/按位与/按位或
Expand Down
3 changes: 3 additions & 0 deletions bytecode.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const (
TypeDivide
TypeModulus
TypeExponentiation
TypeNullCoalescing

TypeCompLT
TypeCompLE
Expand Down Expand Up @@ -163,6 +164,8 @@ func (code *ByteCode) CodeString() string {
return "mod"
case TypeExponentiation:
return "pow"
case TypeNullCoalescing:
return "nullCoalescing"

case TypeLogicAnd:
return "and"
Expand Down
10 changes: 8 additions & 2 deletions roll.peg
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,17 @@ exprAdditive <- exprMultiplicative sp (
)*

// 乘除余
exprMultiplicative <- exprExp sp (
exprMultiplicative <- exprNullCoalescing sp (
multiply exprExp { p.AddOp(TypeMultiply) }
/ divide exprExp { p.AddOp(TypeDivide) }
/ modulus exprExp { p.AddOp(TypeModulus) }
)*

// 空值合并
exprNullCoalescing <- exprExp sp (
nullCoalescing exprExp { p.AddOp(TypeNullCoalescing) }
)

// 平方
exprExp <- exprUnaryNeg sp (
exponentiation exprUnaryNeg { p.AddOp(TypeExponentiation) }
Expand Down Expand Up @@ -306,13 +311,14 @@ sub <- parenOpen exprRoot parenClose
parenOpen <- '(' sp
parenClose <- ')' sp

// 加减乘除余 乘方
// 加减乘除余 乘方 空值合并
add <- ('+'/'+') sp
minus <- ('-' / '-') sp
multiply <- ('*' / '*') sp
divide <- ('/' / '/') sp
modulus <- '%' sp
exponentiation <- '^' sp / '**' sp
nullCoalescing <- '??' sp

// 按位算符
bitwiseOr <- '|' sp
Expand Down
2 changes: 1 addition & 1 deletion rollvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ func (e *Parser) Evaluate() {
case TypePopN:
stackPopN(code.Value.(int64))

case TypeAdd, TypeSubtract, TypeMultiply, TypeDivide, TypeModulus, TypeExponentiation,
case TypeAdd, TypeSubtract, TypeMultiply, TypeDivide, TypeModulus, TypeExponentiation, TypeNullCoalescing,
TypeCompLT, TypeCompLE, TypeCompEQ, TypeCompNE, TypeCompGE, TypeCompGT,
TypeBitwiseAnd, TypeBitwiseOr:
// 所有二元运算符
Expand Down
1 change: 1 addition & 0 deletions rollvm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,7 @@ func TestBytecodeToString(t *testing.T) {
{TypeDivide, nil},
{TypeModulus, nil},
{TypeExponentiation, nil},
{TypeNullCoalescing, nil},

{TypeCompLT, nil},
{TypeCompLE, nil},
Expand Down
9 changes: 9 additions & 0 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ var binOperator = []func(*VMValue, *Context, *VMValue) *VMValue{
(*VMValue).OpDivide,
(*VMValue).OpModulus,
(*VMValue).OpPower,
(*VMValue).OpNullCoalescing,

(*VMValue).OpCompLT,
(*VMValue).OpCompLE,
Expand Down Expand Up @@ -748,6 +749,14 @@ func (v *VMValue) OpPower(ctx *Context, v2 *VMValue) *VMValue {
return nil
}

func (v *VMValue) OpNullCoalescing(ctx *Context, v2 *VMValue) *VMValue {
if v.TypeId == VMTypeUndefined || v.TypeId == VMTypeNull {
return v2
} else {
return v
}
}

func boolToVMValue(v bool) *VMValue {
var val int64
if v {
Expand Down
11 changes: 11 additions & 0 deletions types_methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ func funcDictItems(ctx *Context, this *VMValue, params []*VMValue) *VMValue {
return VMValueNewArrayRaw(arr)
}

func funcDictLen(ctx *Context, this *VMValue, params []*VMValue) *VMValue {
d := this.MustReadDictData()
var size int64
d.Dict.Range(func(key string, value *VMValue) bool {
size++
return true
})
return VMValueNewInt(size)
}

var builtinProto = map[VMValueType]*VMDictValue{
VMTypeArray: VMValueMustNewDictWithArray(
VMValueNewStr("kh"), nnf(&ndf{"Array.kh", []string{"num"}, []*VMValue{VMValueNewInt(1)}, nil, funcArrayKeepHigh}),
Expand All @@ -154,6 +164,7 @@ var builtinProto = map[VMValueType]*VMDictValue{
VMValueNewStr("keys"), nnf(&ndf{"Dict.keys", []string{}, nil, nil, funcDictKeys}),
VMValueNewStr("values"), nnf(&ndf{"Dict.values", []string{}, nil, nil, funcDictValues}),
VMValueNewStr("items"), nnf(&ndf{"Dict.items", []string{}, nil, nil, funcDictItems}),
VMValueNewStr("len"), nnf(&ndf{"Dict.len", []string{}, nil, nil, funcDictLen}),
),
}

Expand Down

0 comments on commit 1088217

Please sign in to comment.