From bb5ea0f095eb39df8ee8917a7a09b6a34b867386 Mon Sep 17 00:00:00 2001 From: Jaroslav Louma Date: Wed, 29 Nov 2023 14:03:40 +0100 Subject: [PATCH] Added ability to revert implicit type conversions --- include/compiler/parser/ASTNodes.h | 2 + src/compiler/analyser/Analyser.c | 22 +++++--- src/compiler/parser/ASTNodes.c | 2 + test/compiler/analyser/Analyser.test.c | 76 +++++++++++++++++++++++--- 4 files changed, 86 insertions(+), 16 deletions(-) diff --git a/include/compiler/parser/ASTNodes.h b/include/compiler/parser/ASTNodes.h index 849dc14..e0634c1 100644 --- a/include/compiler/parser/ASTNodes.h +++ b/include/compiler/parser/ASTNodes.h @@ -221,6 +221,8 @@ typedef struct LiteralExpressionASTNode { enum ASTNodeType _type; union TokenValue value; struct ValueType type; + union TokenValue originalValue; + struct ValueType originalType; } LiteralExpressionASTNode; typedef struct InterpolationExpressionASTNode { diff --git a/src/compiler/analyser/Analyser.c b/src/compiler/analyser/Analyser.c index ed749cf..964e356 100644 --- a/src/compiler/analyser/Analyser.c +++ b/src/compiler/analyser/Analyser.c @@ -933,11 +933,17 @@ AnalyserResult Analyser_resolveExpressionType(Analyser *analyser, ExpressionASTN LiteralExpressionASTNode *literal = (LiteralExpressionASTNode*)node; // Can only retype int literals to double - if(prefferedType.type == TYPE_DOUBLE && literal->type.type == TYPE_INT) { - literal->value.floating = (double)literal->value.integer; + if(prefferedType.type == TYPE_DOUBLE && literal->originalType.type == TYPE_INT) { + literal->value.floating = (double)literal->originalValue.integer; literal->type.type = TYPE_DOUBLE; } + // Revert implicit type conversions + if(prefferedType.type == TYPE_INT && literal->originalType.type == TYPE_INT) { + literal->value = literal->originalValue; + literal->type = literal->originalType; + } + *outType = literal->type; } break; @@ -1326,10 +1332,10 @@ AnalyserResult Analyser_resolveExpressionType(Analyser *analyser, ExpressionASTN binary->left->_type == NODE_LITERAL_EXPRESSION && leftType.type == TYPE_INT && rightType.type == TYPE_DOUBLE ) { - LiteralExpressionASTNode *literal = (LiteralExpressionASTNode*)binary->left; + // LiteralExpressionASTNode *literal = (LiteralExpressionASTNode*)binary->left; - literal->value.floating = (double)literal->value.integer; - literal->type.type = TYPE_DOUBLE; + // literal->value.floating = (double)literal->value.integer; + // literal->type.type = TYPE_DOUBLE; binary->type.type = TYPE_DOUBLE; } else if( @@ -1337,10 +1343,10 @@ AnalyserResult Analyser_resolveExpressionType(Analyser *analyser, ExpressionASTN binary->right->_type == NODE_LITERAL_EXPRESSION && leftType.type == TYPE_DOUBLE && rightType.type == TYPE_INT ) { - LiteralExpressionASTNode *literal = (LiteralExpressionASTNode*)binary->right; + // LiteralExpressionASTNode *literal = (LiteralExpressionASTNode*)binary->right; - literal->value.floating = (double)literal->value.integer; - literal->type.type = TYPE_DOUBLE; + // literal->value.floating = (double)literal->value.integer; + // literal->type.type = TYPE_DOUBLE; binary->type.type = TYPE_DOUBLE; } else { diff --git a/src/compiler/parser/ASTNodes.c b/src/compiler/parser/ASTNodes.c index f36d257..fb0f2cf 100644 --- a/src/compiler/parser/ASTNodes.c +++ b/src/compiler/parser/ASTNodes.c @@ -240,6 +240,8 @@ LiteralExpressionASTNode* new_LiteralExpressionASTNode( prepare_node_of(LiteralExpressionASTNode, NODE_LITERAL_EXPRESSION) node->type = type; node->value = value; + node->originalType = type; + node->originalValue = value; return node; } diff --git a/test/compiler/analyser/Analyser.test.c b/test/compiler/analyser/Analyser.test.c index 3548699..052c62c 100644 --- a/test/compiler/analyser/Analyser.test.c +++ b/test/compiler/analyser/Analyser.test.c @@ -3720,17 +3720,17 @@ DESCRIBE(return_reachability, "Return reachability analysis") { } DESCRIBE(type_conversion, "Implicit type conversion") { - // Lexer lexer; - // Lexer_constructor(&lexer); + Lexer lexer; + Lexer_constructor(&lexer); - // Parser parser; - // Parser_constructor(&parser, &lexer); + Parser parser; + Parser_constructor(&parser, &lexer); - // Analyser analyser; - // Analyser_constructor(&analyser); + Analyser analyser; + Analyser_constructor(&analyser); - // ParserResult parserResult; - // AnalyserResult analyserResult; + ParserResult parserResult; + AnalyserResult analyserResult; // TEST_BEGIN("Conversion of literals inside a complex expression") { // Lexer_setSource( @@ -3743,6 +3743,66 @@ DESCRIBE(type_conversion, "Implicit type conversion") { // analyserResult = Analyser_analyse(&analyser, (ProgramASTNode*)parserResult.node); // EXPECT_TRUE(analyserResult.success); // } TEST_END(); + + TEST_BEGIN("Conversion of literals inside a complex expression") { + Lexer_setSource( + &lexer, + "var a: Double = 5" LF + ); + parserResult = Parser_parse(&parser); + EXPECT_TRUE(parserResult.success); + + analyserResult = Analyser_analyse(&analyser, (ProgramASTNode*)parserResult.node); + EXPECT_TRUE(analyserResult.success); + + EXPECT_STATEMENTS(parserResult.node, 1 + FUNCTIONS_COUNT); + + VariableDeclaration *var = Analyser_getVariableByName(&analyser, "a", analyser.globalScope); + EXPECT_NOT_NULL(var); + + LiteralExpressionASTNode *literal = (LiteralExpressionASTNode*)var->node->initializer; + EXPECT_NOT_NULL(literal); + EXPECT_TRUE(literal->_type == NODE_LITERAL_EXPRESSION); + + EXPECT_TRUE(literal->type.type == TYPE_DOUBLE); + EXPECT_EQUAL_FLOAT(literal->value.floating, 5); + } TEST_END(); + + TEST_BEGIN("Conversion of literals inside a complex expression") { + Lexer_setSource( + &lexer, + "var a: Double = 5.5" LF + ); + parserResult = Parser_parse(&parser); + EXPECT_TRUE(parserResult.success); + + analyserResult = Analyser_analyse(&analyser, (ProgramASTNode*)parserResult.node); + EXPECT_TRUE(analyserResult.success); + + EXPECT_STATEMENTS(parserResult.node, 1 + FUNCTIONS_COUNT); + + VariableDeclaration *var = Analyser_getVariableByName(&analyser, "a", analyser.globalScope); + EXPECT_NOT_NULL(var); + + LiteralExpressionASTNode *literal = (LiteralExpressionASTNode*)var->node->initializer; + EXPECT_NOT_NULL(literal); + EXPECT_TRUE(literal->_type == NODE_LITERAL_EXPRESSION); + + EXPECT_TRUE(literal->type.type == TYPE_DOUBLE); + EXPECT_EQUAL_FLOAT(literal->value.floating, 5.5); + } TEST_END(); + + TEST_BEGIN("Conversion of literals inside a complex expression") { + Lexer_setSource( + &lexer, + "var a: Int = 5.5" LF + ); + parserResult = Parser_parse(&parser); + EXPECT_TRUE(parserResult.success); + + analyserResult = Analyser_analyse(&analyser, (ProgramASTNode*)parserResult.node); + EXPECT_FALSE(analyserResult.success); + } TEST_END(); } DESCRIBE(str_interp_analysis, "String interpolation analysis") {