4 #include <memory_resource>
7 #include "ast/AstNode.h"
8 #include "ast/DeclContext.h"
9 #include "ast/ExprEvaluator.h"
10 #include "ast/ExprNode.h"
11 #include "diagnostics/Diagnostics.h"
12 #include "diagnostics/Location.h"
13 #include "semantic/ExprTypeResolver.h"
14 #include "semantic/HierarchyChecker.h"
15 #include "semantic/Semantic.h"
16 #include "utils/BumpAllocator.h"
17 #include "utils/EnumMacros.h"
36 using ExprResolverTy =
37 std::variant<ExprNameWrapper*, ast::ExprNode*, ast::ExprNodeList>;
48 #define NAME_TYPE_LIST(F)
53 F(SingleAmbiguousName)
72 ast::exprnode::MemberAccess* op)
79 void reclassify(Type type, ast::Decl
const* resolution,
80 ast::Type
const* typeResolution) {
81 this->resolution_ = resolution;
83 this->typeResolution_ = typeResolution;
86 void reclassify(Type type, NameResolver::Pkg
const* resolution) {
87 this->resolution_ = resolution;
89 this->typeResolution_ =
nullptr;
92 void verifyInvariants(Type expectedTy)
const;
95 assert(prev_.has_value() &&
"No previous value");
96 assert(std::holds_alternative<ExprNameWrapper*>(prev_.value()) &&
97 "Previous value is not a wrapper");
98 return std::get<ExprNameWrapper*>(prev_.value());
102 assert(prev_.has_value() &&
"No previous value");
103 if(
auto* list = std::get_if<ExprNameWrapper*>(&prev_.value()))
return *list;
118 Type type()
const {
return type_; }
121 auto resolution()
const {
return resolution_.value(); }
123 auto typeResolution()
const {
return typeResolution_; }
125 void setPrev(std::optional<PrevTy> prev) {
128 if(
auto wrapper = std::get_if<ExprNameWrapper*>(&prev.value()))
129 assert(*wrapper &&
"Previous value is nullptr");
132 std::optional<PrevTy> prev()
const {
return prev_; }
134 void dump(
int indent)
const;
135 std::string_view type_string()
const {
136 return Type_to_string(type_,
"Unknown Type");
140 ast::exprnode::MemberName* node;
141 ast::exprnode::MemberAccess* op;
146 std::optional<PrevTy> prev_;
147 NameResolver::ConstImportOpt resolution_;
148 ast::Type
const* typeResolution_;
157 class ExprResolver
final :
public ast::ExprEvaluator<internal::ExprResolverTy> {
158 using ETy = internal::ExprResolverTy;
159 using Heap = std::pmr::memory_resource;
163 : diag{diag}, heap{heap}, alloc{heap} {}
164 void Init(ExprTypeResolver* TR, NameResolver* NR, ast::Semantic* Sema,
165 semantic::HierarchyChecker* HC) {
172 void BeginCU(ast::CompilationUnit
const* cu) { cu_ = cu; }
173 void BeginContext(ast::DeclContext
const* ctx) { lctx_ = ctx; }
174 ast::ExprNodeList Evaluate(ast::Expr* expr) {
175 loc_ = expr->location();
176 lscope_ = expr->scope();
177 auto ret = EvaluateList(expr->list());
178 return resolveExprNode(ret);
182 ETy EvaluateList(ast::ExprNodeList subexpr)
override final {
184 if(
auto h = dyn_cast<utils::CustomBufferResource*>(heap)) h->reset();
186 return ast::ExprEvaluator<internal::ExprResolverTy>::EvaluateList(subexpr);
190 using Type = ast::Type;
191 using BinaryOp = ast::exprnode::BinaryOp;
192 using UnaryOp = ast::exprnode::UnaryOp;
193 using DotOp = ast::exprnode::MemberAccess;
194 using MethodOp = ast::exprnode::MethodInvocation;
195 using NewOp = ast::exprnode::ClassInstanceCreation;
196 using NewArrayOp = ast::exprnode::ArrayInstanceCreation;
197 using ArrayAccessOp = ast::exprnode::ArrayAccess;
198 using CastOp = ast::exprnode::Cast;
199 using ExprValue = ast::exprnode::ExprValue;
201 ETy mapValue(ExprValue& node)
const override;
202 ETy evalBinaryOp(BinaryOp& op,
const ETy lhs,
const ETy rhs)
const override;
203 ETy evalUnaryOp(UnaryOp& op,
const ETy rhs)
const override;
204 ETy evalMemberAccess(DotOp& op,
const ETy lhs,
const ETy field)
const override;
205 ETy evalMethodCall(MethodOp& op,
const ETy method,
206 const op_array& args)
const override;
207 ETy evalNewObject(NewOp& op,
const ETy object,
208 const op_array& args)
const override;
209 ETy evalNewArray(NewArrayOp& op,
const ETy type,
const ETy size)
const override;
210 ETy evalArrayAccess(ArrayAccessOp& op,
const ETy array,
211 const ETy index)
const override;
212 ETy evalCast(CastOp& op,
const ETy type,
const ETy value)
const override;
213 bool validate(ETy
const& value)
const override;
216 using ty_array = std::pmr::vector<ast::Type
const*>;
219 ast::ExprNodeList resolveExprNode(
const ETy node)
const;
225 ast::DeclContext
const* ctx)
const;
228 NameResolver::ConstImportOpt import)
const;
238 ast::exprnode::MemberName* node)
const {
239 if(
auto method = dyn_cast<ast::exprnode::MethodName*>(node)) {
240 return alloc.new_object<internal::ExprNameWrapper>(
241 internal::ExprNameWrapper::Type::MethodName, method,
nullptr);
243 return reclassifySingleAmbiguousName(
244 alloc.new_object<internal::ExprNameWrapper>(
245 internal::ExprNameWrapper::Type::SingleAmbiguousName,
250 ast::ExprNodeList recursiveReduce(internal::ExprNameWrapper* node)
const;
252 ast::DeclContext
const* getMethodParent(internal::ExprNameWrapper* node)
const;
254 ast::MethodDecl
const* resolveMethodOverload(ast::DeclContext
const* ctx,
255 std::string_view name,
256 const ty_array& argtys,
259 bool isMethodMoreSpecific(ast::MethodDecl
const* a,
260 ast::MethodDecl
const* b)
const;
262 bool areParameterTypesApplicable(ast::MethodDecl
const* method,
263 const ty_array& argtys)
const;
265 bool isAccessible(ast::Modifiers, ast::DeclContext
const*)
const;
267 utils::Generator<ast::MethodDecl
const*> getInheritedMethods(
268 ast::DeclContext
const* ctx)
const;
276 const ast::Decl* lookupDecl(ast::DeclContext
const* ctx,
277 std::function<
bool(ast::Decl
const*)> cond)
const;
288 const ast::Decl* lookupNamedDecl(ast::DeclContext
const* ctx,
289 std::string_view name)
const;
293 ast::CompilationUnit
const* cu_;
294 ast::DeclContext
const* lctx_;
295 ast::ScopeID
const* lscope_;
296 semantic::NameResolver* NR;
297 semantic::ExprTypeResolver* TR;
298 semantic::HierarchyChecker* HC;
301 mutable BumpAllocator alloc;