package goja

import (
	
	
	
	
	
	
	

	
	
)

var (
	// Not goroutine-safe, do not use for anything other than package level init
	pkgHasher maphash.Hash

	hashFalse = randomHash()
	hashTrue  = randomHash()
	hashNull  = randomHash()
	hashUndef = randomHash()
)

// Not goroutine-safe, do not use for anything other than package level init
func randomHash() uint64 {
	pkgHasher.WriteByte(0)
	return pkgHasher.Sum64()
}

var (
	valueFalse    Value = valueBool(false)
	valueTrue     Value = valueBool(true)
	_null         Value = valueNull{}
	_NaN          Value = valueFloat(math.NaN())
	_positiveInf  Value = valueFloat(math.Inf(+1))
	_negativeInf  Value = valueFloat(math.Inf(-1))
	_positiveZero Value = valueInt(0)
	negativeZero        = math.Float64frombits(0 | (1 << 63))
	_negativeZero Value = valueFloat(negativeZero)
	_epsilon            = valueFloat(2.2204460492503130808472633361816e-16)
	_undefined    Value = valueUndefined{}
)

var (
	reflectTypeInt      = reflect.TypeOf(int64(0))
	reflectTypeBool     = reflect.TypeOf(false)
	reflectTypeNil      = reflect.TypeOf(nil)
	reflectTypeFloat    = reflect.TypeOf(float64(0))
	reflectTypeMap      = reflect.TypeOf(map[string]interface{}{})
	reflectTypeArray    = reflect.TypeOf([]interface{}{})
	reflectTypeArrayPtr = reflect.TypeOf((*[]interface{})(nil))
	reflectTypeString   = reflect.TypeOf("")
	reflectTypeFunc     = reflect.TypeOf((func(FunctionCall) Value)(nil))
	reflectTypeError    = reflect.TypeOf((*error)(nil)).Elem()
)

var intCache [256]Value

// Value represents an ECMAScript value.
//
// Export returns a "plain" Go value which type depends on the type of the Value.
//
// For integer numbers it's int64.
//
// For any other numbers (including Infinities, NaN and negative zero) it's float64.
//
// For string it's a string. Note that unicode strings are converted into UTF-8 with invalid code points replaced with utf8.RuneError.
//
// For boolean it's bool.
//
// For null and undefined it's nil.
//
// For Object it depends on the Object type, see Object.Export() for more details.
type Value interface {
	ToInteger() int64
	toString() String
	string() unistring.String
	ToString() Value
	String() string
	ToFloat() float64
	ToNumber() Value
	ToBoolean() bool
	ToObject(*Runtime) *Object
	SameAs(Value) bool
	Equals(Value) bool
	StrictEquals(Value) bool
	Export() interface{}
	ExportType() reflect.Type

	baseObject(r *Runtime) *Object

	hash(hasher *maphash.Hash) uint64
}

type valueContainer interface {
	toValue(*Runtime) Value
}

type typeError string
type rangeError string
type referenceError string
type syntaxError string

type valueInt int64
type valueFloat float64
type valueBool bool
type valueNull struct{}
type valueUndefined struct {
	valueNull
}

// *Symbol is a Value containing ECMAScript Symbol primitive. Symbols must only be created
// using NewSymbol(). Zero values and copying of values (i.e. *s1 = *s2) are not permitted.
// Well-known Symbols can be accessed using Sym* package variables (SymIterator, etc...)
// Symbols can be shared by multiple Runtimes.
type Symbol struct {
	h    uintptr
	desc String
}

type valueUnresolved struct {
	r   *Runtime
	ref unistring.String
}

type memberUnresolved struct {
	valueUnresolved
}

type valueProperty struct {
	value        Value
	writable     bool
	configurable bool
	enumerable   bool
	accessor     bool
	getterFunc   *Object
	setterFunc   *Object
}

var (
	errAccessBeforeInit = referenceError("Cannot access a variable before initialization")
	errAssignToConst    = typeError("Assignment to constant variable.")
	errMixBigIntType    = typeError("Cannot mix BigInt and other types, use explicit conversions")
)

func propGetter( Value,  Value,  *Runtime) *Object {
	if  == _undefined {
		return nil
	}
	if ,  := .(*Object);  {
		if ,  := .self.assertCallable();  {
			return 
		}
	}
	.typeErrorResult(true, "Getter must be a function: %s", .toString())
	return nil
}

func propSetter( Value,  Value,  *Runtime) *Object {
	if  == _undefined {
		return nil
	}
	if ,  := .(*Object);  {
		if ,  := .self.assertCallable();  {
			return 
		}
	}
	.typeErrorResult(true, "Setter must be a function: %s", .toString())
	return nil
}

func fToStr( float64,  ftoa.FToStrMode,  int) string {
	var  [128]byte
	return string(ftoa.FToStr(, , , [:0]))
}

func ( valueInt) () int64 {
	return int64()
}

func ( valueInt) () String {
	return asciiString(.String())
}

func ( valueInt) () unistring.String {
	return unistring.String(.String())
}

func ( valueInt) () Value {
	return 
}

func ( valueInt) () string {
	return strconv.FormatInt(int64(), 10)
}

func ( valueInt) () float64 {
	return float64()
}

func ( valueInt) () bool {
	return  != 0
}

func ( valueInt) ( *Runtime) *Object {
	return .newPrimitiveObject(, .getNumberPrototype(), classNumber)
}

func ( valueInt) () Value {
	return 
}

func ( valueInt) ( Value) bool {
	return  == 
}

func ( valueInt) ( Value) bool {
	switch o := .(type) {
	case valueInt:
		return  == 
	case *valueBigInt:
		return (*big.Int)().Cmp(big.NewInt(int64())) == 0
	case valueFloat:
		return float64() == float64()
	case String:
		return .ToNumber().Equals()
	case valueBool:
		return int64() == .ToInteger()
	case *Object:
		return .(.toPrimitive())
	}

	return false
}

func ( valueInt) ( Value) bool {
	switch o := .(type) {
	case valueInt:
		return  == 
	case valueFloat:
		return float64() == float64()
	}

	return false
}

func ( valueInt) ( *Runtime) *Object {
	return .getNumberPrototype()
}

func ( valueInt) () interface{} {
	return int64()
}

func ( valueInt) () reflect.Type {
	return reflectTypeInt
}

func ( valueInt) (*maphash.Hash) uint64 {
	return uint64()
}

func ( valueBool) () int64 {
	if  {
		return 1
	}
	return 0
}

func ( valueBool) () String {
	if  {
		return stringTrue
	}
	return stringFalse
}

func ( valueBool) () Value {
	return 
}

func ( valueBool) () string {
	if  {
		return "true"
	}
	return "false"
}

func ( valueBool) () unistring.String {
	return unistring.String(.String())
}

func ( valueBool) () float64 {
	if  {
		return 1.0
	}
	return 0
}

func ( valueBool) () bool {
	return bool()
}

func ( valueBool) ( *Runtime) *Object {
	return .newPrimitiveObject(, .getBooleanPrototype(), "Boolean")
}

func ( valueBool) () Value {
	if  {
		return valueInt(1)
	}
	return valueInt(0)
}

func ( valueBool) ( Value) bool {
	if ,  := .(valueBool);  {
		return  == 
	}
	return false
}

func ( valueBool) ( Value) bool {
	if ,  := .(valueBool);  {
		return  == 
	}

	if  {
		return .Equals(intToValue(1))
	} else {
		return .Equals(intToValue(0))
	}

}

func ( valueBool) ( Value) bool {
	if ,  := .(valueBool);  {
		return  == 
	}
	return false
}

func ( valueBool) ( *Runtime) *Object {
	return .getBooleanPrototype()
}

func ( valueBool) () interface{} {
	return bool()
}

func ( valueBool) () reflect.Type {
	return reflectTypeBool
}

func ( valueBool) (*maphash.Hash) uint64 {
	if  {
		return hashTrue
	}

	return hashFalse
}

func ( valueNull) () int64 {
	return 0
}

func ( valueNull) () String {
	return stringNull
}

func ( valueNull) () unistring.String {
	return stringNull.string()
}

func ( valueNull) () Value {
	return 
}

func ( valueNull) () string {
	return "null"
}

func ( valueUndefined) () String {
	return stringUndefined
}

func ( valueUndefined) () Value {
	return 
}

func ( valueUndefined) () string {
	return "undefined"
}

func ( valueUndefined) () unistring.String {
	return "undefined"
}

func ( valueUndefined) () Value {
	return _NaN
}

func ( valueUndefined) ( Value) bool {
	,  := .(valueUndefined)
	return 
}

func ( valueUndefined) ( Value) bool {
	,  := .(valueUndefined)
	return 
}

func ( valueUndefined) () float64 {
	return math.NaN()
}

func ( valueUndefined) (*maphash.Hash) uint64 {
	return hashUndef
}

func ( valueNull) () float64 {
	return 0
}

func ( valueNull) () bool {
	return false
}

func ( valueNull) ( *Runtime) *Object {
	.typeErrorResult(true, "Cannot convert undefined or null to object")
	return nil
	//return r.newObject()
}

func ( valueNull) () Value {
	return intToValue(0)
}

func ( valueNull) ( Value) bool {
	,  := .(valueNull)
	return 
}

func ( valueNull) ( Value) bool {
	switch .(type) {
	case valueUndefined, valueNull:
		return true
	}
	return false
}

func ( valueNull) ( Value) bool {
	,  := .(valueNull)
	return 
}

func ( valueNull) (*Runtime) *Object {
	return nil
}

func ( valueNull) () interface{} {
	return nil
}

func ( valueNull) () reflect.Type {
	return reflectTypeNil
}

func ( valueNull) (*maphash.Hash) uint64 {
	return hashNull
}

func ( *valueProperty) () int64 {
	return 0
}

func ( *valueProperty) () String {
	return stringEmpty
}

func ( *valueProperty) () unistring.String {
	return ""
}

func ( *valueProperty) () Value {
	return _undefined
}

func ( *valueProperty) () string {
	return ""
}

func ( *valueProperty) () float64 {
	return math.NaN()
}

func ( *valueProperty) () bool {
	return false
}

func ( *valueProperty) (*Runtime) *Object {
	return nil
}

func ( *valueProperty) () Value {
	return nil
}

func ( *valueProperty) () bool {
	return .writable || .setterFunc != nil
}

func ( *valueProperty) ( Value) Value {
	if .getterFunc == nil {
		if .value != nil {
			return .value
		}
		return _undefined
	}
	,  := .getterFunc.self.assertCallable()
	return (FunctionCall{
		This: ,
	})
}

func ( *valueProperty) (,  Value) {
	if .setterFunc == nil {
		.value = 
		return
	}
	,  := .setterFunc.self.assertCallable()
	(FunctionCall{
		This:      ,
		Arguments: []Value{},
	})
}

func ( *valueProperty) ( Value) bool {
	if ,  := .(*valueProperty);  {
		return  == 
	}
	return false
}

func ( *valueProperty) (Value) bool {
	return false
}

func ( *valueProperty) (Value) bool {
	return false
}

func ( *valueProperty) ( *Runtime) *Object {
	.typeErrorResult(true, "BUG: baseObject() is called on valueProperty") // TODO error message
	return nil
}

func ( *valueProperty) () interface{} {
	panic("Cannot export valueProperty")
}

func ( *valueProperty) () reflect.Type {
	panic("Cannot export valueProperty")
}

func ( *valueProperty) (*maphash.Hash) uint64 {
	panic("valueProperty should never be used in maps or sets")
}

func floatToIntClip( float64) int64 {
	switch {
	case math.IsNaN():
		return 0
	case  >= math.MaxInt64:
		return math.MaxInt64
	case  <= math.MinInt64:
		return math.MinInt64
	}
	return int64()
}

func ( valueFloat) () int64 {
	return floatToIntClip(float64())
}

func ( valueFloat) () String {
	return asciiString(.String())
}

func ( valueFloat) () unistring.String {
	return unistring.String(.String())
}

func ( valueFloat) () Value {
	return 
}

func ( valueFloat) () string {
	return fToStr(float64(), ftoa.ModeStandard, 0)
}

func ( valueFloat) () float64 {
	return float64()
}

func ( valueFloat) () bool {
	return float64() != 0.0 && !math.IsNaN(float64())
}

func ( valueFloat) ( *Runtime) *Object {
	return .newPrimitiveObject(, .getNumberPrototype(), "Number")
}

func ( valueFloat) () Value {
	return 
}

func ( valueFloat) ( Value) bool {
	switch o := .(type) {
	case valueFloat:
		 := float64()
		 := float64()
		if math.IsNaN() && math.IsNaN() {
			return true
		} else {
			 :=  == 
			if  &&  == 0 {
				 = math.Signbit() == math.Signbit()
			}
			return 
		}
	case valueInt:
		 := float64()
		 :=  == float64()
		if  &&  == 0 {
			 = !math.Signbit()
		}
		return 
	}

	return false
}

func ( valueFloat) ( Value) bool {
	switch o := .(type) {
	case valueFloat:
		return  == 
	case valueInt:
		return float64() == float64()
	case *valueBigInt:
		if IsInfinity() || math.IsNaN(float64()) {
			return false
		}
		if  := big.NewFloat(float64()); .IsInt() {
			,  := .Int(nil)
			return (*big.Int)().Cmp() == 0
		}
		return false
	case String, valueBool:
		return float64() == .ToFloat()
	case *Object:
		return .(.toPrimitive())
	}

	return false
}

func ( valueFloat) ( Value) bool {
	switch o := .(type) {
	case valueFloat:
		return  == 
	case valueInt:
		return float64() == float64()
	}

	return false
}

func ( valueFloat) ( *Runtime) *Object {
	return .getNumberPrototype()
}

func ( valueFloat) () interface{} {
	return float64()
}

func ( valueFloat) () reflect.Type {
	return reflectTypeFloat
}

func ( valueFloat) (*maphash.Hash) uint64 {
	if  == _negativeZero {
		return 0
	}
	return math.Float64bits(float64())
}

func ( *Object) () int64 {
	return .toPrimitiveNumber().ToNumber().ToInteger()
}

func ( *Object) () String {
	return .toPrimitiveString().toString()
}

func ( *Object) () unistring.String {
	return .toPrimitiveString().string()
}

func ( *Object) () Value {
	return .toPrimitiveString().ToString()
}

func ( *Object) () string {
	return .toPrimitiveString().String()
}

func ( *Object) () float64 {
	return .toPrimitiveNumber().ToFloat()
}

func ( *Object) () bool {
	return true
}

func ( *Object) (*Runtime) *Object {
	return 
}

func ( *Object) () Value {
	return .toPrimitiveNumber().ToNumber()
}

func ( *Object) ( Value) bool {
	return .StrictEquals()
}

func ( *Object) ( Value) bool {
	if ,  := .(*Object);  {
		return  ==  || .self.equal(.self)
	}

	switch o1 := .(type) {
	case valueInt, valueFloat, *valueBigInt, String, *Symbol:
		return .toPrimitive().Equals()
	case valueBool:
		return .(.ToNumber())
	}

	return false
}

func ( *Object) ( Value) bool {
	if ,  := .(*Object);  {
		return  ==  ||  != nil &&  != nil && .self.equal(.self)
	}
	return false
}

func ( *Object) (*Runtime) *Object {
	return 
}

// Export the Object to a plain Go type.
// If the Object is a wrapped Go value (created using ToValue()) returns the original value.
//
// If the Object is a function, returns func(FunctionCall) Value. Note that exceptions thrown inside the function
// result in panics, which can also leave the Runtime in an unusable state. Therefore, these values should only
// be used inside another ES function implemented in Go. For calling a function from Go, use AssertFunction() or
// Runtime.ExportTo() as described in the README.
//
// For a Map, returns the list of entries as [][2]interface{}.
//
// For a Set, returns the list of elements as []interface{}.
//
// For a Proxy, returns Proxy.
//
// For a Promise, returns Promise.
//
// For a DynamicObject or a DynamicArray, returns the underlying handler.
//
// For typed arrays it returns a slice of the corresponding type backed by the original data (i.e. it does not copy).
//
// For an untyped array, returns its items exported into a newly created []interface{}.
//
// In all other cases returns own enumerable non-symbol properties as map[string]interface{}.
//
// This method will panic with an *Exception if a JavaScript exception is thrown in the process. Use Runtime.Try to catch these.
func ( *Object) () interface{} {
	return .self.export(&objectExportCtx{})
}

// ExportType returns the type of the value that is returned by Export().
func ( *Object) () reflect.Type {
	return .self.exportType()
}

func ( *Object) (*maphash.Hash) uint64 {
	return .getId()
}

// Get an object's property by name.
// This method will panic with an *Exception if a JavaScript exception is thrown in the process. Use Runtime.Try to catch these.
func ( *Object) ( string) Value {
	return .self.getStr(unistring.NewFromString(), nil)
}

// GetSymbol returns the value of a symbol property. Use one of the Sym* values for well-known
// symbols (such as SymIterator, SymToStringTag, etc...).
// This method will panic with an *Exception if a JavaScript exception is thrown in the process. Use Runtime.Try to catch these.
func ( *Object) ( *Symbol) Value {
	return .self.getSym(, nil)
}

// Keys returns a list of Object's enumerable keys.
// This method will panic with an *Exception if a JavaScript exception is thrown in the process. Use Runtime.Try to catch these.
func ( *Object) () ( []string) {
	 := &enumerableIter{
		o:       ,
		wrapped: .self.iterateStringKeys(),
	}
	for ,  := .next();  != nil; ,  = () {
		 = append(, .name.String())
	}

	return
}

// GetOwnPropertyNames returns a list of all own string properties of the Object, similar to Object.getOwnPropertyNames()
// This method will panic with an *Exception if a JavaScript exception is thrown in the process. Use Runtime.Try to catch these.
func ( *Object) () ( []string) {
	for ,  := .self.iterateStringKeys()();  != nil; ,  = () {
		 = append(, .name.String())
	}

	return
}

// Symbols returns a list of Object's enumerable symbol properties.
// This method will panic with an *Exception if a JavaScript exception is thrown in the process. Use Runtime.Try to catch these.
func ( *Object) () []*Symbol {
	 := .self.symbols(false, nil)
	 := make([]*Symbol, len())
	for ,  := range  {
		[], _ = .(*Symbol)
	}
	return 
}

// DefineDataProperty is a Go equivalent of Object.defineProperty(o, name, {value: value, writable: writable,
// configurable: configurable, enumerable: enumerable})
func ( *Object) ( string,  Value, , ,  Flag) error {
	return .runtime.try(func() {
		.self.defineOwnPropertyStr(unistring.NewFromString(), PropertyDescriptor{
			Value:        ,
			Writable:     ,
			Configurable: ,
			Enumerable:   ,
		}, true)
	})
}

// DefineAccessorProperty is a Go equivalent of Object.defineProperty(o, name, {get: getter, set: setter,
// configurable: configurable, enumerable: enumerable})
func ( *Object) ( string, ,  Value, ,  Flag) error {
	return .runtime.try(func() {
		.self.defineOwnPropertyStr(unistring.NewFromString(), PropertyDescriptor{
			Getter:       ,
			Setter:       ,
			Configurable: ,
			Enumerable:   ,
		}, true)
	})
}

// DefineDataPropertySymbol is a Go equivalent of Object.defineProperty(o, name, {value: value, writable: writable,
// configurable: configurable, enumerable: enumerable})
func ( *Object) ( *Symbol,  Value, , ,  Flag) error {
	return .runtime.try(func() {
		.self.defineOwnPropertySym(, PropertyDescriptor{
			Value:        ,
			Writable:     ,
			Configurable: ,
			Enumerable:   ,
		}, true)
	})
}

// DefineAccessorPropertySymbol is a Go equivalent of Object.defineProperty(o, name, {get: getter, set: setter,
// configurable: configurable, enumerable: enumerable})
func ( *Object) ( *Symbol, ,  Value, ,  Flag) error {
	return .runtime.try(func() {
		.self.defineOwnPropertySym(, PropertyDescriptor{
			Getter:       ,
			Setter:       ,
			Configurable: ,
			Enumerable:   ,
		}, true)
	})
}

func ( *Object) ( string,  interface{}) error {
	return .runtime.try(func() {
		.self.setOwnStr(unistring.NewFromString(), .runtime.ToValue(), true)
	})
}

func ( *Object) ( *Symbol,  interface{}) error {
	return .runtime.try(func() {
		.self.setOwnSym(, .runtime.ToValue(), true)
	})
}

func ( *Object) ( string) error {
	return .runtime.try(func() {
		.self.deleteStr(unistring.NewFromString(), true)
	})
}

func ( *Object) ( *Symbol) error {
	return .runtime.try(func() {
		.self.deleteSym(, true)
	})
}

// Prototype returns the Object's prototype, same as Object.getPrototypeOf(). If the prototype is null
// returns nil.
func ( *Object) () *Object {
	return .self.proto()
}

// SetPrototype sets the Object's prototype, same as Object.setPrototypeOf(). Setting proto to nil
// is an equivalent of Object.setPrototypeOf(null).
func ( *Object) ( *Object) error {
	return .runtime.try(func() {
		.self.setProto(, true)
	})
}

// MarshalJSON returns JSON representation of the Object. It is equivalent to JSON.stringify(o).
// Note, this implements json.Marshaler so that json.Marshal() can be used without the need to Export().
func ( *Object) () ([]byte, error) {
	 := _builtinJSON_stringifyContext{
		r: .runtime,
	}
	 := .runtime.vm.try(func() {
		if !.do() {
			.buf.WriteString("null")
		}
	})
	if  != nil {
		return nil, 
	}
	return .buf.Bytes(), nil
}

// UnmarshalJSON implements the json.Unmarshaler interface. It is added to compliment MarshalJSON, because
// some alternative JSON encoders refuse to use MarshalJSON unless UnmarshalJSON is also present.
// It is a no-op and always returns nil.
func ( *Object) ([]byte) error {
	return nil
}

// ClassName returns the class name
func ( *Object) () string {
	return .self.className()
}

func ( valueUnresolved) () {
	.r.throwReferenceError(.ref)
}

func ( valueUnresolved) () int64 {
	.throw()
	return 0
}

func ( valueUnresolved) () String {
	.throw()
	return nil
}

func ( valueUnresolved) () unistring.String {
	.throw()
	return ""
}

func ( valueUnresolved) () Value {
	.throw()
	return nil
}

func ( valueUnresolved) () string {
	.throw()
	return ""
}

func ( valueUnresolved) () float64 {
	.throw()
	return 0
}

func ( valueUnresolved) () bool {
	.throw()
	return false
}

func ( valueUnresolved) (*Runtime) *Object {
	.throw()
	return nil
}

func ( valueUnresolved) () Value {
	.throw()
	return nil
}

func ( valueUnresolved) (Value) bool {
	.throw()
	return false
}

func ( valueUnresolved) (Value) bool {
	.throw()
	return false
}

func ( valueUnresolved) (Value) bool {
	.throw()
	return false
}

func ( valueUnresolved) (*Runtime) *Object {
	.throw()
	return nil
}

func ( valueUnresolved) () interface{} {
	.throw()
	return nil
}

func ( valueUnresolved) () reflect.Type {
	.throw()
	return nil
}

func ( valueUnresolved) (*maphash.Hash) uint64 {
	.throw()
	return 0
}

func ( *Symbol) () int64 {
	panic(typeError("Cannot convert a Symbol value to a number"))
}

func ( *Symbol) () String {
	panic(typeError("Cannot convert a Symbol value to a string"))
}

func ( *Symbol) () Value {
	return 
}

func ( *Symbol) () string {
	if .desc != nil {
		return .desc.String()
	}
	return ""
}

func ( *Symbol) () unistring.String {
	if .desc != nil {
		return .desc.string()
	}
	return ""
}

func ( *Symbol) () float64 {
	panic(typeError("Cannot convert a Symbol value to a number"))
}

func ( *Symbol) () Value {
	panic(typeError("Cannot convert a Symbol value to a number"))
}

func ( *Symbol) () bool {
	return true
}

func ( *Symbol) ( *Runtime) *Object {
	return .baseObject()
}

func ( *Symbol) ( Value) bool {
	if ,  := .(*Symbol);  {
		return  == 
	}
	return false
}

func ( *Symbol) ( Value) bool {
	switch o := .(type) {
	case *Object:
		return .(.toPrimitive())
	}
	return .SameAs()
}

func ( *Symbol) ( Value) bool {
	return .SameAs()
}

func ( *Symbol) () interface{} {
	return .String()
}

func ( *Symbol) () reflect.Type {
	return reflectTypeString
}

func ( *Symbol) ( *Runtime) *Object {
	return .newPrimitiveObject(, .getSymbolPrototype(), classObject)
}

func ( *Symbol) (*maphash.Hash) uint64 {
	return uint64(.h)
}

func exportValue( Value,  *objectExportCtx) interface{} {
	if ,  := .(*Object);  {
		return .self.export()
	}
	return .Export()
}

func newSymbol( String) *Symbol {
	 := &Symbol{
		desc: ,
	}
	// This may need to be reconsidered in the future.
	// Depending on changes in Go's allocation policy and/or introduction of a compacting GC
	// this may no longer provide sufficient dispersion. The alternative, however, is a globally
	// synchronised random generator/hasher/sequencer and I don't want to go down that route just yet.
	.h = uintptr(unsafe.Pointer())
	return 
}

func ( string) *Symbol {
	return newSymbol(newStringValue())
}

func ( *Symbol) () String {
	 := .desc
	if  == nil {
		 = stringEmpty
	}
	return asciiString("Symbol(").Concat().Concat(asciiString(")"))
}

func funcName( string,  Value) String {
	var  StringBuilder
	.WriteString(asciiString())
	if ,  := .(*Symbol);  {
		if .desc != nil {
			.WriteRune('[')
			.WriteString(.desc)
			.WriteRune(']')
		}
	} else {
		.WriteString(.toString())
	}
	return .String()
}

func newTypeError( ...interface{}) typeError {
	 := ""
	if len() > 0 {
		,  := [0].(string)
		 = fmt.Sprintf(, [1:]...)
	}
	return typeError()
}

func typeErrorResult( bool,  ...interface{}) {
	if  {
		panic(newTypeError(...))
	}

}

func init() {
	for  := 0;  < 256; ++ {
		intCache[] = valueInt( - 256)
	}
}