package main

import (
	"slices"
	"unicode"
)

var whitespaceChars = []rune{' ', '\t', '\n'}
var digitChars = []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
var wordChars = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_")

func dotChars() []rune { // Returns all possible characters represented by the dot metacharacter - this is too tedious to define as a variable, which is why it is a function
	start := 0x0020
	end := 0x007E
	to_return := make([]rune, (end-start)+1)
	for i := start; i <= end; i++ {
		to_return = append(to_return, rune(i))
	}
	return to_return
}

func isAlphaNum(c rune) bool {
	return unicode.IsLetter(c) || unicode.IsNumber(c)
}

func assert(cond bool) {
	if cond != true {
		panic("Assertion Failed")
	}
}

// Ensure that the given elements are only appended to the given slice if they
// don't already exist. Returns the new slice, and the number of unique items appended.
func unique_append[T comparable](slc []T, items ...T) ([]T, int) {
	num_appended := 0
	for _, item := range items {
		if !slices.Contains(slc, item) {
			slc = append(slc, item)
			num_appended++
		}
	}
	return slc, num_appended
}

// Returns true only if all the given elements are equal
func allEqual[T comparable](items ...T) bool {
	first := items[0]
	for _, item := range items {
		if item != first {
			return false
		}
	}
	return true
}