yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
eaa8dcfcc
master
1#include "node.h" 2 3#include "core/slang-string-escape-util.h" 4#include "core/slang-string-util.h" 5#include "file-util.h" 6 7namespace CppParse 8{ 9 10// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Node Impl 11// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 12 13SLANG_FORCE_INLINE static void _indent (Index indentCount ,StringBuilder & out ) 14{ 15FileUtil ::indent (indentCount ,out ); 16} 17 18void Node ::dumpMarkup (int indentCount ,StringBuilder & out ) 19{ 20if (m_markup .getLength () <=0 ) 21 { 22return ; 23 } 24 25List < UnownedStringSlice > lines ; 26StringUtil ::calcLines (m_markup .getUnownedSlice (),lines ); 27 28// Remove empty lines from the end 29while (lines .getCount ()) 30 { 31auto lastLine = lines .getLast (); 32if (lastLine .trim ().getLength ()== 0 ) 33 { 34lines .removeLast (); 35continue ; 36 } 37break ; 38 } 39 40if (lines .getCount ()== 0 ) 41 { 42return ; 43 } 44 45for (auto line :lines ) 46 { 47_indent (indentCount ,out ); 48out <<"// " <<line <<"\n" ; 49 } 50} 51 52ScopeNode * Node ::getRootScope () 53{ 54if (m_parentScope ) 55 { 56ScopeNode * scope = m_parentScope ; 57while (scope -> m_parentScope ) 58 { 59scope = scope -> m_parentScope ; 60 } 61return scope ; 62 } 63else 64 { 65return as < ScopeNode > (this ); 66 } 67} 68 69void Node ::calcScopeDepthFirst (List < Node *>& outNodes ) 70{ 71outNodes .add (this ); 72} 73 74void Node ::calcAbsoluteName (StringBuilder & outName )const 75{ 76List < Node *> path ; 77calcScopePath (const_cast < Node *> (this ),path ); 78 79// 1 so we skip the global scope 80for (Index i = 1 ;i < path .getCount ();++ i ) 81 { 82Node * node = path [i ]; 83 84if (i > 1 ) 85 { 86outName <<"::" ; 87 } 88 89if (node -> m_kind == Kind ::AnonymousNamespace ) 90 { 91outName <<"{Anonymous}" ; 92 } 93else 94 { 95outName <<node -> m_name .getContent (); 96 } 97 } 98} 99 100/* static */ void Node ::calcScopePath (Node * node ,List < Node *>& outPath ) 101{ 102outPath .clear (); 103 104while (node ) 105 { 106outPath .add (node ); 107node = node -> m_parentScope ; 108 } 109 110// reverse the order, so we go from root to the node 111outPath .reverse (); 112} 113 114/* static */ void Node ::filterImpl (Filter inFilter ,List < Node *>& ioNodes ) 115{ 116// Filter out all the unreflected nodes 117Index count = ioNodes .getCount (); 118for (Index j = 0 ;j < count ;) 119 { 120Node * node = ioNodes [j ]; 121 122if (!inFilter (node )) 123 { 124ioNodes .removeAt (j ); 125count -- ; 126 } 127else 128 { 129j ++ ; 130 } 131 } 132} 133 134/* static */ Node * Node ::lookupNameInScope (ScopeNode * scope ,const UnownedStringSlice & name ) 135{ 136// TODO(JS): Doesn't handle 'using namespace'. 137 138// Must be unqualified name 139SLANG_ASSERT (name .indexOf (UnownedStringSlice ::fromLiteral ("::" ))< 0 ); 140 141Node * childNode = scope -> findChild (name ); 142if (childNode ) 143 { 144return childNode ; 145 } 146 147// If we have an anonymous namespace in this scope, try looking up in there.. 148if (scope -> m_anonymousNamespace ) 149 { 150Node * childNode = scope -> m_anonymousNamespace -> findChild (name ); 151if (childNode ) 152 { 153return childNode ; 154 } 155 } 156 157// I could have an enum (that's not an enum class) 158for (Node * node :scope -> m_children ) 159 { 160EnumNode * enumNode = as < EnumNode > (node ); 161if (enumNode && enumNode -> m_kind == Node ::Kind ::Enum ) 162 { 163Node ** nodePtr = enumNode -> m_childMap .tryGetValue (name ); 164if (nodePtr ) 165 { 166return * nodePtr ; 167 } 168 } 169 } 170 171return nullptr ; 172} 173 174/* static */ Node * Node ::lookupFromScope ( 175ScopeNode * scope , 176const UnownedStringSlice * parts , 177Index partsCount ) 178{ 179SLANG_ASSERT (partsCount > 0 ); 180if (partsCount == 1 ) 181 { 182return lookupNameInScope (scope ,parts [0 ]); 183 } 184 185for (Index i = 0 ;i < partsCount ;++ i ) 186 { 187const UnownedStringSlice & part = parts [i ]; 188 189Node * node = lookupNameInScope (scope ,part ); 190if (node == nullptr ) 191 { 192return node ; 193 } 194// If at end, then we are done 195if (i == partsCount - 1 ) 196 { 197return node ; 198 } 199 200// If there are more elements, then node must be some kind of scope, 201// if we are going to find it 202scope = as < ScopeNode > (node ); 203if (scope == nullptr ) 204 { 205break ; 206 } 207 } 208 209return nullptr ; 210} 211 212/* static */ void Node ::splitPath ( 213const UnownedStringSlice & inPath , 214List < UnownedStringSlice >& outParts ) 215{ 216if (inPath .indexOf (UnownedStringSlice ::fromLiteral ("::" )) >=0 ) 217 { 218StringUtil ::split (inPath ,UnownedStringSlice ::fromLiteral ("::" ),outParts ); 219// Remove any whitespace 220for (auto & part :outParts ) 221 { 222part = part .trim (); 223 } 224 } 225else 226 { 227outParts .clear (); 228outParts .add (inPath .trim ()); 229 } 230} 231 232/* static */ Node * Node ::lookupFromScope (ScopeNode * scope ,const UnownedStringSlice & inPath ) 233{ 234if (inPath .indexOf (UnownedStringSlice ::fromLiteral ("::" )) >=0 ) 235 { 236List < UnownedStringSlice > parts ; 237splitPath (inPath ,parts ); 238 239return lookupFromScope (scope ,parts .getBuffer (),parts .getCount ()); 240 } 241else 242 { 243return lookupNameInScope (scope ,inPath ); 244 } 245} 246 247/* static */ Node * Node ::lookup (ScopeNode * scope ,const UnownedStringSlice & inPath ) 248{ 249if (inPath .indexOf (UnownedStringSlice ::fromLiteral ("::" )) >=0 ) 250 { 251List < UnownedStringSlice > parts ; 252splitPath (inPath ,parts ); 253 254if (parts [0 ].getLength ()== 0 ) 255 { 256// It's a lookup from global scope 257ScopeNode * rootScope = scope -> getRootScope (); 258return lookupFromScope (rootScope ,parts .getBuffer ()+ 1 ,parts .getCount ()+ 1 ); 259 } 260 261// Okay lets try a lookup from each scope up to the global scope 262while (scope ) 263 { 264Node * node = lookupFromScope (scope ,parts .getBuffer (),parts .getCount ()); 265if (node ) 266 { 267return node ; 268 } 269 270scope = scope -> m_parentScope ; 271 } 272 } 273else 274 { 275while (scope ) 276 { 277// Lookup in this scope 278Node * node = lookupNameInScope (scope ,inPath ); 279if (node ) 280 { 281return node ; 282 } 283 284// Try parent scope 285scope = scope -> m_parentScope ; 286 } 287 } 288 289return nullptr ; 290} 291 292// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ScopeNode !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 293 294ScopeNode * ScopeNode ::getAnonymousNamespace () 295{ 296if (!m_anonymousNamespace ) 297 { 298m_anonymousNamespace = new ScopeNode (Kind ::AnonymousNamespace ); 299m_anonymousNamespace -> m_parentScope = this ; 300m_children .add (m_anonymousNamespace ); 301 } 302 303return m_anonymousNamespace ; 304} 305 306void ScopeNode ::addChildIgnoringName (Node * child ) 307{ 308SLANG_ASSERT (child -> m_parentScope == nullptr ); 309// Can't add anonymous namespace this way - should be added via getAnonymousNamespace 310SLANG_ASSERT (child -> m_kind != Kind ::AnonymousNamespace ); 311 312child -> m_parentScope = this ; 313m_children .add (child ); 314} 315 316void ScopeNode ::addChild (Node * child ) 317{ 318addChildIgnoringName (child ); 319 320if (child -> m_name .hasContent ()) 321 { 322m_childMap .add (child -> m_name .getContent (),child ); 323 } 324} 325 326Node * ScopeNode ::findChild (const UnownedStringSlice & name )const 327{ 328Node * const * nodePtr = m_childMap .tryGetValue (name ); 329if (nodePtr ) 330 { 331return * nodePtr ; 332 } 333return nullptr ; 334} 335 336void ScopeNode ::calcScopeDepthFirst (List < Node *>& outNodes ) 337{ 338outNodes .add (this ); 339for (Node * child :m_children ) 340 { 341child -> calcScopeDepthFirst (outNodes ); 342 } 343} 344 345void ScopeNode ::dump (int indentCount ,StringBuilder & out ) 346{ 347dumpMarkup (indentCount ,out ); 348 349_indent (indentCount ,out ); 350 351switch (m_kind ) 352 { 353case Kind ::AnonymousNamespace : 354 { 355out <<"namespace {\n" ; 356 } 357case Kind ::Namespace : 358 { 359if (m_name .hasContent ()) 360 { 361out <<"namespace " <<m_name .getContent () <<" {\n" ; 362 } 363else 364 { 365out <<"{\n" ; 366 } 367break ; 368 } 369 } 370 371for (Node * child :m_children ) 372 { 373child -> dump (indentCount + 1 ,out ); 374 } 375 376_indent (indentCount ,out ); 377out <<"}\n" ; 378} 379 380/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EnumCaseNode !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 381 382/* Returns true if needs space between the tokens. 383It determines this based on the locs, and if they contain something between them. 384*/ 385static bool _needsSpace (const Token & prevTok ,const Token & tok ) 386{ 387auto prevLoc = prevTok .getLoc (); 388auto loc = tok .getLoc (); 389 390auto prevContent = prevTok .getContent (); 391 392if (prevLoc + prevContent .getLength ()== loc ) 393 { 394return false; 395 } 396 397return true; 398} 399 400 401static void _dumpTokens (const Token * toks ,Index count ,StringBuilder & out ) 402{ 403if (count > 0 ) 404 { 405out <<toks [0 ].getContent (); 406 407for (Index i = 1 ;i < count ;++ i ) 408 { 409const auto & prevToken = toks [i - 1 ]; 410const auto & token = toks [i ]; 411 412if (_needsSpace (prevToken ,token )) 413 { 414out <<" " ; 415 } 416 417out <<token .getContent (); 418 } 419 } 420} 421 422static void _dumpTokens (const List < Token >& toks ,StringBuilder & out ) 423{ 424_dumpTokens (toks .getBuffer (),toks .getCount (),out ); 425} 426 427 428void EnumCaseNode ::dump (int indent ,StringBuilder & out ) 429{ 430if (isReflected ()) 431 { 432dumpMarkup (indent ,out ); 433 434_indent (indent ,out ); 435out <<m_name .getContent (); 436 437if (m_valueTokens .getCount ()) 438 { 439out <<" = " ; 440_dumpTokens (m_valueTokens ,out ); 441 } 442 443out <<",\n" ; 444 } 445} 446 447/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EnumNode !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 448 449void TypeDefNode ::dump (int indent ,StringBuilder & out ) 450{ 451if (isReflected ()) 452 { 453dumpMarkup (indent ,out ); 454 455_indent (indent ,out ); 456 457out <<"typedef " ; 458_dumpTokens (m_targetTypeTokens ,out ); 459out <<" " <<m_name .getContent () <<";\n" ; 460 } 461} 462 463/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EnumNode !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 464 465void EnumNode ::dump (int indent ,StringBuilder & out ) 466{ 467if (!isReflected ()) 468 { 469return ; 470 } 471 472dumpMarkup (indent ,out ); 473 474_indent (indent ,out ); 475 476out <<"enum " ; 477 478if (m_kind == Kind ::EnumClass ) 479 { 480out <<"class " ; 481 } 482 483if (m_name .type != TokenType ::Invalid ) 484 { 485out <<m_name .getContent (); 486 } 487 488if (m_backingTokens .getCount ()> 0 ) 489 { 490out <<" : " ; 491_dumpTokens (m_backingTokens ,out ); 492 } 493 494out <<"\n" ; 495_indent (indent ,out ); 496out <<"{\n" ; 497 498for (Node * child :m_children ) 499 { 500child -> dump (indent + 1 ,out ); 501 } 502 503_indent (indent ,out ); 504out <<"}\n" ; 505} 506 507/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! CallableNode !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 508 509void CallableNode ::dump (int indent ,StringBuilder & out ) 510{ 511if (!isReflected ()) 512 { 513return ; 514 } 515 516dumpMarkup (indent ,out ); 517 518_indent (indent ,out ); 519 520if (m_isStatic ) 521 { 522out <<"static " ; 523 } 524if (m_isVirtual ) 525 { 526out <<"virtual " ; 527 } 528 529out <<m_returnType <<" " ; 530out <<m_name .getContent () <<"(" ; 531 532const Index count = m_params .getCount (); 533for (Index i = 0 ;i < count ;++ i ) 534 { 535if (i > 0 ) 536 { 537out <<", " ; 538 } 539 540const auto & param = m_params [i ]; 541out <<param .m_type ; 542if (param .m_name .type == TokenType ::Identifier ) 543 { 544out <<" " <<param .m_name .getContent (); 545 } 546 } 547 548out <<")" ; 549 550if (m_isPure ) 551 { 552out <<" = 0" ; 553 } 554 555out <<"\n" ; 556} 557 558/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FieldNode !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 559 560void FieldNode ::dump (int indent ,StringBuilder & out ) 561{ 562if (!isReflected ()) 563 { 564return ; 565 } 566 567dumpMarkup (indent ,out ); 568 569_indent (indent ,out ); 570 571if (m_isStatic ) 572 { 573out <<"static " ; 574 } 575 576out <<m_fieldType <<" " <<m_name .getContent () <<"\n" ; 577} 578 579/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ClassLikeNode !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 580 581/// Add a node that is derived from this 582void ClassLikeNode ::addDerived (ClassLikeNode * derived ) 583{ 584SLANG_ASSERT (derived -> m_superNode == nullptr ); 585derived -> m_superNode = this ; 586m_derivedTypes .add (derived ); 587} 588 589void ClassLikeNode ::calcDerivedDepthFirst (List < ClassLikeNode *>& outNodes ) 590{ 591outNodes .add (this ); 592for (ClassLikeNode * derivedType :m_derivedTypes ) 593 { 594derivedType -> calcDerivedDepthFirst (outNodes ); 595 } 596} 597 598void ClassLikeNode ::dumpDerived (int indentCount ,StringBuilder & out ) 599{ 600if (isClassLike ()&& isReflected ()&& m_name .hasContent ()) 601 { 602_indent (indentCount ,out ); 603out <<m_name .getContent () <<"\n" ; 604 } 605 606for (ClassLikeNode * derivedType :m_derivedTypes ) 607 { 608derivedType -> dumpDerived (indentCount + 1 ,out ); 609 } 610} 611 612Index ClassLikeNode ::calcDerivedDepth ()const 613{ 614const ClassLikeNode * node = this ; 615Index count = 0 ; 616 617while (node ) 618 { 619count ++ ; 620node = node -> m_superNode ; 621 } 622 623return count ; 624} 625 626ClassLikeNode * ClassLikeNode ::findLastDerived () 627{ 628for (Index i = m_derivedTypes .getCount ()- 1 ;i >=0 ;-- i ) 629 { 630ClassLikeNode * derivedType = m_derivedTypes [i ]; 631ClassLikeNode * found = derivedType -> findLastDerived (); 632if (found ) 633 { 634return found ; 635 } 636 } 637return this ; 638} 639 640bool ClassLikeNode ::hasReflectedDerivedType ()const 641{ 642for (ClassLikeNode * type :m_derivedTypes ) 643 { 644if (type -> isReflected ()) 645 { 646return true; 647 } 648 } 649return false; 650} 651 652void ClassLikeNode ::getReflectedDerivedTypes (List < ClassLikeNode *>& out )const 653{ 654out .clear (); 655for (ClassLikeNode * type :m_derivedTypes ) 656 { 657if (type -> isReflected ()) 658 { 659out .add (type ); 660 } 661 } 662} 663 664void ClassLikeNode ::dump (int indentCount ,StringBuilder & out ) 665{ 666dumpMarkup (indentCount ,out ); 667 668_indent (indentCount ,out ); 669 670const char * typeName = (m_kind == Kind ::StructType ) ?"struct" :"class" ; 671 672out <<typeName <<" " ; 673 674if (!isReflected ()) 675 { 676out <<" (" ; 677 } 678out <<m_name .getContent (); 679if (!isReflected ()) 680 { 681out <<") " ; 682 } 683 684if (m_super .hasContent ()) 685 { 686out <<" : " <<m_super .getContent (); 687 } 688 689out <<" {\n" ; 690 691for (Node * child :m_children ) 692 { 693child -> dump (indentCount + 1 ,out ); 694 } 695 696_indent (indentCount ,out ); 697out <<"}\n" ; 698} 699 700}// namespace CppParse