mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Add XOR for booleans
This commit is contained in:
+15
-18
@@ -30,7 +30,7 @@ gb_inline Type *check_type(Checker *c, AstNode *expression) {
|
|||||||
void error_operand_not_expression(Operand *o) {
|
void error_operand_not_expression(Operand *o) {
|
||||||
if (o->mode == Addressing_Type) {
|
if (o->mode == Addressing_Type) {
|
||||||
gbString err = expr_to_string(o->expr);
|
gbString err = expr_to_string(o->expr);
|
||||||
error_node(o->expr, "`%s` is not an expression", err);
|
error_node(o->expr, "`%s` is not an expression but a type", err);
|
||||||
gb_string_free(err);
|
gb_string_free(err);
|
||||||
o->mode = Addressing_Invalid;
|
o->mode = Addressing_Invalid;
|
||||||
}
|
}
|
||||||
@@ -1787,8 +1787,8 @@ bool check_unary_op(Checker *c, Operand *o, Token op) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Token_Xor:
|
case Token_Xor:
|
||||||
if (!is_type_integer(type)) {
|
if (!is_type_integer(type) && !is_type_boolean(type)) {
|
||||||
error(op, "Operator `%.*s` is only allowed with integers", LIT(op.string));
|
error(op, "Operator `%.*s` is only allowed with integers or booleans", LIT(op.string));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1845,6 +1845,8 @@ bool check_binary_op(Checker *c, Operand *o, Token op) {
|
|||||||
case Token_Or:
|
case Token_Or:
|
||||||
case Token_AndEq:
|
case Token_AndEq:
|
||||||
case Token_OrEq:
|
case Token_OrEq:
|
||||||
|
case Token_Xor:
|
||||||
|
case Token_XorEq:
|
||||||
if (!is_type_integer(type) && !is_type_boolean(type)) {
|
if (!is_type_integer(type) && !is_type_boolean(type)) {
|
||||||
error(op, "Operator `%.*s` is only allowed with integers or booleans", LIT(op.string));
|
error(op, "Operator `%.*s` is only allowed with integers or booleans", LIT(op.string));
|
||||||
return false;
|
return false;
|
||||||
@@ -1852,10 +1854,8 @@ bool check_binary_op(Checker *c, Operand *o, Token op) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Token_Mod:
|
case Token_Mod:
|
||||||
case Token_Xor:
|
|
||||||
case Token_AndNot:
|
case Token_AndNot:
|
||||||
case Token_ModEq:
|
case Token_ModEq:
|
||||||
case Token_XorEq:
|
|
||||||
case Token_AndNotEq:
|
case Token_AndNotEq:
|
||||||
if (!is_type_integer(type)) {
|
if (!is_type_integer(type)) {
|
||||||
error(op, "Operator `%.*s` is only allowed with integers", LIT(op.string));
|
error(op, "Operator `%.*s` is only allowed with integers", LIT(op.string));
|
||||||
@@ -4649,13 +4649,19 @@ typedef enum CallArgumentError {
|
|||||||
CallArgumentError_TooManyArguments,
|
CallArgumentError_TooManyArguments,
|
||||||
} CallArgumentError;
|
} CallArgumentError;
|
||||||
|
|
||||||
|
typedef enum CallArgumentErrorMode {
|
||||||
|
CallArgumentMode_NoErrors,
|
||||||
|
CallArgumentMode_ShowErrors,
|
||||||
|
} CallArgumentErrorMode;
|
||||||
|
|
||||||
CallArgumentError check_call_arguments_internal(Checker *c, AstNode *call, Type *proc_type, Operand *operands, isize operand_count,
|
CallArgumentError check_call_arguments_internal(Checker *c, AstNode *call, Type *proc_type, Operand *operands, isize operand_count,
|
||||||
bool show_error, i64 *score_) {
|
CallArgumentErrorMode show_error_mode, i64 *score_) {
|
||||||
ast_node(ce, CallExpr, call);
|
ast_node(ce, CallExpr, call);
|
||||||
isize param_count = 0;
|
isize param_count = 0;
|
||||||
bool variadic = proc_type->Proc.variadic;
|
bool variadic = proc_type->Proc.variadic;
|
||||||
bool vari_expand = (ce->ellipsis.pos.line != 0);
|
bool vari_expand = (ce->ellipsis.pos.line != 0);
|
||||||
i64 score = 0;
|
i64 score = 0;
|
||||||
|
bool show_error = show_error_mode == CallArgumentMode_ShowErrors;
|
||||||
|
|
||||||
if (proc_type->Proc.params != NULL) {
|
if (proc_type->Proc.params != NULL) {
|
||||||
param_count = proc_type->Proc.params->Tuple.variable_count;
|
param_count = proc_type->Proc.params->Tuple.variable_count;
|
||||||
@@ -4839,7 +4845,7 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod
|
|||||||
Type *proc_type = base_type(p->type);
|
Type *proc_type = base_type(p->type);
|
||||||
if (proc_type != NULL && is_type_proc(proc_type)) {
|
if (proc_type != NULL && is_type_proc(proc_type)) {
|
||||||
i64 score = 0;
|
i64 score = 0;
|
||||||
CallArgumentError err = check_call_arguments_internal(c, call, proc_type, operands.e, operands.count, false, &score);
|
CallArgumentError err = check_call_arguments_internal(c, call, proc_type, operands.e, operands.count, CallArgumentMode_NoErrors, &score);
|
||||||
if (err == CallArgumentError_None) {
|
if (err == CallArgumentError_None) {
|
||||||
valids[valid_count].index = i;
|
valids[valid_count].index = i;
|
||||||
valids[valid_count].score = score;
|
valids[valid_count].score = score;
|
||||||
@@ -4884,14 +4890,14 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod
|
|||||||
add_entity_use(c, expr, e);
|
add_entity_use(c, expr, e);
|
||||||
proc_type = e->type;
|
proc_type = e->type;
|
||||||
i64 score = 0;
|
i64 score = 0;
|
||||||
CallArgumentError err = check_call_arguments_internal(c, call, proc_type, operands.e, operands.count, true, &score);
|
CallArgumentError err = check_call_arguments_internal(c, call, proc_type, operands.e, operands.count, CallArgumentMode_ShowErrors, &score);
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_free(heap_allocator(), valids);
|
gb_free(heap_allocator(), valids);
|
||||||
gb_free(heap_allocator(), procs);
|
gb_free(heap_allocator(), procs);
|
||||||
} else {
|
} else {
|
||||||
i64 score = 0;
|
i64 score = 0;
|
||||||
CallArgumentError err = check_call_arguments_internal(c, call, proc_type, operands.e, operands.count, true, &score);
|
CallArgumentError err = check_call_arguments_internal(c, call, proc_type, operands.e, operands.count, CallArgumentMode_ShowErrors, &score);
|
||||||
array_free(&operands);
|
array_free(&operands);
|
||||||
}
|
}
|
||||||
return proc_type;
|
return proc_type;
|
||||||
@@ -4936,14 +4942,6 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (operand->mode == Addressing_Type) {
|
if (operand->mode == Addressing_Type) {
|
||||||
#if 0
|
|
||||||
gbString str = type_to_string(operand->type);
|
|
||||||
error_node(call, "Expected a procedure, got a type `%s`", str);
|
|
||||||
gb_string_free(str);
|
|
||||||
operand->mode = Addressing_Invalid;
|
|
||||||
operand->expr = call;
|
|
||||||
return Expr_Stmt;
|
|
||||||
#else
|
|
||||||
Type *t = operand->type;
|
Type *t = operand->type;
|
||||||
gbString str = type_to_string(t);
|
gbString str = type_to_string(t);
|
||||||
operand->mode = Addressing_Invalid;
|
operand->mode = Addressing_Invalid;
|
||||||
@@ -4961,7 +4959,6 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
|
|||||||
|
|
||||||
gb_string_free(str);
|
gb_string_free(str);
|
||||||
return Expr_Expr;
|
return Expr_Expr;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operand->mode == Addressing_Builtin) {
|
if (operand->mode == Addressing_Builtin) {
|
||||||
|
|||||||
+56
-4
@@ -32,8 +32,7 @@ typedef struct AstFile {
|
|||||||
// < 0: In Control Clause
|
// < 0: In Control Clause
|
||||||
// NOTE(bill): Used to prevent type literals in control clauses
|
// NOTE(bill): Used to prevent type literals in control clauses
|
||||||
isize expr_level;
|
isize expr_level;
|
||||||
bool allow_range;
|
bool allow_range; // NOTE(bill): Ranges are only allowed in certain cases
|
||||||
bool ignore_operand;
|
|
||||||
|
|
||||||
AstNodeArray decls;
|
AstNodeArray decls;
|
||||||
bool is_global_scope;
|
bool is_global_scope;
|
||||||
@@ -3774,7 +3773,48 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, AstNodeArray
|
|||||||
syntax_error_node(node, "Only declarations are allowed at file scope %.*s", LIT(ast_node_strings[node->kind]));
|
syntax_error_node(node, "Only declarations are allowed at file scope %.*s", LIT(ast_node_strings[node->kind]));
|
||||||
} else if (node->kind == AstNode_ImportDecl) {
|
} else if (node->kind == AstNode_ImportDecl) {
|
||||||
ast_node(id, ImportDecl, node);
|
ast_node(id, ImportDecl, node);
|
||||||
|
String collection_name = {0};
|
||||||
|
String oirignal_string = id->relpath.string;
|
||||||
String file_str = id->relpath.string;
|
String file_str = id->relpath.string;
|
||||||
|
gbAllocator allocator = heap_allocator(); // TODO(bill): Change this allocator
|
||||||
|
String import_file = {0};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
isize colon_pos = -1;
|
||||||
|
for (isize j = 0; j < file_str.len; j++) {
|
||||||
|
if (file_str.text[j] == ':') {
|
||||||
|
colon_pos = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (colon_pos > 0) {
|
||||||
|
collection_name = make_string(file_str.text, colon_pos);
|
||||||
|
file_str.text += colon_pos+1;
|
||||||
|
file_str.len -= colon_pos+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (collection_name.len == 0) {
|
||||||
|
syntax_error_node(node, "Missing import collection for path: `%.*s`", LIT(oirignal_string));
|
||||||
|
decls.e[i] = ast_bad_decl(f, id->relpath, id->relpath);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (str_eq(collection_name, str_lit("core"))) {
|
||||||
|
String abs_path = get_fullpath_core(allocator, file_str);
|
||||||
|
if (gb_file_exists(cast(char *)abs_path.text)) { // NOTE(bill): This should be null terminated
|
||||||
|
import_file = abs_path;
|
||||||
|
}
|
||||||
|
} else if (str_eq(collection_name, str_lit("local"))) {
|
||||||
|
String rel_path = get_fullpath_relative(allocator, base_dir, file_str);
|
||||||
|
if (gb_file_exists(cast(char *)rel_path.text)) { // NOTE(bill): This should be null terminated
|
||||||
|
import_file = rel_path;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
syntax_error_node(node, "Unknown import collection: `%.*s`", LIT(collection_name));
|
||||||
|
decls.e[i] = ast_bad_decl(f, id->relpath, id->relpath);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_import_path_valid(file_str)) {
|
if (!is_import_path_valid(file_str)) {
|
||||||
if (id->is_import) {
|
if (id->is_import) {
|
||||||
@@ -3787,16 +3827,28 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, AstNodeArray
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
gbAllocator allocator = heap_allocator(); // TODO(bill): Change this allocator
|
#else
|
||||||
|
if (!is_import_path_valid(file_str)) {
|
||||||
|
if (id->is_import) {
|
||||||
|
syntax_error_node(node, "Invalid import path: `%.*s`", LIT(file_str));
|
||||||
|
} else {
|
||||||
|
syntax_error_node(node, "Invalid include path: `%.*s`", LIT(file_str));
|
||||||
|
}
|
||||||
|
// NOTE(bill): It's a naughty name
|
||||||
|
decls.e[i] = ast_bad_decl(f, id->relpath, id->relpath);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
String rel_path = get_fullpath_relative(allocator, base_dir, file_str);
|
String rel_path = get_fullpath_relative(allocator, base_dir, file_str);
|
||||||
String import_file = rel_path;
|
import_file = rel_path;
|
||||||
if (!gb_file_exists(cast(char *)rel_path.text)) { // NOTE(bill): This should be null terminated
|
if (!gb_file_exists(cast(char *)rel_path.text)) { // NOTE(bill): This should be null terminated
|
||||||
String abs_path = get_fullpath_core(allocator, file_str);
|
String abs_path = get_fullpath_core(allocator, file_str);
|
||||||
if (gb_file_exists(cast(char *)abs_path.text)) {
|
if (gb_file_exists(cast(char *)abs_path.text)) {
|
||||||
import_file = abs_path;
|
import_file = abs_path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
id->fullpath = import_file;
|
id->fullpath = import_file;
|
||||||
try_add_import_path(p, import_file, file_str, ast_node_token(node).pos);
|
try_add_import_path(p, import_file, file_str, ast_node_token(node).pos);
|
||||||
|
|||||||
Reference in New Issue
Block a user