//--------------------------------------------------------------------------------------
//
// X-BASIC'
// 	構造&サイズ定義
//
//--------------------------------------------------------------------------------------
// fdef.h X68k XC Compiler v2.00 Copyright 1990 SHARP/Hudsonを「少し」ベースとしている

#ifndef	__XB_FDEF__
#define __XB_FDEF__	1

#include "XBdefines.h"

#include <stdio.h>		// printf()/sprintf()/FILE *
#include <stdlib.h>		// malloc()/qsort()
#include <string.h>		// strcpy()/strcat()/memset()

//--------------------------------------------------------------------------------------
// データサイズ

#define	SZ_INT		(sizeof(ULong))			// X-BASICのint型サイズ
#define	SZ_FLOAT	(sizeof(DOUBLE_LONG))	// X-BASICのfloat型サイズ=sizeof(double)
// SZ_CHARはXBdefines.hのそれをそのまま利用

#define	MAX_SOUREC1LINE		256			// ソース1行の最大バイト数(EOSを含む)

#define	MAX_DIM				0xffff		// 最大配列要素数(多次元の場合は、その総数)<16bit範囲
#define	MAX_DIM_JIGEN		(10)		// 配列最大次元数 ; 16(bit)-MAX_DIM_JIGEN>0のこと	// DIM1に固定ワークを確保するので大きくしすぎないこと

#define	MAX_PARAM			12			// funcの最大引数数（ユーザー定義も外部関数も同じ）
#define	MAX_INTERNAL_FUNC	2048		// 内部関数の上限	< short
#define	MAX_FUNC_FILES		16			// 外部関数ファイルの最大数(ユーザー作成の物はないので多くする必要がない)
#define MAX_ENUM			1000		// enum定数の最大数(V2.1では固定)
#define MAX_RECURSIVE		512			// 再帰呼び出し回数の最大段数(V2.6では固定)

#define	MAX_LABEL		((bit(15)-1)	// SWord 最大値

#define MAX_PRINT_KETA		15			// floatの表示桁数
#define MAX_PRINT_KETAS		"15"		// floatの表示桁数の文字列化したもの

//-------------------------------------------------------------------

#define	MULTI_STATEMENT		':'		// ユーザーが使えるマルチステートメント記号
// 多バイト文字の２バイト目以降に来るコードを使わないこと
#define	MULTI_STATEMENT2	0x7f	// 内部処理用マルチステートメント記号:他
#define	MULTI_STATEMENT3	0xff	// 内部処理用マルチステートメント記号:'{'の代わり

// 演算子のみ
typedef enum {			//			CD	順位；小さいほど高い
	NOP			=0x00,	// 未定義
	// 算術演算子
	MUL			=0x01,	// '*'		01	01
	DIV			=0x02,	// '/'		02	01
	IDIV		=0x03,	// '\\'		03	02
	MOD			=0x04,	//	mod		04	03
	ADD			=0x05,	// '+'		05	04
	SUB			=0x06,	// '-'		06	04
	SHR			=0x07,	// shr		07	06
	SHL			=0x08,	// shl		08	06
	// 関係演算子
	EQU			=0x09,	// '='		09	10
	NOTEQU		=0x0a,	// <>		10	10
	SMALL		=0x0b,	// '<'		11	10
	LARGE		=0x0c,	// '>'		12	10
	SMALLEQU	=0x0d,	// <=		13	10
	LARGEEQU	=0x0e,	// >=		14	10
	// ビット演算子
	NOT			=0x0f,	// not		15	16
	AND			=0x10,	// and		16	17
	OR			=0x11,	// or		17	18
	XOR			=0x12,	// xor		18	19
	// 符号
	SIGN		=0x13,	// -		19	00	負号
} CAL_CODE;
typedef	UWord uwCODE;	// (有効)中間コードはshort
// 演算子文字列OperatorName[]はveriable.hにある


// 演算子中間コード=演算子(h.b)+優先順位(l.b)
#define	_toCode(cd,Priority)	((cd<<8)|Priority)
#define	_getPriority(code)		((code)&0xff)
#define	_getOperator(code)		(((code)>>8)&0xff)
enum {
	CODE_OPERATOR	=_toCode(MUL	 , 0),	// 0100	演算子はこれ以上である(これ自体は中間コードとしては存在しない)
	//
	CODE_MUL		=_toCode(MUL	 , 1),	// 0101	オリジナルはすべて*2
	CODE_DIV		=_toCode(DIV	 , 1),	// 0201
	CODE_IDIV		=_toCode(IDIV	 , 2),	// 0302
	CODE_MOD		=_toCode(MOD	 , 3),	// 0403
	CODE_ADD		=_toCode(ADD	 , 4),	// 0504
	CODE_SUB		=_toCode(SUB	 , 4),	// 0604
	CODE_SHR		=_toCode(SHR	 , 6),	// 0706
	CODE_SHL		=_toCode(SHL	 , 6),	// 0806
	//
	CODE_EQU		=_toCode(EQU	 ,10),	// 090a
	CODE_NOTEQU		=_toCode(NOTEQU	 ,10),	// 0a0a
	CODE_SMALL		=_toCode(SMALL	 ,10),	// 0b0a
	CODE_LARGE		=_toCode(LARGE	 ,10),	// 0c0a
	CODE_SMALLEQU	=_toCode(SMALLEQU,10),	// 0d0a
	CODE_LARGEEQU	=_toCode(LARGEEQU,10),	// 0e0a
	//
	CODE_NOT		=_toCode(NOT	 ,16),	// 0f10
	CODE_AND		=_toCode(AND	 ,17),	// 1011
	CODE_OR			=_toCode(OR		 ,18),	// 1112
	CODE_XOR		=_toCode(XOR	 ,19),	// 1213
	//
	CODE_SIGN		=_toCode(SIGN	 , 0),	// 1300
};
// <CODE_OPERATORは構文系中間コード

// ステートメント中間コード
// 実行時のコードであり、コンパイル時のstatements[]の要素番号とは別の意味に使われている物もある
enum {
	CODE_NONE	=0,		// 中間コードではない印	
						//			オリジナルでのコード
	CODE_print,			// 1			5*2	=$0a
	CODE_break,			// 2			8*2	=$10
	CODE_case,			// 3			9*2	=$12
	CODE_continue,		// 4			10*2=$14
	CODE_default,		// 5			11*2=$16
	CODE_endfunc,		// 6			12*2=$18
	CODE_switch2,		// 7			13*2=$1a	コンパイル時はendswitch
	CODE_error,			// 8			14*2=$1c
	CODE_return,		// 9			15*2=$1e
	CODE_switch,		// $0a=10		16*2=$20
	CODE_end,			// $0b			19*2=$26
	CODE_endwhile,		// $0c			20*2=$28
	CODE_exit,			// $0d			21*2=$2a
	CODE_for,			// $0e			22*2=$2c
	CODE_gosub,			// $0f			23*2=$2e
	CODE_goto,			// $10			24*2=$30
	CODE_if,			// $11			25*2=$32
	CODE_input,			// $12			26*2=$34
	CODE_linput,		// $13			28*2=$38
	CODE_next,			// $14=20		29*2=$3a
	CODE_next2,			// $15			30*2=$3c	repeat
	CODE_stop,			// $16			31*2=$3e
	CODE_until,			// $17			32*2=$40
	CODE_while,			// $18			33*2=$42
	CODE_dim,			// $19			34*2=$44
	CODE_str,			// $1a			38*2=$4c
	CODE_func,			// $1b			39*2=$4e
	CODE_else,			// $1c			40*2=$50
	CODE_sysvar,		// $1d			41*2=$52	then
	CODE_ifeq,			// $1e=30		42*2=$54	label
	// ここから先はstatements[]と全く異なる
	CODE_ifne,			// $1f			43*2=$56	float
	CODE_iflt,			// $20			44*2=$58	int
	CODE_ifgt,			// $21			45*2=$5a	char
	CODE_ifle,			// $22			46*2=$5c	enum
	CODE_ifge			// $23			47*2=$53	endenum
}; // <0x0100 : >=0x0100は演算子系中間コード(fdef.h)

enum { // コンパイル中にのみ存在するコード
	CODE_label	=CODE_ifeq,
	CODE_enum	=CODE_ifle,
	CODE_endenum,
#if 0
	CODE_fenum,
	CODE_senum,
#endif
};

#define	CODE_FUNC		CODE_NONE	// 関数
#define	CODE_SIKI		CODE_NONE	// 式

#define	CODE_PROGRAMEND	(0xffff)	// プログラム終了


// CODEの修飾情報
// 関数の引数のフラグ(BIT指定)
#define	CODE_ATRB_BIT_POINTER	13
#define	CODE_ATRB_BIT_STR		12
#define	CODE_ATRB_BIT_LOCAL		 8		// ローカル変数

// 即値:下位8ビットにT_*型が入る
#define	CODE_ATRB_FUNC			(bit(15)|bit(14))			// 0xC000	関数
#define	CODE_ATRB_DAINYU		bit(15)						// 0x8000	代入
#define	CODE_ATRB_NOMOVE		CODE_ATRB_DAINYU			// 並び替えで移動済み(代入は自動的に同等処理される)
#define	CODE_ATRB_VARIABLE		bit(14)						// 0x4000	変数
#define	CODE_ATRB_ARRAY			CODE_ATRB_VARIABLE			// 配列もここ
//
#define	CODE_ATRB_POINTER		bit(CODE_ATRB_BIT_POINTER)	// 0x2000
#define	CODE_ATRB_STR			bit(CODE_ATRB_BIT_STR)		// 0x1000
#define	CODE_ATRB_LOCAL			bit(CODE_ATRB_BIT_LOCAL)	// 0x0100
#define	CODE_ATRB_NONE			(0x0000|T_VOID)				// 引数フラグ=0,型=T_VOID	0x00ff

// 関数形式にしておくことで、将来ビット位置を変更することに対応できるようにする
#define	_isVariable(code)		((code)& CODE_ATRB_VARIABLE)	// 変数かどうか	!は配列や関数
#define	_clrVariable(code)		((code)&~CODE_ATRB_VARIABLE)	// そのフラグを消す
#define	_isDainyu(code)			((code)& CODE_ATRB_DAINYU)		// 判定できるのはBIT15<0だけなので、=0=CODE_SIKIは別途調べること

// print using中の中間コード
enum {
	CrLfEnd		=0,
	NoCrLfEnd	,	// 1
	TabJump		,	// 2
	UsingNum	,	// 3
	UsingStr	,	// 4
};

// 数値using用フォーマットビット定義
// OR指定される
#define	USING_NONE		0		// 0x0000 何もしていなし
#define	USING_ASTA		bit(0)	// 0x0001 *
#define	USING_YEN		bit(1)	// 0x0002 ￥(←本当は半角だけど、コメント内でもコンパイラが警告を出すので)
#define	USING_COMMA		bit(2)	// 0x0004 ,
#define	USING_SISUU		bit(3)	// 0x0008 指数表現
#define	USING_BPLUS		bit(4)	// 0x0010 前に符号
#define	USING_APLUS		bit(5)	// 0x0020 後ろに正号
#define	USING_AMINUS	bit(6)	// 0x0040 後ろに負号
#define	USING_ZERO		bit(7)	// 0x0080 0
#define	USING_BPLUS2	bit(8)	// 0x0010 前に符号；ただし+の場合は空白

//-------------------------------------------------------------------
// 型定数

// .b=.w
typedef UWord uwTYPE;
enum { // V3.20でenumに変更
	// Var1Size[]の要素番号でもあるので変更しないこと
	T_INT	=	0x0000,
	T_STR,
	T_CHAR,
	TS_FLOAT		// これはVar1Size[T_FLOAT]で使う;_getSerialType()参照
};
#define	T_FLOAT		0x0080	// .sb<0
#define	T_VOID		0x00ff	// .sb<0
//
// T_INT～T_FLOATを連続番号で返すマクロ;Var1Size[]アクセスなどに使う
#define	_getSerialType(type)	((type)==T_FLOAT? TS_FLOAT:type)

#define	_PARAM			0x8000				// 引数の印			.sw<0になる
#define	_CONSTANT		0x8000				// 定数の印			.hb<0になる		_CONSTANT|T_INTなど	&0x00ffで型だけがわかる
#define	_NOT_CONST_b	0xff				// 定数でない印		.b <0になる
#define	_NOT_CONST		(_NOT_CONST_b<<8)	// 定数でない印		.hb<0になる		0xff00

#define	_notConstType(type)		(_NOT_CONST|(type))				// 定数でない型
#define	_isConstnat(code)		((code)&_CONSTANT)				// 定数かどうか
#define	_getConstantNum(code)	((code)&=~_CONSTANT)			// 数値のみ取り出す
#define	_isNotConstant(code)	(((code)&0xff00)==_NOT_CONST)	// 定数でないかどうか

// 中間コード代入式:uwTYPEの値を代入する式
#define	_dainyuWithType(type)	(_PARAM|(type))
// 各値を得る
#define	_getType(code)			((code)&0x00ff)
#define	_getNo(code)			(((code)>>8)&0xff)
#define	_maskNo(code)			((code)&0xff00)
#define	_changeType(code,type)	(_maskNo(code)|_getType(type))	// 念のため安全性を最大限考慮した式


#define	_type2MathType(type)		(((UWord)(type))<<8)
#define	_mathType2Type(mathtype)	(((UWord)(mathtype))>>8)

// xbmath.m;interpretMath()の式解釈の型指定.w	オリジナルでの定義
//	=variableCheck()のリターン値の下位16ビット
#define	MATH_INT		_type2MathType(T_INT)	// 0x0000	INT
#define	MATH_STR		_type2MathType(T_STR)	// 0x0100	STR
#define	MATH_CHAR		_type2MathType(T_CHAR)	// 0x0200	CHAR
#define	MATH_FLOAT		_type2MathType(T_FLOAT)	// 0x8000	FLOAT
#define	MATH_VOID		(0xffff)				// -1		未宣言変数/型不明	uwMATHTYPEはunsignedなので-1では警告が出る
#define	MATH_NONE		MATH_VOID
// variableCheck()では.lの.hwに一致している変数番号が入ってくる
typedef UWord uwMATHTYPE;


// variableCheck();xbmath.mのstat値;ビット対応
#define	VARIABLE_DIM		bit(0)			// 配列の印
#define	VARIABLE_SYSTEM		bit(1)			// システム変数の印
// グローバル変数
#define	VARIABLE_GLOBAL_VAR	0				// 0x00	グローバル変数
#define	VARIABLE_GLOBAL_DIM	VARIABLE_DIM	// 0x01	グローバル配列
// ローカル変数
#define	VARIABLE_LOCAL		bit(7)			// これでcharが負数になる
#define	VARIABLE_LOCAL_VAR	(VARIABLE_LOCAL|0)				// 0x80	ローカル変数
#define	VARIABLE_LOCAL_DIM	(VARIABLE_LOCAL|VARIABLE_DIM)	// 0x81	ローカル配列
// 存在しない
#define	VARIABLE_NONE		(-1)

#define	_isStatLocal(stat)	(VARIABLE_LOCAL&(stat))		// statでローカル変数かどうかを調べる;VARIABLE_NONEも引っかかるので、別途排除しておくこと
#define	_getStatOnly(stat)	((stat)&~VARIABLE_LOCAL)	// statでローカル変数かどうか以外の情報を得る

//-------------------------------------------------------------------
// パラメーター(引数)テーブル

// bit番号での定義
enum {
	PARAM_BIT_FLOAT		=0,		// float型		0
	PARAM_BIT_INT		,		//   int型		1
	PARAM_BIT_CHAR		,		//  char型		2
	PARAM_BIT_STR		,		//   str型		3
	PARAM_BIT_POINTER	,		// ポインタ		4
	PARAM_BIT_ARRAY1	,		// 1次元配列		5
	PARAM_BIT_ARRAY2	,		// 2次元配列		6
	PARAM_BIT_OMIT		,		// 省略可能		7
	// ↑8bit範囲
	// iOS変更
	PARAM_BIT_ARRAYext	=14,	// 拡張配列引数	; ぺけ-BASICの定義($8080ではリターン値の判定と重なるので変更)
	//
	PARAM_BIT_RETURN	=15,	// 戻り値
};
typedef UWord uwPARAMTYPE;	// 外部関数パラメーターの引数リストの型であり、リターン値の型

// 数値としての定義
#define	PARAM_RETURN	bit(PARAM_BIT_RETURN)	// 戻り値				0x8000
#define	PARAM_PARAM		(0<<PARAM_BIT_RETURN)	// 引数(パラメーター)
//
#define	PARAM_OMIT		bit(PARAM_BIT_OMIT)		// 省略可能			0x0080
#define	PARAM_NO_OMIT	(0<<PARAM_BIT_OMIT)		// 省略不可
//
#define	PARAM_ARRAY2	bit(PARAM_BIT_ARRAY2)	// 2次元配列			0x0040	ARRAYはOR指定で、どちらでも使えるようになる
#define	PARAM_ARRAY1	bit(PARAM_BIT_ARRAY1)	// 1次元配列			0x0020
//
#define	PARAM_POINTER	bit(PARAM_BIT_POINTER)	// ポインタ			0x0010
#define	PARAM_STR		bit(PARAM_BIT_STR)		//   str型			0x0008
#define	PARAM_CHAR		bit(PARAM_BIT_CHAR)		//  char型			0x0004
#define	PARAM_INT		bit(PARAM_BIT_INT)		//   int型			0x0002
#define	PARAM_FLOAT		bit(PARAM_BIT_FLOAT)	// float型			0x0001
// ぺけ-BASIC拡張
#define	PARAM_ARRAYext	bit(PARAM_BIT_ARRAYext)	// 拡張配列			0x4000
#define	isArrayExt(prm)	(prm&PARAM_ARRAYext)	// 拡張配列かどうか

// 引数名称定義.w
#define	FLOAT_VAL	PARAM_FLOAT					// float型の値
#define	INT_VAL		PARAM_INT					//   int型の値
#define	CHAR_VAL	PARAM_CHAR					//  char型の値
#define	STR_VAL		PARAM_STR					//   str型の値

#define	FLOAT_OMT	(PARAM_OMIT|FLOAT_VAL)		// 省略可能なfloat型の値
#define	INT_OMT		(PARAM_OMIT|INT_VAL)		// 省略可能な  int型の値
#define	CHAR_OMT	(PARAM_OMIT|CHAR_VAL)		// 省略可能な char型の値
#define	STR_OMT		(PARAM_OMIT|STR_VAL)		// 省略可能な  str型の値

#define	FLOAT_VP	(PARAM_POINTER|FLOAT_VAL)	// float型の変数の値のポインタ
#define	INT_VP		(PARAM_POINTER|INT_VAL)		//   int型の変数の値のポインタ
#define	CHAR_VP		(PARAM_POINTER|CHAR_VAL)	//  char型の変数の値のポインタ
#define	STR_VP		(PARAM_POINTER|STR_VAL)		//   str型の変数の値のポインタ

#define ARRAY1_FLOAT	(PARAM_ARRAY1|FLOAT_VP)	//	float型 1次元配列
#define	ARRAY1_INT		(PARAM_ARRAY1|INT_VP)	//	  int型 1次元配列
#define	ARRAY1_CHAR		(PARAM_ARRAY1|CHAR_VP)	//	 char型 1次元配列
#define	ARRAY2_CHAR		(PARAM_ARRAY2|CHAR_VP)	//	 char型 2次元配列
#define ARRAY1_STR		(PARAM_ARRAY1|STR_VP)	// 	  str型 1次元配列

#define	ARRAY1			(PARAM_ARRAY1|PARAM_POINTER|PARAM_STR|PARAM_CHAR|PARAM_INT|PARAM_FLOAT)	// 全ての型 1次元配列
#define	ARRAY1_FIC		(PARAM_ARRAY1|PARAM_POINTER|PARAM_CHAR|PARAM_INT|PARAM_FLOAT)			// float,int,char型 1次元配列
#define	ARRAY1_IC		(PARAM_ARRAY1|PARAM_POINTER|PARAM_CHAR|PARAM_INT)						// int,char型 1次元配列
// リターン値定義はvariable.h

//-------------------------------------------------------------------
// error on/off/on2の引数値 v2.6
enum {
	ERR_OFF=0,	// 外部関数のエラーで停止しない
	ERR_ON,		// 停止する
	ERR_ON2		// ファイル系も停止する
};

//-------------------------------------------------------------------

#include	"variable.h"
#include	"XBerror.h"

//-------------------------------------------------------------------

#endif
