Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
Merge pull request #43 from erikh/run-with-context
Browse files Browse the repository at this point in the history
Implement mrb_context_run.
  • Loading branch information
Erik Hollensbe authored Dec 10, 2016
2 parents 8f4fadf + 06f413c commit 79098e5
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 0 deletions.
6 changes: 6 additions & 0 deletions gomruby.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,4 +231,10 @@ static inline void _go_mrb_context_set_capture_errors(struct mrbc_context *ctx,
}
}

static inline mrb_value _go_mrb_context_run(mrb_state *m, struct RProc *proc, mrb_value self, int *stack_keep) {
mrb_value result = mrb_context_run(m, proc, self, *stack_keep);
*stack_keep = proc->body.irep->nlocals;
return result;
}

#endif
26 changes: 26 additions & 0 deletions mruby.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,32 @@ func (m *Mrb) Run(v Value, self Value) (*MrbValue, error) {
return newValue(m.state, value), nil
}

// 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 (m *Mrb) RunWithContext(v Value, self Value, stackKeep int) (int, *MrbValue, error) {
if self == nil {
self = m.TopSelf()
}

mrbV := v.MrbValue(m)
mrbSelf := self.MrbValue(m)
proc := C._go_mrb_proc_ptr(mrbV.value)

i := C.int(stackKeep)

value := C._go_mrb_context_run(m.state, proc, mrbSelf.value, &i)

if exc := checkException(m.state); exc != nil {
return stackKeep, nil, exc
}

return int(i), newValue(m.state, value), nil
}

// Yield yields to a block with the given arguments.
//
// This should be called within the context of a Func.
Expand Down
24 changes: 24 additions & 0 deletions mruby_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,4 +444,28 @@ func TestMrbRun(t *testing.T) {
if rval.String() != "rval" {
t.Fatalf("expected return value 'rval', got %#v", rval)
}

parser.Parse(`a = 10`, context)
proc = parser.GenerateCode()

stackKeep, ret, err := mrb.RunWithContext(proc, nil, 0)
if err != nil {
t.Fatal(err)
}

if stackKeep != 2 {
t.Fatalf("stack value was %d not 2; some variables may not have been captured", stackKeep)
}

parser.Parse(`a`, context)
proc = parser.GenerateCode()

stackKeep, ret, err = mrb.RunWithContext(proc, nil, stackKeep)
if err != nil {
t.Fatal(err)
}

if ret.String() != "10" {
t.Fatalf("Captured variable was not expected value: was %q", ret.String())
}
}

0 comments on commit 79098e5

Please sign in to comment.