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);
|
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));
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user