/*
 NAME
 	cexpconst.m - source code for CExpConst class
 VERSION
 	$Id$
 CHANGELOG
 	$Log$
 */

#include <coconut/cexpconst.h>
#include <coconut/cint.h>
#include <coconut/creal.h>
#include <coconut/cstring.h>
#include <coconut/ptext.h>

@implementation CExpConst

+ newExpConstInt: (int) val format: (int_format_t) form 
{
	id <PNumber>	num ;
	id <PExp>	exp ;

	num = [CInt newInt: val format: form] ;
	exp = [[CExpConst alloc] initExpConst: num] ;
	g_assert(num != nil && exp != nil) ;
	[num release] ;
	return exp ;
}

+ newExpConstReal: (double) val
{
	id <PNumber>	num ;
	id <PExp>	exp ;

	num = [CReal newReal: val] ;
	exp = [[CExpConst alloc] initExpConst: num] ;
	g_assert(num != nil && exp != nil) ;
	[num release] ;
	return exp ;
}

- initExpConst: (id <PNumber>) value ;
{
	if(value){
		const_status = obj_status_constant ;
		const_value = value ; [const_value retain] ;
	} else {
		const_status = obj_status_uninit ;
		const_value = [CInt newInt: 0 format: dec_format] ;
	}
	return [super init] ;
}

- init
{
	const_status = obj_status_uninit ;
	const_value = [CInt newInt: 0 format: dec_format] ;
	return [super init] ;
}

- (void) dealloc
{
	[const_value release] ;
	[super dealloc] ;
}

- (exp_t) type
{
	return const_exp ;
}

- (id <PNumber>) eval
{
	return const_value ;
}

- setValue: (id <PNumber>) value
{
	[const_value release] ;
	const_status = obj_status_constant ;
	const_value = value ; [const_value retain] ;
	return nil ;
}

- (obj_status_t) status
{
	return const_status ;
}

- (id <PString>) toString
{
	id <PString>	newstr ;
	if(const_status == obj_status_constant) {
		return [const_value toString] ;
	} else {
		newstr = [[CString alloc] init] ;
		[newstr setPtr: "(unknown_constant)"] ;
		return newstr ;
	}
}

#define	EXP	((id <PExpConst>) src)
#define	INT(V)	((int) V)
- (int) compare: (id) src
{
	id <PNumber>	val ;
	int		diff ;
	if((diff = INT(const_status) - INT([EXP status])) != 0)
		return diff ;
	if((val = [EXP eval]) != nil)
		return [const_value compare: val] ;
	else
		return (int) self ;
}

- (u_int) hashkey
{
	return (INT(const_status) << 8) + [const_value hashkey] ;
}

#define	STREAM	((id <PIndentStream>) stream)
- print: (id) stream
{
	id <PString>	str ;

	str = [self toString] ;
	[STREAM putStr: str] ;
	[str release] ;
	return nil ;
}

@end

