Merge branch 'main' of gitlab.aliens-lyon.fr:alucas03/c-repl into main
This commit is contained in:
commit
9749b13253
@ -214,6 +214,9 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
|||||||
throw TypeError(ErrorType::AlreadyDeclaredIdentifier, token.pos, identifier);
|
throw TypeError(ErrorType::AlreadyDeclaredIdentifier, token.pos, identifier);
|
||||||
|
|
||||||
Type type = try_string_to_type(type_string, type_token.pos);
|
Type type = try_string_to_type(type_string, type_token.pos);
|
||||||
|
if (type.type == TypeType::Void)
|
||||||
|
throw TypeError(ErrorType::IncompleteType, token.pos, {});
|
||||||
|
|
||||||
memory.declare(identifier, type);
|
memory.declare(identifier, type);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
@ -229,6 +232,9 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
|||||||
throw TypeError(ErrorType::AlreadyDeclaredIdentifier, token.pos, identifier);
|
throw TypeError(ErrorType::AlreadyDeclaredIdentifier, token.pos, identifier);
|
||||||
|
|
||||||
Type type = try_string_to_type(type_string, type_token.pos);
|
Type type = try_string_to_type(type_string, type_token.pos);
|
||||||
|
if (type.type == TypeType::Void)
|
||||||
|
throw TypeError(ErrorType::IncompleteType, token.pos, {});
|
||||||
|
|
||||||
memory.declare(identifier, type);
|
memory.declare(identifier, type);
|
||||||
|
|
||||||
get_cast(type, analyze(node.children[2], memory), get_node_pos(node));
|
get_cast(type, analyze(node.children[2], memory), get_node_pos(node));
|
||||||
@ -295,6 +301,15 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i=1; i < (int)prototype.size(); i++) {
|
||||||
|
if (get<0>(prototype.at(i)).type == TypeType::Void) {
|
||||||
|
InnerNode args_node = get<InnerNode>(node.children[2]);
|
||||||
|
InnerNode declaration_node = get<InnerNode>(args_node.children[i-1]);
|
||||||
|
CodePosition type_pos = get_node_pos(declaration_node.children[0]);
|
||||||
|
throw TypeError(ErrorType::IncompleteType, type_pos, {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
memory.declare(function_name, type);
|
memory.declare(function_name, type);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
@ -335,6 +350,15 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i=1; i < (int)prototype.size(); i++) {
|
||||||
|
if (get<0>(prototype.at(i)).type == TypeType::Void) {
|
||||||
|
InnerNode args_node = get<InnerNode>(node.children[2]);
|
||||||
|
InnerNode declaration_node = get<InnerNode>(args_node.children[i-1]);
|
||||||
|
CodePosition type_pos = get_node_pos(declaration_node.children[0]);
|
||||||
|
throw TypeError(ErrorType::IncompleteType, type_pos, {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
memory.declare(function_name, type);
|
memory.declare(function_name, type);
|
||||||
|
|
||||||
Function fn = { {}, memory.make_closure() };
|
Function fn = { {}, memory.make_closure() };
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
#include "include/utils.h"
|
||||||
#include "include/errors.h"
|
#include "include/errors.h"
|
||||||
#include "include/colors.h"
|
#include "include/colors.h"
|
||||||
#include "include/tokenize.h"
|
#include "include/tokenize.h"
|
||||||
@ -44,6 +46,7 @@ string UserError::get_message(void) const {
|
|||||||
case ErrorType::IncompatibleDefinition: return "Declaration of '"+get<string>(this->data)+"' is incompatible with previous prototype";
|
case ErrorType::IncompatibleDefinition: return "Declaration of '"+get<string>(this->data)+"' is incompatible with previous prototype";
|
||||||
case ErrorType::UnexpectedArgumentCount: return "Expected "+to_string(get<int>(this->data))+" arguments to function call";
|
case ErrorType::UnexpectedArgumentCount: return "Expected "+to_string(get<int>(this->data))+" arguments to function call";
|
||||||
case ErrorType::IncompatibleReturnValue: return "Return value type does not match the function type";
|
case ErrorType::IncompatibleReturnValue: return "Return value type does not match the function type";
|
||||||
|
case ErrorType::IncompleteType: return "Incomplete type is not allowed";
|
||||||
|
|
||||||
// Runtime
|
// Runtime
|
||||||
case ErrorType::UnknownIdentifier: return "Unknown identifier '"+get<string>(this->data)+"'";
|
case ErrorType::UnknownIdentifier: return "Unknown identifier '"+get<string>(this->data)+"'";
|
||||||
@ -60,14 +63,27 @@ void print_error_position(vector<string> history, CodePosition pos) {
|
|||||||
if (pos.column == -1 || pos.line == -1)
|
if (pos.column == -1 || pos.line == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cout << endl;
|
cout << endl << BOLD
|
||||||
string line = history[pos.line];
|
<< setw(4) << setfill(' ')
|
||||||
|
<< pos.line+1 << " " RESET
|
||||||
printf(BOLD "%4d " RESET , pos.line+1);
|
<< history[pos.line] << endl;
|
||||||
cout << line << endl;
|
|
||||||
|
|
||||||
for (int i=0; i < pos.column + 5; i++)
|
for (int i=0; i < pos.column + 5; i++)
|
||||||
cout << " ";
|
cout << " ";
|
||||||
|
|
||||||
cout << BOLD RED "^--" RESET << endl;
|
cout << BOLD RED "^--" RESET << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_error_stack_trace(vector<string> history, const RuntimeError& error) {
|
||||||
|
cout << "\n" BOLD "Traceback" RESET " (most recent call last)" << endl;
|
||||||
|
for (StackTraceEntry e : error.trace) {
|
||||||
|
cout << BOLD << setw(8) << setfill(' ')
|
||||||
|
<< to_string(get<1>(e).line+1) + ":" + to_string(get<1>(e).column+1)
|
||||||
|
<< RESET BLUE
|
||||||
|
<< setw(16) << setfill(' ')
|
||||||
|
<< get<0>(e) << RESET << " \t"
|
||||||
|
<< trim(history[get<1>(e).line]) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << BOLD RED "Runtime Error: " RESET << error.get_message() << endl;
|
||||||
|
}
|
@ -45,6 +45,7 @@ enum class ErrorType {
|
|||||||
IncompatibleDefinition, // function declaration incompatible with prototype
|
IncompatibleDefinition, // function declaration incompatible with prototype
|
||||||
UnexpectedArgumentCount,
|
UnexpectedArgumentCount,
|
||||||
IncompatibleReturnValue,
|
IncompatibleReturnValue,
|
||||||
|
IncompleteType, // void x
|
||||||
|
|
||||||
// Runtime
|
// Runtime
|
||||||
UnknownIdentifier,
|
UnknownIdentifier,
|
||||||
@ -115,4 +116,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
void print_error_position(vector<string> history, CodePosition pos);
|
void print_error_position(vector<string> history, CodePosition pos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the stack trace associated with an error
|
||||||
|
*/
|
||||||
|
void print_error_stack_trace(vector<string> history, const RuntimeError& error);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -39,4 +39,9 @@ string _debug_get_type_type_name(TypeType type);
|
|||||||
*/
|
*/
|
||||||
bool equal_types(Type type1, Type type2);
|
bool equal_types(Type type1, Type type2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trim a string (remove whitespaces before and after)
|
||||||
|
*/
|
||||||
|
string trim(const string& str);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -119,12 +119,7 @@ int main(int argc, char* argv[]) {
|
|||||||
cout << BOLD RED "Type Error: " RESET << e.get_message() << endl;
|
cout << BOLD RED "Type Error: " RESET << e.get_message() << endl;
|
||||||
|
|
||||||
} catch (const RuntimeError& e) {
|
} catch (const RuntimeError& e) {
|
||||||
print_error_position(input, e.pos);
|
print_error_stack_trace(input, e);
|
||||||
cout << BOLD RED "Runtime Error: " RESET << e.get_message() << endl;
|
|
||||||
|
|
||||||
for (StackTraceEntry e : e.trace) {
|
|
||||||
cout << get<0>(e) << " " << (get<1>(e).line + 1) << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cout << endl;
|
cout << endl;
|
||||||
}
|
}
|
||||||
|
@ -112,3 +112,13 @@ bool equal_types(Type type1, Type type2) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string trim(const string& str) {
|
||||||
|
size_t first = str.find_first_not_of(" \t\n\r");
|
||||||
|
size_t last = str.find_last_not_of(" \t\n\r");
|
||||||
|
|
||||||
|
if (first == string::npos || last == string::npos)
|
||||||
|
return ""; // or handle empty string
|
||||||
|
|
||||||
|
return str.substr(first, last - first + 1);
|
||||||
|
}
|
@ -98,5 +98,17 @@ int main() {
|
|||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
_TEST_ASSERT(
|
||||||
|
_TEST_IS_EXCEPTION(execute("int f(int x, void y);"), ErrorType::IncompleteType),
|
||||||
|
"Argument void (prototype)",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
_TEST_ASSERT(
|
||||||
|
_TEST_IS_EXCEPTION(execute("int f(int x, void y) { return x+2; };"), ErrorType::IncompleteType),
|
||||||
|
"Argument void (déclaration)",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -35,6 +35,12 @@ int main() {
|
|||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
_TEST_ASSERT(
|
||||||
|
_TEST_IS_EXCEPTION(execute("void x;"), ErrorType::IncompleteType),
|
||||||
|
"Type void",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
_TEST_ASSERT(
|
_TEST_ASSERT(
|
||||||
_TEST_NO_EXCEPTION(holds_alternative<monostate>(execute("int x; { int x; }"))),
|
_TEST_NO_EXCEPTION(holds_alternative<monostate>(execute("int x; { int x; }"))),
|
||||||
"Identifieur déjà défini dans une autre scope",
|
"Identifieur déjà défini dans une autre scope",
|
||||||
|
Loading…
Reference in New Issue
Block a user