writer: Add TextBuffer to TextGenerator

And migrate the WGSL writer over to the new APIs.

TextBuffer allows text to be written to different buffers.
Helps with the complexities around for loops.

Bug: tint:952
Change-Id: I094a726254f2a97b5830a8d6e07af7649c91e083
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/56771
Reviewed-by: David Neto <dneto@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Ben Clayton 2021-07-02 22:17:25 +00:00
parent 5e607680e7
commit e1f30f1049
17 changed files with 708 additions and 566 deletions

View File

@ -16,7 +16,6 @@
#include <algorithm>
#include <iomanip>
#include <iosfwd>
#include <set>
#include <utility>
#include <vector>
@ -123,7 +122,7 @@ bool GeneratorImpl::Generate() {
}
const TypeInfo* last_kind = nullptr;
std::streampos last_padding_pos;
size_t last_padding_line = 0;
if (!FindAndEmitVectorAssignmentInLoopFunctions()) {
return false;
@ -137,10 +136,10 @@ bool GeneratorImpl::Generate() {
// Emit a new line between declarations if the type of declaration has
// changed, or we're about to emit a function
auto* kind = &decl->TypeInfo();
if (out_.tellp() != last_padding_pos) {
if (current_buffer_->lines.size() != last_padding_line) {
if (last_kind && (last_kind != kind || decl->Is<ast::Function>())) {
out_ << std::endl;
last_padding_pos = out_.tellp();
line();
last_padding_line = current_buffer_->lines.size();
}
}
last_kind = kind;

View File

@ -14,6 +14,7 @@
#include "src/writer/text_generator.h"
#include <algorithm>
#include <limits>
namespace tint {
@ -24,20 +25,20 @@ TextGenerator::TextGenerator(const Program* program)
TextGenerator::~TextGenerator() = default;
void TextGenerator::make_indent() {
make_indent(out_);
}
void TextGenerator::make_indent(std::ostream& out) const {
for (size_t i = 0; i < indent_; i++) {
out << " ";
}
}
std::string TextGenerator::UniqueIdentifier(const std::string& prefix) {
return builder_.Symbols().NameFor(builder_.Symbols().New(prefix));
}
std::string TextGenerator::TrimSuffix(std::string str,
const std::string& suffix) {
if (str.size() >= suffix.size()) {
if (str.substr(str.size() - suffix.size(), suffix.size()) == suffix) {
return str.substr(0, str.size() - suffix.size());
}
}
return str;
}
TextGenerator::LineWriter::LineWriter(TextGenerator* generator)
: gen(generator) {}
@ -48,15 +49,45 @@ TextGenerator::LineWriter::LineWriter(LineWriter&& other) {
TextGenerator::LineWriter::~LineWriter() {
if (gen) {
auto str = os.str();
if (!str.empty()) {
gen->make_indent();
gen->out_ << str;
}
gen->out_ << std::endl;
gen->current_buffer_->Append(os.str());
}
}
TextGenerator::TextBuffer::TextBuffer() = default;
TextGenerator::TextBuffer::~TextBuffer() = default;
void TextGenerator::TextBuffer::IncrementIndent() {
current_indent += 2;
}
void TextGenerator::TextBuffer::DecrementIndent() {
current_indent = std::max(2u, current_indent) - 2u;
}
void TextGenerator::TextBuffer::Append(const std::string& line) {
lines.emplace_back(Line{current_indent, line});
}
void TextGenerator::TextBuffer::Append(const TextBuffer& tb) {
for (auto& line : tb.lines) {
lines.emplace_back(Line{current_indent + line.indent, line.content});
}
}
std::string TextGenerator::TextBuffer::String() const {
std::stringstream ss;
for (auto& line : lines) {
if (!line.content.empty()) {
for (uint32_t i = 0; i < line.indent; i++) {
ss << " ";
}
ss << line.content;
}
ss << std::endl;
}
return ss.str();
}
TextGenerator::ScopedParen::ScopedParen(std::ostream& stream) : s(stream) {
s << "(";
}

View File

@ -18,6 +18,7 @@
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "src/diagnostic/diagnostic.h"
#include "src/program_builder.h"
@ -34,25 +35,12 @@ class TextGenerator {
~TextGenerator();
/// 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();
/// Writes the current indent to `out`
/// @param out the stream to write the indent to
void make_indent(std::ostream& out) const;
void increment_indent() { current_buffer_->IncrementIndent(); }
/// Decrement the emitter indent level
void decrement_indent() { current_buffer_->DecrementIndent(); }
/// @returns the result data
std::string result() const { return out_.str(); }
std::string result() const { return main_buffer_.String(); }
/// @returns the list of diagnostics raised by the generator.
const diag::List& Diagnostics() const { return diagnostics_; }
@ -65,6 +53,12 @@ class TextGenerator {
/// empty "tint_symbol" will be used.
std::string UniqueIdentifier(const std::string& prefix = "");
/// @param str the string
/// @param suffix the suffix to remove
/// @return returns str without the provided trailing suffix string. If str
/// doesn't end with suffix, str is returned unchanged.
std::string TrimSuffix(std::string str, const std::string& suffix);
protected:
/// LineWriter is a helper that acts as a string buffer, who's content is
/// emitted to the TextGenerator as a single line on destruction.
@ -81,7 +75,7 @@ class TextGenerator {
~LineWriter();
/// @returns the ostringstream
operator std::ostream&() { return os; }
operator std::ostream &() { return os; }
/// @param rhs the value to write to the line
/// @returns the ostream so calls can be chained
@ -98,6 +92,49 @@ class TextGenerator {
TextGenerator* gen;
};
/// Line holds a single line of text
struct Line {
/// The indentation of the line in whitespaces
uint32_t indent = 0;
/// The content of the line, without a trailing newline character
std::string content;
};
/// TextBuffer holds a list of lines of text.
struct TextBuffer {
// Constructor
TextBuffer();
// Destructor
~TextBuffer();
/// IncrementIndent increases the indentation of lines that will be written
/// to the TextBuffer
void IncrementIndent();
/// DecrementIndent decreases the indentation of lines that will be written
/// to the TextBuffer
void DecrementIndent();
/// Appends the line to the end of the TextBuffer
/// @param line the line to append to the TextBuffer
void Append(const std::string& line);
/// Appends the lines of `tb` to the end of this TextBuffer
/// @param tb the TextBuffer to append to the end of this TextBuffer
void Append(const TextBuffer& tb);
/// @returns the buffer's content as a single string
std::string String() const;
/// The current indentation of the TextBuffer. Lines appended to the
/// TextBuffer will use this indentation.
uint32_t current_indent = 0;
/// The lines
std::vector<Line> lines;
};
/// Helper for writing a '(' on construction and a ')' destruction.
struct ScopedParen {
/// Constructor
@ -154,13 +191,14 @@ class TextGenerator {
Program const* const program_;
/// A ProgramBuilder that thinly wraps program_
ProgramBuilder builder_;
/// The text output stream
std::ostringstream out_;
/// Diagnostics generated by the generator
diag::List diagnostics_;
/// The buffer the TextGenerator is currently appending lines to
TextBuffer* current_buffer_ = &main_buffer_;
private:
size_t indent_ = 0;
/// The primary text buffer that the generator will emit
TextBuffer main_buffer_;
};
} // namespace writer

File diff suppressed because it is too large Load Diff

View File

@ -60,57 +60,56 @@ class GeneratorImpl : public TextGenerator {
/// @returns true if the declared type was emitted
bool EmitTypeDecl(const ast::TypeDecl* ty);
/// Handles an array accessor expression
/// @param out the output of the expression stream
/// @param expr the expression to emit
/// @returns true if the array accessor was emitted
bool EmitArrayAccessor(ast::ArrayAccessorExpression* expr);
bool EmitArrayAccessor(std::ostream& out, ast::ArrayAccessorExpression* expr);
/// Handles an assignment statement
/// @param stmt the statement to emit
/// @returns true if the statement was emitted successfully
bool EmitAssign(ast::AssignmentStatement* stmt);
/// Handles generating a binary expression
/// @param out the output of the expression stream
/// @param expr the binary expression
/// @returns true if the expression was emitted, false otherwise
bool EmitBinary(ast::BinaryExpression* expr);
bool EmitBinary(std::ostream& out, ast::BinaryExpression* expr);
/// Handles generating a bitcast expression
/// @param out the output of the expression stream
/// @param expr the bitcast expression
/// @returns true if the bitcast was emitted
bool EmitBitcast(ast::BitcastExpression* expr);
bool EmitBitcast(std::ostream& out, ast::BitcastExpression* expr);
/// Handles a block statement
/// @param stmt the statement to emit
/// @returns true if the statement was emitted successfully
bool EmitBlock(const ast::BlockStatement* stmt);
/// Handles a block statement with a newline at the end
/// @param stmt the statement to emit
/// @returns true if the statement was emitted successfully
bool EmitBlockAndNewline(const ast::BlockStatement* stmt);
/// Handles a break statement
/// @param stmt the statement to emit
/// @returns true if the statement was emitted successfully
bool EmitBreak(ast::BreakStatement* stmt);
/// Handles generating a call expression
/// @param out the output of the expression stream
/// @param expr the call expression
/// @returns true if the call expression is emitted
bool EmitCall(ast::CallExpression* expr);
bool EmitCall(std::ostream& out, ast::CallExpression* expr);
/// Handles a case statement
/// @param stmt the statement
/// @returns true if the statment was emitted successfully
bool EmitCase(ast::CaseStatement* stmt);
/// Handles generating a scalar constructor
/// @param out the output of the expression stream
/// @param expr the scalar constructor expression
/// @returns true if the scalar constructor is emitted
bool EmitScalarConstructor(ast::ScalarConstructorExpression* expr);
bool EmitScalarConstructor(std::ostream& out,
ast::ScalarConstructorExpression* expr);
/// Handles a continue statement
/// @param stmt the statement to emit
/// @returns true if the statement was emitted successfully
bool EmitContinue(ast::ContinueStatement* stmt);
/// Handles generating an else statement
/// @param stmt the statement to emit
/// @returns true if the statement was emitted
bool EmitElse(ast::ElseStatement* stmt);
/// Handles generate an Expression
/// @param out the output of the expression stream
/// @param expr the expression
/// @returns true if the expression was emitted
bool EmitExpression(ast::Expression* expr);
bool EmitExpression(std::ostream& out, ast::Expression* expr);
/// Handles generating a fallthrough statement
/// @param stmt the fallthrough statement
/// @returns true if the statement was successfully emitted
@ -120,25 +119,28 @@ class GeneratorImpl : public TextGenerator {
/// @returns true if the function was emitted
bool EmitFunction(ast::Function* func);
/// Handles generating an identifier expression
/// @param out the output of the expression stream
/// @param expr the identifier expression
/// @returns true if the identifeir was emitted
bool EmitIdentifier(ast::IdentifierExpression* expr);
bool EmitIdentifier(std::ostream& out, ast::IdentifierExpression* expr);
/// Handles an if statement
/// @param stmt the statement to emit
/// @returns true if the statement was successfully emitted
bool EmitIf(ast::IfStatement* stmt);
/// Handles generating constructor expressions
/// @param out the output of the expression stream
/// @param expr the constructor expression
/// @returns true if the expression was emitted
bool EmitConstructor(ast::ConstructorExpression* expr);
bool EmitConstructor(std::ostream& out, ast::ConstructorExpression* expr);
/// Handles generating a discard statement
/// @param stmt the discard statement
/// @returns true if the statement was successfully emitted
bool EmitDiscard(ast::DiscardStatement* stmt);
/// Handles a literal
/// @param out the output of the expression stream
/// @param lit the literal to emit
/// @returns true if the literal was successfully emitted
bool EmitLiteral(ast::Literal* lit);
bool EmitLiteral(std::ostream& out, ast::Literal* lit);
/// Handles a loop statement
/// @param stmt the statement to emit
/// @returns true if the statement was emtited
@ -148,9 +150,11 @@ class GeneratorImpl : public TextGenerator {
/// @returns true if the statement was emtited
bool EmitForLoop(ast::ForLoopStatement* stmt);
/// Handles a member accessor expression
/// @param out the output of the expression stream
/// @param expr the member accessor expression
/// @returns true if the member accessor was emitted
bool EmitMemberAccessor(ast::MemberAccessorExpression* expr);
bool EmitMemberAccessor(std::ostream& out,
ast::MemberAccessorExpression* expr);
/// Handles return statements
/// @param stmt the statement to emit
/// @returns true if the statement was successfully emitted
@ -159,47 +163,58 @@ class GeneratorImpl : public TextGenerator {
/// @param stmt the statement to emit
/// @returns true if the statement was emitted
bool EmitStatement(ast::Statement* stmt);
/// Emits a statement without an indentation or trailing semi-colon and
/// newline
/// @param stmt the statement to emit
/// @returns true if the statement was emitted
bool EmitRawStatement(ast::Statement* stmt);
/// Handles a statement list
/// @param stmts the statements to emit
/// @returns true if the statements were emitted
bool EmitStatements(const ast::StatementList& stmts);
/// Handles a statement list with an increased indentation
/// @param stmts the statements to emit
/// @returns true if the statements were emitted
bool EmitStatementsWithIndent(const ast::StatementList& stmts);
/// Handles generating a switch statement
/// @param stmt the statement to emit
/// @returns true if the statement was emitted
bool EmitSwitch(ast::SwitchStatement* stmt);
/// Handles generating type
/// @param out the output of the expression stream
/// @param type the type to generate
/// @returns true if the type is emitted
bool EmitType(const ast::Type* type);
bool EmitType(std::ostream& out, const ast::Type* type);
/// Handles generating a struct declaration
/// @param str the struct
/// @returns true if the struct is emitted
bool EmitStructType(const ast::Struct* str);
/// Handles emitting an image format
/// @param out the output of the expression stream
/// @param fmt the format to generate
/// @returns true if the format is emitted
bool EmitImageFormat(const ast::ImageFormat fmt);
bool EmitImageFormat(std::ostream& out, const ast::ImageFormat fmt);
/// Handles emitting an access control
/// @param out the output of the expression stream
/// @param access the access to generate
/// @returns true if the access is emitted
bool EmitAccess(const ast::Access access);
bool EmitAccess(std::ostream& out, const ast::Access access);
/// Handles emitting a type constructor
/// @param out the output of the expression stream
/// @param expr the type constructor expression
/// @returns true if the constructor is emitted
bool EmitTypeConstructor(ast::TypeConstructorExpression* expr);
bool EmitTypeConstructor(std::ostream& out,
ast::TypeConstructorExpression* expr);
/// Handles a unary op expression
/// @param out the output of the expression stream
/// @param expr the expression to emit
/// @returns true if the expression was emitted
bool EmitUnaryOp(ast::UnaryOpExpression* expr);
bool EmitUnaryOp(std::ostream& out, ast::UnaryOpExpression* expr);
/// Handles generating a variable
/// @param out the output of the expression stream
/// @param var the variable to generate
/// @returns true if the variable was emitted
bool EmitVariable(ast::Variable* var);
bool EmitVariable(std::ostream& out, ast::Variable* var);
/// Handles generating a decoration list
/// @param out the output of the expression stream
/// @param decos the decoration list
/// @returns true if the decorations were emitted
bool EmitDecorations(const ast::DecorationList& decos);
bool EmitDecorations(std::ostream& out, const ast::DecorationList& decos);
};
} // namespace wgsl

View File

@ -28,8 +28,9 @@ TEST_F(WgslGeneratorImplTest, ArrayAccessor) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(expr)) << gen.error();
EXPECT_EQ(gen.result(), "ary[5]");
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "ary[5]");
}
TEST_F(WgslGeneratorImplTest, ArrayAccessor_OfDref) {
@ -41,8 +42,9 @@ TEST_F(WgslGeneratorImplTest, ArrayAccessor_OfDref) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(expr)) << gen.error();
EXPECT_EQ(gen.result(), "(*(p))[5]");
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "(*(p))[5]");
}
} // namespace

View File

@ -50,8 +50,9 @@ TEST_P(WgslBinaryTest, Emit) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(expr)) << gen.error();
EXPECT_EQ(gen.result(), params.result);
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), params.result);
}
INSTANTIATE_TEST_SUITE_P(
WgslGeneratorImplTest,

View File

@ -27,8 +27,9 @@ TEST_F(WgslGeneratorImplTest, EmitExpression_Bitcast) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(bitcast)) << gen.error();
EXPECT_EQ(gen.result(), "bitcast<f32>(1)");
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, bitcast)) << gen.error();
EXPECT_EQ(out.str(), "bitcast<f32>(1)");
}
} // namespace

View File

@ -36,20 +36,6 @@ TEST_F(WgslGeneratorImplTest, Emit_Block) {
)");
}
TEST_F(WgslGeneratorImplTest, Emit_Block_WithoutNewline) {
auto* b = Block(create<ast::DiscardStatement>());
WrapInFunction(b);
GeneratorImpl& gen = Build();
gen.increment_indent();
ASSERT_TRUE(gen.EmitBlock(b)) << gen.error();
EXPECT_EQ(gen.result(), R"({
discard;
})");
}
} // namespace
} // namespace wgsl
} // namespace writer

View File

@ -31,8 +31,9 @@ TEST_F(WgslGeneratorImplTest, EmitExpression_Call_WithoutParams) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(call)) << gen.error();
EXPECT_EQ(gen.result(), "my_func()");
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_EQ(out.str(), "my_func()");
}
TEST_F(WgslGeneratorImplTest, EmitExpression_Call_WithParams) {
@ -50,8 +51,9 @@ TEST_F(WgslGeneratorImplTest, EmitExpression_Call_WithParams) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(call)) << gen.error();
EXPECT_EQ(gen.result(), "my_func(param1, param2)");
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_EQ(out.str(), "my_func(param1, param2)");
}
TEST_F(WgslGeneratorImplTest, EmitStatement_Call) {

View File

@ -27,8 +27,9 @@ TEST_F(WgslGeneratorImplTest, EmitExpression_Cast_Scalar) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(cast)) << gen.error();
EXPECT_EQ(gen.result(), "f32(1)");
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.error();
EXPECT_EQ(out.str(), "f32(1)");
}
TEST_F(WgslGeneratorImplTest, EmitExpression_Cast_Vector) {
@ -37,8 +38,9 @@ TEST_F(WgslGeneratorImplTest, EmitExpression_Cast_Vector) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(cast)) << gen.error();
EXPECT_EQ(gen.result(), "vec3<f32>(vec3<i32>(1, 2, 3))");
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.error();
EXPECT_EQ(out.str(), "vec3<f32>(vec3<i32>(1, 2, 3))");
}
} // namespace

View File

@ -28,8 +28,9 @@ TEST_F(WgslGeneratorImplTest, EmitIdentifierExpression_Single) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(i)) << gen.error();
EXPECT_EQ(gen.result(), "glsl");
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, i)) << gen.error();
EXPECT_EQ(out.str(), "glsl");
}
} // namespace

View File

@ -58,8 +58,9 @@ TEST_P(WgslGenerator_FloatLiteralTest, Emit) {
SetResolveOnBuild(false);
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitScalarConstructor(v)) << gen.error();
EXPECT_EQ(gen.result(), GetParam().expected);
std::stringstream out;
ASSERT_TRUE(gen.EmitScalarConstructor(out, v)) << gen.error();
EXPECT_EQ(out.str(), GetParam().expected);
}
INSTANTIATE_TEST_SUITE_P(Zero,

View File

@ -30,8 +30,9 @@ TEST_F(WgslGeneratorImplTest, EmitExpression_MemberAccessor) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(expr)) << gen.error();
EXPECT_EQ(gen.result(), "str.mem");
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "str.mem");
}
TEST_F(WgslGeneratorImplTest, EmitExpression_MemberAccessor_OfDref) {
@ -44,8 +45,9 @@ TEST_F(WgslGeneratorImplTest, EmitExpression_MemberAccessor_OfDref) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(expr)) << gen.error();
EXPECT_EQ(gen.result(), "(*(p)).mem");
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "(*(p)).mem");
}
} // namespace

View File

@ -32,8 +32,9 @@ TEST_F(WgslGeneratorImplTest, EmitType_Alias) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(alias_ty)) << gen.error();
EXPECT_EQ(gen.result(), "alias");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, alias_ty)) << gen.error();
EXPECT_EQ(out.str(), "alias");
}
TEST_F(WgslGeneratorImplTest, EmitType_Array) {
@ -42,8 +43,9 @@ TEST_F(WgslGeneratorImplTest, EmitType_Array) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(arr)) << gen.error();
EXPECT_EQ(gen.result(), "array<bool, 4>");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, arr)) << gen.error();
EXPECT_EQ(out.str(), "array<bool, 4>");
}
TEST_F(WgslGeneratorImplTest, EmitType_Array_Decoration) {
@ -52,8 +54,9 @@ TEST_F(WgslGeneratorImplTest, EmitType_Array_Decoration) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(a)) << gen.error();
EXPECT_EQ(gen.result(), "[[stride(16)]] array<bool, 4>");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, a)) << gen.error();
EXPECT_EQ(out.str(), "[[stride(16)]] array<bool, 4>");
}
TEST_F(WgslGeneratorImplTest, EmitType_RuntimeArray) {
@ -62,8 +65,9 @@ TEST_F(WgslGeneratorImplTest, EmitType_RuntimeArray) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(a)) << gen.error();
EXPECT_EQ(gen.result(), "array<bool>");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, a)) << gen.error();
EXPECT_EQ(out.str(), "array<bool>");
}
TEST_F(WgslGeneratorImplTest, EmitType_Bool) {
@ -72,8 +76,9 @@ TEST_F(WgslGeneratorImplTest, EmitType_Bool) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(bool_)) << gen.error();
EXPECT_EQ(gen.result(), "bool");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, bool_)) << gen.error();
EXPECT_EQ(out.str(), "bool");
}
TEST_F(WgslGeneratorImplTest, EmitType_F32) {
@ -82,8 +87,9 @@ TEST_F(WgslGeneratorImplTest, EmitType_F32) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(f32)) << gen.error();
EXPECT_EQ(gen.result(), "f32");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, f32)) << gen.error();
EXPECT_EQ(out.str(), "f32");
}
TEST_F(WgslGeneratorImplTest, EmitType_I32) {
@ -92,8 +98,9 @@ TEST_F(WgslGeneratorImplTest, EmitType_I32) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(i32)) << gen.error();
EXPECT_EQ(gen.result(), "i32");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, i32)) << gen.error();
EXPECT_EQ(out.str(), "i32");
}
TEST_F(WgslGeneratorImplTest, EmitType_Matrix) {
@ -102,8 +109,9 @@ TEST_F(WgslGeneratorImplTest, EmitType_Matrix) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(mat2x3)) << gen.error();
EXPECT_EQ(gen.result(), "mat2x3<f32>");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, mat2x3)) << gen.error();
EXPECT_EQ(out.str(), "mat2x3<f32>");
}
TEST_F(WgslGeneratorImplTest, EmitType_Pointer) {
@ -112,8 +120,9 @@ TEST_F(WgslGeneratorImplTest, EmitType_Pointer) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(p)) << gen.error();
EXPECT_EQ(gen.result(), "ptr<workgroup, f32>");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, p)) << gen.error();
EXPECT_EQ(out.str(), "ptr<workgroup, f32>");
}
TEST_F(WgslGeneratorImplTest, EmitType_Struct) {
@ -126,8 +135,9 @@ TEST_F(WgslGeneratorImplTest, EmitType_Struct) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(s_ty)) << gen.error();
EXPECT_EQ(gen.result(), "S");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, s_ty)) << gen.error();
EXPECT_EQ(out.str(), "S");
}
TEST_F(WgslGeneratorImplTest, EmitType_StructOffsetDecl) {
@ -257,8 +267,9 @@ TEST_F(WgslGeneratorImplTest, EmitType_U32) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(u32)) << gen.error();
EXPECT_EQ(gen.result(), "u32");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, u32)) << gen.error();
EXPECT_EQ(out.str(), "u32");
}
TEST_F(WgslGeneratorImplTest, EmitType_Vector) {
@ -267,8 +278,9 @@ TEST_F(WgslGeneratorImplTest, EmitType_Vector) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(vec3)) << gen.error();
EXPECT_EQ(gen.result(), "vec3<f32>");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, vec3)) << gen.error();
EXPECT_EQ(out.str(), "vec3<f32>");
}
struct TextureData {
@ -289,8 +301,9 @@ TEST_P(WgslGenerator_DepthTextureTest, EmitType_DepthTexture) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(d)) << gen.error();
EXPECT_EQ(gen.result(), param.name);
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, d)) << gen.error();
EXPECT_EQ(out.str(), param.name);
}
INSTANTIATE_TEST_SUITE_P(
WgslGeneratorImplTest,
@ -311,8 +324,9 @@ TEST_P(WgslGenerator_SampledTextureTest, EmitType_SampledTexture_F32) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(t)) << gen.error();
EXPECT_EQ(gen.result(), std::string(param.name) + "<f32>");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, t)) << gen.error();
EXPECT_EQ(out.str(), std::string(param.name) + "<f32>");
}
TEST_P(WgslGenerator_SampledTextureTest, EmitType_SampledTexture_I32) {
@ -323,8 +337,9 @@ TEST_P(WgslGenerator_SampledTextureTest, EmitType_SampledTexture_I32) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(t)) << gen.error();
EXPECT_EQ(gen.result(), std::string(param.name) + "<i32>");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, t)) << gen.error();
EXPECT_EQ(out.str(), std::string(param.name) + "<i32>");
}
TEST_P(WgslGenerator_SampledTextureTest, EmitType_SampledTexture_U32) {
@ -335,8 +350,9 @@ TEST_P(WgslGenerator_SampledTextureTest, EmitType_SampledTexture_U32) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(t)) << gen.error();
EXPECT_EQ(gen.result(), std::string(param.name) + "<u32>");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, t)) << gen.error();
EXPECT_EQ(out.str(), std::string(param.name) + "<u32>");
}
INSTANTIATE_TEST_SUITE_P(
WgslGeneratorImplTest,
@ -358,8 +374,9 @@ TEST_P(WgslGenerator_MultiampledTextureTest, EmitType_MultisampledTexture_F32) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(t)) << gen.error();
EXPECT_EQ(gen.result(), std::string(param.name) + "<f32>");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, t)) << gen.error();
EXPECT_EQ(out.str(), std::string(param.name) + "<f32>");
}
TEST_P(WgslGenerator_MultiampledTextureTest, EmitType_MultisampledTexture_I32) {
@ -370,8 +387,9 @@ TEST_P(WgslGenerator_MultiampledTextureTest, EmitType_MultisampledTexture_I32) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(t)) << gen.error();
EXPECT_EQ(gen.result(), std::string(param.name) + "<i32>");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, t)) << gen.error();
EXPECT_EQ(out.str(), std::string(param.name) + "<i32>");
}
TEST_P(WgslGenerator_MultiampledTextureTest, EmitType_MultisampledTexture_U32) {
@ -382,8 +400,9 @@ TEST_P(WgslGenerator_MultiampledTextureTest, EmitType_MultisampledTexture_U32) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(t)) << gen.error();
EXPECT_EQ(gen.result(), std::string(param.name) + "<u32>");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, t)) << gen.error();
EXPECT_EQ(out.str(), std::string(param.name) + "<u32>");
}
INSTANTIATE_TEST_SUITE_P(WgslGeneratorImplTest,
WgslGenerator_MultiampledTextureTest,
@ -414,8 +433,9 @@ TEST_P(WgslGenerator_StorageTextureTest, EmitType_StorageTexture) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(t)) << gen.error();
EXPECT_EQ(gen.result(), param.name);
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, t)) << gen.error();
EXPECT_EQ(out.str(), param.name);
}
INSTANTIATE_TEST_SUITE_P(
WgslGeneratorImplTest,
@ -460,8 +480,9 @@ TEST_P(WgslGenerator_ImageFormatTest, EmitType_StorageTexture_ImageFormat) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitImageFormat(param.fmt)) << gen.error();
EXPECT_EQ(gen.result(), param.name);
std::stringstream out;
ASSERT_TRUE(gen.EmitImageFormat(out, param.fmt)) << gen.error();
EXPECT_EQ(out.str(), param.name);
}
INSTANTIATE_TEST_SUITE_P(
@ -510,8 +531,9 @@ TEST_F(WgslGeneratorImplTest, EmitType_Sampler) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(sampler)) << gen.error();
EXPECT_EQ(gen.result(), "sampler");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, sampler)) << gen.error();
EXPECT_EQ(out.str(), "sampler");
}
TEST_F(WgslGeneratorImplTest, EmitType_SamplerComparison) {
@ -520,8 +542,9 @@ TEST_F(WgslGeneratorImplTest, EmitType_SamplerComparison) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitType(sampler)) << gen.error();
EXPECT_EQ(gen.result(), "sampler_comparison");
std::stringstream out;
ASSERT_TRUE(gen.EmitType(out, sampler)) << gen.error();
EXPECT_EQ(out.str(), "sampler_comparison");
}
} // namespace

View File

@ -29,8 +29,9 @@ TEST_F(WgslUnaryOpTest, AddressOf) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(op)) << gen.error();
EXPECT_EQ(gen.result(), "&(expr)");
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error();
EXPECT_EQ(out.str(), "&(expr)");
}
TEST_F(WgslUnaryOpTest, Complement) {
@ -41,8 +42,9 @@ TEST_F(WgslUnaryOpTest, Complement) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(op)) << gen.error();
EXPECT_EQ(gen.result(), "~(expr)");
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error();
EXPECT_EQ(out.str(), "~(expr)");
}
TEST_F(WgslUnaryOpTest, Indirection) {
@ -56,8 +58,9 @@ TEST_F(WgslUnaryOpTest, Indirection) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(op)) << gen.error();
EXPECT_EQ(gen.result(), "*(expr)");
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error();
EXPECT_EQ(out.str(), "*(expr)");
}
TEST_F(WgslUnaryOpTest, Not) {
@ -67,8 +70,9 @@ TEST_F(WgslUnaryOpTest, Not) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(op)) << gen.error();
EXPECT_EQ(gen.result(), "!(expr)");
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error();
EXPECT_EQ(out.str(), "!(expr)");
}
TEST_F(WgslUnaryOpTest, Negation) {
@ -79,8 +83,9 @@ TEST_F(WgslUnaryOpTest, Negation) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitExpression(op)) << gen.error();
EXPECT_EQ(gen.result(), "-(expr)");
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error();
EXPECT_EQ(out.str(), "-(expr)");
}
} // namespace

View File

@ -28,8 +28,9 @@ TEST_F(WgslGeneratorImplTest, EmitVariable) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitVariable(v)) << gen.error();
EXPECT_EQ(gen.result(), R"(var<private> a : f32)");
std::stringstream out;
ASSERT_TRUE(gen.EmitVariable(out, v)) << gen.error();
EXPECT_EQ(out.str(), R"(var<private> a : f32;)");
}
TEST_F(WgslGeneratorImplTest, EmitVariable_StorageClass) {
@ -37,8 +38,9 @@ TEST_F(WgslGeneratorImplTest, EmitVariable_StorageClass) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitVariable(v)) << gen.error();
EXPECT_EQ(gen.result(), R"(var<private> a : f32)");
std::stringstream out;
ASSERT_TRUE(gen.EmitVariable(out, v)) << gen.error();
EXPECT_EQ(out.str(), R"(var<private> a : f32;)");
}
TEST_F(WgslGeneratorImplTest, EmitVariable_Access_Read) {
@ -53,9 +55,9 @@ TEST_F(WgslGeneratorImplTest, EmitVariable_Access_Read) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitVariable(v)) << gen.error();
EXPECT_EQ(gen.result(),
R"([[binding(0), group(0)]] var<storage, read> a : S)");
std::stringstream out;
ASSERT_TRUE(gen.EmitVariable(out, v)) << gen.error();
EXPECT_EQ(out.str(), R"([[binding(0), group(0)]] var<storage, read> a : S;)");
}
TEST_F(WgslGeneratorImplTest, EmitVariable_Access_Write) {
@ -70,9 +72,10 @@ TEST_F(WgslGeneratorImplTest, EmitVariable_Access_Write) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitVariable(v)) << gen.error();
EXPECT_EQ(gen.result(),
R"([[binding(0), group(0)]] var<storage, write> a : S)");
std::stringstream out;
ASSERT_TRUE(gen.EmitVariable(out, v)) << gen.error();
EXPECT_EQ(out.str(),
R"([[binding(0), group(0)]] var<storage, write> a : S;)");
}
TEST_F(WgslGeneratorImplTest, EmitVariable_Access_ReadWrite) {
@ -87,9 +90,10 @@ TEST_F(WgslGeneratorImplTest, EmitVariable_Access_ReadWrite) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitVariable(v)) << gen.error();
EXPECT_EQ(gen.result(),
R"([[binding(0), group(0)]] var<storage, read_write> a : S)");
std::stringstream out;
ASSERT_TRUE(gen.EmitVariable(out, v)) << gen.error();
EXPECT_EQ(out.str(),
R"([[binding(0), group(0)]] var<storage, read_write> a : S;)");
}
TEST_F(WgslGeneratorImplTest, EmitVariable_Decorated) {
@ -102,8 +106,9 @@ TEST_F(WgslGeneratorImplTest, EmitVariable_Decorated) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitVariable(v)) << gen.error();
EXPECT_EQ(gen.result(), R"([[group(1), binding(2)]] var a : sampler)");
std::stringstream out;
ASSERT_TRUE(gen.EmitVariable(out, v)) << gen.error();
EXPECT_EQ(out.str(), R"([[group(1), binding(2)]] var a : sampler;)");
}
TEST_F(WgslGeneratorImplTest, EmitVariable_Constructor) {
@ -111,8 +116,9 @@ TEST_F(WgslGeneratorImplTest, EmitVariable_Constructor) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitVariable(v)) << gen.error();
EXPECT_EQ(gen.result(), R"(var<private> a : f32 = 1.0)");
std::stringstream out;
ASSERT_TRUE(gen.EmitVariable(out, v)) << gen.error();
EXPECT_EQ(out.str(), R"(var<private> a : f32 = 1.0;)");
}
TEST_F(WgslGeneratorImplTest, EmitVariable_Const) {
@ -121,8 +127,9 @@ TEST_F(WgslGeneratorImplTest, EmitVariable_Const) {
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitVariable(v)) << gen.error();
EXPECT_EQ(gen.result(), R"(let a : f32 = 1.0)");
std::stringstream out;
ASSERT_TRUE(gen.EmitVariable(out, v)) << gen.error();
EXPECT_EQ(out.str(), R"(let a : f32 = 1.0;)");
}
} // namespace