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); }
public bool ValidateArguments(CompileTimeValue[] staticArgv, int dynamicArgc) { return staticArgv.Length + dynamicArgc >= 1; }
/// <summary> /// Checks whether the static arguments and number of dynamic arguments are valid for the CIL extension. /// /// <para>Returning false means that the CIL extension cannot provide a CIL implementation for the set of arguments at hand. In that case the CIL compiler will fall back to <see /// cref = "ICilCompilerAware" /> and finally the built-in mechanisms.</para> /// <para>Returning true means that the CIL extension can provide a CIL implementation for the set of arguments at hand. In that case the CIL compiler may subsequently call <see /// cref = "ICilExtension.Implement" /> with the same set of arguments.</para> /// </summary> /// <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> /// <returns>true if the extension can provide a CIL implementation for the set of arguments; false otherwise</returns> public bool ValidateArguments(CompileTimeValue[] staticArgv, int dynamicArgc) { return dynamicArgc <= 0 && staticArgv.All(ctv => !ctv.IsReference); }
/// <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(); } }
bool ICilExtension.ValidateArguments(CompileTimeValue[] staticArgv, int dynamicArgc) { return true; }
void ICilExtension.Implement(CompilerState state, Instruction ins, CompileTimeValue[] staticArgv, int dynamicArgc) { FlippedFunctionalPartialCallCommand._ImplementCtorCall(state, ins, staticArgv, dynamicArgc, _functionPartialCallCtor); }
bool ICilExtension.ValidateArguments(CompileTimeValue[] staticArgv, int dynamicArgc) { string literal; int code; return dynamicArgc == 0 && staticArgv.Length == 1 && (staticArgv[0].TryGetString(out literal) && literal.Length > 0 || staticArgv[0].TryGetInt(out code) && code >= 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(); }
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); }
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); }
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); } }
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(); } }
internal static String _ToString(CompileTimeValue value) { switch (value.Interpretation) { case CompileTimeInterpretation.Null: return ""; case CompileTimeInterpretation.String: string str; if (!value.TryGetString(out str)) goto default; return str; case CompileTimeInterpretation.Int: int integer; if (!value.TryGetInt(out integer)) goto default; return integer.ToString(); case CompileTimeInterpretation.Bool: bool boolean; if (!value.TryGetBool(out boolean)) goto default; return boolean.ToString(); default: throw new ArgumentOutOfRangeException(); } }
void ICilExtension.Implement(CompilerState state, Instruction ins, CompileTimeValue[] staticArgv, int dynamicArgc) { foreach (var compileTimeValue in staticArgv) { EntityRef.Variable.Local local; if (!compileTimeValue.TryGetLocalVariableReference(out local)) throw new ArgumentException( "CIL implementation of Core.Unbind command only accepts local variable references.", "staticArgv"); CilSymbol cilSymbol; if (!state.Symbols.TryGetValue(local.Id, out cilSymbol) || cilSymbol.Kind != SymbolKind.LocalRef) throw new PrexoniteException( string.Format("CIL implementation of {1} cannot find local explicit variable {0}", local.Id, GetType().FullName)); //Create new PVariable state.Il.Emit(OpCodes.Newobj, Compiler.Cil.Compiler.NewPVariableCtor); state.Il.Emit(OpCodes.Dup); //Copy old value state.EmitLoadPValue(cilSymbol); state.EmitCall(Compiler.Cil.Compiler.SetValueMethod); //Override variable slot state.EmitStoreLocal(cilSymbol.Local); } if (!ins.JustEffect) state.EmitLoadNullAsPValue(); }
bool ICilExtension.ValidateArguments(CompileTimeValue[] staticArgv, int dynamicArgc) { return dynamicArgc == 0 && staticArgv.All( arg => arg.Interpretation == CompileTimeInterpretation.LocalVariableReference); }