/*
	Copyright 2010-2011 Leszek Dubiel <leszek@dubiel.pl>

	This file is part of Treep.

	Treep is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	Treep is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Treep. If not, see <http://www.gnu.org/licenses/>.
*/

#define VOID 0x0
#define	SPAC 0x1
#define	TABU 0x2
#define	LINE 0x3
#define	LPAR 0x4
#define	RPAR 0x5
#define NUMB 0x6
#define NAME 0x7
#define	TEXT 0x8
#define	BOOL 0x9
#define	NODE 0xA
#define	TREE 0xB

struct vlue {
	unsigned int type;
	union {
		long double numb;
		char *name;
		char *text;
		int bool;
		struct node *node;
		struct tree *tree;
	} data;
};

#define CALL 0x0
#define VLUE 0x1

struct expr {
	unsigned int type;
	union {
		struct expr *call;
		struct vlue *vlue;
	} data;
	struct expr *next;
};

#define CORE 0x0
#define USER 0x1

struct func {
	char *name;
	int type;
	union {
		struct vlue *(*core) (size_t, struct vlue **);
		struct {
			size_t parc;
			char **parv;
			struct expr *expr;
		} user;
	} body;
};

extern struct tree *func;	/* global */
extern struct tree *tree;	/* global */

/* 
 * Numbers in treep are of type long double, so computations can use only 
 * LDBL_DIG digits. Minimum and maximum numbers are
 *
 *	0.00000000000000001 = powl(10.0L, 1 - LDBL_DIG)
 * 	99999999999999999.9 = powl(10.0L, LDBL_DIG - 1) - 0.1L
 * 	1234567890.12345678 : 18 digits, dot, 19 chars total .
 * 
 * Every operation on numbers must truncate number do display precission 
 * by using function numb_norm. Truncation is made by use of printf and 
 * scanf functions. Printf results are like this: 
 *
 * 	printf("%.17Lf", powl(10.0L, 1 - LDBL_DIG) * 0.5L) 
 * 						= 0.00000000000000000
 * 	printf("%.17Lf", powl(10.0L, 1 - LDBL_DIG) * 0.5L + ...) 
 * 						= 0.00000000000000001
 *	printf("%.1Lf", powl(10.0L, LDBL_DIG - 1) - 0.1L + 0.05L) 
 *						= 99999999999999999.9
 *	printf("%.1Lf", powl(10.0L, LDBL_DIG - 1) - 0.1L + 0.05L + ...) 
 *						= 100000000000000000.0 
 *	printf("%.7Lf", powl(10.0L, LDBL_DIG - 1) - 0.1L + 0.05L) 
 *						= 99999999999999999.9453125
 *	printf("%.7Lf", powl(10.0L, LDBL_DIG - 1) - 0.05L)
 *						= 99999999999999999.9531250 .
 *
 * Every number less or equal to MIN * 0.5L is converted to zero, and every 
 * number greater then MAX + 0.05L generates error. This is not perfect so we 
 * wait until _Decimal64 type is fully supported in compiler.
 */

long double numb_norm(long double);	/* round to display precission */
char *numb_text(long double);	/* number to text */
long double text_numb(char *);	/* text to number */

long double numb_read();
void numb_wrte(long double);
char *name_read();
void name_wrte(char *);
char *text_read();
void text_wrte(char *);

struct vlue *vlue_read(void);
void vlue_wrte(struct vlue *);

struct expr *expr_read(void);
void expr_wrte(struct expr *);

struct func *func_read(void);
void func_wrte(struct func *);

struct vlue *expr_vlue(struct expr *);
