Пример #1
0
 /// <summary>
 /// Unpacks the specified LValue, if it's an LValue. Otherwise the value is returned again.
 /// </summary>
 public static object Deref( State state, object value )
 {
     if( value is LValue )
     return ((LValue)value).read( state );
     else
     return value;
 }
Пример #2
0
        /// <summary>
        /// Works like throwException(), except we search for the right try clause.
        /// </summary>
        public static void ThrowException( State state, object thrown )
        {
            Step tryStep = state.findAction( step => IsTryMarker( step ) );
            if( tryStep == null )
            {
            // Make sure we have a CoralException.
            if( !(thrown is CoralException) )
                thrown = new CoralException( thrown );

            CoralException cex = (CoralException)thrown;
            if( cex.trace == null )
                cex.setStackTrace( state );

            // Unwind everything else off the stack. There is an implicit "except" at the top anyway.
            state.clearActions();

            // Push on a thrower. We do this in a separate step so that the same try/catch can deal
            // with it at the Runner level.
            state.pushAction( new Step( null, a => { throw new UnhandledException( (CoralException)thrown ); }, "re-thrower" ) );
            return;
            }

            AstTry node = (AstTry)tryStep.node;
            node.throwException( state, thrown );
        }
Пример #3
0
 /// <summary>
 /// Unpacks the LValue from the result stack, if it's an LValue. Otherwise the value is returned again.
 /// </summary>
 public static object Deref( State state )
 {
     object value = state.popResult();
     if( value is LValue )
     return ((LValue)value).read( state );
     else
     return value;
 }
Пример #4
0
        /// <summary>
        /// Handles various method calls on string objects.
        /// </summary>
        public static FValue Method( State state, string str, string name )
        {
            if( name == "length" )
            {
            return new FValue( (st2, args) =>
                {
                    st2.pushResult( str.Length );
                }
            );
            }
            else if( name == "format" )
            {
            return new FValue( (st2, args) =>
                {
                    string result = str.FormatI( args );
                    st2.pushResult( result );
                }
            );
            }
            else if( name == "split" )
            {
            return new FValue( (st2, args) =>
                {
                    // We should have 1 or 2 args.
                    if( args.Length < 1 )
                        throw CoralException.GetArg( "Not enough args to string.split" );

                    // Convert the split-by array if necessary.
                    string[] splitBy;
                    if( args[0] is string )
                        splitBy = new string[] { Util.CoerceString( args[0] ) };
                    else
                        splitBy = Util.CoerceStringArray( args[0] );

                    if( args.Length == 1 )
                        st2.pushResult( Util.CoerceStringListObject( str.Split( splitBy, StringSplitOptions.None ) ) );
                    else
                        st2.pushResult( Util.CoerceStringListObject( str.Split( splitBy, Util.CoerceNumber( args[1] ), StringSplitOptions.None ) ) );
                }
            );
            }
            else if( name == "replace" )
            {
            return new FValue( (st2, args) =>
                {
                    if( args.Length != 2 )
                        throw CoralException.GetArg( "Must pass replace() two args" );

                    string from = Util.CoerceString( args[0] );
                    string to = Util.CoerceString( args[1] );

                    st2.pushResult( str.Replace( from, to ) );
                }
            );
            }
            else
            throw CoralException.GetArg( "String object has no method '{0}'".FormatI( name ) );
        }
Пример #5
0
        /// <summary>
        /// Queues a Coral function to run asynchronously.
        /// </summary>
        public static void CallFunction( State state, string name, object[] args, StackTrace.StackFrame frame )
        {
            // Convert the arguments.
            AstNode[] wrapped = WrapArgs( args );

            // Construct a synthetic AstIdentifier for the name.
            AstIdentifier id = new AstIdentifier( name );

            // Construct a synthetic AstCall.
            AstCall call = new AstCall( id, wrapped, frame );

            call.run( state );
        }
Пример #6
0
 public override void run( State state )
 {
     // We execute by executing the "lhs" and "rhs" code, then using the lhs's
     // LValue callbacks to set the value.
     state.pushAction(
     new Step( this, s =>
     {
         LValue lv = (LValue)s.popResult();
         object rv = LValue.Deref( s );
         lv.write( s, rv );
     } )
     );
     this.lhs.run( state );
     this.rhs.run( state );
 }
Пример #7
0
 public override void run( State state )
 {
     // We execute here by simply "running" each of the steps and letting them
     // push onto the stack. There is no branching possible, and these calls will
     // be shallow / non-blocking, so there's no need to do anything tricky or conditional.
     //
     // One point of interest is that we push a "clear results" step after each statement
     // just to verify that nothing was left on the results stack (this happens and is okay).
     foreach( AstNode c in ((IEnumerable<AstNode>)_children).Reverse() )
     {
     // Clear the result stack after each statement.
     state.pushAction( new Step( this, st2 => st2.clearResults(), "[Clear Results]" ) );
     c.run( state );
     };
 }
Пример #8
0
        string dumpScope( State s )
        {
            string rv = "";
            string[] names = s.scope.getNames();
            foreach( string n in names )
            {
            // Don't include things from the const values.
            if( s.constScope.has( n ) )
                continue;

            object val = s.scope.get( n );
            rv += "{0} = {1}\r\n".FormatI( n, dumpObject( val ) );
            }

            return rv;
        }
Пример #9
0
        public Player( int id )
        {
            _id = id;

            // Default to acting as the player.
            _coralState = new Coral.State();
            Coral.Runner r = new Coral.Runner( _coralState );
            r.pushSecurityContext( new SecurityContext( "base", _id ) );

            // If we're anon, make a mob for it.
            if( id == Mob.Anon.id )
            {
            _anonWorld = new AnonWorld();
            _anonMob = new AnonMob( _anonWorld, this );
            _anonWorld.anonMob = _anonMob;
            }
        }
Пример #10
0
        public override void run( State state )
        {
            // We execute by getting the indexer value and the source, looking the
            // value in question up, and then pushing the result on the result stack.
            state.pushAction( new Step( this, st =>
            {
            object source = LValue.Deref( st );
            object index = LValue.Deref( st );

            if( source is Dictionary<object,object> )
            {
                var sourcedict = (Dictionary<object,object>)source;
                if( sourcedict.ContainsKey( index ) )
                    st.pushResult( sourcedict[index] );
                else
                    st.pushResult( null );
            }
            else if( source is List<object> && index is int )
            {
                var sourcelist = (List<object>)source;
                int indexint = (int)index;
                if( indexint < sourcelist.Count )
                    st.pushResult( sourcelist[indexint] );
                else
                    st.pushResult( null );
            }
            else if( source is string && index is int )
            {
                st.pushResult( StringObject.ArrayAccess( (string)source, (int)index ) );
            }
            else if( source is MetalObject && ((MetalObject)source).indexLookup != null )
            {
                ((MetalObject)source).indexLookup( st, index );
            }
            else
            {
                // Whatever is left never has a value.
                st.pushResult( null );
            }
            } ) );
            this.source.run( state );
            this.index.run( state );
        }
Пример #11
0
        public override void run( State state )
        {
            // We execute here by searching up the stack for the previous function call
            // scope marker, and unwinding past that, then pushing on our return value.
            state.pushAction( new Step( this, st =>
            {
            st.pushAction( new Step( this, st2 =>
            {
                // Make sure we don't leak LValues.
                st2.pushResult( LValue.Deref( st2 ) );

                // And do the stack unwind.
                st2.unwindActions( step => AstCall.IsScopeMarker( step ) );
            }, "return: stack unwinder" ) );

            if( this.value != null )
                this.value.run( st );
            else
                st.pushResult( null );
            } ) );
        }
Пример #12
0
        public override void run( State state )
        {
            // We execute by pushing all the code for building the keys and values onto the
            // action stack, and finish off with one that will combine them all.
            state.pushAction(
            new Step( this, s =>
            {
                var dict = new Dictionary<object, object>();
                for( int i=0; i<this.pairs.Count; ++i )
                {
                    object key = LValue.Deref( s );
                    object value = LValue.Deref( s );
                    dict[key] = value;
                }

                s.pushResult( dict );
            } )
            );
            foreach( Pair p in this.pairs )
            {
            p.key.run( state );
            p.value.run( state );
            }
        }
Пример #13
0
 // This IEnumerable implementation will be very inefficient for large arrays.
 void oneIteration( State state )
 {
     state.pushAction( new Step( this, st =>
     {
         object resultObj = LValue.Deref( st );
         bool result = Util.CoerceBool( resultObj );
         if( result )
         {
             st.pushAction( new Step( this, st2 =>
                 {
                     oneIteration( st2 );
                 }, "while: next block runner" ) );
             if( this.postLoop != null )
                 this.postLoop.run( st );
             st.pushAction( new Step( this, a => {}, BlockMarker ) );
             this.block.run( st );
         }
     }, "while: test checker" ) );
     this.test.run( state );
 }
Пример #14
0
 public void setProperty( State state, string name, object value )
 {
     if( name == "arbitrary" )
     _f = (string)value;
     if( name == "throws" )
     throw new ArgumentException( "Can't write this" );
 }
Пример #15
0
 public bool hasProperty( State state, string name )
 {
     return name == "arbitrary" || name == "other" || name == "throws";
 }
Пример #16
0
 public bool hasMethod( State state, string name )
 {
     return name == "test2" || name == "complex" || name == "dumpcontext";
 }
Пример #17
0
 public object getProperty( State state, string name )
 {
     if( name == "arbitrary" )
     return "it's arbitrary, yo";
     else if( name == "throws" )
     throw new ArgumentException( "Can't read this" );
     else
     return "something else";
 }
Пример #18
0
 public bool hasProperty( State state, string name )
 {
     return false;
 }
Пример #19
0
 public object callMethod( State state, string name, object[] args )
 {
     if( name == "other" )
     {
     Runner r = new Runner();
     r.runSync( _code );
     return new AsyncAction()
     {
         action = AsyncAction.Action.Call,
         function = (FValue)r.state.scope.get( "verb" ),
         args = args,
         frame = new StackTrace.StackFrame()
     };
     }
     else if( name == "thrower" )
     {
     Runner r = new Runner();
     r.runSync( _code );
     return new AsyncAction()
     {
         action = AsyncAction.Action.Call,
         function = (FValue)r.state.scope.get( "thrower" ),
         args = args,
         frame = new StackTrace.StackFrame()
     };
     }
     else
     throw new NotImplementedException();
 }
Пример #20
0
 public Runner( State st )
 {
     _state = st;
 }
Пример #21
0
 public Runner()
 {
     _state = new State();
 }
Пример #22
0
 public object getProperty( State state, string name )
 {
     return null;
 }
Пример #23
0
 public override void run( State state )
 {
     // We execute here by executing the condition, then interpreting the
     // outcome of that expression to determin if we should push on the contents
     // of the block.
     //
     // In order to handle multiple elif clauses, we curry a "clause index" value
     // in the continuations so that it can chain to the next elif or else if
     // the condition isn't true.
     state.pushAction( new Step( this, st => ifRunner( st, 0 ), this.clauses[0].ToString() ) );
     this.clauses[0].condition.run( state );
 }
Пример #24
0
        // Pulls the result of a conditional comparison and either queues the attached
        // block, or queues the next comparison.
        void ifRunner( State st, int clauseIndex )
        {
            object result = LValue.Deref( st );
            bool conv = Util.CoerceBool( result );

            if( conv )
            this.clauses[clauseIndex].block.run( st );
            else
            {
            ++clauseIndex;
            if( clauseIndex >= this.clauses.Length )
                return;

            if( this.clauses[clauseIndex].condition == null )
            {
                this.clauses[clauseIndex].block.run( st );
            }
            else
            {
                st.pushAction( new Step( this, st2 => ifRunner( st2, clauseIndex ), this.clauses[clauseIndex].ToString() ) );
                this.clauses[clauseIndex].condition.run( st );
            }
            }
        }
Пример #25
0
 public void setProperty( State state, string name, object value )
 {
 }
Пример #26
0
 public override void run( State state )
 {
     // We execute by first evaluating the test, and then if that's true, pushing one
     // iteration of the loop onto the action stack. Each iteration, if it completes
     // successfully, will push the next on. We also push a while loop marker on so
     // that break and continue work.
     state.pushAction( new Step( this, a => {}, LoopMarker ) );
     oneIteration( state );
     if( this.preLoop != null )
     this.preLoop.run( state );
 }
Пример #27
0
        /// <summary>
        /// Queues a Coral function to run asynchronously.
        /// </summary>
        public static void CallFunction( State state, FValue func, object[] args, StackTrace.StackFrame frame )
        {
            // Convert the arguments.
            AstNode[] wrapped = WrapArgs( args );

            // Construct a synthetic AstIdentifier for the name.
            AstNode funcNode = new WrapperAstObject( func );

            // Construct a synthetic AstCall.
            AstCall call = new AstCall( funcNode, wrapped, frame );

            call.run( state );
        }
Пример #28
0
 public object callMethod( State state, string name, object[] args )
 {
     if( name == "test2" )
     return "test worked " + String.Join( ",", args.Select( x => x.ToStringI() ).ToArray() );
     else if( name == "dumpcontext" )
     {
     var cxt = state.securityContext;
     return "Current context: " + ( cxt == null ? "none" : cxt.name );
     }
     else if( name == "complex" )
     {
     int which = (int)args[0];
     if( which == 1 )
     {
         return new AsyncAction()
         {
             action = AsyncAction.Action.Call,
             function = (FValue)args[1],
             args = new object[] { "added\r\n" },
             frame = new StackTrace.StackFrame()
             {
                 line = 0,
                 col = 0,
                 unitName = "test",
                 funcName = "PtTest.{0}".FormatI( name )
             }
         };
     }
     else if( which == 2 )
     {
         return new AsyncAction[]
         {
             new AsyncAction()
             {
                 action = AsyncAction.Action.Variable,
                 name = "shouldexist",
                 value = "oh cool"
             },
             new AsyncAction()
             {
                 action = AsyncAction.Action.Callback,
                 callback = st =>
                     {
                         var rv = "{0}".FormatI( st.scope.get( "shouldexist" ) );
                         st.pushResult( rv );
                     }
             }
         };
     }
     else if( which == 3 )
     {
         var constscope = new ConstScope( state.scope );
         constscope.setConstant( "testconst", "bob" );
         return new AsyncAction[]
         {
             new AsyncAction()
             {
                 action = AsyncAction.Action.Code,
                 code = Compiler.Compile( "test", @"
     def innerfunc(x):
     return [x + 1, testconst]
     " )
             },
             new AsyncAction()
             {
                 action = AsyncAction.Action.Call,
                 name = "innerfunc",
                 args = new object[] { 5 },
                 frame = new StackTrace.StackFrame()
                 {
                     line = 0,
                     col = 0,
                     unitName = "test",
                     funcName = "PtTest.{0}".FormatI( name )
                 }
             },
             new AsyncAction()
             {
                 action = AsyncAction.Action.PushScope,
                 scope = constscope
             }
         };
     }
     else if( which == 4 )
     {
         return new AsyncAction[]
         {
             new AsyncAction()
             {
                 action = AsyncAction.Action.Code,
                 code = Compiler.Compile( "test", @"
     def innerfunc(pt):
     return pt.dumpcontext()
     " )
             },
             new AsyncAction()
             {
                 action = AsyncAction.Action.Call,
                 name = "innerfunc",
                 args = new object[] { this },
                 frame = new StackTrace.StackFrame()
             },
             new AsyncAction()
             {
                 action = AsyncAction.Action.PushSecurityContext,
                 securityContext = new TestSC( "Context 1" )
             }
         };
     }
     else if( which == 5 )
     {
         return new AsyncAction[]
         {
             new AsyncAction()
             {
                 action = AsyncAction.Action.Code,
                 code = Compiler.Compile( "test", @"
     def innerfunc(pt):
     return pt.dumpcontext()
     " )
             },
             new AsyncAction()
             {
                 action = AsyncAction.Action.Call,
                 name = "innerfunc",
                 args = new object[] { this },
                 frame = new StackTrace.StackFrame()
             }
         };
     }
     else /* if( which == 6 ) */
     {
         throw new ArgumentException( "No idea what you're talking about!" );
     }
     }
     else
     return null;
 }
Пример #29
0
        public override void run( State state )
        {
            // We execute by running the "lhs" and "rhs", and then applying the operator to them,
            // producing another value. If the result of either is an LValue, we have to dereference it.

            state.pushAction(
            new Step( this, st =>
            {
                object right = LValue.Deref( st );

                if( this.op == "+=" )
                {
                    object left = st.popResult();

                    // This one is a bit trickier since we do different things based on different
                    // types, and the left side needs to be an LValue.
                    if( !(left is LValue) )
                        throw CoralException.GetArg( "Left-hand side of += must be LValue" );

                    // We need to write the LValue back, but keep the result value on
                    // the result stack since this can be used as a normal expression too.
                    LValue lv = (LValue)left;
                    object val = lv.read( st );
                    val = Plus( val, right );
                    lv.write( st, val );
                    st.pushResult( val );
                }
                else
                {
                    if( this.left != null )
                    {
                        object left = LValue.Deref( st );
                        st.pushResult( s_operations[this.op]( left, right ) );
                    }
                    else if( this.op == "-" )
                    {
                        st.pushResult( s_operations[this.op]( null, right ) );
                    }
                    else if( this.op == "!" )
                    {
                        st.pushResult( !((bool)Util.CoerceBool( right ) ) );
                    }
                    else
                        throw CoralException.GetInvProg( "Unary operator not supported" );
                }
            } )
            );
            this.right.run( state );
            if( this.left != null )
            this.left.run( state );
            else
            state.pushResult( null );
        }
Пример #30
0
 public bool hasMethod( State state, string name )
 {
     return true;
 }