Skip to content

Commit

Permalink
Added condition-less blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
IsaacShelton committed Feb 14, 2022
1 parent af5a5f6 commit 369b80a
Show file tree
Hide file tree
Showing 12 changed files with 95 additions and 4 deletions.
1 change: 1 addition & 0 deletions include/AST/EXPR/ast_expr_ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ enum {
EXPR_VA_COPY,
EXPR_FOR,
EXPR_DECLARE_CONSTANT,
EXPR_CONDITIONLESS_BLOCK,
EXPR_TOTAL,
};

Expand Down
7 changes: 7 additions & 0 deletions include/AST/ast_expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,13 @@ typedef struct {
// Aliases
ast_expr_ifelse_t, ast_expr_unlesselse_t, ast_expr_ifwhileelse_t, ast_expr_unlessuntilelse_t;

// ---------------- ast_expr_conditionless_blocK_t ----------------
// A conditionless block
typedef struct {
DERIVE_AST_EXPR;
ast_expr_list_t statements;
} ast_expr_conditionless_block_t;

// ---------------- ast_expr_each_in_t ----------------
// Expression for 'each in' loop. Used for iterating
// over a low-level array given a length.
Expand Down
4 changes: 4 additions & 0 deletions include/PARSE/parse_stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ errorcode_t parse_switch(parse_ctx_t *ctx, ast_expr_list_t *stmt_list, defer_sco
// such as 'if' or 'unless'
errorcode_t parse_onetime_conditional(parse_ctx_t *ctx, ast_expr_list_t *stmt_list, defer_scope_t *defer_scope);

// ------------------ parse_conditionless_block ------------------
// Parses a conditionless block
errorcode_t parse_conditionless_block(parse_ctx_t *ctx, ast_expr_list_t *stmt_list, defer_scope_t *defer_scope);

// ------------------ parse_mutable_expr_operation ------------------
// Parses a statement that begins with a mutable expression
// e.g. variable = value or my_array[index].doSomething()
Expand Down
3 changes: 3 additions & 0 deletions src/AST/EXPR/ast_expr_free.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,5 +326,8 @@ void ast_expr_free(ast_expr_t *expr){
case EXPR_DECLARE_CONSTANT:
ast_expr_declare_constant_free((ast_expr_declare_constant_t*) expr);
break;
case EXPR_CONDITIONLESS_BLOCK:
ast_expr_list_free(&((ast_expr_conditionless_block_t*) expr)->statements);
break;
}
}
10 changes: 10 additions & 0 deletions src/AST/ast_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,16 @@ ast_expr_t *ast_expr_clone(ast_expr_t* expr){

#undef expr_as_declare_constant
#undef clone_as_declare_constant
case EXPR_CONDITIONLESS_BLOCK:
#define expr_as_block ((ast_expr_conditionless_block_t*) expr)
#define clone_as_block ((ast_expr_conditionless_block_t*) clone)

clone = malloc(sizeof(ast_expr_conditionless_block_t));
clone_as_block->statements = ast_expr_list_clone(&expr_as_block->statements);
break;

#undef expr_as_conditionless_block
#undef clone_as_conditionless_block
default:
die("ast_expr_clone() - Got unrecognized expression ID 0x%08X\n", expr->id);
}
Expand Down
2 changes: 1 addition & 1 deletion src/IRGEN/ir_gen_polymorphable.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ static errorcode_t ir_gen_polymorphable_elem_prereq(
ast_elem_polymorph_prereq_t *prereq = (ast_elem_polymorph_prereq_t*) polymorphic_type->elements[index];
ast_poly_catalog_type_t *type_var = ast_poly_catalog_find_type(catalog, prereq->name);

// Ok since 'ast_elem_polymorph_t' is guaranteed to overlap with 'ast_elem_polymorph_t'
// Ok since 'ast_elem_polymorph_prereq_t' is guaranteed to overlap with 'ast_elem_polymorph_t'
errorcode_t res = enforce_polymorph(compiler, object, catalog, (ast_elem_polymorph_t*) prereq, type_var, &replacement);
free(replacement.elements);
return res;
Expand Down
17 changes: 17 additions & 0 deletions src/IRGEN/ir_gen_stmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,23 @@ errorcode_t ir_gen_stmts(ir_builder_t *builder, ast_expr_list_t *stmt_list, bool
asm_expr->has_side_effects, asm_expr->is_stack_align);
}
break;
case EXPR_CONDITIONLESS_BLOCK: {
ast_expr_conditionless_block_t *block_expr = (ast_expr_conditionless_block_t*) stmt;

open_scope(builder);

if(ir_gen_stmts(builder, &block_expr->statements, out_is_terminated)){
close_scope(builder);
return FAILURE;
}

close_scope(builder);

if(*out_is_terminated){
return SUCCESS;
}
}
break;
default:
compiler_panic(builder->compiler, stmt->source, "INTERNAL ERROR: Unimplemented statement in ir_gen_stmts()");
return FAILURE;
Expand Down
33 changes: 33 additions & 0 deletions src/PARSE/parse_stmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,9 @@ errorcode_t parse_stmts(parse_ctx_t *ctx, ast_expr_list_t *stmt_list, defer_scop
case TOKEN_LLVM_ASM:
if(parse_llvm_asm(ctx, stmt_list)) return FAILURE;
break;
case TOKEN_BEGIN:
if(parse_conditionless_block(ctx, stmt_list, defer_scope)) return FAILURE;
break;
default:
parse_panic_token(ctx, sources[*i], tokens[*i].id, "Encountered unexpected token '%s' at beginning of statement");
return FAILURE;
Expand Down Expand Up @@ -1013,6 +1016,36 @@ errorcode_t parse_switch(parse_ctx_t *ctx, ast_expr_list_t *stmt_list, defer_sco
return SUCCESS;
}

errorcode_t parse_conditionless_block(parse_ctx_t *ctx, ast_expr_list_t *stmt_list, defer_scope_t *defer_scope){
source_t source = ctx->tokenlist->sources[(*ctx->i)++];

ast_expr_list_t block_stmt_list;
ast_expr_list_init(&block_stmt_list, 4);

defer_scope_t block_defer_scope;
defer_scope_init(&block_defer_scope, defer_scope, NULL, TRAIT_NONE);

if(parse_stmts(ctx, &block_stmt_list, &block_defer_scope, PARSE_STMTS_STANDARD)
|| parse_eat(ctx, TOKEN_END, "Expected '}' to close condition-less block")){
ast_expr_list_free(&block_stmt_list);
defer_scope_free(&block_defer_scope);
return FAILURE;
}

defer_scope_free(&block_defer_scope);

ast_expr_conditionless_block_t *stmt = malloc(sizeof(ast_expr_conditionless_block_t));

*stmt = (ast_expr_conditionless_block_t){
.id = EXPR_CONDITIONLESS_BLOCK,
.source = source,
.statements = block_stmt_list,
};

stmt_list->statements[stmt_list->length++] = (ast_expr_t*) stmt;
return SUCCESS;
}

errorcode_t parse_onetime_conditional(parse_ctx_t *ctx, ast_expr_list_t *stmt_list, defer_scope_t *defer_scope){
token_t *tokens = ctx->tokenlist->tokens;
length_t *i = ctx->i;
Expand Down
14 changes: 14 additions & 0 deletions tests/conditionless_block/main.adept
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

import basics

func main {
defer print("4")

{
defer print("2")

print("1")
}

print("3")
}
2 changes: 2 additions & 0 deletions tests/run.bat
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ call :compile complement
if %errorlevel% neq 0 popd & exit /b %errorlevel%
call :compile complex_composite_rtti
if %errorlevel% neq 0 popd & exit /b %errorlevel%
call :compile conditionless_block
if %errorlevel% neq 0 popd & exit /b %errorlevel%
call :compile conditionless_break_label
if %errorlevel% neq 0 popd & exit /b %errorlevel%
call :compile const_variables
Expand Down
1 change: 1 addition & 0 deletions tests/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ compile circular_pointers || exit $?
compile colons_alternative_syntax || exit $?
compile complement || exit $?
compile complex_composite_rtti || exit $?
compile conditionless_block || exit $?
compile conditionless_break_label || exit $?
compile const_variables || exit $?
compile constants || exit $?
Expand Down
5 changes: 2 additions & 3 deletions todolists/2.6.todolist
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@ LOW-PRIORITY:
* Make 'typeinfo' work better with aliases and '*void'
* Add way to manually invoke DEINIT_SVARS
* Maybe add support for methods on non-struct types, e.g. toString(this *$#N $T) String, toString(this *int), toUnique(this *ubyte) <ubyte> Unique, etc.
* Unconditional blocks (like: if true {}, except with 'if true' part)
* Specify default value arguments by name (e.g - captLoadTexturesByFieldName(this, assetsFolder: where(), approximateByDefault: true) )
* 'adept install https://github.com/IsaacShelton/Box2D'
* conditionless blocks
* match/when statement or something like that
* support for disallowing/disencouraging assignment for a composite type
* macro/snippet functions? that expand to be inline and never become an actual function
Expand All @@ -53,7 +51,6 @@ LOW-PRIORITY:
#end
}
```
* make call to functions like `max($T, $T) $T` allow built-in auto conversions between primitives for arguments

v2.4 COMPLETED:
+ Standard Library Imports
Expand Down Expand Up @@ -89,3 +86,5 @@ v2.6 COMPLETED:
+ __assign__ auto-generation
+ no more "new update" false-positives for preview builds
+ optional parameter names for foreign functions
+ changed '$T' polymorphs to always allow built-in auto conversions (equivalent to '$~T' in previous versions)
+ conditionless blocks

0 comments on commit 369b80a

Please sign in to comment.