1// Copyright 2021 CUE Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package fix
16
17import (
18	"cuelang.org/go/cue/ast"
19	"cuelang.org/go/cue/ast/astutil"
20	"cuelang.org/go/cue/token"
21)
22
23func simplify(f *ast.File) *ast.File {
24	// Rewrite disjunctions with _ to _.
25	f = astutil.Apply(f, nil, func(c astutil.Cursor) bool {
26		if x, ok := c.Node().(ast.Expr); ok {
27			if y := elideTop(x); x != y {
28				c.Replace(y)
29			}
30		}
31		return true
32	}).(*ast.File)
33
34	return f
35}
36
37func elideTop(x ast.Expr) ast.Expr {
38	switch x := x.(type) {
39	case *ast.BinaryExpr:
40		switch x.Op {
41		case token.OR:
42			if isTop(x.X) {
43				return x.X
44			}
45			if isTop(x.Y) {
46				ast.SetRelPos(x.Y, token.NoRelPos)
47				return x.Y
48			}
49
50		case token.AND:
51			if isTop(x.X) {
52				ast.SetRelPos(x.Y, token.NoRelPos)
53				return x.Y
54			}
55			if isTop(x.Y) {
56				return x.X
57			}
58		}
59
60	case *ast.ParenExpr:
61		switch x.X.(type) {
62		case *ast.BinaryExpr, *ast.UnaryExpr:
63		default:
64			return x.X
65		}
66	}
67	return x
68}
69
70func isTop(x ast.Expr) bool {
71	v, ok := x.(*ast.Ident)
72	return ok && v.Name == "_"
73}
74