Esempio n. 1
0
        /// <summary>
        /// Generate call to a routine and store result into a variable.
        /// </summary>
        /// <para>Stack behavior: </para>
        /// <list type="number">
        /// <item><description>create new variable</description></item>
        /// <item><description>store returned value</description></item>
        /// <item><description>nothing left on the stack</description></item>
        /// </list>
        /// <param name="call">"CALL" AST fragment</param>
        /// <returns>SLang variable which holds a value returned from a call.</returns>
        private Variable GenerateVariableFromCall(Call call)
        {
            var routine = GenerateCall(call);

            if (!routine.SignatureReference.ReturnType.IsVoid)
            {
                var variable = new BodyVariable(routine.SignatureDefinition.ReturnType);
                variable.Store(ip);
                return(variable);
            }

            return(new BodyVariable(Context.TypeSystem.Void));
        }
Esempio n. 2
0
        /// <summary>
        /// Generate "VARIABLE" declaration, evaluate its initializer and assign.
        /// </summary>
        /// <para>Stack behavior: expects nothing, leaves nothing.</para>
        /// <param name="declaration">SLang IR variable declaration.</param>
        private void GenerateVariableDeclaration(VariableDeclaration declaration)
        {
            var      name     = declaration.Name;
            var      varType  = new UnitReference(Context, declaration.Type).Resolve();
            Variable variable = new BodyVariable(varType, name);

            // declare in the current scope
            scopeCurrent.Declare(name, variable);
            // evaluate initializer
            var exprType = GenerateExpression(declaration.Initializer);

            // assign
            variable.Store(ip);

            // verify
            varType.AssertIsAssignableFrom(exprType);
        }
Esempio n. 3
0
        /// <summary>
        /// Given that instance of the underlying type is on the top of the stack, wrap it into new object of this type.
        /// </summary>
        /// <para>Stack behavior:</para>
        /// <list type="number">
        /// <item><description>raw (underlying) value is on the top of the stack</description></item>
        /// <item><description>instantiate new object wrapping that value</description></item>
        /// <item><description>new object is stored is a variable</description></item>
        /// <item><description>stack is empty: neither raw nor boxed value</description></item>
        /// </list>
        /// <returns>An instance of the <see cref="Variable"/> is the only way to access the created boxed object.</returns>
        public Variable Boxed(ILProcessor ip)
        {
            if (!IsForeign)
            {
                var boxed = new BodyVariable(this);
                var raw   = new VariableDefinition(WrappedNativeType);

                ip.Body.Variables.Add(raw);
                ip.Body.InitLocals = true;

                ip.Emit(OpCodes.Stloc, raw);
                boxed.LoadA(ip);
                ip.Emit(OpCodes.Ldloc, raw);
                ip.Emit(OpCodes.Call, Ctor);

                return(boxed);
            }

            return(new BodyVariable(Context.TypeSystem.Void));
        }