[qfcc] Implement bool and lbool types

Since spir-v needs actual bools for its conditional instructions, the
time to do bool properly finally came. As expected, the changes caused
quite a mess, but Ruamoko now does bool/true/false.
This commit is contained in:
Bill Currie 2024-11-15 12:36:08 +09:00
parent ad36d2cd50
commit ebb3ec592a
32 changed files with 381 additions and 206 deletions

View file

@ -53,7 +53,7 @@ next_type (qfot_type_t *type)
return (qfot_type_t *) ((int *) type + size); return (qfot_type_t *) ((int *) type + size);
} }
int bool
type_is_null (qfot_type_t *type) type_is_null (qfot_type_t *type)
{ {
return type.size == 0; return type.size == 0;

View file

@ -43,7 +43,7 @@
{ {
qfot_struct_t *strct =&type.strct; qfot_struct_t *strct =&type.strct;
PLItem *field_dict = [parse getObjectForKey:[self name]]; PLItem *field_dict = [parse getObjectForKey:[self name]];
int readonly = [field_dict string] == "readonly"; bool readonly = [field_dict string] == "readonly";
if (readonly) { if (readonly) {
return; return;
@ -103,7 +103,7 @@
-(void) writeForward -(void) writeForward
{ {
PLItem *field_dict = [parse getObjectForKey:[self name]]; PLItem *field_dict = [parse getObjectForKey:[self name]];
int readonly = [field_dict string] == "readonly"; bool readonly = [field_dict string] == "readonly";
if (!readonly) { if (!readonly) {
fprintf (output_file, "static int %s (const plfield_t *field," fprintf (output_file, "static int %s (const plfield_t *field,"
" const plitem_t *item, void *data, plitem_t *messages," " const plitem_t *item, void *data, plitem_t *messages,"
@ -255,7 +255,7 @@ write_type (Struct *self, PLItem *field_dict, string type)
} }
static void static void
write_parser (Struct *self, int have_sType, PLItem *only) write_parser (Struct *self, bool have_sType, PLItem *only)
{ {
write_function_head (self); write_function_head (self);
if (have_sType) { if (have_sType) {
@ -342,17 +342,17 @@ write_table (Struct *self, PLItem *field_dict, Array *field_defs,
PLItem *only, int need_parser) PLItem *only, int need_parser)
{ {
qfot_type_t *type = self.type; qfot_type_t *type = self.type;
int have_sType = 0; bool have_sType = false;
int have_pNext = 0; bool have_pNext = false;
int readonly = [field_dict string] == "readonly"; bool readonly = [field_dict string] == "readonly";
for (int i = 0; i < type.strct.num_fields; i++) { for (int i = 0; i < type.strct.num_fields; i++) {
qfot_var_t *field = &type.strct.fields[i]; qfot_var_t *field = &type.strct.fields[i];
if (field.name == "sType") { if (field.name == "sType") {
have_sType = 1; have_sType = true;
} }
if (field.name == "pNext") { if (field.name == "pNext") {
have_pNext = 1; have_pNext = true;
self.write_symtab = 1; self.write_symtab = 1;
} }
} }

View file

@ -23,20 +23,20 @@
current = base = b; current = base = b;
} }
- (int) keyEvent:(int)key unicode:(int)unicode down:(int)down - (bool) keyEvent:(int)key unicode:(int)unicode down:(bool)down
{ {
View *cur = [views objectAtIndex: current]; View *cur = [views objectAtIndex: current];
int ret = [cur keyEvent: key unicode: unicode down: down]; bool ret = [cur keyEvent: key unicode: unicode down: down];
if (!ret) { if (!ret) {
switch (key) { switch (key) {
case QFK_DOWN: case QFK_DOWN:
//case QFM_WHEEL_DOWN: //case QFM_WHEEL_DOWN:
[self next]; [self next];
return 1; return true;
case QFK_UP: case QFK_UP:
//case QFM_WHEEL_UP: //case QFM_WHEEL_UP:
[self prev]; [self prev];
return 1; return true;
} }
} }
return ret; return ret;

View file

@ -13,7 +13,7 @@
return self; return self;
} }
- (int) keyEvent:(int)key unicode:(int)unicode down:(int)down - (bool) keyEvent:(int)key unicode:(int)unicode down:(bool)down
{ {
return [view keyEvent:key unicode:unicode down:down]; return [view keyEvent:key unicode:unicode down:down];
} }

View file

@ -42,7 +42,7 @@ menu_leave_sound =
S_LocalSound ("misc/menu2.wav"); S_LocalSound ("misc/menu2.wav");
} }
int (int key, int unicode, int down) bool (int key, int unicode, bool down)
menu_key_sound = menu_key_sound =
{ {
switch (key) { switch (key) {
@ -55,7 +55,7 @@ menu_key_sound =
S_LocalSound ("misc/menu1.wav"); S_LocalSound ("misc/menu1.wav");
break; break;
} }
return 0; return false;
} }
void (int x, int y) spinner = void (int x, int y) spinner =
@ -227,7 +227,7 @@ int (int x, int y) save_draw =
return 1; return 1;
}; };
int (int key, int unicode, int down) load_quickbup_keyevent = bool (int key, int unicode, bool down) load_quickbup_keyevent =
{ {
switch (key) { switch (key) {
case QFK_DOWN: case QFK_DOWN:
@ -235,13 +235,13 @@ int (int key, int unicode, int down) load_quickbup_keyevent =
S_LocalSound ("misc/menu1.wav"); S_LocalSound ("misc/menu1.wav");
load_cursor++; load_cursor++;
load_cursor %= MAX_QUICK; load_cursor %= MAX_QUICK;
return 1; return true;
case QFK_UP: case QFK_UP:
//case QFM_WHEEL_UP: //case QFM_WHEEL_UP:
S_LocalSound ("misc/menu1.wav"); S_LocalSound ("misc/menu1.wav");
load_cursor += MAX_QUICK - 1; load_cursor += MAX_QUICK - 1;
load_cursor %= MAX_QUICK; load_cursor %= MAX_QUICK;
return 1; return true;
case QFK_RETURN: case QFK_RETURN:
//case QFM_BUTTON1: //case QFM_BUTTON1:
if (loadable[load_cursor]) { if (loadable[load_cursor]) {
@ -250,12 +250,12 @@ int (int key, int unicode, int down) load_quickbup_keyevent =
Cbuf_AddText (nil, sprintf ("load quick%i.sav\n", load_cursor)); Cbuf_AddText (nil, sprintf ("load quick%i.sav\n", load_cursor));
load_cursor = MAX_SAVEGAMES; load_cursor = MAX_SAVEGAMES;
} }
return 1; return true;
} }
return 0; return false;
}; };
int (int key, int unicode, int down) load_keyevent = bool (int key, int unicode, bool down) load_keyevent =
{ {
switch (key) { switch (key) {
case QFK_DOWN: case QFK_DOWN:
@ -263,13 +263,13 @@ int (int key, int unicode, int down) load_keyevent =
S_LocalSound ("misc/menu1.wav"); S_LocalSound ("misc/menu1.wav");
load_cursor++; load_cursor++;
load_cursor %= MAX_SAVEGAMES + 1; load_cursor %= MAX_SAVEGAMES + 1;
return 1; return true;
case QFK_UP: case QFK_UP:
//case QFM_WHEEL_UP: //case QFM_WHEEL_UP:
S_LocalSound ("misc/menu1.wav"); S_LocalSound ("misc/menu1.wav");
load_cursor += MAX_SAVEGAMES; load_cursor += MAX_SAVEGAMES;
load_cursor %= MAX_SAVEGAMES + 1; load_cursor %= MAX_SAVEGAMES + 1;
return 1; return true;
case QFK_RETURN: case QFK_RETURN:
//case QFM_BUTTON1: //case QFM_BUTTON1:
if (load_cursor == MAX_SAVEGAMES) { if (load_cursor == MAX_SAVEGAMES) {
@ -281,12 +281,12 @@ int (int key, int unicode, int down) load_keyevent =
Menu_SelectMenu (nil); Menu_SelectMenu (nil);
Cbuf_AddText (nil, sprintf ("load s%i.sav\n", load_cursor)); Cbuf_AddText (nil, sprintf ("load s%i.sav\n", load_cursor));
} }
return 1; return true;
} }
return 0; return false;
}; };
int (int key, int unicode, int down) save_keyevent = bool (int key, int unicode, bool down) save_keyevent =
{ {
switch (key) { switch (key) {
case QFK_DOWN: case QFK_DOWN:
@ -294,20 +294,20 @@ int (int key, int unicode, int down) save_keyevent =
S_LocalSound ("misc/menu1.wav"); S_LocalSound ("misc/menu1.wav");
save_cursor++; save_cursor++;
save_cursor %= MAX_SAVEGAMES; save_cursor %= MAX_SAVEGAMES;
return 1; return true;
case QFK_UP: case QFK_UP:
//case QFM_WHEEL_UP: //case QFM_WHEEL_UP:
S_LocalSound ("misc/menu1.wav"); S_LocalSound ("misc/menu1.wav");
save_cursor += MAX_SAVEGAMES - 1; save_cursor += MAX_SAVEGAMES - 1;
save_cursor %= MAX_SAVEGAMES; save_cursor %= MAX_SAVEGAMES;
return 1; return true;
case QFK_RETURN: case QFK_RETURN:
//case QFM_BUTTON1: //case QFM_BUTTON1:
Menu_SelectMenu (nil); Menu_SelectMenu (nil);
Cbuf_AddText (nil, sprintf ("save s%i.sav\n", save_cursor)); Cbuf_AddText (nil, sprintf ("save s%i.sav\n", save_cursor));
return 1; return true;
} }
return 0; return false;
}; };
void () load_quickbup_menu = void () load_quickbup_menu =
@ -361,17 +361,17 @@ int (string text, int key) quit_f =
return 0; return 0;
}; };
int (int key, int unicode, int down) quit_keyevent = bool (int key, int unicode, bool down) quit_keyevent =
{ {
if (key == 'y') { if (key == 'y') {
Menu_Quit (); Menu_Quit ();
return 1; return true;
} }
if (key == 'n') { if (key == 'n') {
Menu_SelectMenu (nil); Menu_SelectMenu (nil);
return 1; return true;
} }
return 0; return false;
}; };
int (int x, int y) quit_draw = int (int x, int y) quit_draw =
@ -429,7 +429,7 @@ void () single_player_menu =
// ********* MULTIPLAYER // ********* MULTIPLAYER
int JoiningGame; bool JoiningGame;
int lanConfig_cursor; int lanConfig_cursor;
string my_tcpip_address; string my_tcpip_address;
string lanConfig_portname; string lanConfig_portname;
@ -488,7 +488,7 @@ int (int x, int y) lanconfig_draw =
return 0; return 0;
}; };
int (int key, int unicode, int down) lanconfig_keyevent = bool (int key, int unicode, bool down) lanconfig_keyevent =
{ {
if (input_active) if (input_active)
[input_active processInput:(key >= 256 ? key : unicode)]; [input_active processInput:(key >= 256 ? key : unicode)];
@ -500,7 +500,7 @@ int (int key, int unicode, int down) lanconfig_keyevent =
lanConfig_cursor ++; lanConfig_cursor ++;
lanConfig_cursor %= NUM_LANCONFIG_CMDS; lanConfig_cursor %= NUM_LANCONFIG_CMDS;
} }
return 1; return true;
case QFK_UP: case QFK_UP:
//case QFM_WHEEL_UP: //case QFM_WHEEL_UP:
if (!input_active) { if (!input_active) {
@ -508,7 +508,7 @@ int (int key, int unicode, int down) lanconfig_keyevent =
lanConfig_cursor += NUM_LANCONFIG_CMDS - 1; lanConfig_cursor += NUM_LANCONFIG_CMDS - 1;
lanConfig_cursor %= NUM_LANCONFIG_CMDS; lanConfig_cursor %= NUM_LANCONFIG_CMDS;
} }
return 1; return true;
case QFK_RETURN: case QFK_RETURN:
if (input_active) { if (input_active) {
input_active = nil; input_active = nil;
@ -521,9 +521,9 @@ int (int key, int unicode, int down) lanconfig_keyevent =
} }
} }
} }
return 1; return true;
} }
return 0; return false;
}; };
void () lanconfig_menu = void () lanconfig_menu =
@ -558,12 +558,12 @@ void () join_menu =
Menu_End (); Menu_End ();
}; };
int (int key, int unicode, int down) multi_player_keyevent = bool (int key, int unicode, bool down) multi_player_keyevent =
{ {
if (key == QFK_RETURN) { if (key == QFK_RETURN) {
JoiningGame = (Menu_GetIndex () == 0); JoiningGame = (Menu_GetIndex () == 0);
} }
return 0; return false;
}; };
void () multi_player_menu = void () multi_player_menu =

View file

@ -16,7 +16,7 @@
int (func)(string text, int key), int (func)(string text, int key),
int allkeys); int allkeys);
@extern void Menu_Cursor (void (func)(int x, int y)); @extern void Menu_Cursor (void (func)(int x, int y));
@extern void Menu_KeyEvent (int (func)(int key, int unicode, int down)); @extern void Menu_KeyEvent (bool (func)(int key, int unicode, bool down));
@extern void Menu_End (void); @extern void Menu_End (void);
@extern void Menu_TopMenu (string name); @extern void Menu_TopMenu (string name);
@extern void Menu_SelectMenu (string name); @extern void Menu_SelectMenu (string name);

View file

@ -11,7 +11,7 @@ void (int x, int y, string name) Menu_CenterPic = #0;
void (int x, int y, string name, int srcx, int srcy, int width, int height) Menu_CenterSubPic = #0; void (int x, int y, string name, int srcx, int srcy, int width, int height) Menu_CenterSubPic = #0;
void (int x, int y, string text, int (string text, int key) func, int allkeys) Menu_Item = #0; void (int x, int y, string text, int (string text, int key) func, int allkeys) Menu_Item = #0;
void (void (int x, int y) func) Menu_Cursor = #0; void (void (int x, int y) func) Menu_Cursor = #0;
void (int (int key, int unicode, int down) func) Menu_KeyEvent = #0; void (bool (int key, int unicode, bool down) func) Menu_KeyEvent = #0;
void () Menu_End = #0; void () Menu_End = #0;
void (string name) Menu_TopMenu = #0; void (string name) Menu_TopMenu = #0;
void (string name) Menu_SelectMenu = #0; void (string name) Menu_SelectMenu = #0;

View file

@ -107,7 +107,7 @@ DRAW_video_options =
return 1; return 1;
}; };
int (int key, int unicode, int down) bool (int key, int unicode, bool down)
KEY_video_options = KEY_video_options =
{ {
return [video_options keyEvent:key unicode:unicode down:down]; return [video_options keyEvent:key unicode:unicode down:down];
@ -154,7 +154,7 @@ DRAW_audio_options =
return 1; return 1;
}; };
int (int key, int unicode, int down) bool (int key, int unicode, bool down)
KEY_audio_options = KEY_audio_options =
{ {
return [audio_options keyEvent:key unicode:unicode down:down]; return [audio_options keyEvent:key unicode:unicode down:down];
@ -201,7 +201,7 @@ DRAW_control_options =
return 0; return 0;
}; };
int (int key, int unicode, int down) bool (int key, int unicode, bool down)
KEY_control_options = KEY_control_options =
{ {
return [control_options keyEvent:key unicode:unicode down:down]; return [control_options keyEvent:key unicode:unicode down:down];
@ -251,7 +251,7 @@ DRAW_feature_options =
return 1; return 1;
}; };
int (int key, int unicode, int down) bool (int key, int unicode, bool down)
KEY_feature_options = KEY_feature_options =
{ {
return [feature_options keyEvent:key unicode:unicode down:down]; return [feature_options keyEvent:key unicode:unicode down:down];
@ -313,7 +313,7 @@ string player_config_vals[NUM_PLAYERCONFIG_CMDS] = {
}; };
int (int key, int unicode, int down) bool (int key, int unicode, bool down)
KEY_player_options = KEY_player_options =
{ {
return [player_options keyEvent:key unicode:unicode down:down]; return [player_options keyEvent:key unicode:unicode down:down];
@ -390,7 +390,7 @@ string network_config_vals[NUM_NETWORKCONFIG_CMDS] = {
}; };
int (int key, int unicode, int down) bool (int key, int unicode, bool down)
KEY_network_options = KEY_network_options =
{ {
return [network_options keyEvent:key unicode:unicode down:down]; return [network_options keyEvent:key unicode:unicode down:down];

View file

@ -208,7 +208,7 @@ syntax_error ()
Script_GetLine (script)); Script_GetLine (script));
} }
static int static bool
match (token_e token) match (token_e token)
{ {
if (lookahead == -1) { if (lookahead == -1) {

View file

@ -61,9 +61,9 @@
{ {
} }
- (int) keyEvent:(int)key unicode:(int)unicode down:(int)down - (bool) keyEvent:(int)key unicode:(int)unicode down:(bool)down
{ {
return 0; return false;
} }
@end @end

View file

@ -10,7 +10,7 @@
{ {
int index; int index;
int size; int size;
int dir; bool dir;
} }
- (id) initWithBounds: (Rect)aRect size: (int) aSize; - (id) initWithBounds: (Rect)aRect size: (int) aSize;

View file

@ -31,7 +31,7 @@
- (void) setBasePosFromView: (View*)view; - (void) setBasePosFromView: (View*)view;
- (void) draw; - (void) draw;
- (int) keyEvent:(int)key unicode:(int)unicode down:(int)down; - (bool) keyEvent:(int)key unicode:(int)unicode down:(bool)down;
@end @end
///@} ///@}

View file

@ -6,7 +6,7 @@
@interface PointerView : DefView @interface PointerView : DefView
{ {
unsigned *data; unsigned *data;
int invalid; bool invalid;
unsigned ptr; unsigned ptr;
qfot_type_t *ptr_type; qfot_type_t *ptr_type;
int ptr_size; int ptr_size;

View file

@ -49,7 +49,7 @@
in:ptr_data in:ptr_data
target:target] retain]; target:target] retain];
} }
invalid = 1; invalid = true;
if (!ptr_view || ptr != (unsigned) data[0]) { if (!ptr_view || ptr != (unsigned) data[0]) {
invalid = qdb_get_data (target, data[0], ptr_size, ptr_data) < 0; invalid = qdb_get_data (target, data[0], ptr_size, ptr_data) < 0;
} }

View file

@ -10,7 +10,7 @@
@interface ScrollBar : View @interface ScrollBar : View
{ {
int vertical; bool vertical;
int bgchar; int bgchar;
double mouseTime; double mouseTime;
Point mouseStart; Point mouseStart;

View file

@ -521,8 +521,8 @@ expr_t *new_label_ref (const ex_label_t *label);
expr_t *new_state_expr (const expr_t *frame, const expr_t *think, expr_t *new_state_expr (const expr_t *frame, const expr_t *think,
const expr_t *step); const expr_t *step);
expr_t *new_bool_expr (ex_boollist_t *true_list, ex_boollist_t *false_list, expr_t *new_boolean_expr (ex_boollist_t *true_list, ex_boollist_t *false_list,
const expr_t *e); const expr_t *e);
/** Create a new statement block expression node. /** Create a new statement block expression node.
@ -759,6 +759,9 @@ const expr_t *new_pointer_expr (int val, const type_t *type, struct def_s *def);
const expr_t *new_quaternion_expr (const float *quaternion_val); const expr_t *new_quaternion_expr (const float *quaternion_val);
const float *expr_quaternion (const expr_t *e) __attribute__((pure)); const float *expr_quaternion (const expr_t *e) __attribute__((pure));
const expr_t *new_bool_expr (bool bool_val);
const expr_t *new_lbool_expr (bool lbool_val);
/** Create a new itn constant expression node. /** Create a new itn constant expression node.
\param int_val The int constant being represented. \param int_val The int constant being represented.

View file

@ -57,8 +57,8 @@ struct symtab_s *start_enum (struct symbol_s *enm);
struct symbol_s *finish_enum (struct symbol_s *sym); struct symbol_s *finish_enum (struct symbol_s *sym);
void add_enum (struct symbol_s *enm, struct symbol_s *name, void add_enum (struct symbol_s *enm, struct symbol_s *name,
const struct expr_s *val); const struct expr_s *val);
int enum_as_bool (const type_t *enm, struct expr_s **zero, bool enum_as_bool (const type_t *enm, struct expr_s **zero,
struct expr_s **one); struct expr_s **one);
struct symbol_s *make_structure (const char *name, int su, struct_def_t *defs, struct symbol_s *make_structure (const char *name, int su, struct_def_t *defs,
const type_t *type); const type_t *type);

View file

@ -233,6 +233,8 @@ bool is_pointer (const type_t *type) __attribute__((pure));
bool is_reference (const type_t *type) __attribute__((pure)); bool is_reference (const type_t *type) __attribute__((pure));
bool is_enum (const type_t *type) __attribute__((pure)); bool is_enum (const type_t *type) __attribute__((pure));
bool is_bool (const type_t *type) __attribute__((pure)); bool is_bool (const type_t *type) __attribute__((pure));
bool is_lbool (const type_t *type) __attribute__((pure));
bool is_boolean (const type_t *type) __attribute__((pure));
bool is_signed (const type_t *type) __attribute__((pure)); bool is_signed (const type_t *type) __attribute__((pure));
bool is_unsigned (const type_t *type) __attribute__((pure)); bool is_unsigned (const type_t *type) __attribute__((pure));
bool is_integral (const type_t *type) __attribute__((pure)); bool is_integral (const type_t *type) __attribute__((pure));

View file

@ -493,7 +493,8 @@ new_state_expr (const expr_t *frame, const expr_t *think, const expr_t *step)
} }
expr_t * expr_t *
new_bool_expr (ex_boollist_t *true_list, ex_boollist_t *false_list, const expr_t *e) new_boolean_expr (ex_boollist_t *true_list, ex_boollist_t *false_list,
const expr_t *e)
{ {
expr_t *b = new_expr (); expr_t *b = new_expr ();
@ -640,7 +641,8 @@ new_horizontal_expr (int op, const expr_t *vec, type_t *type)
return (expr_t *) vec; return (expr_t *) vec;
} }
auto vec_type = get_type (vec); auto vec_type = get_type (vec);
if (!is_math (vec_type) || is_scalar (vec_type)) { if (!(is_math (vec_type) || is_boolean (vec_type))
|| is_scalar (vec_type)) {
internal_error (vec, "horizontal operand not a vector type"); internal_error (vec, "horizontal operand not a vector type");
} }
if (!is_scalar (type)) { if (!is_scalar (type)) {
@ -864,6 +866,25 @@ new_quaternion_expr (const float *quaternion_val)
return new_value_expr (new_quaternion_val (quaternion_val), false); return new_value_expr (new_quaternion_val (quaternion_val), false);
} }
const expr_t *
new_bool_expr (bool bool_val)
{
pr_type_t data = { .value = -bool_val };
auto val = new_type_value (&type_bool, &data);
return new_value_expr (val, false);
}
const expr_t *
new_lbool_expr (bool lbool_val)
{
pr_type_t data[2] = {
{ .value = -lbool_val },
{ .value = -lbool_val },
};
auto val = new_type_value (&type_lbool, data);
return new_value_expr (val, false);
}
const expr_t * const expr_t *
new_int_expr (int int_val, bool implicit) new_int_expr (int int_val, bool implicit)
{ {
@ -1827,6 +1848,12 @@ convert_from_bool (const expr_t *e, const type_t *type)
} else if (is_int (type)) { } else if (is_int (type)) {
one = new_int_expr (1, false); one = new_int_expr (1, false);
zero = new_int_expr (0, false); zero = new_int_expr (0, false);
} else if (is_bool (type)) {
one = new_bool_expr (1);
zero = new_bool_expr (0);
} else if (is_lbool (type)) {
one = new_lbool_expr (1);
zero = new_lbool_expr (0);
} else if (is_enum (type) && enum_as_bool (type, &enum_zero, &enum_one)) { } else if (is_enum (type) && enum_as_bool (type, &enum_zero, &enum_one)) {
zero = enum_zero; zero = enum_zero;
one = enum_one; one = enum_one;

View file

@ -110,12 +110,12 @@ static bool fp_ass_mul (void)
static expr_type_t string_string[] = { static expr_type_t string_string[] = {
{'+', &type_string}, {'+', &type_string},
{QC_EQ, &type_int}, {QC_EQ, &type_bool},
{QC_NE, &type_int}, {QC_NE, &type_bool},
{QC_LE, &type_int}, {QC_LE, &type_bool},
{QC_GE, &type_int}, {QC_GE, &type_bool},
{QC_LT, &type_int}, {QC_LT, &type_bool},
{QC_GT, &type_int}, {QC_GT, &type_bool},
{0, 0} {0, 0}
}; };
@ -137,14 +137,14 @@ static expr_type_t float_float[] = {
{QC_MOD, &type_float}, {QC_MOD, &type_float},
{QC_SHL, &type_float}, {QC_SHL, &type_float},
{QC_SHR, &type_float}, {QC_SHR, &type_float},
{QC_AND, &type_int}, {QC_AND, &type_bool},
{QC_OR, &type_int}, {QC_OR, &type_bool},
{QC_EQ, &type_int}, {QC_EQ, &type_bool},
{QC_NE, &type_int}, {QC_NE, &type_bool},
{QC_LE, &type_int}, {QC_LE, &type_bool},
{QC_GE, &type_int}, {QC_GE, &type_bool},
{QC_LT, &type_int}, {QC_LT, &type_bool},
{QC_GT, &type_int}, {QC_GT, &type_bool},
{0, 0} {0, 0}
}; };
@ -176,12 +176,12 @@ static expr_type_t float_int[] = {
{QC_MOD, &type_float, 0, &type_float}, {QC_MOD, &type_float, 0, &type_float},
{QC_SHL, &type_float, 0, &type_float}, {QC_SHL, &type_float, 0, &type_float},
{QC_SHR, &type_float, 0, &type_float}, {QC_SHR, &type_float, 0, &type_float},
{QC_EQ, &type_int, 0, &type_float}, {QC_EQ, &type_bool, 0, &type_float},
{QC_NE, &type_int, 0, &type_float}, {QC_NE, &type_bool, 0, &type_float},
{QC_LE, &type_int, 0, &type_float}, {QC_LE, &type_bool, 0, &type_float},
{QC_GE, &type_int, 0, &type_float}, {QC_GE, &type_bool, 0, &type_float},
{QC_LT, &type_int, 0, &type_float}, {QC_LT, &type_bool, 0, &type_float},
{QC_GT, &type_int, 0, &type_float}, {QC_GT, &type_bool, 0, &type_float},
{0, 0} {0, 0}
}; };
#define float_uint float_int #define float_uint float_int
@ -240,14 +240,14 @@ static expr_type_t vector_double[] = {
}; };
static expr_type_t entity_entity[] = { static expr_type_t entity_entity[] = {
{QC_EQ, &type_int, 0, 0, entity_compare}, {QC_EQ, &type_bool, 0, 0, entity_compare},
{QC_NE, &type_int, 0, 0, entity_compare}, {QC_NE, &type_bool, 0, 0, entity_compare},
{0, 0} {0, 0}
}; };
static expr_type_t field_field[] = { static expr_type_t field_field[] = {
{QC_EQ, &type_int}, {QC_EQ, &type_bool},
{QC_NE, &type_int}, {QC_NE, &type_bool},
{0, 0} {0, 0}
}; };
@ -335,12 +335,12 @@ static expr_type_t int_float[] = {
{QC_MOD, &type_float, &type_float, 0}, {QC_MOD, &type_float, &type_float, 0},
{QC_SHL, &type_int, 0, &type_int}, //FIXME? {QC_SHL, &type_int, 0, &type_int}, //FIXME?
{QC_SHR, &type_int, 0, &type_int}, //FIXME? {QC_SHR, &type_int, 0, &type_int}, //FIXME?
{QC_EQ, &type_int, &type_float, 0}, {QC_EQ, &type_bool, &type_float, 0},
{QC_NE, &type_int, &type_float, 0}, {QC_NE, &type_bool, &type_float, 0},
{QC_LE, &type_int, &type_float, 0}, {QC_LE, &type_bool, &type_float, 0},
{QC_GE, &type_int, &type_float, 0}, {QC_GE, &type_bool, &type_float, 0},
{QC_LT, &type_int, &type_float, 0}, {QC_LT, &type_bool, &type_float, 0},
{QC_GT, &type_int, &type_float, 0}, {QC_GT, &type_bool, &type_float, 0},
{0, 0} {0, 0}
}; };
@ -377,14 +377,14 @@ static expr_type_t int_int[] = {
{QC_MOD, &type_int}, {QC_MOD, &type_int},
{QC_SHL, &type_int}, {QC_SHL, &type_int},
{QC_SHR, &type_int}, {QC_SHR, &type_int},
{QC_AND, &type_int}, {QC_AND, &type_bool},
{QC_OR, &type_int}, {QC_OR, &type_bool},
{QC_EQ, &type_int}, {QC_EQ, &type_bool},
{QC_NE, &type_int}, {QC_NE, &type_bool},
{QC_LE, &type_int}, {QC_LE, &type_bool},
{QC_GE, &type_int}, {QC_GE, &type_bool},
{QC_LT, &type_int}, {QC_LT, &type_bool},
{QC_GT, &type_int}, {QC_GT, &type_bool},
{0, 0} {0, 0}
}; };
@ -406,8 +406,8 @@ static expr_type_t int_uint[] = {
{QC_MOD, &type_int, 0, &type_int}, {QC_MOD, &type_int, 0, &type_int},
{QC_SHL, &type_int, 0, &type_int}, {QC_SHL, &type_int, 0, &type_int},
{QC_SHR, &type_int, 0, &type_int}, {QC_SHR, &type_int, 0, &type_int},
{QC_EQ, &type_int, 0, &type_int}, {QC_EQ, &type_bool, 0, &type_int},
{QC_NE, &type_int, 0, &type_int}, {QC_NE, &type_bool, 0, &type_int},
{QC_LE, .process = uint_compare}, {QC_LE, .process = uint_compare},
{QC_GE, .process = uint_compare}, {QC_GE, .process = uint_compare},
{QC_LT, .process = uint_compare}, {QC_LT, .process = uint_compare},
@ -433,12 +433,12 @@ static expr_type_t int_short[] = {
{QC_MOD, &type_int, 0, &type_int}, {QC_MOD, &type_int, 0, &type_int},
{QC_SHL, &type_int, 0, &type_int}, {QC_SHL, &type_int, 0, &type_int},
{QC_SHR, &type_int, 0, &type_int}, {QC_SHR, &type_int, 0, &type_int},
{QC_EQ, &type_int, 0, &type_int}, {QC_EQ, &type_bool, 0, &type_int},
{QC_NE, &type_int, 0, &type_int}, {QC_NE, &type_bool, 0, &type_int},
{QC_LE, &type_int, 0, &type_int}, {QC_LE, &type_bool, 0, &type_int},
{QC_GE, &type_int, 0, &type_int}, {QC_GE, &type_bool, 0, &type_int},
{QC_LT, &type_int, 0, &type_int}, {QC_LT, &type_bool, 0, &type_int},
{QC_GT, &type_int, 0, &type_int}, {QC_GT, &type_bool, 0, &type_int},
{0, 0} {0, 0}
}; };
@ -452,12 +452,12 @@ static expr_type_t int_double[] = {
{'/', &type_double, &type_double, 0}, {'/', &type_double, &type_double, 0},
{'%', &type_double, &type_double, 0}, {'%', &type_double, &type_double, 0},
{QC_MOD, &type_double, &type_double, 0}, {QC_MOD, &type_double, &type_double, 0},
{QC_EQ, &type_long, &type_double, 0}, {QC_EQ, &type_lbool, &type_double, 0},
{QC_NE, &type_long, &type_double, 0}, {QC_NE, &type_lbool, &type_double, 0},
{QC_LE, &type_long, &type_double, 0}, {QC_LE, &type_lbool, &type_double, 0},
{QC_GE, &type_long, &type_double, 0}, {QC_GE, &type_lbool, &type_double, 0},
{QC_LT, &type_long, &type_double, 0}, {QC_LT, &type_lbool, &type_double, 0},
{QC_GT, &type_long, &type_double, 0}, {QC_GT, &type_lbool, &type_double, 0},
{0, 0} {0, 0}
}; };
@ -484,8 +484,8 @@ static expr_type_t uint_int[] = {
{QC_MOD, &type_int, &type_int, &type_int }, {QC_MOD, &type_int, &type_int, &type_int },
{QC_SHL, &type_uint, &type_int, &type_int }, {QC_SHL, &type_uint, &type_int, &type_int },
{QC_SHR, &type_uint, 0, &type_int }, {QC_SHR, &type_uint, 0, &type_int },
{QC_EQ, &type_int, &type_int, &type_int }, {QC_EQ, &type_bool, &type_int, &type_int },
{QC_NE, &type_int, &type_int, &type_int }, {QC_NE, &type_bool, &type_int, &type_int },
{QC_LE, .process = uint_compare}, {QC_LE, .process = uint_compare},
{QC_GE, .process = uint_compare}, {QC_GE, .process = uint_compare},
{QC_LT, .process = uint_compare}, {QC_LT, .process = uint_compare},
@ -511,8 +511,8 @@ static expr_type_t uint_uint[] = {
{QC_MOD, &type_uint}, {QC_MOD, &type_uint},
{QC_SHL, &type_uint}, {QC_SHL, &type_uint},
{QC_SHR, &type_uint}, {QC_SHR, &type_uint},
{QC_EQ, &type_int, &type_int, &type_int}, {QC_EQ, &type_bool, &type_int, &type_int},
{QC_NE, &type_int, &type_int, &type_int}, {QC_NE, &type_bool, &type_int, &type_int},
{QC_LE, &type_int}, {QC_LE, &type_int},
{QC_GE, &type_int}, {QC_GE, &type_int},
{QC_LT, &type_int}, {QC_LT, &type_int},
@ -545,12 +545,12 @@ static expr_type_t short_int[] = {
{QC_MOD, &type_int, &type_int, 0}, {QC_MOD, &type_int, &type_int, 0},
{QC_SHL, &type_short}, {QC_SHL, &type_short},
{QC_SHR, &type_short}, {QC_SHR, &type_short},
{QC_EQ, &type_int, &type_int, 0}, {QC_EQ, &type_bool, &type_int, 0},
{QC_NE, &type_int, &type_int, 0}, {QC_NE, &type_bool, &type_int, 0},
{QC_LE, &type_int, &type_int, 0}, {QC_LE, &type_bool, &type_int, 0},
{QC_GE, &type_int, &type_int, 0}, {QC_GE, &type_bool, &type_int, 0},
{QC_LT, &type_int, &type_int, 0}, {QC_LT, &type_bool, &type_int, 0},
{QC_GT, &type_int, &type_int, 0}, {QC_GT, &type_bool, &type_int, 0},
{0, 0} {0, 0}
}; };
@ -572,12 +572,12 @@ static expr_type_t short_uint[] = {
{QC_MOD, &type_uint, &type_uint, 0}, {QC_MOD, &type_uint, &type_uint, 0},
{QC_SHL, &type_short}, {QC_SHL, &type_short},
{QC_SHR, &type_short}, {QC_SHR, &type_short},
{QC_EQ, &type_int, &type_uint, 0}, {QC_EQ, &type_bool, &type_uint, 0},
{QC_NE, &type_int, &type_uint, 0}, {QC_NE, &type_bool, &type_uint, 0},
{QC_LE, &type_int, &type_uint, 0}, {QC_LE, &type_bool, &type_uint, 0},
{QC_GE, &type_int, &type_uint, 0}, {QC_GE, &type_bool, &type_uint, 0},
{QC_LT, &type_int, &type_uint, 0}, {QC_LT, &type_bool, &type_uint, 0},
{QC_GT, &type_int, &type_uint, 0}, {QC_GT, &type_bool, &type_uint, 0},
{0, 0} {0, 0}
}; };
@ -593,12 +593,12 @@ static expr_type_t short_short[] = {
{QC_MOD, &type_short}, {QC_MOD, &type_short},
{QC_SHL, &type_short}, {QC_SHL, &type_short},
{QC_SHR, &type_short}, {QC_SHR, &type_short},
{QC_EQ, &type_int}, {QC_EQ, &type_bool},
{QC_NE, &type_int}, {QC_NE, &type_bool},
{QC_LE, &type_int}, {QC_LE, &type_bool},
{QC_GE, &type_int}, {QC_GE, &type_bool},
{QC_LT, &type_int}, {QC_LT, &type_bool},
{QC_GT, &type_int}, {QC_GT, &type_bool},
{0, 0} {0, 0}
}; };
#define short_double int_double #define short_double int_double
@ -663,12 +663,12 @@ static expr_type_t double_double[] = {
{'/', &type_double}, {'/', &type_double},
{'%', &type_double}, {'%', &type_double},
{QC_MOD, &type_double}, {QC_MOD, &type_double},
{QC_EQ, &type_long}, {QC_EQ, &type_lbool},
{QC_NE, &type_long}, {QC_NE, &type_lbool},
{QC_LE, &type_long}, {QC_LE, &type_lbool},
{QC_GE, &type_long}, {QC_GE, &type_lbool},
{QC_LT, &type_long}, {QC_LT, &type_lbool},
{QC_GT, &type_long}, {QC_GT, &type_lbool},
{0, 0} {0, 0}
}; };
@ -690,12 +690,12 @@ static expr_type_t long_long[] = {
{QC_MOD, &type_long}, {QC_MOD, &type_long},
{QC_SHL, &type_long}, {QC_SHL, &type_long},
{QC_SHR, &type_long}, {QC_SHR, &type_long},
{QC_EQ, &type_long}, {QC_EQ, &type_lbool},
{QC_NE, &type_long}, {QC_NE, &type_lbool},
{QC_LE, &type_long}, {QC_LE, &type_lbool},
{QC_GE, &type_long}, {QC_GE, &type_lbool},
{QC_LT, &type_long}, {QC_LT, &type_lbool},
{QC_GT, &type_long}, {QC_GT, &type_lbool},
{0, 0} {0, 0}
}; };
@ -717,12 +717,12 @@ static expr_type_t ulong_ulong[] = {
{QC_MOD, &type_ulong}, {QC_MOD, &type_ulong},
{QC_SHL, &type_ulong}, {QC_SHL, &type_ulong},
{QC_SHR, &type_ulong}, {QC_SHR, &type_ulong},
{QC_EQ, &type_long}, {QC_EQ, &type_lbool},
{QC_NE, &type_long}, {QC_NE, &type_lbool},
{QC_LE, &type_long}, {QC_LE, &type_lbool},
{QC_GE, &type_long}, {QC_GE, &type_lbool},
{QC_LT, &type_long}, {QC_LT, &type_lbool},
{QC_GT, &type_long}, {QC_GT, &type_lbool},
{0, 0} {0, 0}
}; };
@ -848,15 +848,15 @@ static expr_type_t **binary_expr_types[ev_type_count] = {
}; };
static expr_type_t int_handle[] = { static expr_type_t int_handle[] = {
{QC_EQ, &type_int}, {QC_EQ, &type_bool},
{QC_NE, &type_int}, {QC_NE, &type_bool},
{0, 0} {0, 0}
}; };
static expr_type_t long_handle[] = { static expr_type_t long_handle[] = {
{QC_EQ, &type_int}, {QC_EQ, &type_bool},
{QC_NE, &type_int}, {QC_NE, &type_bool},
{0, 0} {0, 0}
}; };
@ -874,11 +874,45 @@ static expr_type_t **binary_expr_handle[ev_type_count] = {
[ev_long] = long_handle_x, [ev_long] = long_handle_x,
}; };
static expr_type_t int_bool[] = {
{'|', &type_bool},
{'&', &type_bool},
{'^', &type_bool},
{QC_EQ, &type_bool},
{QC_NE, &type_bool},
{0, 0}
};
static expr_type_t long_bool[] = {
{'|', &type_lbool},
{'&', &type_lbool},
{'^', &type_lbool},
{QC_EQ, &type_lbool},
{QC_NE, &type_lbool},
{0, 0}
};
static expr_type_t *int_bool_x[ev_type_count] = {
[ev_int] = int_bool,
};
static expr_type_t *long_bool_x[ev_type_count] = {
[ev_long] = long_bool,
};
static expr_type_t **binary_expr_bool[ev_type_count] = {
[ev_int] = int_bool_x,
[ev_long] = long_bool_x,
};
static expr_type_t ***binary_expr_meta[ty_meta_count] = { static expr_type_t ***binary_expr_meta[ty_meta_count] = {
[ty_basic] = binary_expr_types, [ty_basic] = binary_expr_types,
[ty_enum] = binary_expr_types, [ty_enum] = binary_expr_types,
[ty_alias] = binary_expr_types, [ty_alias] = binary_expr_types,
[ty_handle] = binary_expr_handle, [ty_handle] = binary_expr_handle,
[ty_bool] = binary_expr_bool,
}; };
// supported operators for scalar-vector expressions // supported operators for scalar-vector expressions
@ -968,7 +1002,7 @@ pointer_compare (int op, const expr_t *e1, const expr_t *e2)
e = new_binary_expr (op, cast_expr (&type_int, e1), e = new_binary_expr (op, cast_expr (&type_int, e1),
cast_expr (&type_int, e2)); cast_expr (&type_int, e2));
} }
e->expr.type = &type_int; e->expr.type = &type_bool;
return e; return e;
} }
@ -983,7 +1017,7 @@ func_compare (int op, const expr_t *e1, const expr_t *e2)
e = new_binary_expr (op, new_alias_expr (&type_int, e1), e = new_binary_expr (op, new_alias_expr (&type_int, e1),
new_alias_expr (&type_int, e2)); new_alias_expr (&type_int, e2));
} }
e->expr.type = &type_int; e->expr.type = &type_bool;
if (options.code.progsversion == PROG_ID_VERSION) { if (options.code.progsversion == PROG_ID_VERSION) {
e->expr.type = &type_float; e->expr.type = &type_float;
} }
@ -1014,7 +1048,7 @@ vector_compare (int op, const expr_t *e1, const expr_t *e2)
e1 = new_alias_expr (&type_vec3, e1); e1 = new_alias_expr (&type_vec3, e1);
e2 = new_alias_expr (&type_vec3, e2); e2 = new_alias_expr (&type_vec3, e2);
expr_t *e = new_binary_expr (op, e1, e2); expr_t *e = new_binary_expr (op, e1, e2);
e->expr.type = &type_ivec3; e->expr.type = &type_bvec3;
return new_horizontal_expr (hop, e, &type_int); return new_horizontal_expr (hop, e, &type_int);
} }
@ -1023,14 +1057,14 @@ quat_compare (int op, const expr_t *e1, const expr_t *e2)
{ {
if (options.code.progsversion < PROG_VERSION) { if (options.code.progsversion < PROG_VERSION) {
expr_t *e = new_binary_expr (op, e1, e2); expr_t *e = new_binary_expr (op, e1, e2);
e->expr.type = &type_int; e->expr.type = &type_bool;
return e; return e;
} }
int hop = op == QC_EQ ? '&' : '|'; int hop = op == QC_EQ ? '&' : '|';
e1 = new_alias_expr (&type_vec4, e1); e1 = new_alias_expr (&type_vec4, e1);
e2 = new_alias_expr (&type_vec4, e2); e2 = new_alias_expr (&type_vec4, e2);
expr_t *e = new_binary_expr (op, e1, e2); expr_t *e = new_binary_expr (op, e1, e2);
e->expr.type = &type_ivec4; e->expr.type = &type_bvec4;
return new_horizontal_expr (hop, e, &type_int); return new_horizontal_expr (hop, e, &type_int);
} }
@ -1102,7 +1136,7 @@ double_compare (int op, const expr_t *e1, const expr_t *e2)
e1 = cast_expr (&type_double, e1); e1 = cast_expr (&type_double, e1);
} }
e = new_binary_expr (op, e1, e2); e = new_binary_expr (op, e1, e2);
e->expr.type = &type_long; e->expr.type = &type_lbool;
return e; return e;
} }
@ -1130,7 +1164,7 @@ uint_compare (int op, const expr_t *e1, const expr_t *e2)
} }
} }
e = new_binary_expr (op, e1, e2); e = new_binary_expr (op, e1, e2);
e->expr.type = &type_int; e->expr.type = &type_bool;
return e; return e;
} }
@ -1142,7 +1176,7 @@ entity_compare (int op, const expr_t *e1, const expr_t *e2)
e2 = new_alias_expr (&type_int, e2); e2 = new_alias_expr (&type_int, e2);
} }
expr_t *e = new_binary_expr (op, e1, e2); expr_t *e = new_binary_expr (op, e1, e2);
e->expr.type = &type_int; e->expr.type = &type_bool;
if (options.code.progsversion == PROG_ID_VERSION) { if (options.code.progsversion == PROG_ID_VERSION) {
e->expr.type = &type_float; e->expr.type = &type_float;
} }

View file

@ -234,15 +234,15 @@ bool_expr (int op, const expr_t *label, const expr_t *e1, const expr_t *e2)
switch (op) { switch (op) {
case QC_OR: case QC_OR:
backpatch (e1->boolean.false_list, label); backpatch (e1->boolean.false_list, label);
return new_bool_expr (merge (e1->boolean.true_list, return new_boolean_expr (merge (e1->boolean.true_list,
e2->boolean.true_list), e2->boolean.true_list),
e2->boolean.false_list, block); e2->boolean.false_list, block);
break; break;
case QC_AND: case QC_AND:
backpatch (e1->boolean.true_list, label); backpatch (e1->boolean.true_list, label);
return new_bool_expr (e2->boolean.true_list, return new_boolean_expr (e2->boolean.true_list,
merge (e1->boolean.false_list, merge (e1->boolean.false_list,
e2->boolean.false_list), block); e2->boolean.false_list), block);
break; break;
} }
internal_error (e1, 0); internal_error (e1, 0);
@ -301,15 +301,16 @@ convert_bool (const expr_t *e, int block)
val = expr_float (e) != 0; val = expr_float (e) != 0;
} }
if (val) if (val)
e = new_bool_expr (make_list (b), 0, b); e = new_boolean_expr (make_list (b), 0, b);
else else
e = new_bool_expr (0, make_list (b), b); e = new_boolean_expr (0, make_list (b), b);
} else { } else {
auto b = new_block_expr (0); auto b = new_block_expr (0);
append_expr (b, branch_expr (QC_NE, e, 0)); append_expr (b, branch_expr (QC_NE, e, 0));
append_expr (b, goto_expr (0)); append_expr (b, goto_expr (0));
e = new_bool_expr (make_list (b->block.list.head->expr), e = new_boolean_expr (make_list (b->block.list.head->expr),
make_list (b->block.list.head->next->expr), b); make_list (b->block.list.head->next->expr),
b);
} }
} }
if (block && e->boolean.e->type != ex_block) { if (block && e->boolean.e->type != ex_block) {

View file

@ -41,6 +41,7 @@
#include "tools/qfcc/include/def.h" #include "tools/qfcc/include/def.h"
#include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/diagnostic.h"
#include "tools/qfcc/include/expr.h" #include "tools/qfcc/include/expr.h"
#include "tools/qfcc/include/struct.h"
#include "tools/qfcc/include/type.h" #include "tools/qfcc/include/type.h"
#include "tools/qfcc/include/value.h" #include "tools/qfcc/include/value.h"
@ -115,6 +116,23 @@ cast_expr (const type_t *dstType, const expr_t *e)
|| (is_string (dstType) && is_pointer (srcType))) { || (is_string (dstType) && is_pointer (srcType))) {
return new_alias_expr (dstType, e); return new_alias_expr (dstType, e);
} }
if (is_enum (dstType) && is_boolean (srcType)) {
expr_t *enum_zero, *enum_one;
if (enum_as_bool (dstType, &enum_zero, &enum_one)) {
return conditional_expr (e, enum_one, enum_zero);
}
}
if (is_integral (dstType) && is_boolean (srcType)) {
auto type = dstType;
if (type_size (dstType) != type_size (srcType)) {
type = ev_types[srcType->type];
}
e = new_alias_expr (type, e);
if (type != dstType) {
e = cast_expr (dstType, e);
}
return e;
}
if (is_algebra (dstType) || is_algebra (srcType)) { if (is_algebra (dstType) || is_algebra (srcType)) {
const expr_t *c; const expr_t *c;
if ((c = algebra_cast_expr (dstType, e))) { if ((c = algebra_cast_expr (dstType, e))) {

View file

@ -269,6 +269,18 @@ ulong_bitnot (const expr_t *e)
return new_ulong_expr (~expr_ulong (e)); return new_ulong_expr (~expr_ulong (e));
} }
static const expr_t *
bool_not (const expr_t *e)
{
return new_bool_expr (expr_int (e));
}
static const expr_t *
lbool_not (const expr_t *e)
{
return new_lbool_expr (expr_long (e));
}
static unary_type_t string_u[] = { static unary_type_t string_u[] = {
{ .op = '!', .result_type = &type_bool, .constant = string_not, }, { .op = '!', .result_type = &type_bool, .constant = string_not, },
@ -414,6 +426,18 @@ static unary_type_t algebra_u[] = {
{} {}
}; };
static unary_type_t bool_u[] = {
{ .op = '!', .result_type = &type_bool, .constant = bool_not, },
{}
};
static unary_type_t lbool_u[] = {
{ .op = '!', .result_type = &type_lbool, .constant = lbool_not, },
{}
};
static unary_type_t *unary_expr_types[ev_type_count] = { static unary_type_t *unary_expr_types[ev_type_count] = {
[ev_string] = string_u, [ev_string] = string_u,
[ev_float] = float_u, [ev_float] = float_u,
@ -448,7 +472,8 @@ unary_expr (int op, const expr_t *e)
auto t = get_type (e); auto t = get_type (e);
if (op == '!' && e->type == ex_bool) { if (op == '!' && e->type == ex_bool) {
return new_bool_expr (e->boolean.false_list, e->boolean.true_list, e); return new_boolean_expr (e->boolean.false_list,
e->boolean.true_list, e);
} }
if (op == '+' && is_math (t)) { if (op == '+' && is_math (t)) {
@ -459,6 +484,10 @@ unary_expr (int op, const expr_t *e)
unary_type = algebra_u; unary_type = algebra_u;
} else if (is_enum (t)) { } else if (is_enum (t)) {
unary_type = int_u; unary_type = int_u;
} else if (is_bool (t)) {
unary_type = bool_u;
} else if (is_lbool (t)) {
unary_type = lbool_u;
} else if (t->meta == ty_basic || is_handle (t)) { } else if (t->meta == ty_basic || is_handle (t)) {
unary_type = unary_expr_types[t->type]; unary_type = unary_expr_types[t->type];
} }

View file

@ -324,6 +324,7 @@ pp_vnumber '({s}*{m}?{pp_number}){2,4}{s}*'{ULFD}?
"&&" { return QC_AND; } "&&" { return QC_AND; }
"||" { return QC_OR; } "||" { return QC_OR; }
"^^" { return QC_XOR; }
"==" { return QC_EQ; } "==" { return QC_EQ; }
"!=" { return QC_NE; } "!=" { return QC_NE; }
"<=" { return QC_LE; } "<=" { return QC_LE; }

View file

@ -145,6 +145,7 @@ int yylex (YYSTYPE *yylval, YYLTYPE *yylloc);
%left '.' '(' '[' %left '.' '(' '['
%token <expr> VALUE STRING TOKEN %token <expr> VALUE STRING TOKEN
%token TRUE FALSE
%token ELLIPSIS %token ELLIPSIS
%token RESERVED %token RESERVED
// end of common tokens // end of common tokens
@ -2117,6 +2118,18 @@ arg_expr
const const
: VALUE : VALUE
| TRUE
{
pr_type_t data = { .value = 1 };
auto val = new_type_value (&type_bool, &data);
$$ = new_value_expr (val, false);
}
| FALSE
{
pr_type_t data = { .value = 0 };
auto val = new_type_value (&type_bool, &data);
$$ = new_value_expr (val, false);
}
| NIL { $$ = new_nil_expr (); } | NIL { $$ = new_nil_expr (); }
| string | string
; ;
@ -2864,11 +2877,15 @@ static keyword_t qf_keywords[] = {
{"double", QC_TYPE_SPEC, .spec = { .type = &type_double } }, {"double", QC_TYPE_SPEC, .spec = { .type = &type_double } },
{"int", QC_TYPE_SPEC, .spec = { .type = &type_int } }, {"int", QC_TYPE_SPEC, .spec = { .type = &type_int } },
{"bool", QC_TYPE_SPEC, .spec = { .type = &type_bool } }, {"bool", QC_TYPE_SPEC, .spec = { .type = &type_bool } },
{"lbool", QC_TYPE_SPEC, .spec = { .type = &type_lbool } },
{"unsigned", QC_TYPE_SPEC, .spec = { .is_unsigned = true } }, {"unsigned", QC_TYPE_SPEC, .spec = { .is_unsigned = true } },
{"signed", QC_TYPE_SPEC, .spec = { .is_signed = true } }, {"signed", QC_TYPE_SPEC, .spec = { .is_signed = true } },
{"long", QC_TYPE_SPEC, .spec = { .is_long = true } }, {"long", QC_TYPE_SPEC, .spec = { .is_long = true } },
{"short", QC_TYPE_SPEC, .spec = { .is_short = true } }, {"short", QC_TYPE_SPEC, .spec = { .is_short = true } },
{"true", QC_TRUE },
{"false", QC_FALSE},
{"@args", QC_ARGS, }, {"@args", QC_ARGS, },
{"@va_list", QC_TYPE_SPEC, .spec = { .type = &type_va_list } }, {"@va_list", QC_TYPE_SPEC, .spec = { .type = &type_va_list } },
{"@param", QC_TYPE_SPEC, .spec = { .type = &type_param } }, {"@param", QC_TYPE_SPEC, .spec = { .type = &type_param } },

View file

@ -141,9 +141,12 @@ int yylex (void);
%token <type> TYPE TYPE_NAME %token <type> TYPE TYPE_NAME
%token <symbol> ID %token <symbol> ID
%token <expr> VALUE %token <expr> VALUE
%token TRUE FALSE
%token ELLIPSIS
%token RESERVED
%token PROGRAM VAR ARRAY OF FUNCTION PROCEDURE PBEGIN END IF THEN ELSE %token PROGRAM VAR ARRAY OF FUNCTION PROCEDURE PBEGIN END IF THEN ELSE
%token WHILE DO RANGE ASSIGNOP NOT ELLIPSIS %token WHILE DO RANGE ASSIGNOP NOT
%token RETURN %token RETURN
%type <type> type standard_type %type <type> type standard_type

View file

@ -308,7 +308,7 @@ add_enum (symbol_t *enm, symbol_t *name, const expr_t *val)
symtab_addsymbol (enum_tab, name); symtab_addsymbol (enum_tab, name);
} }
int bool
enum_as_bool (const type_t *enm, expr_t **zero, expr_t **one) enum_as_bool (const type_t *enm, expr_t **zero, expr_t **one)
{ {
symtab_t *symtab = enm->symtab; symtab_t *symtab = enm->symtab;
@ -318,7 +318,7 @@ enum_as_bool (const type_t *enm, expr_t **zero, expr_t **one)
int val, v; int val, v;
if (!symtab) if (!symtab)
return 0; return false;
for (sym = symtab->symbols; sym; sym = sym->next) { for (sym = symtab->symbols; sym; sym = sym->next) {
if (sym->sy_type != sy_const) if (sym->sy_type != sy_const)
continue; continue;
@ -336,10 +336,10 @@ enum_as_bool (const type_t *enm, expr_t **zero, expr_t **one)
} }
if (!zero_sym || !one_sym) if (!zero_sym || !one_sym)
return 0; return false;
*zero = new_symbol_expr (zero_sym); *zero = new_symbol_expr (zero_sym);
*one = new_symbol_expr (one_sym); *one = new_symbol_expr (one_sym);
return 1; return true;
} }
symbol_t * symbol_t *

View file

@ -445,7 +445,7 @@ switch_expr (switch_block_t *switch_block, const expr_t *break_label,
case_node_t *case_tree; case_node_t *case_tree;
if (is_string(type)) if (is_string(type))
temp = new_temp_def_expr (&type_int); temp = new_temp_def_expr (&type_bool);
else else
temp = new_temp_def_expr (type); temp = new_temp_def_expr (type);
case_tree = build_case_tree (labels, num_labels, is_integral (type)); case_tree = build_case_tree (labels, num_labels, is_integral (type));

View file

@ -746,10 +746,16 @@ reference_type (const type_t *aux)
const type_t * const type_t *
matrix_type (const type_t *ele_type, int cols, int rows) matrix_type (const type_t *ele_type, int cols, int rows)
{ {
if (!is_bool (ele_type) && !is_scalar (ele_type)) { if (!is_boolean (ele_type) && !is_scalar (ele_type)) {
return nullptr; return nullptr;
} }
if (rows == 1 && cols == 1) { if (rows == 1 && cols == 1) {
if (is_bool (ele_type)) {
return &type_bool;
}
if (is_lbool (ele_type)) {
return &type_lbool;
}
for (auto t = ev_types; t - ev_types < ev_type_count; t++) { for (auto t = ev_types; t - ev_types < ev_type_count; t++) {
if ((*t)->type == ele_type->type && (*t)->width == 1) { if ((*t)->type == ele_type->type && (*t)->width == 1) {
return *t; return *t;
@ -1376,7 +1382,23 @@ is_bool (const type_t *type)
if (type->meta != ty_bool) { if (type->meta != ty_bool) {
return false; return false;
} }
return type->type == ev_int || type->type == ev_long; return type->type == ev_int;
}
bool
is_lbool (const type_t *type)
{
type = unalias_type (type);
if (type->meta != ty_bool) {
return false;
}
return type->type == ev_long;
}
bool
is_boolean (const type_t *type)
{
return is_bool (type) || is_lbool (type);
} }
bool bool
@ -1425,7 +1447,7 @@ is_scalar (const type_t *type)
if (type->width != 1) { if (type->width != 1) {
return false; return false;
} }
return is_real (type) || is_integral (type); return is_real (type) || is_integral (type) || is_boolean (type);
} }
bool bool
@ -1563,6 +1585,20 @@ type_assignable (const type_t *dst, const type_t *src)
&& type_width (dst) == type_width (src)) { && type_width (dst) == type_width (src)) {
return true; return true;
} }
if ((is_int (dst) || is_uint (dst) || is_float (dst))
&& is_bool (src)) {
return true;
}
if (is_enum (dst) && is_bool (src)) {
return true;
}
if ((is_long (dst) || is_ulong (dst) || is_double (dst))
&& is_boolean (src)) {
return true;
}
if (is_lbool (dst) && is_bool (src)) {
return true;
}
return false; return false;
} }
@ -1599,26 +1635,30 @@ type_promotes (const type_t *dst, const type_t *src)
|| type_cols (dst) != type_cols (src)) { || type_cols (dst) != type_cols (src)) {
return false; return false;
} }
// nothing promotes to int
if (is_int (dst)) { if (is_int (dst) && is_bool (src)) {
return true; return true;
} }
if (is_uint (dst) && is_int (src)) { if (is_uint (dst) && is_int (src)) {
return true; return true;
} }
if (is_long (dst) && (is_int (src) || is_uint (src))) { if (is_long (dst) && (is_int (src) || is_uint (src) || is_boolean (src))) {
return true; return true;
} }
if (is_ulong (dst) && (is_int (src) || is_uint (src) || is_long (src))) { if (is_ulong (dst) && (is_int (src) || is_uint (src) || is_long (src)
|| is_boolean (src))) {
return true; return true;
} }
if (is_float (dst) && (is_int (src) || is_uint (src))) { if (is_float (dst) && (is_int (src) || is_uint (src) || is_bool (src))) {
return true; return true;
} }
//XXX what to do with (u)long<->float? //XXX what to do with (u)long<->float?
if (is_double (dst) if (is_double (dst)
&& (is_int (src) || is_uint (src) || is_long (src) || is_ulong (src) && (is_int (src) || is_uint (src) || is_long (src) || is_ulong (src)
|| is_float (src))) { || is_float (src) || is_boolean (src))) {
return true;
}
if (is_lbool (dst) && is_bool (src)) {
return true; return true;
} }
return false; return false;

View file

@ -36,7 +36,7 @@ int subsub_c_t_c_e (int x) { return 6 - (7 - x); }
int int
main () main ()
{ {
int fail = 0; bool fail = false;
fail |= mul_e_c_t_c (10) != 420; fail |= mul_e_c_t_c (10) != 420;
fail |= mul_c_e_t_c (10) != 420; fail |= mul_c_e_t_c (10) != 420;

View file

@ -6,10 +6,10 @@ union {
int i[2]; int i[2];
} type_pun; } type_pun;
long bool
test_format () test_format ()
{ {
int fail = 0; bool fail;
type_pun.d = M_PI; type_pun.d = M_PI;
printf ("%.17g %08x%08x\n", type_pun.d, type_pun.i[1], type_pun.i[0]); printf ("%.17g %08x%08x\n", type_pun.d, type_pun.i[1], type_pun.i[0]);
// this will fail on big-endian systems // this will fail on big-endian systems
@ -17,10 +17,10 @@ test_format ()
return fail; return fail;
} }
long lbool
test_constant () test_constant ()
{ {
long fail = 0; lbool fail = false;
double a, b, c, d, e; double a, b, c, d, e;
a = 1; a = 1;
b = 2.0; b = 2.0;
@ -43,7 +43,7 @@ double greater = 5;
long long
test_copare () test_copare ()
{ {
long fail = 0; lbool fail = 0;
fail |= !(less < greater); fail |= !(less < greater);
fail |= (less > greater); fail |= (less > greater);
@ -75,10 +75,10 @@ test_copare ()
return fail; return fail;
} }
long lbool
test_ops () test_ops ()
{ {
long fail = 0; lbool fail = 0;
double a = 6.25, b = 2.375; double a = 6.25, b = 2.375;
double c; double c;
@ -98,8 +98,8 @@ test_ops ()
int int
main () main ()
{ {
long fail = 0; lbool fail = false;
fail |= test_format (); fail |= (lbool) test_format ();
fail |= test_constant (); fail |= test_constant ();
fail |= test_ops (); fail |= test_ops ();
return fail; return fail;

View file

@ -46,7 +46,7 @@ test_struct_4(Rect rect)
int int
main() main()
{ {
int ret = 0; bool ret = false;
ret |= test_struct_1(rect) != 1; ret |= test_struct_1(rect) != 1;
ret |= test_struct_2(rect) != 2; ret |= test_struct_2(rect) != 2;
ret |= test_struct_3(rect) != 3; ret |= test_struct_3(rect) != 3;