mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Allow type inference on enum comparisons. Add chdir. Fix bug when command was missing. Allow {} on basic types.
This commit is contained in:
42
lib/std/io/os/chdir.c3
Normal file
42
lib/std/io/os/chdir.c3
Normal file
@@ -0,0 +1,42 @@
|
||||
module std::io::os;
|
||||
import libc;
|
||||
|
||||
|
||||
$if (!env::COMPILER_LIBC_AVAILABLE):
|
||||
|
||||
fn void! native_chdir(Path path)
|
||||
{
|
||||
unreachable("'getcwd' not available");
|
||||
}
|
||||
|
||||
$elif (env::OS_TYPE == OsType.WIN32):
|
||||
|
||||
macro void! native_chdir(Path path)
|
||||
{
|
||||
@pool()
|
||||
{
|
||||
if (files::win32_SetCurrentDirectoryW(path.as_str().to_temp_utf16()!!)) return;
|
||||
};
|
||||
return IoError.GENERAL_ERROR!;
|
||||
}
|
||||
|
||||
$else:
|
||||
|
||||
extern fn int _chdir(ZString) @extern("chdir");
|
||||
macro void! native_chdir(Path p)
|
||||
{
|
||||
if (_chdir((ZString)p.as_str()))
|
||||
{
|
||||
switch (libc::errno())
|
||||
{
|
||||
case errno::EACCES: return IoError.NO_PERMISSION!;
|
||||
case errno::ENAMETOOLONG: return IoError.NAME_TOO_LONG!;
|
||||
case errno::ENOTDIR: return IoError.FILE_NOT_DIR!;
|
||||
case errno::ENOENT: return IoError.FILE_NOT_FOUND!;
|
||||
case errno::ELOOP: return IoError.SYMLINK_FAILED!;
|
||||
default: return IoError.GENERAL_ERROR!;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$endif;
|
||||
@@ -40,6 +40,7 @@ fn bool is_file(Path path) => os::native_is_file(path.as_str());
|
||||
fn usz! file_size(Path path) => os::native_file_size(path.as_str());
|
||||
fn bool exists(Path path) => os::native_file_or_dir_exists(path.as_str());
|
||||
fn Path! tgetcwd() => getcwd(mem::temp()) @inline;
|
||||
fn void! chdir(Path path) => os::native_chdir(path) @inline;
|
||||
fn Path! temp_directory(Allocator* using = mem::heap()) => os::native_temp_directory(using);
|
||||
|
||||
macro bool is_separator(char c, PathEnv path_env = DEFAULT_PATH_ENV)
|
||||
|
||||
@@ -27,6 +27,7 @@ struct Win32_FILE_ATTRIBUTE_DATA
|
||||
extern fn bool win32_GetFileAttributesExW(Win32_LPCWSTR, Win32_GET_FILEEX_INFO_LEVELS, Win32_LPVOID) @extern("GetFileAttributesExW");
|
||||
extern fn bool win32_PathFileExistsW(Win32_LPCWSTR) @extern("PathFileExistsW");
|
||||
extern fn Win32_DWORD win32_GetTempPathW(Win32_DWORD nBufferLength, Win32_LPWSTR lpBuffer) @extern("GetTempPathW");
|
||||
extern fn bool win32_SetCurrentDirectoryW(Win32_LPCTSTR buffer) @extern("SetCurrentDirectoryW");
|
||||
|
||||
/*
|
||||
extern ulong _win32_GetCurrentDirectoryW(ulong, Char16* buffer) @extern("GetCurrentDirectoryW");
|
||||
|
||||
@@ -898,6 +898,10 @@ BuildOptions parse_arguments(int argc, const char *argv[])
|
||||
}
|
||||
FAIL_WITH_ERR("Found the unexpected argument \"%s\".", current_arg);
|
||||
}
|
||||
if (build_options.command == COMMAND_MISSING)
|
||||
{
|
||||
FAIL_WITH_ERR("Missing a compiler command such as 'compile' or 'build'.");
|
||||
}
|
||||
return build_options;
|
||||
}
|
||||
|
||||
|
||||
@@ -931,6 +931,24 @@ static inline bool sema_binary_promote_top_down(SemaContext *context, Expr *bina
|
||||
|
||||
static inline bool sema_binary_analyse_subexpr(SemaContext *context, Expr *binary, Expr *left, Expr *right)
|
||||
{
|
||||
// Special handling of f = FOO_BAR
|
||||
if (right->expr_kind == EXPR_IDENTIFIER && right->identifier_expr.is_const)
|
||||
{
|
||||
if (!sema_analyse_expr(context, left)) return false;
|
||||
if (type_flatten(left->type)->type_kind == TYPE_ENUM)
|
||||
{
|
||||
return sema_analyse_inferred_expr(context, left->type, right);
|
||||
}
|
||||
}
|
||||
// Special handling of f = FOO_BAR
|
||||
if (left->expr_kind == EXPR_IDENTIFIER && left->identifier_expr.is_const)
|
||||
{
|
||||
if (!sema_analyse_expr(context, right)) return false;
|
||||
if (type_flatten(right->type)->type_kind == TYPE_ENUM)
|
||||
{
|
||||
return sema_analyse_inferred_expr(context, right->type, left);
|
||||
}
|
||||
}
|
||||
if (right->expr_kind == EXPR_INITIALIZER_LIST)
|
||||
{
|
||||
if (!sema_analyse_expr(context, left)) return false;
|
||||
@@ -2103,11 +2121,11 @@ static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr)
|
||||
case EXPR_TYPEINFO:
|
||||
if (func_expr->type_expr->resolve_status == RESOLVE_DONE)
|
||||
{
|
||||
SEMA_ERROR(expr, "A type cannot be followed by (), if you intended a cast, use (type)(expression).");
|
||||
SEMA_ERROR(expr, "A type cannot be followed by (), if you intended a cast, use '(type) expression'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
SEMA_ERROR(expr, "A type cannot be followed by (), did you mean to use {}?");
|
||||
SEMA_ERROR(expr, "A type cannot be followed by (), did you mean to use 'type {}'?");
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
|
||||
@@ -528,6 +528,7 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
|
||||
if (!to) to = type_untypedlist;
|
||||
assert(to);
|
||||
Type *flattened = type_flatten(to);
|
||||
bool is_zero_init = expr->expr_kind == EXPR_INITIALIZER_LIST && !vec_size(expr->initializer_list);
|
||||
switch (flattened->type_kind)
|
||||
{
|
||||
case TYPE_UNTYPED_LIST:
|
||||
@@ -541,7 +542,7 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
|
||||
return sema_expr_analyse_initializer(context, to, flattened, expr);
|
||||
case TYPE_SUBARRAY:
|
||||
{
|
||||
if (expr->expr_kind == EXPR_INITIALIZER_LIST && !vec_size(expr->initializer_list))
|
||||
if (is_zero_init)
|
||||
{
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.const_kind = CONST_POINTER;
|
||||
@@ -561,12 +562,31 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
|
||||
SEMA_ERROR(expr, "Scaled vectors cannot be initialized using an initializer list, since the length is not known at compile time.");
|
||||
return false;
|
||||
case TYPE_POINTER:
|
||||
if (is_zero_init)
|
||||
{
|
||||
expr_rewrite_to_const_zero(expr, to);
|
||||
return true;
|
||||
}
|
||||
SEMA_ERROR(expr, "Pointers cannot be initialized using an initializer list, instead you need to take the address of an array.");
|
||||
return false;
|
||||
case TYPE_VOID:
|
||||
case TYPE_POISONED:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_TYPEDEF:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case TYPE_OPTIONAL:
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_MEMBER:
|
||||
break;
|
||||
default:
|
||||
if (is_zero_init)
|
||||
{
|
||||
expr_rewrite_to_const_zero(expr, flattened);
|
||||
expr->type = to;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Fix error on compound literals
|
||||
SEMA_ERROR(expr, "'%s' cannot use compound literal initialization, did you intend to use a cast?", type_to_error_string(to));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@ static inline bool sema_analyse_block_exit_stmt(SemaContext *context, Ast *state
|
||||
}
|
||||
else
|
||||
{
|
||||
if (block_type && block_type != type_void)
|
||||
if (block_type && type_no_optional(block_type) != type_void)
|
||||
{
|
||||
SEMA_ERROR(statement, "Expected a return value of type %s here.", type_quoted_error_string(block_type));
|
||||
return false;
|
||||
@@ -966,9 +966,24 @@ static inline bool sema_analyse_cond(SemaContext *context, Expr *expr, CondType
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3a. Check for optional in case of an expression.
|
||||
if (IS_OPTIONAL(last))
|
||||
{
|
||||
if (type_no_optional(last->type) == type_void && cast_to_bool)
|
||||
{
|
||||
Expr *catch = expr_new_expr(EXPR_CATCH, last);
|
||||
catch->expr_kind = EXPR_CATCH;
|
||||
catch->inner_expr = expr_copy(last);
|
||||
catch->type = type_anyerr;
|
||||
catch->resolve_status = RESOLVE_DONE;
|
||||
catch->inner_expr->resolve_status = RESOLVE_DONE;
|
||||
last->expr_kind = EXPR_UNARY;
|
||||
last->unary_expr.operator = UNARYOP_NOT;
|
||||
last->unary_expr.expr = catch;
|
||||
last->type = type_bool;
|
||||
return true;
|
||||
}
|
||||
SEMA_ERROR(last, "The expression may not be an optional, but was %s.", type_quoted_error_string(last->type));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.107"
|
||||
#define COMPILER_VERSION "0.4.108"
|
||||
@@ -7,7 +7,7 @@ fn void test2()
|
||||
|
||||
fn void test3()
|
||||
{
|
||||
int x = int(32); // #error: A type cannot be followed by (), if you intended a cast, use (type)(expression)
|
||||
int x = int(32); // #error: A type cannot be followed by (), if you intended a cast, use '(type) expression'
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,5 +4,5 @@ struct Foo { int a; }
|
||||
fn void test1()
|
||||
{
|
||||
(Foo)({ 32 });
|
||||
Foo({ 32 }); // #error: A type cannot be followed by (), if you intended a cast, use (type)(expression)
|
||||
Foo({ 32 }); // #error: A type cannot be followed by (), if you intended a cast, use '(type) expression'
|
||||
}
|
||||
Reference in New Issue
Block a user