public ParameterScope( IScope parent, string[] parameters ) { _parent = parent; _contents = new StandardScope(); foreach( string p in parameters ) _contents.set( p, null ); }
public object invoke( VerbParameters param, bool coralContinuation ) { // Inject the verb script blob parameters as script variables. var scope = new Dictionary<string, object>(); scope["input"] = param.input; scope["inputwords"] = param.inputwords; scope["self"] = new Proxies.MobProxy(param.self, param.player); scope["obj"] = new Proxies.MobProxy(param.dobj, param.player); if (param.prep != Prep.None) scope["prep"] = param.prep.ToString().ToLowerInvariant(); else scope["prep"] = null; scope["indobj"] = new Proxies.MobProxy(param.iobj, param.player); if (param.prep2 != Prep.None) scope["prep2"] = param.prep2.ToString().ToLowerInvariant(); else scope["prep2"] = null; scope["indobj2"] = new Proxies.MobProxy(param.iobj2, param.player); scope["objwords"] = param.dobjwords; scope["prepwords"] = param.prepwords; scope["indobjwords"] = param.iobjwords; scope["prep2words"] = param.prep2words; scope["indobj2words"] = param.iobj2words; // Inject some standard MOO objects. scope["ambiguous"] = Proxies.MobProxy.Ambiguous; scope["none"] = Proxies.MobProxy.None; // Inject the player object. Proxies.PlayerProxy player = null; if (param.player != null) player = new Proxies.PlayerProxy( param.player, param.world ); scope["player"] = player; // "caller" is the same as the player, unless otherwise specified. if (param.caller != null) scope["caller"] = new Proxies.MobProxy(param.caller, param.player); else scope["caller"] = player; scope["args"] = param.args; scope["world"] = new Proxies.WorldProxy(param.world, param.player); scope["$"] = new Proxies.MobProxy(param.world.findObject(1), param.player); scope["perms"] = Proxies.PermBitsProxy.Static; Func<string,object> querier = (name) => { if (name.StartsWithI("#")) { int number = CultureFree.ParseInt(name.Substring(1)); if( number == Mob.Anon.id ) { Mob m = param.player.anonMob; if( m != null ) return new Proxies.MobProxy( m, param.player ); } return new Proxies.MobProxy(param.world.findObject(number), param.player); } return null; }; // Is the verb valid / compiled properly? if( !_coral.success ) { player.write( "Verb was not properly compiled." ); if( _coral.errors != null ) { foreach( var err in _coral.errors ) player.write( " line {0}, col {1}: {2}".FormatI( err.line, err.col, err.message ) ); } return null; } // We have to run the code first, for it to define its verb. var runner = new Coral.Runner(); var tempScope = new Coral.StandardScope( runner.state.baseScope ); runner.pushScope( tempScope ); runner.setScopeCallback( querier ); foreach( var kv in scope ) runner.addToScope( kv.Key, kv.Value ); runner.runSync( _coral ); Coral.FValue verbFunc = (Coral.FValue)tempScope.get( "verb" ); tempScope.delete( "verb" ); // Now that's done, hook up to the main state. runner = new Coral.Runner( param.player.coralState ); runner.pushScope( tempScope ); // Pass these on literally to any down-stream invokes. runner.state.baggage.set( VerbParamsKey, param ); Coral.StackTrace.StackFrame frame = new Coral.StackTrace.StackFrame() { unitName = "<climoo>", funcName = "<trampoline>" }; // If there wasn't one, throw a sensible error. if( verbFunc == null ) throw new InvalidOperationException( "Verb does not define a function called 'verb'." ); // Print security context debug info if the player's debug flag is set. if( player.get.attrHas( "debug" ) ) { var value = player.get.attrGet( "debug" ).contents; if( value is bool && (bool)value ) { string securityStack = String.Join( "->", param.player.actorContextStack.Select( id => "{0}".FormatI( id ) ) .ToArray() ); string securityText = "[color=#0cc]Running {0} as {1} ({2})[/color]".FormatI( this.name, param.player.actorContext, securityStack ); param.player.writeError( securityText ); } } // If we came from Coral and we're going to Coral, use a continuation. if( coralContinuation ) { return new Coral.AsyncAction() { action = Coral.AsyncAction.Action.Call, function = verbFunc, args = param.args, frame = frame }; } else { try { runner.state.scope.set( "!verb-" + this.name, verbFunc ); return runner.callFunction( "!verb-" + this.name, param.args, typeof( object ), frame ); } catch( Coral.CoralException ex ) { param.player.writeError( "Unhandled exception {0}: {1}\n{2}".FormatI( ex.name, ex.Message, ex.trace ) ); return null; } } }