/*	Copyright  (c)	Günter Woigk 2010 - 2021
					mailto:kio@little-bat.de

	This file is free software.

	Permission to use, copy, modify, distribute, and sell this software
	and its documentation for any purpose is hereby granted without fee,
	provided that the above copyright notice appears in all copies and
	that both that copyright notice, this permission notice and the
	following disclaimer appear in supporting documentation.

	THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY,
	NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
	A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE COPYRIGHT HOLDER
	BE LIABLE FOR ANY DAMAGES ARISING FROM THE USE OF THIS SOFTWARE,
	TO THE EXTENT PERMITTED BY APPLICABLE LAW.
*/

#pragma once
#include "kio/kio.h"
//#include "Templates/Array.h"
//#include "NameID.h"
#include "Type.h"
//#include "types.h"



class Ival
{
	// Ival ("immediate value") combines a value with a type.
	// Supported types are: numeric (basic types and enum) and cstrings.
	// Values with a signed integer type are guaranteed to fit in int64.
	// Values with a unsigned integer type are guaranteed to fit in uint64.

public:
	cType* type;
	//uint64 dummy_padding = 0;

	union  // value
	{
		float128 value;
		cstr	 string;
	};

//	Ival (cType* t)					noexcept :type(t),value(0) {}
	Ival (cType* t, float128 n)		noexcept;	// value of integer types must fit in u/long
	Ival (cstr utf8string)			noexcept;	// cstrings: sets errno for utf8_to_ucs1/2 conversion
//	Ival (int64 n)					noexcept;	// nothrow even if value exceeds tlong
//	Ival (uint64 n)					noexcept;	// nothrow even if value exceeds tulong
	~Ival();
	Ival (Ival const&);
	Ival (Ival&&);
//	Ival& operator= (Ival const&);
	Ival& operator= (Ival&&);

	bool isChar			()	const	{ return type->isChar(); }
	bool isNumeric		()	const	{ return type->isNumeric(); }
	bool isInteger		()	const	{ return type->isInteger(); }
	bool isSignedInt	()	const	{ return type->isSignedInt(); }
	bool isUnsignedInt	()	const	{ return type->isUnsignedInt(); }
	bool isFloat		()	const	{ return type->isFloat(); }
	bool isString		()	const	{ return type->isString(); }

	int8	i8Value		()	const	{ assert(isNumeric()); assert(value ==  int8 (value));	return  int8 (value); }
	uint8	u8Value		()	const	{ assert(isNumeric()); assert(value == uint8 (value));	return uint8 (value); }
	int16	i16Value	()	const	{ assert(isNumeric()); assert(value ==  int16(value));	return  int16(value); }
	uint16	u16Value	()	const	{ assert(isNumeric()); assert(value == uint16(value));	return uint16(value); }
	int32	i32Value	()	const	{ assert(isNumeric()); assert(value ==  int32(value));	return  int32(value); }
	uint32	u32Value	()	const	{ assert(isNumeric()); assert(value == uint32(value));	return uint32(value); }
	int64	i64Value	()	const	{ assert(isNumeric()); assert(value ==  int64(value));	return  int64(value); }
	uint64	u64Value	()	const	{ assert(isNumeric()); assert(value == uint64(value));	return uint64(value); }
	float32	f32Value	()	const	{ assert(isNumeric()); return float32(value); }
	float64	f64Value	()	const	{ assert(isNumeric()); return float64(value); }
	float128 f128Value	()	const	{ assert(isNumeric()); return value; }
	float128 getValue	()	const	{ assert(isNumeric()); return value; }
	cstr	getString	()	const	{ assert(isString());  return string; }
	uint32  getChar		() const	{ assert(isChar());    return uint32(value); }

	int64	rawInt64	()	const	{ assert(isNumeric()); return value<0 ? int64(value) : int64(uint64(value)); }
	uint64	rawUInt64	()	const	{ assert(isNumeric()); return value<0 ? uint64(int64(value)) : uint64(value); }

	cstr toString		()	const;
};













