From 6c69e19b63a97e39ec1cffcd1143dc0f15b15bc4 Mon Sep 17 00:00:00 2001 From: Sayon Date: Mon, 4 Aug 2014 15:38:08 +0400 Subject: [PATCH] Relations support and cli --- dwarf/dwarf-compiler/AST.h | 9 +++ dwarf/dwarf-compiler/ast_constructors.c | 8 --- dwarf/dwarf-compiler/ast_helpers.c | 24 ++----- dwarf/dwarf-compiler/bytecode.c | 53 ++++++++++---- dwarf/dwarf-compiler/bytecode.h | 11 ++- dwarf/dwarf-compiler/codegen.c | 71 +++++-------------- dwarf/dwarf-compiler/dwarf-compiler.vcxproj | 3 +- .../dwarf-compiler.vcxproj.filters | 5 +- dwarf/dwarf-compiler/main.c | 48 ++++++++++--- dwarf/dwarf-compiler/parser.c | 6 -- dwarf/dwarf-compiler/tokens.h | 10 +-- 11 files changed, 126 insertions(+), 122 deletions(-) diff --git a/dwarf/dwarf-compiler/AST.h b/dwarf/dwarf-compiler/AST.h index 3c26e43..4a42ce9 100755 --- a/dwarf/dwarf-compiler/AST.h +++ b/dwarf/dwarf-compiler/AST.h @@ -14,6 +14,9 @@ typedef enum { AST_MINUS, AST_MULT, AST_DIVIDE, + AST_LT, + AST_EQ, + AST_GT, AST_SEQ, AST_IDENTIFIER, AST_PRINT @@ -77,6 +80,12 @@ ast_t* ast_plus( ast_t* left, ast_t* right ); ast_t* ast_minus( ast_t* left, ast_t* right ); ast_t* ast_mult( ast_t* left, ast_t* right ); ast_t* ast_div( ast_t* left, ast_t* right ); + +ast_t* ast_lt( ast_t* left, ast_t* right ); +ast_t* ast_eq( ast_t* left, ast_t* right ); +ast_t* ast_gt( ast_t* left, ast_t* right ); + + ast_t* ast_assignment( ast_t* ident, ast_t* expr ); ast_t* ast_seq( ast_t* left, ast_t* right ); ast_t* ast_identifier( char* name ); diff --git a/dwarf/dwarf-compiler/ast_constructors.c b/dwarf/dwarf-compiler/ast_constructors.c index 4a8e169..fa0eadf 100755 --- a/dwarf/dwarf-compiler/ast_constructors.c +++ b/dwarf/dwarf-compiler/ast_constructors.c @@ -41,18 +41,10 @@ ast_t* ast_lt( ast_t* left, ast_t* right ) { return ast_binop( left, right, AST_LT ); } -ast_t* ast_le( ast_t* left, ast_t* right ) { - return ast_binop( left, right, AST_LE ); -} - ast_t* ast_eq( ast_t* left, ast_t* right ) { return ast_binop( left, right, AST_EQ ); } -ast_t* ast_ge( ast_t* left, ast_t* right ) { - return ast_binop( left, right, AST_GE ); -} - ast_t* ast_gt( ast_t* left, ast_t* right ) { return ast_binop( left, right, AST_GT ); } diff --git a/dwarf/dwarf-compiler/ast_helpers.c b/dwarf/dwarf-compiler/ast_helpers.c index 58b23a2..c9fc080 100755 --- a/dwarf/dwarf-compiler/ast_helpers.c +++ b/dwarf/dwarf-compiler/ast_helpers.c @@ -27,10 +27,8 @@ void ast_visit( ast_t* node, void (before)( ast_t* node ), void (after)( ast_t* case AST_MINUS: case AST_MULT: case AST_DIVIDE: - case AST_LT: - case AST_LE: - case AST_EQ: - case AST_GE: + case AST_LT: + case AST_EQ: case AST_GT: ast_visit( node->attributes.as_binop.left, before, after ); ast_visit( node->attributes.as_binop.right, before, after ); @@ -119,28 +117,14 @@ void ast_print( ast_t* node, FILE* out ) { fprintf( out, " < " ); ast_print( node->attributes.as_binop.right, out ); fprintf( out, " )" ); - break; - case AST_LE: - fprintf( out, "( " ); - ast_print( node->attributes.as_binop.left, out ); - fprintf( out, " <= " ); - ast_print( node->attributes.as_binop.right, out ); - fprintf( out, " )" ); - break; + break; case AST_EQ: fprintf( out, "( " ); ast_print( node->attributes.as_binop.left, out ); fprintf( out, " == " ); ast_print( node->attributes.as_binop.right, out ); fprintf( out, " )" ); - break; - case AST_GE: - fprintf( out, "( " ); - ast_print( node->attributes.as_binop.left, out ); - fprintf( out, " >= " ); - ast_print( node->attributes.as_binop.right, out ); - fprintf( out, " )" ); - break; + break; case AST_GT: fprintf( out, "( " ); ast_print( node->attributes.as_binop.left, out ); diff --git a/dwarf/dwarf-compiler/bytecode.c b/dwarf/dwarf-compiler/bytecode.c index e3f45b0..3665ce0 100755 --- a/dwarf/dwarf-compiler/bytecode.c +++ b/dwarf/dwarf-compiler/bytecode.c @@ -9,27 +9,19 @@ size_t bytecode_size[] = { 1, 1, 1, + 1, 1 + sizeof( lang_int_t ), 1 + sizeof( reg_num_t ), 1 + sizeof( reg_num_t ), 1 + sizeof( addr_offset_t ), 1 + sizeof( addr_offset_t ), + 1 + sizeof( addr_offset_t ), + 1, 1, 1, 1 }; -/* Helpers *//* -static bytecode_t* last( bytecode_t* bc ) -{ - while (bc != NULL) bc = bc->next; - return bc; -} - -static void bc_concat( bytecode_t* left, bytecode_t* right ) { - last( left )-> next = right; -}*/ - void bytecode_foreach( bytecode_t* bc, void ( action )( bytecode_t* ) ) { bytecode_t* next; @@ -57,7 +49,6 @@ bytecode_t* emit_bytecode( bytecode_builder_t* builder, opcode_t opcode) { } - /* Helpers to emit specific bytecodes with parameters */ static addr_offset_t* emit_delayed_jump( bytecode_builder_t* builder, opcode_t code ) { @@ -132,4 +123,42 @@ void bytecode_prettyprint( bytecode_t* bc ) { bc = next; } } +static void bytecode_free_one( bytecode_t* bc ) { free (bc); } + +void bytecode_free( bytecode_t* bc ) { + bytecode_foreach( bc, bytecode_free_one ); +} + +static void bytecode_flush_one( bytecode_t* bc, FILE* file ) { + fwrite( &(bc->opcode), 1, 1, file ); + + switch( bc->opcode ) { + case BC_IPUSHC: + fwrite( &(bc-> params.immediate), sizeof( lang_int_t ), 1, file ); + break; + case BC_IPUSHREG: + case BC_IPOPREG: + fwrite( &(bc-> params.reg), sizeof( reg_num_t ), 1, file ); + break; + case BC_JMP: + case BC_JZ: + fwrite( &(bc-> params.offset), sizeof( addr_offset_t ), 1, file ); + break; + default: + break; + + } +} + +void bytecode_flush( bytecode_t* bc, FILE* file) { + bytecode_t* next; + + if ( bc == NULL ) return; + + while( bc != NULL ) { + next = bc->next; + bytecode_flush_one( bc, file ); + bc = next; + } +} \ No newline at end of file diff --git a/dwarf/dwarf-compiler/bytecode.h b/dwarf/dwarf-compiler/bytecode.h index 1bd832e..bd6e7e3 100755 --- a/dwarf/dwarf-compiler/bytecode.h +++ b/dwarf/dwarf-compiler/bytecode.h @@ -18,6 +18,7 @@ typedef enum { BC_JZ, BC_JNZ, BC_ICMP, + BC_EQ, BC_PRINT, BC_DEBUG } opcode_t; @@ -36,6 +37,7 @@ static char* bytecode_mnemonics[] = { "JZ", "JNZ", "ICMP", + "EQ", "PRINT", "DEBUG" }; @@ -61,11 +63,7 @@ typedef struct { bytecode_t* last; } bytecode_builder_t; - -typedef struct { - addr_offset_t* addr; -} addr_param_t; - + bytecode_t* emit_bytecode( bytecode_builder_t* builder, opcode_t opcode ); @@ -90,5 +88,6 @@ void emit_ipopreg( bytecode_builder_t* builder, reg_num_t reg); void bytecode_foreach( bytecode_t* bc, void ( action )( bytecode_t* ) ); void bytecode_print( bytecode_t* bytecode ); void bytecode_prettyprint( bytecode_t* bc ); - +void bytecode_free( bytecode_t* bc ); +void bytecode_flush( bytecode_t* bc, FILE* file); #endif \ No newline at end of file diff --git a/dwarf/dwarf-compiler/codegen.c b/dwarf/dwarf-compiler/codegen.c index 01fc7bc..4c71ca1 100755 --- a/dwarf/dwarf-compiler/codegen.c +++ b/dwarf/dwarf-compiler/codegen.c @@ -77,64 +77,33 @@ static size_t generate_div( ast_t* node, bytecode_builder_t* bc, generator_conte return first + bytecode_size[ BC_IDIV ] + second; } -static size_t generate_lt( ast_t* node, bytecode_builder_t* bc, generator_context_t* ctx ) { +static size_t generate_gt_helper( ast_t* left, ast_t* right, bytecode_builder_t* bc, generator_context_t* ctx ) { size_t first, second; - first = generate( node->attributes.as_binop.right, bc, ctx ); - second = generate( node->attributes.as_binop.left, bc, ctx ); + first = generate( left, bc, ctx ); + second = generate( right, bc, ctx ); emit_bytecode( bc, BC_ICMP ); - return first + bytecode_size[ BC_ICMP ] + second; -} - -static size_t generate_gt( ast_t* node, bytecode_builder_t* bc, generator_context_t* ctx ) { - size_t first, second; - first = generate( node->attributes.as_binop.left, bc, ctx ); - second = generate( node->attributes.as_binop.right, bc, ctx ); - emit_bytecode( bc, BC_ICMP ); - return first + bytecode_size[ BC_ICMP ] + second; -} - -static size_t generate_eq( ast_t* node, bytecode_builder_t* bc, generator_context_t* ctx ) { - size_t first, second; - first = generate( node->attributes.as_binop.left, bc, ctx ); - second = generate( node->attributes.as_binop.right, bc, ctx ); - emit_bytecode( bc, BC_ICMP ); - emit_bytecode( bc, BC_DUP ); - emit_bytecode( bc, BC_IMUL ); - emit_ipushc( bc, -1 ); - emit_ipushc( bc, BC_IADD ); + emit_ipushc( bc, 1 ); + emit_bytecode( bc, BC_EQ ); return first + second + bytecode_size[ BC_ICMP ] - + bytecode_size[ BC_DUP ] - + bytecode_size[ BC_IMUL ] + bytecode_size[ BC_IPUSHC ] - + bytecode_size[ BC_IADD ] ; + + bytecode_size[ BC_EQ ]; } -static size_t generate_le( ast_t* node, bytecode_builder_t* bc, generator_context_t* ctx ) { - size_t first, second; - first = generate( node->attributes.as_binop.right, bc, ctx ); - second = generate( node->attributes.as_binop.left, bc, ctx ); - emit_bytecode( bc, BC_ICMP ); - emit_ipushc( bc, 1 ); - emit_ipushc( bc, BC_IADD ); - return first + second - + bytecode_size[ BC_ICMP ] - + bytecode_size[ BC_IPUSHC ] - + bytecode_size[ BC_IADD ] ; +static size_t generate_gt( ast_t* node, bytecode_builder_t* bc, generator_context_t* ctx ) { + return generate_gt_helper( node->attributes.as_binop.left, node->attributes.as_binop.right, bc, ctx ); } +static size_t generate_lt( ast_t* node, bytecode_builder_t* bc, generator_context_t* ctx ) { //a < b === b > a + return generate_gt_helper( node->attributes.as_binop.right, node->attributes.as_binop.left, bc, ctx ); +} -static size_t generate_ge( ast_t* node, bytecode_builder_t* bc, generator_context_t* ctx ) { - size_t first, second; - first = generate( node->attributes.as_binop.left, bc, ctx ); - second = generate( node->attributes.as_binop.right, bc, ctx ); - emit_bytecode( bc, BC_ICMP ); - emit_ipushc( bc, 1 ); - emit_ipushc( bc, BC_IADD ); - return first + second - + bytecode_size[ BC_ICMP ] - + bytecode_size[ BC_IPUSHC ] - + bytecode_size[ BC_IADD ] ; + +static size_t generate_eq( ast_t* node, bytecode_builder_t* bc, generator_context_t* ctx ) { + size_t parts; + parts = generate( node->attributes.as_binop.left, bc, ctx ) + generate( node->attributes.as_binop.right, bc, ctx ); + emit_bytecode( bc, BC_EQ ); + return parts + bytecode_size[ BC_EQ ]; } static size_t generate_seq( ast_t* node, bytecode_builder_t* bc, generator_context_t* ctx ) { @@ -214,10 +183,8 @@ static size_t generate( ast_t* node, bytecode_builder_t* bc, generator_context_t case AST_MINUS: return generate_minus( node, bc, ctx ); case AST_MULT: return generate_mult( node, bc, ctx ); case AST_DIVIDE: return generate_div( node, bc, ctx ); - case AST_LT: return generate_lt( node, bc, ctx ); - case AST_LE: return generate_le( node, bc, ctx ); - case AST_EQ: return generate_eq( node, bc, ctx ); - case AST_GE: return generate_ge( node, bc, ctx ); + case AST_LT: return generate_lt( node, bc, ctx ); + case AST_EQ: return generate_eq( node, bc, ctx ); case AST_GT: return generate_gt( node, bc, ctx ); case AST_SEQ: return generate_seq( node, bc, ctx ); case AST_IDENTIFIER: return generate_identifier( node, bc, ctx ); diff --git a/dwarf/dwarf-compiler/dwarf-compiler.vcxproj b/dwarf/dwarf-compiler/dwarf-compiler.vcxproj index e2d6154..ecb930c 100755 --- a/dwarf/dwarf-compiler/dwarf-compiler.vcxproj +++ b/dwarf/dwarf-compiler/dwarf-compiler.vcxproj @@ -82,7 +82,7 @@ - + @@ -93,6 +93,7 @@ + diff --git a/dwarf/dwarf-compiler/dwarf-compiler.vcxproj.filters b/dwarf/dwarf-compiler/dwarf-compiler.vcxproj.filters index 2c1a250..6fc77da 100755 --- a/dwarf/dwarf-compiler/dwarf-compiler.vcxproj.filters +++ b/dwarf/dwarf-compiler/dwarf-compiler.vcxproj.filters @@ -39,7 +39,7 @@ Header Files - + Header Files @@ -71,5 +71,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/dwarf/dwarf-compiler/main.c b/dwarf/dwarf-compiler/main.c index 22d9efd..3f44a61 100755 --- a/dwarf/dwarf-compiler/main.c +++ b/dwarf/dwarf-compiler/main.c @@ -9,34 +9,64 @@ static void token_item_print( token_list_t* item ) { token_print( & ( item->token ) ); } + +static char* read_file_by_name( char* name ) { + FILE* input; + char* contents; + input = fopen( name, "r" ); + if( input ) { + contents = read_file( input ); + fclose( input ); + return contents; + } else return NULL; + +} + +void usage( void ) { + fprintf( stderr, "Usage: dwarf-compiler input-file-name output-file-name\n" ); +} int main( int argc, char** argv ) { token_list_t* list; bytecode_builder_t bc; ast_t* tree; - char* program; - FILE* input; + char* program; + FILE* output; + char* input_filename = NULL; + char* output_filename = "out.dwarfvm"; - input = fopen( "program.txt", "r" ); - if (!input) return EXIT_FAILURE; + if (argc != 2 && argc != 3 ) { usage(); return EXIT_FAILURE; } + + if ( argc >= 2 ) input_filename = argv[1]; + if ( argc >= 3 ) output_filename = argv[2]; - program = read_file( input ); - fclose( input ); + program = read_file_by_name( input_filename ); + + if ( program == NULL ) { fprintf( stderr, "Can not read file %s!\n", input_filename ); return EXIT_FAILURE; } list = tokenize( program ); + puts("Tokens:"); token_list_foreach( list, token_item_print ); puts(""); tree = parse( list, program ); + puts("Parsing successful, ast tree: " ); + ast_print( tree, stdout ); + puts( "\nGenerating bytecode:" ); bc = generate_from_ast( tree ); - puts(""); bytecode_prettyprint( bc.first ); - + + output = fopen( output_filename, "wb"); + if (output) + bytecode_flush( bc.first , output); + + else { fprintf( stderr, "Can not write bytecode to file %s!", output_filename); return EXIT_FAILURE; } + free( program ); token_list_free( list ); ast_free( tree ); - //free bytecode? + bytecode_free( bc.first ); } diff --git a/dwarf/dwarf-compiler/parser.c b/dwarf/dwarf-compiler/parser.c index c7c29f9..81729fc 100755 --- a/dwarf/dwarf-compiler/parser.c +++ b/dwarf/dwarf-compiler/parser.c @@ -73,15 +73,9 @@ static ast_t* expression( token_list_t** stream, const char* const code ) { if ( accept( stream, TOK_LT) ) { rhs = expression0( stream, code ); error_if_null( rhs, stream, code ); return ast_lt( lhs, rhs ); - } else if ( accept( stream, TOK_LE) ) { - rhs = expression0( stream, code ); error_if_null( rhs, stream, code ); - return ast_le( lhs, rhs ); } else if ( accept( stream, TOK_EQ) ) { rhs = expression0( stream, code ); error_if_null( rhs, stream, code ); return ast_eq( lhs, rhs ); - } else if ( accept( stream, TOK_GE) ) { - rhs = expression0( stream, code ); error_if_null( rhs, stream, code ); - return ast_ge( lhs, rhs ); } else if ( accept( stream, TOK_GT) ) { rhs = expression0( stream, code ); error_if_null( rhs, stream, code ); return ast_gt( lhs, rhs ); diff --git a/dwarf/dwarf-compiler/tokens.h b/dwarf/dwarf-compiler/tokens.h index a761349..36c2fb9 100755 --- a/dwarf/dwarf-compiler/tokens.h +++ b/dwarf/dwarf-compiler/tokens.h @@ -23,10 +23,8 @@ typedef enum { TOK_MULT, TOK_DIVIDE, - TOK_LE, TOK_LT, - TOK_EQ, - TOK_GE, + TOK_EQ, TOK_GT, TOK_NUM, @@ -55,11 +53,9 @@ static char* token_strings[] = { "*", "/", - "<=", "<", - "==", - ">=", - ">" + "==", + ">", "", "",