Browse Source

Add XOR for booleans

Ginger Bill 8 years ago
parent
commit
7692061eef
2 changed files with 71 additions and 22 deletions
  1. 15 18
      src/check_expr.c
  2. 56 4
      src/parser.c

+ 15 - 18
src/check_expr.c

@@ -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)) {
-			error(op, "Operator `%.*s` is only allowed with integers", LIT(op.string));
+		if (!is_type_integer(type) && !is_type_boolean(type)) {
+			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
src/parser.c

@@ -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           ignore_operand;
+	bool           allow_range; // NOTE(bill): Ranges are only allowed in certain cases
 
 
 	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);