diff --git a/compiler/compiler.c b/compiler/compiler.c index e8c7dd1..00d8b9e 100644 --- a/compiler/compiler.c +++ b/compiler/compiler.c @@ -26,22 +26,14 @@ void set_current_compiler(Compiler *compiler) st_current_compiler = compiler; } -void add_definitions_to_compiler(DefinitionList *definitions) +void add_func_definition_to_compiler(FuncDefinition *func_definition) { Compiler *compiler = get_current_compiler(); - for (DefinitionList *pos = definitions; pos != NULL; pos = pos->next) - { - switch (pos->definition->kind) - { - case FUNC_DEFINITION: - compiler->func_definition_list = chain_func_definition_list( - compiler->func_definition_list, pos->definition->u.func_d); - break; - case DECLARATION_DEFINITION: - compiler->declaration_list = chain_declaration_list( - compiler->declaration_list, pos->definition->u.declaration); - default: - break; - } - } + compiler->func_definition_list = chain_func_definition_list(compiler->func_definition_list, func_definition); +} + +void add_stmt_to_compiler(Statement *stmt) +{ + Compiler *compiler = get_current_compiler(); + compiler->stmt_list = chain_stmt_list(compiler->stmt_list, stmt); } diff --git a/compiler/create.c b/compiler/create.c index 02b3a04..877aa26 100644 --- a/compiler/create.c +++ b/compiler/create.c @@ -270,27 +270,21 @@ ParameterList *chain_parameter(ParameterList *list, ParameterList *parameter) return list; } -Definition *alloc_definition(DefinitionKind kind) -{ - Definition *definition = (Definition *)malloc(sizeof(Definition)); - definition->kind = kind; - return definition; -} - -Definition *alloc_func_definition(char *name, ParameterList *parameters, TypeSpecifier *return_type, Block *block) +FuncDefinition *alloc_func_definition(char *name, ParameterList *parameters, TypeSpecifier *return_type, Block *block) { FuncDefinition *func_d = (FuncDefinition *)malloc(sizeof(FuncDefinition)); func_d->name = name; func_d->parameters = parameters; func_d->return_type = return_type; + if (!return_type) + { + func_d->return_type = alloc_type_specifier(VOID_TYPE); + } func_d->block = block; func_d->local_variable_count = 0; func_d->local_variable = NULL; func_d->next = NULL; - - Definition *definition = alloc_definition(FUNC_DEFINITION); - definition->u.func_d = func_d; - return definition; + return func_d; } FuncDefinition *chain_func_definition_list(FuncDefinition *list, FuncDefinition *next) @@ -308,35 +302,6 @@ FuncDefinition *chain_func_definition_list(FuncDefinition *list, FuncDefinition return list; } -Definition *alloc_declaration_definition(Statement *declaration_stmt) -{ - Definition *definition = alloc_definition(DECLARATION_DEFINITION); - definition->u.declaration = declaration_stmt->u.decl_s; - return definition; -} - -DefinitionList *alloc_definition_list(Definition *definition) -{ - DefinitionList *list = (DefinitionList *)malloc(sizeof(DefinitionList)); - list->definition = definition; - list->next = NULL; - return list; -} - -DefinitionList *chain_definition_list(DefinitionList *list, Definition *definition) -{ - if (list == NULL) - { - list->next = alloc_definition_list(definition); - return list; - } - DefinitionList *pos; - for (pos = list; pos->next; pos = pos->next) - ; - pos->next = alloc_definition_list(definition); - return list; -} - Declaration *chain_declaration_list(Declaration *list, Declaration *next) { if (list == NULL) diff --git a/compiler/error.c b/compiler/error.c index 902f3d4..669b3e0 100644 --- a/compiler/error.c +++ b/compiler/error.c @@ -129,6 +129,8 @@ static ErrorDefinition dkc_error_message_format[] = { {"字符字面量中包含了2个以上的字符。"}, {"类型转换不匹配。"}, {"函数调用类型不匹配。"}, + {"变量声明类型与表达式类型不匹配。"}, + {"返回值类型不匹配."}, {"dummy"}}; typedef struct diff --git a/compiler/error.h b/compiler/error.h index b2b0832..c77f5dc 100644 --- a/compiler/error.h +++ b/compiler/error.h @@ -132,6 +132,8 @@ typedef enum TOO_LONG_CHARACTER_LITERAL_ERR, TYPE_CAST_MISMATH_ERR, FUNCTION_CALL_TYPE_MISMATCH_ERR, + DECLARATION_TYPE_MISMATCH_ERR, + RETURN_TYPE_MISMATCH_ERR, COMPILE_ERROR_COUNT_PLUS_1, } CompileError; diff --git a/compiler/fix_tree.c b/compiler/fix_tree.c index 8748be7..7923f40 100644 --- a/compiler/fix_tree.c +++ b/compiler/fix_tree.c @@ -8,9 +8,22 @@ extern BuiltinFun *search_builtin_function(char *name); static Expression *fix_expression(Block *current_block, Expression *expr); +static void fix_statement_list(Block *current_block, StatementList *list, FuncDefinition *fd); -Declaration * -search_declaration(char *identifier, Block *block) +Declaration *search_declaration_in_current_block(char *identifier, Block *block) +{ + Declaration *d_pos; + for (d_pos = block->declaration_list; d_pos; d_pos = d_pos->next) + { + if (!strcmp(identifier, d_pos->name)) + { + return d_pos; + } + } + return NULL; +} + +Declaration *search_declaration(char *identifier, Block *block) { Block *b_pos; Declaration *d_pos; @@ -589,6 +602,28 @@ fix_function_call_expression(Block *current_block, Expression *expr) return expr; } +static Expression *init_expression(BasicType basic_type) +{ + switch (basic_type) + { + case AMOUNT_TYPE: + case INT_TYPE: + return alloc_int_expression(0); + case DOUBLE_TYPE: + return alloc_double_expression(0); + case STRING_TYPE: + case ASSET_TYPE: + case HASH_TYPE: + case PUBKEY_TYPE: + case SIG_TYPE: + case HEX_TYPE: + return alloc_string_expression(""); + default: + DBG_assert(0, ("bad case. type..%d\n", basic_type)); + } + return NULL; +} + static Expression * fix_expression(Block *current_block, Expression *expr) { @@ -648,8 +683,9 @@ fix_expression(Block *current_block, Expression *expr) return expr; } -static void add_local_variable(FuncDefinition *fd, Declaration *decl, - bool is_parameter) +static void +add_local_variable(FuncDefinition *fd, Declaration *decl, + bool is_parameter) { fd->local_variable = realloc(fd->local_variable, sizeof(Declaration *) * (fd->local_variable_count + 1)); @@ -663,7 +699,7 @@ add_declaration(Block *current_block, Declaration *decl, FuncDefinition *fd, int line_number, bool is_parameter) { - if (search_declaration(decl->name, current_block)) + if (search_declaration_in_current_block(decl->name, current_block)) { compile_error(line_number, VARIABLE_MULTIPLE_DEFINE_ERR, @@ -686,29 +722,145 @@ add_declaration(Block *current_block, Declaration *decl, } } -static void fix_declaration_stmt(Declaration *decl, Block *current_block) +static void +fix_if_statement(Block *current_block, IfStatement *if_s, FuncDefinition *fd) +{ + if_s->condition = fix_expression(current_block, if_s->condition); + if (if_s->condition->type->basic_type != BOOLEAN_TYPE) + { + compile_error(if_s->condition->line_number, + IF_CONDITION_NOT_BOOLEAN_ERR, + MESSAGE_ARGUMENT_END); + } + + fix_statement_list(if_s->then_block, if_s->then_block->statement_list, fd); + + for (Elseif *pos = if_s->elseif_list; pos; pos = pos->next) + { + pos->condition = fix_expression(current_block, pos->condition); + if (pos->block) + { + fix_statement_list(pos->block, pos->block->statement_list, fd); + } + } + if (if_s->else_block) + { + fix_statement_list(if_s->else_block, if_s->else_block->statement_list, fd); + } +} + +static void +fix_return_statement(Block *current_block, Statement *statement, FuncDefinition *fd) { - add_declaration(current_block, decl, NULL, 0, false); + Expression *return_value = fix_expression(current_block, statement->u.expr_s); + if (fd->return_type->basic_type == VOID_TYPE && return_value != NULL) + { + compile_error(statement->line_number, + RETURN_IN_VOID_FUNCTION_ERR, + MESSAGE_ARGUMENT_END); + } + if (fd->return_type->basic_type != VOID_TYPE) + { + if (return_value == NULL || return_value->type->basic_type != fd->return_type->basic_type) + compile_error(statement->line_number, + RETURN_TYPE_MISMATCH_ERR, + MESSAGE_ARGUMENT_END); + } + + statement->u.expr_s = return_value; +} + +static void +fix_declaration_stmt(Statement *stmt, Block *current_block, FuncDefinition *fd) +{ + Declaration *decl = stmt->u.decl_s; + add_declaration(current_block, decl, fd, stmt->line_number, false); if (decl->initializer) { decl->initializer = fix_expression(current_block, decl->initializer); - // decl->initializer = create_assign_cast(decl->initializer, decl->type); + if (!decl->type) + { + decl->type = decl->initializer->type; + } + else if (decl->initializer->kind == INT_EXPRESSION && decl->type->basic_type == DOUBLE_TYPE) + { + decl->initializer->kind = DOUBLE_EXPRESSION; + decl->initializer->type->basic_type = DOUBLE_TYPE; + decl->initializer->u.double_value = decl->initializer->u.int_value; + } + else if (decl->initializer->type->basic_type != decl->type->basic_type) + { + compile_error(stmt->line_number, + DECLARATION_TYPE_MISMATCH_ERR, + MESSAGE_ARGUMENT_END); + } + } + else + { + decl->initializer = init_expression(decl->type->basic_type); + } +} + +static void +fix_statement(Block *current_block, Statement *statement, FuncDefinition *fd) +{ + switch (statement->kind) + { + case IF_STATEMENT: + fix_if_statement(current_block, statement->u.if_s, fd); + break; + case RETURN_STATEMENT: + fix_return_statement(current_block, statement, fd); + break; + case DECLARATION_STATEMENT: + fix_declaration_stmt(statement, current_block, fd); + break; + default: + DBG_assert(0, ("bad case. kind..%d\n", statement->kind)); + } +} + +static void +fix_statement_list(Block *current_block, StatementList *list, FuncDefinition *fd) +{ + StatementList *pos; + + for (pos = list; pos; pos = pos->next) + { + fix_statement(current_block, pos->statement, fd); + } +} + +static void +add_parameter_as_declaration(FuncDefinition *fd) +{ + Declaration *decl; + ParameterList *param; + + for (param = fd->parameters; param; param = param->next) + { + decl = alloc_declaration(param->name, param->type, NULL); + if (fd->block) + { + add_declaration(fd->block, decl, fd, param->line_number, true); + } } } static void fix_function(FuncDefinition *fd) { + add_parameter_as_declaration(fd); + if (fd->block) + { + fix_statement_list(fd->block, fd->block->statement_list, fd); + } } void fix_tree(Compiler *compiler) { FuncDefinition *func_pos; - Declaration *decl_pos; - for (decl_pos = compiler->declaration_list; decl_pos; decl_pos = decl_pos->next) - { - fix_declaration_stmt(decl_pos, NULL); - } + fix_statement_list(NULL, compiler->stmt_list, NULL); for (func_pos = compiler->func_definition_list; func_pos; func_pos = func_pos->next) { diff --git a/compiler/grammar.y b/compiler/grammar.y index d277783..18ca7b9 100644 --- a/compiler/grammar.y +++ b/compiler/grammar.y @@ -18,10 +18,9 @@ int yyerror(const char *s); struct StatementList *statement_list; struct Block *block; struct Elseif *elseif; + struct FuncDefinition *func_definition; struct TypeSpecifier *type_specifier; struct ParameterList *parameter_list; - struct Definition *definition; - struct DefinitionList *definition_list; struct ArgumentList *argument_list; } @@ -38,10 +37,9 @@ int yyerror(const char *s); %type stmt_list %type block %type elseif elseif_list +%type func_definition %type type_specifier %type parameter_list paramter -%type definition func_definition variable_definition const_definition -%type definition_list %type argument_list %nonassoc '=' ADD_ASSIGN SUB_ASSIGN MUL_ASSIGN DIV_ASSIGN DECL_ASSIGN @@ -55,20 +53,11 @@ int yyerror(const char *s); %% -translation_unit: - new_line_option definition_list new_line_option { add_definitions_to_compiler($2); } - ; - -definition_list: - definition { $$ = alloc_definition_list($1); } - | definition_list new_line definition { $$ = chain_definition_list($1, $3); } - ; - -definition: - func_definition - | const_definition - | variable_definition - ; +definition_or_stmt: + func_definition { add_func_definition_to_compiler($1); } + | const_stmt { add_stmt_to_compiler($1); } + | variable_declaration_stmt { add_stmt_to_compiler($1); } + ; func_definition: FUNCTION IDENTIFIER '(' parameter_list ')' type_specifier block { $$ = alloc_func_definition($2, $4, $6, $7); } @@ -77,14 +66,6 @@ func_definition: | FUNCTION IDENTIFIER '(' ')' block { $$ = alloc_func_definition($2, NULL, NULL, $5); } ; -variable_definition: - variable_declaration_stmt { $$ = alloc_declaration_definition($1); } - ; - -const_definition: - const_stmt { $$ = alloc_declaration_definition($1); } - ; - parameter_list: paramter | parameter_list ',' paramter { $$ = chain_parameter($1, $3); } diff --git a/compiler/summoner.h b/compiler/summoner.h index c868233..7cfbe3c 100644 --- a/compiler/summoner.h +++ b/compiler/summoner.h @@ -155,6 +155,7 @@ typedef struct AssignStatement typedef struct Statement { StatementKind kind; + int line_number; union { struct AssignStatement *assign_s; @@ -216,6 +217,7 @@ typedef struct ParameterList { char *name; TypeSpecifier *type; + int line_number; struct ParameterList *next; } ParameterList; @@ -230,22 +232,6 @@ typedef enum STRUCT_DEFINITION, } DefinitionKind; -typedef struct DefinitionList -{ - struct Definition *definition; - struct DefinitionList *next; -} DefinitionList; - -typedef struct Definition -{ - DefinitionKind kind; - union - { - struct FuncDefinition *func_d; - struct Declaration *declaration; - } u; -} Definition; - typedef struct FuncDefinition { char *name; @@ -257,12 +243,9 @@ typedef struct FuncDefinition struct FuncDefinition *next; } FuncDefinition; -Definition *alloc_func_definition(char *name, ParameterList *parameters, TypeSpecifier *return_type, Block *block); +FuncDefinition *alloc_func_definition(char *name, ParameterList *parameters, TypeSpecifier *return_type, Block *block); FuncDefinition *chain_func_definition_list(FuncDefinition *list, FuncDefinition *next); -Definition *alloc_declaration_definition(Statement *declaration_stmt); Declaration *chain_declaration_list(Declaration *list, Declaration *declaration); -DefinitionList *alloc_definition_list(Definition *definition); -DefinitionList *chain_definition_list(DefinitionList *list, Definition *definition); typedef wchar_t SVM_Char; typedef unsigned char SVM_Byte; @@ -338,6 +321,7 @@ typedef struct Compiler SVM_Constant *svm_constant; int function_count; FuncDefinition *func_definition_list; + StatementList *stmt_list; Block *current_block; Declaration *declaration_list; int current_line_number; @@ -346,7 +330,8 @@ typedef struct Compiler Compiler *create_compiler(); Compiler *get_current_compiler(); void set_current_compiler(Compiler *compiler); -void add_definitions_to_compiler(DefinitionList *definitions); +void add_stmt_to_compiler(Statement *stmt); +void add_func_definition_to_compiler(FuncDefinition *func_definition); typedef struct SVM_Executable { diff --git a/interpreter/eval.cpp b/interpreter/eval.cpp index 8c46e4d..70e5ddf 100644 --- a/interpreter/eval.cpp +++ b/interpreter/eval.cpp @@ -209,16 +209,17 @@ ExprValue Interpreter::eval_expression(Expression *expr) case FUNC_CALL_EXPRESSION: { FuncCallExpression *func_call_expr = expr->u.func_call_expression; - FuncDefinition *func_d = this->find_func_definition(func_call_expr->identifier); + const char *func_identifier = func_call_expr->function->u.identifier->name; + FuncDefinition *func_d = this->find_func_definition(func_identifier); if (func_d == nullptr) { - cout << "func \"" << func_call_expr->identifier << "\" is undefined" << endl; + cout << "func \"" << func_identifier << "\" is undefined" << endl; exit(1); } return *(this->eval_func(func_d, func_call_expr->argument_list)); } case IDENTIFIER_EXPRESSION: - return this->current_scope->find_identifier(expr->u.identifier)->get_value(); + return this->current_scope->find_identifier(expr->u.identifier->name)->get_value(); default: printf("invalid expression type when eval expression:%d\n", expr->kind); exit(1); @@ -308,10 +309,11 @@ StmtResult Interpreter::eval_stmt(Statement *stmt) case ASSIGN_STATEMENT: { AssignStatement *assign_s = stmt->u.assign_s; - Identifier *identifier = this->current_scope->find_identifier(assign_s->variable); + char *identifier_name = assign_s->left->u.identifier->name; + Identifier *identifier = this->current_scope->find_identifier(identifier_name); if (identifier == nullptr) { - cout << "\"" << assign_s->variable << "\" is undefined" << endl; + cout << "\"" << identifier_name << "\" is undefined" << endl; exit(1); } if (identifier->get_is_const())