Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions packages/cxx-gen-ast/src/gen_ast_h.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,27 @@ template <typename T>

${code.join("\n")}

[[nodiscard]] inline auto is_prvalue(ExpressionAST* expr) -> bool {
if (!expr) return false;
return expr->valueCategory == ValueCategory::kPrValue;
}

[[nodiscard]] inline auto is_lvalue(ExpressionAST* expr) -> bool {
if (!expr) return false;
return expr->valueCategory == ValueCategory::kLValue;
}

[[nodiscard]] inline auto is_xvalue(ExpressionAST* expr) -> bool {
if (!expr) return false;
return expr->valueCategory == ValueCategory::kXValue;
}

[[nodiscard]] inline auto is_glvalue(ExpressionAST* expr) -> bool {
if (!expr) return false;
return expr->valueCategory == ValueCategory::kLValue ||
expr->valueCategory == ValueCategory::kXValue;
}

} // namespace cxx
`;

Expand Down
5 changes: 3 additions & 2 deletions packages/cxx-gen-ast/src/new_ast_rewriter_cc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,9 @@ namespace cxx {
${opName}::${opName}(TypeChecker* typeChcker,
const std::vector<TemplateArgument>& templateArguments)
: typeChecker_(typeChcker)
, unit_(typeChcker->translationUnit())
, templateArguments_(templateArguments) {}
, unit_(typeChcker->translationUnit())
, templateArguments_(templateArguments)
, binder_(typeChcker->translationUnit()) {}

${opName}::~${opName}() {}

Expand Down
2 changes: 2 additions & 0 deletions packages/cxx-gen-ast/src/new_ast_rewriter_h.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export function new_ast_rewriter_h({

#include <cxx/ast_fwd.h>
#include <cxx/names_fwd.h>
#include <cxx/binder.h>

#include <vector>

Expand All @@ -96,6 +97,7 @@ private:
TypeChecker* typeChecker_ = nullptr;
const std::vector<TemplateArgument>& templateArguments_;
TranslationUnit* unit_ = nullptr;
Binder binder_;
};

} // namespace cxx
Expand Down
21 changes: 21 additions & 0 deletions src/parser/cxx/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -5328,4 +5328,25 @@ template <>
} // switch
}

[[nodiscard]] inline auto is_prvalue(ExpressionAST* expr) -> bool {
if (!expr) return false;
return expr->valueCategory == ValueCategory::kPrValue;
}

[[nodiscard]] inline auto is_lvalue(ExpressionAST* expr) -> bool {
if (!expr) return false;
return expr->valueCategory == ValueCategory::kLValue;
}

[[nodiscard]] inline auto is_xvalue(ExpressionAST* expr) -> bool {
if (!expr) return false;
return expr->valueCategory == ValueCategory::kXValue;
}

[[nodiscard]] inline auto is_glvalue(ExpressionAST* expr) -> bool {
if (!expr) return false;
return expr->valueCategory == ValueCategory::kLValue ||
expr->valueCategory == ValueCategory::kXValue;
}

} // namespace cxx
5 changes: 4 additions & 1 deletion src/parser/cxx/ast_rewriter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ ASTRewriter::ASTRewriter(TypeChecker* typeChcker,
const std::vector<TemplateArgument>& templateArguments)
: typeChecker_(typeChcker),
unit_(typeChcker->translationUnit()),
templateArguments_(templateArguments) {}
templateArguments_(templateArguments),
binder_(typeChcker->translationUnit()) {}

ASTRewriter::~ASTRewriter() {}

Expand Down Expand Up @@ -1027,6 +1028,7 @@ auto ASTRewriter::operator()(EnumeratorAST* ast) -> EnumeratorAST* {
copy->equalLoc = ast->equalLoc;
copy->expression = operator()(ast->expression);
copy->identifier = ast->identifier;
copy->symbol = ast->symbol;

return copy;
}
Expand Down Expand Up @@ -3094,6 +3096,7 @@ auto ASTRewriter::ExpressionVisitor::operator()(ConditionExpressionAST* ast)

copy->declarator = rewrite(ast->declarator);
copy->initializer = rewrite(ast->initializer);
copy->symbol = ast->symbol;

return copy;
}
Expand Down
2 changes: 2 additions & 0 deletions src/parser/cxx/ast_rewriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#pragma once

#include <cxx/ast_fwd.h>
#include <cxx/binder.h>
#include <cxx/names_fwd.h>

#include <vector>
Expand Down Expand Up @@ -136,6 +137,7 @@ class ASTRewriter {
TypeChecker* typeChecker_ = nullptr;
const std::vector<TemplateArgument>& templateArguments_;
TranslationUnit* unit_ = nullptr;
Binder binder_;
};

} // namespace cxx
84 changes: 84 additions & 0 deletions src/parser/cxx/binder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,22 @@ void Binder::bind(ParameterDeclarationAST* ast, const Decl& decl,
}
}

void Binder::bind(DecltypeSpecifierAST* ast) {
if (auto id = ast_cast<IdExpressionAST>(ast->expression)) {
if (id->symbol) ast->type = id->symbol->type();
} else if (auto member = ast_cast<MemberExpressionAST>(ast->expression)) {
if (member->symbol) ast->type = member->symbol->type();
} else if (ast->expression && ast->expression->type) {
if (is_lvalue(ast->expression)) {
ast->type = control()->add_lvalue_reference(ast->expression->type);
} else if (is_xvalue(ast->expression)) {
ast->type = control()->add_rvalue_reference(ast->expression->type);
} else {
ast->type = ast->expression->type;
}
}
}

void Binder::bind(EnumeratorAST* ast, const Type* type,
std::optional<ConstValue> value) {
auto symbol = control()->newEnumeratorSymbol(scope(), ast->identifierLoc);
Expand Down Expand Up @@ -475,6 +491,10 @@ void Binder::bind(UsingDirectiveAST* ast) {
}
}

void Binder::bind(TypeIdAST* ast, const Decl& decl) {
ast->type = getDeclaratorType(unit_, ast->declarator, decl.specs.getType());
}

auto Binder::declareTypedef(DeclaratorAST* declarator, const Decl& decl)
-> TypeAliasSymbol* {
auto name = decl.getName();
Expand Down Expand Up @@ -617,4 +637,68 @@ auto Binder::isConstructor(Symbol* symbol) const -> bool {
return true;
}

auto Binder::resolve(NestedNameSpecifierAST* nestedNameSpecifier,
UnqualifiedIdAST* unqualifiedId, bool canInstantiate)
-> Symbol* {
if (auto templateId = ast_cast<SimpleTemplateIdAST>(unqualifiedId)) {
if (!canInstantiate) return nullptr;

auto instance = instantiate(templateId);

if (!is_type(instance)) return nullptr;

return instance;
}

auto name = ast_cast<NameIdAST>(unqualifiedId);

auto symbol =
Lookup{scope()}.lookupType(nestedNameSpecifier, name->identifier);

if (!is_type(symbol)) return nullptr;

return symbol;
}

auto Binder::instantiate(SimpleTemplateIdAST* templateId) -> Symbol* {
std::vector<TemplateArgument> args;
for (auto it = templateId->templateArgumentList; it; it = it->next) {
if (auto arg = ast_cast<TypeTemplateArgumentAST>(it->value)) {
args.push_back(arg->typeId->type);
} else {
error(it->value->firstSourceLocation(),
std::format("only type template arguments are supported"));
}
}

auto needsInstantiation = [&]() -> bool {
if (args.empty()) return true;
for (std::size_t i = 0; i < args.size(); ++i) {
auto typeArgument = std::get_if<const Type*>(&args[i]);
if (!typeArgument) return true;
auto ty = type_cast<TypeParameterType>(*typeArgument);
if (!ty) return true;
if (ty->symbol()->index() != i) return true;
}
return false;
};

if (!needsInstantiation()) return nullptr;

auto symbol = control()->instantiate(unit_, templateId->primaryTemplateSymbol,
std::move(args));

return symbol;
}

void Binder::bind(IdExpressionAST* ast) {
if (ast->unqualifiedId) {
auto name = get_name(control(), ast->unqualifiedId);
const Name* componentName = name;
if (auto templateId = name_cast<TemplateId>(name))
componentName = templateId->name();
ast->symbol = Lookup{scope()}(ast->nestedNameSpecifier, componentName);
}
}

} // namespace cxx
12 changes: 12 additions & 0 deletions src/parser/cxx/binder.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ class Binder {

void complete(ClassSpecifierAST* ast);

void bind(DecltypeSpecifierAST* ast);

void bind(EnumeratorAST* ast, const Type* type,
std::optional<ConstValue> value);

Expand Down Expand Up @@ -121,6 +123,16 @@ class Binder {

void bind(UsingDirectiveAST* ast);

void bind(TypeIdAST* ast, const Decl& decl);

void bind(IdExpressionAST* ast);

[[nodiscard]] auto instantiate(SimpleTemplateIdAST* templateId) -> Symbol*;

[[nodiscard]] auto resolve(NestedNameSpecifierAST* nestedNameSpecifier,
UnqualifiedIdAST* unqualifiedId,
bool canInstantiate) -> Symbol*;

class ScopeGuard {
public:
Binder* p = nullptr;
Expand Down
4 changes: 3 additions & 1 deletion src/parser/cxx/cli.cc
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,9 @@ auto CLI::positionals() const -> std::vector<std::string> {
std::vector<std::string> result;
for (const auto& match : result_) {
if (auto p = std::get_if<CLIPositional>(&match)) {
result.push_back(std::get<0>(*p));
auto arg = std::get<0>(*p);
if (arg.empty()) continue;
result.push_back(std::move(arg));
}
}
return result;
Expand Down
10 changes: 9 additions & 1 deletion src/parser/cxx/decl_specs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,12 @@ void DeclSpecs::Visitor::operator()(ComplexTypeSpecifierAST* ast) {

void DeclSpecs::Visitor::operator()(NamedTypeSpecifierAST* ast) {
specs.typeSpecifier = ast;
if (ast->symbol) specs.type = ast->symbol->type();

if (ast->symbol)
specs.type = ast->symbol->type();
else
specs.type = control()->getUnresolvedNameType(
specs.unit, ast->nestedNameSpecifier, ast->unqualifiedId);
}

void DeclSpecs::Visitor::operator()(AtomicTypeSpecifierAST* ast) {
Expand Down Expand Up @@ -322,6 +327,9 @@ void DeclSpecs::Visitor::operator()(ClassSpecifierAST* ast) {

void DeclSpecs::Visitor::operator()(TypenameSpecifierAST* ast) {
specs.typeSpecifier = ast;
specs.type = control()->getUnresolvedNameType(
specs.unit, ast->nestedNameSpecifier, ast->unqualifiedId);

// ### todo
}

Expand Down
Loading