Add type determination for IdentifierExpression.

This CL adds the type determination for identifier expressions.
Namespaced identifiers are not determined yet.

Bug: tint:5
Change-Id: Id8f39ad122cef0349393de4d429a6d971b2a7ce8
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/18841
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
dan sinclair 2020-04-07 12:57:27 +00:00 committed by dan sinclair
parent ca893e3200
commit cab0e73b31
3 changed files with 90 additions and 1 deletions

View File

@ -19,6 +19,7 @@
#include "src/ast/case_statement.h" #include "src/ast/case_statement.h"
#include "src/ast/continue_statement.h" #include "src/ast/continue_statement.h"
#include "src/ast/else_statement.h" #include "src/ast/else_statement.h"
#include "src/ast/identifier_expression.h"
#include "src/ast/if_statement.h" #include "src/ast/if_statement.h"
#include "src/ast/loop_statement.h" #include "src/ast/loop_statement.h"
#include "src/ast/regardless_statement.h" #include "src/ast/regardless_statement.h"
@ -176,6 +177,9 @@ bool TypeDeterminer::DetermineResultType(ast::Expression* expr) {
if (expr->IsConstructor()) { if (expr->IsConstructor()) {
return DetermineConstructor(expr->AsConstructor()); return DetermineConstructor(expr->AsConstructor());
} }
if (expr->IsIdentifier()) {
return DetermineIdentifier(expr->AsIdentifier());
}
error_ = "unknown expression for type determination"; error_ = "unknown expression for type determination";
return false; return false;
@ -190,4 +194,28 @@ bool TypeDeterminer::DetermineConstructor(ast::ConstructorExpression* expr) {
return true; return true;
} }
bool TypeDeterminer::DetermineIdentifier(ast::IdentifierExpression* expr) {
if (expr->name().size() > 1) {
// TODO(dsinclair): Handle imports
error_ = "imports not handled in type determination";
return false;
}
auto name = expr->name()[0];
ast::Variable* var;
if (variable_stack_.get(name, &var)) {
expr->set_result_type(var->type());
return true;
}
auto iter = name_to_function_.find(name);
if (iter != name_to_function_.end()) {
expr->set_result_type(iter->second->return_type());
return true;
}
error_ = "unknown identifier for type determination";
return false;
}
} // namespace tint } // namespace tint

View File

@ -26,6 +26,7 @@ namespace tint {
namespace ast { namespace ast {
class ConstructorExpression; class ConstructorExpression;
class IdentifierExpression;
class Function; class Function;
class Variable; class Variable;
@ -69,7 +70,7 @@ class TypeDeterminer {
private: private:
bool DetermineConstructor(ast::ConstructorExpression* expr); bool DetermineConstructor(ast::ConstructorExpression* expr);
bool DetermineIdentifier(ast::IdentifierExpression* expr);
Context& ctx_; Context& ctx_;
std::string error_; std::string error_;
ScopeStack<ast::Variable*> variable_stack_; ScopeStack<ast::Variable*> variable_stack_;

View File

@ -24,6 +24,7 @@
#include "src/ast/continue_statement.h" #include "src/ast/continue_statement.h"
#include "src/ast/else_statement.h" #include "src/ast/else_statement.h"
#include "src/ast/float_literal.h" #include "src/ast/float_literal.h"
#include "src/ast/identifier_expression.h"
#include "src/ast/if_statement.h" #include "src/ast/if_statement.h"
#include "src/ast/int_literal.h" #include "src/ast/int_literal.h"
#include "src/ast/loop_statement.h" #include "src/ast/loop_statement.h"
@ -406,5 +407,64 @@ TEST_F(TypeDeterminerTest, Expr_Constructor_Type) {
EXPECT_EQ(tc.result_type()->AsVector()->size(), 3); EXPECT_EQ(tc.result_type()->AsVector()->size(), 3);
} }
TEST_F(TypeDeterminerTest, Expr_Identifier_GlobalVariable) {
ast::type::F32Type f32;
ast::Module m;
auto var =
std::make_unique<ast::Variable>("my_var", ast::StorageClass::kNone, &f32);
m.AddGlobalVariable(std::move(var));
// Register the global
EXPECT_TRUE(td()->Determine(&m));
ast::IdentifierExpression ident("my_var");
EXPECT_TRUE(td()->DetermineResultType(&ident));
ASSERT_NE(ident.result_type(), nullptr);
EXPECT_TRUE(ident.result_type()->IsF32());
}
TEST_F(TypeDeterminerTest, Expr_Identifier_FunctionVariable) {
ast::type::F32Type f32;
auto my_var = std::make_unique<ast::IdentifierExpression>("my_var");
auto my_var_ptr = my_var.get();
ast::StatementList body;
body.push_back(std::make_unique<ast::VariableDeclStatement>(
std::make_unique<ast::Variable>("my_var", ast::StorageClass::kNone,
&f32)));
body.push_back(std::make_unique<ast::AssignmentStatement>(
std::move(my_var),
std::make_unique<ast::IdentifierExpression>("my_var")));
ast::Function f("my_func", {}, &f32);
f.set_body(std::move(body));
EXPECT_TRUE(td()->DetermineFunction(&f));
ASSERT_NE(my_var_ptr->result_type(), nullptr);
EXPECT_TRUE(my_var_ptr->result_type()->IsF32());
}
TEST_F(TypeDeterminerTest, Expr_Identifier_Function) {
ast::type::F32Type f32;
ast::VariableList params;
auto func =
std::make_unique<ast::Function>("my_func", std::move(params), &f32);
ast::Module m;
m.AddFunction(std::move(func));
// Register the function
EXPECT_TRUE(td()->Determine(&m));
ast::IdentifierExpression ident("my_func");
EXPECT_TRUE(td()->DetermineResultType(&ident));
ASSERT_NE(ident.result_type(), nullptr);
EXPECT_TRUE(ident.result_type()->IsF32());
}
} // namespace } // namespace
} // namespace tint } // namespace tint