diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc index 9eec516580..09c20a32d0 100644 --- a/src/writer/wgsl/generator_impl.cc +++ b/src/writer/wgsl/generator_impl.cc @@ -19,6 +19,7 @@ #include "src/ast/binding_decoration.h" #include "src/ast/builtin_decoration.h" #include "src/ast/decorated_variable.h" +#include "src/ast/identifier_expression.h" #include "src/ast/location_decoration.h" #include "src/ast/set_decoration.h" #include "src/ast/struct.h" @@ -76,7 +77,14 @@ bool GeneratorImpl::Generate(const ast::Module& module) { return true; } +void GeneratorImpl::make_indent() { + for (size_t i = 0; i < indent_; i++) { + out_ << " "; + } +} + bool GeneratorImpl::EmitAliasType(const ast::type::AliasType* alias) { + make_indent(); out_ << "type " << alias->name() << " = "; if (!EmitType(alias->type())) { return false; @@ -87,6 +95,7 @@ bool GeneratorImpl::EmitAliasType(const ast::type::AliasType* alias) { } bool GeneratorImpl::EmitEntryPoint(const ast::EntryPoint* ep) { + make_indent(); out_ << "entry_point " << ep->stage() << " "; if (!ep->name().empty() && ep->name() != ep->function_name()) { out_ << R"(as ")" << ep->name() << R"(" )"; @@ -96,7 +105,25 @@ bool GeneratorImpl::EmitEntryPoint(const ast::EntryPoint* ep) { return true; } +bool GeneratorImpl::EmitExpression(ast::Expression* expr) { + if (expr->IsIdentifier()) { + bool first = true; + for (const auto& part : expr->AsIdentifier()->name()) { + if (!first) { + out_ << "::"; + } + first = false; + out_ << part; + } + } else { + error_ = "unknown expression type"; + return false; + } + return true; +} + bool GeneratorImpl::EmitImport(const ast::Import* import) { + make_indent(); out_ << R"(import ")" << import->path() << R"(" as )" << import->name() << ";" << std::endl; return true; @@ -143,9 +170,10 @@ bool GeneratorImpl::EmitType(ast::type::Type* type) { out_ << "[[" << str->decoration() << "]] "; } out_ << "struct {" << std::endl; + + increment_indent(); for (const auto& mem : str->members()) { - // TODO(dsinclair): This formats bad with nested structs - out_ << " "; + make_indent(); if (!mem->decorations().empty()) { out_ << "[["; bool first = true; @@ -169,6 +197,8 @@ bool GeneratorImpl::EmitType(ast::type::Type* type) { } out_ << ";" << std::endl; } + decrement_indent(); + make_indent(); out_ << "}"; } else if (type->IsU32()) { @@ -191,6 +221,8 @@ bool GeneratorImpl::EmitType(ast::type::Type* type) { } bool GeneratorImpl::EmitVariable(ast::Variable* var) { + make_indent(); + if (var->IsDecorated()) { if (!EmitVariableDecorations(var->AsDecorated())) { return false; @@ -212,8 +244,10 @@ bool GeneratorImpl::EmitVariable(ast::Variable* var) { } if (var->initializer() != nullptr) { - // out_ << " = "; - // EmitExpr(var-initializer()); + out_ << " = "; + if (!EmitExpression(var->initializer())) { + return false; + } } out_ << ";" << std::endl; diff --git a/src/writer/wgsl/generator_impl.h b/src/writer/wgsl/generator_impl.h index c48ba0901e..9d526a89ae 100644 --- a/src/writer/wgsl/generator_impl.h +++ b/src/writer/wgsl/generator_impl.h @@ -47,6 +47,20 @@ class GeneratorImpl { /// @returns the error from the generator std::string error() const { return error_; } + /// Increment the emitter indent level + void increment_indent() { indent_ += 2; } + /// Decrement the emiter indent level + void decrement_indent() { + if (indent_ < 2) { + indent_ = 0; + return; + } + indent_ -= 2; + } + + /// Writes the current indent to the output stream + void make_indent(); + /// Handles generating an alias /// @param alias the alias to generate /// @returns true if the alias was emitted @@ -55,6 +69,10 @@ class GeneratorImpl { /// @param ep the entry point /// @returns true if the entry point was emitted bool EmitEntryPoint(const ast::EntryPoint* ep); + /// Handles generate an Expression + /// @param expr the expression + /// @returns true if the expression was emitted + bool EmitExpression(ast::Expression* expr); /// Handles generating an import command /// @param import the import to generate /// @returns true if the import was emitted @@ -73,6 +91,7 @@ class GeneratorImpl { bool EmitVariableDecorations(ast::DecoratedVariable* var); private: + size_t indent_ = 0; std::ostringstream out_; std::string error_; }; diff --git a/src/writer/wgsl/generator_impl_test.cc b/src/writer/wgsl/generator_impl_test.cc index 89d4513667..813d71bb4f 100644 --- a/src/writer/wgsl/generator_impl_test.cc +++ b/src/writer/wgsl/generator_impl_test.cc @@ -23,6 +23,7 @@ #include "src/ast/builtin.h" #include "src/ast/builtin_decoration.h" #include "src/ast/decorated_variable.h" +#include "src/ast/identifier_expression.h" #include "src/ast/location_decoration.h" #include "src/ast/set_decoration.h" #include "src/ast/struct.h" @@ -83,7 +84,7 @@ TEST_F(GeneratorImplTest, DISABLED_EmitAliasType_Struct) { GeneratorImpl g; ASSERT_TRUE(g.EmitAliasType(&alias)); EXPECT_EQ(g.result(), R"(type a = struct { - a: f32; + a : f32; [[offset 4]] b : i32; } )"); @@ -322,9 +323,48 @@ TEST_F(GeneratorImplTest, EmitVariable_Decorated_Multiple) { )"); } -TEST_F(GeneratorImplTest, DISABLED_EmitVariable_Initializer) {} +TEST_F(GeneratorImplTest, EmitVariable_Initializer) { + auto ident = std::make_unique("initializer"); -TEST_F(GeneratorImplTest, DISABLED_EmitVariable_Const) {} + ast::type::F32Type f32; + ast::Variable v("a", ast::StorageClass::kNone, &f32); + v.set_initializer(std::move(ident)); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitVariable(&v)); + EXPECT_EQ(g.result(), R"(var a : f32 = initializer; +)"); +} + +TEST_F(GeneratorImplTest, EmitVariable_Const) { + auto ident = std::make_unique("initializer"); + + ast::type::F32Type f32; + ast::Variable v("a", ast::StorageClass::kNone, &f32); + v.set_initializer(std::move(ident)); + v.set_is_const(true); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitVariable(&v)); + EXPECT_EQ(g.result(), R"(const a : f32 = initializer; +)"); +} + +TEST_F(GeneratorImplTest, EmitExpression_Identifier) { + ast::IdentifierExpression i("init"); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitExpression(&i)); + EXPECT_EQ(g.result(), "init"); +} + +TEST_F(GeneratorImplTest, EmitExpression_Identifier_MultipleNames) { + ast::IdentifierExpression i({"std", "glsl", "init"}); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitExpression(&i)); + EXPECT_EQ(g.result(), "std::glsl::init"); +} } // namespace } // namespace wgsl