Browse Source

Merge branch 'master' of github.com:odin-lang/Odin

Kevin Watters 6 years ago
parent
commit
381fbd3daf

+ 1 - 1
build.bat

@@ -42,7 +42,7 @@ del *.ilk > NUL 2> NUL
 
 cl %compiler_settings% "src\main.cpp" ^
 	/link %linker_settings% -OUT:%exe_name% ^
-	&& odin run examples/demo/demo.odin -keep-temp-files
+	&& odin run examples/demo/demo.odin
 
 del *.obj > NUL 2> NUL
 

+ 1 - 1
core/dynlib/lib_windows.odin

@@ -17,7 +17,7 @@ unload_library :: proc(library: Library) -> bool {
 }
 
 symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) {
-	c_str := strings.new_cstring(symbol, context.temp_allocator);
+	c_str := strings.clone_to_cstring(symbol, context.temp_allocator);
 	ptr = win32.get_proc_address(cast(win32.Hmodule)library, c_str);
 	found == ptr != nil;
 	return;

+ 6 - 6
core/fmt/fmt.odin

@@ -59,12 +59,12 @@ fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
 
 
 // print* procedures return the number of bytes written
-print       :: proc(args: ..any)              -> int { return fprint(os.stdout, ..args); }
-print_err   :: proc(args: ..any)              -> int { return fprint(os.stderr, ..args); }
-println     :: proc(args: ..any)              -> int { return fprintln(os.stdout, ..args); }
-println_err :: proc(args: ..any)              -> int { return fprintln(os.stderr, ..args); }
-printf      :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args); }
-printf_err  :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args); }
+print       :: proc(args: ..any)              -> int { return fprint(context.stdout, ..args); }
+print_err   :: proc(args: ..any)              -> int { return fprint(context.stderr, ..args); }
+println     :: proc(args: ..any)              -> int { return fprintln(context.stdout, ..args); }
+println_err :: proc(args: ..any)              -> int { return fprintln(context.stderr, ..args); }
+printf      :: proc(fmt: string, args: ..any) -> int { return fprintf(context.stdout, fmt, ..args); }
+printf_err  :: proc(fmt: string, args: ..any) -> int { return fprintf(context.stderr, fmt, ..args); }
 
 
 // aprint* procedures return a string that was allocated with the current context

+ 1 - 1
core/log/file_console_logger.odin

@@ -69,7 +69,7 @@ file_console_logger_proc :: proc(logger_data: rawptr, level: Level, text: string
 
     h : os.Handle;
     if(data.file_handle != os.INVALID_HANDLE) do h = data.file_handle;
-    else                                      do h = level <= Level.Error ? os.stdout : os.stderr;
+    else                                      do h = level <= Level.Error ? context.stdout : context.stderr;
     backing: [1024]byte; //NOTE(Hoej): 1024 might be too much for a header backing, unless somebody has really long paths.
     buf := strings.builder_from_slice(backing[:]);
 

+ 3 - 1
core/odin/parser/parser.odin

@@ -1528,6 +1528,8 @@ parse_field_list :: proc(p: ^Parser, follow: token.Kind, allowed_flags: ast.Fiel
 			return ok;
 		}
 
+		is_signature := (allowed_flags & Field_Flags_Signature_Params) == Field_Flags_Signature_Params;
+
 		any_polymorphic_names := check_procedure_name_list(p, names);
 		set_flags = check_field_flag_prefixes(p, len(names), allowed_flags, set_flags);
 
@@ -1538,7 +1540,7 @@ parse_field_list :: proc(p: ^Parser, follow: token.Kind, allowed_flags: ast.Fiel
 		if p.curr_tok.kind != token.Eq {
 			type = parse_var_type(p, allowed_flags);
 			tt := ast.unparen_expr(type);
-			if !any_polymorphic_names {
+			if is_signature && !any_polymorphic_names {
 				if ti, ok := tt.derived.(ast.Typeid_Type); ok && ti.specialization != nil {
 					error(p, tt.pos, "specialization of typeid is not allowed without polymorphic names");
 				}

+ 6 - 6
core/os/os_osx.odin

@@ -153,7 +153,7 @@ foreign dl {
 }
 
 open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {
-	cstr := strings.new_cstring(path);
+	cstr := strings.clone_to_cstring(path);
 	handle := _unix_open(cstr, flags, mode);
 	delete(cstr);
 	if handle == -1 {
@@ -221,14 +221,14 @@ is_path_separator :: proc(r: rune) -> bool {
 
 stat :: inline proc(path: string) -> (Stat, bool) {
 	s: Stat;
-	cstr := strings.new_cstring(path);
+	cstr := strings.clone_to_cstring(path);
 	defer delete(cstr);
 	ret_int := _unix_stat(cstr, &s);
 	return s, ret_int==0;
 }
 
 access :: inline proc(path: string, mask: int) -> bool {
-	cstr := strings.new_cstring(path);
+	cstr := strings.clone_to_cstring(path);
 	defer delete(cstr);
 	return _unix_access(cstr, mask) == 0;
 }
@@ -245,7 +245,7 @@ heap_free :: inline proc(ptr: rawptr) {
 }
 
 getenv :: proc(name: string) -> (string, bool) {
-	path_str := strings.new_cstring(name);
+	path_str := strings.clone_to_cstring(name);
 	defer delete(path_str);
 	cstr := _unix_getenv(path_str);
 	if cstr == nil {
@@ -265,14 +265,14 @@ current_thread_id :: proc "contextless" () -> int {
 }
 
 dlopen :: inline proc(filename: string, flags: int) -> rawptr {
-	cstr := strings.new_cstring(filename);
+	cstr := strings.clone_to_cstring(filename);
 	defer delete(cstr);
 	handle := _unix_dlopen(cstr, flags);
 	return handle;
 }
 dlsym :: inline proc(handle: rawptr, symbol: string) -> rawptr {
 	assert(handle != nil);
-	cstr := strings.new_cstring(symbol);
+	cstr := strings.clone_to_cstring(symbol);
 	defer delete(cstr);
 	proc_handle := _unix_dlsym(handle, cstr);
 	return proc_handle;

+ 14 - 5
core/runtime/core.odin

@@ -213,9 +213,14 @@ Context :: struct {
 	assertion_failure_proc: Assertion_Failure_Proc,
 	logger: log.Logger,
 
+	stdin:  os.Handle,
+	stdout: os.Handle,
+	stderr: os.Handle,
+
 	thread_id:  int,
 
 	user_data:  any,
+	user_ptr:   rawptr,
 	user_index: int,
 
 	derived:    any, // May be used for derived data types
@@ -350,6 +355,10 @@ __init_context :: proc "contextless" (c: ^Context) {
 
 	c.logger.procedure = log.nil_logger_proc;
 	c.logger.data = nil;
+
+	c.stdin  = os.stdin;
+	c.stdout = os.stdout;
+	c.stderr = os.stderr;
 }
 
 @builtin
@@ -358,7 +367,7 @@ init_global_temporary_allocator :: proc(data: []byte, backup_allocator := contex
 }
 
 default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) {
-	fd := os.stderr;
+	fd := context.stderr;
 	print_caller_location(fd, loc);
 	os.write_string(fd, " ");
 	os.write_string(fd, prefix);
@@ -653,7 +662,7 @@ card :: proc(s: $S/bit_set[$E; $U]) -> int {
 
 
 @builtin
-assert :: proc "contextless" (condition: bool, message := "", loc := #caller_location) -> bool {
+assert :: proc(condition: bool, message := "", loc := #caller_location) -> bool {
 	if !condition {
 		p := context.assertion_failure_proc;
 		if p == nil {
@@ -665,7 +674,7 @@ assert :: proc "contextless" (condition: bool, message := "", loc := #caller_loc
 }
 
 @builtin
-panic :: proc "contextless" (message: string, loc := #caller_location) -> ! {
+panic :: proc(message: string, loc := #caller_location) -> ! {
 	p := context.assertion_failure_proc;
 	if p == nil {
 		p = default_assertion_failure_proc;
@@ -674,7 +683,7 @@ panic :: proc "contextless" (message: string, loc := #caller_location) -> ! {
 }
 
 @builtin
-unimplemented :: proc "contextless" (message := "", loc := #caller_location) -> ! {
+unimplemented :: proc(message := "", loc := #caller_location) -> ! {
 	p := context.assertion_failure_proc;
 	if p == nil {
 		p = default_assertion_failure_proc;
@@ -683,7 +692,7 @@ unimplemented :: proc "contextless" (message := "", loc := #caller_location) ->
 }
 
 @builtin
-unreachable :: proc "contextless" (message := "", loc := #caller_location) -> ! {
+unreachable :: proc(message := "", loc := #caller_location) -> ! {
 	p := context.assertion_failure_proc;
 	if p == nil {
 		p = default_assertion_failure_proc;

+ 31 - 27
core/runtime/internal.odin

@@ -223,6 +223,21 @@ print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
 			print_type(fd, info.underlying);
 		}
 		os.write_byte(fd, ']');
+
+	case Type_Info_Opaque:
+		os.write_string(fd, "opaque ");
+		print_type(fd, info.elem);
+
+	case Type_Info_Simd_Vector:
+		if info.is_x86_mmx {
+			os.write_string(fd, "intrinsics.x86_mmx");
+		} else {
+			os.write_string(fd, "intrinsics.vector(");
+			print_u64(fd, u64(info.count));
+			os.write_string(fd, ", ");
+			print_type(fd, info.elem);
+			os.write_byte(fd, ')');
+		}
 	}
 }
 
@@ -285,38 +300,27 @@ bounds_check_error :: proc "contextless" (file: string, line, column: int, index
 	handle_error(file, line, column, index, count);
 }
 
+slice_handle_error :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) {
+	fd := os.stderr;
+	print_caller_location(fd, Source_Code_Location{file, line, column, "", 0});
+	os.write_string(fd, " Invalid slice indices: ");
+	print_i64(fd, i64(lo));
+	os.write_string(fd, ":");
+	print_i64(fd, i64(hi));
+	os.write_string(fd, ":");
+	print_i64(fd, i64(len));
+	os.write_byte(fd, '\n');
+	debug_trap();
+}
+
 slice_expr_error_hi :: proc "contextless" (file: string, line, column: int, hi: int, len: int) {
 	if 0 <= hi && hi <= len do return;
-	handle_error :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) {
-		fd := os.stderr;
-		print_caller_location(fd, Source_Code_Location{file, line, column, "", 0});
-		os.write_string(fd, " Invalid slice indices: ");
-		print_i64(fd, i64(lo));
-		os.write_string(fd, ":");
-		print_i64(fd, i64(hi));
-		os.write_string(fd, ":");
-		print_i64(fd, i64(len));
-		os.write_byte(fd, '\n');
-		debug_trap();
-	}
-	handle_error(file, line, column, 0, hi, len);
+	slice_handle_error(file, line, column, 0, hi, len);
 }
 
 slice_expr_error_lo_hi :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) {
-	if 0 <= lo && lo < len && lo <= hi && hi <= len do return;
-	handle_error :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) {
-		fd := os.stderr;
-		print_caller_location(fd, Source_Code_Location{file, line, column, "", 0});
-		os.write_string(fd, " Invalid slice indices: ");
-		print_i64(fd, i64(lo));
-		os.write_string(fd, ":");
-		print_i64(fd, i64(hi));
-		os.write_string(fd, ":");
-		print_i64(fd, i64(len));
-		os.write_byte(fd, '\n');
-		debug_trap();
-	}
-	handle_error(file, line, column, lo, hi, len);
+	if 0 <= lo && lo <= len && lo <= hi && hi <= len do return;
+	slice_handle_error(file, line, column, lo, hi, len);
 }
 
 dynamic_array_expr_error :: proc "contextless" (file: string, line, column: int, low, high, max: int) {

+ 2 - 2
core/strconv/strconv.odin

@@ -236,8 +236,8 @@ quote :: proc(buf: []byte, s: string) -> string {
 			write_byte(buf, &i, digits[s[0]&0xf]);
 		}
 		if i < len(buf) {
-			s2 := quote_rune(buf[i:], r);
-			i += len(s2);
+			x := quote_rune(buf[i:], r);
+			i += len(x);
 		}
 	}
 	write_byte(buf, &i, c);

+ 30 - 2
src/check_expr.cpp

@@ -5,6 +5,7 @@ enum CallArgumentError {
 	CallArgumentError_NonVariadicExpand,
 	CallArgumentError_VariadicTuple,
 	CallArgumentError_MultipleVariadicExpand,
+	CallArgumentError_AmbiguousPolymorphicVariadic,
 	CallArgumentError_ArgumentCount,
 	CallArgumentError_TooFewArguments,
 	CallArgumentError_TooManyArguments,
@@ -4492,6 +4493,15 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
 		err = CallArgumentError_NonVariadicExpand;
 	} else if (operands.count == 0 && param_count_excluding_defaults == 0) {
 		err = CallArgumentError_None;
+
+		if (variadic) {
+			GB_ASSERT(param_tuple != nullptr && param_tuple->variables.count > 0);
+			Type *t = param_tuple->variables[0]->type;
+			if (is_type_polymorphic(t)) {
+				error(call, "Ambiguous call to a polymorphic variadic procedure with no variadic input");
+				err = CallArgumentError_AmbiguousPolymorphicVariadic;
+			}
+		}
 	} else {
 		i32 error_code = 0;
 		if (operands.count < param_count_excluding_defaults) {
@@ -4583,6 +4593,12 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
 				GB_ASSERT(is_type_slice(slice));
 				Type *elem = base_type(slice)->Slice.elem;
 				Type *t = elem;
+
+				if (is_type_polymorphic(t)) {
+					error(call, "Ambiguous call to a polymorphic variadic procedure with no variadic input");
+					err = CallArgumentError_AmbiguousPolymorphicVariadic;
+				}
+
 				for (; operand_index < operands.count; operand_index++) {
 					Operand o = operands[operand_index];
 					if (vari_expand) {
@@ -4761,11 +4777,24 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
 
 
 	for (isize i = 0; i < param_count; i++) {
+		Entity *e = pt->params->Tuple.variables[i];
 		Operand *o = &ordered_operands[i];
+		bool param_is_variadic = pt->variadic && pt->variadic_index == i;
+
+
 		if (o->mode == Addressing_Invalid) {
+			if (param_is_variadic) {
+				Type *slice = e->type;
+				GB_ASSERT(is_type_slice(slice));
+				Type *elem = base_type(slice)->Slice.elem;
+				if (is_type_polymorphic(elem)) {
+					error(call, "Ambiguous call to a polymorphic variadic procedure with no variadic input");
+					err = CallArgumentError_AmbiguousPolymorphicVariadic;
+					return err;
+				}
+			}
 			continue;
 		}
-		Entity *e = pt->params->Tuple.variables[i];
 
 		if (e->kind == Entity_TypeName) {
 			GB_ASSERT(pt->is_polymorphic);
@@ -4782,7 +4811,6 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
 			}
 		} else {
 			i64 s = 0;
-			bool param_is_variadic = pt->variadic && pt->variadic_index == i;
 			if (!check_is_assignable_to_with_score(c, o, e->type, &s, param_is_variadic)) {
 				bool ok = false;
 				if (e->flags & EntityFlag_AutoCast) {

+ 6 - 0
src/check_type.cpp

@@ -1570,6 +1570,12 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
 				if (operands != nullptr && variables.count < operands->count) {
 
 					Operand op = (*operands)[variables.count];
+					if (op.expr == nullptr) {
+						// NOTE(bill): 2019-03-30
+						// This is just to add the error message to determine_type_from_polymorphic which
+						// depends on valid position information
+						op.expr = _params;
+					}
 					if (is_type_polymorphic_type) {
 						type = determine_type_from_polymorphic(ctx, type, op);
 						if (type == t_invalid) {

+ 5 - 3
src/ir.cpp

@@ -1433,11 +1433,13 @@ irValue *ir_value_procedure(irModule *m, Entity *entity, Type *type, Ast *type_e
 irValue *ir_generate_array(irModule *m, Type *elem_type, i64 count, String prefix, i64 id) {
 	gbAllocator a = ir_allocator();
 	Token token = {Token_Ident};
-	isize name_len = prefix.len + 10;
+	isize name_len = prefix.len + 1 + 20;
 
-	char *text = gb_alloc_array(a, char, name_len);
+	auto suffix_id = cast(unsigned long long)id;
+	char *text = gb_alloc_array(a, char, name_len+1);
 	gb_snprintf(text, name_len,
-	            "%.*s-%llx", LIT(prefix), cast(unsigned long long)id);
+	            "%.*s-%llu", LIT(prefix), suffix_id);
+	text[name_len] = 0;
 
 	String s = make_string_c(text);
 

+ 3 - 2
src/parser.cpp

@@ -3024,6 +3024,7 @@ Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKi
 	isize total_name_count = 0;
 	bool allow_ellipsis = allowed_flags&FieldFlag_ellipsis;
 	bool seen_ellipsis = false;
+	bool is_signature = (allowed_flags & FieldFlag_Signature) == FieldFlag_Signature;
 
 	while (f->curr_token.kind != follow &&
 	       f->curr_token.kind != Token_Colon &&
@@ -3064,7 +3065,7 @@ Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKi
 		if (f->curr_token.kind != Token_Eq) {
 			type = parse_var_type(f, allow_ellipsis, allow_typeid_token);
 			Ast *tt = unparen_expr(type);
-			if (!any_polymorphic_names && tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) {
+			if (is_signature && !any_polymorphic_names && tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) {
 				syntax_error(type, "Specialization of typeid is not allowed without polymorphic names");
 			}
 		}
@@ -3121,7 +3122,7 @@ Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKi
 			if (f->curr_token.kind != Token_Eq) {
 				type = parse_var_type(f, allow_ellipsis, allow_typeid_token);
 				Ast *tt = unparen_expr(type);
-				if (!any_polymorphic_names && tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) {
+				if (is_signature && !any_polymorphic_names && tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) {
 					syntax_error(type, "Specialization of typeid is not allowed without polymorphic names");
 				}
 			}