Add casting.cpp
This commit is contained in:
parent
553c820a8a
commit
cc218d0834
103
src/analysis.cpp
103
src/analysis.cpp
@ -1,53 +1,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "include/utils.hpp"
|
|
||||||
#include "include/errors.hpp"
|
#include "include/errors.hpp"
|
||||||
#include "include/analysis.hpp"
|
#include "include/analysis.hpp"
|
||||||
|
#include "include/casting.hpp"
|
||||||
|
|
||||||
bool bool_castable(AnalysisResult type) {
|
|
||||||
(void)type;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_comparable(AnalysisResult res1, AnalysisResult res2, CodePosition pos) {
|
|
||||||
if (holds_alternative<monostate>(res1) || holds_alternative<monostate>(res2)) {
|
|
||||||
throw TypeError(ErrorType::TypesNotComparable, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
Type type1 = get<Type>(res1);
|
|
||||||
Type type2 = get<Type>(res2);
|
|
||||||
|
|
||||||
|
|
||||||
switch (type1.type) {
|
|
||||||
case TypeType::Int:
|
|
||||||
case TypeType::Double: {
|
|
||||||
switch (type2.type) {
|
|
||||||
case TypeType::Int:
|
|
||||||
case TypeType::Double: {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
throw TypeError(ErrorType::TypesNotComparable, pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
throw TypeError(ErrorType::TypesNotComparable, pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Type get_cast(AnalysisResult type1, AnalysisResult type2, CodePosition pos) {
|
|
||||||
(void)type1; (void)type2; (void)pos;
|
|
||||||
return type_type_to_type(TypeType::Int);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_arithmetic_type(Type type) {
|
|
||||||
switch (type.type) {
|
|
||||||
case TypeType::Int:
|
|
||||||
case TypeType::Double:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Type try_string_to_type(string type_name, CodePosition pos) {
|
Type try_string_to_type(string type_name, CodePosition pos) {
|
||||||
try {
|
try {
|
||||||
@ -58,7 +13,7 @@ Type try_string_to_type(string type_name, CodePosition pos) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AnalysisResult analyze(Node &ast, Memory &memory) {
|
Type analyze(Node &ast, Memory &memory) {
|
||||||
if (holds_alternative<Token>(ast)) {
|
if (holds_alternative<Token>(ast)) {
|
||||||
Token token = get<Token>(ast);
|
Token token = get<Token>(ast);
|
||||||
switch (token.type) {
|
switch (token.type) {
|
||||||
@ -100,7 +55,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
|||||||
break;
|
break;
|
||||||
case NodeType::If:
|
case NodeType::If:
|
||||||
case NodeType::IfElse: {
|
case NodeType::IfElse: {
|
||||||
if (!bool_castable(analyze(node.children[0], memory))) {
|
if (!is_arithmetic_type(analyze(node.children[0], memory))) {
|
||||||
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
|
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +66,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
|||||||
return {};
|
return {};
|
||||||
} break;
|
} break;
|
||||||
case NodeType::While: {
|
case NodeType::While: {
|
||||||
if (!bool_castable(analyze(node.children[0], memory))) {
|
if (!is_arithmetic_type(analyze(node.children[0], memory))) {
|
||||||
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
|
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
|
||||||
}
|
}
|
||||||
analyze(node.children[1], memory);
|
analyze(node.children[1], memory);
|
||||||
@ -123,7 +78,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
|||||||
|
|
||||||
analyze(node.children[0], memory);
|
analyze(node.children[0], memory);
|
||||||
|
|
||||||
if (!bool_castable(analyze(node.children[1], memory))) {
|
if (!is_arithmetic_type(analyze(node.children[1], memory))) {
|
||||||
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[1]), "bool");
|
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[1]), "bool");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,17 +97,17 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
|||||||
} break;
|
} break;
|
||||||
case NodeType::Lor:
|
case NodeType::Lor:
|
||||||
case NodeType::Land: {
|
case NodeType::Land: {
|
||||||
if (!bool_castable(analyze(node.children[0], memory))) {
|
if (!is_arithmetic_type(analyze(node.children[0], memory))) {
|
||||||
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
|
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
|
||||||
}
|
}
|
||||||
if (!bool_castable(analyze(node.children[1], memory))) {
|
if (!is_arithmetic_type(analyze(node.children[1], memory))) {
|
||||||
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[1]), "bool");
|
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[1]), "bool");
|
||||||
}
|
}
|
||||||
|
|
||||||
return type_type_to_type(TypeType::Int);
|
return type_type_to_type(TypeType::Int);
|
||||||
} break;
|
} break;
|
||||||
case NodeType::Neg: {
|
case NodeType::Neg: {
|
||||||
if (!bool_castable(analyze(node.children[0], memory))) {
|
if (!is_arithmetic_type(analyze(node.children[0], memory))) {
|
||||||
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
|
throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,33 +116,33 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
|||||||
case NodeType::Lt:
|
case NodeType::Lt:
|
||||||
case NodeType::Gt:
|
case NodeType::Gt:
|
||||||
case NodeType::Leq:
|
case NodeType::Leq:
|
||||||
case NodeType::Geq: {
|
case NodeType::Geq:
|
||||||
AnalysisResult res1 = analyze(node.children[0], memory);
|
case NodeType::Eq:
|
||||||
AnalysisResult res2 = analyze(node.children[1], memory);
|
case NodeType::Neq: {
|
||||||
|
Type res1 = analyze(node.children[0], memory);
|
||||||
|
Type res2 = analyze(node.children[1], memory);
|
||||||
|
|
||||||
check_comparable(res1, res2, node.pos);
|
check_comparable(res1, res2, node.pos);
|
||||||
|
|
||||||
return type_type_to_type(TypeType::Int);
|
return type_type_to_type(TypeType::Int);
|
||||||
} break;
|
} break;
|
||||||
case NodeType::Eq:
|
|
||||||
case NodeType::Neq:
|
|
||||||
case NodeType::Plus:
|
case NodeType::Plus:
|
||||||
case NodeType::Minus:
|
case NodeType::Minus:
|
||||||
case NodeType::Mult:
|
case NodeType::Mult:
|
||||||
case NodeType::Div: {
|
case NodeType::Div: {
|
||||||
AnalysisResult res1 = analyze(node.children[0], memory);
|
Type res1 = analyze(node.children[0], memory);
|
||||||
AnalysisResult res2 = analyze(node.children[1], memory);
|
Type res2 = analyze(node.children[1], memory);
|
||||||
|
|
||||||
return get_cast(res1, res2, node.pos);
|
return get_operation_cast(res1, res2, node.pos);
|
||||||
} break;
|
} break;
|
||||||
case NodeType::Mod: {
|
case NodeType::Mod: {
|
||||||
AnalysisResult e1 = analyze(node.children[0], memory);
|
Type e1 = analyze(node.children[0], memory);
|
||||||
AnalysisResult e2 = analyze(node.children[1], memory);
|
Type e2 = analyze(node.children[1], memory);
|
||||||
|
|
||||||
if (holds_alternative<monostate>(e1) || get<Type>(e1).type != TypeType::Int) {
|
if (e1.type != TypeType::Int) {
|
||||||
throw TypeError(ErrorType::ExpectedIntegralType, get_node_pos(node.children[0]));
|
throw TypeError(ErrorType::ExpectedIntegralType, get_node_pos(node.children[0]));
|
||||||
}
|
}
|
||||||
if (holds_alternative<monostate>(e2) || get<Type>(e2).type != TypeType::Int) {
|
if (e2.type != TypeType::Int) {
|
||||||
throw TypeError(ErrorType::ExpectedIntegralType, get_node_pos(node.children[1]));
|
throw TypeError(ErrorType::ExpectedIntegralType, get_node_pos(node.children[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,13 +150,13 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
|||||||
} break;
|
} break;
|
||||||
case NodeType::UnaryPlus:
|
case NodeType::UnaryPlus:
|
||||||
case NodeType::UnaryMinus: {
|
case NodeType::UnaryMinus: {
|
||||||
AnalysisResult res = analyze(node.children[0], memory);
|
Type res = analyze(node.children[0], memory);
|
||||||
|
|
||||||
if (holds_alternative<monostate>(res) || !is_arithmetic_type(get<Type>(res))) {
|
if (!is_arithmetic_type(res)) {
|
||||||
throw TypeError(ErrorType::ExpectedArithmeticType, get_node_pos(node.children[0]));
|
throw TypeError(ErrorType::ExpectedArithmeticType, get_node_pos(node.children[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return get<Type>(res);
|
return res;
|
||||||
} break;
|
} break;
|
||||||
case NodeType::Declaration: {
|
case NodeType::Declaration: {
|
||||||
Token type_token = get<Token>(node.children[0]);
|
Token type_token = get<Token>(node.children[0]);
|
||||||
@ -237,7 +192,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
|||||||
|
|
||||||
memory.declare(identifier, type);
|
memory.declare(identifier, type);
|
||||||
|
|
||||||
get_cast(type, analyze(node.children[2], memory), get_node_pos(node));
|
check_cast(type, analyze(node.children[2], memory), get_node_pos(node));
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
} break;
|
} break;
|
||||||
@ -248,9 +203,9 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
|||||||
throw TypeError(ErrorType::UnknownIdentifier, identifier_token.pos, identifier);
|
throw TypeError(ErrorType::UnknownIdentifier, identifier_token.pos, identifier);
|
||||||
|
|
||||||
Type type = memory.get(identifier).type;
|
Type type = memory.get(identifier).type;
|
||||||
AnalysisResult res = analyze(node.children[1], memory);
|
Type res = analyze(node.children[1], memory);
|
||||||
|
|
||||||
get_cast(type, res, get_node_pos(node.children[1]));
|
check_cast(type, res, get_node_pos(node.children[1]));
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
} break;
|
} break;
|
||||||
@ -408,10 +363,10 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
|||||||
if (node.children.size() == 0)
|
if (node.children.size() == 0)
|
||||||
throw TypeError(ErrorType::IncompatibleReturnValue, node.pos, {});
|
throw TypeError(ErrorType::IncompatibleReturnValue, node.pos, {});
|
||||||
|
|
||||||
AnalysisResult res = analyze(node.children[0], memory);
|
Type res = analyze(node.children[0], memory);
|
||||||
AnalysisResult expected_type = return_type;
|
Type expected_type = return_type;
|
||||||
|
|
||||||
get_cast(res, expected_type, node.pos);
|
check_cast(res, expected_type, node.pos);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
101
src/casting.cpp
Normal file
101
src/casting.cpp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#include "include/casting.hpp"
|
||||||
|
#include "include/errors.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
bool check_valid_cast_int(Type type) {
|
||||||
|
switch (type.type) {
|
||||||
|
case TypeType::Int:
|
||||||
|
case TypeType::Double:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_valid_cast_double(Type type) {
|
||||||
|
switch (type.type) {
|
||||||
|
case TypeType::Int:
|
||||||
|
case TypeType::Double:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool check_valid_cast(Type dest, Type type) {
|
||||||
|
switch (dest.type) {
|
||||||
|
case TypeType::Void: return true;
|
||||||
|
case TypeType::Function: return false;
|
||||||
|
case TypeType::Int: return check_valid_cast_int(type);
|
||||||
|
case TypeType::Double: return check_valid_cast_double(type);
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_cast(Type dest, Type type, CodePosition pos) {
|
||||||
|
if (!check_valid_cast(dest, type))
|
||||||
|
throw TypeError(ErrorType::TypeNotCastable, pos, type_type_to_string(type.type));
|
||||||
|
}
|
||||||
|
|
||||||
|
Type get_operation_cast(Type type1, Type type2, CodePosition pos) {
|
||||||
|
|
||||||
|
if (!is_arithmetic_type(type1) || !is_arithmetic_type(type2))
|
||||||
|
throw TypeError(ErrorType::ExpectedArithmeticType, pos, {});
|
||||||
|
|
||||||
|
if (type1.type == TypeType::Double || type2.type == TypeType::Double)
|
||||||
|
return type_type_to_type(TypeType::Double);
|
||||||
|
|
||||||
|
return type_type_to_type(TypeType::Int);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_arithmetic_type(Type type) {
|
||||||
|
switch (type.type) {
|
||||||
|
case TypeType::Int:
|
||||||
|
case TypeType::Double:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_comparable(Type type1, Type type2, CodePosition pos) {
|
||||||
|
if (!is_arithmetic_type(type1) || !is_arithmetic_type(type2))
|
||||||
|
throw TypeError(ErrorType::TypesNotComparable, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bool_cast(EvalResult value) {
|
||||||
|
if (holds_alternative<int>(value)) {
|
||||||
|
return get<int>(value) != 0;
|
||||||
|
}
|
||||||
|
else if (holds_alternative<double>(value)) {
|
||||||
|
return get<double>(value) != 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int int_cast(EvalResult value) {
|
||||||
|
if (holds_alternative<int>(value)) {
|
||||||
|
return get<int>(value);
|
||||||
|
} else if (holds_alternative<double>(value)) {
|
||||||
|
return int(get<double>(value));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double double_cast(EvalResult value) {
|
||||||
|
if (holds_alternative<int>(value)) {
|
||||||
|
return double(get<int>(value));
|
||||||
|
}
|
||||||
|
else if (holds_alternative<double>(value)) {
|
||||||
|
return get<double>(value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw exception();
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,10 @@
|
|||||||
#ifndef ANALYSIS_H
|
#ifndef DEF_ANALYSIS_H
|
||||||
#define ANALYSIS_H
|
#define DEF_ANALYSIS_H
|
||||||
|
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
#include "memory.hpp"
|
#include "memory.hpp"
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
using AnalysisResult = variant<Type, monostate>;
|
Type analyze(Node &ast, Memory &memory);
|
||||||
|
|
||||||
AnalysisResult analyze(Node &ast, Memory &memory);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
37
src/include/casting.hpp
Normal file
37
src/include/casting.hpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef DEF_CASTING_H
|
||||||
|
#define DEF_CASTING_H
|
||||||
|
|
||||||
|
#include "utils.hpp"
|
||||||
|
#include "types.hpp"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if two types are comparable
|
||||||
|
*/
|
||||||
|
void check_comparable(Type type1, Type type2, CodePosition pos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if cast possible de type vers dest
|
||||||
|
* Else throw error
|
||||||
|
*/
|
||||||
|
void check_cast(Type dest, Type type, CodePosition pos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cast type de retour d'une opération entre type1 et type2
|
||||||
|
* Par exemple: (Int) / (Float) -> (Float)
|
||||||
|
* If impossible, throw error
|
||||||
|
*/
|
||||||
|
Type get_operation_cast(Type dest, Type type, CodePosition pos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if type is arithmetic
|
||||||
|
* double, int, ...
|
||||||
|
*/
|
||||||
|
bool is_arithmetic_type(Type type);
|
||||||
|
|
||||||
|
bool bool_cast(EvalResult value);
|
||||||
|
|
||||||
|
int int_cast(EvalResult value);
|
||||||
|
|
||||||
|
double double_cast(EvalResult value);
|
||||||
|
|
||||||
|
#endif
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef MEMORY_H
|
#ifndef DEF_MEMORY_H
|
||||||
#define MEMORY_H
|
#define DEF_MEMORY_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef TOKENIZE_H
|
#ifndef DEF_TOKENIZE_H
|
||||||
#define TOKENIZE_H
|
#define DEF_TOKENIZE_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef TYPES_H
|
#ifndef DEF_TYPES_H
|
||||||
#define TYPES_H
|
#define DEF_TYPES_H
|
||||||
|
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -25,7 +25,7 @@ using FunctionPrototype = vector<ArgDefinition>;
|
|||||||
using TypeData = variant<monostate, FunctionPrototype>;
|
using TypeData = variant<monostate, FunctionPrototype>;
|
||||||
|
|
||||||
struct Type {
|
struct Type {
|
||||||
TypeType type;
|
TypeType type=TypeType::Void;
|
||||||
TypeData data { };
|
TypeData data { };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ vector<string> split_string(const string& input, char delimiter);
|
|||||||
/**
|
/**
|
||||||
* Returns a human-readable name for a TypeType object
|
* Returns a human-readable name for a TypeType object
|
||||||
*/
|
*/
|
||||||
string _debug_get_type_type_name(TypeType type);
|
string type_type_to_string(TypeType type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if two types are equal
|
* Check if two types are equal
|
||||||
|
@ -1,46 +1,13 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "include/parser.hpp"
|
|
||||||
#include "include/interpreter.hpp"
|
|
||||||
#include "include/memory.hpp"
|
|
||||||
#include "include/utils.hpp"
|
#include "include/utils.hpp"
|
||||||
|
#include "include/memory.hpp"
|
||||||
|
#include "include/parser.hpp"
|
||||||
|
#include "include/casting.hpp"
|
||||||
|
#include "include/interpreter.hpp"
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
bool bool_cast(EvalResult value) {
|
|
||||||
if (holds_alternative<int>(value)) {
|
|
||||||
return get<int>(value) != 0;
|
|
||||||
}
|
|
||||||
else if (holds_alternative<double>(value)) {
|
|
||||||
return get<double>(value) != 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int int_cast(EvalResult value) {
|
|
||||||
if (holds_alternative<int>(value)) {
|
|
||||||
return get<int>(value);
|
|
||||||
} else if (holds_alternative<double>(value)) {
|
|
||||||
return int(get<double>(value));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double double_cast(EvalResult value) {
|
|
||||||
if (holds_alternative<int>(value)) {
|
|
||||||
return double(get<int>(value));
|
|
||||||
}
|
|
||||||
else if (holds_alternative<double>(value)) {
|
|
||||||
return get<double>(value);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EvalResult cast_from_type(Type type, EvalResult val) {
|
EvalResult cast_from_type(Type type, EvalResult val) {
|
||||||
switch (type.type) {
|
switch (type.type) {
|
||||||
|
@ -187,7 +187,7 @@ void _debug_print_scope(Scope scope) {
|
|||||||
cout << setw (14) << it.first << " ";
|
cout << setw (14) << it.first << " ";
|
||||||
}
|
}
|
||||||
cout << "|";
|
cout << "|";
|
||||||
cout << setw (9) << _debug_get_type_type_name(it.second.type.type) << " |";
|
cout << setw (9) << type_type_to_string(it.second.type.type) << " |";
|
||||||
|
|
||||||
_debug_print_memory_var(it.second);
|
_debug_print_memory_var(it.second);
|
||||||
cout << endl;
|
cout << endl;
|
||||||
|
@ -68,12 +68,12 @@ vector<string> split_string(const string& input, char delimiter) {
|
|||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
string _debug_get_type_type_name(TypeType type) {
|
string type_type_to_string(TypeType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TypeType::Int: return "INT";
|
case TypeType::Int: return "int";
|
||||||
case TypeType::Double: return "DOUBLE";
|
case TypeType::Double: return "double";
|
||||||
case TypeType::Void: return "VOID";
|
case TypeType::Void: return "void";
|
||||||
case TypeType::Function: return "FUNCTION";
|
case TypeType::Function: return "function";
|
||||||
default: return "Unknown";
|
default: return "Unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
71
test/analysis.cpp
Normal file
71
test/analysis.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#include "include/test.hpp"
|
||||||
|
|
||||||
|
#include "../src/include/execute.hpp"
|
||||||
|
#include "../src/include/utils.hpp"
|
||||||
|
|
||||||
|
int execute(string s) {
|
||||||
|
Memory memory;
|
||||||
|
return get<int>(execute(split_string(s, '\n'), memory));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
_TEST_PRESENTATION("Analyse statique");
|
||||||
|
|
||||||
|
_TEST_ASSERT(
|
||||||
|
_TEST_IS_EXCEPTION(execute("unknown x;"), ErrorType::UnknownType),
|
||||||
|
"Type inconnu",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
_TEST_ASSERT(
|
||||||
|
_TEST_IS_EXCEPTION(execute(R"(
|
||||||
|
void f() {}
|
||||||
|
int x = f();
|
||||||
|
)"), ErrorType::TypeNotCastable),
|
||||||
|
"Cast depuis void",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
_TEST_ASSERT(
|
||||||
|
_TEST_IS_EXCEPTION(execute(R"(
|
||||||
|
void f() {}
|
||||||
|
5.0 / f();
|
||||||
|
)"), ErrorType::ExpectedArithmeticType),
|
||||||
|
"Division par void",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
_TEST_ASSERT(
|
||||||
|
_TEST_IS_EXCEPTION(execute("5 % (5.0 / 2.0);"), ErrorType::ExpectedIntegralType),
|
||||||
|
"Modulo flottant",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
_TEST_ASSERT(
|
||||||
|
_TEST_IS_EXCEPTION(execute("void x;"), ErrorType::IncompleteType),
|
||||||
|
"Variable de type void",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
_TEST_ASSERT(
|
||||||
|
_TEST_IS_EXCEPTION(execute(R"(
|
||||||
|
int x;
|
||||||
|
int x;
|
||||||
|
)"), ErrorType::AlreadyDeclaredIdentifier),
|
||||||
|
"Redéclaration",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
_TEST_ASSERT(
|
||||||
|
_TEST_IS_EXCEPTION(execute(R"(
|
||||||
|
int x;
|
||||||
|
void x() {}
|
||||||
|
)"), ErrorType::IncompatibleRedefinition),
|
||||||
|
"Redéfinition",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user