diff --git a/ast/walk.go b/ast/walk.go index 4ce089fff..0cea28fe9 100644 --- a/ast/walk.go +++ b/ast/walk.go @@ -456,6 +456,9 @@ func Walk(v Visitor, node Node) { Walk(v, n.Name) walkExprList(v, n.Funcs) + case *EnvExpr: + Walk(v, n.Name) + default: panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n)) } diff --git a/cl/compile_spx_test.go b/cl/compile_spx_test.go index bca913462..bb284bc7c 100644 --- a/cl/compile_spx_test.go +++ b/cl/compile_spx_test.go @@ -259,6 +259,36 @@ func (this *bar) Classfname() string { `) } +func TestEnvOp(t *testing.T) { + gopSpxTest(t, ` +echo ${PATH}, $id +`, ``, `package main + +import ( + "fmt" + "github.com/goplus/gop/cl/internal/spx" +) + +type bar struct { + spx.Sprite + *index +} +type index struct { + *spx.MyGame +} + +func (this *index) MainEntry() { + fmt.Println(this.Gop_Env("PATH"), this.Gop_Env("id")) +} +func main() { + spx.Gopt_MyGame_Main(new(index)) +} +func (this *bar) Classfname() string { + return "bar" +} +`) +} + func TestSpxGopEnv(t *testing.T) { gopSpxTest(t, ` echo "${PATH}" diff --git a/cl/error_msg_test.go b/cl/error_msg_test.go index cc27271a3..5c268cd92 100644 --- a/cl/error_msg_test.go +++ b/cl/error_msg_test.go @@ -509,6 +509,15 @@ func (p *[]byte) foo() { `) } +func TestErrEnvOp(t *testing.T) { + codeErrorTest(t, `bar.gop:2:6: operator $name undefined`, ` +echo ${name} +`) + codeErrorTest(t, `bar.gop:2:1: operator $id undefined`, ` +$id +`) +} + func TestErrStringLit(t *testing.T) { codeErrorTest(t, `bar.gop:2:9: [].string undefined (type []interface{} has no field or method string)`, ` echo "${[]}" diff --git a/cl/expr.go b/cl/expr.go index 7a49b06ca..b261dcf73 100644 --- a/cl/expr.go +++ b/cl/expr.go @@ -188,6 +188,21 @@ find: return } +func compileEnvExpr(ctx *blockCtx, v *ast.EnvExpr) { + cb := ctx.cb + if ctx.isClass { // in a Go+ class file + if recv := classRecv(cb); recv != nil { + if gopMember(cb, recv, "Gop_Env", v) == nil { + name := v.Name + cb.Val(name.Name, name).CallWith(1, 0, v) + return + } + } + } + invalidVal(cb) + ctx.handleErrorf(v.Pos(), "operator $%v undefined", v.Name) +} + func classRecv(cb *gogen.CodeBuilder) *types.Var { if fn := cb.Func(); fn != nil { sig := fn.Ancestor().Type().(*types.Signature) @@ -346,6 +361,8 @@ func compileExpr(ctx *blockCtx, expr ast.Expr, inFlags ...int) { compileErrWrapExpr(ctx, v, 0) case *ast.FuncType: ctx.cb.Typ(toFuncType(ctx, v, nil, nil), v) + case *ast.EnvExpr: + compileEnvExpr(ctx, v) default: log.Panicf("compileExpr failed: unknown - %T\n", v) } @@ -938,6 +955,10 @@ func compileBasicLit(ctx *blockCtx, v *ast.BasicLit) { } } +func invalidVal(cb *gogen.CodeBuilder) { + cb.Val(&gogen.Element{Type: types.Typ[types.Invalid]}) +} + func basicLit(cb *gogen.CodeBuilder, v *ast.BasicLit) { cb.Val(&goast.BasicLit{Kind: gotoken.Token(v.Kind), Value: v.Value}, v) }