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); throw RuntimeError(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);
memory.declare(identifier, type); memory.declare(identifier, type, type_token.pos);
return {}; return {};
} break; } break;
@ -229,7 +229,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
throw RuntimeError(ErrorType::AlreadyDeclaredIdentifier, token.pos, identifier); throw RuntimeError(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);
memory.declare(identifier, type); memory.declare(identifier, type, type_token.pos);
get_cast(type, analyze(node.children[2], memory), get_node_pos(node)); get_cast(type, analyze(node.children[2], memory), get_node_pos(node));

View File

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

View File

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

View File

@ -137,17 +137,98 @@ EvalResult eval(Node &ast, Memory &memory) {
return {}; return {};
} break; } 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: { case NodeType::Eq: {
EvalResult e1 = eval(node.children[0], memory); EvalResult e1 = eval(node.children[0], memory);
EvalResult e2 = eval(node.children[1], 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; } break;
case NodeType::Neq: { case NodeType::Neq: {
EvalResult e1 = eval(node.children[0], memory); EvalResult e1 = eval(node.children[0], memory);
EvalResult e2 = eval(node.children[1], 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; } break;
case NodeType::Lor: { case NodeType::Lor: {
EvalResult e1 = eval(node.children[0], memory); EvalResult e1 = eval(node.children[0], memory);
@ -169,26 +250,46 @@ EvalResult eval(Node &ast, Memory &memory) {
case NodeType::Lt: { case NodeType::Lt: {
EvalResult e1 = eval(node.children[0], memory); EvalResult e1 = eval(node.children[0], memory);
EvalResult e2 = eval(node.children[1], 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; } break;
case NodeType::Gt: { case NodeType::Gt: {
EvalResult e1 = eval(node.children[0], memory); EvalResult e1 = eval(node.children[0], memory);
EvalResult e2 = eval(node.children[1], 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; } break;
case NodeType::Leq: { case NodeType::Leq: {
EvalResult e1 = eval(node.children[0], memory); EvalResult e1 = eval(node.children[0], memory);
EvalResult e2 = eval(node.children[1], 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; } break;
case NodeType::Geq: { case NodeType::Geq: {
EvalResult e1 = eval(node.children[0], memory); EvalResult e1 = eval(node.children[0], memory);
EvalResult e2 = eval(node.children[1], 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; } break;
case NodeType::Plus: { case NodeType::Plus: {
EvalResult e1 = eval(node.children[0], memory); EvalResult e1 = eval(node.children[0], memory);
@ -287,7 +388,8 @@ EvalResult eval(Node &ast, Memory &memory) {
string typeName = get<string>(typeTok.data); string typeName = get<string>(typeTok.data);
string identifier = get<string>(identifierTok.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 {}; return {};
} break; } break;
@ -299,7 +401,7 @@ EvalResult eval(Node &ast, Memory &memory) {
EvalResult value = eval(node.children[2], memory); EvalResult value = eval(node.children[2], memory);
Type type = string_to_type(typeName); Type type = string_to_type(typeName);
memory.declare(identifier, type); memory.declare(identifier, type, typeTok.pos);
if (type.type == TypeType::Int) { if (type.type == TypeType::Int) {
memory.update(identifier, int_cast(value)); memory.update(identifier, int_cast(value));
@ -323,6 +425,9 @@ EvalResult eval(Node &ast, Memory &memory) {
else if (type.type == TypeType::Double) { else if (type.type == TypeType::Double) {
memory.update(identifier, double_cast(value)); memory.update(identifier, double_cast(value));
} }
else {
throw exception();
}
return value; return value;
} break; } break;

View File

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