blob: 5725f8e2115117c984f68af419e5c80930818466 [file] [log] [blame]
// Copyright 2017 The Wuffs Authors.
//
// 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
//
// https://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 ast
import (
t "github.com/google/wuffs/lang/token"
)
// Eq returns whether n and o are equal.
//
// It may return false negatives. In general, it will not report that "x + y"
// equals "y + x". However, if both are constant expressions (i.e. each Expr
// node, including the sum nodes, has a ConstValue), both sums will have the
// same value and will compare equal.
func (n *Expr) Eq(o *Expr) bool {
if n == o {
return true
}
if n == nil || o == nil {
return false
}
if n.constValue != nil && o.constValue != nil {
return n.constValue.Cmp(o.constValue) == 0
}
if n.flags != o.flags || n.id0 != o.id0 || n.id1 != o.id1 || n.id2 != o.id2 {
return false
}
if !n.lhs.AsExpr().Eq(o.lhs.AsExpr()) {
return false
}
if !n.mhs.AsExpr().Eq(o.mhs.AsExpr()) {
return false
}
if n.id0 == t.IDXBinaryAs {
if !n.rhs.AsTypeExpr().Eq(o.rhs.AsTypeExpr()) {
return false
}
} else if !n.rhs.AsExpr().Eq(o.rhs.AsExpr()) {
return false
}
if len(n.list0) != len(o.list0) {
return false
}
for i, x := range n.list0 {
if !x.AsExpr().Eq(o.list0[i].AsExpr()) {
return false
}
}
return true
}
func (n *Expr) Mentions(o *Expr) bool {
if n == nil {
return false
}
if n.Eq(o) ||
n.lhs.AsExpr().Mentions(o) ||
n.mhs.AsExpr().Mentions(o) ||
(n.id0 != t.IDXBinaryAs && n.rhs.AsExpr().Mentions(o)) {
return true
}
for _, x := range n.list0 {
if x.AsExpr().Mentions(o) {
return true
}
}
return false
}
// Eq returns whether n and o are equal.
func (n *TypeExpr) Eq(o *TypeExpr) bool {
return n.eq(o, false)
}
// EqIgnoringRefinements returns whether n and o are equal, ignoring the
// "[i:j]" in "base.u32[i:j]".
func (n *TypeExpr) EqIgnoringRefinements(o *TypeExpr) bool {
return n.eq(o, true)
}
func (n *TypeExpr) eq(o *TypeExpr, ignoreRefinements bool) bool {
for {
if n == o {
return true
}
if n == nil || o == nil {
return false
}
if n.id0 != o.id0 || n.id1 != o.id1 || n.id2 != o.id2 {
return false
}
if n.IsArrayType() || !ignoreRefinements {
if !n.lhs.AsExpr().Eq(o.lhs.AsExpr()) || !n.mhs.AsExpr().Eq(o.mhs.AsExpr()) {
return false
}
}
if n.rhs == nil && o.rhs == nil {
return true
}
n = n.rhs.AsTypeExpr()
o = o.rhs.AsTypeExpr()
}
}