Prevent wrong types
This commit is contained in:
		@@ -18,7 +18,7 @@ void yyerror(char *s)
 | 
				
			|||||||
typedef struct var	// a variable
 | 
					typedef struct var	// a variable
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char *name;
 | 
						char *name;
 | 
				
			||||||
	int type;
 | 
						int class;
 | 
				
			||||||
	int value;	// 0 = bool, 1 = int
 | 
						int value;	// 0 = bool, 1 = int
 | 
				
			||||||
	struct var *next;
 | 
						struct var *next;
 | 
				
			||||||
} var;
 | 
					} var;
 | 
				
			||||||
@@ -32,6 +32,7 @@ typedef struct varlist	// variable reference (used for print statement)
 | 
				
			|||||||
typedef struct expr	// boolean expression
 | 
					typedef struct expr	// boolean expression
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int type;	// TRUE, FALSE, OR, AND, EQUIV, NOT, 0 (variable), PLUS, TIMES, INT, EQUALS, LT
 | 
						int type;	// TRUE, FALSE, OR, AND, EQUIV, NOT, 0 (variable), PLUS, TIMES, INT, EQUALS, LT
 | 
				
			||||||
 | 
						int class;	// 0 = bool, 1 = int, 2 = both
 | 
				
			||||||
	var *var;
 | 
						var *var;
 | 
				
			||||||
	struct expr *left, *right;
 | 
						struct expr *left, *right;
 | 
				
			||||||
} expr;
 | 
					} expr;
 | 
				
			||||||
@@ -55,11 +56,11 @@ stmt *program_stmts;
 | 
				
			|||||||
/****************************************************************************/
 | 
					/****************************************************************************/
 | 
				
			||||||
/* Functions for settting up data structures at parse time.                 */
 | 
					/* Functions for settting up data structures at parse time.                 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var* make_ident (char *s, int type)	// type = 0 for a boolean var, type = 1 for an int var
 | 
					var* make_ident (char *s, int class)	// type = 0 for a boolean var, type = 1 for an int var
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	var *v = malloc(sizeof(var));
 | 
						var *v = malloc(sizeof(var));
 | 
				
			||||||
	v->name = s;
 | 
						v->name = s;
 | 
				
			||||||
	v->type = type;
 | 
						v->class = class;
 | 
				
			||||||
	v->value = 0;	// make variable false initially
 | 
						v->value = 0;	// make variable false initially
 | 
				
			||||||
	v->next = NULL;
 | 
						v->next = NULL;
 | 
				
			||||||
	return v;
 | 
						return v;
 | 
				
			||||||
@@ -87,7 +88,7 @@ var* make_int(int val)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	var *v = malloc(sizeof(var));
 | 
						var *v = malloc(sizeof(var));
 | 
				
			||||||
	v->name = NULL;
 | 
						v->name = NULL;
 | 
				
			||||||
	v->type = 1;	// int
 | 
						v->class = 1;	// int
 | 
				
			||||||
	v->value = val;
 | 
						v->value = val;
 | 
				
			||||||
	v->next = NULL;
 | 
						v->next = NULL;
 | 
				
			||||||
	return v;
 | 
						return v;
 | 
				
			||||||
@@ -102,10 +103,11 @@ varlist* make_varlist (char *s)
 | 
				
			|||||||
	return l;
 | 
						return l;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
expr* make_expr (int type, var *var, expr *left, expr *right)
 | 
					expr* make_expr (int type, int class, var *var, expr *left, expr *right)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	expr *e = malloc(sizeof(expr));
 | 
						expr *e = malloc(sizeof(expr));
 | 
				
			||||||
	e->type = type;
 | 
						e->type = type;
 | 
				
			||||||
 | 
						e->class = class;
 | 
				
			||||||
	e->var = var;
 | 
						e->var = var;
 | 
				
			||||||
	e->left = left;
 | 
						e->left = left;
 | 
				
			||||||
	e->right = right;
 | 
						e->right = right;
 | 
				
			||||||
@@ -197,20 +199,20 @@ assign	: IDENT ASSIGN expr
 | 
				
			|||||||
varlist	: IDENT			{ $$ = make_varlist($1); }
 | 
					varlist	: IDENT			{ $$ = make_varlist($1); }
 | 
				
			||||||
	| varlist ',' IDENT	{ ($$ = make_varlist($3))->next = $1; }
 | 
						| varlist ',' IDENT	{ ($$ = make_varlist($3))->next = $1; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
expr	: IDENT		{ $$ = make_expr(0,find_ident($1),NULL,NULL); }
 | 
					expr	: IDENT		{ $$ = make_expr(0, 2, find_ident($1), NULL, NULL); }
 | 
				
			||||||
	| expr XOR expr	{ $$ = make_expr(XOR,NULL,$1,$3); }
 | 
						| expr XOR expr	{ $$ = make_expr(XOR, 0, NULL, $1, $3); }
 | 
				
			||||||
	| expr OR expr	{ $$ = make_expr(OR,NULL,$1,$3); }
 | 
						| expr OR expr	{ $$ = make_expr(OR, 0, NULL, $1, $3); }
 | 
				
			||||||
	| expr AND expr	{ $$ = make_expr(AND,NULL,$1,$3); }
 | 
						| expr AND expr	{ $$ = make_expr(AND, 0, NULL, $1, $3); }
 | 
				
			||||||
	| expr EQUIV expr 	{ $$ = make_expr(EQUIV,NULL,$1,$3); }
 | 
						| expr EQUIV expr 	{ $$ = make_expr(EQUIV, 0, NULL, $1, $3); }
 | 
				
			||||||
	| NOT expr	{ $$ = make_expr(NOT,NULL,$2,NULL); }
 | 
						| NOT expr	{ $$ = make_expr(NOT, 0, NULL, $2, NULL); }
 | 
				
			||||||
	| TRUE		{ $$ = make_expr(TRUE,NULL,NULL,NULL); }
 | 
						| TRUE		{ $$ = make_expr(TRUE, 0, NULL, NULL, NULL); }
 | 
				
			||||||
	| FALSE		{ $$ = make_expr(FALSE,NULL,NULL,NULL); }
 | 
						| FALSE		{ $$ = make_expr(FALSE, 0, NULL, NULL, NULL); }
 | 
				
			||||||
	| '(' expr ')'	{ $$ = $2; }
 | 
						| '(' expr ')'	{ $$ = $2; }
 | 
				
			||||||
	| INT		{ $$ = make_expr(INT, make_int($1), NULL, NULL); }
 | 
						| INT		{ $$ = make_expr(INT, 1, make_int($1), NULL, NULL); }
 | 
				
			||||||
	| expr TIMES expr	{ $$ = make_expr(TIMES, NULL, $1, $3); }
 | 
						| expr TIMES expr	{ $$ = make_expr(TIMES, 1, NULL, $1, $3); }
 | 
				
			||||||
	| expr PLUS expr	{ $$ = make_expr(PLUS, NULL, $1, $3); }
 | 
						| expr PLUS expr	{ $$ = make_expr(PLUS, 1, NULL, $1, $3); }
 | 
				
			||||||
	| expr EQUALS expr	{ $$ = make_expr(EQUALS, NULL, $1, $3); }
 | 
						| expr LT expr		{ $$ = make_expr(LT, 0, NULL, $1, $3); }
 | 
				
			||||||
	| expr LT expr		{ $$ = make_expr(LT, NULL, $1, $3); }
 | 
						| expr EQUALS expr	{ $$ = make_expr(EQUALS, 0, NULL, $1, $3); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%%
 | 
					%%
 | 
				
			||||||
@@ -226,25 +228,74 @@ int eval (expr *e)
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		case TRUE: return 1;
 | 
							case TRUE: return 1;
 | 
				
			||||||
		case FALSE: return 0;
 | 
							case FALSE: return 0;
 | 
				
			||||||
		case XOR: return eval(e->left) ^ eval(e->right);
 | 
							case XOR: {
 | 
				
			||||||
		case OR: return eval(e->left) || eval(e->right);
 | 
								if (e->left->class != 0 || e->right->class != 0) {
 | 
				
			||||||
		case AND: return eval(e->left) && eval(e->right);
 | 
									yyerror("An expression has wrong types");
 | 
				
			||||||
 | 
									exit(-1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return eval(e->left) ^ eval(e->right);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							case OR: {
 | 
				
			||||||
 | 
								if (e->left->class != 0 || e->right != NULL && e->right->class != 0) {
 | 
				
			||||||
 | 
									yyerror("An expression has wrong types");
 | 
				
			||||||
 | 
									exit(-1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return eval(e->left) || eval(e->right);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							case AND: {
 | 
				
			||||||
 | 
								if (e->left->class != 0 || e->right->class != 0) {
 | 
				
			||||||
 | 
									yyerror("An expression has wrong types");
 | 
				
			||||||
 | 
									exit(-1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return eval(e->left) && eval(e->right);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		case EQUIV: {
 | 
							case EQUIV: {
 | 
				
			||||||
 | 
								if (e->left->class != 0 || e->right->class != 0) {
 | 
				
			||||||
 | 
									yyerror("An expression has wrong types");
 | 
				
			||||||
 | 
									exit(-1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			int right = eval(e->right);
 | 
								int right = eval(e->right);
 | 
				
			||||||
			int left = eval(e->left);
 | 
								int left = eval(e->left);
 | 
				
			||||||
			return (right && left) || (!right && !left);  // Équivalent avec left == right avec la définition.
 | 
								return (right && left) || (!right && !left);  // Équivalent avec left == right avec la définition.
 | 
				
			||||||
														  // Toutefois, on privilégie cette forme car faux = 0 et vrai = tout entier non nul.
 | 
																			  // Toutefois, on privilégie cette forme car faux = 0 et vrai = tout entier non nul
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		case NOT: return !eval(e->left);
 | 
							case NOT: {
 | 
				
			||||||
		case PLUS:
 | 
								if (e->left->class != 0) {
 | 
				
			||||||
 | 
									yyerror("An expression has wrong types");
 | 
				
			||||||
 | 
									exit(-1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return !eval(e->left);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							case PLUS: {
 | 
				
			||||||
 | 
								if (e->left->class != 1 || e->right->class != 1) {
 | 
				
			||||||
 | 
									yyerror("An expression has wrong types");
 | 
				
			||||||
 | 
									exit(-1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			return eval(e->left) + eval(e->right);
 | 
								return eval(e->left) + eval(e->right);
 | 
				
			||||||
		case TIMES:
 | 
							}
 | 
				
			||||||
 | 
							case TIMES: {
 | 
				
			||||||
 | 
								if (e->left->class != 1 || e->right->class != 1) {
 | 
				
			||||||
 | 
									yyerror("An expression has wrong types");
 | 
				
			||||||
 | 
									exit(-1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			return eval(e->left) * eval(e->right);
 | 
								return eval(e->left) * eval(e->right);
 | 
				
			||||||
		case EQUALS:
 | 
							}
 | 
				
			||||||
 | 
							case EQUALS: {
 | 
				
			||||||
 | 
								if (e->left->class != 1 || e->right->class != 1) {
 | 
				
			||||||
 | 
									yyerror("An expression has wrong types");
 | 
				
			||||||
 | 
									exit(-1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			printf("%d, %d\n", eval(e->left), eval(e->right));
 | 
								printf("%d, %d\n", eval(e->left), eval(e->right));
 | 
				
			||||||
			return eval(e->left) == eval(e->right) ? 1 : 0;
 | 
								return eval(e->left) == eval(e->right) ? 1 : 0;
 | 
				
			||||||
		case LT:
 | 
							}
 | 
				
			||||||
 | 
							case LT: {
 | 
				
			||||||
 | 
								if (e->left->class != 1 || e->right->class != 1) {
 | 
				
			||||||
 | 
									yyerror("An expression has wrong types");
 | 
				
			||||||
 | 
									exit(-1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			return eval(e->left) < eval(e->right) ? 1 : 0;
 | 
								return eval(e->left) < eval(e->right) ? 1 : 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		case INT:
 | 
							case INT:
 | 
				
			||||||
		case 0:
 | 
							case 0:
 | 
				
			||||||
			return e->var->value;
 | 
								return e->var->value;
 | 
				
			||||||
@@ -258,9 +309,9 @@ void print_vars (varlist *l)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (!l) return;
 | 
						if (!l) return;
 | 
				
			||||||
	print_vars(l->next);
 | 
						print_vars(l->next);
 | 
				
			||||||
	if (l->var->type == 0)
 | 
						if (l->var->class == 0)
 | 
				
			||||||
		printf("%s = %c  ", l->var->name, l->var->value ? 'T' : 'F');
 | 
							printf("%s = %c  ", l->var->name, l->var->value ? 'T' : 'F');
 | 
				
			||||||
	else if (l->var->type == 1)
 | 
						else if (l->var->class == 1)
 | 
				
			||||||
		printf("%s = %d  ", l->var->name, l->var->value);
 | 
							printf("%s = %d  ", l->var->name, l->var->value);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		fprintf(stderr, "The type of the var %s is unknown", l->var->name);
 | 
							fprintf(stderr, "The type of the var %s is unknown", l->var->name);
 | 
				
			||||||
@@ -271,6 +322,10 @@ void execute (stmt *s)
 | 
				
			|||||||
	switch(s->type)
 | 
						switch(s->type)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		case ASSIGN:
 | 
							case ASSIGN:
 | 
				
			||||||
 | 
								if (s->var->class != s->expr->class) {
 | 
				
			||||||
 | 
									yyerror("An assignment has the wrong type");
 | 
				
			||||||
 | 
									exit(-1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			s->var->value = eval(s->expr);
 | 
								s->var->value = eval(s->expr);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case ';':
 | 
							case ';':
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
bool y;
 | 
					bool y;
 | 
				
			||||||
int x;
 | 
					int x;
 | 
				
			||||||
x := 42 + 21;
 | 
					x := 6 * (4 + 3);
 | 
				
			||||||
y := x == (7 * (5 + 4));
 | 
					y := (0 < 1) || 19 + 23 == x;
 | 
				
			||||||
print x,y,x
 | 
					print x,y,x
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user