Skip to content

Commit

Permalink
Implement minimal rest parameter feature
Browse files Browse the repository at this point in the history
  • Loading branch information
elct9620 committed May 22, 2024
1 parent ec3ca3e commit bee7536
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 2 deletions.
38 changes: 38 additions & 0 deletions array.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package mruby

func initArray(mrb *State) (err error) {
mrb.ArrayClass, err = mrb.DefineClassId(_ArrayClass(mrb), mrb.ObjectClass)
if err != nil {
return err
}

mrb.DefineMethodId(mrb.ArrayClass, _join(mrb), arrayJoin)

return nil
}

func arrayJoin(mrb *State, self Value) Value {
argv := mrb.GetArgv()

elem, ok := self.([]Value)
if !ok {
return nil
}

ret := ""
elemLen := len(elem)
for i, v := range elem {
v, ok := v.(string)
if !ok {
continue
}

ret += v
hasNext := elemLen > i+1
if hasNext {
ret += argv[0].(string)
}
}

return ret
}
2 changes: 2 additions & 0 deletions class.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ func (mrb *State) Class(v Value) RClass {
switch v := v.(type) {
case RObject:
return v.Class()
case []Value:
return mrb.ArrayClass
case bool:
if v {
return mrb.TrueClass
Expand Down
1 change: 0 additions & 1 deletion features/method.feature
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ Feature: Method
"""
Then there should return string "Hello, Ruby! I love Ruby"

@wip
Scenario: I can call the method with rest arguments
When I execute ruby code:
"""
Expand Down
4 changes: 4 additions & 0 deletions init.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,9 @@ func initCore(mrb *State) (err error) {
return
}

if err = initArray(mrb); err != nil {
return
}

return
}
1 change: 1 addition & 0 deletions mruby.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type State struct {
ClassClass RClass
FalseClass RClass
TrueClass RClass
ArrayClass RClass
KernelModule RClass

topSelf RObject
Expand Down
2 changes: 2 additions & 0 deletions presym.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,7 @@ var (
_Kernel = predefineSymbol("Kernel")
_TrueClass = predefineSymbol("TrueClass")
_FalseClass = predefineSymbol("FalseClass")
_ArrayClass = predefineSymbol("Array")
_join = predefineSymbol("join")
_raise = predefineSymbol("raise")
)
12 changes: 12 additions & 0 deletions proc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@ package mruby

import "github.com/elct9620/mruby-go/insn"

func AspecReq(n int) int {
return (((n) >> 18) & 0x1f)
}

func AspecOpt(n int) int {
return (((n) >> 13) & 0x1f)
}

func AspecRest(n int) int {
return (((n) >> 12) & 0x1)
}

type RProc interface {
IsGoFunction() bool
Body() any
Expand Down
19 changes: 18 additions & 1 deletion vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,24 @@ func (mrb *State) VmExec(proc RProc, code *insn.Sequence) (ret Value, err error)
ctx.Set(0, method.Call(mrb, recv))
mrb.callinfoPop()
case op.Enter:
_ = code.ReadW()
a := code.ReadW()
a = append([]byte{0x00}, a...)
aspec := int(binary.BigEndian.Uint32(a))

req := AspecReq(aspec)
opt := AspecOpt(aspec)
rest := AspecRest(aspec)

if rest > 0 {
values := make([]Value, 0)
argv := mrb.GetArgv()
for i := 0; i < len(argv); i++ {
values = append(values, argv[i])
}

ctx.Set(req+opt+1, values)
}

ctx.SetSequenceCursor(code.Cursor())
case op.EQ:
a := code.ReadB()
Expand Down

0 comments on commit bee7536

Please sign in to comment.