| 116 | } |
| 117 | |
| 118 | std::variant<std::unique_ptr<AST>, ErrorList> Program::parseObject(Dialect const& _dialect, CharStream _source) |
| 119 | { |
| 120 | ErrorList errors; |
| 121 | ErrorReporter errorReporter(errors); |
| 122 | auto scanner = std::make_shared<Scanner>(_source); |
| 123 | |
| 124 | ObjectParser parser(errorReporter, _dialect); |
| 125 | std::shared_ptr<Object> object = parser.parse(scanner, false); |
| 126 | if (object == nullptr || errorReporter.hasErrors()) |
| 127 | // NOTE: It's possible to get errors even if the returned object is non-null. |
| 128 | // For example when there are errors in a nested object. |
| 129 | return errors; |
| 130 | |
| 131 | Object* deployedObject = nullptr; |
| 132 | if (object->subObjects.size() > 0) |
| 133 | for (auto& subObject: object->subObjects) |
| 134 | // solc --ir produces an object with a subobject of the same name as the outer object |
| 135 | // but suffixed with "_deployed". |
| 136 | // The other object references the nested one which makes analysis fail. Below we try to |
| 137 | // extract just the nested one for that reason. This is just a heuristic. If there's no |
| 138 | // subobject with such a suffix we fall back to accepting the whole object as is. |
| 139 | if (subObject != nullptr && subObject->name == object->name + "_deployed") |
| 140 | { |
| 141 | deployedObject = dynamic_cast<Object*>(subObject.get()); |
| 142 | if (deployedObject != nullptr) |
| 143 | break; |
| 144 | } |
| 145 | Object* selectedObject = (deployedObject != nullptr ? deployedObject : object.get()); |
| 146 | |
| 147 | // NOTE: I'm making a copy of the whole AST to get unique_ptr rather than shared_ptr. |
| 148 | // This is a slight performance hit but it's much less than the parsing itself. |
| 149 | // unique_ptr lets me be sure that two Program instances can never share the AST by mistake. |
| 150 | // The public API of the class does not provide access to the smart pointer so it won't be hard |
| 151 | // to switch to shared_ptr if the copying turns out to be an issue (though it would be better |
| 152 | // to refactor ObjectParser and Object to use unique_ptr instead). |
| 153 | auto astCopy = std::make_unique<AST>(_dialect, std::get<Block>(ASTCopier{}(selectedObject->code()->root()))); |
| 154 | |
| 155 | return std::variant<std::unique_ptr<AST>, ErrorList>(std::move(astCopy)); |
| 156 | } |
| 157 | |
| 158 | std::variant<std::unique_ptr<AsmAnalysisInfo>, ErrorList> Program::analyzeAST(Dialect const& _dialect, AST const& _ast) |
| 159 | { |