<commit_before>package ast

import (
	"strconv"
	"strings"
)

func (s *StringExpr) String() string {
	if s.quoted {
		return `"` + stringify(s.str) + `"`
	}

	return s.str
}

func (i *IntExpr) String() string {
	return strconv.Itoa(i.val)
}

func (l *ListExpr) string() (string, bool) {
	elems := make([]string, len(l.list))
	columnCount := 0
	forceMulti := false

	for i := 0; i < len(l.list); i++ {
		if l.list[i].Type() == NodeListExpr {
			forceMulti = true
		}

		elems[i] = l.list[i].String()
		columnCount += len(elems[i])
	}

	if columnCount+len(elems) > 50 || forceMulti {
		forceMulti = true
		return "(\n\t" + strings.Join(elems, "\n\t") + "\n)", forceMulti
	}

	return "(" + strings.Join(elems, " ") + ")", false
}

func (l *ListExpr) String() string {
	str, _ := l.string()
	return str
}

func (c *ConcatExpr) String() string {
	ret := ""

	for i := 0; i < len(c.concat); i++ {
		ret += c.concat[i].String()

		if i < (len(c.concat) - 1) {
			ret += "+"
		}
	}

	return ret
}

func (v *VarExpr) String() string {
	return v.name
}

func (i *IndexExpr) String() string {
	return i.variable.String() + "[" + i.index.String() + "]"
}

func (l *BlockNode) adjustGroupAssign(node assignable, nodes []Node) {
	var (
		eqSpace int = node.getEqSpace()
		i       int
	)

	eqSpace = len(node.Identifier()) + 1

	for i = 0; i < len(nodes); i++ {
		assign, ok := nodes[i].(assignable)

		if !ok {
			break
		}

		if len(assign.Identifier())+1 > eqSpace {
			eqSpace = len(assign.Identifier()) + 1
		}
	}

	for j := 0; j < i; j++ {
		knode := nodes[j].(assignable)
		knode.setEqSpace(eqSpace)
	}

	node.setEqSpace(eqSpace)
}

func (l *BlockNode) String() string {
	nodes := l.Nodes
	content := make([]string, 0, 8192)

	last := (len(nodes) - 1)

	for i := 0; i < len(nodes); i++ {
		addEOL := false
		node := nodes[i]

		nodebytes := node.String()

		if i == 0 && node.Type() == NodeComment &&
			strings.HasPrefix(node.String(), "#!") {
			addEOL = true
		} else if (node.Type() == NodeComment) && i < last {
			nextNode := nodes[i+1]

			if nextNode.Line() > node.Line()+1 {
				addEOL = true
			}
		} else if i < last {
			nextNode := nodes[i+1]

			if node.Type() != nextNode.Type() {
				addEOL = true
			} else if node.Type() == NodeFnDecl {
				addEOL = true
			} else if node.Type() == NodeAssignment || node.Type() == NodeExecAssign {
				nodeAssign := node.(assignable)

				if nodeAssign.getEqSpace() == -1 {
					// lookahead to decide about best '=' distance
					l.adjustGroupAssign(nodeAssign, nodes[i+1:])
				}

				nodebytes, addEOL = nodeAssign.string()
			}
		}

		if addEOL {
			nodebytes += "\n"
		}

		content = append(content, nodebytes)
	}

	return strings.Join(content, "\n")
}

// String returns the string representation of the import
func (n *ImportNode) String() string {
	return `import ` + n.path.String()
}

// String returns the string representation of assignment
func (n *SetenvNode) String() string {
	return "setenv " + n.varName
}

func (n *AssignmentNode) string() (string, bool) {
	var (
		objStr string
		multi  bool
	)

	obj := n.val

	if obj.Type().IsExpr() {
		if obj.Type() == NodeListExpr {
			lobj := obj.(*ListExpr)
			objStr, multi = lobj.string()
		} else {
			objStr = obj.String()
		}

		if n.eqSpace > len(n.name) && !multi {
			ret := n.name + strings.Repeat(" ", n.eqSpace-len(n.name)) + "= " + objStr
			return ret, multi
		}

		ret := n.name + " = " + objStr
		return ret, multi
	}

	return "<unknown>", false
}

// String returns the string representation of assignment statement
func (n *AssignmentNode) String() string {
	str, _ := n.string()
	return str
}

func (n *ExecAssignNode) string() (string, bool) {
	var (
		cmdStr string
		multi  bool
	)

	if n.cmd.Type() == NodeCommand {
		cmd := n.cmd.(*CommandNode)
		cmdStr, multi = cmd.string()
	} else if n.cmd.Type() == NodePipe {
		cmd := n.cmd.(*PipeNode)
		cmdStr, multi = cmd.string()
	} else {
		cmd := n.cmd.(*FnInvNode)
		cmdStr, multi = cmd.string()
	}

	if n.eqSpace > len(n.name) {
		ret := n.name + strings.Repeat(" ", n.eqSpace-len(n.name)) + "<= " + cmdStr
		return ret, multi
	}

	return n.name + " <= " + cmdStr, multi
}

// String returns the string representation of command assignment statement
func (n *ExecAssignNode) String() string {
	str, _ := n.string()
	return str
}

func (n *CommandNode) toStringParts() ([]string, int) {
	var (
		content  []string
		line     string
		last     = len(n.args) - 1
		totalLen = 0
	)

	for i := 0; i < len(n.args); i += 2 {
		var next string

		arg := n.args[i].String()

		if i < last {
			next = n.args[i+1].String()
		}

		if i == 0 {
			arg = n.name + " " + arg
		}

		if arg[0] == '-' {
			if line != "" {
				content = append(content, line)
				line = ""
			}

			if next[0] != '-' {
				if line == "" {
					line += arg + " " + next
				} else {
					line += " " + arg + " " + next
				}
			} else {
				content = append(content, arg, next)
			}
		} else if next != "" {
			if line == "" {
				line += arg + " " + next
			} else {
				line += " " + arg + " " + next
			}
		} else {
			if line == "" {
				line += arg
			} else {<commit_msg>fix array out of bounds panic<commit_after>package ast

import (
	"strconv"
	"strings"
)

func (s *StringExpr) String() string {
	if s.quoted {
		return `"` + stringify(s.str) + `"`
	}

	return s.str
}

func (i *IntExpr) String() string {
	return strconv.Itoa(i.val)
}

func (l *ListExpr) string() (string, bool) {
	elems := make([]string, len(l.list))
	columnCount := 0
	forceMulti := false

	for i := 0; i < len(l.list); i++ {
		if l.list[i].Type() == NodeListExpr {
			forceMulti = true
		}

		elems[i] = l.list[i].String()
		columnCount += len(elems[i])
	}

	if columnCount+len(elems) > 50 || forceMulti {
		forceMulti = true
		return "(\n\t" + strings.Join(elems, "\n\t") + "\n)", forceMulti
	}

	return "(" + strings.Join(elems, " ") + ")", false
}

func (l *ListExpr) String() string {
	str, _ := l.string()
	return str
}

func (c *ConcatExpr) String() string {
	ret := ""

	for i := 0; i < len(c.concat); i++ {
		ret += c.concat[i].String()

		if i < (len(c.concat) - 1) {
			ret += "+"
		}
	}

	return ret
}

func (v *VarExpr) String() string {
	return v.name
}

func (i *IndexExpr) String() string {
	return i.variable.String() + "[" + i.index.String() + "]"
}

func (l *BlockNode) adjustGroupAssign(node assignable, nodes []Node) {
	var (
		eqSpace int = node.getEqSpace()
		i       int
	)

	eqSpace = len(node.Identifier()) + 1

	for i = 0; i < len(nodes); i++ {
		assign, ok := nodes[i].(assignable)

		if !ok {
			break
		}

		if len(assign.Identifier())+1 > eqSpace {
			eqSpace = len(assign.Identifier()) + 1
		}
	}

	for j := 0; j < i; j++ {
		knode := nodes[j].(assignable)
		knode.setEqSpace(eqSpace)
	}

	node.setEqSpace(eqSpace)
}

func (l *BlockNode) String() string {
	nodes := l.Nodes
	content := make([]string, 0, 8192)

	last := (len(nodes) - 1)

	for i := 0; i < len(nodes); i++ {
		addEOL := false
		node := nodes[i]

		nodebytes := node.String()

		if i == 0 && node.Type() == NodeComment &&
			strings.HasPrefix(node.String(), "#!") {
			addEOL = true
		} else if (node.Type() == NodeComment) && i < last {
			nextNode := nodes[i+1]

			if nextNode.Line() > node.Line()+1 {
				addEOL = true
			}
		} else if i < last {
			nextNode := nodes[i+1]

			if node.Type() != nextNode.Type() {
				addEOL = true
			} else if node.Type() == NodeFnDecl {
				addEOL = true
			} else if node.Type() == NodeAssignment || node.Type() == NodeExecAssign {
				nodeAssign := node.(assignable)

				if nodeAssign.getEqSpace() == -1 {
					// lookahead to decide about best '=' distance
					l.adjustGroupAssign(nodeAssign, nodes[i+1:])
				}

				nodebytes, addEOL = nodeAssign.string()
			}
		}

		if addEOL {
			nodebytes += "\n"
		}

		content = append(content, nodebytes)
	}

	return strings.Join(content, "\n")
}

// String returns the string representation of the import
func (n *ImportNode) String() string {
	return `import ` + n.path.String()
}

// String returns the string representation of assignment
func (n *SetenvNode) String() string {
	return "setenv " + n.varName
}

func (n *AssignmentNode) string() (string, bool) {
	var (
		objStr string
		multi  bool
	)

	obj := n.val

	if obj.Type().IsExpr() {
		if obj.Type() == NodeListExpr {
			lobj := obj.(*ListExpr)
			objStr, multi = lobj.string()
		} else {
			objStr = obj.String()
		}

		if n.eqSpace > len(n.name) && !multi {
			ret := n.name + strings.Repeat(" ", n.eqSpace-len(n.name)) + "= " + objStr
			return ret, multi
		}

		ret := n.name + " = " + objStr
		return ret, multi
	}

	return "<unknown>", false
}

// String returns the string representation of assignment statement
func (n *AssignmentNode) String() string {
	str, _ := n.string()
	return str
}

func (n *ExecAssignNode) string() (string, bool) {
	var (
		cmdStr string
		multi  bool
	)

	if n.cmd.Type() == NodeCommand {
		cmd := n.cmd.(*CommandNode)
		cmdStr, multi = cmd.string()
	} else if n.cmd.Type() == NodePipe {
		cmd := n.cmd.(*PipeNode)
		cmdStr, multi = cmd.string()
	} else {
		cmd := n.cmd.(*FnInvNode)
		cmdStr, multi = cmd.string()
	}

	if n.eqSpace > len(n.name) {
		ret := n.name + strings.Repeat(" ", n.eqSpace-len(n.name)) + "<= " + cmdStr
		return ret, multi
	}

	return n.name + " <= " + cmdStr, multi
}

// String returns the string representation of command assignment statement
func (n *ExecAssignNode) String() string {
	str, _ := n.string()
	return str
}

func (n *CommandNode) toStringParts() ([]string, int) {
	var (
		content  []string
		line     string
		last     = len(n.args) - 1
		totalLen = 0
	)

	for i := 0; i < len(n.args); i += 2 {
		var next string

		arg := n.args[i].String()

		if i < last {
			next = n.args[i+1].String()
		}

		if i == 0 {
			arg = n.name + " " + arg
		}

		if arg[0] == '-' {
			if line != "" {
				content = append(content, line)
				line = ""
			}

			if len(next) > 0 && next[0] != '-' {
				if line == "" {
					line += arg + " " + next
				} else {
					line += " " + arg + " " + next
				}
			} else {
				content = append(content, arg, next)
			}
		} else if next != "" {
			if line == "" {
				line += arg + " " + next
			} else {
				line += " " + arg + " " + next
			}
		} else {
			if line == "" {
				line += arg
			} else {
{'fraction_non_alphanumeric': 0.18071115440818314, 'fraction_numerical': 0.0063321967851924016, 'mean_word_length': 2.7222625090645396, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 16, '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': '4390471', 'n_tokens_mistral': 4358, 'n_tokens_neox': 3860, 'n_words': 995}