Skip to content

Commit

Permalink
Merge branch 'master' of https://gitee.com/wa-lang/wa
Browse files Browse the repository at this point in the history
  • Loading branch information
3dgen committed Apr 10, 2024
2 parents 14b3727 + 9862f39 commit 02ea75e
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 32 deletions.
13 changes: 12 additions & 1 deletion internal/types/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,18 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
// can only appear in qualified identifiers which are mapped to
// selector expressions.
if ident, ok := e.X.(*ast.Ident); ok {
obj := check.lookup(ident.Name)
var obj Object
if ident.Name[0] == '#' {
// 内部: 根据包路径查询
for _, pkg := range check.pkg.imports {
if pkg.path == ident.Name[1:] {
// todo(chai)
}
}
} else {
obj = check.lookup(ident.Name)
}

if pname, _ := obj.(*PkgName); pname != nil {
assert(pname.pkg == check.pkg)
check.recordUse(ident, pname)
Expand Down
10 changes: 4 additions & 6 deletions internal/types/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) {
return
}

if fn := check.tryUnaryOperatorCall(x, e, op); fn != nil {
x.mode = value
if check.tryUnaryOperatorCall(x, e) {
return
}

Expand Down Expand Up @@ -781,13 +780,12 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
return
}

if isShift(op) {
check.shift(x, &y, e, op)
if check.tryBinaryOperatorCall(x, &y, e) {
return
}

if fn := check.tryBinaryOperatorCall(x, e, lhs, rhs, op); fn != nil {
x.mode = value
if isShift(op) {
check.shift(x, &y, e, op)
return
}

Expand Down
185 changes: 160 additions & 25 deletions internal/types/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,42 +132,177 @@ func (check *Checker) processTypeOperators() {
}
}

func (check *Checker) tryUnaryOperatorCall(
x *operand, e *ast.UnaryExpr,
op token.Token,
) *Func {
func (check *Checker) tryUnaryOperatorCall(x *operand, e *ast.UnaryExpr) bool {
if true {
return false // todo(chai): debug
}

assert(x.typ != nil)

var ops *typeOperator
switch typ := x.typ.(type) {
case *Named:
ops = typ.obj.ops
default:
// todo(chai)
var xNamed *Named
if v, ok := x.typ.(*Named); ok {
xNamed = v
}
if ops == nil {
return nil
if xNamed == nil || xNamed.obj == nil || xNamed.obj.ops == nil {
return false
}

switch op {
var fn *Func
switch e.Op {
case token.ADD:
return ops.Unary_ADD
fn = xNamed.obj.ops.Unary_ADD
case token.SUB:
return ops.Unary_SUB
fn = xNamed.obj.ops.Unary_SUB
case token.XOR:
return ops.Unary_XOR
fn = xNamed.obj.ops.Unary_XOR
case token.NOT:
return ops.Unary_NOT
fn = xNamed.obj.ops.Unary_NOT
}
if fn == nil {
return false
}

unreachable()
return nil
err := check.tryUnaryOpFunc(fn, x, e)
if err == nil {
return false
}

x.mode = value
x.typ = fn.typ.(*Signature).results.vars[0].typ
x.expr = &ast.CallExpr{
Fun: &ast.SelectorExpr{
X: &ast.Ident{Name: "#" + fn.pkg.path},
Sel: &ast.Ident{Name: fn.pkg.name},
},
Args: []ast.Expr{e.X},
}

check.hasCallOrRecv = true
return true
}

func (check *Checker) tryBinaryOperatorCall(
x *operand, e *ast.BinaryExpr,
lhs, rhs ast.Expr,
op token.Token,
) *Func {
return nil // todo(chai)
func (check *Checker) tryBinaryOperatorCall(x, y *operand, e *ast.BinaryExpr) bool {
if true {
return false // todo(chai): debug
}

var xNamed, yNamed *Named
if v, ok := x.typ.(*Named); ok {
xNamed = v
}
if v, ok := y.typ.(*Named); ok {
yNamed = v
}

// 至少有1个是自定义类型
if xNamed == nil && yNamed == nil {
return false
}

// 根据左右顺序匹配
xFuncs := check.getBinOpFuncs(xNamed, e.Op)
yFuncs := check.getBinOpFuncs(yNamed, e.Op)

var fnMached *Func
if fnMached == nil {
for _, fn := range xFuncs {
if err := check.tryBinOpFunc(fn, x, y, e); err == nil {
fnMached = fn
break
}
}
}
if fnMached == nil {
for _, fn := range yFuncs {
if err := check.tryBinOpFunc(fn, x, y, e); err == nil {
fnMached = fn
break
}
}
}
if fnMached == nil {
return false
}

x.mode = value
x.typ = fnMached.typ.(*Signature).results.vars[0].typ
x.expr = &ast.CallExpr{
Fun: &ast.SelectorExpr{
X: &ast.Ident{Name: "#" + fnMached.pkg.path},
Sel: &ast.Ident{Name: fnMached.pkg.name},
},
Args: []ast.Expr{e.X},
}

check.hasCallOrRecv = true
return true
}

func (check *Checker) tryUnaryOpFunc(fn *Func, x *operand, e *ast.UnaryExpr) (err error) {
assert(fn != nil)

firstErrBak := check.firstErr
check.firstErr = nil

defer func() { check.firstErr = firstErrBak }()

defer check.handleBailout(&err)

check.rawExpr(x, e.X, nil)

assert(fn.typ != nil)
sig, _ := fn.typ.(*Signature)
assert(sig != nil)
assert(sig.recv == nil)
assert(sig.params.Len() == 1)
assert(sig.results.Len() == 1)

// 检查参数是否匹配
check.argument(sig, 0, x, token.NoPos, "")
return
}

func (check *Checker) tryBinOpFunc(fn *Func, x, y *operand, e *ast.BinaryExpr) (err error) {
firstErrBak := check.firstErr
check.firstErr = nil

defer func() { check.firstErr = firstErrBak }()

defer check.handleBailout(&err)

check.rawExpr(x, e.X, nil)
check.rawExpr(y, e.Y, nil)

assert(fn.typ != nil)
sig, _ := fn.typ.(*Signature)
assert(sig != nil)
assert(sig.recv == nil)
assert(sig.params.Len() == 2)
assert(sig.results.Len() == 1)

// 检查参数是否匹配
check.argument(sig, 0, x, token.NoPos, "")
check.argument(sig, 1, y, token.NoPos, "")
return
}

func (check *Checker) getBinOpFuncs(x *Named, op token.Token) []*Func {
if x == nil {
return nil
}
if typ := x.obj; typ != nil && typ.ops != nil {
switch op {
case token.ADD:
return typ.ops.ADD
case token.SUB:
return typ.ops.ADD
case token.MUL:
return typ.ops.ADD
case token.QUO:
return typ.ops.ADD
case token.REM:
return typ.ops.ADD
}
}
return nil
}

0 comments on commit 02ea75e

Please sign in to comment.