/*	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 "types.h"
#include <cfloat>
#include "Templates/HashMap.h"
#include "NameID.h"


namespace pp
{

typedef Array<cType*> Types;
class Type;
using cType = const Type;


enum TypeID : uint16
{
	VOID = 0,
	INT8,
	INT16,
	INT32,
	INT64,
	UINT8,
	UINT16,
	UINT32,
	UINT64,
	FLOAT32,
	FLOAT64,
	FLOAT128,
	CHAR,CSTR,
};


class Type
{
public:
	NameID name;		// short name: tUINT8, "int(bool,int)", ...
	TypeID type;		// class identifier: VOID, UINT32, ENUM, ...
	uint16 bits;		// size is measured in bits

	uint16 precision;		// fp only
	int16  min_exp;			// fp only
	int16  max_exp;			// fp only
	bool   denormalizing;	// fp only
	bool   filler;

	const float128 max;		// numeric limits
	const float128 min;		// numeric limits

public:
	Type (NameID, TypeID, uint bits);
	Type (NameID, TypeID, uint bits, float128 min, float128 max); // int
	Type (NameID, TypeID, uint bits, float128 min, float128 max, uint16, int16, int16, bool);	// fp

	// classification of basic types:
	bool isVoid ()			const { return type == VOID; }
	bool isNotVoid () 		const { return type != VOID; }
	bool isNumeric () 		const { return type > VOID && type < CHAR; }
	bool isFloat () 		const { return type >= FLOAT32 && type <= FLOAT128; }
	bool isInteger () 		const { return type >= INT8 && type <= UINT64; }
	bool isSignedInt () 	const { return type >= INT8 && type <= INT64; }
	bool isUnsignedInt () 	const { return type >= UINT8 && type <= UINT64; }
	bool isString () 		const { return type == CSTR; }
	bool isChar ()			const { return type == CHAR; }

	bool isInLimit (float128 n)			const noexcept { return n >= min && n <= max; }

	bool canRepresent (float128)		const noexcept;	// numeric: in limit && not denormalized
	bool isNaN (float128)				const noexcept;	// fp
	bool isInfinity (float128)			const noexcept;	// fp
	bool isDenormalized (float128)		const noexcept;	// fp
	bool isRoundToZero (float128)		const noexcept;	// fp
	uint numLostBits (float128)			const noexcept;	// fp

	void print (FD& fd, cstr indent)	const;
};


} // namespace




















