Skip to content

Commit

Permalink
Added advanced type checking.
Browse files Browse the repository at this point in the history
  • Loading branch information
danielzsh committed Oct 7, 2020
1 parent 1a3b673 commit 524e60b
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 39 deletions.
194 changes: 161 additions & 33 deletions Interpreter/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,68 +2,196 @@
#include "../Parser/parser.h"
#include <map>
#include <string>
#include <cmath>
#include "Symbols.h"
#include <typeinfo>
class Interpreter
{
private:
Parser parser;
SymbolTable symTab;
public:
std::map<std::string, double> GLOBAL_SCOPE;
union val
{
int i;
double d;
};
std::map<std::string,val> GLOBAL_SCOPE;
Interpreter(std::string input) : parser(input) {

}
~Interpreter() {}
void visit(AstNode* node) {
if (node->print() == "Block") visit_Block(*static_cast<Block*>(node));
else if (node->print() == "Assign") visit_Assign(*static_cast<class Assign*>(node));
else if (node->print() == "NoOp") visit_NoOp();
template<class T>
T visit(AstNode* node) {
if (typeid(T) == typeid(void)) {
if (node->print() == "Block") visit_Block(*static_cast<Block*>(node));
else if (node->print() == "Assign") visit_Assign(*static_cast<class Assign*>(node));
else if (node->print() == "NoOp") visit_NoOp();
else {
std::string error = "Error: void operation not recognized";
throw error;
}
}
else if (typeid(T) == typeid(int) || typeid(T) == typeid(double)) {
if (node->print() == "BinOp") {
BinOp binOp = *static_cast<BinOp*>(node);
return visit_BinOp<T>(binOp);
}
else if (node->print() == "Num") {
return visit_Num<T>(*static_cast<Num*>(node));
}
else if (node->print() == "UnOp") {
return visit_UnOp<T>(*static_cast<UnOp*>(node));
}
else if (node->print() == "Var") {
return visit_Var<T>(*static_cast<Var*>(node));
}
else {
std::string error = "Error: not recognized";
throw error;
}
}
else {
std::string error = "Error: not recognized";
std::string error("Type not recognized");
throw error;
}
}
double visit_Real(AstNode* node) {
if (node->print() == "Num") return visit_Num(*static_cast<Num*>(node));
else if (node->print() == "UnOp") return visit_UnOp(*static_cast<UnOp*>(node));
else if (node->print() == "Var") return visit_Var(*static_cast<Var*>(node));
else if (node->print() == "BinOp") return visit_BinOp(*static_cast<BinOp*>(node));
template <class T>
T visit_BinOp(BinOp binOp) {
if (typeid(T) == typeid(int))
{
if (binOp.op.type == Div) {
std::string error = "Error: Float division and int are incompatible types";
throw error;
}
else if (binOp.op.type == Plus) {
return (T)(visit<int>(binOp.left) + visit<int>(binOp.right));
}
else if (binOp.op.type == Minus) {
return (T)(visit<int>(binOp.left) - visit<int>(binOp.right));
}
else if (binOp.op.type == Times) return (T)(visit<int>(binOp.left) * visit<int>(binOp.right));
else if (binOp.op.type == IntDiv) return (T)(visit<int>(binOp.left) / visit<int>(binOp.right));
else {
std::string error("Error: BinOp operation not recognized.");
throw error;
}
}
else if (typeid(T) == typeid(double)) {
if (binOp.op.type == Plus) {
return (T)(visit<double>(binOp.left) + visit<double>(binOp.right));
}
else if (binOp.op.type == Minus) {
return (T)(visit<int>(binOp.left) - visit<int>(binOp.right));
}
else if (binOp.op.type == Times) return (T)(visit<double>(binOp.left) * visit<double>(binOp.right));
else if (binOp.op.type == IntDiv) return (T)(visit<int>(binOp.left) / visit<int>(binOp.right));
else if (binOp.op.type == Div) {
return (T)(visit<double>(binOp.left) / visit<double>(binOp.right));
}
else {
std::string error("Error: BinOp operation not recognized.");
throw error;
}
}
else {
std::string error = "Error: not recognized";
std::string error("Type not recognized");
throw error;
}
}
double visit_Num(Num num) {
return num.value;
template<class T>
T visit_Num(Num num) {
if (typeid(T) == typeid(void)) {
return (T)(1);
}
if (typeid(T) == typeid(int)) {
if (ceil(num.value) == num.value) return (T)num.value;
else {
std::string error = "Error: Wanted int but got double";
throw error;
}
}
else return (T)num.value;

}
double visit_BinOp(BinOp binOp) {
if (binOp.op.type == Plus) return visit_Real(binOp.left) + visit_Real(binOp.right);
else if (binOp.op.type == Minus) return visit_Real(binOp.left) - visit_Real(binOp.right);
else if (binOp.op.type == Times) return visit_Real(binOp.left) * visit_Real(binOp.right);
else if (binOp.op.type == Div) return (double)(visit_Real(binOp.left) / (double)visit_Real(binOp.right));
else if (binOp.op.type == IntDiv) return (int)(visit_Real(binOp.left) / visit_Real(binOp.right));
else {
std::string error("Error: BinOp operation not recognized.");
template <class T>
T visit_UnOp(UnOp unOp) {
if (typeid(T) == typeid(void)) {
std::string error = "void unOp? srsly";
throw error;
}
}
double visit_UnOp(UnOp unOp) {
TokenType op = unOp.op.type;
if (op == Plus) return visit_Real(unOp.expr);
else return 0 - visit_Real(unOp.expr);
if (typeid(T) == typeid(int)) {
if (op == Plus) return (T)(visit<int>(unOp.expr));
else return (T)(0 - visit<int>(unOp.expr));
}
if (typeid(T) == typeid(double)) {
if (op == Plus) return (T)(visit<double>(unOp.expr));
else return (T)(0 - visit<double>(unOp.expr));
}
else {
std::string error("Type not recognized");
throw error;
}
}
void visit_Block(Block block) {
for (AstNode* child : block.children) {
visit(child);
visit<void>(child);
}
}
void visit_Assign(class Assign assign) {
string var_name = assign.var.value;
GLOBAL_SCOPE[var_name] = visit_Real(assign.right);
std::string var_name = assign.var.value;
std::string type = symTab.lookup(var_name)->type->name;
cout << type << endl;
if (type == "int") {
GLOBAL_SCOPE[var_name].i = visit<int>(assign.right);
return;
}
else if (type == "real") {
GLOBAL_SCOPE[var_name].d = visit<double>(assign.right);
return;
}
else {
std::string error("Var type not supported");
throw error;
}
}
template<class T>
T visit_Var(Var var) {
if (GLOBAL_SCOPE.find(var.value) != GLOBAL_SCOPE.end()) {
if (typeid(T) == typeid(int)) {
std::string type = symTab.lookup(var.value)->type->name;
if (type == "int") return (T)GLOBAL_SCOPE[var.value].i;
else {
std::string error("Wanted integer, got " + type);
throw error;
}
}
else if (typeid(T) == typeid(double)) {
std::string type = symTab.lookup(var.value)->type->name;
if (type == "real") return (T)GLOBAL_SCOPE[var.value].d;
else {
std::string error("Wanted real, got " + type);
throw error;
}
}
else {
std::string error("Var type invalid");
throw error;
}
}
else return (T)0;
}
double visit_Var(Var var) {
if (GLOBAL_SCOPE.find(var.value) != GLOBAL_SCOPE.end()) return GLOBAL_SCOPE[var.value];
SymbolTable getSymTab() {
return symTab;
}
void visit_NoOp() {}
void interpret() {
Block block = parser.parseProgram();
SymbolTableBuilder symtabBuilder;
symtabBuilder.visit(&block);
std::cout << "Finished building symtab...\n";
symTab = symtabBuilder.symtab;
visit_Block(block);
}
private:
Parser parser;
};
3 changes: 2 additions & 1 deletion Lexer/Lexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ class Lexer {
{"int", INT},
{"real", REAL},
{"vars", VARS},
{"program", PROGRAM}
{"program", PROGRAM},
{"func", FUNCTION}
};
public:
Lexer(string inputPass) {
Expand Down
1 change: 1 addition & 0 deletions Lexer/tokens.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ enum TokenType {
REAL,
VARS,
PROGRAM,
FUNCTION,
// Miscellaneous
Colon,
Comma
Expand Down
12 changes: 11 additions & 1 deletion main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ int interpret(string input) {
return 1;
}
Interpreter interpreter(input);
cout << "Interpreting...\n";
try {
interpreter.interpret();
}
Expand All @@ -49,8 +50,17 @@ int interpret(string input) {
}

cout << "Variables: " << endl;
SymbolTable symtab = interpreter.getSymTab();
for (auto const& pair : interpreter.GLOBAL_SCOPE) {
cout << pair.first << " " << pair.second << endl;
cout << pair.first << " ";
std::string type = symtab.lookup(pair.first)->type->name;
if (type == "int") {
cout << pair.second.i;
}
else if (type == "real") {
cout << pair.second.d;
}
cout << endl;
}


Expand Down
9 changes: 5 additions & 4 deletions test.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
main() {
vars:
int: a, c;
int: a, c, d;
real: b;
program:
a = 1*1+4/-2;
a = 1*1+4//-2;
b = -13+4.5;
c = (a - b)//3;
c = (a - d)//3;
d = 40;
{
program:
c = (a - b)//3;
c = (a - d)//3;
}
}

0 comments on commit 524e60b

Please sign in to comment.