mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-11-04 03:07:28 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			137 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2023 The LevelDB-Go and Pebble Authors. All rights reserved. Use
 | 
						|
// of this source code is governed by a BSD-style license that can be found in
 | 
						|
// the LICENSE file.
 | 
						|
 | 
						|
package dsl
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"go/token"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
	"sync/atomic"
 | 
						|
 | 
						|
	"github.com/cockroachdb/errors"
 | 
						|
)
 | 
						|
 | 
						|
// Predicate encodes conditional logic that yields a boolean.
 | 
						|
type Predicate[E any] interface {
 | 
						|
	Evaluate(E) bool
 | 
						|
	String() string
 | 
						|
}
 | 
						|
 | 
						|
// Not returns a Predicate that negates the provided predicate.
 | 
						|
func Not[E any](p Predicate[E]) Predicate[E] { return not[E]{Predicate: p} }
 | 
						|
 | 
						|
// And returns a Predicate that evaluates to true if all its operands evaluate
 | 
						|
// to true.
 | 
						|
func And[E any](preds ...Predicate[E]) Predicate[E] { return and[E](preds) }
 | 
						|
 | 
						|
// Or returns a Predicate that evaluates to true if any of its operands evaluate
 | 
						|
// true.
 | 
						|
func Or[E any](preds ...Predicate[E]) Predicate[E] { return or[E](preds) }
 | 
						|
 | 
						|
// OnIndex returns a Predicate that evaluates to true on its N-th call.
 | 
						|
func OnIndex[E any](n int32) *Index[E] {
 | 
						|
	p := new(Index[E])
 | 
						|
	p.Int32.Store(n)
 | 
						|
	return p
 | 
						|
}
 | 
						|
 | 
						|
// Index is a Predicate that evaluates to true only on its N-th invocation.
 | 
						|
type Index[E any] struct {
 | 
						|
	atomic.Int32
 | 
						|
}
 | 
						|
 | 
						|
// String implements fmt.Stringer.
 | 
						|
func (p *Index[E]) String() string {
 | 
						|
	return fmt.Sprintf("(OnIndex %d)", p.Int32.Load())
 | 
						|
}
 | 
						|
 | 
						|
// Evaluate implements Predicate.
 | 
						|
func (p *Index[E]) Evaluate(E) bool { return p.Int32.Add(-1) == -1 }
 | 
						|
 | 
						|
type not[E any] struct {
 | 
						|
	Predicate[E]
 | 
						|
}
 | 
						|
 | 
						|
func (p not[E]) String() string    { return fmt.Sprintf("(Not %s)", p.Predicate.String()) }
 | 
						|
func (p not[E]) Evaluate(e E) bool { return !p.Predicate.Evaluate(e) }
 | 
						|
 | 
						|
type and[E any] []Predicate[E]
 | 
						|
 | 
						|
func (p and[E]) String() string {
 | 
						|
	var sb strings.Builder
 | 
						|
	sb.WriteString("(And")
 | 
						|
	for i := 0; i < len(p); i++ {
 | 
						|
		sb.WriteRune(' ')
 | 
						|
		sb.WriteString(p[i].String())
 | 
						|
	}
 | 
						|
	sb.WriteRune(')')
 | 
						|
	return sb.String()
 | 
						|
}
 | 
						|
 | 
						|
func (p and[E]) Evaluate(e E) bool {
 | 
						|
	ok := true
 | 
						|
	for i := range p {
 | 
						|
		ok = ok && p[i].Evaluate(e)
 | 
						|
	}
 | 
						|
	return ok
 | 
						|
}
 | 
						|
 | 
						|
type or[E any] []Predicate[E]
 | 
						|
 | 
						|
func (p or[E]) String() string {
 | 
						|
	var sb strings.Builder
 | 
						|
	sb.WriteString("(Or")
 | 
						|
	for i := 0; i < len(p); i++ {
 | 
						|
		sb.WriteRune(' ')
 | 
						|
		sb.WriteString(p[i].String())
 | 
						|
	}
 | 
						|
	sb.WriteRune(')')
 | 
						|
	return sb.String()
 | 
						|
}
 | 
						|
 | 
						|
func (p or[E]) Evaluate(e E) bool {
 | 
						|
	ok := false
 | 
						|
	for i := range p {
 | 
						|
		ok = ok || p[i].Evaluate(e)
 | 
						|
	}
 | 
						|
	return ok
 | 
						|
}
 | 
						|
 | 
						|
func parseNot[E any](p *Parser[Predicate[E]], s *Scanner) Predicate[E] {
 | 
						|
	preds := parseVariadicPredicate(p, s)
 | 
						|
	if len(preds) != 1 {
 | 
						|
		panic(errors.Newf("dsl: not accepts exactly 1 argument, given %d", len(preds)))
 | 
						|
	}
 | 
						|
	return not[E]{Predicate: preds[0]}
 | 
						|
}
 | 
						|
 | 
						|
func parseAnd[E any](p *Parser[Predicate[E]], s *Scanner) Predicate[E] {
 | 
						|
	return And[E](parseVariadicPredicate[E](p, s)...)
 | 
						|
}
 | 
						|
 | 
						|
func parseOr[E any](p *Parser[Predicate[E]], s *Scanner) Predicate[E] {
 | 
						|
	return Or[E](parseVariadicPredicate[E](p, s)...)
 | 
						|
}
 | 
						|
 | 
						|
func parseOnIndex[E any](p *Parser[Predicate[E]], s *Scanner) Predicate[E] {
 | 
						|
	i, err := strconv.ParseInt(s.Consume(token.INT).Lit, 10, 32)
 | 
						|
	if err != nil {
 | 
						|
		panic(err)
 | 
						|
	}
 | 
						|
	s.Consume(token.RPAREN)
 | 
						|
	return OnIndex[E](int32(i))
 | 
						|
}
 | 
						|
 | 
						|
func parseVariadicPredicate[E any](p *Parser[Predicate[E]], s *Scanner) (ret []Predicate[E]) {
 | 
						|
	tok := s.Scan()
 | 
						|
	for tok.Kind == token.LPAREN || tok.Kind == token.IDENT {
 | 
						|
		ret = append(ret, p.ParseFromPos(s, tok))
 | 
						|
		tok = s.Scan()
 | 
						|
	}
 | 
						|
	assertTok(tok, token.RPAREN)
 | 
						|
	return ret
 | 
						|
}
 |