public override void Compile(Emitter.Emitter emitter) { if (emitter.CurrentLoop == null) Error(Resources.errBreakRedoOutsideLoop); emitter.EmitBranch(emitter.CurrentLoop.BodyStart); }
public override void Compile(Emitter.Emitter emitter) { // check types var leftType = Left.GetExpressionType(emitter); var rightType = Right.GetExpressionType(emitter); if (leftType != "bool" || rightType != "bool") Error(String.Format(Resources.errOperatorTypesMismatch, "||", leftType, rightType)); // create labels var labelElse = emitter.CreateLabel(); var labelEnd = emitter.CreateLabel(); Left.Compile(emitter); emitter.EmitBranchFalse(labelElse); emitter.EmitLoadBool(true); emitter.EmitBranch(labelEnd); emitter.PlaceLabel(labelElse); Right.Compile(emitter); emitter.PlaceLabel(labelEnd); }
public override void Compile(Emitter.Emitter emitter) { // check if condition is boolean var condType = Condition.GetExpressionType(emitter); MethodNode converter = null; if (condType != "bool") { try { converter = emitter.FindMethod(condType, "to_b"); } catch { Error(Resources.errBoolExpected); } } // create markers BodyStart = emitter.CreateLabel(); BodyEnd = emitter.CreateLabel(); emitter.PlaceLabel(BodyStart); // condition Condition.Compile(emitter); if (converter != null) emitter.EmitCall(converter); emitter.EmitBranchFalse(BodyEnd); // body var preCurrLoop = emitter.CurrentLoop; emitter.CurrentLoop = this; Body.Compile(emitter); emitter.CurrentLoop = preCurrLoop; // re-test condition emitter.EmitBranch(BodyStart); emitter.PlaceLabel(BodyEnd); }
public override void Compile(Emitter.Emitter emitter) { // make sure there is an array var exprType = Expression.GetExpressionType(emitter); if (!exprType.Contains("[]")) Error(Resources.errSplatArrayExpected); // define required variables var type = emitter.GetArrayItemType(exprType); var typeRef = emitter.ResolveType(type); var idx = 0; var tmpVar = emitter.CurrentMethod.Scope.Introduce(exprType, emitter.ResolveType(exprType)); // compile array Expression.Compile(emitter); emitter.EmitSaveVariable(tmpVar); foreach(var curr in Names) { // check for variable redefinition if (emitter.CurrentMethod.Scope.Exists(curr.Data)) Error(String.Format(Resources.errVariableRedefinition, curr.Data), curr); var varDecl = emitter.CurrentMethod.Scope.Introduce(type, emitter.ResolveType(type), curr.Data); var elseLabel = emitter.CreateLabel(); var endLabel = emitter.CreateLabel(); // make sure the array is not a null emitter.EmitLoadNull(); emitter.EmitLoadVariable(tmpVar); emitter.EmitCompareEqual(); emitter.EmitBranchTrue(elseLabel); // make sure there are items in the array emitter.EmitLoadInt(idx); emitter.EmitLoadVariable(tmpVar); emitter.EmitLoadArraySize(); emitter.EmitCompareLess(); emitter.EmitBranchFalse(elseLabel); // retrieve the current value emitter.EmitLoadVariable(tmpVar); emitter.EmitLoadInt(idx); if(type == "complex") { emitter.EmitLoadIndexAddress(typeRef); emitter.EmitLoadObject(typeRef); } else emitter.EmitLoadIndex(type); emitter.EmitBranch(endLabel); // or create a default emitter.PlaceLabel(elseLabel); emitter.EmitLoadDefaultValue(type); // assign the variable emitter.PlaceLabel(endLabel); emitter.EmitSaveVariable(varDecl); idx++; } }
/// <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(); }
/// <summary> /// Create iteration code for a dictionary /// </summary> /// <param name="emitter"></param> public void CompileDict(Emitter.Emitter emitter) { // check if key defined if (Key == null) Error(Resources.errDictIterKeyRequired); // make local variables only visible inside the scope emitter.CurrentMethod.Scope.EnterSubScope(); var dictVar = emitter.CurrentMethod.Scope.Introduce("dict", emitter.ResolveType("dict")); var currVar = emitter.CurrentMethod.Scope.Introduce("string[]", emitter.ResolveType("string[]")); var keyVar = emitter.CurrentMethod.Scope.Introduce("string", emitter.ResolveType("string"), Key.Data); var itemVar = emitter.CurrentMethod.Scope.Introduce("string", emitter.ResolveType("string"), Item.Data); // preface: dictVar = ...; Iterable.Compile(emitter); emitter.EmitSaveVariable(dictVar); emitter.EmitLoadVariable(dictVar); emitter.EmitCall(emitter.FindMethod("dict", "reset")); // dict.next == false ? exit emitter.PlaceLabel(BodyStart); emitter.EmitLoadVariable(dictVar); emitter.EmitCall(emitter.FindMethod("dict", "next")); emitter.EmitLoadBool(false); emitter.EmitCompareEqual(); emitter.EmitBranchTrue(BodyEnd); // curr = dict.current emitter.EmitLoadVariable(dictVar); emitter.EmitCall(emitter.FindMethod("dict", "current")); emitter.EmitSaveVariable(currVar); // (key, value) = curr emitter.EmitLoadVariable(currVar); emitter.EmitLoadInt(0); emitter.EmitLoadIndex("string"); emitter.EmitSaveVariable(keyVar); emitter.EmitLoadVariable(currVar); emitter.EmitLoadInt(1); emitter.EmitLoadIndex("string"); emitter.EmitSaveVariable(itemVar); // 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) { // check if condition is boolean or can be converted var condType = Condition.GetExpressionType(emitter); MethodNode converter = null; if (condType != "bool") { try { converter = emitter.FindMethod(condType, "to_b"); } catch { Error(Resources.errBoolExpected); } } FalseBlockStart = emitter.CreateLabel(); // condition Condition.Compile(emitter); if (converter != null) emitter.EmitCall(converter); emitter.EmitBranchFalse(FalseBlockStart); // "true" body TrueBlock.Compile(emitter); // there is a false block? if(FalseBlock != null) { // create a jump FalseBlockEnd = emitter.CreateLabel(); emitter.EmitBranch(FalseBlockEnd); emitter.PlaceLabel(FalseBlockStart); // "false" body FalseBlock.Compile(emitter); emitter.PlaceLabel(FalseBlockEnd); } else { // put the 'nop' after the condition body emitter.PlaceLabel(FalseBlockStart); } }