Esempio n. 1
0
        /// <summary>
        /// Binds this function to an instance of a class,
        /// allowing it to access the instance's 'this' variable.
        /// </summary>
        /// <param name="instance">Instance to bind to.</param>
        /// <returns>The bound function.</returns>
        public Function Bind(Instance instance)
        {
            var environment = new EnvironmentState(outerEnvironment: _closure);

            environment.Define("this", instance);
            return(new Function(_declaration, environment, _name, _isInit));
        }
Esempio n. 2
0
        /// <summary>
        /// Calls the function.
        /// </summary>
        /// <param name="interpreter">Interpreter calling the function.</param>
        /// <param name="arguments">Arguments to pass to the function.</param>
        /// <returns>The result of the function call.</returns>
        public object Call(Interpreter interpreter, IEnumerable <object> arguments)
        {
            // each call gets its own scope so that it can keep track of its individual state
            var environment = new EnvironmentState(outerEnvironment: _closure);

            // combine the params and the arguments into one collection
            var paramArguments = _declaration.Params.Zip(arguments, (param, argument) => new
            {
                Name  = param.WrappedSource,
                Value = argument
            });

            // define scoped variables for each param/argument
            foreach (var item in paramArguments)
            {
                environment.Define(item.Name, item.Value);
            }

            try
            {
                // execute the function body with the new scope we just created
                interpreter.ExecuteBlock(_declaration.Body, environment);
            }
            catch (ReturnException ex)
            {
                return(_isInit
                    ? _closure.GetValue("this", 0)
                    : ex.Value);
            }

            // constructors will always return 'this'
            return(_isInit
                ? _closure.GetValue("this", 0)
                : null);
        }
Esempio n. 3
0
 /// <summary>
 /// Initialize a <see cref="Function"/> with the
 /// <see cref="FunctionStatement"/> declaration it originated from.
 /// </summary>
 /// <param name="declaration">Parsed source of the function.</param>
 public Function(FunctionExpression declaration, EnvironmentState closure,
                 Token name = null, bool isInit = false)
 {
     _declaration = declaration;
     _closure     = closure;
     _name        = name;
     _isInit      = isInit;
     ParamCount   = _declaration.Params.Count();
 }
Esempio n. 4
0
        /// <summary>
        /// Interprets and executes the given statements.
        /// </summary>
        /// <param name="statements">Statements to execute.</param>
        public void Interpret(IEnumerable <StatementBase> statements)
        {
            RuntimeExceptionThrown = false;
            _environment           = GlobalState;
            PrepareGlobalScope();

            try
            {
                foreach (var statement in statements)
                {
                    Execute(statement);
                }
            }
            catch (RuntimeException ex)
            {
                RuntimeExceptionThrown = true;
                ErrorReporter.ReportRuntimeException(ex);
            }
        }
Esempio n. 5
0
        /// <summary>
        /// <see cref="Execute(StatementBase)"/>s all statements in a block.
        /// </summary>
        /// <param name="statements">Statements to execute.</param>
        /// <param name="environment">The block's environment.</param>
        public void ExecuteBlock(IEnumerable <StatementBase> statements, EnvironmentState environment)
        {
            // hang on to the current scope
            var outerEnvironment = _environment;

            try
            {
                // our scope is now this block's scope
                _environment = environment;

                foreach (var statement in statements)
                {
                    Execute(statement);
                }
            }
            finally
            {
                // restore to the first scope
                _environment = outerEnvironment;
            }
        }
Esempio n. 6
0
 /// <summary>
 /// Initializes an <see cref="EnvironmentState"/>, optionally with an enclosing environment.
 /// </summary>
 /// <param name="outerEnvironment">The <see cref="EnvironmentState"/> enclosing this one.</param>
 public EnvironmentState(EnvironmentState outerEnvironment = null)
 {
     OuterEnvironment = outerEnvironment;
 }