Sarah Mashayekhi | 462dd67 | 2020-03-04 20:51:29 +0000 | [diff] [blame] | 1 | // 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 Mashayekhi | 34f90a0 | 2020-11-06 17:31:15 +0000 | [diff] [blame] | 15 | #ifndef SRC_VALIDATOR_VALIDATOR_IMPL_H_ |
| 16 | #define SRC_VALIDATOR_VALIDATOR_IMPL_H_ |
Sarah Mashayekhi | 462dd67 | 2020-03-04 20:51:29 +0000 | [diff] [blame] | 17 | |
| 18 | #include <string> |
Sarah Mashayekhi | eec1a6e | 2020-08-17 15:32:38 +0000 | [diff] [blame] | 19 | #include <unordered_map> |
David Neto | 20f4d1d | 2021-01-18 19:45:24 +0000 | [diff] [blame^] | 20 | #include <unordered_set> |
Sarah Mashayekhi | d8ea65b | 2020-11-18 22:34:30 +0000 | [diff] [blame] | 21 | #include <vector> |
Sarah Mashayekhi | 462dd67 | 2020-03-04 20:51:29 +0000 | [diff] [blame] | 22 | |
Sarah Mashayekhi | 591fe91 | 2020-07-23 23:49:52 +0000 | [diff] [blame] | 23 | #include "src/ast/assignment_statement.h" |
Sarah Mashayekhi | 8db00df | 2020-08-20 17:00:09 +0000 | [diff] [blame] | 24 | #include "src/ast/call_expression.h" |
Sarah Mashayekhi | 591fe91 | 2020-07-23 23:49:52 +0000 | [diff] [blame] | 25 | #include "src/ast/expression.h" |
Sarah Mashayekhi | 65f88d6 | 2020-08-06 21:24:14 +0000 | [diff] [blame] | 26 | #include "src/ast/identifier_expression.h" |
Sarah Mashayekhi | 462dd67 | 2020-03-04 20:51:29 +0000 | [diff] [blame] | 27 | #include "src/ast/module.h" |
Sarah Mashayekhi | b08e253 | 2020-08-17 15:46:07 +0000 | [diff] [blame] | 28 | #include "src/ast/return_statement.h" |
Sarah Mashayekhi | 591fe91 | 2020-07-23 23:49:52 +0000 | [diff] [blame] | 29 | #include "src/ast/statement.h" |
Ben Clayton | 1d8098a | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 30 | #include "src/ast/switch_statement.h" |
Sarah Mashayekhi | b77399c | 2020-08-05 15:23:47 +0000 | [diff] [blame] | 31 | #include "src/ast/variable.h" |
Ben Clayton | 1d8098a | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 32 | #include "src/ast/variable_decl_statement.h" |
Ben Clayton | ba06db6 | 2020-11-26 16:50:02 +0000 | [diff] [blame] | 33 | #include "src/diagnostic/diagnostic.h" |
| 34 | #include "src/diagnostic/formatter.h" |
Sarah Mashayekhi | b77399c | 2020-08-05 15:23:47 +0000 | [diff] [blame] | 35 | #include "src/scope_stack.h" |
Sarah Mashayekhi | 462dd67 | 2020-03-04 20:51:29 +0000 | [diff] [blame] | 36 | |
| 37 | namespace tint { |
| 38 | |
| 39 | /// Determines if the module is complete and valid |
| 40 | class ValidatorImpl { |
| 41 | public: |
| 42 | /// Constructor |
dan sinclair | 795b6b5 | 2021-01-11 15:10:19 +0000 | [diff] [blame] | 43 | /// @param module the module to validate |
| 44 | explicit ValidatorImpl(const ast::Module* module); |
Sarah Mashayekhi | 462dd67 | 2020-03-04 20:51:29 +0000 | [diff] [blame] | 45 | ~ValidatorImpl(); |
| 46 | |
| 47 | /// Runs the validator |
Sarah Mashayekhi | 462dd67 | 2020-03-04 20:51:29 +0000 | [diff] [blame] | 48 | /// @returns true if the validation was successful |
dan sinclair | 795b6b5 | 2021-01-11 15:10:19 +0000 | [diff] [blame] | 49 | bool Validate(); |
Sarah Mashayekhi | 462dd67 | 2020-03-04 20:51:29 +0000 | [diff] [blame] | 50 | |
Ben Clayton | ba06db6 | 2020-11-26 16:50:02 +0000 | [diff] [blame] | 51 | /// @returns the diagnostic messages |
| 52 | const diag::List& diagnostics() const { return diags_; } |
| 53 | /// @returns the diagnostic messages |
| 54 | diag::List& diagnostics() { return diags_; } |
| 55 | |
Sarah Mashayekhi | 462dd67 | 2020-03-04 20:51:29 +0000 | [diff] [blame] | 56 | /// @returns error messages from the validator |
Ben Clayton | ba06db6 | 2020-11-26 16:50:02 +0000 | [diff] [blame] | 57 | std::string error() { |
Ben Clayton | d221738 | 2021-01-11 21:09:22 +0000 | [diff] [blame] | 58 | diag::Formatter formatter{{false, false, false, false}}; |
Ben Clayton | ba06db6 | 2020-11-26 16:50:02 +0000 | [diff] [blame] | 59 | return formatter.format(diags_); |
| 60 | } |
Sarah Mashayekhi | 462dd67 | 2020-03-04 20:51:29 +0000 | [diff] [blame] | 61 | /// @returns true if an error was encountered |
Ben Clayton | ba06db6 | 2020-11-26 16:50:02 +0000 | [diff] [blame] | 62 | bool has_error() const { return diags_.contains_errors(); } |
Sarah Mashayekhi | 462dd67 | 2020-03-04 20:51:29 +0000 | [diff] [blame] | 63 | |
Ben Clayton | f8971ae | 2020-12-02 15:31:08 +0000 | [diff] [blame] | 64 | /// Appends an error at `src` with the code `code` and message `msg` |
Ben Clayton | f32a3c1 | 2020-11-26 17:49:22 +0000 | [diff] [blame] | 65 | /// @param src the source causing the error |
| 66 | /// @param code the validation error code |
| 67 | /// @param msg the error message |
| 68 | void add_error(const Source& src, const char* code, const std::string& msg); |
| 69 | |
Ben Clayton | f8971ae | 2020-12-02 15:31:08 +0000 | [diff] [blame] | 70 | /// Appends an error at `src` with the message `msg` |
Sarah Mashayekhi | 462dd67 | 2020-03-04 20:51:29 +0000 | [diff] [blame] | 71 | /// @param src the source causing the error |
| 72 | /// @param msg the error message |
Ben Clayton | ba06db6 | 2020-11-26 16:50:02 +0000 | [diff] [blame] | 73 | void add_error(const Source& src, const std::string& msg); |
| 74 | |
Sarah Mashayekhi | 4fb431c | 2020-08-25 15:04:53 +0000 | [diff] [blame] | 75 | /// Validate global variables |
| 76 | /// @param global_vars list of global variables to check |
| 77 | /// @returns true if the validation was successful |
| 78 | bool ValidateGlobalVariables(const ast::VariableList& global_vars); |
Sarah Mashayekhi | 591fe91 | 2020-07-23 23:49:52 +0000 | [diff] [blame] | 79 | /// Validates Functions |
| 80 | /// @param funcs the functions to check |
| 81 | /// @returns true if the validation was successful |
dan sinclair | 5f81262 | 2020-09-22 14:53:03 +0000 | [diff] [blame] | 82 | bool ValidateFunctions(const ast::FunctionList& funcs); |
Sarah Mashayekhi | 591fe91 | 2020-07-23 23:49:52 +0000 | [diff] [blame] | 83 | /// Validates a function |
| 84 | /// @param func the function to check |
| 85 | /// @returns true if the validation was successful |
Sarah Mashayekhi | a3f9778 | 2020-07-30 02:27:03 +0000 | [diff] [blame] | 86 | bool ValidateFunction(const ast::Function* func); |
Ben Clayton | ca2c1ed | 2021-01-05 18:20:40 +0000 | [diff] [blame] | 87 | /// Validates a function parameter |
| 88 | /// @param param the function parameter to check |
| 89 | /// @returns true if the validation was successful |
| 90 | bool ValidateParameter(const ast::Variable* param); |
dan sinclair | 4069f33 | 2020-07-27 15:25:00 +0000 | [diff] [blame] | 91 | /// Validates a block of statements |
| 92 | /// @param block the statements to check |
| 93 | /// @returns true if the validation was successful |
Sarah Mashayekhi | a3f9778 | 2020-07-30 02:27:03 +0000 | [diff] [blame] | 94 | bool ValidateStatements(const ast::BlockStatement* block); |
Sarah Mashayekhi | 591fe91 | 2020-07-23 23:49:52 +0000 | [diff] [blame] | 95 | /// Validates a statement |
| 96 | /// @param stmt the statement to check |
| 97 | /// @returns true if the validation was successful |
Sarah Mashayekhi | a3f9778 | 2020-07-30 02:27:03 +0000 | [diff] [blame] | 98 | bool ValidateStatement(const ast::Statement* stmt); |
Sarah Mashayekhi | 591fe91 | 2020-07-23 23:49:52 +0000 | [diff] [blame] | 99 | /// Validates an assignment |
Sarah Mashayekhi | e88f1c3 | 2020-08-07 14:34:34 +0000 | [diff] [blame] | 100 | /// @param assign the assignment to check |
Sarah Mashayekhi | 591fe91 | 2020-07-23 23:49:52 +0000 | [diff] [blame] | 101 | /// @returns true if the validation was successful |
Sarah Mashayekhi | e88f1c3 | 2020-08-07 14:34:34 +0000 | [diff] [blame] | 102 | bool ValidateAssign(const ast::AssignmentStatement* assign); |
Sarah Mashayekhi | 65f88d6 | 2020-08-06 21:24:14 +0000 | [diff] [blame] | 103 | /// Validates an expression |
| 104 | /// @param expr the expression to check |
Sarah Mashayekhi | 8db00df | 2020-08-20 17:00:09 +0000 | [diff] [blame] | 105 | /// @return true if the expression is valid |
Sarah Mashayekhi | 65f88d6 | 2020-08-06 21:24:14 +0000 | [diff] [blame] | 106 | bool ValidateExpression(const ast::Expression* expr); |
| 107 | /// Validates v-0006:Variables must be defined before use |
| 108 | /// @param ident the identifer to check if its in the scope |
| 109 | /// @return true if idnet was defined |
| 110 | bool ValidateIdentifier(const ast::IdentifierExpression* ident); |
| 111 | /// Validates if the input follows type checking rules |
Sarah Mashayekhi | e88f1c3 | 2020-08-07 14:34:34 +0000 | [diff] [blame] | 112 | /// @param assign the assignment to check |
Sarah Mashayekhi | 65f88d6 | 2020-08-06 21:24:14 +0000 | [diff] [blame] | 113 | /// @returns ture if successful |
Sarah Mashayekhi | e88f1c3 | 2020-08-07 14:34:34 +0000 | [diff] [blame] | 114 | bool ValidateResultTypes(const ast::AssignmentStatement* assign); |
| 115 | /// Validate v-0021: Cannot re-assign a constant |
| 116 | /// @param assign is the assigment to check if its lhs is a const |
| 117 | /// @returns false if lhs of assign is a constant identifier |
| 118 | bool ValidateConstant(const ast::AssignmentStatement* assign); |
Ben Clayton | f8971ae | 2020-12-02 15:31:08 +0000 | [diff] [blame] | 119 | /// Validates declaration name uniqueness |
| 120 | /// @param decl is the new declaration to be added |
| 121 | /// @returns true if no previous declaration with the `decl` 's name |
Sarah Mashayekhi | d3107bd | 2020-08-11 20:44:06 +0000 | [diff] [blame] | 122 | /// exist in the variable stack |
| 123 | bool ValidateDeclStatement(const ast::VariableDeclStatement* decl); |
Sarah Mashayekhi | b08e253 | 2020-08-17 15:46:07 +0000 | [diff] [blame] | 124 | /// Validates return statement |
| 125 | /// @param ret the return statement to check |
| 126 | /// @returns true if function return type matches the return statement type |
| 127 | bool ValidateReturnStatement(const ast::ReturnStatement* ret); |
Sarah Mashayekhi | 8db00df | 2020-08-20 17:00:09 +0000 | [diff] [blame] | 128 | /// Validates function calls |
| 129 | /// @param expr the call to validate |
| 130 | /// @returns true if successful |
| 131 | bool ValidateCallExpr(const ast::CallExpression* expr); |
Sarah Mashayekhi | 2e9f1f5 | 2020-09-10 14:37:17 +0000 | [diff] [blame] | 132 | /// Validates switch statements |
| 133 | /// @param s the switch statement to check |
| 134 | /// @returns true if the valdiation was successful |
| 135 | bool ValidateSwitch(const ast::SwitchStatement* s); |
| 136 | /// Validates case statements |
| 137 | /// @param c the case statement to check |
| 138 | /// @returns true if the valdiation was successful |
| 139 | bool ValidateCase(const ast::CaseStatement* c); |
Sarah Mashayekhi | 3b04058 | 2020-11-11 14:21:05 +0000 | [diff] [blame] | 140 | /// Validates entry points |
| 141 | /// @param funcs the functions to check |
| 142 | /// @returns true if the valdiation was successful |
| 143 | bool ValidateEntryPoint(const ast::FunctionList& funcs); |
Sarah Mashayekhi | 462dd67 | 2020-03-04 20:51:29 +0000 | [diff] [blame] | 144 | |
Sarah Mashayekhi | d8ea65b | 2020-11-18 22:34:30 +0000 | [diff] [blame] | 145 | /// Validates constructed types |
| 146 | /// @param constructed_types the types to check |
| 147 | /// @returns true if the valdiation was successful |
| 148 | bool ValidateConstructedTypes( |
| 149 | const std::vector<ast::type::Type*>& constructed_types); |
| 150 | |
David Neto | 20f4d1d | 2021-01-18 19:45:24 +0000 | [diff] [blame^] | 151 | /// Returns true if the given type is storable. This uses and |
| 152 | /// updates `storable_` and `not_storable_`. |
| 153 | /// @param type the given type |
| 154 | /// @returns true if the given type is storable. |
| 155 | bool IsStorable(ast::type::Type* type); |
| 156 | |
Sarah Mashayekhi | 462dd67 | 2020-03-04 20:51:29 +0000 | [diff] [blame] | 157 | private: |
dan sinclair | 795b6b5 | 2021-01-11 15:10:19 +0000 | [diff] [blame] | 158 | const ast::Module& module_; |
Ben Clayton | ba06db6 | 2020-11-26 16:50:02 +0000 | [diff] [blame] | 159 | diag::List diags_; |
Sarah Mashayekhi | b77399c | 2020-08-05 15:23:47 +0000 | [diff] [blame] | 160 | ScopeStack<ast::Variable*> variable_stack_; |
Sarah Mashayekhi | eec1a6e | 2020-08-17 15:32:38 +0000 | [diff] [blame] | 161 | ScopeStack<ast::Function*> function_stack_; |
Sarah Mashayekhi | b08e253 | 2020-08-17 15:46:07 +0000 | [diff] [blame] | 162 | ast::Function* current_function_ = nullptr; |
Sarah Mashayekhi | 462dd67 | 2020-03-04 20:51:29 +0000 | [diff] [blame] | 163 | }; |
| 164 | |
| 165 | } // namespace tint |
| 166 | |
Sarah Mashayekhi | 34f90a0 | 2020-11-06 17:31:15 +0000 | [diff] [blame] | 167 | #endif // SRC_VALIDATOR_VALIDATOR_IMPL_H_ |