Add IdentifierExpression to WGSL writer.

This CL extends the WGSL writer to output IdentiferExpression and fills
out the variable with initializer test case and implementation.

Bug: tint:4
Change-Id: I9db9affb5ec4c4c109488f60bbc81bf3a96eee35
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/16744
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
dan sinclair 2020-03-12 12:43:05 +00:00 committed by dan sinclair
parent d9e9ff3be5
commit 306a2f8381
3 changed files with 100 additions and 7 deletions

View File

@ -19,6 +19,7 @@
#include "src/ast/binding_decoration.h" #include "src/ast/binding_decoration.h"
#include "src/ast/builtin_decoration.h" #include "src/ast/builtin_decoration.h"
#include "src/ast/decorated_variable.h" #include "src/ast/decorated_variable.h"
#include "src/ast/identifier_expression.h"
#include "src/ast/location_decoration.h" #include "src/ast/location_decoration.h"
#include "src/ast/set_decoration.h" #include "src/ast/set_decoration.h"
#include "src/ast/struct.h" #include "src/ast/struct.h"
@ -76,7 +77,14 @@ bool GeneratorImpl::Generate(const ast::Module& module) {
return true; return true;
} }
void GeneratorImpl::make_indent() {
for (size_t i = 0; i < indent_; i++) {
out_ << " ";
}
}
bool GeneratorImpl::EmitAliasType(const ast::type::AliasType* alias) { bool GeneratorImpl::EmitAliasType(const ast::type::AliasType* alias) {
make_indent();
out_ << "type " << alias->name() << " = "; out_ << "type " << alias->name() << " = ";
if (!EmitType(alias->type())) { if (!EmitType(alias->type())) {
return false; return false;
@ -87,6 +95,7 @@ bool GeneratorImpl::EmitAliasType(const ast::type::AliasType* alias) {
} }
bool GeneratorImpl::EmitEntryPoint(const ast::EntryPoint* ep) { bool GeneratorImpl::EmitEntryPoint(const ast::EntryPoint* ep) {
make_indent();
out_ << "entry_point " << ep->stage() << " "; out_ << "entry_point " << ep->stage() << " ";
if (!ep->name().empty() && ep->name() != ep->function_name()) { if (!ep->name().empty() && ep->name() != ep->function_name()) {
out_ << R"(as ")" << ep->name() << R"(" )"; out_ << R"(as ")" << ep->name() << R"(" )";
@ -96,7 +105,25 @@ bool GeneratorImpl::EmitEntryPoint(const ast::EntryPoint* ep) {
return true; 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) { bool GeneratorImpl::EmitImport(const ast::Import* import) {
make_indent();
out_ << R"(import ")" << import->path() << R"(" as )" << import->name() << ";" out_ << R"(import ")" << import->path() << R"(" as )" << import->name() << ";"
<< std::endl; << std::endl;
return true; return true;
@ -143,9 +170,10 @@ bool GeneratorImpl::EmitType(ast::type::Type* type) {
out_ << "[[" << str->decoration() << "]] "; out_ << "[[" << str->decoration() << "]] ";
} }
out_ << "struct {" << std::endl; out_ << "struct {" << std::endl;
increment_indent();
for (const auto& mem : str->members()) { for (const auto& mem : str->members()) {
// TODO(dsinclair): This formats bad with nested structs make_indent();
out_ << " ";
if (!mem->decorations().empty()) { if (!mem->decorations().empty()) {
out_ << "[["; out_ << "[[";
bool first = true; bool first = true;
@ -169,6 +197,8 @@ bool GeneratorImpl::EmitType(ast::type::Type* type) {
} }
out_ << ";" << std::endl; out_ << ";" << std::endl;
} }
decrement_indent();
make_indent();
out_ << "}"; out_ << "}";
} else if (type->IsU32()) { } else if (type->IsU32()) {
@ -191,6 +221,8 @@ bool GeneratorImpl::EmitType(ast::type::Type* type) {
} }
bool GeneratorImpl::EmitVariable(ast::Variable* var) { bool GeneratorImpl::EmitVariable(ast::Variable* var) {
make_indent();
if (var->IsDecorated()) { if (var->IsDecorated()) {
if (!EmitVariableDecorations(var->AsDecorated())) { if (!EmitVariableDecorations(var->AsDecorated())) {
return false; return false;
@ -212,8 +244,10 @@ bool GeneratorImpl::EmitVariable(ast::Variable* var) {
} }
if (var->initializer() != nullptr) { if (var->initializer() != nullptr) {
// out_ << " = "; out_ << " = ";
// EmitExpr(var-initializer()); if (!EmitExpression(var->initializer())) {
return false;
}
} }
out_ << ";" << std::endl; out_ << ";" << std::endl;

View File

@ -47,6 +47,20 @@ class GeneratorImpl {
/// @returns the error from the generator /// @returns the error from the generator
std::string error() const { return error_; } 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 /// Handles generating an alias
/// @param alias the alias to generate /// @param alias the alias to generate
/// @returns true if the alias was emitted /// @returns true if the alias was emitted
@ -55,6 +69,10 @@ class GeneratorImpl {
/// @param ep the entry point /// @param ep the entry point
/// @returns true if the entry point was emitted /// @returns true if the entry point was emitted
bool EmitEntryPoint(const ast::EntryPoint* ep); 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 /// Handles generating an import command
/// @param import the import to generate /// @param import the import to generate
/// @returns true if the import was emitted /// @returns true if the import was emitted
@ -73,6 +91,7 @@ class GeneratorImpl {
bool EmitVariableDecorations(ast::DecoratedVariable* var); bool EmitVariableDecorations(ast::DecoratedVariable* var);
private: private:
size_t indent_ = 0;
std::ostringstream out_; std::ostringstream out_;
std::string error_; std::string error_;
}; };

View File

@ -23,6 +23,7 @@
#include "src/ast/builtin.h" #include "src/ast/builtin.h"
#include "src/ast/builtin_decoration.h" #include "src/ast/builtin_decoration.h"
#include "src/ast/decorated_variable.h" #include "src/ast/decorated_variable.h"
#include "src/ast/identifier_expression.h"
#include "src/ast/location_decoration.h" #include "src/ast/location_decoration.h"
#include "src/ast/set_decoration.h" #include "src/ast/set_decoration.h"
#include "src/ast/struct.h" #include "src/ast/struct.h"
@ -83,7 +84,7 @@ TEST_F(GeneratorImplTest, DISABLED_EmitAliasType_Struct) {
GeneratorImpl g; GeneratorImpl g;
ASSERT_TRUE(g.EmitAliasType(&alias)); ASSERT_TRUE(g.EmitAliasType(&alias));
EXPECT_EQ(g.result(), R"(type a = struct { EXPECT_EQ(g.result(), R"(type a = struct {
a: f32; a : f32;
[[offset 4]] b : i32; [[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<ast::IdentifierExpression>("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<ast::IdentifierExpression>("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
} // namespace wgsl } // namespace wgsl