diff --git a/pkgs/gnolang/machine.go b/pkgs/gnolang/machine.go index ac39dc2a227..87dd387d38e 100644 --- a/pkgs/gnolang/machine.go +++ b/pkgs/gnolang/machine.go @@ -804,6 +804,9 @@ const ( OpValueDecl Op = 0x90 // var/const ... OpTypeDecl Op = 0x91 // type ... + /* ContextOp */ + OpSetContext Op = 0xA0 + /* Loop (sticky) operators (>= 0xD0) */ OpSticky Op = 0xD0 // not a real op. OpBody Op = 0xD1 // if/block/switch/select. @@ -1275,6 +1278,9 @@ func (m *Machine) Run() { case OpReturnCallDefers: m.incrCPU(OpCPUReturnCallDefers) m.doOpReturnCallDefers() + case OpSetContext: + m.incrCPU(1) + m.doOpSetContext() default: panic(fmt.Sprintf("unexpected opcode %s", op.String())) } diff --git a/pkgs/gnolang/op_call.go b/pkgs/gnolang/op_call.go index c6f286dc930..0e4f82fc5af 100644 --- a/pkgs/gnolang/op_call.go +++ b/pkgs/gnolang/op_call.go @@ -407,3 +407,8 @@ func (m *Machine) doOpPanic2() { m.PushOp(OpReturnCallDefers) // XXX rename, not return? } } + +func (m *Machine) doOpSetContext() { + cv := m.PopValue().V.(ContextValue) + m.Context = cv.Context +} diff --git a/pkgs/gnolang/values.go b/pkgs/gnolang/values.go index 227d5368eeb..ce19a9d0d30 100644 --- a/pkgs/gnolang/values.go +++ b/pkgs/gnolang/values.go @@ -40,6 +40,7 @@ func (*PackageValue) assertValue() {} func (*NativeValue) assertValue() {} func (*Block) assertValue() {} func (RefValue) assertValue() {} +func (ContextValue) assertValue() {} const ( nilStr = "nil" @@ -62,6 +63,7 @@ var ( _ Value = &NativeValue{} _ Value = &Block{} _ Value = RefValue{} + _ Value = ContextValue{} ) // ---------------------------------------- @@ -2184,6 +2186,17 @@ func (tv *TypedValue) GetSlice2(alloc *Allocator, low, high, max int) TypedValue } } +// ---------------------------------------- +// ContextValue + +type ContextValue struct { + Context interface{} +} + +func (ctx ContextValue) String() string { + return fmt.Sprintf("%v", ctx.Context) +} + // ---------------------------------------- // Block // diff --git a/stdlibs/stdlibs.go b/stdlibs/stdlibs.go index 4660d6d4398..bd028334086 100644 --- a/stdlibs/stdlibs.go +++ b/stdlibs/stdlibs.go @@ -289,18 +289,32 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { // to support multiple concurrent contexts and advanced flows. arg0 := m.LastBlock().GetParams1().TV fn := arg0.GetFunc() - println("#####################", arg0, fn.GetType(m.Store).String()) - //gno.Call(fn, "nil") - //m.Eval(gno.Call(fn)) - // m.Eval(gno.Call(gno.FuncT(nil, nil), fn)) - println("@@@@@@@@@@") - //println(fn) - /* - ctx := m.Context.(stdlibs.ExecContext) - ctx.OrigCaller = crypto.Bech32Address(addr) - m.Context = ctx - */ + ctx := m.Context.(ExecContext) + ctx.OrigCaller = ctx.OrigPkgAddr + + backupContext := m.Context.(ExecContext) + + m.PushValue(gno.TypedValue{ + T: &gno.InterfaceType{}, + V: gno.ContextValue{ + Context: backupContext, + }, + }) + m.PushOp(gno.OpSetContext) + + cx := gno.Call(gno.FuncT(nil, nil)) + m.PushValue(gno.TypedValue{}) + m.PushFrameCall(cx, fn, gno.TypedValue{}) + m.PushOp(gno.OpCall) + + m.PushValue(gno.TypedValue{ + T: &gno.InterfaceType{}, + V: gno.ContextValue{ + Context: ctx, + }, + }) + m.PushOp(gno.OpSetContext) }, ) pn.DefineNative("GetCallerAt", diff --git a/tests/file.go b/tests/file.go index 33afbe38ebb..640e9c55347 100644 --- a/tests/file.go +++ b/tests/file.go @@ -34,7 +34,7 @@ func TestMachine(store gno.Store, stdout io.Writer, pkgPath string) *gno.Machine func testMachineCustom(store gno.Store, pkgPath string, stdout io.Writer, maxAlloc int64, send std.Coins) *gno.Machine { // FIXME: create a better package to manage this, with custom constructors pkgAddr := gno.DerivePkgAddr(pkgPath) // the addr of the pkgPath called. - caller := gno.DerivePkgAddr(pkgPath) // NOTE: for the purpose of testing, the caller is generally the "main" package, same as pkgAddr. + caller := gno.DerivePkgAddr("caller") // NOTE: for the purpose of testing, the caller is generally the "main" package, same as pkgAddr. pkgCoins := std.MustParseCoins("200000000ugnot").Add(send) // >= send. banker := newTestBanker(pkgAddr.Bech32(), pkgCoins) ctx := stdlibs.ExecContext{ diff --git a/tests/files/zrealm_std6.gno b/tests/files/zrealm_std6.gno new file mode 100644 index 00000000000..36a9393b983 --- /dev/null +++ b/tests/files/zrealm_std6.gno @@ -0,0 +1,20 @@ +// PKGPATH: gno.land/r/std_test +package std_test + +import ( + "fmt" + "std" +) + +func main() { + println(std.GetOrigCaller()) + std.ExecAsPkg(func() { + println(std.GetOrigCaller()) + }) + println(std.GetOrigCaller()) +} + +// Output: +// g1fahslvxakc058u0wa98ytfc9fd6trhe5qfh9ld +// g157y5v3k529jyzhjjz4fn49tzzhf4gess6v39xg +// g1fahslvxakc058u0wa98ytfc9fd6trhe5qfh9ld