Implement functions (partial)
This commit is contained in:
parent
91b398dbe9
commit
f50b87f68c
@ -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));
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
@ -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<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;
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user