blob: 102fb4bb7ce638df5a695a3ab81a915739c2f1d9 [file] [log] [blame]
Sarah Mashayekhi462dd672020-03-04 20:51:29 +00001// Copyright 2020 The Tint Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Sarah Mashayekhi34f90a02020-11-06 17:31:15 +000015#ifndef SRC_VALIDATOR_VALIDATOR_IMPL_H_
16#define SRC_VALIDATOR_VALIDATOR_IMPL_H_
Sarah Mashayekhi462dd672020-03-04 20:51:29 +000017
18#include <string>
David Neto20f4d1d2021-01-18 19:45:24 +000019#include <unordered_set>
Sarah Mashayekhi462dd672020-03-04 20:51:29 +000020
Sarah Mashayekhi591fe912020-07-23 23:49:52 +000021#include "src/ast/assignment_statement.h"
Sarah Mashayekhi65f88d62020-08-06 21:24:14 +000022#include "src/ast/identifier_expression.h"
Ben Claytona6b9a8e2021-01-26 16:57:10 +000023#include "src/ast/module.h"
Sarah Mashayekhib08e2532020-08-17 15:46:07 +000024#include "src/ast/return_statement.h"
Ben Clayton1d8098a2020-11-30 23:30:58 +000025#include "src/ast/switch_statement.h"
Ben Clayton1d8098a2020-11-30 23:30:58 +000026#include "src/ast/variable_decl_statement.h"
Ben Claytonc40f6272021-01-26 16:57:10 +000027#include "src/program.h"
Sarah Mashayekhib77399c2020-08-05 15:23:47 +000028#include "src/scope_stack.h"
Sarah Mashayekhi462dd672020-03-04 20:51:29 +000029
30namespace tint {
31
Ben Claytonc40f6272021-01-26 16:57:10 +000032/// Determines if the program is complete and valid
Sarah Mashayekhi462dd672020-03-04 20:51:29 +000033class ValidatorImpl {
34 public:
35 /// Constructor
Ben Claytonc40f6272021-01-26 16:57:10 +000036 /// @param program the program to validate
37 explicit ValidatorImpl(const Program* program);
Sarah Mashayekhi462dd672020-03-04 20:51:29 +000038 ~ValidatorImpl();
39
40 /// Runs the validator
Sarah Mashayekhi462dd672020-03-04 20:51:29 +000041 /// @returns true if the validation was successful
dan sinclair795b6b52021-01-11 15:10:19 +000042 bool Validate();
Sarah Mashayekhi462dd672020-03-04 20:51:29 +000043
Ben Claytona6b9a8e2021-01-26 16:57:10 +000044 /// @returns the program being validated
45 const Program* program() { return program_; }
46
Ben Claytonba06db62020-11-26 16:50:02 +000047 /// @returns the diagnostic messages
48 const diag::List& diagnostics() const { return diags_; }
49 /// @returns the diagnostic messages
50 diag::List& diagnostics() { return diags_; }
51
Sarah Mashayekhi462dd672020-03-04 20:51:29 +000052 /// @returns error messages from the validator
Ben Claytonba06db62020-11-26 16:50:02 +000053 std::string error() {
Ben Claytond2217382021-01-11 21:09:22 +000054 diag::Formatter formatter{{false, false, false, false}};
Ben Claytonba06db62020-11-26 16:50:02 +000055 return formatter.format(diags_);
56 }
Sarah Mashayekhi462dd672020-03-04 20:51:29 +000057 /// @returns true if an error was encountered
Ben Claytonba06db62020-11-26 16:50:02 +000058 bool has_error() const { return diags_.contains_errors(); }
Sarah Mashayekhi462dd672020-03-04 20:51:29 +000059
Ben Claytonf8971ae2020-12-02 15:31:08 +000060 /// Appends an error at `src` with the code `code` and message `msg`
Ben Claytonf32a3c12020-11-26 17:49:22 +000061 /// @param src the source causing the error
62 /// @param code the validation error code
63 /// @param msg the error message
64 void add_error(const Source& src, const char* code, const std::string& msg);
65
Ben Claytonf8971ae2020-12-02 15:31:08 +000066 /// Appends an error at `src` with the message `msg`
Sarah Mashayekhi462dd672020-03-04 20:51:29 +000067 /// @param src the source causing the error
68 /// @param msg the error message
Ben Claytonba06db62020-11-26 16:50:02 +000069 void add_error(const Source& src, const std::string& msg);
70
James Pricec0f30192021-02-09 23:22:32 +000071 /// Validates a global variable
72 /// @param var the global variable to check
Sarah Mashayekhi4fb431c2020-08-25 15:04:53 +000073 /// @returns true if the validation was successful
James Pricec0f30192021-02-09 23:22:32 +000074 bool ValidateGlobalVariable(const ast::Variable* var);
Sarah Mashayekhi591fe912020-07-23 23:49:52 +000075 /// Validates a function
76 /// @param func the function to check
77 /// @returns true if the validation was successful
Sarah Mashayekhia3f97782020-07-30 02:27:03 +000078 bool ValidateFunction(const ast::Function* func);
dan sinclair4069f332020-07-27 15:25:00 +000079 /// Validates a block of statements
80 /// @param block the statements to check
81 /// @returns true if the validation was successful
Sarah Mashayekhia3f97782020-07-30 02:27:03 +000082 bool ValidateStatements(const ast::BlockStatement* block);
Sarah Mashayekhi591fe912020-07-23 23:49:52 +000083 /// Validates a statement
84 /// @param stmt the statement to check
85 /// @returns true if the validation was successful
Sarah Mashayekhia3f97782020-07-30 02:27:03 +000086 bool ValidateStatement(const ast::Statement* stmt);
Sarah Mashayekhi591fe912020-07-23 23:49:52 +000087 /// Validates an assignment
Sarah Mashayekhie88f1c32020-08-07 14:34:34 +000088 /// @param assign the assignment to check
Sarah Mashayekhi591fe912020-07-23 23:49:52 +000089 /// @returns true if the validation was successful
Sarah Mashayekhie88f1c32020-08-07 14:34:34 +000090 bool ValidateAssign(const ast::AssignmentStatement* assign);
David Neto71012dc2021-01-18 22:17:25 +000091 /// Validates a bad assignment to an identifier. Issues an error
92 /// and returns false if the left hand side is an identifier.
93 /// @param assign the assignment to check
94 /// @returns true if the LHS of theassignment is not an identifier expression
95 bool ValidateBadAssignmentToIdentifier(
96 const ast::AssignmentStatement* assign);
Sarah Mashayekhi65f88d62020-08-06 21:24:14 +000097 /// Validates an expression
98 /// @param expr the expression to check
Sarah Mashayekhi8db00df2020-08-20 17:00:09 +000099 /// @return true if the expression is valid
Sarah Mashayekhi65f88d62020-08-06 21:24:14 +0000100 bool ValidateExpression(const ast::Expression* expr);
Ben Claytonf8971ae2020-12-02 15:31:08 +0000101 /// Validates declaration name uniqueness
102 /// @param decl is the new declaration to be added
103 /// @returns true if no previous declaration with the `decl` 's name
Sarah Mashayekhid3107bd2020-08-11 20:44:06 +0000104 /// exist in the variable stack
105 bool ValidateDeclStatement(const ast::VariableDeclStatement* decl);
Sarah Mashayekhib08e2532020-08-17 15:46:07 +0000106 /// Validates return statement
107 /// @param ret the return statement to check
108 /// @returns true if function return type matches the return statement type
109 bool ValidateReturnStatement(const ast::ReturnStatement* ret);
Sarah Mashayekhi8db00df2020-08-20 17:00:09 +0000110 /// Validates function calls
111 /// @param expr the call to validate
112 /// @returns true if successful
113 bool ValidateCallExpr(const ast::CallExpression* expr);
Sarah Mashayekhi2e9f1f52020-09-10 14:37:17 +0000114 /// Validates switch statements
115 /// @param s the switch statement to check
116 /// @returns true if the valdiation was successful
117 bool ValidateSwitch(const ast::SwitchStatement* s);
118 /// Validates case statements
119 /// @param c the case statement to check
120 /// @returns true if the valdiation was successful
121 bool ValidateCase(const ast::CaseStatement* c);
Sarah Mashayekhi3b040582020-11-11 14:21:05 +0000122 /// Validates entry points
123 /// @param funcs the functions to check
124 /// @returns true if the valdiation was successful
125 bool ValidateEntryPoint(const ast::FunctionList& funcs);
David Neto20f4d1d2021-01-18 19:45:24 +0000126 /// Returns true if the given type is storable. This uses and
127 /// updates `storable_` and `not_storable_`.
128 /// @param type the given type
129 /// @returns true if the given type is storable.
Ben Clayton207b5e22021-01-21 15:42:10 +0000130 bool IsStorable(type::Type* type);
David Neto20f4d1d2021-01-18 19:45:24 +0000131
David Neto71012dc2021-01-18 22:17:25 +0000132 /// Testing method to inserting a given variable into the current scope.
Ben Clayton207b5e22021-01-21 15:42:10 +0000133 /// @param var the variable to register
David Neto71012dc2021-01-18 22:17:25 +0000134 void RegisterVariableForTesting(ast::Variable* var) {
135 variable_stack_.set(var->symbol(), var);
136 }
137
Sarah Mashayekhi462dd672020-03-04 20:51:29 +0000138 private:
Ben Claytonc40f6272021-01-26 16:57:10 +0000139 const Program* program_;
Ben Claytonba06db62020-11-26 16:50:02 +0000140 diag::List diags_;
James Pricec0f30192021-02-09 23:22:32 +0000141 ScopeStack<const ast::Variable*> variable_stack_;
Sarah Mashayekhib08e2532020-08-17 15:46:07 +0000142 ast::Function* current_function_ = nullptr;
Sarah Mashayekhi462dd672020-03-04 20:51:29 +0000143};
144
145} // namespace tint
146
Sarah Mashayekhi34f90a02020-11-06 17:31:15 +0000147#endif // SRC_VALIDATOR_VALIDATOR_IMPL_H_