Ejemplo n.º 1
0
        public static void Register(Engine engine)
        {
            TypeDef_Class ourType  = TypeFactory.GetTypeDef_Class("Debug", null, false);
            ClassDef      classDef = engine.defaultContext.CreateClass("Debug", ourType, null, null, true);

            classDef.Initialize();

            // string DumpClass(string className = "")
            //   Returns a string dump of the fields of a class with the given name.
            //   If no argument is given (or string is empty), instead returns a list of all classes.
            {
                FunctionValue_Host.EvaluateDelegate eval = (context, args, thisScope) => {
                    string className = (string)args[0];

                    if ("" == className)
                    {
                        return(context.GetDebugTypeString(true, false, false));
                    }
                    else
                    {
                        ClassDef def = context.GetClass(className);
                        if (null == def)
                        {
                            return("Class '" + className + "' not found.");
                        }

                        return(def.GetDebugString());
                    }
                };

                // Note: Here is an example of how you provide default argument values for a host function.
                List <Expr_Literal> defaultArgVals = new List <Expr_Literal>();
                defaultArgVals.Add(new Expr_Literal(null, "", IntrinsicTypeDefs.STRING));

                FunctionValue newValue = new FunctionValue_Host(IntrinsicTypeDefs.STRING, new ArgList {
                    IntrinsicTypeDefs.STRING
                }, eval, false, null, false, defaultArgVals);
                classDef.AddMemberLiteral("DumpClass", newValue.valType, newValue, true);
            }

            // string DumpStack()
            //   Returns a string printout of the stack at the point the function is called.
            {
                FunctionValue_Host.EvaluateDelegate eval = (context, args, thisScope) => {
                    return(context.ToString());
                };
                FunctionValue newValue = new FunctionValue_Host(IntrinsicTypeDefs.STRING, new ArgList {
                }, eval, false);
                classDef.AddMemberLiteral("DumpStack", newValue.valType, newValue, true);
            }

            // string DumpTypes()
            //   Returns a string printout of the registered types.
            {
                FunctionValue_Host.EvaluateDelegate eval = (context, args, thisScope) => {
                    return(context.GetDebugTypeString());
                };
                FunctionValue newValue = new FunctionValue_Host(IntrinsicTypeDefs.STRING, new ArgList {
                }, eval, false);
                classDef.AddMemberLiteral("DumpTypes", newValue.valType, newValue, true);
            }

            // string GetTotalMemory()
            //   Wraps GC.GetTotalMemory, which returns the number of bytes estimated to be allocated by C#.
            //   Note that this is NOT just memory allocated by Pebble.
            {
                FunctionValue_Host.EvaluateDelegate eval = (context, args, thisScope) => {
                    bool forceFullCorrection = (bool)args[0];

                    return(Convert.ToDouble(GC.GetTotalMemory(forceFullCorrection)));
                };
                FunctionValue newValue = new FunctionValue_Host(IntrinsicTypeDefs.NUMBER, new ArgList {
                    IntrinsicTypeDefs.BOOL
                }, eval, false);
                classDef.AddMemberLiteral("GetTotalMemory", newValue.valType, newValue, true);
            }

            // functype<bool(bool, string)> SetAssertCallback(functype<bool(bool, string)>)
            //   Sets callback for assert results, returns previous callback.
            //   Callback gets success as first variable, message as second. If returns false, system throws an Assert runtime exception.
            {
                TypeRef_Function handlerTypeRef = new TypeRef_Function(new TypeRef("bool"), new List <ITypeRef>()
                {
                    new TypeRef("bool"), new TypeRef("string")
                });
                bool             error          = false;
                TypeDef_Function handlerTypeDef = (TypeDef_Function)handlerTypeRef.Resolve(engine.defaultContext, ref error);
                Pb.Assert(!error, "Internal error: SetAssertHandler initialization.");

                FunctionValue_Host.EvaluateDelegate eval = (context, args, thisScope) => {
                    FunctionValue newHandler = (FunctionValue)args[0];
                    FunctionValue oldHandler = Expr_Assert.handler;
                    Expr_Assert.handler = newHandler;
                    return(oldHandler);
                };
                FunctionValue newValue = new FunctionValue_Host(handlerTypeDef, new ArgList {
                    handlerTypeDef
                }, eval, false);
                classDef.AddMemberLiteral("SetAssertCallback", newValue.valType, newValue, true);
            }

            //@ bool SetLogCompileErrors(bool log)
            //   Sets whether or not compile errors should be logged to the Engine's log function.
            //   Returns the previous value.
            {
                FunctionValue_Host.EvaluateDelegate eval = (context, args, thisScope) => {
                    bool oldValue = context.engine.logCompileErrors;
                    bool newVal   = (bool)args[0];
                    context.engine.logCompileErrors = newVal;
                    return(oldValue);
                };
                FunctionValue newValue = new FunctionValue_Host(IntrinsicTypeDefs.BOOL, new ArgList {
                    IntrinsicTypeDefs.BOOL
                }, eval, false);
                classDef.AddMemberLiteral("SetLogCompileErrors", newValue.valType, newValue, true);
            }

            // void TimerStart()
            //   Starts a debug timer. If one is already running it will be set to this new start time.
            {
                FunctionValue_Host.EvaluateDelegate eval = (context, args, thisScope) => {
                    timer = Stopwatch.StartNew();
                    return(null);
                };
                FunctionValue newValue = new FunctionValue_Host(IntrinsicTypeDefs.VOID, new ArgList {
                }, eval, false);
                classDef.AddMemberLiteral("TimerStart", newValue.valType, newValue, true);
            }

            // num TimerGet()
            //   Returns elapsed ms since TimerStart called, or -1 if TimerStart wasn't previously called.
            {
                FunctionValue_Host.EvaluateDelegate eval = (context, args, thisScope) => {
                    if (null == timer)
                    {
                        return(-1.0);
                    }
                    return(Convert.ToDouble(timer.ElapsedMilliseconds));
                };
                FunctionValue newValue = new FunctionValue_Host(IntrinsicTypeDefs.NUMBER, new ArgList {
                }, eval, false);
                classDef.AddMemberLiteral("TimerGet", newValue.valType, newValue, true);
            }

            classDef.FinalizeClass(engine.defaultContext);
        }
Ejemplo n.º 2
0
        public FunctionValue_Script(string name, IExpr _expr, ITypeRef _retType, List <ITypeRef> _argTypes, List <Expr_Literal> defaultVals = null)
        {
            argDefaultValues = defaultVals;
            BuildArgHasDefaults(_argTypes.Count);

            originalName = name;
            expr         = _expr;
            typeRef      = new TypeRef_Function(_retType, _argTypes, argHasDefaults, false);

            Evaluate = (context, args, thisScope) => {
                Pb.Assert(null != originalName);
                Pb.Assert(args.Count == _argTypes.Count, "Internal error: Don't have enough arguments!");

                if (context.IsRuntimeErrorSet())
                {
                    return(null);
                }

                object result;

                bool pushResult = false;
                if (null != staticClassDef)
                {
                    pushResult = context.stack.PushClassCall_StaticOrTypeCheck(typeDef, staticClassDef, true, context);
                }
                else
                {
                    pushResult = context.stack.PushCall(typeDef, originalName, thisScope, false, context);
                }

                if (!pushResult)
                {
                    context.SetRuntimeError(RuntimeErrorType.StackOverflow, "FunctionValue_Script.Evaluate : stack overflow");
                    return(null);
                }

                {
                    // Add name of this function as first variable in function scope.
                    // This condition loosely mirrors the check in Expr_Literal. It's shitty that the code that
                    // runs during TypeCheck is so far removed from this code that runs during Execute.
                    if (null == typeDef.classType)
                    {
                        context.stack.AddVariable(originalName, false, typeDef, this);
                    }

                    // Add argument variables to function scope.
                    if (null != args)
                    {
                        for (int ii = 0; ii < args.Count; ++ii)
                        {
                            context.AddLocalVariable(argNames[ii], valType.argTypes[ii], args[ii]);
                        }
                    }

                    result = _EvaluateInternal(context);
                }
                context.stack.PopScope();

                if (context.IsRuntimeErrorSet())
                {
                    return(null);
                }

                if (0 != (context.control.flags & ControlInfo.RETURN))
                {
                    result = context.control.result;
                    context.control.result = null;
                    context.control.flags -= ControlInfo.RETURN;
                }

                Pb.Assert(0 == context.control.flags);

                return(result);
            };
        }