diff --git a/README.md b/README.md index 7dd020531..b3c3a7f77 100644 --- a/README.md +++ b/README.md @@ -115,19 +115,19 @@ to C3 and compiled with the c3c compiler: - [x] CT only macros evaluating to constants - [x] range initializers e.g. `{ [1..2] = 2 }` - [x] Trailing body macros e.g. `@foo(1, 100; int a) { bar(a); };` +- [x] Complex macros - [ ] Anonymous structs - [ ] Complete C ABI conformance *in progress* - [ ] Debug info *in progress* - [ ] Virtual type *in progress* - [ ] Enum associated data support -- [ ] Windows support -- [ ] All attributes +- [ ] Windows support *in progress* +- [ ] All attributes *in progress* - [ ] Associative array literals - [ ] CT type constants - [ ] Reflection methods - [ ] LTO/ThinLTO setup - [ ] `global` / `shared` for globals -- [ ] Complex macros - [ ] Escape macros - [ ] Implicit capturing macros - [ ] Subarray initializers diff --git a/src/compiler/ast.c b/src/compiler/ast.c index 633fcddb8..4b74e1ad2 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -581,6 +581,9 @@ void fprint_expr_recursive(Context *context, FILE *file, Expr *expr, int indent) if (!expr) return; switch (expr->expr_kind) { + case EXPR_NOP: + DUMP("(nop)"); + return; case EXPR_FLATPATH: DUMP("(idents)"); return; diff --git a/src/compiler/copying.c b/src/compiler/copying.c index 348369f2c..d4662d5e9 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -75,6 +75,7 @@ Expr *copy_expr(Expr *source_expr) UNREACHABLE case EXPR_FLATPATH: case EXPR_UNDEF: + case EXPR_NOP: return expr; case EXPR_CT_CALL: MACRO_COPY_EXPR_LIST(expr->ct_call_expr.arguments); diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 2b6b5f249..367509b67 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -214,6 +214,7 @@ typedef enum EXPR_UNARY, EXPR_UNDEF, EXPR_CT_CALL, + EXPR_NOP, } ExprKind; typedef enum diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 15ddf666e..18ac569c7 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -3177,6 +3177,8 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) case EXPR_CATCH: gencontext_emit_trycatch_expr(c, value, expr); return; + case EXPR_NOP: + return; case EXPR_ELSE: gencontext_emit_else_expr(c, value, expr); return; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 950ddea11..8fb877910 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -3357,6 +3357,43 @@ static bool sema_expr_analyse_ct_identifier_assign(Context *context, Expr *expr, return true; } +static bool sema_expr_analyse_ct_type_identifier_assign(Context *context, Expr *expr, Expr *left, Expr *right) +{ + TypeInfo *info = left->type_expr; + + if (info->kind != TYPE_INFO_IDENTIFIER || info->unresolved.path || TOKTYPE(info->unresolved.name_loc) != TOKEN_CT_TYPE_IDENT) + { + SEMA_ERROR(left, "A type cannot be assigned to."); + return false; + } + + TokenId token = info->unresolved.name_loc; + + if (!sema_analyse_expr_value(context, NULL, right)) return false; + + if (right->expr_kind != EXPR_TYPEINFO) + { + SEMA_ERROR(right, "Expected a type here."); + return false; + } + + Decl *decl = sema_resolve_normal_symbol(context, token, NULL, false); + + if (!decl) + { + decl = decl_new(DECL_VAR, token, VISIBLE_LOCAL); + decl->var.kind = VARDECL_LOCAL_CT_TYPE; + if (!sema_add_local(context, decl)) return false; + } + decl = sema_resolve_normal_symbol(context, token, NULL, true); + + decl->var.init_expr = right; + + expr->expr_kind = EXPR_NOP; + expr->type = type_void; + + return true; +} /** * Analyse a = b @@ -3372,6 +3409,11 @@ static bool sema_expr_analyse_assign(Context *context, Expr *expr, Expr *left, E { return sema_expr_analyse_ct_identifier_assign(context, expr, left, right); } + + if (left->expr_kind == EXPR_TYPEINFO) + { + return sema_expr_analyse_ct_type_identifier_assign(context, expr, left, right); + } if (!sema_analyse_expr_value(context, NULL, left)) return false; // 2. Check assignability @@ -3442,6 +3484,7 @@ static bool sema_expr_analyse_common_assign(Context *context, Expr *expr, Expr * { return sema_expr_analyse_ct_common_assign(context, expr, left); } + // 1. Analyse left side. if (!sema_analyse_expr_value(context, NULL, left)) return false; @@ -5690,6 +5733,7 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Type *to, Expr * case EXPR_DESIGNATOR: case EXPR_MACRO_BODY_EXPANSION: case EXPR_FLATPATH: + case EXPR_NOP: UNREACHABLE case EXPR_CT_CALL: return sema_expr_analyse_ct_call(context, to, expr); diff --git a/test/test_suite/expressions/assignability.c3 b/test/test_suite/expressions/assignability.c3 index 98f4e0bf1..20c98dbc0 100644 --- a/test/test_suite/expressions/assignability.c3 +++ b/test/test_suite/expressions/assignability.c3 @@ -31,3 +31,8 @@ func void test21() int b = 2; a++ = b++; // #error: Expression is not assignable } + +func void test22() +{ + $Type = int; +} \ No newline at end of file