Skip to content

Commit

Permalink
Replace message-building functions with message-building blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
positively-charged committed Apr 20, 2017
1 parent 53b70b4 commit c2a54ed
Show file tree
Hide file tree
Showing 17 changed files with 475 additions and 221 deletions.
26 changes: 19 additions & 7 deletions doc/grammar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ statement:
<label>
<palette-translation>
<assert>
<buildmsg>
<empty-statement>
<expression-statement>

Expand Down Expand Up @@ -547,8 +548,9 @@ script-jump-statement:
restart ;

return-statement:
return <expression> ;
return ;
return <expression> ;
return <buildmsg>

goto-statement:
goto <identifier> ;
Expand Down Expand Up @@ -586,6 +588,12 @@ assert:
static assert ( <expression> ) ;
static assert ( <expression> , <string> ) ;

buildmsg-statement:
<buildmsg>

buildmsg:
buildmsg ( <expression> ) <block-statement>

inline-asm:
> <id> <nl>
> <id> <inline-asm-args> <nl>
Expand Down Expand Up @@ -692,14 +700,17 @@ suffix:
<suffix> ++
<suffix> --
<suffix> [ <expression> ]
<suffix> ( )
<suffix> ( <expression-list> )
<suffix> ( const : <expression-list> )
<suffix> ( <format-item-list> )
<suffix> ( <format-item-list> ; <expression-list> )
<suffix> <call>
<suffix> . <identifier>
<suffix> ! !

call:
( )
( <expression-list> )
( const : <expression-list> )
( <format-item-list> )
( <format-item-list> ; <expression-list> )

format-item-list:
<format-item>
<format-item-list> , <format-item>
Expand Down Expand Up @@ -852,6 +863,7 @@ keyword:
auto
bool
break
buildmsg
case
const
continue
Expand Down Expand Up @@ -925,4 +937,4 @@ context-sensitive-keyword:
respawn
unloading
wadauthor
whitereturn
whitereturn
23 changes: 9 additions & 14 deletions src/codegen/expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1767,7 +1767,7 @@ void visit_format_item( struct codegen* codegen, struct format_item* item ) {
if ( item->cast == FCAST_ARRAY ) {
visit_array_format_item( codegen, item );
}
else if ( item->cast == FCAST_MSGBUILD ) {
else if ( item->cast == FCAST_BUILDMSG ) {
visit_msgbuild_format_item( codegen, item );
}
else {
Expand Down Expand Up @@ -1852,20 +1852,15 @@ void visit_array_format_item( struct codegen* codegen,

void visit_msgbuild_format_item( struct codegen* codegen,
struct format_item* item ) {
struct format_item_msgbuild* extra = item->extra;
if ( extra->call ) {
struct result result;
init_result( &result, true );
visit_user_call( codegen, &result, extra->call );
}
else if ( extra->func ) {
struct func_user* impl = extra->func->impl;
c_pcd( codegen, PCD_CALLDISCARD, impl->index );
struct format_item_buildmsg* extra = item->extra;
// Inline the message-building block if it only has a single user.
if ( list_size( &extra->usage->buildmsg->usages ) == 1 ) {
c_write_block( codegen, extra->usage->buildmsg->block );
}
else {
c_push_expr( codegen, item->value );
c_pcd( codegen, PCD_CALLSTACK );
c_pcd( codegen, PCD_DROP );
struct c_point* jump_point = c_create_point( codegen );
c_append_node( codegen, &jump_point->node );
extra->usage->point = jump_point;
}
}

Expand Down Expand Up @@ -3153,4 +3148,4 @@ void next_diminfo( struct codegen* codegen ) {
void push_diminfo( struct codegen* codegen ) {
c_push_dimtrack( codegen );
c_pcd( codegen, PCD_PUSHMAPARRAY, codegen->shary.index );
}
}
87 changes: 80 additions & 7 deletions src/codegen/stmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ static void write_palrange_tint( struct codegen* codegen,
static void visit_script_jump( struct codegen* codegen, struct script_jump* );
static void visit_label( struct codegen* codegen, struct label* );
static void visit_goto( struct codegen* codegen, struct goto_stmt* );
static void visit_buildmsg_stmt( struct codegen* codegen,
struct buildmsg_stmt* stmt );
static void write_msgbuild_block( struct codegen* codegen,
struct buildmsg* buildmsg );
static void write_multi_usage_msgbuild_block( struct codegen* codegen,
struct buildmsg* buildmsg );
static void visit_expr_stmt( struct codegen* codegen, struct expr_stmt* stmt );

void c_write_block( struct codegen* codegen, struct block* stmt ) {
Expand Down Expand Up @@ -213,6 +219,10 @@ void c_write_stmt( struct codegen* codegen, struct node* node ) {
case NODE_PALTRANS:
visit_paltrans( codegen, ( struct paltrans* ) node );
break;
case NODE_BUILDMSG:
visit_buildmsg_stmt( codegen,
( struct buildmsg_stmt* ) node );
break;
case NODE_EXPR_STMT:
visit_expr_stmt( codegen,
( struct expr_stmt* ) node );
Expand Down Expand Up @@ -1096,19 +1106,22 @@ void set_jumps_point( struct codegen* codegen, struct jump* jump,
}

void visit_return( struct codegen* codegen, struct return_stmt* stmt ) {
if ( codegen->func->nested_func ) {
if ( stmt->return_value ) {
c_push_initz_expr( codegen, codegen->func->func->ref,
stmt->return_value );
// Push return value.
if ( stmt->return_value ) {
c_push_initz_expr( codegen, codegen->func->func->ref,
stmt->return_value );
if ( stmt->buildmsg ) {
write_msgbuild_block( codegen, stmt->buildmsg );
}
}
// Exit.
if ( codegen->func->nested_func ) {
struct c_jump* epilogue_jump = c_create_jump( codegen, PCD_GOTO );
c_append_node( codegen, &epilogue_jump->node );
stmt->epilogue_jump = epilogue_jump;
}
else {
if ( stmt->return_value ) {
c_push_initz_expr( codegen, codegen->func->func->ref,
stmt->return_value );
c_pcd( codegen, PCD_RETURNVAL );
}
else {
Expand Down Expand Up @@ -1201,11 +1214,71 @@ void visit_goto( struct codegen* codegen, struct goto_stmt* stmt ) {
jump->point = stmt->label->point;
}

static void visit_buildmsg_stmt( struct codegen* codegen,
struct buildmsg_stmt* stmt ) {
c_visit_expr( codegen, stmt->buildmsg->expr );
write_msgbuild_block( codegen, stmt->buildmsg );
}

static void write_msgbuild_block( struct codegen* codegen,
struct buildmsg* buildmsg ) {
// When a message-building block is used more than once in the same
// expression, instead of duplicating the block code, use a goto instruction
// to enter the block. Single-usage blocks are inlined at the call site.
if ( list_size( &buildmsg->usages ) > 1 ) {
write_multi_usage_msgbuild_block( codegen, buildmsg );
}
}

static void write_multi_usage_msgbuild_block( struct codegen* codegen,
struct buildmsg* buildmsg ) {
struct c_jump* exit_jump = c_create_jump( codegen, PCD_GOTO );
c_append_node( codegen, &exit_jump->node );
struct c_point* enter_point = c_create_point( codegen );
c_append_node( codegen, &enter_point->node );
c_write_block( codegen, buildmsg->block );
// Create jumps into the message-building block.
unsigned int entry_number = 0;
list_iter_t i;
list_iter_init( &i, &buildmsg->usages );
while ( ! list_end( &i ) ) {
struct buildmsg_usage* usage = list_data( &i );
c_seek_node( codegen, &usage->point->node );
c_pcd( codegen, PCD_PUSHNUMBER, entry_number );
struct c_jump* jump = c_create_jump( codegen, PCD_GOTO );
c_append_node( codegen, &jump->node );
jump->point = enter_point;
struct c_point* return_point = c_create_point( codegen );
c_append_node( codegen, &return_point->node );
usage->point = return_point;
++entry_number;
list_next( &i );
}
c_seek_node( codegen, codegen->node_tail );
// Create return table.
struct c_sortedcasejump* return_table = c_create_sortedcasejump( codegen );
c_append_node( codegen, &return_table->node );
entry_number = 0;
list_iter_init( &i, &buildmsg->usages );
while ( ! list_end( &i ) ) {
struct buildmsg_usage* usage = list_data( &i );
struct c_casejump* entry = c_create_casejump( codegen, entry_number,
usage->point );
c_append_casejump( return_table, entry );
++entry_number;
list_next( &i );
}
// Exit.
struct c_point* exit_point = c_create_point( codegen );
c_append_node( codegen, &exit_point->node );
exit_jump->point = exit_point;
}

void visit_expr_stmt( struct codegen* codegen, struct expr_stmt* stmt ) {
list_iter_t i;
list_iter_init( &i, &stmt->expr_list );
while ( ! list_end( &i ) ) {
c_visit_expr( codegen, list_data( &i ) );
list_next( &i );
}
}
}
2 changes: 1 addition & 1 deletion src/parse/asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,4 @@ struct inline_asm_arg* alloc_inline_asm_arg( struct pos* pos ) {
arg->value.number = 0;
arg->pos = *pos;
return arg;
}
}
2 changes: 1 addition & 1 deletion src/parse/dec.c
Original file line number Diff line number Diff line change
Expand Up @@ -2711,4 +2711,4 @@ void read_special_return_type( struct parse* parse,
p_bail( parse );
}
p_read_tk( parse );
}
}
62 changes: 18 additions & 44 deletions src/parse/expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ static void read_format_cast( struct parse* parse, struct format_cast* cast );
static bool peek_format_cast( struct parse* parse );
static void init_array_field( struct array_field* field );
static void read_array_field( struct parse* parse, struct array_field* field );
static void read_msgbuild_format_item( struct parse* parse,
struct format_item* item );
static void read_id( struct parse* parse, struct expr_reading* reading );
static void read_literal( struct parse* parse, struct expr_reading* reading );
static void read_string( struct parse* parse, struct expr_reading* reading );
Expand Down Expand Up @@ -1041,12 +1039,8 @@ struct format_item* read_format_item_list( struct parse* parse ) {
}

struct format_item* read_format_item( struct parse* parse ) {
struct format_item* item = mem_alloc( sizeof( *item ) );
item->cast = FCAST_DECIMAL;
struct format_item* item = t_alloc_format_item();
item->pos = parse->tk_pos;
item->next = NULL;
item->value = NULL;
item->extra = NULL;
struct format_cast cast;
init_format_cast( &cast );
read_format_cast( parse, &cast );
Expand All @@ -1063,9 +1057,6 @@ struct format_item* read_format_item( struct parse* parse ) {
item->extra = extra;
}
}
else if ( item->cast == FCAST_MSGBUILD ) {
read_msgbuild_format_item( parse, item );
}
else {
struct expr_reading value;
p_init_expr_reading( &value, false, false, false, true );
Expand Down Expand Up @@ -1094,28 +1085,23 @@ void read_format_cast( struct parse* parse, struct format_cast* cast ) {
}
break;
default:
if ( parse->tk == TK_MSGBUILD ) {
cast->type = FCAST_MSGBUILD;
switch ( parse->tk_text[ 0 ] ) {
case 'a': cast->type = FCAST_ARRAY; break;
case 'b': cast->type = FCAST_BINARY; break;
case 'c': cast->type = FCAST_CHAR; break;
case 'd': cast->type = FCAST_DECIMAL; break;
case 'f': cast->type = FCAST_FIXED; break;
case 'i': cast->type = FCAST_RAW; break;
case 'k': cast->type = FCAST_KEY; break;
case 'l': cast->type = FCAST_LOCAL_STRING; break;
case 'n': cast->type = FCAST_NAME; break;
case 's': cast->type = FCAST_STRING; break;
case 'x': cast->type = FCAST_HEX; break;
default:
cast->unknown = true;
}
else {
switch ( parse->tk_text[ 0 ] ) {
case 'a': cast->type = FCAST_ARRAY; break;
case 'b': cast->type = FCAST_BINARY; break;
case 'c': cast->type = FCAST_CHAR; break;
case 'd': cast->type = FCAST_DECIMAL; break;
case 'f': cast->type = FCAST_FIXED; break;
case 'i': cast->type = FCAST_RAW; break;
case 'k': cast->type = FCAST_KEY; break;
case 'l': cast->type = FCAST_LOCAL_STRING; break;
case 'n': cast->type = FCAST_NAME; break;
case 's': cast->type = FCAST_STRING; break;
case 'x': cast->type = FCAST_HEX; break;
default:
cast->unknown = true;
}
if ( parse->tk_length != 1 ) {
cast->unknown = true;
}
if ( parse->tk_length != 1 ) {
cast->unknown = true;
}
}
if ( cast->unknown ) {
Expand Down Expand Up @@ -1171,18 +1157,6 @@ void read_array_field( struct parse* parse, struct array_field* field ) {
p_read_tk( parse );
}

void read_msgbuild_format_item( struct parse* parse,
struct format_item* item ) {
struct format_item_msgbuild* extra = mem_alloc( sizeof( *extra ) );
extra->func = NULL;
extra->call = NULL;
item->extra = extra;
struct expr_reading value;
p_init_expr_reading( &value, false, false, false, true );
p_read_expr( parse, &value );
item->value = value.output_node;
}

void read_sure( struct parse* parse, struct expr_reading* reading ) {
p_test_tk( parse, TK_LOG_NOT );
struct sure* sure = mem_alloc( sizeof( *sure ) );
Expand Down Expand Up @@ -1361,4 +1335,4 @@ void read_magic_id( struct parse* parse, struct expr_reading* reading ) {
}
p_read_tk( parse );
reading->node = &magic_id->node;
}
}
3 changes: 2 additions & 1 deletion src/parse/phase.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ enum tk {
TK_FUNCTIONNAME,
TK_SCRIPTNAME,
TK_AT,
TK_BUILDMSG,

TK_TOTAL,

Expand Down Expand Up @@ -560,4 +561,4 @@ void p_init_paren_reading( struct parse* parse,
void p_read_paren_type( struct parse* parse, struct paren_reading* reading );
void p_add_altern_file_name( struct parse* parse, const char* name, int line );

#endif
#endif
Loading

0 comments on commit c2a54ed

Please sign in to comment.