From 0a6252d829ebe35332b513398e146bd19c67ffa6 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Wed, 21 Feb 2024 21:57:19 +0800 Subject: [PATCH] cb.BinaryOp: -> <> --- codebuild.go | 31 +++++++++++++++++++++++-------- error_msg_test.go | 12 ++++++++++++ token/token.go | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 8 deletions(-) create mode 100644 token/token.go diff --git a/codebuild.go b/codebuild.go index d81a9de9..aca267c7 100644 --- a/codebuild.go +++ b/codebuild.go @@ -28,6 +28,7 @@ import ( "syscall" "github.com/goplus/gox/internal" + xtoken "github.com/goplus/gox/token" "golang.org/x/tools/go/types/typeutil" ) @@ -1351,7 +1352,7 @@ func (p *CodeBuilder) VarVal(name string, src ...ast.Node) *CodeBuilder { if o == nil { log.Panicf("VarVal: variable `%v` not found\n", name) } - return p.Val(o) + return p.Val(o, src...) } // Val func @@ -2196,15 +2197,18 @@ func (p *CodeBuilder) UnaryOp(op token.Token, params ...interface{}) *CodeBuilde // BinaryOp func func (p *CodeBuilder) BinaryOp(op token.Token, src ...ast.Node) *CodeBuilder { + const ( + errNotFound = syscall.ENOENT + ) if debugInstr { - log.Println("BinaryOp", op) + log.Println("BinaryOp", xtoken.String(op)) } pkg := p.pkg name := goxPrefix + binaryOps[op] args := p.stk.GetArgs(2) var ret *internal.Elem - var err error = syscall.ENOENT + var err error = errNotFound isUserDef := false arg0 := args[0].Type named0, ok0 := checkNamed(arg0) @@ -2240,20 +2244,28 @@ func (p *CodeBuilder) BinaryOp(op token.Token, src ...ast.Node) *CodeBuilder { CVal: binaryOp(p, op, args), }, nil } - } else { - lm := pkg.builtin.Ref(name) + } else if lm := pkg.builtin.TryRef(name); lm != nil { ret, err = matchFuncCall(pkg, toObject(pkg, lm, nil), args, 0) + } else { + err = errNotFound } } expr := getSrc(src) if err != nil { + opstr := xtoken.String(op) src, pos := p.loadExpr(expr) if src == "" { - src = op.String() + src = opstr + } + if err != errNotFound { + p.panicCodeErrorf( + pos, "invalid operation: %s (mismatched types %v and %v)", src, arg0, args[1].Type) + } else { + arg0Src, _ := p.loadExpr(args[0].Src) + p.panicCodeErrorf( + pos, "invalid operation: operator %s not defined on %s (%v)", opstr, arg0Src, arg0) } - p.panicCodeErrorf( - pos, "invalid operation: %s (mismatched types %v and %v)", src, arg0, args[1].Type) } ret.Src = expr p.stk.Ret(2, ret) @@ -2300,6 +2312,9 @@ var ( token.GEQ: "GE", token.EQL: "EQ", token.NEQ: "NE", + + xtoken.SRARROW: "PointTo", // -> + xtoken.BIDIARROW: "PointBi", // <> } ) diff --git a/error_msg_test.go b/error_msg_test.go index 45a2daf8..94141017 100644 --- a/error_msg_test.go +++ b/error_msg_test.go @@ -27,6 +27,7 @@ import ( "testing" "github.com/goplus/gox" + xtoken "github.com/goplus/gox/token" ) type txtNode struct { @@ -278,6 +279,17 @@ func TestErrBinaryOp(t *testing.T) { }) } +func TestErrBinaryOp2(t *testing.T) { + codeErrorTest(t, `-: invalid operation: operator <> not defined on a (int)`, + func(pkg *gox.Package) { + pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg). + NewVar(types.Typ[types.Int], "a"). + NewVar(types.Typ[types.Int], "b"). + VarVal("a", source("a")).VarVal("b").BinaryOp(xtoken.BIDIARROW).EndStmt(). + End() + }) +} + func TestErrTypeAssert(t *testing.T) { codeErrorTest(t, "./foo.gop:2:9: impossible type assertion:\n\tstring does not implement bar (missing Bar method)", func(pkg *gox.Package) { diff --git a/token/token.go b/token/token.go new file mode 100644 index 00000000..dae72798 --- /dev/null +++ b/token/token.go @@ -0,0 +1,41 @@ +/* + Copyright 2024 The GoPlus Authors (goplus.org) + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package token + +import ( + "go/token" +) + +// Token is the set of lexical tokens of the Go/Go+ programming language. +type Token = token.Token + +const ( + additional_beg = token.TILDE - 1 + additional_end = token.TILDE + 1 + + SRARROW = additional_beg // -> (single right arrow) + BIDIARROW = additional_end // <> (bidirectional arrow) +) + +func String(tok Token) string { + if tok >= additional_beg { + switch tok { + case SRARROW: + return "->" + case BIDIARROW: + return "<>" + } + } + return tok.String() +}