| [55cbff8] | 1 | //
 | 
|---|
 | 2 | // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
 | 
|---|
 | 3 | //
 | 
|---|
 | 4 | // The contents of this file are covered under the licence agreement in the
 | 
|---|
 | 5 | // file "LICENCE" distributed with Cforall.
 | 
|---|
 | 6 | //
 | 
|---|
 | 7 | // ResolvProtoDump.cpp -- Prints AST as instances for resolv-proto.
 | 
|---|
 | 8 | //
 | 
|---|
 | 9 | // Author           : Andrew Beach
 | 
|---|
 | 10 | // Created On       : Wed Oct  6 14:10:00 2021
 | 
|---|
 | 11 | // Last Modified By : Andrew Beach
 | 
|---|
 | 12 | // Last Modified On : Tue Oct 18 11:23:00 2021
 | 
|---|
 | 13 | // Update Count     : 0
 | 
|---|
 | 14 | //
 | 
|---|
 | 15 | 
 | 
|---|
 | 16 | #include "ResolvProtoDump.hpp"
 | 
|---|
 | 17 | 
 | 
|---|
 | 18 | #include <cctype>
 | 
|---|
 | 19 | #include <iostream>
 | 
|---|
 | 20 | #include <set>
 | 
|---|
| [9feb34b] | 21 | #include <sstream>
 | 
|---|
| [55cbff8] | 22 | #include <unordered_set>
 | 
|---|
 | 23 | 
 | 
|---|
 | 24 | #include "AST/Copy.hpp"
 | 
|---|
 | 25 | #include "AST/Pass.hpp"
 | 
|---|
 | 26 | #include "AST/TranslationUnit.hpp"
 | 
|---|
 | 27 | #include "AST/Type.hpp"
 | 
|---|
 | 28 | #include "CodeGen/OperatorTable.h"
 | 
|---|
 | 29 | 
 | 
|---|
 | 30 | namespace {
 | 
|---|
 | 31 | 
 | 
|---|
 | 32 | /// Add a prefix to an existing name.
 | 
|---|
 | 33 | std::string add_prefix( const std::string & prefix, const char * added ) {
 | 
|---|
 | 34 |         if ( prefix.empty() ) {
 | 
|---|
 | 35 |                 return std::string("$") + added;
 | 
|---|
 | 36 |         } else {
 | 
|---|
 | 37 |                 return prefix + added;
 | 
|---|
 | 38 |         }
 | 
|---|
 | 39 | }
 | 
|---|
 | 40 | 
 | 
|---|
 | 41 | /// Shortens operator names.
 | 
|---|
 | 42 | std::string op_name( const std::string & name ) {
 | 
|---|
 | 43 |         if ( name.compare( 0, 10, "_operator_" ) == 0 ) {
 | 
|---|
 | 44 |                 return name.substr( 10 );
 | 
|---|
 | 45 |         } else if ( name.compare( "_constructor" ) == 0
 | 
|---|
 | 46 |                         || name.compare( "_destructor" ) == 0 ) {
 | 
|---|
 | 47 |                 return name.substr( 1 );
 | 
|---|
 | 48 |         } else if ( name.compare( 0, 11, "__operator_" ) == 0 ) {
 | 
|---|
 | 49 |                 return name.substr( 11 );
 | 
|---|
 | 50 |         } else {
 | 
|---|
 | 51 |                 return name;
 | 
|---|
 | 52 |         }
 | 
|---|
 | 53 | }
 | 
|---|
 | 54 | 
 | 
|---|
 | 55 | /// Get the resolv-proto names for operators.
 | 
|---|
 | 56 | std::string rp_name( const std::string & name, std::string && pre = "" ) {
 | 
|---|
 | 57 |         // Check for anonymous names.
 | 
|---|
 | 58 |         if ( name.empty() ) {
 | 
|---|
 | 59 |                 return add_prefix( pre, "anon" );
 | 
|---|
 | 60 |         }
 | 
|---|
 | 61 | 
 | 
|---|
 | 62 |         // Replace operator names.
 | 
|---|
 | 63 |         const CodeGen::OperatorInfo * opInfo = CodeGen::operatorLookup( name );
 | 
|---|
 | 64 |         if ( nullptr != opInfo ) {
 | 
|---|
 | 65 |                 return add_prefix( pre, "" ) + op_name( opInfo->outputName );
 | 
|---|
 | 66 |         }
 | 
|---|
 | 67 | 
 | 
|---|
 | 68 |         // Replace return value prefix.
 | 
|---|
 | 69 |         if ( name.compare( 0, 8, "_retval_" ) == 0 ) {
 | 
|---|
 | 70 |                 return add_prefix( pre, "rtn_" ) + op_name( name.substr( 8 ) );
 | 
|---|
 | 71 |         }
 | 
|---|
 | 72 | 
 | 
|---|
 | 73 |         // Default to just name, with first character in lowercase.
 | 
|---|
 | 74 |         if ( std::isupper( name[0] ) ) {
 | 
|---|
 | 75 |                 std::string copy = name;
 | 
|---|
 | 76 |                 copy[0] = std::tolower( copy[0] );
 | 
|---|
 | 77 |                 return pre + copy;
 | 
|---|
 | 78 |         }
 | 
|---|
 | 79 |         return pre + name;
 | 
|---|
 | 80 | }
 | 
|---|
 | 81 | 
 | 
|---|
 | 82 | /// Normalise a type instance name.
 | 
|---|
 | 83 | std::string ti_name( const std::string & name ) {
 | 
|---|
 | 84 |         // Replace built-in names
 | 
|---|
 | 85 |         if ( name == "char16_t" || name == "char32_t" || name == "wchar_t" ) {
 | 
|---|
 | 86 |                 return std::string("#") + name;
 | 
|---|
 | 87 |         }
 | 
|---|
 | 88 | 
 | 
|---|
 | 89 |         // Strip leadng underscores.
 | 
|---|
 | 90 |         unsigned i = 0;
 | 
|---|
 | 91 |         while ( i < name.size() && name[i] == '_' ) { ++i; }
 | 
|---|
 | 92 |         if ( i == name.size() ) {
 | 
|---|
 | 93 |                 return "Anon";
 | 
|---|
 | 94 |         }
 | 
|---|
 | 95 | 
 | 
|---|
 | 96 |         std::string stripped = name.substr( i );
 | 
|---|
 | 97 |         // Strip trailing generic from autogen names ()
 | 
|---|
 | 98 |         static char generic[] = "_generic_";
 | 
|---|
 | 99 |         static size_t n_generic = sizeof(generic) - 1;
 | 
|---|
 | 100 |         if ( stripped.size() >= n_generic
 | 
|---|
 | 101 |                         && stripped.substr( stripped.size() - n_generic ) == generic ) {
 | 
|---|
 | 102 |                 stripped.resize( stripped.size() - n_generic );
 | 
|---|
 | 103 |         }
 | 
|---|
 | 104 | 
 | 
|---|
 | 105 |         // Uppercase first character.
 | 
|---|
 | 106 |         stripped[0] = std::toupper( stripped[0] );
 | 
|---|
 | 107 |         return stripped;
 | 
|---|
 | 108 | }
 | 
|---|
 | 109 | 
 | 
|---|
 | 110 | std::vector<ast::ptr<ast::Type>> to_types(
 | 
|---|
 | 111 |                 const std::vector<ast::ptr<ast::Expr>> & data ) {
 | 
|---|
 | 112 |         std::vector<ast::ptr<ast::Type>> ret_val;
 | 
|---|
 | 113 |         ret_val.reserve( data.size() );
 | 
|---|
 | 114 |         for ( auto entry : data ) {
 | 
|---|
 | 115 |                 if ( auto * typeExpr = entry.as<ast::TypeExpr>() ) {
 | 
|---|
 | 116 |                         ret_val.emplace_back( typeExpr->type );
 | 
|---|
 | 117 |                 }
 | 
|---|
 | 118 |         }
 | 
|---|
 | 119 |         return ret_val;
 | 
|---|
 | 120 | }
 | 
|---|
 | 121 | 
 | 
|---|
 | 122 | enum class septype { separated, terminated, preceded };
 | 
|---|
 | 123 | 
 | 
|---|
 | 124 | template<typename V>
 | 
|---|
 | 125 | void build(
 | 
|---|
 | 126 |                 V & visitor,
 | 
|---|
 | 127 |                 const std::vector<ast::ptr<ast::Type>> & types,
 | 
|---|
 | 128 |                 std::stringstream & ss,
 | 
|---|
 | 129 |                 septype mode );
 | 
|---|
 | 130 | 
 | 
|---|
 | 131 | template<typename V>
 | 
|---|
 | 132 | void buildAsTuple(
 | 
|---|
 | 133 |                 V & visitor, const std::vector<ast::ptr<ast::Type>> & types,
 | 
|---|
 | 134 |                 std::stringstream & ss );
 | 
|---|
 | 135 | 
 | 
|---|
 | 136 | struct TypePrinter : public ast::WithShortCircuiting, ast::WithVisitorRef<TypePrinter> {
 | 
|---|
 | 137 |         /// Accumulator for the printed type.
 | 
|---|
 | 138 |         std::stringstream ss;
 | 
|---|
 | 139 |         /// Closed type variables.
 | 
|---|
 | 140 |         const std::unordered_set<std::string> & closed;
 | 
|---|
 | 141 |         /// Depth of nesting from root type.
 | 
|---|
 | 142 |         unsigned depth;
 | 
|---|
 | 143 | 
 | 
|---|
 | 144 |         TypePrinter( const std::unordered_set<std::string> & closed ) :
 | 
|---|
 | 145 |                 ss(), closed(closed), depth(0)
 | 
|---|
 | 146 |         {}
 | 
|---|
 | 147 | 
 | 
|---|
 | 148 |         std::string result() const {
 | 
|---|
 | 149 |                 return ss.str();
 | 
|---|
 | 150 |         }
 | 
|---|
 | 151 | 
 | 
|---|
 | 152 |         // Basic type represented as an integer type.
 | 
|---|
 | 153 |         // TODO: Maybe hard-code conversion graph and make named type.
 | 
|---|
 | 154 |         void previsit( const ast::BasicType * type ) {
 | 
|---|
 | 155 |                 ss << (int)type->kind;
 | 
|---|
 | 156 |         }
 | 
|---|
 | 157 | 
 | 
|---|
 | 158 |         // Pointers (except function pointers) are represented as generic type.
 | 
|---|
 | 159 |         void previsit( const ast::PointerType * type ) {
 | 
|---|
 | 160 |                 if ( nullptr == type->base.as<ast::FunctionType>() ) {
 | 
|---|
 | 161 |                         ss << "#$ptr<";
 | 
|---|
 | 162 |                         ++depth;
 | 
|---|
 | 163 |                 }
 | 
|---|
 | 164 |         }
 | 
|---|
 | 165 |         void postvisit( const ast::PointerType * type ) {
 | 
|---|
 | 166 |                 if ( nullptr == type->base.as<ast::FunctionType>() ) {
 | 
|---|
 | 167 |                         --depth;
 | 
|---|
 | 168 |                         ss << '>';
 | 
|---|
 | 169 |                 }
 | 
|---|
 | 170 |         }
 | 
|---|
 | 171 | 
 | 
|---|
 | 172 |         // Arrays repersented as pointers.
 | 
|---|
 | 173 |         void previsit( const ast::ArrayType * type ) {
 | 
|---|
 | 174 |                 ss << "#$ptr<";
 | 
|---|
 | 175 |                 ++depth;
 | 
|---|
 | 176 |                 type->base->accept( *visitor );
 | 
|---|
 | 177 |                 --depth;
 | 
|---|
 | 178 |                 ss << '>';
 | 
|---|
 | 179 |                 visit_children = false;
 | 
|---|
 | 180 |         }
 | 
|---|
 | 181 | 
 | 
|---|
 | 182 |         // Ignore top-level references as they are mostly transparent to resolution.
 | 
|---|
 | 183 |         void previsit( const ast::ReferenceType * ) {
 | 
|---|
 | 184 |                 if ( !atTopLevel() ) { ss << "#$ref<"; }
 | 
|---|
 | 185 |                 ++depth;
 | 
|---|
 | 186 |         }
 | 
|---|
 | 187 |         void postvisit( const ast::ReferenceType * ) {
 | 
|---|
 | 188 |                 --depth;
 | 
|---|
 | 189 |                 if ( !atTopLevel() ) { ss << '>'; }
 | 
|---|
 | 190 |         }
 | 
|---|
 | 191 | 
 | 
|---|
 | 192 |         void previsit( const ast::FunctionType * type ) {
 | 
|---|
 | 193 |                 ss << '[';
 | 
|---|
 | 194 |                 ++depth;
 | 
|---|
 | 195 |                 build( *visitor, type->returns, ss, septype::preceded );
 | 
|---|
 | 196 |                 ss << " : ";
 | 
|---|
 | 197 |                 build( *visitor, type->params, ss, septype::terminated );
 | 
|---|
 | 198 |                 --depth;
 | 
|---|
 | 199 |                 ss << ']';
 | 
|---|
 | 200 |                 visit_children = false;
 | 
|---|
 | 201 |         }
 | 
|---|
 | 202 | 
 | 
|---|
 | 203 | private:
 | 
|---|
 | 204 |         bool atTopLevel() const {
 | 
|---|
 | 205 |                 return 0 == depth;
 | 
|---|
 | 206 |         }
 | 
|---|
 | 207 | 
 | 
|---|
 | 208 |         void handleAggregate( const ast::BaseInstType * type ) {
 | 
|---|
 | 209 |                 ss << '#' << type->name;
 | 
|---|
 | 210 |                 if ( !type->params.empty() ) {
 | 
|---|
 | 211 |                         ss << '<';
 | 
|---|
 | 212 |                         ++depth;
 | 
|---|
 | 213 |                         build( *visitor, to_types( type->params ), ss, septype::separated );
 | 
|---|
 | 214 |                         --depth;
 | 
|---|
 | 215 |                         ss << '>';
 | 
|---|
 | 216 |                 }
 | 
|---|
 | 217 |                 visit_children = false;
 | 
|---|
 | 218 |         }
 | 
|---|
 | 219 | public:
 | 
|---|
 | 220 | 
 | 
|---|
 | 221 |         void previsit( const ast::StructInstType * type ) {
 | 
|---|
 | 222 |                 handleAggregate( type );
 | 
|---|
 | 223 |         }
 | 
|---|
 | 224 | 
 | 
|---|
 | 225 |         void previsit( const ast::UnionInstType * type ) {
 | 
|---|
 | 226 |                 handleAggregate( type );
 | 
|---|
 | 227 |         }
 | 
|---|
 | 228 | 
 | 
|---|
| [c19edd1] | 229 |         void previsit( const ast::EnumInstType * ) {
 | 
|---|
| [fc134a48] | 230 |                 // TODO: Add the meaningful text representation of typed enum
 | 
|---|
| [55cbff8] | 231 |                 ss << (int)ast::BasicType::SignedInt;
 | 
|---|
 | 232 |         }
 | 
|---|
 | 233 | 
 | 
|---|
 | 234 |         void previsit( const ast::TypeInstType * type ) {
 | 
|---|
 | 235 |                 // Print closed variables as named types.
 | 
|---|
 | 236 |                 if ( closed.count( type->name ) ) {
 | 
|---|
 | 237 |                         ss << '#' << type->name;
 | 
|---|
 | 238 |                 // Otherwise normalize the name.
 | 
|---|
 | 239 |                 } else {
 | 
|---|
 | 240 |                         ss << ti_name( type->name );
 | 
|---|
 | 241 |                 }
 | 
|---|
 | 242 |         }
 | 
|---|
 | 243 | 
 | 
|---|
 | 244 |         void previsit( const ast::TupleType * tupleType ) {
 | 
|---|
 | 245 |                 ++depth;
 | 
|---|
 | 246 |                 buildAsTuple( *visitor, tupleType->types, ss );
 | 
|---|
 | 247 |                 --depth;
 | 
|---|
 | 248 |                 visit_children = false;
 | 
|---|
 | 249 |         }
 | 
|---|
 | 250 | 
 | 
|---|
 | 251 |         void previsit( const ast::VarArgsType * ) {
 | 
|---|
 | 252 |                 if ( atTopLevel() ) ss << "#$varargs";
 | 
|---|
 | 253 |         }
 | 
|---|
 | 254 | 
 | 
|---|
 | 255 |         // TODO: Support 0 and 1 with their type names and conversions.
 | 
|---|
 | 256 |         void previsit( const ast::ZeroType * ) {
 | 
|---|
 | 257 |                 ss << (int)ast::BasicType::SignedInt;
 | 
|---|
 | 258 |         }
 | 
|---|
 | 259 | 
 | 
|---|
 | 260 |         void previsit( const ast::OneType * ) {
 | 
|---|
 | 261 |                 ss << (int)ast::BasicType::SignedInt;
 | 
|---|
 | 262 |         }
 | 
|---|
 | 263 | 
 | 
|---|
 | 264 |         void previsit( const ast::VoidType * ) {
 | 
|---|
 | 265 |                 if ( !atTopLevel() ) {
 | 
|---|
 | 266 |                         ss << "#void";
 | 
|---|
 | 267 |                 }
 | 
|---|
 | 268 |         }
 | 
|---|
 | 269 | };
 | 
|---|
 | 270 | 
 | 
|---|
 | 271 | struct ExprPrinter : public ast::WithShortCircuiting, ast::WithVisitorRef<ExprPrinter> {
 | 
|---|
 | 272 |         // TODO: Change interface to generate multiple expression canditates.
 | 
|---|
 | 273 |         /// Accumulator of the printed expression.
 | 
|---|
 | 274 |         std::stringstream ss;
 | 
|---|
 | 275 |         /// Set of closed type variables.
 | 
|---|
 | 276 |         const std::unordered_set<std::string> & closed;
 | 
|---|
 | 277 | 
 | 
|---|
 | 278 |         ExprPrinter( const std::unordered_set<std::string> & closed ) :
 | 
|---|
 | 279 |                 ss(), closed( closed )
 | 
|---|
 | 280 |         {}
 | 
|---|
 | 281 | 
 | 
|---|
 | 282 |         std::string result() const {
 | 
|---|
 | 283 |                 return ss.str();
 | 
|---|
 | 284 |         }
 | 
|---|
 | 285 | 
 | 
|---|
 | 286 |         void previsit( const ast::NameExpr * expr ) {
 | 
|---|
 | 287 |                 ss << '&' << rp_name( expr->name );
 | 
|---|
 | 288 |         }
 | 
|---|
 | 289 | 
 | 
|---|
 | 290 |         /// Handle already resolved variables as type constants.
 | 
|---|
 | 291 |         void previsit( const ast::VariableExpr * expr ) {
 | 
|---|
 | 292 |                 ss << ast::Pass<TypePrinter>::read( expr->var->get_type(), closed );
 | 
|---|
 | 293 |                 visit_children = false;
 | 
|---|
 | 294 |         }
 | 
|---|
 | 295 | 
 | 
|---|
 | 296 |         void previsit( const ast::UntypedExpr * expr ) {
 | 
|---|
 | 297 |                 // TODO: Handle name extraction more generally.
 | 
|---|
 | 298 |                 const ast::NameExpr * name = expr->func.as<ast::NameExpr>();
 | 
|---|
 | 299 | 
 | 
|---|
 | 300 |                 // TODO: Incorporate function type into resolv-proto.
 | 
|---|
 | 301 |                 if ( !name ) {
 | 
|---|
 | 302 |                         expr->func->accept( *visitor );
 | 
|---|
 | 303 |                         visit_children = false;
 | 
|---|
 | 304 |                         return;
 | 
|---|
 | 305 |                 }
 | 
|---|
 | 306 | 
 | 
|---|
 | 307 |                 ss << rp_name( name->name );
 | 
|---|
 | 308 |                 if ( expr->args.empty() ) {
 | 
|---|
 | 309 |                         ss << "()";
 | 
|---|
 | 310 |                 } else {
 | 
|---|
 | 311 |                         ss << "( ";
 | 
|---|
 | 312 |                         auto it = expr->args.begin();
 | 
|---|
 | 313 |                         while (true) {
 | 
|---|
 | 314 |                                 (*it)->accept( *visitor );
 | 
|---|
 | 315 |                                 if ( ++it == expr->args.end() ) break;
 | 
|---|
 | 316 |                                 ss << ' ';
 | 
|---|
 | 317 |                         }
 | 
|---|
 | 318 |                         ss << " )";
 | 
|---|
 | 319 |                 }
 | 
|---|
 | 320 |                 visit_children = false;
 | 
|---|
 | 321 |         }
 | 
|---|
 | 322 | 
 | 
|---|
 | 323 |         void previsit( const ast::ApplicationExpr * expr ) {
 | 
|---|
 | 324 |                 ss << ast::Pass<TypePrinter>::read( static_cast<const ast::Expr *>( expr ), closed );
 | 
|---|
 | 325 |                 visit_children = false;
 | 
|---|
 | 326 |         }
 | 
|---|
 | 327 | 
 | 
|---|
 | 328 |         void previsit( const ast::AddressExpr * expr ) {
 | 
|---|
 | 329 |                 ss << "$addr( ";
 | 
|---|
 | 330 |                 expr->arg->accept( *visitor );
 | 
|---|
 | 331 |                 ss << " )";
 | 
|---|
 | 332 |                 visit_children = false;
 | 
|---|
 | 333 |         }
 | 
|---|
 | 334 | 
 | 
|---|
 | 335 |         void previsit( const ast::CastExpr * expr ) {
 | 
|---|
 | 336 |                 ss << ast::Pass<TypePrinter>::read( expr->result.get(), closed );
 | 
|---|
 | 337 |                 visit_children = false;
 | 
|---|
 | 338 |         }
 | 
|---|
 | 339 | 
 | 
|---|
 | 340 |         /// Member access handled as function from aggregate to member.
 | 
|---|
 | 341 |         void previsit( const ast::UntypedMemberExpr * expr ) {
 | 
|---|
 | 342 |                 // TODO: Handle name extraction more generally.
 | 
|---|
 | 343 |                 const ast::NameExpr * name = expr->member.as<ast::NameExpr>();
 | 
|---|
 | 344 | 
 | 
|---|
 | 345 |                 // TODO: Incorporate function type into resolve-proto.
 | 
|---|
 | 346 |                 if ( !name ) {
 | 
|---|
 | 347 |                         expr->member->accept( *visitor );
 | 
|---|
 | 348 |                         visit_children = false;
 | 
|---|
 | 349 |                         return;
 | 
|---|
 | 350 |                 }
 | 
|---|
 | 351 | 
 | 
|---|
 | 352 |                 ss << rp_name( name->name, "$field_" );
 | 
|---|
 | 353 |                 ss << "( ";
 | 
|---|
 | 354 |                 expr->aggregate->accept( *visitor );
 | 
|---|
 | 355 |                 ss << " )";
 | 
|---|
 | 356 |                 visit_children = false;
 | 
|---|
 | 357 |         }
 | 
|---|
 | 358 | 
 | 
|---|
 | 359 |         /// Constant expression replaced by its type.
 | 
|---|
 | 360 |         void previsit( const ast::ConstantExpr * expr ) {
 | 
|---|
 | 361 |                 ss << ast::Pass<TypePrinter>::read( static_cast<const ast::Expr *>( expr ), closed );
 | 
|---|
 | 362 |                 visit_children = false;
 | 
|---|
 | 363 |         }
 | 
|---|
 | 364 | 
 | 
|---|
 | 365 |         /// sizeof, alignof, & offsetof are replaced by constant type.
 | 
|---|
 | 366 |         // TODO: Extra expression to resolve argument.
 | 
|---|
 | 367 |         void previsit( const ast::SizeofExpr * ) {
 | 
|---|
 | 368 |                 ss << (int)ast::BasicType::LongUnsignedInt;
 | 
|---|
 | 369 |                 visit_children = false;
 | 
|---|
 | 370 |         }
 | 
|---|
 | 371 |         void previsit( const ast::AlignofExpr * ) {
 | 
|---|
 | 372 |                 ss << (int)ast::BasicType::LongUnsignedInt;
 | 
|---|
 | 373 |                 visit_children = false;
 | 
|---|
 | 374 |         }
 | 
|---|
 | 375 |         void previsit( const ast::UntypedOffsetofExpr * ) {
 | 
|---|
 | 376 |                 ss << (int)ast::BasicType::LongUnsignedInt;
 | 
|---|
 | 377 |                 visit_children = false;
 | 
|---|
 | 378 |         }
 | 
|---|
 | 379 | 
 | 
|---|
 | 380 |         /// Logical expressions represented as operators.
 | 
|---|
 | 381 |         void previsit( const ast::LogicalExpr * expr ) {
 | 
|---|
 | 382 |                 ss << ( (ast::AndExpr == expr->isAnd) ? "$and( " : "$or( " );
 | 
|---|
 | 383 |                 expr->arg1->accept( *visitor );
 | 
|---|
 | 384 |                 ss << ' ';
 | 
|---|
 | 385 |                 expr->arg2->accept( *visitor );
 | 
|---|
 | 386 |                 ss << " )";
 | 
|---|
 | 387 |                 visit_children = false;
 | 
|---|
 | 388 |         }
 | 
|---|
 | 389 | 
 | 
|---|
 | 390 |         /// Conditional expression represented as an operator.
 | 
|---|
 | 391 |         void previsit( const ast::ConditionalExpr * expr ) {
 | 
|---|
 | 392 |                 ss << "$if( ";
 | 
|---|
 | 393 |                 expr->arg1->accept( *visitor );
 | 
|---|
 | 394 |                 ss << ' ';
 | 
|---|
 | 395 |                 expr->arg2->accept( *visitor );
 | 
|---|
 | 396 |                 ss << ' ';
 | 
|---|
 | 397 |                 expr->arg3->accept( *visitor );
 | 
|---|
 | 398 |                 ss << " )";
 | 
|---|
 | 399 |                 visit_children = false;
 | 
|---|
 | 400 |         }
 | 
|---|
 | 401 | 
 | 
|---|
 | 402 |         /// Comma expression represented as on operator.
 | 
|---|
 | 403 |         void previsit( const ast::CommaExpr * expr ) {
 | 
|---|
 | 404 |                 ss << "$seq( ";
 | 
|---|
 | 405 |                 expr->arg1->accept( *visitor );
 | 
|---|
 | 406 |                 ss << ' ';
 | 
|---|
 | 407 |                 expr->arg2->accept( *visitor );
 | 
|---|
 | 408 |                 ss << " )";
 | 
|---|
 | 409 |                 visit_children = false;
 | 
|---|
 | 410 |         }
 | 
|---|
 | 411 | 
 | 
|---|
 | 412 |         // TODO: Handle ignored ImplicitCopyCtorExpr and below.
 | 
|---|
 | 413 | };
 | 
|---|
 | 414 | 
 | 
|---|
 | 415 | template<typename V>
 | 
|---|
 | 416 | void build(
 | 
|---|
 | 417 |                 V & visitor,
 | 
|---|
 | 418 |                 const std::vector<ast::ptr<ast::Type>> & types,
 | 
|---|
 | 419 |                 std::stringstream & ss,
 | 
|---|
 | 420 |                 septype mode ) {
 | 
|---|
 | 421 |         if ( types.empty() ) return;
 | 
|---|
 | 422 | 
 | 
|---|
 | 423 |         if ( septype::preceded == mode ) { ss << ' '; }
 | 
|---|
 | 424 | 
 | 
|---|
 | 425 |         auto it = types.begin();
 | 
|---|
 | 426 |         (*it)->accept( visitor );
 | 
|---|
 | 427 | 
 | 
|---|
 | 428 |         while ( ++it != types.end() ) {
 | 
|---|
 | 429 |                 ss << ' ';
 | 
|---|
 | 430 |                 (*it)->accept( visitor );
 | 
|---|
 | 431 |         }
 | 
|---|
 | 432 | 
 | 
|---|
 | 433 |         if ( septype::terminated == mode ) { ss << ' '; }
 | 
|---|
 | 434 | }
 | 
|---|
 | 435 | 
 | 
|---|
 | 436 | std::string buildType(
 | 
|---|
 | 437 |                 const std::string & name, const ast::Type * type,
 | 
|---|
 | 438 |                 const std::unordered_set<std::string> & closed );
 | 
|---|
 | 439 | 
 | 
|---|
 | 440 | /// Build a string representing a function type.
 | 
|---|
 | 441 | std::string buildFunctionType(
 | 
|---|
 | 442 |                 const std::string & name, const ast::FunctionType * type,
 | 
|---|
 | 443 |                 const std::unordered_set<std::string> & closed ) {
 | 
|---|
 | 444 |         ast::Pass<TypePrinter> printer( closed );
 | 
|---|
 | 445 |         std::stringstream & ss = printer.core.ss;
 | 
|---|
 | 446 | 
 | 
|---|
 | 447 |         build( printer, type->returns, ss, septype::terminated );
 | 
|---|
 | 448 |         ss << rp_name( name );
 | 
|---|
 | 449 |         build( printer, type->params, ss, septype::preceded );
 | 
|---|
 | 450 |         for ( const auto & assertion : type->assertions ) {
 | 
|---|
 | 451 |                 auto var = assertion->var;
 | 
|---|
 | 452 |                 ss << " | " << buildType( var->name, var->get_type(), closed );
 | 
|---|
 | 453 |         }
 | 
|---|
 | 454 |         return ss.str();
 | 
|---|
 | 455 | }
 | 
|---|
 | 456 | 
 | 
|---|
 | 457 | /// Build a description of a type.
 | 
|---|
 | 458 | std::string buildType(
 | 
|---|
 | 459 |                 const std::string & name, const ast::Type * type,
 | 
|---|
 | 460 |                 const std::unordered_set<std::string> & closed ) {
 | 
|---|
 | 461 |         const ast::Type * norefs = type->stripReferences();
 | 
|---|
 | 462 | 
 | 
|---|
 | 463 |         if ( const auto & ptrType = dynamic_cast<const ast::PointerType *>( norefs ) ) {
 | 
|---|
 | 464 |                 if ( const auto & funcType = ptrType->base.as<ast::FunctionType>() ) {
 | 
|---|
 | 465 |                         return buildFunctionType( name, funcType, closed );
 | 
|---|
 | 466 |                 }
 | 
|---|
 | 467 |         } else if ( const auto & funcType = dynamic_cast<const ast::FunctionType *>( norefs ) ) {
 | 
|---|
 | 468 |                 return buildFunctionType( name, funcType, closed );
 | 
|---|
 | 469 |         }
 | 
|---|
 | 470 | 
 | 
|---|
 | 471 |         std::stringstream ss;
 | 
|---|
 | 472 |         ss << ast::Pass<TypePrinter>::read( norefs, closed );
 | 
|---|
 | 473 |         ss << " &" << rp_name( name );
 | 
|---|
 | 474 |         return ss.str();
 | 
|---|
 | 475 | }
 | 
|---|
 | 476 | 
 | 
|---|
 | 477 | /// Builds description of a field access.
 | 
|---|
 | 478 | std::string buildAggregateDecl( const std::string & name,
 | 
|---|
 | 479 |                 const ast::AggregateDecl * agg, const ast::Type * type,
 | 
|---|
 | 480 |                 const std::unordered_set<std::string> & closed ) {
 | 
|---|
 | 481 |         const ast::Type * norefs = type->stripReferences();
 | 
|---|
 | 482 |         std::stringstream ss;
 | 
|---|
 | 483 | 
 | 
|---|
 | 484 |         ss << ast::Pass<TypePrinter>::read( norefs, closed ) << ' ';
 | 
|---|
 | 485 |         ss << rp_name( name, "$field_" );
 | 
|---|
 | 486 |         ss << " #" << agg->name;
 | 
|---|
 | 487 |         if ( !agg->params.empty() ) {
 | 
|---|
 | 488 |                 ss << '<';
 | 
|---|
 | 489 |                 auto it = agg->params.begin();
 | 
|---|
 | 490 |                 while (true) {
 | 
|---|
 | 491 |                         ss << ti_name( (*it)->name );
 | 
|---|
 | 492 |                         if ( ++it == agg->params.end() ) break;
 | 
|---|
 | 493 |                         ss << ' ';
 | 
|---|
 | 494 |                 }
 | 
|---|
 | 495 |                 ss << '>';
 | 
|---|
 | 496 |         }
 | 
|---|
 | 497 |         return ss.str();
 | 
|---|
 | 498 | }
 | 
|---|
 | 499 | 
 | 
|---|
 | 500 | template<typename V>
 | 
|---|
 | 501 | void buildAsTuple(
 | 
|---|
 | 502 |                 V & visitor, const std::vector<ast::ptr<ast::Type>> & types,
 | 
|---|
 | 503 |                 std::stringstream & ss ) {
 | 
|---|
 | 504 |         switch ( types.size() ) {
 | 
|---|
 | 505 |         case 0:
 | 
|---|
 | 506 |                 ss << "#void";
 | 
|---|
 | 507 |                 break;
 | 
|---|
 | 508 |         case 1:
 | 
|---|
 | 509 |                 types.front()->accept( visitor );
 | 
|---|
 | 510 |                 break;
 | 
|---|
 | 511 |         default:
 | 
|---|
 | 512 |                 ss << "#$" << types.size() << '<';
 | 
|---|
 | 513 |                 build( visitor, types, ss, septype::separated );
 | 
|---|
 | 514 |                 ss << '>';
 | 
|---|
 | 515 |                 break;
 | 
|---|
 | 516 |         }
 | 
|---|
 | 517 | }
 | 
|---|
 | 518 | 
 | 
|---|
 | 519 | /// Adds a return
 | 
|---|
 | 520 | std::string buildReturn(
 | 
|---|
 | 521 |                 const ast::Type * returnType,
 | 
|---|
 | 522 |                 const ast::Expr * expr,
 | 
|---|
 | 523 |                 const std::unordered_set<std::string> & closed ) {
 | 
|---|
 | 524 |         std::stringstream ss;
 | 
|---|
 | 525 |         ss << "$constructor( ";
 | 
|---|
 | 526 |         ss << ast::Pass<TypePrinter>::read( returnType, closed );
 | 
|---|
 | 527 |         ss << ' ';
 | 
|---|
 | 528 |         ss << ast::Pass<ExprPrinter>::read( expr, closed );
 | 
|---|
 | 529 |         ss << " )";
 | 
|---|
 | 530 |         return ss.str();
 | 
|---|
 | 531 | }
 | 
|---|
 | 532 | 
 | 
|---|
 | 533 | void buildInitComponent(
 | 
|---|
 | 534 |                 std::stringstream & out, const ast::Init * init,
 | 
|---|
 | 535 |                 const std::unordered_set<std::string> & closed ) {
 | 
|---|
 | 536 |         if ( const auto * s = dynamic_cast<const ast::SingleInit *>( init ) ) {
 | 
|---|
 | 537 |                 out << ast::Pass<ExprPrinter>::read( s->value.get(), closed ) << ' ';
 | 
|---|
 | 538 |         } else if ( const auto * l = dynamic_cast<const ast::ListInit *>( init ) ) {
 | 
|---|
 | 539 |                 for ( const auto & it : l->initializers ) {
 | 
|---|
 | 540 |                         buildInitComponent( out, it, closed );
 | 
|---|
 | 541 |                 }
 | 
|---|
 | 542 |         }
 | 
|---|
 | 543 | }
 | 
|---|
 | 544 | 
 | 
|---|
 | 545 | /// Build a representation of an initializer.
 | 
|---|
 | 546 | std::string buildInitializer(
 | 
|---|
 | 547 |                 const std::string & name, const ast::Init * init,
 | 
|---|
 | 548 |                 const std::unordered_set<std::string> & closed ) {
 | 
|---|
 | 549 |         std::stringstream ss;
 | 
|---|
 | 550 |         ss << "$constructor( &";
 | 
|---|
 | 551 |         ss << rp_name( name );
 | 
|---|
 | 552 |         ss << ' ';
 | 
|---|
 | 553 |         buildInitComponent( ss, init, closed );
 | 
|---|
 | 554 |         ss << ')';
 | 
|---|
 | 555 |         return ss.str();
 | 
|---|
 | 556 | }
 | 
|---|
 | 557 | 
 | 
|---|
 | 558 | /// Visitor for collecting and printing resolver prototype output.
 | 
|---|
 | 559 | class ProtoDump : public ast::WithShortCircuiting, ast::WithVisitorRef<ProtoDump> {
 | 
|---|
 | 560 |         /// Declarations in this scope.
 | 
|---|
 | 561 |         // Set is used for ordering of printing.
 | 
|---|
 | 562 |         std::set<std::string> decls;
 | 
|---|
 | 563 |         /// Expressions in this scope.
 | 
|---|
 | 564 |         std::vector<std::string> exprs;
 | 
|---|
 | 565 |         /// Sub-scopes
 | 
|---|
 | 566 |         std::vector<ProtoDump> subs;
 | 
|---|
 | 567 |         /// Closed type variables
 | 
|---|
 | 568 |         std::unordered_set<std::string> closed;
 | 
|---|
 | 569 |         /// Outer lexical scope
 | 
|---|
 | 570 |         const ProtoDump * parent;
 | 
|---|
 | 571 |         /// Return type for this scope
 | 
|---|
 | 572 |         ast::ptr<ast::Type> returnType;
 | 
|---|
 | 573 | 
 | 
|---|
 | 574 |         /// Is the declaration in this scope or a parent scope?
 | 
|---|
 | 575 |         bool hasDecl( const std::string & decl ) const {
 | 
|---|
 | 576 |                 return decls.count( decl ) || (parent && parent->hasDecl( decl ));
 | 
|---|
 | 577 |         }
 | 
|---|
 | 578 | 
 | 
|---|
 | 579 |         /// Adds a declaration to this scope if it is new.
 | 
|---|
 | 580 |         void addDecl( const std::string & decl ) {
 | 
|---|
 | 581 |                 if ( !hasDecl( decl ) ) decls.insert( decl );
 | 
|---|
 | 582 |         }
 | 
|---|
 | 583 | 
 | 
|---|
 | 584 |         /// Adds a new expression to this scope.
 | 
|---|
 | 585 |         void addExpr( const std::string & expr ) {
 | 
|---|
 | 586 |                 if ( !expr.empty() ) exprs.emplace_back( expr );
 | 
|---|
 | 587 |         }
 | 
|---|
 | 588 | 
 | 
|---|
 | 589 |         /// Adds a new scope as a child scope.
 | 
|---|
 | 590 |         void addSub( ast::Pass<ProtoDump> && pass ) {
 | 
|---|
 | 591 |                 subs.emplace_back( std::move( pass.core ) );
 | 
|---|
 | 592 |         }
 | 
|---|
 | 593 | 
 | 
|---|
 | 594 |         /// Adds all named declaration in a list to the local scope.
 | 
|---|
 | 595 |         void addAll( const std::vector<ast::ptr<ast::DeclWithType>> & decls ) {
 | 
|---|
 | 596 |                 for ( auto decl : decls ) {
 | 
|---|
 | 597 |                         // Skip anonymous decls.
 | 
|---|
 | 598 |                         if ( decl->name.empty() ) continue;
 | 
|---|
 | 599 | 
 | 
|---|
 | 600 |                         if ( const auto & obj = decl.as<ast::ObjectDecl>() ) {
 | 
|---|
 | 601 |                                 previsit( obj );
 | 
|---|
 | 602 |                         }
 | 
|---|
 | 603 |                 }
 | 
|---|
 | 604 |         }
 | 
|---|
 | 605 | 
 | 
|---|
 | 606 | public:
 | 
|---|
 | 607 |         ProtoDump() :
 | 
|---|
 | 608 |                 parent( nullptr ), returnType( nullptr )
 | 
|---|
 | 609 |         {}
 | 
|---|
 | 610 | 
 | 
|---|
 | 611 |         ProtoDump( const ProtoDump * parent, const ast::Type * returnType ) :
 | 
|---|
 | 612 |                 closed( parent->closed ), parent( parent ), returnType( returnType )
 | 
|---|
 | 613 |         {}
 | 
|---|
 | 614 | 
 | 
|---|
 | 615 |         ProtoDump( const ProtoDump & other ) :
 | 
|---|
 | 616 |                 decls( other.decls ), exprs( other.exprs ), subs( other.subs ),
 | 
|---|
 | 617 |                 closed( other.closed ), parent( other.parent ),
 | 
|---|
 | 618 |                 returnType( other.returnType )
 | 
|---|
 | 619 |         {}
 | 
|---|
 | 620 | 
 | 
|---|
 | 621 |         ProtoDump( ProtoDump && ) = default;
 | 
|---|
 | 622 | 
 | 
|---|
 | 623 |         ProtoDump & operator=( const ProtoDump & ) = delete;
 | 
|---|
 | 624 |         ProtoDump & operator=( ProtoDump && ) = delete;
 | 
|---|
 | 625 | 
 | 
|---|
 | 626 |         void previsit( const ast::ObjectDecl * decl ) {
 | 
|---|
 | 627 |                 // Add variable as declaration.
 | 
|---|
 | 628 |                 addDecl( buildType( decl->name, decl->type, closed ) );
 | 
|---|
 | 629 | 
 | 
|---|
 | 630 |                 // Add initializer as expression if applicable.
 | 
|---|
 | 631 |                 if ( decl->init ) {
 | 
|---|
 | 632 |                         addExpr( buildInitializer( decl->name, decl->init, closed ) );
 | 
|---|
 | 633 |                 }
 | 
|---|
 | 634 |         }
 | 
|---|
 | 635 | 
 | 
|---|
 | 636 |         void previsit( const ast::FunctionDecl * decl ) {
 | 
|---|
 | 637 |                 visit_children = false;
 | 
|---|
 | 638 | 
 | 
|---|
 | 639 |                 // Skips declarations with ftype parameters.
 | 
|---|
 | 640 |                 for ( const auto & typeDecl : decl->type->forall ) {
 | 
|---|
 | 641 |                         if ( ast::TypeDecl::Ftype == typeDecl->kind ) {
 | 
|---|
 | 642 |                                 return;
 | 
|---|
 | 643 |                         }
 | 
|---|
 | 644 |                 }
 | 
|---|
 | 645 | 
 | 
|---|
 | 646 |                 // Add function as declaration.
 | 
|---|
 | 647 |                 // NOTE: I'm not sure why the assertions are only present on the
 | 
|---|
 | 648 |                 // declaration and not the function type. Is that an error?
 | 
|---|
 | 649 |                 ast::FunctionType * new_type = ast::shallowCopy( decl->type.get() );
 | 
|---|
 | 650 |                 for ( const ast::ptr<ast::DeclWithType> & assertion : decl->assertions ) {
 | 
|---|
 | 651 |                         new_type->assertions.push_back(
 | 
|---|
 | 652 |                                 new ast::VariableExpr( assertion->location , assertion )
 | 
|---|
 | 653 |                         );
 | 
|---|
 | 654 |                 }
 | 
|---|
 | 655 |                 addDecl( buildFunctionType( decl->name, new_type, closed ) );
 | 
|---|
 | 656 |                 delete new_type;
 | 
|---|
 | 657 | 
 | 
|---|
 | 658 |                 // Add information body if available.
 | 
|---|
 | 659 |                 if ( !decl->stmts ) return;
 | 
|---|
 | 660 |                 const std::vector<ast::ptr<ast::Type>> & returns =
 | 
|---|
 | 661 |                                 decl->type->returns;
 | 
|---|
 | 662 | 
 | 
|---|
 | 663 |                 // Add the return statement.
 | 
|---|
 | 664 |                 ast::ptr<ast::Type> retType = nullptr;
 | 
|---|
 | 665 |                 if ( 1 == returns.size() ) {
 | 
|---|
 | 666 |                         if ( !returns.front().as<ast::VoidType>() ) {
 | 
|---|
 | 667 |                                 retType = returns.front();
 | 
|---|
 | 668 |                         }
 | 
|---|
 | 669 |                 } else if ( 1 < returns.size() ) {
 | 
|---|
 | 670 |                         retType = new ast::TupleType( copy( returns ) );
 | 
|---|
 | 671 |                 }
 | 
|---|
 | 672 |                 ast::Pass<ProtoDump> body( this, retType.get() );
 | 
|---|
 | 673 | 
 | 
|---|
 | 674 |                 // Handle the forall clause (type parameters and assertions).
 | 
|---|
 | 675 |                 for ( const ast::ptr<ast::TypeDecl> & typeDecl : decl->type_params ) {
 | 
|---|
 | 676 |                         // Add set of "closed" types to body so that it can print them as NamedType.
 | 
|---|
 | 677 |                         body.core.closed.insert( typeDecl->name );
 | 
|---|
 | 678 | 
 | 
|---|
 | 679 |                         // Add assertions to local scope as declarations as well.
 | 
|---|
 | 680 |                         for ( const ast::DeclWithType * assertion : typeDecl->assertions ) {
 | 
|---|
 | 681 |                                 assertion->accept( body );
 | 
|---|
 | 682 |                         }
 | 
|---|
 | 683 |                 }
 | 
|---|
 | 684 | 
 | 
|---|
 | 685 |                 // NOTE: Related to the last NOTE; this is where the assertions are now.
 | 
|---|
 | 686 |                 for ( const ast::ptr<ast::DeclWithType> & assertion : decl->assertions ) {
 | 
|---|
 | 687 |                         assertion->accept( body );
 | 
|---|
 | 688 |                 }
 | 
|---|
 | 689 | 
 | 
|---|
 | 690 |                 // Add named parameters and returns to local scope.
 | 
|---|
 | 691 |                 body.core.addAll( decl->returns );
 | 
|---|
 | 692 |                 body.core.addAll( decl->params );
 | 
|---|
 | 693 | 
 | 
|---|
 | 694 |                 // Add contents of the function to a new scope.
 | 
|---|
 | 695 |                 decl->stmts->accept( body );
 | 
|---|
 | 696 | 
 | 
|---|
 | 697 |                 // Store sub-scope
 | 
|---|
 | 698 |                 addSub( std::move( body ) );
 | 
|---|
 | 699 |         }
 | 
|---|
 | 700 | 
 | 
|---|
 | 701 | private:
 | 
|---|
 | 702 |         void addAggregateFields( const ast::AggregateDecl * agg ) {
 | 
|---|
 | 703 |                 for ( const auto & member : agg->members ) {
 | 
|---|
 | 704 |                         if ( const ast::ObjectDecl * obj = member.as<ast::ObjectDecl>() ) {
 | 
|---|
 | 705 |                                 addDecl( buildAggregateDecl( obj->name, agg, obj->type, closed ) );
 | 
|---|
 | 706 |                         }
 | 
|---|
 | 707 |                 }
 | 
|---|
 | 708 |                 visit_children = false;
 | 
|---|
 | 709 |         }
 | 
|---|
 | 710 | 
 | 
|---|
 | 711 | public:
 | 
|---|
 | 712 | 
 | 
|---|
 | 713 |         void previsit( const ast::StructDecl * decl ) {
 | 
|---|
 | 714 |                 addAggregateFields( decl );
 | 
|---|
 | 715 |         }
 | 
|---|
 | 716 | 
 | 
|---|
 | 717 |         void previsit( const ast::UnionDecl * decl ) {
 | 
|---|
 | 718 |                 addAggregateFields( decl );
 | 
|---|
 | 719 |         }
 | 
|---|
 | 720 | 
 | 
|---|
 | 721 |         void previsit( const ast::EnumDecl * decl ) {
 | 
|---|
 | 722 |                 for ( const auto & member : decl->members ) {
 | 
|---|
 | 723 |                         if ( const auto * obj = member.as<ast::ObjectDecl>() ) {
 | 
|---|
 | 724 |                                 previsit( obj );
 | 
|---|
 | 725 |                         }
 | 
|---|
 | 726 |                 }
 | 
|---|
 | 727 | 
 | 
|---|
 | 728 |                 visit_children = false;
 | 
|---|
 | 729 |         }
 | 
|---|
 | 730 | 
 | 
|---|
 | 731 |         void previsit( const ast::ReturnStmt * stmt ) {
 | 
|---|
 | 732 |                 // Do nothing for void-returning functions or statements returning nothing.
 | 
|---|
 | 733 |                 if ( !returnType || !stmt->expr ) return;
 | 
|---|
 | 734 | 
 | 
|---|
 | 735 |                 // Otherwise constuct the return type from the expression.
 | 
|---|
 | 736 |                 addExpr( buildReturn( returnType.get(), stmt->expr, closed ) );
 | 
|---|
 | 737 |                 visit_children = false;
 | 
|---|
 | 738 |         }
 | 
|---|
 | 739 | 
 | 
|---|
 | 740 |         void previsit( const ast::AsmStmt * ) {
 | 
|---|
 | 741 |                 // Skip asm statements.
 | 
|---|
 | 742 |                 visit_children = false;
 | 
|---|
 | 743 |         }
 | 
|---|
 | 744 | 
 | 
|---|
 | 745 |         void previsit( const ast::Expr * expr ) {
 | 
|---|
 | 746 |                 addExpr( ast::Pass<ExprPrinter>::read( expr, closed ) );
 | 
|---|
 | 747 |                 visit_children = false;
 | 
|---|
 | 748 |         }
 | 
|---|
 | 749 | 
 | 
|---|
 | 750 | private:
 | 
|---|
 | 751 |         /// Print the pesudo-declarations not in any scope.
 | 
|---|
 | 752 |         void printGlobal( std::ostream & out ) const {
 | 
|---|
 | 753 |                 // &? Address of operator.
 | 
|---|
 | 754 |                 out << "#$ptr<T> $addr T" << std::endl;
 | 
|---|
 | 755 |                 const int intId = (int)ast::BasicType::SignedInt;
 | 
|---|
 | 756 |                 // ?&&? ?||? ?: Logical operators.
 | 
|---|
 | 757 |                 out << intId << " $and " << intId << ' ' << intId << std::endl;
 | 
|---|
 | 758 |                 out << intId << " $or " << intId << ' ' << intId << std::endl;
 | 
|---|
 | 759 |                 out << "T $if " << intId << " T T" << std::endl;
 | 
|---|
 | 760 |                 // ?,? Sequencing.
 | 
|---|
 | 761 |                 out << "T $seq X T" << std::endl;
 | 
|---|
 | 762 |         }
 | 
|---|
 | 763 | 
 | 
|---|
 | 764 |         /// Print everything in this scope and its child scopes.
 | 
|---|
 | 765 |         void printLocal( std::ostream & out, unsigned indent ) const {
 | 
|---|
 | 766 |                 const std::string tab( indent, '\t' );
 | 
|---|
 | 767 | 
 | 
|---|
 | 768 |                 // Print Declarations:
 | 
|---|
 | 769 |                 for ( const std::string & decl : decls ) {
 | 
|---|
 | 770 |                         out << tab << decl << std::endl;
 | 
|---|
 | 771 |                 }
 | 
|---|
 | 772 | 
 | 
|---|
 | 773 |                 // Print Divider:
 | 
|---|
 | 774 |                 out << '\n' << tab << "%%\n" << std::endl;
 | 
|---|
 | 775 | 
 | 
|---|
 | 776 |                 // Print Top-Level Expressions:
 | 
|---|
 | 777 |                 for ( const std::string & expr : exprs ) {
 | 
|---|
 | 778 |                         out << tab << expr << std::endl;
 | 
|---|
 | 779 |                 }
 | 
|---|
 | 780 | 
 | 
|---|
 | 781 |                 // Print Children Scopes:
 | 
|---|
 | 782 |                 ++indent;
 | 
|---|
 | 783 |                 for ( const ProtoDump & sub : subs ) {
 | 
|---|
 | 784 |                         out << tab << '{' << std::endl;
 | 
|---|
 | 785 |                         sub.printLocal( out, indent );
 | 
|---|
 | 786 |                         out << tab << '}' << std::endl;
 | 
|---|
 | 787 |                 }
 | 
|---|
 | 788 |         }
 | 
|---|
 | 789 | public:
 | 
|---|
 | 790 |         /// Start printing, the collected information.
 | 
|---|
 | 791 |         void print( std::ostream & out ) const {
 | 
|---|
 | 792 |                 printGlobal( out );
 | 
|---|
 | 793 |                 printLocal( out, 0 );
 | 
|---|
 | 794 |         }
 | 
|---|
 | 795 | };
 | 
|---|
 | 796 | 
 | 
|---|
 | 797 | } // namespace
 | 
|---|
 | 798 | 
 | 
|---|
 | 799 | void dumpAsResolverProto( ast::TranslationUnit & transUnit ) {
 | 
|---|
 | 800 |         ast::Pass<ProtoDump> dump;
 | 
|---|
 | 801 |         accept_all( transUnit, dump );
 | 
|---|
 | 802 |         dump.core.print( std::cout );
 | 
|---|
 | 803 | }
 | 
|---|
 | 804 | 
 | 
|---|
 | 805 | // Local Variables: //
 | 
|---|
 | 806 | // tab-width: 4 //
 | 
|---|
 | 807 | // mode: c++ //
 | 
|---|
 | 808 | // compile-command: "make install" //
 | 
|---|
 | 809 | // End: //
 | 
|---|