ready to write type tracker

This commit is contained in:
2024-08-14 09:57:42 +00:00
parent 1ba056f0ac
commit 7995862a30
5 changed files with 182 additions and 14 deletions

View File

@ -55,8 +55,19 @@ class ASTNodeVirturalVisitor : public ASTNodeVisitorBase {
};
class ASTSemanticCheckVisitor : public ASTNodeVirturalVisitor {
bool is_in_func;
FunctionSchema cur_func_schema;
size_t loop_level;
std::shared_ptr<GlobalScope> global_scope;
friend std::shared_ptr<Program_ASTNode> CheckAndDecorate(std::shared_ptr<Program_ASTNode> src);
bool ClassExists(const std::string &name) {
if (name == "int" || name == "bool") return true;
return global_scope->classes.find(name) != global_scope->classes.end();
}
public:
ASTSemanticCheckVisitor() = default;
ASTSemanticCheckVisitor() : is_in_func(false), loop_level(0) {}
// Structural AST Nodes
void ActuralVisit(FuncDef_ASTNode *node) override;
void ActuralVisit(ClassDef_ASTNode *node) override;

View File

@ -19,6 +19,7 @@ class ScopeBase {
ScopeBase *parent; // cannot use std::shared_ptr<ScopeBase> because of circular dependency
virtual bool VariableNameAvailable(const std::string &name, int ttl) = 0;
virtual bool add_variable(const std::string &name, const ExprTypeInfo &type) = 0;
virtual ExprTypeInfo fetch_varaible(const std::string &name) = 0;
static inline bool IsKeyWord(const std::string &name) {
static const std::unordered_set<std::string> keywords = {"void", "bool", "int", "string", "new", "class",
"null", "true", "false", "this", "if", "else",
@ -43,6 +44,12 @@ class LocalScope : public ScopeBase {
local_variables[name] = type;
return true;
}
virtual ExprTypeInfo fetch_varaible(const std::string &name) override {
if (local_variables.find(name) != local_variables.end()) {
return local_variables[name];
}
return parent->fetch_varaible(name);
}
bool VariableNameAvailable(const std::string &name, int ttl) override {
if (ttl == 0 && IsKeyWord(name)) {
return false;
@ -63,10 +70,19 @@ struct FunctionSchema {
class FunctionScope : public ScopeBase {
friend std::shared_ptr<class Program_ASTNode> CheckAndDecorate(std::shared_ptr<class Program_ASTNode> src);
friend class Visitor;
friend class ASTSemanticCheckVisitor;
FunctionSchema schema;
bool add_variable([[maybe_unused]] const std::string &name, [[maybe_unused]] const ExprTypeInfo &type) override {
throw std::runtime_error("FunctionScope does not support add_variable");
}
virtual ExprTypeInfo fetch_varaible(const std::string &name) override {
for (const auto &arg : schema.arguments) {
if (arg.second == name) {
return arg.first;
}
}
return parent->fetch_varaible(name);
}
bool VariableNameAvailable(const std::string &name, int ttl) override {
if (ttl == 0 && IsKeyWord(name)) {
return false;
@ -99,6 +115,12 @@ class ClassDefScope : public ScopeBase {
member_variables[name] = type;
return true;
}
virtual ExprTypeInfo fetch_varaible(const std::string &name) override {
if (member_variables.find(name) != member_variables.end()) {
return member_variables[name];
}
return parent->fetch_varaible(name);
}
bool add_function(const std::string &name, std::shared_ptr<FunctionScope> ptr) {
if (IsKeyWord(name)) return false;
if (member_variables.find(name) != member_variables.end()) {
@ -129,6 +151,7 @@ class ClassDefScope : public ScopeBase {
};
class GlobalScope : public ScopeBase {
friend class Visitor;
friend class ASTSemanticCheckVisitor;
friend std::shared_ptr<class Program_ASTNode> CheckAndDecorate(std::shared_ptr<class Program_ASTNode> src);
std::unordered_map<std::string, ExprTypeInfo> global_variables;
std::unordered_map<std::string, std::shared_ptr<FunctionScope>> global_functions;
@ -192,6 +215,12 @@ class GlobalScope : public ScopeBase {
}
return true;
}
virtual ExprTypeInfo fetch_varaible(const std::string &name) override {
if (global_variables.find(name) != global_variables.end()) {
return global_variables[name];
}
throw SemanticError("Variable " + name + " not found", 1);
}
public:
GlobalScope() { parent = nullptr; }