Add type checker which fills symbols for Ident
This commit is contained in:
parent
8d8a1cef6a
commit
fbf70de089
@ -348,7 +348,7 @@ set(memgraph_src_files
|
||||
${src_dir}/database/graph_db.cpp
|
||||
${src_dir}/database/graph_db_accessor.cpp
|
||||
${src_dir}/query/stripper.cpp
|
||||
${src_dir}/query/backend/cpp/cypher_main_visitor.cpp
|
||||
${src_dir}/query/frontend/ast/cypher_main_visitor.cpp
|
||||
${src_dir}/query/backend/cpp/typed_value.cpp
|
||||
${src_dir}/query/frontend/ast/ast.cpp
|
||||
)
|
||||
|
@ -11,10 +11,49 @@ namespace query {
|
||||
class Frame;
|
||||
class SymbolTable;
|
||||
|
||||
// Forward declares for TreeVisitorBase
|
||||
class Query;
|
||||
class Ident;
|
||||
class Match;
|
||||
class Return;
|
||||
class Pattern;
|
||||
class NodePart;
|
||||
class EdgePart;
|
||||
|
||||
class TreeVisitorBase {
|
||||
public:
|
||||
// Start of the tree is a Query.
|
||||
virtual void PreVisit(Query& query) {}
|
||||
virtual void Visit(Query& query) = 0;
|
||||
virtual void PostVisit(Query& query) {}
|
||||
// Expressions
|
||||
virtual void PreVisit(Ident& ident) {}
|
||||
virtual void Visit(Ident& ident) = 0;
|
||||
virtual void PostVisit(Ident& ident) {}
|
||||
// Clauses
|
||||
virtual void PreVisit(Match& match) {}
|
||||
virtual void Visit(Match& match) = 0;
|
||||
virtual void PostVisit(Match& match) {}
|
||||
virtual void PreVisit(Return& ret) {}
|
||||
virtual void Visit(Return& ret) = 0;
|
||||
virtual void PostVisit(Return& ret) {}
|
||||
// Pattern and its subparts.
|
||||
virtual void PreVisit(Pattern& pattern) {}
|
||||
virtual void Visit(Pattern& pattern) = 0;
|
||||
virtual void PostVisit(Pattern& pattern) {}
|
||||
virtual void PreVisit(NodePart& node_part) {}
|
||||
virtual void Visit(NodePart& node_part) = 0;
|
||||
virtual void PostVisit(NodePart& node_part) {}
|
||||
virtual void PreVisit(EdgePart& edge_part) {}
|
||||
virtual void Visit(EdgePart& edge_part) = 0;
|
||||
virtual void PostVisit(EdgePart& edge_part) {}
|
||||
};
|
||||
|
||||
class Tree {
|
||||
public:
|
||||
Tree(const int uid) : uid_(uid) {}
|
||||
int uid() const { return uid_; }
|
||||
virtual void Accept(TreeVisitorBase& visitor) = 0;
|
||||
|
||||
private:
|
||||
const int uid_;
|
||||
@ -29,9 +68,14 @@ class Ident : public Expr {
|
||||
public:
|
||||
std::string identifier_;
|
||||
TypedValue Evaluate(Frame &frame, SymbolTable &symbol_table) override;
|
||||
void Accept(TreeVisitorBase& visitor) override {
|
||||
visitor.PreVisit(*this);
|
||||
visitor.Visit(*this);
|
||||
visitor.PostVisit(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class Part {};
|
||||
class Part : public Tree {};
|
||||
|
||||
class NodePart : public Part {
|
||||
public:
|
||||
@ -39,12 +83,24 @@ public:
|
||||
// TODO: Mislav call GraphDb::label(label_name) to populate labels_!
|
||||
std::vector<GraphDb::Label> labels_;
|
||||
// TODO: properties
|
||||
void Accept(TreeVisitorBase& visitor) override {
|
||||
visitor.PreVisit(*this);
|
||||
identifier_.Accept(visitor);
|
||||
visitor.Visit(*this);
|
||||
visitor.PostVisit(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class EdgePart : public Part {
|
||||
public:
|
||||
Ident identifier_;
|
||||
// TODO: finish this: properties, types...
|
||||
void Accept(TreeVisitorBase& visitor) override {
|
||||
visitor.PreVisit(*this);
|
||||
identifier_.Accept(visitor);
|
||||
visitor.Visit(*this);
|
||||
visitor.PostVisit(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class Clause : public Tree {};
|
||||
@ -52,20 +108,52 @@ class Clause : public Tree {};
|
||||
class Pattern : public Tree {
|
||||
public:
|
||||
std::vector<std::unique_ptr<Part>> node_parts_;
|
||||
void Accept(TreeVisitorBase& visitor) override {
|
||||
visitor.PreVisit(*this);
|
||||
for (auto& node_part : node_parts_) {
|
||||
node_part->Accept(visitor);
|
||||
}
|
||||
visitor.Visit(*this);
|
||||
visitor.PostVisit(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class Query : public Tree {
|
||||
public:
|
||||
std::vector<std::unique_ptr<Clause>> clauses_;
|
||||
void Accept(TreeVisitorBase& visitor) override {
|
||||
visitor.PreVisit(*this);
|
||||
for (auto& clause : clauses_) {
|
||||
clause->Accept(visitor);
|
||||
}
|
||||
visitor.Visit(*this);
|
||||
visitor.PostVisit(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class Match : public Clause {
|
||||
public:
|
||||
std::vector<std::unique_ptr<Pattern>> patterns_;
|
||||
void Accept(TreeVisitorBase& visitor) override {
|
||||
visitor.PreVisit(*this);
|
||||
for (auto& pattern : patterns_) {
|
||||
pattern->Accept(visitor);
|
||||
}
|
||||
visitor.Visit(*this);
|
||||
visitor.PostVisit(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class Return : public Clause {
|
||||
public:
|
||||
std::vector<std::unique_ptr<Expr>> exprs_;
|
||||
void Accept(TreeVisitorBase& visitor) override {
|
||||
visitor.PreVisit(*this);
|
||||
for (auto& expr : exprs_) {
|
||||
expr->Accept(visitor);
|
||||
}
|
||||
visitor.Visit(*this);
|
||||
visitor.PostVisit(*this);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "query/backend/cpp/cypher_main_visitor.hpp"
|
||||
#include "query/frontend/ast/cypher_main_visitor.hpp"
|
||||
|
||||
#include <climits>
|
||||
#include <string>
|
||||
|
73
src/query/frontend/typecheck/typecheck.hpp
Normal file
73
src/query/frontend/typecheck/typecheck.hpp
Normal file
@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/exceptions/basic_exception.hpp"
|
||||
#include "query/frontend/ast/ast.hpp"
|
||||
#include "query/frontend/typecheck/symbol_table.hpp"
|
||||
|
||||
namespace query {
|
||||
|
||||
class TypeCheckVisitor : public TreeVisitorBase {
|
||||
public:
|
||||
TypeCheckVisitor(SymbolTable& symbol_table) : symbol_table_(symbol_table_) {}
|
||||
|
||||
// Start of the tree is a Query.
|
||||
void Visit(Query& query) override {}
|
||||
// Expressions
|
||||
void Visit(Ident& ident) override {
|
||||
Symbol symbol;
|
||||
} if (scope_.in_pattern) {
|
||||
symbol = GetOrCreateSymbol(ident.identifier_);
|
||||
} else {
|
||||
if (!HasSymbol(ident.identifier_))
|
||||
// TODO: Special exception for type check
|
||||
throw BasicException("Unbound identifier: " + ident.identifier_);
|
||||
symbol = scope_.variables[ident.identifier_];
|
||||
}
|
||||
symbol_table_[ident] = symbol;
|
||||
}
|
||||
// Clauses
|
||||
void Visit(Match& match) override {}
|
||||
void PreVisit(Return& ret) override {
|
||||
scope_.in_return = true;
|
||||
}
|
||||
void PostVisit(Return& ret) override {
|
||||
scope_.in_return = false;
|
||||
}
|
||||
void Visit(Return& ret) override {}
|
||||
// Pattern and its subparts.
|
||||
void PreVisit(Pattern& pattern) override {
|
||||
scope_.in_pattern = true;
|
||||
}
|
||||
void PostVisit(Pattern& pattern) override {
|
||||
scope_.in_pattern = false;
|
||||
}
|
||||
void Visit(Pattern& pattern) override {}
|
||||
void Visit(NodePart& node_part) override {}
|
||||
void Visit(EdgePart& edge_part) override {}
|
||||
|
||||
private:
|
||||
struct Scope {
|
||||
Scope() : in_pattern(false), in_return(false) {}
|
||||
bool in_pattern;
|
||||
bool in_return;
|
||||
std::map<std::string, Symbol> variables;
|
||||
};
|
||||
|
||||
bool HasSymbol(const std::string& name)
|
||||
{
|
||||
return scope_.variables.find(name) != scope_.variables.end();
|
||||
}
|
||||
|
||||
Symbol GetOrCreateSymbol(const std::string& name)
|
||||
{
|
||||
auto search = scope_.variables.find(name)
|
||||
if (search != scope_.variables.end()) {
|
||||
return *search;
|
||||
}
|
||||
scope_.variables[name] = symbol_table_.CreateSymbol(name);
|
||||
}
|
||||
SymbolTable& symbol_table_;
|
||||
Scope scope_;
|
||||
};
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user