Implement functions (partial)

This commit is contained in:
ala89 2023-12-28 12:13:52 +01:00
parent 91b398dbe9
commit f50b87f68c
5 changed files with 122 additions and 15 deletions

View File

@ -214,7 +214,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
throw RuntimeError(ErrorType::AlreadyDeclaredIdentifier, token.pos, identifier);
Type type = try_string_to_type(type_string, type_token.pos);
memory.declare(identifier, type);
memory.declare(identifier, type, type_token.pos);
return {};
} break;
@ -229,7 +229,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
throw RuntimeError(ErrorType::AlreadyDeclaredIdentifier, token.pos, identifier);
Type type = try_string_to_type(type_string, type_token.pos);
memory.declare(identifier, type);
memory.declare(identifier, type, type_token.pos);
get_cast(type, analyze(node.children[2], memory), get_node_pos(node));

View File

@ -16,7 +16,7 @@ class Memory {
void remove_scope(void);
MemoryVar& get(string identifier);
void declare(string identifier, Type type);
void declare(string identifier, Type type, CodePosition pos);
void update(string identifier, EvalResult value);
Scope& _debug_top(void);

View File

@ -19,7 +19,7 @@ enum class TypeType {
Int, Double, Void, Function
};
using FunctionPrototype = vector<tuple<string, Type>>;
using FunctionPrototype = vector<tuple<Type, string>>;
using TypeData = variant<monostate, FunctionPrototype>;
struct Type {
@ -197,7 +197,7 @@ struct ParseReturn {
/**
* Interpreter
*/
using EvalResult = variant<monostate, int, double>;
using EvalResult = variant<monostate, int, double, Node>;
enum class ScopeType { Block, Function, For };
@ -205,6 +205,7 @@ struct MemoryVar {
EvalResult value;
Type type;
bool initialized;
CodePosition declarationPos;
};
struct Scope {

View File

@ -137,17 +137,98 @@ EvalResult eval(Node &ast, Memory &memory) {
return {};
} break;
case NodeType::FunctionPrototype: {
Token retTypeTok = get<Token>(node.children[0]);
Token fnIdentifierTok = get<Token>(node.children[1]);
string retTypeName = get<string>(retTypeTok.data);
string fnIdentifier = get<string>(fnIdentifierTok.data);
Type retType = string_to_type(retTypeName);
vector<Node> args = get<InnerNode>(node.children[2]).children;
FunctionPrototype prototype = { { retType, "" } };
for (Node arg : args) {
InnerNode argInner = get<InnerNode>(arg);
Token typeTok = get<Token>(argInner.children[0]);
Token identifierTok = get<Token>(argInner.children[1]);
string typeName = get<string>(typeTok.data);
string identifier = get<string>(identifierTok.data);
Type type = string_to_type(typeName);
prototype.push_back({ type, identifier });
}
memory.declare(fnIdentifier, {
.type = TypeType::Function,
.data = prototype
}, retTypeTok.pos);
return {};
} break;
case NodeType::FunctionDeclaration: {
Token retTypeTok = get<Token>(node.children[0]);
Token fnIdentifierTok = get<Token>(node.children[1]);
string retTypeName = get<string>(retTypeTok.data);
string fnIdentifier = get<string>(fnIdentifierTok.data);
Type retType = string_to_type(retTypeName);
vector<Node> args = get<InnerNode>(node.children[2]).children;
FunctionPrototype prototype = { { retType, "" } };
for (Node arg : args) {
InnerNode argInner = get<InnerNode>(arg);
Token typeTok = get<Token>(argInner.children[0]);
Token identifierTok = get<Token>(argInner.children[1]);
string typeName = get<string>(typeTok.data);
string identifier = get<string>(identifierTok.data);
Type type = string_to_type(typeName);
prototype.push_back({ type, identifier });
}
memory.declare(fnIdentifier, {
.type = TypeType::Function,
.data = prototype
}, retTypeTok.pos);
memory.update(fnIdentifier, node.children[3]);
return {};
} break;
case NodeType::FunctionCall: {
memory.add_scope(ScopeType::Function);
try {
memory.remove_scope();
}
catch (...) {
memory.remove_scope();
exception_ptr e = current_exception();
if (e) rethrow_exception(e);
}
} break;
case NodeType::Eq: {
EvalResult e1 = eval(node.children[0], memory);
EvalResult e2 = eval(node.children[1], memory);
return e1 == e2;
if (holds_alternative<double>(e1) || holds_alternative<double>(e2)) {
return double_cast(e1) == double_cast(e2);
}
else {
return get<int>(e1) == get<int>(e2);
}
} break;
case NodeType::Neq: {
EvalResult e1 = eval(node.children[0], memory);
EvalResult e2 = eval(node.children[1], memory);
return e1 != e2;
if (holds_alternative<double>(e1) || holds_alternative<double>(e2)) {
return double_cast(e1) != double_cast(e2);
}
else {
return get<int>(e1) != get<int>(e2);
}
} break;
case NodeType::Lor: {
EvalResult e1 = eval(node.children[0], memory);
@ -170,25 +251,45 @@ EvalResult eval(Node &ast, Memory &memory) {
EvalResult e1 = eval(node.children[0], memory);
EvalResult e2 = eval(node.children[1], memory);
return e1 < e2;
if (holds_alternative<double>(e1) || holds_alternative<double>(e2)) {
return double_cast(e1) < double_cast(e2);
}
else {
return get<int>(e1) < get<int>(e2);
}
} break;
case NodeType::Gt: {
EvalResult e1 = eval(node.children[0], memory);
EvalResult e2 = eval(node.children[1], memory);
return e1 > e2;
if (holds_alternative<double>(e1) || holds_alternative<double>(e2)) {
return double_cast(e1) > double_cast(e2);
}
else {
return get<int>(e1) > get<int>(e2);
}
} break;
case NodeType::Leq: {
EvalResult e1 = eval(node.children[0], memory);
EvalResult e2 = eval(node.children[1], memory);
return e1 <= e2;
if (holds_alternative<double>(e1) || holds_alternative<double>(e2)) {
return double_cast(e1) <= double_cast(e2);
}
else {
return get<int>(e1) <= get<int>(e2);
}
} break;
case NodeType::Geq: {
EvalResult e1 = eval(node.children[0], memory);
EvalResult e2 = eval(node.children[1], memory);
return e1 >= e2;
if (holds_alternative<double>(e1) || holds_alternative<double>(e2)) {
return double_cast(e1) >= double_cast(e2);
}
else {
return get<int>(e1) >= get<int>(e2);
}
} break;
case NodeType::Plus: {
EvalResult e1 = eval(node.children[0], memory);
@ -287,7 +388,8 @@ EvalResult eval(Node &ast, Memory &memory) {
string typeName = get<string>(typeTok.data);
string identifier = get<string>(identifierTok.data);
memory.declare(identifier, string_to_type(typeName));
Type type = string_to_type(typeName);
memory.declare(identifier, type, typeTok.pos);
return {};
} break;
@ -299,7 +401,7 @@ EvalResult eval(Node &ast, Memory &memory) {
EvalResult value = eval(node.children[2], memory);
Type type = string_to_type(typeName);
memory.declare(identifier, type);
memory.declare(identifier, type, typeTok.pos);
if (type.type == TypeType::Int) {
memory.update(identifier, int_cast(value));
@ -323,6 +425,9 @@ EvalResult eval(Node &ast, Memory &memory) {
else if (type.type == TypeType::Double) {
memory.update(identifier, double_cast(value));
}
else {
throw exception();
}
return value;
} break;

View File

@ -41,9 +41,10 @@ MemoryVar& Memory::get(string identifier) {
throw exception();
}
void Memory::declare(string identifier, Type type) {
void Memory::declare(string identifier, Type type, CodePosition pos) {
Scope& top = scopes.back();
top.vars[identifier].type = type;
top.vars[identifier].declarationPos = pos;
}
void Memory::update(string identifier, EvalResult value) {