/// <summary> /// Create iteration code for an array /// </summary> /// <param name="emitter"></param> public void CompileArray(Emitter.Emitter emitter) { var iterType = Iterable.GetExpressionType(emitter); // make local variables only visible inside the scope emitter.CurrentMethod.Scope.EnterSubScope(); var idxVar = emitter.CurrentMethod.Scope.Introduce("int", emitter.ResolveType("int"), Key == null ? null : Key.Data); var arrVar = emitter.CurrentMethod.Scope.Introduce(iterType, emitter.ResolveType(iterType)); var currType = emitter.GetArrayItemType(iterType); var currVar = emitter.CurrentMethod.Scope.Introduce(currType, emitter.ResolveType(currType), Item.Data); // prelude: arr = ..., idx = -1 Iterable.Compile(emitter); emitter.EmitSaveVariable(arrVar); emitter.EmitLoadInt(-1); emitter.EmitSaveVariable(idxVar); emitter.PlaceLabel(BodyStart); // increment emitter.EmitLoadVariable(idxVar); emitter.EmitLoadInt(1); emitter.EmitAdd(); emitter.EmitSaveVariable(idxVar); // loop exit condition emitter.EmitLoadVariable(idxVar); emitter.EmitLoadVariable(arrVar); emitter.EmitLoadArraySize(); emitter.EmitCompareLess(); emitter.EmitBranchFalse(BodyEnd); // variable: curr = array[idx] emitter.EmitLoadVariable(arrVar); emitter.EmitLoadVariable(idxVar); emitter.EmitLoadIndex(currType); emitter.EmitSaveVariable(currVar); // body var preCurrLoop = emitter.CurrentLoop; emitter.CurrentLoop = this; Body.Compile(emitter); emitter.CurrentLoop = preCurrLoop; emitter.EmitBranch(BodyStart); emitter.PlaceLabel(BodyEnd); emitter.CurrentMethod.Scope.LeaveSubScope(); }
/// <summary> /// Create iteration code for a range /// </summary> /// <param name="emitter"></param> public void CompileRange(Emitter.Emitter emitter) { // make local variables only visible inside the scope emitter.CurrentMethod.Scope.EnterSubScope(); var idxVar = emitter.CurrentMethod.Scope.Introduce("int", emitter.ResolveType("int"), Key == null ? null : Key.Data); var rangeVar = emitter.CurrentMethod.Scope.Introduce("range", emitter.ResolveType("range")); var currVar = emitter.CurrentMethod.Scope.Introduce("int", emitter.ResolveType("int"), Item.Data); // preface: range = ..., range.reset Iterable.Compile(emitter); emitter.EmitSaveVariable(rangeVar); emitter.EmitLoadVariable(rangeVar); emitter.EmitCall(emitter.FindMethod("range", "reset")); // set key if exists if(Key != null) { emitter.EmitLoadInt(-1); emitter.EmitSaveVariable(idxVar); } // range.next == false ? exit emitter.PlaceLabel(BodyStart); emitter.EmitLoadVariable(rangeVar); emitter.EmitCall(emitter.FindMethod("range", "next")); emitter.EmitLoadBool(false); emitter.EmitCompareEqual(); emitter.EmitBranchTrue(BodyEnd); // curr = range.current emitter.EmitLoadVariable(rangeVar); emitter.EmitCall(emitter.FindMethod("range", "current")); emitter.EmitSaveVariable(currVar); // increment key if exists if(Key != null) { emitter.EmitLoadVariable(idxVar); emitter.EmitLoadInt(1); emitter.EmitAdd(); emitter.EmitSaveVariable(idxVar); } // body var preCurrLoop = emitter.CurrentLoop; emitter.CurrentLoop = this; Body.Compile(emitter); emitter.CurrentLoop = preCurrLoop; emitter.EmitBranch(BodyStart); emitter.PlaceLabel(BodyEnd); emitter.CurrentMethod.Scope.LeaveSubScope(); }
public override void Compile(Emitter.Emitter emitter) { var leftType = Left.GetExpressionType(emitter); var rightType = Right.GetExpressionType(emitter); var type = GetExpressionType(emitter); // concat strings if (type == "string") { Left.Compile(emitter); Right.Compile(emitter); emitter.EmitCall(emitter.FindMethod("string", "concat", "string", "string")); } // add matrices else if(type == "matrix") { Left.Compile(emitter); Right.Compile(emitter); var matrixType = typeof(MN.Matrix<double>); var method = emitter.AssemblyImport(matrixType.GetMethod("Add", new [] { matrixType } )); emitter.EmitCall(method); } // add dicts else if (type == "dict") { Left.Compile(emitter); Right.Compile(emitter); var dictType = typeof(Dict); var method = emitter.AssemblyImport(dictType.GetMethod("Add", new[] { dictType })); emitter.EmitCall(method); } // add complex numbers else if(type == "complex") { Left.Compile(emitter); if(leftType != "complex") { emitter.EmitUpcastBasicType(leftType, "float"); emitter.EmitLoadFloat(0); emitter.EmitNewObj(emitter.FindMethod("complex", ".ctor", "float", "float")); } Right.Compile(emitter); if (rightType != "complex") { emitter.EmitUpcastBasicType(rightType, "float"); emitter.EmitLoadFloat(0); emitter.EmitNewObj(emitter.FindMethod("complex", ".ctor", "float", "float")); } emitter.EmitCall(emitter.AssemblyImport(typeof(SN.Complex).GetMethod("op_Addition", new[] { typeof(SN.Complex), typeof(SN.Complex) }))); } // add floating point numbers or integers else if(type.IsAnyOf("int", "float")) { Left.Compile(emitter); emitter.EmitUpcastBasicType(leftType, type); Right.Compile(emitter); emitter.EmitUpcastBasicType(rightType, type); emitter.EmitAdd(); } // array addition else if(type.Contains("[]")) { Left.Compile(emitter); Right.Compile(emitter); var method = emitter.AssemblyImport(typeof(ArrayHelper).GetMethod("AddArrays", new[] { typeof(object), typeof(object) } )); emitter.EmitCall(method); } }