<commit_before>package vrp

import (
	"fmt"
	"log"
	"math/big"

	"honnef.co/go/ssa"
)

// s1 + s2
// s[:]
// len(s)
// "" -> len("")
// s1 == s2
// len(s1) <cmp> x

type StringInterval struct {
	Length IntInterval
}

func (s StringInterval) Union(other Range) Range {
	i, ok := other.(StringInterval)
	if !ok {
		i = StringInterval{EmptyIntInterval}
	}
	if s.Length.Empty() || !s.Length.IsKnown() {
		return i
	}
	if i.Length.Empty() || !i.Length.IsKnown() {
		return s
	}
	return StringInterval{
		Length: s.Length.Union(i.Length).(IntInterval),
	}
}

func (s StringInterval) String() string {
	return s.Length.String()
}

func (s StringInterval) IsKnown() bool {
	return s.Length.IsKnown()
}

type StringSliceConstraint struct {
	aConstraint
	X     ssa.Value
	Lower ssa.Value
	Upper ssa.Value
}

func (c *StringSliceConstraint) String() string {
	var lname, uname string
	if c.Lower != nil {
		lname = c.Lower.Name()
	}
	if c.Upper != nil {
		uname = c.Upper.Name()
	}
	return fmt.Sprintf("%s[%s:%s]", c.X.Name(), lname, uname)
}

func (c *StringSliceConstraint) Eval(g *Graph) Range {
	lr := NewIntInterval(NewZ(&big.Int{}), NewZ(&big.Int{}))
	if c.Lower != nil {
		lr = g.Range(c.Lower).(IntInterval)
	}
	ur := g.Range(c.X).(StringInterval).Length
	if c.Upper != nil {
		ur = g.Range(c.Upper).(IntInterval)
	}
	if !lr.IsKnown() || !ur.IsKnown() {
		return StringInterval{}
	}

	ls := []Z{
		ur.lower.Sub(lr.lower),
		ur.upper.Sub(lr.lower),
		ur.lower.Sub(lr.upper),
		ur.upper.Sub(lr.upper),
	}
	// TODO(dh): if we don't truncate lengths to 0 we might be able to
	// easily detect slices with high < low. we'd need to treat -∞
	// specially, though.
	for i, l := range ls {
		if l.Sign() == -1 {
			ls[i] = NewZ(&big.Int{})
		}
	}

	return StringInterval{
		Length: NewIntInterval(MinZ(ls...), MaxZ(ls...)),
	}
}

func (c *StringSliceConstraint) Operands() []ssa.Value {
	vs := []ssa.Value{c.X}
	if c.Lower != nil {
		vs = append(vs, c.Lower)
	}
	if c.Upper != nil {
		vs = append(vs, c.Upper)
	}
	return vs
}

type StringIntersectionConstraint struct {
	aConstraint
	X ssa.Value
	I IntInterval
}

func (c *StringIntersectionConstraint) Operands() []ssa.Value {
	return []ssa.Value{c.X}
}

func (c *StringIntersectionConstraint) Eval(g *Graph) Range {
	xi := g.Range(c.X).(StringInterval)
	if !xi.IsKnown() {
		return c.I
	}
	return StringInterval{
		Length: xi.Length.Intersection(c.I),
	}
}

func (c *StringIntersectionConstraint) String() string {
	return fmt.Sprintf("%s = %s.%t ⊓ %s", c.Y().Name(), c.X.Name(), c.Y().(*ssa.Sigma).Branch, c.I)
}

type StringConcatConstraint struct {
	aConstraint
	A ssa.Value
	B ssa.Value
}

func NewStringConcatConstraint(a, b, y ssa.Value) Constraint {
	return &StringConcatConstraint{
		aConstraint: aConstraint{
			y: y,
		},
		A: a,
		B: b,
	}
}

func (c StringConcatConstraint) String() string {
	return fmt.Sprintf("%s = %s + %s", c.Y().Name(), c.A.Name(), c.B.Name())
}

func (c StringConcatConstraint) Eval(g *Graph) Range {
	i1, i2 := g.Range(c.A).(StringInterval), g.Range(c.B).(StringInterval)
	if !i1.Length.IsKnown() || !i2.Length.IsKnown() {
		return StringInterval{}
	}
	return StringInterval{
		Length: i1.Length.Add(i2.Length),
	}
}

func (c StringConcatConstraint) Operands() []ssa.Value {
	return []ssa.Value{c.A, c.B}
}

type StringLengthConstraint struct {
	aConstraint
	X ssa.Value
}

func NewStringLengthConstraint(x ssa.Value, y ssa.Value) Constraint {
	return &StringLengthConstraint{
		aConstraint: aConstraint{
			y: y,
		},
		X: x,
	}
}

func (c *StringLengthConstraint) String() string {
	return fmt.Sprintf("%s = len(%s)", c.Y().Name(), c.X.Name())
}

func (c *StringLengthConstraint) Eval(g *Graph) Range {
	i := g.Range(c.X).(StringInterval).Length
	log.Println(c.Y().Name(), i)
	if !i.IsKnown() {
		return NewIntInterval(NewZ(&big.Int{}), PInfinity)
	}
	return i
}

func (c *StringLengthConstraint) Operands() []ssa.Value {
	return []ssa.Value{c.X}
}

type StringIntervalConstraint struct {
	aConstraint
	I IntInterval
}

func (s *StringIntervalConstraint) Operands() []ssa.Value {
	return nil
}

func (c *StringIntervalConstraint) Eval(*Graph) Range {
	return StringInterval{c.I}
}

func (c *StringIntervalConstraint) String() string {
	return fmt.Sprintf("%s = %s", c.Y().Name(), c.I)<commit_msg>vrp: remove debug output<commit_after>package vrp

import (
	"fmt"
	"math/big"

	"honnef.co/go/ssa"
)

type StringInterval struct {
	Length IntInterval
}

func (s StringInterval) Union(other Range) Range {
	i, ok := other.(StringInterval)
	if !ok {
		i = StringInterval{EmptyIntInterval}
	}
	if s.Length.Empty() || !s.Length.IsKnown() {
		return i
	}
	if i.Length.Empty() || !i.Length.IsKnown() {
		return s
	}
	return StringInterval{
		Length: s.Length.Union(i.Length).(IntInterval),
	}
}

func (s StringInterval) String() string {
	return s.Length.String()
}

func (s StringInterval) IsKnown() bool {
	return s.Length.IsKnown()
}

type StringSliceConstraint struct {
	aConstraint
	X     ssa.Value
	Lower ssa.Value
	Upper ssa.Value
}

func (c *StringSliceConstraint) String() string {
	var lname, uname string
	if c.Lower != nil {
		lname = c.Lower.Name()
	}
	if c.Upper != nil {
		uname = c.Upper.Name()
	}
	return fmt.Sprintf("%s[%s:%s]", c.X.Name(), lname, uname)
}

func (c *StringSliceConstraint) Eval(g *Graph) Range {
	lr := NewIntInterval(NewZ(&big.Int{}), NewZ(&big.Int{}))
	if c.Lower != nil {
		lr = g.Range(c.Lower).(IntInterval)
	}
	ur := g.Range(c.X).(StringInterval).Length
	if c.Upper != nil {
		ur = g.Range(c.Upper).(IntInterval)
	}
	if !lr.IsKnown() || !ur.IsKnown() {
		return StringInterval{}
	}

	ls := []Z{
		ur.lower.Sub(lr.lower),
		ur.upper.Sub(lr.lower),
		ur.lower.Sub(lr.upper),
		ur.upper.Sub(lr.upper),
	}
	// TODO(dh): if we don't truncate lengths to 0 we might be able to
	// easily detect slices with high < low. we'd need to treat -∞
	// specially, though.
	for i, l := range ls {
		if l.Sign() == -1 {
			ls[i] = NewZ(&big.Int{})
		}
	}

	return StringInterval{
		Length: NewIntInterval(MinZ(ls...), MaxZ(ls...)),
	}
}

func (c *StringSliceConstraint) Operands() []ssa.Value {
	vs := []ssa.Value{c.X}
	if c.Lower != nil {
		vs = append(vs, c.Lower)
	}
	if c.Upper != nil {
		vs = append(vs, c.Upper)
	}
	return vs
}

type StringIntersectionConstraint struct {
	aConstraint
	X ssa.Value
	I IntInterval
}

func (c *StringIntersectionConstraint) Operands() []ssa.Value {
	return []ssa.Value{c.X}
}

func (c *StringIntersectionConstraint) Eval(g *Graph) Range {
	xi := g.Range(c.X).(StringInterval)
	if !xi.IsKnown() {
		return c.I
	}
	return StringInterval{
		Length: xi.Length.Intersection(c.I),
	}
}

func (c *StringIntersectionConstraint) String() string {
	return fmt.Sprintf("%s = %s.%t ⊓ %s", c.Y().Name(), c.X.Name(), c.Y().(*ssa.Sigma).Branch, c.I)
}

type StringConcatConstraint struct {
	aConstraint
	A ssa.Value
	B ssa.Value
}

func NewStringConcatConstraint(a, b, y ssa.Value) Constraint {
	return &StringConcatConstraint{
		aConstraint: aConstraint{
			y: y,
		},
		A: a,
		B: b,
	}
}

func (c StringConcatConstraint) String() string {
	return fmt.Sprintf("%s = %s + %s", c.Y().Name(), c.A.Name(), c.B.Name())
}

func (c StringConcatConstraint) Eval(g *Graph) Range {
	i1, i2 := g.Range(c.A).(StringInterval), g.Range(c.B).(StringInterval)
	if !i1.Length.IsKnown() || !i2.Length.IsKnown() {
		return StringInterval{}
	}
	return StringInterval{
		Length: i1.Length.Add(i2.Length),
	}
}

func (c StringConcatConstraint) Operands() []ssa.Value {
	return []ssa.Value{c.A, c.B}
}

type StringLengthConstraint struct {
	aConstraint
	X ssa.Value
}

func NewStringLengthConstraint(x ssa.Value, y ssa.Value) Constraint {
	return &StringLengthConstraint{
		aConstraint: aConstraint{
			y: y,
		},
		X: x,
	}
}

func (c *StringLengthConstraint) String() string {
	return fmt.Sprintf("%s = len(%s)", c.Y().Name(), c.X.Name())
}

func (c *StringLengthConstraint) Eval(g *Graph) Range {
	i := g.Range(c.X).(StringInterval).Length
	if !i.IsKnown() {
		return NewIntInterval(NewZ(&big.Int{}), PInfinity)
	}
	return i
}

func (c *StringLengthConstraint) Operands() []ssa.Value {
	return []ssa.Value{c.X}
}

type StringIntervalConstraint struct {
	aConstraint
	I IntInterval
}

func (s *StringIntervalConstraint) Operands() []ssa.Value {
	return nil
}

func (c *StringIntervalConstraint) Eval(*Graph) Range {
	return StringInterval{c.I}
}

func (c *StringIntervalConstraint) String() string {
	return fmt.Sprintf("%s = %s", c.Y().Name(), c.I)
{'fraction_non_alphanumeric': 0.17274449443523562, 'fraction_numerical': 0.0024863840871418423, 'mean_word_length': 3.8657834101382487, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4119447', 'n_tokens_mistral': 3388, 'n_tokens_neox': 3276, 'n_words': 755}