From 9161597c13f3d8d9ab894b60d50415da45441f94 Mon Sep 17 00:00:00 2001 From: augustin64 Date: Wed, 3 Jan 2024 18:09:28 +0100 Subject: [PATCH] Analysis: check return value --- src/analysis.cpp | 30 ++++++++++++++++++++++-------- src/errors.cpp | 1 + src/include/errors.h | 1 + 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/analysis.cpp b/src/analysis.cpp index bb81956..6d08c7b 100644 --- a/src/analysis.cpp +++ b/src/analysis.cpp @@ -286,7 +286,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) { if (memory.contains(function_name)) { // Il existe une variable non fonction à ce nom if (memory.get(function_name).type.type != TypeType::Function) { - throw RuntimeError(ErrorType::IncompatibleRedefinition, token.pos, function_name); + throw TypeError(ErrorType::IncompatibleRedefinition, token.pos, function_name); } Type old_type = memory.get(function_name).type; @@ -326,7 +326,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) { if (memory.contains(function_name)) { // Il existe une variable non fonction à ce nom if (memory.get(function_name).type.type != TypeType::Function) { - throw RuntimeError(ErrorType::IncompatibleRedefinition, token.pos, function_name); + throw TypeError(ErrorType::IncompatibleRedefinition, token.pos, function_name); } Type old_type = memory.get(function_name).type; @@ -358,23 +358,37 @@ AnalysisResult analyze(Node &ast, Memory &memory) { if (!memory.contains(function_name)) throw RuntimeError(ErrorType::UnknownIdentifier, token.pos, function_name); - - if (memory.contains(function_name) && !memory.get(function_name).initialized) - throw RuntimeError(ErrorType::UninitializedIdentifier, token.pos, function_name); - MemoryVar function = memory.get(function_name); if (get(node.children[1]).children.size() != get(function.type.data).size()-1) - throw RuntimeError(ErrorType::UnexpectedArgumentCount, token.pos, int(get(function.type.data).size())-1); + throw TypeError(ErrorType::UnexpectedArgumentCount, token.pos, int(get(function.type.data).size())-1); return get<0>(get(function.type.data).at(0)); } break; case NodeType::Return: { + MemoryVar function; try { - memory.get_function_scope(); + function = *memory.get_function_scope().fn; } catch (const InternalError& _) { throw RuntimeError(ErrorType::UnexpectedReturn, node.pos, {}); } + + FunctionPrototype prototype = get(function.type.data); + Type return_type = get<0>(prototype.at(0)); + if (return_type.type == TypeType::Void) { + if (node.children.size() != 0) + throw TypeError(ErrorType::IncompatibleReturnValue, node.pos, {}); + return {}; + } + + if (node.children.size() == 0) + throw TypeError(ErrorType::IncompatibleReturnValue, node.pos, {}); + + AnalysisResult res = analyze(node.children[0], memory); + AnalysisResult expected_type = return_type; + + get_cast(res, expected_type, node.pos); + return {}; } default: diff --git a/src/errors.cpp b/src/errors.cpp index 4b9af77..ee00a51 100644 --- a/src/errors.cpp +++ b/src/errors.cpp @@ -30,6 +30,7 @@ string UserError::get_message(void) const { case ErrorType::IncompatibleDefinition: return "Declaration of '"+get(this->data)+"' is incompatible with previous prototype"; case ErrorType::UnexpectedArgumentCount: return "Expected "+to_string(get(this->data))+" arguments to function call"; case ErrorType::UnexpectedReturn: return "Return not within a function"; + case ErrorType::IncompatibleReturnValue: return "Return value type does not match the function type"; case ErrorType::ExpectedArithmeticType: return "Expression must have arithmetic type"; case ErrorType::UnknownIdentifier: return "Unknown identifier '"+get(this->data)+"'"; case ErrorType::AlreadyDeclaredIdentifier: return "Already declared identifier '"+get(this->data)+"'"; diff --git a/src/include/errors.h b/src/include/errors.h index 62e0a59..8319148 100644 --- a/src/include/errors.h +++ b/src/include/errors.h @@ -39,6 +39,7 @@ enum class ErrorType { IncompatibleDefinition, // function declaration incompatible with prototype UnexpectedArgumentCount, UnexpectedReturn, + IncompatibleReturnValue, // Runtime UnknownIdentifier,