Guest User

Untitled

a guest
Feb 18th, 2013
1,412
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //========== Copyright © 2008, Valve Corporation, All rights reserved. ========
  2. //
  3. // Purpose: Script initially run after squirrel VM is initialized
  4. //
  5. //=============================================================================
  6.  
  7. //-----------------------------------------------------------------------------
  8. // General
  9. //-----------------------------------------------------------------------------
  10.  
  11. function printl( text )
  12. {
  13.     return print( text + "\n" );
  14. }
  15.  
  16. function Msg( text )
  17. {
  18.     return print( text );
  19. }
  20.  
  21. function Assert( b, msg = null )
  22. {
  23.     if ( b )
  24.         return;
  25.        
  26.     if ( msg != null )
  27.     {
  28.         throw "Assertion failed: " + msg;
  29.     }
  30.     else
  31.     {
  32.         throw "Assertion failed";
  33.     }
  34. }
  35.  
  36. //-----------------------------------------------------------------------------
  37. // Documentation table
  38. //-----------------------------------------------------------------------------
  39.  
  40. if ( developer() > 0 )
  41. {
  42.     Documentation <-
  43.     {
  44.         classes = {}
  45.         functions = {}
  46.         instances = {}
  47.     }
  48.  
  49.  
  50.     function RetrieveNativeSignature( nativeFunction )
  51.     {
  52.         if ( nativeFunction in NativeFunctionSignatures )
  53.         {
  54.             return NativeFunctionSignatures[nativeFunction]
  55.         }
  56.         return "<unnamed>"
  57.     }
  58.    
  59.     function RegisterFunctionDocumentation( func, name, signature, description )
  60.     {
  61.         if ( description.len() )
  62.         {
  63.             local b = ( description[0] == '#' );
  64.             if ( description[0] == '#' )
  65.             {
  66.                 local colon = description.find( ":" );
  67.                 if ( colon == null )
  68.                 {
  69.                     colon = description.len();
  70.                 }
  71.                 local alias = description.slice( 1, colon );
  72.                 description = description.slice( colon + 1 );
  73.                 name = alias;
  74.                 signature = "#";
  75.             }
  76.         }
  77.         Documentation.functions[name] <- [ signature, description ]
  78.     }
  79.  
  80.     function Document( symbolOrTable, itemIfSymbol = null, descriptionIfSymbol = null )
  81.     {
  82.         if ( typeof( symbolOrTable ) == "table" )
  83.         {
  84.             foreach( symbol, itemDescription in symbolOrTable )
  85.             {
  86.                 Assert( typeof(symbol) == "string" )
  87.                
  88.                 Document( symbol, itemDescription[0], itemDescription[1] );
  89.             }
  90.         }
  91.         else
  92.         {
  93.             printl( symbolOrTable + ":" + itemIfSymbol.tostring() + "/" + descriptionIfSymbol );
  94.         }
  95.     }
  96.    
  97.     function PrintHelp( string = "*", exact = false )
  98.     {
  99.         local matches = []
  100.        
  101.         if ( string == "*" || !exact )
  102.         {
  103.             foreach( name, documentation in Documentation.functions )
  104.             {
  105.                 if ( string != "*" && name.tolower().find( string.tolower() ) == null )
  106.                 {
  107.                     continue;
  108.                 }
  109.                
  110.                 matches.append( name );
  111.             }
  112.         }
  113.         else if ( exact )
  114.         {
  115.             if ( string in Documentation.functions )
  116.                 matches.append( string )
  117.         }
  118.        
  119.         if ( matches.len() == 0 )
  120.         {
  121.             printl( "Symbol " + string + " not found" );
  122.             return;
  123.         }
  124.        
  125.         matches.sort();
  126.        
  127.         foreach( name in matches )
  128.         {
  129.             local result = name;
  130.             local documentation = Documentation.functions[name];
  131.            
  132.             printl( "Function:    " + name );
  133.             local signature;
  134.             if ( documentation[0] != "#" )
  135.             {
  136.                 signature = documentation[0];
  137.             }
  138.             else
  139.             {
  140.                 signature = GetFunctionSignature( this[name], name );
  141.             }
  142.            
  143.             printl( "Signature:   " + signature );
  144.             if ( documentation[1].len() )
  145.                 printl( "Description: " + documentation[1] );
  146.             print( "\n" );
  147.         }
  148.     }
  149. }
  150. else
  151. {
  152.     function RetrieveNativeSignature( nativeFunction ) { return "<unnamed>"; }
  153.     function Document( symbolOrTable, itemIfSymbol = null, descriptionIfSymbol = null ) {}
  154.     function PrintHelp( string = "*", exact = false ) {}
  155. }
  156.  
  157. //-----------------------------------------------------------------------------
  158. // VSquirrel support functions
  159. //-----------------------------------------------------------------------------
  160.  
  161. function VSquirrel_OnCreateScope( name, outer )
  162. {
  163.     local result;
  164.     if ( !(name in outer) )
  165.     {
  166.         result = outer[name] <- { __vname=name, __vrefs = 1 };
  167.         delegate outer : result;
  168.     }
  169.     else
  170.     {
  171.         result = outer[name];
  172.         result.__vrefs += 1;
  173.     }
  174.     return result;
  175. }
  176.  
  177. function VSquirrel_OnReleaseScope( scope )
  178. {
  179.     scope.__vrefs -= 1;
  180.     if ( scope.__vrefs < 0 )
  181.     {
  182.         throw "Bad reference counting on scope " + scope.__vname;
  183.     }
  184.     else if ( scope.__vrefs == 0 )
  185.     {
  186.         delete scope.parent[scope.__vname];
  187.         scope.__vname = null;
  188.         delegate null : scope;
  189.     }
  190. }
  191.  
  192.  
  193. //-----------------------------------------------------------------------------
  194. //
  195. //-----------------------------------------------------------------------------
  196. class CCallChainer
  197. {
  198.     constructor( prefixString, scopeForThis = null )
  199.     {
  200.         prefix = prefixString;
  201.         if ( scopeForThis != null )
  202.             scope = scopeForThis;
  203.         else
  204.             scope = ::getroottable();
  205.         chains = {};
  206.        
  207.         // Expose a bound global function to dispatch to this object
  208.         scope[ "Dispatch" + prefixString ] <- Call.bindenv( this );
  209.     }
  210.    
  211.     function PostScriptExecute()
  212.     {
  213.         foreach( key, value in scope )
  214.         {
  215.             if ( typeof( value ) == "function" )
  216.             {
  217.                 if ( key.find( prefix ) == 0 )
  218.                 {
  219.                     key = key.slice( prefix.len() );
  220.                    
  221.                     if ( !(key in chains) )
  222.                     {
  223.                         //::print( "Creating new call chain " + key + "\n");
  224.                         chains[key] <- [];
  225.                     }
  226.                    
  227.                     local chain = chains[key];
  228.                    
  229.                     if ( !chain.len() || chain.top() != value )
  230.                     {
  231.                         chain.push( value );
  232.                         //::print( "Added " + value + " to call chain " + key + "\n" );
  233.                     }
  234.                 }
  235.             }
  236.         }
  237.     }
  238.    
  239.     function Call( event, ... )
  240.     {
  241.         if ( event in chains )
  242.         {
  243.             local chain = chains[event];
  244.             if ( chain.len() )
  245.             {
  246.                 local i;
  247.                 local args = [];
  248.                 if ( vargc > 0 )
  249.                 {
  250.                     args.push( scope );
  251.                     for ( i = 0; i < vargc; i++ )
  252.                     {
  253.                         args.push( vargv[i] );
  254.                     }
  255.                 }
  256.                 for ( i = chain.len() - 1; i >= 0; i -= 1 )
  257.                 {
  258.                     local func = chain[i];
  259.                     local result;
  260.                     if ( !args.len() )
  261.                     {
  262.                         result = func();
  263.                     }
  264.                     else
  265.                     {
  266.                         result = func.acall( args );
  267.                     }
  268.                     if ( result != null && !result )
  269.                         return false;
  270.                 }
  271.             }
  272.         }
  273.        
  274.         return true;
  275.     }
  276.    
  277.     scope = null;
  278.     prefix = null;
  279.     chains = null;
  280. };
  281.  
  282.  
  283. //-----------------------------------------------------------------------------
  284. //
  285. //-----------------------------------------------------------------------------
  286. class CSimpleCallChainer
  287. {
  288.     constructor( prefixString, scopeForThis = null, exactNameMatch = false )
  289.     {
  290.         prefix = prefixString;
  291.         if ( scopeForThis != null )
  292.             scope = scopeForThis;
  293.         else
  294.             scope = ::getroottable();
  295.         chain = [];
  296.        
  297.         // Expose a bound global function to dispatch to this object
  298.         scope[ "Dispatch" + prefixString ] <- Call.bindenv( this );
  299.        
  300.         exactMatch = exactNameMatch
  301.     }
  302.    
  303.     function PostScriptExecute()
  304.     {
  305.         foreach( key, value in scope )
  306.         {
  307.             if ( typeof( value ) == "function" )
  308.             {
  309.                 local foundMatch = false;
  310.                 if ( exactMatch )
  311.                 {
  312.                     foundMatch = ( prefix == key );
  313.                 }
  314.                 else
  315.                 {
  316.                     foundMatch = ( key.find( prefix ) == 0 )
  317.                 }
  318.                        
  319.                 if ( foundMatch )
  320.                 {
  321.                     if ( !exactMatch )
  322.                         key = key.slice( prefix.len() );
  323.                    
  324.                     if ( !(chain) )
  325.                     {
  326.                         //::print( "Creating new call simple chain\n");
  327.                         chain <- [];
  328.                     }
  329.                    
  330.                     if ( !chain.len() || chain != value )
  331.                     {
  332.                         chain.push( value );
  333.                         //::print( "Added " + value + " to call chain.\n" );
  334.                     }
  335.                 }
  336.             }
  337.         }
  338.     }
  339.    
  340.     function Call( ... )
  341.     {
  342.         if ( chain.len() )
  343.         {
  344.             local i;
  345.             local args = [];
  346.             if ( vargc > 0 )
  347.             {
  348.                 args.push( scope );
  349.                 for ( i = 0; i < vargc; i++ )
  350.                 {
  351.                     args.push( vargv[i] );
  352.                 }
  353.             }
  354.             for ( i = chain.len() - 1; i >= 0; i -= 1 )
  355.             {
  356.                 local func = chain[i];
  357.                 local result;
  358.                 if ( !args.len() )
  359.                 {
  360.                     result = func.pcall( scope );
  361.                 }
  362.                 else
  363.                 {
  364.                     result = func.pacall( scope, args );
  365.                 }
  366.                 if ( result != null && !result )
  367.                     return false;
  368.             }
  369.         }
  370.        
  371.         return true;
  372.     }
  373.    
  374.     exactMatch = false
  375.     scope = null;
  376.     prefix = null;
  377.     chain = null;
  378. };
  379.  
  380. //-----------------------------------------------------------------------------
  381. // Late binding: allows a table to refer to parts of itself, it's children,
  382. // it's owner, and then have the references fixed up after it's fully parsed
  383. //
  384. // Usage:
  385. //    lateBinder <- LateBinder();
  386. //    lateBinder.Begin( this );
  387. //    
  388. //    Test1 <-
  389. //    {  
  390. //     Foo=1
  391. //    }  
  392. //    
  393. //    Test2 <-
  394. //    {  
  395. //     FooFoo = "I'm foo foo"
  396. //     BarBar="@Test1.Foo"
  397. //     SubTable = { boo=[bah, "@Test2.FooFoo", "@Test1.Foo"], booboo2={one=bah, two="@Test2.FooFoo", three="@Test1.Foo"} }
  398. //     booboo=[bah, "@Test2.FooFoo", "@Test1.Foo"]
  399. //     booboo2={one=bah, two="@Test2.FooFoo", three="@Test1.Foo"}
  400. //     bah=wha
  401. //    }  
  402. //    
  403. //    lateBinder.End();
  404. //    delete lateBinder;
  405. //
  406. // When End() is called, all of the unresolved symbols in the tables and arrays will be resolved,
  407. // any left unresolved will become a string prepended with '~', which later code can deal with
  408. //-----------------------------------------------------------------------------
  409.  
  410. class LateBinder
  411. {
  412.     // public:
  413.     function Begin( target, log = false )
  414.     {
  415.         m_log = log;
  416.        
  417.         HookRootMetamethod( "_get", function( key ) { return "^" + key; } );
  418.         HookRootMetamethod( "_newslot", function( key, value ) { if ( typeof value == "table" ) { m_fixupSet.push( [ key, value ] ); this.rawset( key, value ); };  }.bindenv(this) );
  419.         m_targetTable = target;
  420.        
  421.         Log( "Begin late bind on table " + m_targetTable );
  422.     }
  423.    
  424.     function End()
  425.     {
  426.         UnhookRootMetamethod( "_get" );
  427.         UnhookRootMetamethod( "_newslot" );
  428.  
  429.         Log( "End late bind on table " + m_targetTable );
  430.        
  431.         foreach( subTablePair in m_fixupSet )
  432.         {
  433.             EstablishDelegation( m_targetTable, subTablePair[1] );
  434.         }
  435.  
  436.         Log( "Begin resolution... " )
  437.         m_logIndent++;
  438.        
  439.         local found = true;
  440.        
  441.         while ( found )
  442.         {
  443.             foreach( subTablePair in m_fixupSet )
  444.             {
  445.                 Log( subTablePair[0] + " = " );
  446.                 Log( "{" );
  447.                 if ( !Resolve( subTablePair[1], subTablePair[1], false ) )
  448.                 {
  449.                     found = false;
  450.                 }
  451.                 Log( "}" );
  452.             }
  453.         }
  454.            
  455.         m_logIndent--;
  456.        
  457.         foreach( subTablePair in m_fixupSet )
  458.         {
  459.             RemoveDelegation( subTablePair[1] );
  460.         }
  461.        
  462.         Log( "...end resolution" );
  463.     }
  464.        
  465.     // private:
  466.     function HookRootMetamethod( name, value )
  467.     {
  468.         local saved = null;
  469.         local roottable = getroottable();
  470.         if ( name in roottable )
  471.         {
  472.             saved = roottable[name];
  473.         }
  474.         roottable[name] <- value;
  475.         roottable["__saved" + name] <- saved;
  476.     }
  477.  
  478.     function UnhookRootMetamethod( name )
  479.     {
  480.         local saveSlot = "__saved" + name;
  481.         local roottable = getroottable();
  482.         local saved = roottable[saveSlot];
  483.         if ( saved != null )
  484.         {
  485.             roottable[name] = saved;
  486.         }
  487.         else
  488.         {
  489.             delete roottable[name];
  490.         }
  491.         delete roottable[saveSlot];
  492.     }
  493.  
  494.     function EstablishDelegation( parentTable, childTable )
  495.     {
  496.         delegate parentTable : childTable;
  497.        
  498.         foreach( key, value in childTable )
  499.         {
  500.             local type = typeof value;
  501.             if ( type == "table" )
  502.             {
  503.                 EstablishDelegation( childTable, value );
  504.             }
  505.         }
  506.     }
  507.    
  508.     function RemoveDelegation( childTable )
  509.     {
  510.         delegate null : childTable;
  511.        
  512.         foreach( key, value in childTable )
  513.         {
  514.             local type = typeof value;
  515.             if ( type == "table" )
  516.             {
  517.                 RemoveDelegation( value );
  518.             }
  519.         }
  520.     }
  521.  
  522.     function Resolve( lookupTable, subTableOrArray, throwException = false )
  523.     {
  524.         m_logIndent++;
  525.         local found = false;
  526.    
  527.         foreach( key, value in subTableOrArray )
  528.         {
  529.             local type = typeof value;
  530.             if ( type == "string" )
  531.             {
  532.                 if ( value.len() )
  533.                 {
  534.                     local unresolvedId = null;
  535.                     local controlChar = value[0]
  536.                     if ( controlChar == '^' )
  537.                     {
  538.                         found = true;
  539.                         value = value.slice( 1 );
  540.                         if ( value in lookupTable )
  541.                         {
  542.                             subTableOrArray[key] = lookupTable[value];
  543.                             Log( key + " = " + lookupTable[value] + " <-- " + value );
  544.                         }
  545.                         else
  546.                         {
  547.                             subTableOrArray[key] = "~" + value;
  548.                             unresolvedId = value;
  549.                             Log( key + " = \"" + "~" + value + "\" (unresolved)" );
  550.                         }
  551.                     }
  552.                     else if ( controlChar == '@' )
  553.                     {
  554.                         found = true;
  555.                         local identifiers = [];
  556.                         local iLast = 1;
  557.                         local iNext;
  558.                         while ( ( iNext = value.find( ".", iLast ) ) != null )
  559.                         {
  560.                             identifiers.push( value.slice( iLast, iNext ) );
  561.                             iLast = iNext + 1;
  562.                         }
  563.                         identifiers.push( value.slice( iLast ) );
  564.                        
  565.                         local depthSuccess = 0;
  566.                         local result = lookupTable;
  567.                         foreach( identifier in identifiers )
  568.                         {
  569.                             if ( identifier in result )
  570.                             {
  571.                                 depthSuccess++;
  572.                                 result = result[identifier];
  573.                             }
  574.                             else
  575.                             {
  576.                                 break;
  577.                             }
  578.                         }
  579.                         if ( depthSuccess == identifiers.len() )
  580.                         {
  581.                             subTableOrArray[key] = result;
  582.                             Log( key + " = " + result + " <-- " + value );
  583.                         }
  584.                         else
  585.                         {
  586.                             subTableOrArray[key] = "~" + value.slice( 1 );
  587.                             unresolvedId = value;
  588.                             Log( key + " = \"" + "~" + value + "\" (unresolved)" );
  589.                         }
  590.                     }
  591.                    
  592.                     if ( unresolvedId != null )
  593.                     {
  594.                         if ( throwException )
  595.                         {
  596.                             local exception = "Unresolved symbol: " + bind + " in ";
  597.                             foreach ( entry in m_bindNamesStack )
  598.                             {
  599.                                 exception += entry;
  600.                                 exception += "."
  601.                             }
  602.                             exception += unresolvedId;
  603.                            
  604.                             throw exception;
  605.                         }
  606.                     }
  607.                 }
  608.             }
  609.         }
  610.  
  611.         foreach( key, value in subTableOrArray )
  612.         {
  613.             local type = typeof value;
  614.             local isTable = ( type == "table" );
  615.             local isArray = ( type == "array" )
  616.             if ( isTable || isArray )
  617.             {
  618.                 Log( key + " =" );
  619.                 Log( isTable ? "{" : "[" );
  620.                
  621.                 m_bindNamesStack.push( key );
  622.                 if ( Resolve( ( isTable ) ? value : lookupTable, value, throwException ) )
  623.                 {
  624.                     found = true;
  625.                 }
  626.                 m_bindNamesStack.pop();
  627.                
  628.                 Log( isTable ? "}" : "]" );
  629.             }
  630.         }
  631.         m_logIndent--;
  632.         return found;
  633.     }
  634.    
  635.     function Log( string )
  636.     {
  637.         if ( m_log )
  638.         {
  639.             for ( local i = 0; i < m_logIndent; i++ )
  640.             {
  641.                 print( "  " );
  642.             }
  643.            
  644.             printl( string );
  645.         }
  646.     }
  647.  
  648.     m_targetTable = null;
  649.     m_fixupSet = [];
  650.     m_bindNamesStack = [];
  651.     m_log = false;
  652.     m_logIndent = 0;
  653. }
RAW Paste Data