Beispiel #1
0
        void ICilCompilerAware.ImplementInCil(CompilerState state, Instruction ins)
        {
            var argc = ins.Arguments;

            if (argc < 2)
            {
                state.EmitLoadNullAsPValue();
            }
            else
            {
                //pop excessive arguments
                for (var i = 2; i < argc; i++)
                    state.Il.Emit(OpCodes.Pop);

                //make pvkvp
                state.Il.Emit(OpCodes.Newobj, Compiler.Cil.Compiler.NewPValueKeyValuePair);

                //save pvkvp in temporary variable
                state.EmitStoreTemp(0);

                //PType.Object.CreatePValue(temp)
                state.Il.EmitCall(OpCodes.Call, Compiler.Cil.Compiler.GetObjectPTypeSelector, null);
                state.EmitLoadTemp(0);
                state.Il.EmitCall(OpCodes.Call, Compiler.Cil.Compiler.CreatePValueAsObject, null);
            }
        }
Beispiel #2
0
 void ICilCompilerAware.ImplementInCil(CompilerState state, Instruction ins)
 {
     state.EmitIgnoreArguments(ins.Arguments);
     state.Il.Emit(OpCodes.Newobj, _channelCtor);
     PType.PrexoniteObjectTypeProxy._ImplementInCil(state, typeof (Channel));
     state.Il.Emit(OpCodes.Newobj, _newPValue);
 }
Beispiel #3
0
        void ICilCompilerAware.ImplementInCil(CompilerState state, Instruction ins)
        {
            if (ins.Arguments > 0)
                throw new PrexoniteException("The meta command no longer accepts arguments.");

            state.EmitLoadLocal(state.SctxLocal);
            state.EmitLoadArg(CompilerState.ParamSourceIndex);
            var getMeta = typeof (PFunction).GetProperty("Meta").GetGetMethod();
            state.Il.EmitCall(OpCodes.Callvirt, getMeta, null);
            state.Il.EmitCall(OpCodes.Call, Compiler.Cil.Compiler.CreateNativePValue, null);
        }
Beispiel #4
0
 public void EmitLoad(CompilerState state)
 {
     switch (Kind)
     {
         case SymbolKind.Local:
             state.EmitLoadLocal(Local.LocalIndex);
             break;
         case SymbolKind.LocalRef:
             state.EmitLoadLocal(Local.LocalIndex);
             state.Il.EmitCall(OpCodes.Call, Compiler.GetValueMethod, null);
             break;
     }
 }
Beispiel #5
0
 public void Implement(CompilerState state, Instruction ins, CompileTimeValue[] staticArgv,
     int dynamicArgc)
 {
     if (dynamicArgc >= 1)
     {
         state.EmitIgnoreArguments(dynamicArgc - 1);
     }
     else
     {
         staticArgv[0].EmitLoadAsPValue(state);
     }
     state.EmitLoadLocal(state.SctxLocal);
     state.Il.EmitCall(OpCodes.Call, OperationMethod, null);
 }
Beispiel #6
0
        public void ImplementInCil(CompilerState state, Instruction ins)
        {
            var argc = ins.Arguments;
            if (argc == 0)
                return;

            if (ins.JustEffect)
            {
                state.EmitIgnoreArguments(argc);
            }
            else
            {
                state.EmitIgnoreArguments(argc - 1);
            }
        }
Beispiel #7
0
        public virtual void Implement(CompilerState state, Instruction ins,
            CompileTimeValue[] staticArgv, int dynamicArgc)
        {
            if (dynamicArgc >= 2)
            {
                state.EmitIgnoreArguments(dynamicArgc - 2);
                state.EmitStoreLocal(state.PrimaryTempLocal);
                state.EmitLoadLocal(state.SctxLocal);
                state.EmitLoadLocal(state.PrimaryTempLocal);
            }
            else if (dynamicArgc == 1)
            {
                //we can load the second static arg just where we need it
                state.EmitLoadLocal(state.SctxLocal);
                staticArgv[0].EmitLoadAsPValue(state);
            }
            else
            {
                PValue left;
                PValue right;

                if (staticArgv[0].TryGetConstant(out left)
                    && staticArgv[1].TryGetConstant(out right))
                {
                    //Both operands are constants (remember: static args can also be references)
                    //=> Apply the operator at compile time.
                    var result = Run(state, new[] {left, right});
                    switch (result.Type.ToBuiltIn())
                    {
                        case PType.BuiltIn.Real:
                            state.EmitLoadRealAsPValue((double) result.Value);
                            break;
                        case PType.BuiltIn.Int:
                            state.EmitLoadIntAsPValue((int) result.Value);
                            break;
                        case PType.BuiltIn.String:
                            state.EmitLoadStringAsPValue((string) result.Value);
                            break;
                        case PType.BuiltIn.Null:
                            state.EmitLoadNullAsPValue();
                            break;
                        case PType.BuiltIn.Bool:
                            state.EmitLoadBoolAsPValue((bool) result.Value);
                            break;
                        default:
                            throw new PrexoniteException(
                                string.Format(
                                    "The operation {0} is no implemented correctly. Given {1} and {2} it results in the non-constant {3}",
                                    GetType().FullName, left, right, result));
                    }
                    return; //We've already emitted the result. 
                }
                else
                {
                    //Load the first operand now, then proceed like for just one static arg
                    staticArgv[0].EmitLoadAsPValue(state);
                    state.EmitLoadLocal(state.SctxLocal);
                    staticArgv[1].EmitLoadAsPValue(state);
                }
            }

            state.Il.EmitCall(OpCodes.Call, OperationMethod, null);
        }
Beispiel #8
0
        private static void _createAndInitializeRemainingLocals(CompilerState state)
        {
            var nullLocals = new List<LocalBuilder>();

            //Create remaining local variables and initialize them
            foreach (var pair in state.Symbols)
            {
                var id = pair.Key;
                var sym = pair.Value;
                if (sym.Local != null)
                    continue;

                switch (sym.Kind)
                {
                    case SymbolKind.Local:
                        {
                            sym.Local = state.Il.DeclareLocal(typeof (PValue));
                            var initVal = _getVariableInitialization(state, id, false);
                            switch (initVal)
                            {
                                case VariableInitialization.ArgV:
                                    _emitLoadArgV(state);
                                    state.EmitStoreLocal(sym.Local);
                                    break;
                                case VariableInitialization.Null:
                                    nullLocals.Add(sym.Local); //defer assignment
                                    break;

                                    // ReSharper disable RedundantCaseLabel
                                case VariableInitialization.None:
                                    // ReSharper restore RedundantCaseLabel
                                default:
                                    break;
                            }
                        }
                        break;
                    case SymbolKind.LocalRef:
                        {
                            sym.Local = state.Il.DeclareLocal(typeof (PVariable));
                            var initVal = _getVariableInitialization(state, id, true);

                            var idx = sym.Local.LocalIndex;

                            state.Il.Emit(OpCodes.Newobj, NewPVariableCtor);

                            if (initVal != VariableInitialization.None)
                            {
                                state.Il.Emit(OpCodes.Dup);
                                state.EmitStoreLocal(idx);

                                switch (initVal)
                                {
                                    case VariableInitialization.ArgV:
                                        _emitLoadArgV(state);
                                        break;
                                    case VariableInitialization.Null:
                                        state.EmitLoadNullAsPValue();
                                        break;

                                    default:
                                        break;
                                }
                                state.Il.EmitCall(OpCodes.Call, SetValueMethod, null);
                            }
                            else
                            {
                                state.EmitStoreLocal(idx);
                            }
                        }
                        break;
                    case SymbolKind.LocalEnum:
                        {
                            sym.Local = state.Il.DeclareLocal(typeof (IEnumerator<PValue>));
                            //No initialization needed.
                        }
                        break;
                    default:
                        throw new PrexoniteException("Cannot initialize unknown symbol kind.");
                }
            }

            //Initialize null locals
            var nullCount = nullLocals.Count;
            if (nullCount > 0)
            {
                state.EmitLoadNullAsPValue();
                for (var i = 0; i < nullCount; i++)
                {
                    var local = nullLocals[i];
                    if (i + 1 != nullCount)
                        state.Il.Emit(OpCodes.Dup);
                    state.EmitStoreLocal(local);
                }
            }
        }
Beispiel #9
0
		public override void Implement(CompilerState state, Instruction ins, CompileTimeValue[] staticArgv, int dynamicArgc)
		{
			if(dynamicArgc >= 2)
			{
				state.EmitIgnoreArguments(dynamicArgc-2);
			}
			else if(dynamicArgc == 1)
			{
				staticArgv[0].EmitLoadAsPValue(state);
			}
			else
			{
				staticArgv[0].EmitLoadAsPValue(state);
				staticArgv[1].EmitLoadAsPValue(state);
			}
			state.EmitLoadLocal(state.SctxLocal);
            state.Il.EmitCall(System.Reflection.Emit.OpCodes.Call, OperationMethod, null);
		}
Beispiel #10
0
        private static void _emitInstructions(CompilerState state)
        {
            //Tables of foreach call hint hooks
            var foreachCasts = new Dictionary<int, ForeachHint>();
            var foreachGetCurrents = new Dictionary<int, ForeachHint>();
            var foreachMoveNexts = new Dictionary<int, ForeachHint>();
            var foreachDisposes = new Dictionary<int, ForeachHint>();

            foreach (var hint in state._ForeachHints)
            {
                foreachCasts.Add(hint.CastAddress, hint);
                foreachGetCurrents.Add(hint.GetCurrentAddress, hint);
                foreachMoveNexts.Add(hint.MoveNextAddress, hint);
                foreachDisposes.Add(hint.DisposeAddress, hint);
            }

            var sourceCode = state.Source.Code;

            //CIL Extension
            var cilExtensionMode = false;
            List<CompileTimeValue> staticArgv = null;

            for (var instructionIndex = 0; instructionIndex < sourceCode.Count; instructionIndex++)
            {
                #region Handling for try-finally-catch blocks

                //Handle try-finally-catch blocks
                //Push new blocks
                foreach (var block in state.Seh.GetOpeningTryBlocks(instructionIndex))
                {
                    state.TryBlocks.Push(block);
                    if (block.HasFinally)
                        state.Il.BeginExceptionBlock();
                    if (block.HasCatch)
                        state.Il.BeginExceptionBlock();
                }

                //Handle active blocks
                if (state.TryBlocks.Count > 0)
                {
                    CompiledTryCatchFinallyBlock block;
                    do
                    {
                        block = state.TryBlocks.Peek();
                        if (instructionIndex == block.BeginFinally)
                        {
                            if (block.SkipTry == instructionIndex)
                            {
                                //state.Il.MarkLabel(block.SkipTryLabel);
                                state.Il.Emit(OpCodes.Nop);
                            }
                            state.Il.BeginFinallyBlock();
                        }
                        else if (instructionIndex == block.BeginCatch)
                        {
                            if (block.HasFinally)
                                state.Il.EndExceptionBlock(); //end finally here
                            state.Il.BeginCatchBlock(typeof (Exception));
                            //parse the exception
                            state.EmitLoadLocal(state.SctxLocal);
                            state.Il.EmitCall(OpCodes.Call, Runtime.ParseExceptionMethod, null);
                            //user code will store it in a local variable
                        }
                        else if (instructionIndex == block.EndTry)
                        {
                            if (block.HasFinally || block.HasCatch)
                                state.Il.EndExceptionBlock();
                            if (block.SkipTry == instructionIndex)
                            {
                                //state.Il.MarkLabel(block.SkipTryLabel);
                                state.Il.Emit(OpCodes.Nop);
                            }
                            state.TryBlocks.Pop();
                            block = null; //signal another loop iteration
                        }
                    } while (block == null && state.TryBlocks.Count > 0);
                }

                #endregion

                state.MarkInstruction(instructionIndex);

                var ins = sourceCode[instructionIndex];

                #region CIL hints

                // **** CIL hints ****
                //  * CIL Extension *
                {
                    if (state._CilExtensionOffsets.Count > 0 &&
                        state._CilExtensionOffsets.Peek() == instructionIndex)
                    {
                        state._CilExtensionOffsets.Dequeue();
                        if (staticArgv == null)
                            staticArgv = new List<CompileTimeValue>(8);
                        else
                            staticArgv.Clear();
                        cilExtensionMode = true;
                    }
                    if (cilExtensionMode)
                    {
                        CompileTimeValue compileTimeValue;
                        if (CompileTimeValue.TryParse(ins, state.IndexMap, state.Cache, state.Source.ParentApplication.Module.Name, out compileTimeValue))
                        {
                            staticArgv.Add(compileTimeValue);
                        }
                        else
                        {
                            //found the actual invocation of the CIL extension
                            cilExtensionMode = false;

                            switch (ins.OpCode)
                            {
                                case OpCode.cmd:
                                    PCommand command;
                                    ICilExtension extension;
                                    if (
                                        !state.TargetEngine.Commands.TryGetValue(ins.Id, out command) ||
                                            (extension = command as ICilExtension) == null)
                                        goto default;

                                    extension.Implement(state, ins, staticArgv.ToArray(),
                                        ins.Arguments - staticArgv.Count);
                                    break;
                                default:
                                    throw new PrexoniteException(
                                        "The CIL compiler does not support CIL extensions for this opcode: " +
                                            ins);
                            }
                        }
                        continue;
                    }
                }
                //  * Foreach *
                {
                    ForeachHint hint;
                    if (foreachCasts.TryGetValue(instructionIndex, out hint))
                    {
                        //result of (expr).GetEnumerator on the stack
                        //cast IEnumerator
                        state.EmitLoadLocal(state.SctxLocal);
                        state.Il.EmitCall(OpCodes.Call, Runtime.ExtractEnumeratorMethod, null);
                        instructionIndex++;
                        //stloc enum
                        state.EmitStoreLocal(state.Symbols[hint.EnumVar].Local);
                        continue;
                    }
                    else if (foreachGetCurrents.TryGetValue(instructionIndex, out hint))
                    {
                        //ldloc enum
                        state.EmitLoadLocal(state.Symbols[hint.EnumVar].Local);
                        instructionIndex++;
                        //get.0 Current
                        state.Il.EmitCall(OpCodes.Callvirt, ForeachHint.GetCurrentMethod, null);
                        //result will be stored by user code
                        continue;
                    }
                    else if (foreachMoveNexts.TryGetValue(instructionIndex, out hint))
                    {
                        //ldloc enum
                        state.EmitLoadLocal(state.Symbols[hint.EnumVar].Local);
                        instructionIndex++;
                        //get.0 MoveNext
                        state.Il.EmitCall(OpCodes.Callvirt, ForeachHint.MoveNextMethod, null);
                        instructionIndex++;
                        //jump.t begin
                        var target = sourceCode[instructionIndex].Arguments; //read from user code
                        state.Il.Emit(OpCodes.Brtrue, state.InstructionLabels[target]);
                        continue;
                    }
                    else if (foreachDisposes.TryGetValue(instructionIndex, out hint))
                    {
                        //ldloc enum
                        state.EmitLoadLocal(state.Symbols[hint.EnumVar].Local);
                        instructionIndex++;
                        //@cmd.1 dispose
                        state.Il.EmitCall(OpCodes.Callvirt, ForeachHint.DisposeMethod, null);
                        continue;
                    }
                }

                #endregion

                //  * Normal code generation *
                //Decode instruction
                var argc = ins.Arguments;
                var justEffect = ins.JustEffect;
                var id = ins.Id;
                int idx;
                string methodId;
                string typeExpr;
                var moduleName = ins.ModuleName;

                //Emit code for the instruction
                switch (ins.OpCode)
                {
                        #region NOP

                        //NOP
                    case OpCode.nop:
                        //Do nothing
                        state.Il.Emit(OpCodes.Nop);
                        break;

                        #endregion

                        #region LOAD

                        #region LOAD CONSTANT

                        //LOAD CONSTANT
                    case OpCode.ldc_int:
                        state.EmitLoadIntAsPValue(argc);
                        break;
                    case OpCode.ldc_real:
                        state.EmitLoadRealAsPValue(ins);
                        break;
                    case OpCode.ldc_bool:
                        state.EmitLoadBoolAsPValue(argc != 0);
                        break;
                    case OpCode.ldc_string:
                        state.EmitLoadStringAsPValue(id);
                        break;

                    case OpCode.ldc_null:
                        state.EmitLoadNullAsPValue();
                        break;

                        #endregion LOAD CONSTANT

                        #region LOAD REFERENCE

                        //LOAD REFERENCE
                    case OpCode.ldr_loc:
                        state.EmitLoadLocalRefAsPValue(id);
                        break;
                    case OpCode.ldr_loci:
                        id = state.IndexMap[argc];
                        goto case OpCode.ldr_loc;
                    case OpCode.ldr_glob:
                        state.EmitLoadGlobalRefAsPValue(id, moduleName);
                        break;
                    case OpCode.ldr_func:
                        state.EmitLoadFuncRefAsPValue(id, moduleName);
                        break;
                    case OpCode.ldr_cmd:
                        state.EmitLoadCmdRefAsPValue(id);
                        break;
                    case OpCode.ldr_app:
                        CompilerState.EmitLoadAppRefAsPValue(state);
                        break;
                    case OpCode.ldr_eng:
                        state.EmitLoadEngRefAsPValue();
                        break;
                    case OpCode.ldr_type:
                        state.EmitPTypeAsPValue(id);
                        break;
                    case OpCode.ldr_mod:
                        state.EmitModuleNameAsPValue(moduleName);
                        break;

                        #endregion //LOAD REFERENCE

                        #endregion //LOAD

                        #region VARIABLES

                        #region LOCAL

                        //LOAD LOCAL VARIABLE
                    case OpCode.ldloc:
                        state.EmitLoadPValue(state.Symbols[id]);
                        break;
                    case OpCode.stloc:
                        //Don't use EmitStorePValue here, because this is a more efficient solution
                        var sym = state.Symbols[id];
                        if (sym.Kind == SymbolKind.Local)
                        {
                            state.EmitStoreLocal(sym.Local.LocalIndex);
                        }
                        else if (sym.Kind == SymbolKind.LocalRef)
                        {
                            state.EmitStoreLocal(state.PrimaryTempLocal.LocalIndex);
                            state.EmitLoadLocal(sym.Local.LocalIndex);
                            state.EmitLoadLocal(state.PrimaryTempLocal.LocalIndex);
                            state.Il.EmitCall(OpCodes.Call, SetValueMethod, null);
                        }
                        break;

                    case OpCode.ldloci:
                        id = state.IndexMap[argc];
                        goto case OpCode.ldloc;

                    case OpCode.stloci:
                        id = state.IndexMap[argc];
                        goto case OpCode.stloc;

                        #endregion

                        #region GLOBAL

                        //LOAD GLOBAL VARIABLE
                    case OpCode.ldglob:
                        state.EmitLoadGlobalValue(id, moduleName);
                        break;
                    case OpCode.stglob:
                        state.EmitStoreLocal(state.PrimaryTempLocal);
                        state.EmitLoadGlobalReference(id,moduleName);
                        state.EmitLoadLocal(state.PrimaryTempLocal);
                        state.Il.EmitCall(OpCodes.Call, SetValueMethod, null);
                        break;

                        #endregion

                        #endregion

                        #region CONSTRUCTION

                        //CONSTRUCTION
                    case OpCode.newobj:
                        state.EmitNewObj(id, argc);
                        break;
                    case OpCode.newtype:
                        state.FillArgv(argc);
                        state.EmitLoadLocal(state.SctxLocal);
                        state.ReadArgv(argc);
                        state.Il.Emit(OpCodes.Ldstr, id);
                        state.Il.EmitCall(OpCodes.Call, Runtime.NewTypeMethod, null);
                        break;

                    case OpCode.newclo:
                        //Collect shared variables
                        MetaEntry[] entries;
                        var func = state.Source.ParentApplication.Functions[id];
                        if (func.Meta.ContainsKey(PFunction.SharedNamesKey))
                            entries = func.Meta[PFunction.SharedNamesKey].List;
                        else
                            entries = new MetaEntry[] {};
                        var hasSharedVariables = entries.Length > 0;
                        if (hasSharedVariables)
                        {
                            state.EmitLdcI4(entries.Length);
                            state.Il.Emit(OpCodes.Newarr, typeof (PVariable));
                            state.EmitStoreLocal(state.SharedLocal);
                            for (var i = 0; i < entries.Length; i++)
                            {
                                state.EmitLoadLocal(state.SharedLocal);
                                state.EmitLdcI4(i);
                                state.EmitLoadLocal(state.Symbols[entries[i].Text].Local);
                                state.Il.Emit(OpCodes.Stelem_Ref);
                            }
                        }
                        state.EmitLoadLocal(state.SctxLocal);
                        if (hasSharedVariables)
                            state.EmitLoadLocal(state.SharedLocal);
                        else
                            state.Il.Emit(OpCodes.Ldnull);

                        state.EmitNewClo(id,moduleName);
                        break;

                    case OpCode.newcor:
                        state.FillArgv(argc);
                        state.EmitLoadLocal(state.SctxLocal);
                        state.ReadArgv(argc);
                        state.Il.EmitCall(OpCodes.Call, Runtime.NewCoroutineMethod, null);
                        break;

                        #endregion

                        #region OPERATORS

                        #region UNARY

                        //UNARY OPERATORS
                    case OpCode.incloc:
                        sym = state.Symbols[id];
                        if (sym.Kind == SymbolKind.Local)
                        {
                            state.EmitLoadLocal(sym.Local);
                            state.EmitLoadLocal(state.SctxLocal);
                            state.Il.EmitCall(OpCodes.Call, PVIncrementMethod, null);
                            state.EmitStoreLocal(sym.Local);
                        }
                        else if (sym.Kind == SymbolKind.LocalRef)
                        {
                            state.EmitLoadLocal(sym.Local);
                            state.Il.Emit(OpCodes.Dup);
                            state.Il.EmitCall(OpCodes.Call, GetValueMethod, null);
                            state.EmitLoadLocal(state.SctxLocal);
                            state.Il.EmitCall(OpCodes.Call, PVIncrementMethod, null);
                            state.Il.EmitCall(OpCodes.Call, SetValueMethod, null);
                        }
                        break;

                    case OpCode.incloci:
                        id = state.IndexMap[argc];
                        goto case OpCode.incloc;

                    case OpCode.incglob:
                        state.EmitLoadGlobalReference(id,moduleName);
                        state.Il.Emit(OpCodes.Dup);
                        state.Il.EmitCall(OpCodes.Call, GetValueMethod, null);
                        state.EmitLoadLocal(state.SctxLocal);
                        state.Il.EmitCall(OpCodes.Call, PVIncrementMethod, null);
                        state.Il.EmitCall(OpCodes.Call, SetValueMethod, null);
                        break;

                    case OpCode.decloc:
                        sym = state.Symbols[id];
                        if (sym.Kind == SymbolKind.Local)
                        {
                            state.EmitLoadLocal(sym.Local);
                            state.EmitLoadLocal(state.SctxLocal);
                            state.Il.EmitCall(OpCodes.Call, PVDecrementMethod, null);
                            state.EmitStoreLocal(sym.Local);
                        }
                        else if (sym.Kind == SymbolKind.LocalRef)
                        {
                            state.EmitLoadLocal(sym.Local);
                            state.Il.Emit(OpCodes.Dup);
                            state.Il.EmitCall(OpCodes.Call, GetValueMethod, null);
                            state.EmitLoadLocal(state.SctxLocal);
                            state.Il.EmitCall(OpCodes.Call, PVDecrementMethod, null);
                            state.Il.EmitCall(OpCodes.Call, SetValueMethod, null);
                        }
                        break;
                    case OpCode.decloci:
                        id = state.IndexMap[argc];
                        goto case OpCode.decloc;

                    case OpCode.decglob:
                        state.EmitLoadGlobalReference(id,moduleName);
                        state.Il.Emit(OpCodes.Dup);
                        state.Il.EmitCall(OpCodes.Call, GetValueMethod, null);
                        state.EmitLoadLocal(state.SctxLocal);
                        state.Il.EmitCall(OpCodes.Call, PVDecrementMethod, null);
                        state.Il.EmitCall(OpCodes.Call, SetValueMethod, null);
                        break;

                        #endregion

                        #region BINARY

                        // all binary operators are implemented as CIL extensions in
                        //  Prexonite.Commands.Core.Operators

                        #endregion //OPERATORS

                        #endregion

                        #region TYPE OPERATIONS

                        #region TYPE CHECK

                        //TYPE CHECK
                    case OpCode.check_const:
                        //Stack:
                        //  Obj
                        state.EmitLoadType(id);
                        //Stack:
                        //  Obj
                        //  Type
                        state.EmitCall(Runtime.CheckTypeConstMethod);
                        break;
                    case OpCode.check_arg:
                        //Stack: 
                        //  Obj
                        //  Type
                        state.Il.EmitCall(OpCodes.Call, Runtime.CheckTypeMethod, null);
                        break;

                    case OpCode.check_null:
                        state.Il.EmitCall(OpCodes.Call, PVIsNullMethod, null);
                        state.Il.Emit(OpCodes.Box, typeof (bool));
                        state.Il.EmitCall(OpCodes.Call, GetBoolPType, null);
                        state.Il.Emit(OpCodes.Newobj, NewPValue);
                        break;

                        #endregion

                        #region TYPE CAST

                    case OpCode.cast_const:
                        //Stack:
                        //  Obj
                        state.EmitLoadType(id);
                        //Stack:
                        //  Obj
                        //  Type
                        state.EmitLoadLocal(state.SctxLocal);
                        state.EmitCall(Runtime.CastConstMethod);

                        break;
                    case OpCode.cast_arg:
                        //Stack
                        //  Obj
                        //  Type
                        state.EmitLoadLocal(state.SctxLocal);
                        state.Il.EmitCall(OpCodes.Call, Runtime.CastMethod, null);
                        break;

                        #endregion

                        #endregion

                        #region OBJECT CALLS

                        #region DYNAMIC

                    case OpCode.get:
                        state.FillArgv(argc);
                        state.EmitLoadLocal(state.SctxLocal);
                        state.ReadArgv(argc);
                        state.EmitLdcI4((int) PCall.Get);
                        state.Il.Emit(OpCodes.Ldstr, id);
                        state.Il.EmitCall(OpCodes.Call, PVDynamicCallMethod, null);
                        if (justEffect)
                            state.Il.Emit(OpCodes.Pop);
                        break;

                    case OpCode.set:
                        state.FillArgv(argc);
                        state.EmitLoadLocal(state.SctxLocal);
                        state.ReadArgv(argc);
                        state.EmitLdcI4((int) PCall.Set);
                        state.Il.Emit(OpCodes.Ldstr, id);
                        state.Il.EmitCall(OpCodes.Call, PVDynamicCallMethod, null);
                        state.Il.Emit(OpCodes.Pop);
                        break;

                        #endregion

                        #region STATIC

                    case OpCode.sget:
                        //Stack:
                        //  arg
                        //   .
                        //   .
                        //   .
                        state.FillArgv(argc);
                        idx = id.LastIndexOf("::");
                        if (idx < 0)
                            throw new PrexoniteException
                                (
                                "Invalid sget instruction. Does not specify a method.");
                        methodId = id.Substring(idx + 2);
                        typeExpr = id.Substring(0, idx);
                        state.EmitLoadType(typeExpr);
                        state.EmitLoadLocal(state.SctxLocal);
                        state.ReadArgv(argc);
                        state.EmitLdcI4((int) PCall.Get);
                        state.Il.Emit(OpCodes.Ldstr, methodId);
                        state.EmitVirtualCall(Runtime.StaticCallMethod);
                        if (justEffect)
                            state.Il.Emit(OpCodes.Pop);
                        break;

                    case OpCode.sset:
                        state.FillArgv(argc);
                        idx = id.LastIndexOf("::");
                        if (idx < 0)
                            throw new PrexoniteException
                                (
                                "Invalid sset instruction. Does not specify a method.");
                        methodId = id.Substring(idx + 2);
                        typeExpr = id.Substring(0, idx);
                        state.EmitLoadType(typeExpr);
                        state.EmitLoadLocal(state.SctxLocal);
                        state.ReadArgv(argc);
                        state.EmitLdcI4((int) PCall.Set);
                        state.Il.Emit(OpCodes.Ldstr, methodId);
                        state.EmitVirtualCall(Runtime.StaticCallMethod);
                        state.Il.Emit(OpCodes.Pop);
                        break;

                        #endregion

                        #endregion

                        #region INDIRECT CALLS

                    case OpCode.indloc:
                        sym = state.Symbols[id];
                        if (sym == null)
                            throw new PrexoniteException(
                                "Internal CIL compiler error. Information about local entity " + id +
                                    " missing.");
                        state.FillArgv(argc);
                        sym.EmitLoad(state);
                        state.EmitIndirectCall(argc, justEffect);
                        break;

                    case OpCode.indloci:
                        idx = argc & ushort.MaxValue;
                        argc = (argc & (ushort.MaxValue << 16)) >> 16;
                        id = state.IndexMap[idx];
                        goto case OpCode.indloc;

                    case OpCode.indglob:
                        state.FillArgv(argc);
                        state.EmitLoadGlobalValue(id,moduleName);
                        state.EmitIndirectCall(argc, justEffect);
                        break;

                    case OpCode.indarg:
                        //Stack
                        //  obj
                        //  args
                        state.FillArgv(argc);
                        state.EmitIndirectCall(argc, justEffect);
                        break;

                    case OpCode.tail:
                        throw new PrexoniteException(
                            "Cannot compile tail instruction to CIL. Qualification should have failed.");

                        #endregion

                        #region ENGINE CALLS

                    case OpCode.func:
                        state.EmitFuncCall(argc, id, moduleName, justEffect);
                        break;
                    case OpCode.cmd:
                        state.EmitCommandCall(ins);
                        break;

                        #endregion

                        #region FLOW CONTROL

                        //FLOW CONTROL

                        #region JUMPS

                    case OpCode.jump:
                    case OpCode.jump_t:
                    case OpCode.jump_f:
                    case OpCode.ret_break:
                    case OpCode.ret_continue:
                        state.Seh.EmitJump(instructionIndex, ins);
                        break;

                        #endregion

                        #region RETURNS

                    case OpCode.ret_exit:
                        goto case OpCode.jump;

                    case OpCode.ret_value:
                        //return value is assigned by SEH
                        goto case OpCode.jump;

                    case OpCode.ret_set:
                        state.EmitSetReturnValue();
                        break;

                        #endregion

                        #region THROW

                    case OpCode.@throw:
                        state.EmitLoadLocal(state.SctxLocal);
                        state.Il.EmitCall(OpCodes.Call, Runtime.ThrowExceptionMethod, null);
                        break;

                        #endregion

                        #region LEAVE

                    case OpCode.@try:
                        //Is done via analysis of TryCatchFinally objects associated with the function
                        Debug.Assert(state.StackSize[instructionIndex] == 0,
                            "The stack should be empty when entering a try-block.",
                            "The stack is not empty when entering the try-block at instruction {0} in function {1}.",
                            instructionIndex, state.Source);
                        break;

                    case OpCode.leave:
                        //is handled by the CLR

                        #endregion

                        #region EXCEPTION

                    case OpCode.exc:
                        //is not implemented via Emit
                        // The exception is stored when the exception block is entered.
                        break;

                        #endregion

                        #endregion

                        #region STACK MANIPULATION

                        //STACK MANIPULATION
                    case OpCode.pop:
                        for (var i = 0; i < argc; i++)
                            state.Il.Emit(OpCodes.Pop);
                        break;
                    case OpCode.dup:
                        for (var i = 0; i < argc; i++)
                            state.Il.Emit(OpCodes.Dup);
                        break;
                    case OpCode.rot:
                        var values = (int) ins.GenericArgument;
                        var rotations = argc;
                        for (var i = 0; i < values; i++)
                            state.EmitStoreLocal
                                (
                                    state.TempLocals[(i + rotations)%values].LocalIndex);
                        for (var i = values - 1; i >= 0; i--)
                            state.EmitLoadLocal(state.TempLocals[i].LocalIndex);
                        break;

                        #endregion
                } //end of switch over opcode

                //DON'T ADD ANY CODE HERE, A LOT OF CASES USE `CONTINUE`
            } // end of loop over instructions

            //Close all pending try blocks, since the next instruction will never come
            //  (other closing try blocks are handled by the emitting the instruction immediately following 
            //  the try block)
            foreach (var block in state.TryBlocks)
            {
                if (block.HasCatch || block.HasFinally)
                    state.Il.EndExceptionBlock();
            }

            //Implicit return
            //Often instructions refer to a virtual instruction after the last real one.
            state.MarkInstruction(sourceCode.Count);
            state.Il.MarkLabel(state.ReturnLabel);
            state.Il.Emit(OpCodes.Ret);
        }
Beispiel #11
0
 void ICilCompilerAware.ImplementInCil(CompilerState state, Instruction ins)
 {
     throw new NotSupportedException("The command " + GetType().Name +
         " does not support CIL compilation via ICilCompilerAware.");
 }
Beispiel #12
0
 /// <summary>
 ///     Provides a custom compiler routine for emitting CIL byte code for a specific instruction.
 /// </summary>
 /// <param name = "state">The compiler state.</param>
 /// <param name = "ins">The instruction to compile.</param>
 void ICilCompilerAware.ImplementInCil(CompilerState state, Instruction ins)
 {
     switch (ins.Arguments)
     {
         case 0:
             state.Il.EmitCall(OpCodes.Call, consoleWriteLineMethod_, null);
             if (!ins.JustEffect)
             {
                 state.Il.Emit(OpCodes.Ldstr, "");
                 state.Il.EmitCall(OpCodes.Call, Compiler.Cil.Compiler.GetStringPType, null);
                 state.Il.Emit(OpCodes.Newobj, Compiler.Cil.Compiler.NewPValue);
             }
             break;
         case 1:
             state.EmitLoadLocal(state.SctxLocal);
             state.Il.EmitCall(OpCodes.Call, PValueCallToString, null);
             if (!ins.JustEffect)
             {
                 state.Il.Emit(OpCodes.Dup);
                 state.Il.EmitCall(OpCodes.Call, Compiler.Cil.Compiler.GetStringPType, null);
                 state.Il.Emit(OpCodes.Newobj, Compiler.Cil.Compiler.NewPValue);
                 state.EmitStoreTemp(0);
             }
             state.Il.EmitCall(OpCodes.Call, consoleWriteLineMethod_String, null);
             if (!ins.JustEffect)
             {
                 state.EmitLoadTemp(0);
             }
             break;
         default:
             throw new NotSupportedException();
     }
 }
Beispiel #13
0
 /// <summary>
 ///     Provides a custom compiler routine for emitting CIL byte code for a specific instruction.
 /// </summary>
 /// <param name = "state">The compiler state.</param>
 /// <param name = "ins">The instruction to compile.</param>
 void ICilCompilerAware.ImplementInCil(CompilerState state, Instruction ins)
 {
     state.EmitCall(_getCharPType);
 }
Beispiel #14
0
 public void EmitLoadAsPValue(CompilerState state)
 {
     switch (Interpretation)
     {
         case CompileTimeInterpretation.Null:
             state.EmitLoadNullAsPValue();
             break;
         case CompileTimeInterpretation.String:
             string stringValue;
             if (!TryGetString(out stringValue))
                 goto default;
             state.EmitLoadStringAsPValue(stringValue);
             break;
         case CompileTimeInterpretation.Int:
             int intValue;
             if (!TryGetInt(out intValue))
                 goto default;
             state.EmitLoadIntAsPValue(intValue);
             break;
         case CompileTimeInterpretation.Bool:
             bool boolValue;
             if (!TryGetBool(out boolValue))
                 goto default;
             state.EmitLoadBoolAsPValue(boolValue);
             break;
         case CompileTimeInterpretation.LocalVariableReference:
             EntityRef.Variable.Local localVariable;
             if (!TryGetLocalVariableReference(out localVariable))
                 goto default;
             state.EmitLoadLocalRefAsPValue(localVariable);
             break;
         case CompileTimeInterpretation.GlobalVariableReference:
             EntityRef.Variable.Global globalVariable;
             if (!TryGetGlobalVariableReference(out globalVariable))
                 goto default;
             state.EmitLoadGlobalRefAsPValue(globalVariable);
             break;
         case CompileTimeInterpretation.FunctionReference:
             EntityRef.Function func;
             if (!TryGetFunctionReference(out func))
                 goto default;
             state.EmitLoadFuncRefAsPValue(func);
             break;
         case CompileTimeInterpretation.CommandReference:
             EntityRef.Command command;
             if (!TryGetCommandReference(out command))
                 goto default;
             state.EmitLoadCmdRefAsPValue(command);
             break;
         default:
             throw new ArgumentOutOfRangeException();
     }
 }
Beispiel #15
0
        void ICilExtension.Implement(CompilerState state, Instruction ins,
            CompileTimeValue[] staticArgv, int dynamicArgc)
        {
            if (ins.JustEffect)
                return; // Usually for commands without side-effects you have to at least
            //  pop dynamic arguments from the stack.
            // ValidateArguments proved that there are no arguments on the stack.
            string literal;
            int code;
            if (staticArgv[0].TryGetString(out literal))
                code = literal[0];
            else if (!staticArgv[0].TryGetInt(out code))
                throw new ArgumentException(
                    "char command requires one argument that is either a string or a 32-bit integer with the most significant bit cleared.");

            state.EmitLdcI4(code);
            state.EmitWrapChar();
        }
Beispiel #16
0
        /// <summary>
        ///     Provides a custom compiler routine for emitting CIL byte code for a specific instruction.
        /// </summary>
        /// <param name = "state">The compiler state.</param>
        /// <param name = "ins">The instruction to compile.</param>
        void ICilCompilerAware.ImplementInCil(CompilerState state, Instruction ins)
        {
            if (ins.JustEffect)
            {
                for (var i = 0; i < ins.Arguments; i++)
                    state.Il.Emit(OpCodes.Pop);
            }
            else
            {
                switch (ins.Arguments)
                {
                    case 0:
                        state.EmitLoadNullAsPValue();
                        state.EmitLoadNullAsPValue();
                        break;
                    case 1:
                        state.EmitLoadNullAsPValue();
                        break;
                    case 2:
                        break;
                    default:
                        throw new NotSupportedException();
                }

                state.EmitLoadLocal(state.SctxLocal);
                state.EmitCall(RunStaticallyMethod);
            }
        }
Beispiel #17
0
        public void Implement(CompilerState state, Instruction ins, CompileTimeValue[] staticArgv,
            int dynamicArgc)
        {
            var text = String.Concat(staticArgv.Select(StaticPrint._ToString));

            state.EmitCall(StaticPrint._StaticPrintTextWriterGetMethod);
            state.Il.Emit(OpCodes.Ldstr, text);
            if (!ins.JustEffect)
            {
                state.Il.Emit(OpCodes.Dup);
                state.EmitStoreTemp(0);
            }
            state.EmitVirtualCall(_textWriterWriteLineMethod);
            if (!ins.JustEffect)
            {
                state.EmitLoadTemp(0);
                state.EmitWrapString();
            }
        }
Beispiel #18
0
 void ICilCompilerAware.ImplementInCil(CompilerState state, Instruction ins)
 {
     for (var i = 0; i < ins.Arguments; i++)
         state.Il.Emit(OpCodes.Pop);
     if (!ins.JustEffect)
     {
         state.EmitLoadLocal(state.SctxLocal);
         state.Il.EmitCall(OpCodes.Call, GetCallerFromCilFunctionMethod, null);
     }
 }
 void ICilExtension.Implement(CompilerState state, Instruction ins,
     CompileTimeValue[] staticArgv, int dynamicArgc)
 {
     FlippedFunctionalPartialCallCommand._ImplementCtorCall(state, ins, staticArgv, dynamicArgc, _functionPartialCallCtor);
 }
Beispiel #20
0
 public void ImplementInCil(CompilerState state, Instruction ins)
 {
     throw new NotSupportedException("The command " + Alias +
         " does provide a custom cil implementation. ");
 }
Beispiel #21
0
 /// <summary>
 ///     Provides a custom compiler routine for emitting CIL byte code for a specific instruction.
 /// </summary>
 /// <param name = "state">The compiler state.</param>
 /// <param name = "ins">The instruction to compile.</param>
 void ICilCompilerAware.ImplementInCil(CompilerState state, Instruction ins)
 {
     throw new NotSupportedException();
 }
        internal static void _ImplementCtorCall(CompilerState state, Instruction ins, CompileTimeValue[] staticArgv,
            int dynamicArgc, ConstructorInfo partialCallCtor)
        {
//the call subject is not part of argv
            var argc = staticArgv.Length + dynamicArgc - 1;

            if (argc == 0)
            {
                //there is no subject, just load null
                state.EmitLoadNullAsPValue();
                return;
            }

            //We don't actually need static arguments, just emit the corresponding opcodes
            foreach (var compileTimeValue in staticArgv)
                compileTimeValue.EmitLoadAsPValue(state);

            //pack arguments (including static ones) into the argv array, but exclude subject (the first argument)
            state.FillArgv(argc);
            state.ReadArgv(argc);

            //call constructor of FunctionalPartialCall

            state.Il.Emit(OpCodes.Newobj, partialCallCtor);

            //wrap in PValue
            if (ins.JustEffect)
            {
                state.Il.Emit(OpCodes.Pop);
            }
            else
            {
                state.EmitStoreTemp(0);
                state.EmitLoadLocal(state.SctxLocal);
                state.EmitLoadTemp(0);
                state.EmitVirtualCall(Compiler.Cil.Compiler.CreateNativePValue);
            }
        }
Beispiel #23
0
        /// <summary>
        ///     Implements the CIL extension in CIL for the supplied arguments. The CIL compiler guarantees to always first call <see
        ///      cref = "ICilExtension.ValidateArguments" /> in order to establish whether the extension can actually implement a particular call.
        ///     Thus, this method does not have to verify <paramref name = "staticArgv" /> and <paramref name = "dynamicArgc" />.
        /// </summary>
        /// <param name = "state">The CIL compiler state. This object is used to emit instructions.</param>
        /// <param name = "ins">The instruction that "calls" the CIL extension. Usually a command call.</param>
        /// <param name = "staticArgv">The suffix of compile-time constant arguments, starting after the last dynamic (not compile-time constant) argument. An empty array means that there were no compile-time constant arguments at the end.</param>
        /// <param name = "dynamicArgc">The number of dynamic arguments preceding the supplied static arguments. The total number of arguments is determined by <code>(staticArgv.Length + dynamicArgc)</code></param>
        public void Implement(CompilerState state, Instruction ins, CompileTimeValue[] staticArgv,
            int dynamicArgc)
        {
            var text = String.Concat(staticArgv.Select(StaticPrint._ToString));

            state.Il.Emit(OpCodes.Ldstr, text);
            if (!ins.JustEffect)
            {
                state.Il.Emit(OpCodes.Dup);
            }
            state.EmitCall(consoleWriteLineMethod_String);
            if (!ins.JustEffect)
            {
                state.EmitWrapString();
            }
        }
Beispiel #24
0
 /// <summary>
 ///     Provides a custom compiler routine for emitting CIL byte code for a specific instruction.
 /// </summary>
 /// <param name = "state">The compiler state.</param>
 /// <param name = "ins">The instruction to compile.</param>
 void ICilCompilerAware.ImplementInCil(CompilerState state, Instruction ins)
 {
     var argc = ins.Arguments;
     if (ins.JustEffect)
     {
         state.EmitIgnoreArguments(argc);
     }
     else
     {
         if (argc > 2)
         {
             state.EmitIgnoreArguments(argc - 2);
             argc = 2;
         }
         switch (argc)
         {
             case 0:
                 state.EmitLdcI4(0);
                 state.EmitWrapInt();
                 goto case 1;
             case 1:
                 state.EmitLoadLocal(state.SctxLocal);
                 state.EmitCall(RunStaticallyNaturalMethod);
                 break;
             case 2:
                 state.EmitLoadLocal(state.SctxLocal);
                 state.EmitCall(RunStaticallyAnyMethod);
                 break;
         }
     }
 }
Beispiel #25
0
        internal static void _CallStaticFunc1(CompilerState state, Instruction ins, MethodInfo runStaticallyMethod)
        {
            if (ins == null)
                throw new ArgumentNullException("ins");

            switch (ins.Arguments)
            {
                case 1:
                    break;
                default:
                    throw new NotSupportedException();
            }

            if (ins.JustEffect)
            {
                state.Il.Emit(OpCodes.Pop);
            }
            else
            {
                state.EmitLoadLocal(state.SctxLocal);
                state.EmitCall(runStaticallyMethod);
            }
        }
Beispiel #26
0
 public static void EmitLoadAppRefAsPValue(CompilerState state)
 {
     state.EmitLoadLocal(state.SctxLocal);
     state.Il.EmitCall
         (
             OpCodes.Call, Runtime.LoadApplicationReferenceMethod, null);
 }
Beispiel #27
0
 /// <summary>
 ///     Provides a custom compiler routine for emitting CIL byte code for a specific instruction.
 /// </summary>
 /// <param name = "state">The compiler state.</param>
 /// <param name = "ins">The instruction to compile.</param>
 void ICilCompilerAware.ImplementInCil(CompilerState state, Instruction ins)
 {
     Abs._CallStaticFunc1(state, ins, RunStaticallyMethod);
 }
Beispiel #28
0
 public void ImplementInCil(CompilerState state, Instruction ins)
 {
     throw new NotSupportedException(Alias + " does not provide a custom CIL implementation.");
 }
Beispiel #29
0
 /// <summary>
 ///     Provides a custom compiler routine for emitting CIL byte code for a specific instruction.
 /// </summary>
 /// <param name = "state">The compiler state.</param>
 /// <param name = "ins">The instruction to compile.</param>
 void ICilCompilerAware.ImplementInCil(CompilerState state, Instruction ins)
 {
     state.EmitCall(Compiler.Cil.Compiler.GetIntPType);
 }
Beispiel #30
0
        public void ImplementInCil(CompilerState state, Instruction ins)
        {
            var argc = ins.Arguments;
            if (argc > 1)
                state.EmitIgnoreArguments(argc - 1);

            state.EmitLoadLocal(state.SctxLocal);
            if (argc == 0)
                state.EmitLoadNullAsPValue();

            state.EmitCall(_createConstFunction);
        }