func (this *ifExprs) addIfExpr(cond funcs.Bool, then, els *ast.Pattern) { // efficienctly append the then and else return to two copies of the current returns. if this.ret != nil { this.cond = cond thenterms := make([]*ast.Pattern, len(this.ret)+1) copy(thenterms, this.ret) thenterms[len(thenterms)-1] = then this.then = &ifExprs{ret: thenterms} this.els = &ifExprs{ret: append(this.ret, els)} this.ret = nil return } // remove duplicate condition if funcs.Equal(this.cond, cond) { this.then.addReturn(then) this.els.addReturn(els) return } // remove impossible (always false) then condition if funcs.IsFalse(funcs.Simplify(funcs.And(this.cond, cond))) { this.then.addReturn(els) this.els.addIfExpr(cond, then, els) return } // remove impossible (always false) else condition if funcs.IsFalse(funcs.Simplify(funcs.And(this.cond, funcs.Not(cond)))) { this.then.addIfExpr(cond, then, els) this.els.addReturn(then) return } this.then.addIfExpr(cond, then, els) this.els.addIfExpr(cond, then, els) return }
func (this *simplifier) simplify(p *ast.Pattern, top bool) *ast.Pattern { cRef := func(cp *ast.Pattern) *ast.Pattern { if top { return cp } return checkRef(this.refs, cp) } cachesimp := func(sp *ast.Pattern) *ast.Pattern { if _, ok := this.cache[sp]; ok { return sp } s := this.simplify(sp, false) this.cache[s] = struct{}{} return s } simp := func(sp *ast.Pattern) *ast.Pattern { return this.simplify(sp, false) } typ := p.GetValue() switch v := typ.(type) { case *ast.Empty: return p case *ast.TreeNode: child := cachesimp(v.GetPattern()) if isNotZany(child) { return emptyset } name := v.GetName() b := nameexpr.NameToFunc(v.GetName()) if funcs.IsFalse(b) { return emptyset } if funcs.IsTrue(b) { name = ast.NewAnyName() } return cRef(ast.NewTreeNode(name, child)) case *ast.LeafNode: b, err := compose.NewBool(v.GetExpr()) if err != nil { //Don't simplify if there is an error to keep this function signature simple. return p } if funcs.IsFalse(b) { return emptyset } return p case *ast.Concat: return cRef(simplifyConcat( simp(v.GetLeftPattern()), simp(v.GetRightPattern()), )) case *ast.Or: return cRef(simplifyOr(this.refs, simp(v.GetLeftPattern()), simp(v.GetRightPattern()), this.record, )) case *ast.And: return cRef(simplifyAnd(this.refs, simp(v.GetLeftPattern()), simp(v.GetRightPattern()), this.record, )) case *ast.ZeroOrMore: return cRef(simplifyZeroOrMore(simp(v.GetPattern()))) case *ast.Reference: return p case *ast.Not: return cRef(simplifyNot(simp(v.GetPattern()))) case *ast.ZAny: return p case *ast.Contains: return cRef(simplifyContains(simp(v.GetPattern()))) case *ast.Optional: return simplifyOptional(simp(v.GetPattern())) case *ast.Interleave: return cRef(simplifyInterleave(this.refs, cachesimp(v.GetLeftPattern()), cachesimp(v.GetRightPattern()), )) } panic(fmt.Sprintf("unknown pattern typ %T", typ)) }