Skip to content

Commit 369b80a

Browse files
committed
Added condition-less blocks
1 parent af5a5f6 commit 369b80a

File tree

12 files changed

+95
-4
lines changed

12 files changed

+95
-4
lines changed

include/AST/EXPR/ast_expr_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ enum {
130130
EXPR_VA_COPY,
131131
EXPR_FOR,
132132
EXPR_DECLARE_CONSTANT,
133+
EXPR_CONDITIONLESS_BLOCK,
133134
EXPR_TOTAL,
134135
};
135136

include/AST/ast_expr.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,13 @@ typedef struct {
358358
// Aliases
359359
ast_expr_ifelse_t, ast_expr_unlesselse_t, ast_expr_ifwhileelse_t, ast_expr_unlessuntilelse_t;
360360

361+
// ---------------- ast_expr_conditionless_blocK_t ----------------
362+
// A conditionless block
363+
typedef struct {
364+
DERIVE_AST_EXPR;
365+
ast_expr_list_t statements;
366+
} ast_expr_conditionless_block_t;
367+
361368
// ---------------- ast_expr_each_in_t ----------------
362369
// Expression for 'each in' loop. Used for iterating
363370
// over a low-level array given a length.

include/PARSE/parse_stmt.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ errorcode_t parse_switch(parse_ctx_t *ctx, ast_expr_list_t *stmt_list, defer_sco
8686
// such as 'if' or 'unless'
8787
errorcode_t parse_onetime_conditional(parse_ctx_t *ctx, ast_expr_list_t *stmt_list, defer_scope_t *defer_scope);
8888

89+
// ------------------ parse_conditionless_block ------------------
90+
// Parses a conditionless block
91+
errorcode_t parse_conditionless_block(parse_ctx_t *ctx, ast_expr_list_t *stmt_list, defer_scope_t *defer_scope);
92+
8993
// ------------------ parse_mutable_expr_operation ------------------
9094
// Parses a statement that begins with a mutable expression
9195
// e.g. variable = value or my_array[index].doSomething()

src/AST/EXPR/ast_expr_free.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,5 +326,8 @@ void ast_expr_free(ast_expr_t *expr){
326326
case EXPR_DECLARE_CONSTANT:
327327
ast_expr_declare_constant_free((ast_expr_declare_constant_t*) expr);
328328
break;
329+
case EXPR_CONDITIONLESS_BLOCK:
330+
ast_expr_list_free(&((ast_expr_conditionless_block_t*) expr)->statements);
331+
break;
329332
}
330333
}

src/AST/ast_expr.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,16 @@ ast_expr_t *ast_expr_clone(ast_expr_t* expr){
594594

595595
#undef expr_as_declare_constant
596596
#undef clone_as_declare_constant
597+
case EXPR_CONDITIONLESS_BLOCK:
598+
#define expr_as_block ((ast_expr_conditionless_block_t*) expr)
599+
#define clone_as_block ((ast_expr_conditionless_block_t*) clone)
600+
601+
clone = malloc(sizeof(ast_expr_conditionless_block_t));
602+
clone_as_block->statements = ast_expr_list_clone(&expr_as_block->statements);
603+
break;
604+
605+
#undef expr_as_conditionless_block
606+
#undef clone_as_conditionless_block
597607
default:
598608
die("ast_expr_clone() - Got unrecognized expression ID 0x%08X\n", expr->id);
599609
}

src/IRGEN/ir_gen_polymorphable.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ static errorcode_t ir_gen_polymorphable_elem_prereq(
179179
ast_elem_polymorph_prereq_t *prereq = (ast_elem_polymorph_prereq_t*) polymorphic_type->elements[index];
180180
ast_poly_catalog_type_t *type_var = ast_poly_catalog_find_type(catalog, prereq->name);
181181

182-
// Ok since 'ast_elem_polymorph_t' is guaranteed to overlap with 'ast_elem_polymorph_t'
182+
// Ok since 'ast_elem_polymorph_prereq_t' is guaranteed to overlap with 'ast_elem_polymorph_t'
183183
errorcode_t res = enforce_polymorph(compiler, object, catalog, (ast_elem_polymorph_t*) prereq, type_var, &replacement);
184184
free(replacement.elements);
185185
return res;

src/IRGEN/ir_gen_stmt.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,23 @@ errorcode_t ir_gen_stmts(ir_builder_t *builder, ast_expr_list_t *stmt_list, bool
530530
asm_expr->has_side_effects, asm_expr->is_stack_align);
531531
}
532532
break;
533+
case EXPR_CONDITIONLESS_BLOCK: {
534+
ast_expr_conditionless_block_t *block_expr = (ast_expr_conditionless_block_t*) stmt;
535+
536+
open_scope(builder);
537+
538+
if(ir_gen_stmts(builder, &block_expr->statements, out_is_terminated)){
539+
close_scope(builder);
540+
return FAILURE;
541+
}
542+
543+
close_scope(builder);
544+
545+
if(*out_is_terminated){
546+
return SUCCESS;
547+
}
548+
}
549+
break;
533550
default:
534551
compiler_panic(builder->compiler, stmt->source, "INTERNAL ERROR: Unimplemented statement in ir_gen_stmts()");
535552
return FAILURE;

src/PARSE/parse_stmt.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,9 @@ errorcode_t parse_stmts(parse_ctx_t *ctx, ast_expr_list_t *stmt_list, defer_scop
731731
case TOKEN_LLVM_ASM:
732732
if(parse_llvm_asm(ctx, stmt_list)) return FAILURE;
733733
break;
734+
case TOKEN_BEGIN:
735+
if(parse_conditionless_block(ctx, stmt_list, defer_scope)) return FAILURE;
736+
break;
734737
default:
735738
parse_panic_token(ctx, sources[*i], tokens[*i].id, "Encountered unexpected token '%s' at beginning of statement");
736739
return FAILURE;
@@ -1013,6 +1016,36 @@ errorcode_t parse_switch(parse_ctx_t *ctx, ast_expr_list_t *stmt_list, defer_sco
10131016
return SUCCESS;
10141017
}
10151018

1019+
errorcode_t parse_conditionless_block(parse_ctx_t *ctx, ast_expr_list_t *stmt_list, defer_scope_t *defer_scope){
1020+
source_t source = ctx->tokenlist->sources[(*ctx->i)++];
1021+
1022+
ast_expr_list_t block_stmt_list;
1023+
ast_expr_list_init(&block_stmt_list, 4);
1024+
1025+
defer_scope_t block_defer_scope;
1026+
defer_scope_init(&block_defer_scope, defer_scope, NULL, TRAIT_NONE);
1027+
1028+
if(parse_stmts(ctx, &block_stmt_list, &block_defer_scope, PARSE_STMTS_STANDARD)
1029+
|| parse_eat(ctx, TOKEN_END, "Expected '}' to close condition-less block")){
1030+
ast_expr_list_free(&block_stmt_list);
1031+
defer_scope_free(&block_defer_scope);
1032+
return FAILURE;
1033+
}
1034+
1035+
defer_scope_free(&block_defer_scope);
1036+
1037+
ast_expr_conditionless_block_t *stmt = malloc(sizeof(ast_expr_conditionless_block_t));
1038+
1039+
*stmt = (ast_expr_conditionless_block_t){
1040+
.id = EXPR_CONDITIONLESS_BLOCK,
1041+
.source = source,
1042+
.statements = block_stmt_list,
1043+
};
1044+
1045+
stmt_list->statements[stmt_list->length++] = (ast_expr_t*) stmt;
1046+
return SUCCESS;
1047+
}
1048+
10161049
errorcode_t parse_onetime_conditional(parse_ctx_t *ctx, ast_expr_list_t *stmt_list, defer_scope_t *defer_scope){
10171050
token_t *tokens = ctx->tokenlist->tokens;
10181051
length_t *i = ctx->i;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
import basics
3+
4+
func main {
5+
defer print("4")
6+
7+
{
8+
defer print("2")
9+
10+
print("1")
11+
}
12+
13+
print("3")
14+
}

tests/run.bat

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ call :compile complement
6565
if %errorlevel% neq 0 popd & exit /b %errorlevel%
6666
call :compile complex_composite_rtti
6767
if %errorlevel% neq 0 popd & exit /b %errorlevel%
68+
call :compile conditionless_block
69+
if %errorlevel% neq 0 popd & exit /b %errorlevel%
6870
call :compile conditionless_break_label
6971
if %errorlevel% neq 0 popd & exit /b %errorlevel%
7072
call :compile const_variables

0 commit comments

Comments
 (0)