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
128 changes: 92 additions & 36 deletions packages/cxx-gen-ast/src/new_ast_rewriter_cc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import * as fs from "fs";

export function new_ast_rewriter_cc({
ast,
opName,
opHeader,
output,
}: {
Expand Down Expand Up @@ -61,16 +60,19 @@ export function new_ast_rewriter_cc({
const className = chopAST(base);
emit();
emit(` struct ASTRewriter::${className}Visitor {`);
emit(` ${opName}& rewrite;`);
emit(` ASTRewriter& rewrite;`);
emit(
` [[nodiscard]] auto translationUnit() const -> TranslationUnit* { return rewrite.unit_; }`
`[[nodiscard]] auto translationUnit() const -> TranslationUnit* { return rewrite.unit_; }`
);
emit();
emit(
` [[nodiscard]] auto control() const -> Control* { return rewrite.control(); }`
`[[nodiscard]] auto control() const -> Control* { return rewrite.control(); }`
);
emit(
` [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); }`
`[[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); }`
);
emit(
`[[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; }`
);
nodes.forEach(({ name }) => {
emit();
Expand All @@ -88,24 +90,48 @@ export function new_ast_rewriter_cc({
emit(`auto _ = Binder::ScopeGuard(&rewrite.binder_);

if (ast->${blockSymbol.name}) {
copy->${blockSymbol.name} = control()->newBlockSymbol(rewrite.binder_.scope(),
ast->${blockSymbol.name}->location());

rewrite.binder_.setScope(copy->${blockSymbol.name});
copy->${blockSymbol.name} = rewrite.binder_.enterBlock(ast->${blockSymbol.name}->location());
}
`);
}

let typeAttr: Member | undefined;

members.forEach((m) => {
if (m === blockSymbol) return;
if (m === typeAttr) return;

switch (m.kind) {
case "node": {
if (isBase(m.type)) {
emit(` copy->${m.name} = ${visitor}(ast->${m.name});`);
emit(`copy->${m.name} = ${visitor}(ast->${m.name});`);

switch (m.type) {
case "DeclaratorAST":
const specsAttr =
members.find((m) => m.name == "typeSpecifierList")?.name ??
members.find((m) => m.name == "declSpecifierList")?.name;
if (specsAttr) {
emit();
emit(
`auto ${m.name}Type = getDeclaratorType(translationUnit(), copy->${m.name}, ${specsAttr}Ctx.getType());`
);

typeAttr = members.find(
(m) => m.kind === "attribute" && m.name === "type"
);

if (typeAttr) {
emit(`copy->${typeAttr.name} = ${m.name}Type;`);
}
}
break;
default:
break;
} // switch
} else {
emit(
` copy->${m.name} = ast_cast<${m.type}>(${visitor}(ast->${m.name}));`
`copy->${m.name} = ast_cast<${m.type}>(${visitor}(ast->${m.name}));`
);
}
break;
Expand All @@ -116,36 +142,35 @@ export function new_ast_rewriter_cc({
// check the base type has a context that must be passed
switch (m.type) {
case "SpecifierAST":
emit(` DeclSpecs ${m.name}Ctx{translationUnit()};`);
emit(` auto ${m.name}Ctx = DeclSpecs{rewriter()};`);
break;

default:
break;
} // switch

emit(` if (auto it = ast->${m.name}) {`);
emit(` auto out = &copy->${m.name};`);

emit(` for (auto node : ListView{ast->${m.name}}) {`);
emit(
`for (auto ${m.name} = &copy->${m.name}; auto node : ListView{ast->${m.name}}) {`
);

switch (m.type) {
case "InitDeclaratorAST":
emit(
` auto value = ${visitor}(node, declSpecifierListCtx);`
);
emit(`auto value = ${visitor}(node, declSpecifierListCtx);`);
break;

default:
emit(` auto value = ${visitor}(node);`);
emit(`auto value = ${visitor}(node);`);
break;
} // switch

if (isBase(m.type)) {
emit(`*out = make_list_node(arena(), value);`);
emit(`*${m.name} = make_list_node(arena(), value);`);
} else {
emit(`*out = make_list_node(arena(), ast_cast<${m.type}>(value));`);
emit(
`*${m.name} = make_list_node(arena(), ast_cast<${m.type}>(value));`
);
}
emit(` out = &(*out)->next;`);
emit(`${m.name} = &(*${m.name})->next;`);

// update the context if needed
switch (m.type) {
Expand All @@ -158,7 +183,6 @@ export function new_ast_rewriter_cc({
} // switch

emit(` }`);
emit(` }`);
emit();
break;
}
Expand All @@ -180,7 +204,7 @@ export function new_ast_rewriter_cc({

switch (base) {
case "ExpressionAST":
emit(`auto ${opName}::operator()(${base}* ast) -> ${base}* {`);
emit(`auto ASTRewriter::operator()(${base}* ast) -> ${base}* {`);
emit(` if (!ast) return {};`);
emit(` auto expr = visit(${chopAST(base)}Visitor{*this}, ast);`);
emit(` if (expr) typeChecker_->check(expr);`);
Expand All @@ -189,15 +213,15 @@ export function new_ast_rewriter_cc({
break;

case "SpecifierAST":
emit(`auto ${opName}::operator()(${base}* ast) -> ${base}* {`);
emit(`auto ASTRewriter::operator()(${base}* ast) -> ${base}* {`);
emit(` if (!ast) return {};`);
emit(` auto specifier = visit(${chopAST(base)}Visitor{*this}, ast);`);
emit(` return specifier;`);
emit(`}`);
break;

default:
emit(`auto ${opName}::operator()(${base}* ast) -> ${base}* {`);
emit(`auto ASTRewriter::operator()(${base}* ast) -> ${base}* {`);
emit(` if (!ast) return {};`);
emit(` return visit(${chopAST(base)}Visitor{*this}, ast);`);
emit(`}`);
Expand All @@ -210,11 +234,11 @@ export function new_ast_rewriter_cc({
switch (name) {
case "InitDeclaratorAST":
emit(
`auto ${opName}::operator()(${name}* ast, const DeclSpecs& declSpecs) -> ${name}* {`
`auto ASTRewriter::operator()(${name}* ast, const DeclSpecs& declSpecs) -> ${name}* {`
);
break;
default:
emit(`auto ${opName}::operator()(${name}* ast) -> ${name}* {`);
emit(`auto ASTRewriter::operator()(${name}* ast) -> ${name}* {`);
break;
} // switch

Expand All @@ -235,8 +259,32 @@ export function new_ast_rewriter_cc({
nodes.forEach(({ name, members }) => {
emit();
emit(
`auto ${opName}::${className}Visitor::operator()(${name}* ast) -> ${base}* {`
`auto ASTRewriter::${className}Visitor::operator()(${name}* ast) -> ${base}* {`
);
if (name === "IdExpressionAST") {
emit(`
if (auto x = symbol_cast<NonTypeParameterSymbol>(ast->symbol);
x && x->depth() == 0 && x->index() < rewrite.templateArguments_.size()) {
auto initializerPtr =
std::get_if<ExpressionAST*>(&rewrite.templateArguments_[x->index()]);
if (!initializerPtr) {
cxx_runtime_error("expected initializer for non-type template parameter");
}

auto initializer = rewrite(*initializerPtr);

if (auto eq = ast_cast<EqualInitializerAST>(initializer)) {
return eq->expression;
}

if (auto bracedInit = ast_cast<BracedInitListAST>(initializer)) {
if (bracedInit->expressionList && !bracedInit->expressionList->next) {
return bracedInit->expressionList->value;
}
}
}
`);
}
emit(` auto copy = make_node<${name}>(arena());`);
emit();
ast.baseMembers.get(base)?.forEach((m) => {
Expand Down Expand Up @@ -266,21 +314,29 @@ export function new_ast_rewriter_cc({

namespace cxx {

${opName}::${opName}(TypeChecker* typeChcker,
ASTRewriter::ASTRewriter(TypeChecker* typeChcker,
const std::vector<TemplateArgument>& templateArguments)
: typeChecker_(typeChcker)
, unit_(typeChcker->translationUnit())
, templateArguments_(templateArguments)
, binder_(typeChcker->translationUnit()) {}

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

auto ASTRewriter::control() const -> Control* {
return unit_->control();
}

auto ASTRewriter::arena() const -> Arena* {
return unit_->arena();
}

auto ${opName}::control() const -> Control* {
return unit_->control();
auto ASTRewriter::restrictedToDeclarations() const -> bool {
return restrictedToDeclarations_;
}

auto ${opName}::arena() const -> Arena* {
return unit_->arena();
void ASTRewriter::setRestrictedToDeclarations(bool restrictedToDeclarations) {
restrictedToDeclarations_ = restrictedToDeclarations;
}

${code.join("\n")}
Expand Down
37 changes: 26 additions & 11 deletions packages/cxx-gen-ast/src/new_ast_rewriter_h.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import * as fs from "fs";

export function new_ast_rewriter_h({
ast,
opName,
output,
}: {
ast: AST;
Expand Down Expand Up @@ -90,23 +89,39 @@ class TypeChecker;
class Control;
class Arena;

class ${opName} {
class ASTRewriter {
public:
explicit ${opName}(TypeChecker* typeChecker, const std::vector<TemplateArgument>& templateArguments);
~${opName}();
explicit ASTRewriter(TypeChecker* typeChecker, const std::vector<TemplateArgument>& templateArguments);
~ASTRewriter();

[[nodiscard]] auto translationUnit() const -> TranslationUnit* { return unit_; }
[[nodiscard]] auto translationUnit() const -> TranslationUnit* { return unit_; }

[[nodiscard]] auto control() const -> Control*;
[[nodiscard]] auto arena() const -> Arena*;
[[nodiscard]] const std::vector<TemplateArgument>& templateArguments() const {
return templateArguments_;
}

[[nodiscard]] auto typeChecker() const -> TypeChecker* {
return typeChecker_;
}

[[nodiscard]] auto binder() -> Binder& { return binder_; }

[[nodiscard]] auto control() const -> Control*;
[[nodiscard]] auto arena() const -> Arena*;

[[nodiscard]] auto restrictedToDeclarations() const -> bool;
void setRestrictedToDeclarations(bool restrictedToDeclarations);

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

private:
TypeChecker* typeChecker_ = nullptr;
const std::vector<TemplateArgument>& templateArguments_;
TranslationUnit* unit_ = nullptr;
Binder binder_;
[[nodiscard]] auto rewriter() -> ASTRewriter* { return this; }

TypeChecker* typeChecker_ = nullptr;
const std::vector<TemplateArgument>& templateArguments_;
TranslationUnit* unit_ = nullptr;
Binder binder_;
bool restrictedToDeclarations_ = false;
};

} // namespace cxx
Expand Down
7 changes: 5 additions & 2 deletions src/frontend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

aux_source_directory(cxx SOURCES)

add_executable(cxx ${SOURCES})
add_executable(cxx
cxx/ast_printer.cc
cxx/frontend.cc
cxx/verify_diagnostics_client.cc
)

target_link_libraries(cxx PRIVATE cxx-lsp)

Expand Down
2 changes: 1 addition & 1 deletion src/parser/cxx/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -2120,7 +2120,7 @@ class ConditionExpressionAST final : public ExpressionAST {
List<SpecifierAST*>* declSpecifierList = nullptr;
DeclaratorAST* declarator = nullptr;
ExpressionAST* initializer = nullptr;
Symbol* symbol = nullptr;
VariableSymbol* symbol = nullptr;

void accept(ASTVisitor* visitor) override { visitor->visit(this); }

Expand Down
Loading