diff --git a/src/analysis.cpp b/src/analysis.cpp index 1871c3d..b2bebc9 100644 --- a/src/analysis.cpp +++ b/src/analysis.cpp @@ -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)); diff --git a/src/include/memory.h b/src/include/memory.h index fec96da..0c000d7 100644 --- a/src/include/memory.h +++ b/src/include/memory.h @@ -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); diff --git a/src/include/types.h b/src/include/types.h index 84a934c..c704405 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -19,7 +19,7 @@ enum class TypeType { Int, Double, Void, Function }; -using FunctionPrototype = vector>; +using FunctionPrototype = vector>; using TypeData = variant; struct Type { @@ -197,7 +197,7 @@ struct ParseReturn { /** * Interpreter */ -using EvalResult = variant; +using EvalResult = variant; enum class ScopeType { Block, Function, For }; @@ -205,6 +205,7 @@ struct MemoryVar { EvalResult value; Type type; bool initialized; + CodePosition declarationPos; }; struct Scope { diff --git a/src/interpreter.cpp b/src/interpreter.cpp index b43cc6e..2ce6247 100644 --- a/src/interpreter.cpp +++ b/src/interpreter.cpp @@ -137,17 +137,98 @@ EvalResult eval(Node &ast, Memory &memory) { return {}; } break; + case NodeType::FunctionPrototype: { + Token retTypeTok = get(node.children[0]); + Token fnIdentifierTok = get(node.children[1]); + string retTypeName = get(retTypeTok.data); + string fnIdentifier = get(fnIdentifierTok.data); + + Type retType = string_to_type(retTypeName); + vector args = get(node.children[2]).children; + FunctionPrototype prototype = { { retType, "" } }; + + for (Node arg : args) { + InnerNode argInner = get(arg); + Token typeTok = get(argInner.children[0]); + Token identifierTok = get(argInner.children[1]); + string typeName = get(typeTok.data); + string identifier = get(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(node.children[0]); + Token fnIdentifierTok = get(node.children[1]); + string retTypeName = get(retTypeTok.data); + string fnIdentifier = get(fnIdentifierTok.data); + + Type retType = string_to_type(retTypeName); + vector args = get(node.children[2]).children; + FunctionPrototype prototype = { { retType, "" } }; + + for (Node arg : args) { + InnerNode argInner = get(arg); + Token typeTok = get(argInner.children[0]); + Token identifierTok = get(argInner.children[1]); + string typeName = get(typeTok.data); + string identifier = get(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(e1) || holds_alternative(e2)) { + return double_cast(e1) == double_cast(e2); + } + else { + return get(e1) == get(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(e1) || holds_alternative(e2)) { + return double_cast(e1) != double_cast(e2); + } + else { + return get(e1) != get(e2); + } } break; case NodeType::Lor: { EvalResult e1 = eval(node.children[0], memory); @@ -169,26 +250,46 @@ EvalResult eval(Node &ast, Memory &memory) { case NodeType::Lt: { EvalResult e1 = eval(node.children[0], memory); EvalResult e2 = eval(node.children[1], memory); - - return e1 < e2; + + if (holds_alternative(e1) || holds_alternative(e2)) { + return double_cast(e1) < double_cast(e2); + } + else { + return get(e1) < get(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(e1) || holds_alternative(e2)) { + return double_cast(e1) > double_cast(e2); + } + else { + return get(e1) > get(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(e1) || holds_alternative(e2)) { + return double_cast(e1) <= double_cast(e2); + } + else { + return get(e1) <= get(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(e1) || holds_alternative(e2)) { + return double_cast(e1) >= double_cast(e2); + } + else { + return get(e1) >= get(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(typeTok.data); string identifier = get(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; diff --git a/src/memory.cpp b/src/memory.cpp index aab4100..59adedc 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -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) {