public static void make_dotStep(CompileEnv env, ASBinCode.rtti.ClassMember member, ASTool.Token token, StackSlotAccessor eax, RightValueBase rvObj ) { OpStep op = new OpStep( member.bindField is MethodGetterBase ? OpCode.access_method : OpCode.access_dot , new SourceToken(token.line, token.ptr, token.sourceFile)); RightValueBase field = (RightValueBase)member.bindField; op.reg = eax; eax._isDotAccessTarget = true; op.regType = eax.valueType; op.arg1 = rvObj; op.arg1Type = rvObj.valueType; op.arg2 = field; op.arg2Type = member.valueType; env.block.opSteps.Add(op); }
private void build_void(CompileEnv env, RightValueBase cls, ASTool.AS3.Expr.AS3ExprStep step, Builder builder) { OpStep opnewclass = new OpStep(OpCode.new_instance_class, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); opnewclass.arg1 = cls; opnewclass.arg1Type = RunTimeDataType.rt_void; StackSlotAccessor _eax = env.createASTRegister(step.Arg1.Reg); _eax.setEAXTypeWhenCompile(RunTimeDataType.rt_void); opnewclass.reg = _eax; opnewclass.regType = RunTimeDataType.rt_void; OpStep opMakeArgs = new OpStep(OpCode.prepare_constructor_class_argement, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); opMakeArgs.arg1 = cls; opMakeArgs.arg1Type = RunTimeDataType.rt_void; env.block.opSteps.Add(opMakeArgs); if (step.Arg3 != null) { List <ASTool.AS3.Expr.AS3DataStackElement> args = (List <ASTool.AS3.Expr.AS3DataStackElement>)step.Arg3.Data.Value; for (int i = 0; i < args.Count; i++) { ASTool.AS3.Expr.AS3DataStackElement argData = args[i]; RightValueBase arg = builds.ExpressionBuilder.getRightValue(env, argData, step.token, builder); //***参数准备*** OpStep opPushArgs = new OpStep(OpCode.push_parameter_class, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); opPushArgs.arg1 = arg; opPushArgs.arg1Type = arg.valueType; opPushArgs.arg2 = new ASBinCode.rtData.RightValue(new ASBinCode.rtData.rtInt(i)); opPushArgs.arg2Type = RunTimeDataType.rt_int; env.block.opSteps.Add(opPushArgs); } } env.block.opSteps.Add(opnewclass); }
public void buildAS3Throw(CompileEnv env, ASTool.AS3.AS3Throw as3throw, Builder builder) { if (as3throw.Exception != null) { var testV = ExpressionEval.Eval(as3throw.Exception); if (testV != null && as3throw.Exception.Value.IsReg) { OpStep op = new OpStep(OpCode.raise_error, new SourceToken(as3throw.Token.line, as3throw.Token.ptr, as3throw.Token.sourceFile)); op.arg1 = new ASBinCode.rtData.RightValue(testV); op.arg1Type = testV.rtType; op.arg2 = null; op.arg2Type = RunTimeDataType.unknown; op.reg = null; op.regType = RunTimeDataType.unknown; env.block.opSteps.Add(op); } else { builder.buildExpression(env, as3throw.Exception); OpStep op = new OpStep(OpCode.raise_error, new SourceToken(as3throw.Token.line, as3throw.Token.ptr, as3throw.Token.sourceFile)); RightValueBase lv = builds.ExpressionBuilder.getRightValue(env, as3throw.Exception.Value, as3throw.Token, builder); op.arg1 = lv; op.arg1Type = lv.valueType; op.arg2 = null; op.arg2Type = RunTimeDataType.unknown; op.reg = null; op.regType = RunTimeDataType.unknown; env.block.opSteps.Add(op); } } else { //***只有在catch块中才能throw***; int l = 0; for (int i = 0; i < env.block.opSteps.Count; i++) { if (env.block.opSteps[i].opCode == OpCode.enter_catch) { l++; } else if (env.block.opSteps[i].opCode == OpCode.quit_catch) { l--; } } if (l < 1) { throw new BuildException(as3throw.Token.line, as3throw.Token.ptr, as3throw.Token.sourceFile, "此处不能有throw;" ); } throw new BuildException(as3throw.Token.line, as3throw.Token.ptr, as3throw.Token.sourceFile, "throw必须有抛出的对象;" ); //OpStep op = new OpStep(OpCode.raise_error, new SourceToken(as3throw.Token.line, as3throw.Token.ptr, as3throw.Token.sourceFile)); //op.arg1 = null; //op.arg1Type = RunTimeDataType.unknown; //op.arg2 = null; //op.arg2Type = RunTimeDataType.unknown; //op.reg = null; //op.regType = RunTimeDataType.unknown; //env.block.opSteps.Add(op); } }
private static void build_bracket_access(CompileEnv env, ASTool.AS3.Expr.AS3ExprStep step, RightValueBase v1, Builder builder) { ASBinCode.StackSlotAccessor eax = env.createASTRegister(step.Arg1.Reg); eax.setEAXTypeWhenCompile(RunTimeDataType.rt_void); var v2 = ExpressionBuilder.getRightValue(env, step.Arg3, step.token, builder); if (v1.valueType == RunTimeDataType.rt_void ) { OpStep op = new OpStep(OpCode.bracket_access, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); op.reg = eax; eax._isDotAccessTarget = true; op.regType = eax.valueType; op.arg1 = v1; op.arg1Type = v1.valueType; op.arg2 = v2; op.arg2Type = v2.valueType; env.block.opSteps.Add(op); } else if (v1.valueType > RunTimeDataType.unknown && builder.bin.dict_Vector_type.ContainsKey(builder.getClassByRunTimeDataType(v1.valueType)) ) { ASBinCode.rtti.Class vector = builder.getClassByRunTimeDataType(v1.valueType); RunTimeDataType vt = builder.bin.dict_Vector_type[vector]; if (v2.valueType > RunTimeDataType.unknown) { v2 = ExpressionBuilder.addCastToPrimitive(env, v2, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile), builder); } if (v2.valueType == RunTimeDataType.rt_int || v2.valueType == RunTimeDataType.rt_number || v2.valueType == RunTimeDataType.rt_uint ) { v2 = ExpressionBuilder.addCastOpStep(env, v2, RunTimeDataType.rt_int, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile) , builder); eax.setEAXTypeWhenCompile(vt); { OpStep op = new OpStep(OpCode.vectorAccessor_bind, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); op.reg = eax; eax._isDotAccessTarget = true; op.regType = eax.valueType; op.arg1 = v1; op.arg1Type = v1.valueType; op.arg2 = v2; op.arg2Type = v2.valueType; env.block.opSteps.Add(op); } } else { OpStep op = new OpStep(OpCode.vectorAccessor_convertidx, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); op.reg = eax; eax._isDotAccessTarget = true; op.regType = eax.valueType; op.arg1 = v1; op.arg1Type = v1.valueType; op.arg2 = v2; op.arg2Type = v2.valueType; env.block.opSteps.Add(op); } //if (v2.valueType != RunTimeDataType.rt_int) //{ // v2=ExpressionBuilder.addCastOpStep(env, v2, RunTimeDataType.rt_int, // new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile) // , builder); //} //eax.setEAXTypeWhenCompile(vt); //eax._vector_Type = vt; //{ // OpStep op = new OpStep(OpCode.vectorAccessor_bind, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); // op.reg = eax; // op.regType = eax.valueType; // op.arg1 = v1; // op.arg1Type = v1.valueType; // op.arg2 = v2; // op.arg2Type = v2.valueType; // env.block.opSteps.Add(op); //} } else if (builder.bin.ArrayClass != null && builder.bin.ArrayClass.getRtType() == v1.valueType && (v2.valueType == RunTimeDataType.rt_int || v2.valueType == RunTimeDataType.rt_number || v2.valueType == RunTimeDataType.rt_uint ) ) { v1 = builds.ExpressionBuilder.addCastToPrimitive(env, v1, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile), builder); v2 = ExpressionBuilder.addCastOpStep(env, v2, RunTimeDataType.rt_int, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile) , builder); OpStep op = new OpStep(OpCode.arrayAccessor_bind, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); op.reg = eax; eax._isDotAccessTarget = true; op.regType = eax.valueType; op.arg1 = v1; op.arg1Type = v1.valueType; op.arg2 = v2; op.arg2Type = v2.valueType; env.block.opSteps.Add(op); } else if (v1.valueType == RunTimeDataType.rt_array && (v2.valueType == RunTimeDataType.rt_int || v2.valueType == RunTimeDataType.rt_number || v2.valueType == RunTimeDataType.rt_uint ) ) { v2 = ExpressionBuilder.addCastOpStep(env, v2, RunTimeDataType.rt_int, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile) , builder); OpStep op = new OpStep(OpCode.arrayAccessor_bind, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); op.reg = eax; eax._isDotAccessTarget = true; op.regType = eax.valueType; op.arg1 = v1; op.arg1Type = v1.valueType; op.arg2 = v2; op.arg2Type = v2.valueType; env.block.opSteps.Add(op); } else { OpStep op = new OpStep(OpCode.bracket_byname, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); op.reg = eax; eax._isDotAccessTarget = true; op.regType = eax.valueType; op.arg1 = v1; op.arg1Type = v1.valueType; op.arg2 = v2; op.arg2Type = v2.valueType; env.block.opSteps.Add(op); } }
private static void build_dot_name(CompileEnv env, ASTool.AS3.Expr.AS3ExprStep step, RightValueBase v1) { ASBinCode.StackSlotAccessor eax = env.createASTRegister(step.Arg1.Reg); eax.setEAXTypeWhenCompile(RunTimeDataType.rt_void); OpStep op = new OpStep(OpCode.access_dot_byname, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); op.reg = eax; eax._isDotAccessTarget = true; op.regType = eax.valueType; op.arg1 = v1; op.arg1Type = v1.valueType; op.arg2 = new ASBinCode.rtData.RightValue( new ASBinCode.rtData.rtString(step.Arg3.Data.Value.ToString())); op.arg2Type = RunTimeDataType.rt_string; env.block.opSteps.Add(op); }
private static void build_dot(CompileEnv env, ASTool.AS3.Expr.AS3ExprStep step, RightValueBase v1, ASBinCode.rtti.ClassMember member) { ASBinCode.StackSlotAccessor eax = env.createASTRegister(step.Arg1.Reg); eax._regMember = member; eax._regMemberSrcObj = v1; eax.setEAXTypeWhenCompile(member.valueType); make_dotStep(env, member, step.token, eax, v1); //OpStep op = new OpStep( // member.bindField is ClassMethodGetter? // OpCode.access_method // : // OpCode.access_dot // , new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); //op.reg = eax; //op.regType = eax.valueType; //op.arg1 = v1; //op.arg1Type = v1.valueType; //op.arg2 = (IRightValue)member.bindField; //new ASBinCode.rtData.RightValue(new ASBinCode.rtData.rtInt(member.index)); //op.arg2Type = member.valueType; //RunTimeDataType.rt_int; //env.block.opSteps.Add(op); }
private static void build_class(CompileEnv env, ASTool.AS3.Expr.AS3ExprStep step, RightValueBase v1, ASBinCode.rtti.Class cls, Builder builder) { if (step.Arg3.Data.FF1Type == ASTool.AS3.Expr.FF1DataValueType.identifier) { ASBinCode.rtti.ClassMember member = null; //***查找对象成员*** member = MemberFinder.findClassMember(cls, step.Arg3.Data.Value.ToString(), env, builder); if (member == null) { if (cls.dynamic && cls.staticClass != null //***编译时检查不能向Class动态加属性。 ) { //***此处编译为动态属性*** build_dot_name(env, step, v1); return; } } if (member == null) { if (step.Arg3.Data.Value.ToString() == "hasOwnProperty" ) //***这是Object原型链对象,特殊处理 { //***此处编译为动态属性*** build_dot_name(env, step, v1); return; } if (v1 is SuperPointer) { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "Attempted access of inaccessible property " + step.Arg3.Data.Value + " through a reference with static type " + ((SuperPointer)v1).thisClass.name + ".")); } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, cls.name + "对象成员" + step.Arg3.Data.Value + "未找到")); } } if (!member.isConst && env.isEval) { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "Eval时忽略非Const成员")); } build_dot(env, step, v1, member); } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "静态成员名期待一个identifier")); } }
public static ASBinCode.RunTimeValueBase Eval(ASTool.AS3.AS3Expression expression, Builder importBuilder = null ) { try { Builder builder = new Builder(new BuildOptions() { isConsoleOut = false }, true); int bid = builder.getBlockId(); if (importBuilder != null && importBuilder._currentImports.Count > 0) { List <ASBinCode.rtti.Class> imps = new List <ASBinCode.rtti.Class>(); imps.AddRange(importBuilder._currentImports.Peek()); builder._currentImports.Push(imps); bid = importBuilder.bin.blocks.Count; } CompileEnv tempEnv = new CompileEnv(new CodeBlock(bid, "temp", -65535, true), true); tempEnv.block.scope = new ASBinCode.scopes.StartUpBlockScope(); builder.buildExpressNotEval(tempEnv, expression); tempEnv.completSteps(builder); tempEnv.block.totalStackSlots = tempEnv.combieNeedStackSlots(); if (builder.buildErrors.Count == 0) { RightValueBase value = builds.ExpressionBuilder.getRightValue(tempEnv, expression.Value, expression.token, builder); if (player == null) { player = new ASRuntime.Player(null); } CSWC tempswc = new CSWC(); if (importBuilder != null) { tempswc.blocks.AddRange(importBuilder.bin.blocks); tempswc.classes.AddRange(importBuilder.bin.classes); tempswc.functions.AddRange(importBuilder.bin.functions); } tempswc.blocks.Add(tempEnv.block); Variable variableResult = new Variable("@@", tempEnv.block.scope.members.Count, tempEnv.block.id); tempEnv.block.scope.members.Add(variableResult); OpStep step = new OpStep(OpCode.assigning, new SourceToken(0, 0, "")); step.reg = variableResult; step.arg1 = value; tempEnv.block.opSteps.Add(step); tempEnv.block.instructions = tempEnv.block.opSteps.ToArray(); tempEnv.block.opSteps = null; player.loadCode(tempswc, tempEnv.block); RunTimeValueBase result = player.run(variableResult); return(result); //IRunTimeScope scope = player.run(); //if (player.runtimeError ==null) //{ // return value.getValue(scope); //} //else //{ // return null; //} } else { return(null); } } catch (BuildException) { return(null); } }
public void buildAS3ForEach(CompileEnv env, ASTool.AS3.AS3ForEach as3foreach, Builder builder) { if (!string.IsNullOrEmpty(as3foreach.label)) { //**包装一个block** ASTool.AS3.AS3Block tempblock = new ASTool.AS3.AS3Block(as3foreach.Token); tempblock.CodeList = new List <ASTool.AS3.IAS3Stmt>(); tempblock.CodeList.Add(as3foreach); tempblock.label = as3foreach.label; as3foreach.label = null; OpStep lbl_forlabel = new OpStep(OpCode.flag, new SourceToken(as3foreach.Token.line, as3foreach.Token.ptr, as3foreach.Token.sourceFile)); lbl_forlabel.flag = "LOOP_LABEL_START_" + tempblock.label; env.block.opSteps.Add(lbl_forlabel); builder.buildStmt(env, tempblock); OpStep lbl_forlabel_end = new OpStep(OpCode.flag, new SourceToken(as3foreach.Token.line, as3foreach.Token.ptr, as3foreach.Token.sourceFile)); lbl_forlabel_end.flag = "LOOP_LABEL_END_" + tempblock.label; env.block.opSteps.Add(lbl_forlabel_end); } else { int lblid = env.getLabelId(); builder.buildStmt(env, as3foreach.ForArg); LeftValueBase varvalue = null; if (as3foreach.ForArg is ASTool.AS3.AS3StmtExpressions) { ASTool.AS3.AS3StmtExpressions exprs = (ASTool.AS3.AS3StmtExpressions)as3foreach.ForArg; if (exprs.as3exprlist.Count != 1) { throw new BuildException( as3foreach.Token.line, as3foreach.Token.ptr, as3foreach.Token.sourceFile, "Syntax error: invalid for-in initializer, only 1 expression expected."); } ASTool.AS3.AS3Expression expr = exprs.as3exprlist[0]; varvalue = (LeftValueBase)ExpressionBuilder.getRightValue(env, expr.Value, expr.token, builder); } else if (as3foreach.ForArg is ASTool.AS3.AS3Variable) { ASTool.AS3.AS3Variable v = (ASTool.AS3.AS3Variable)as3foreach.ForArg; varvalue = (VariableBase)MemberFinder.find(v.Name, env, false, builder, v.token); } else { throw new BuildException( as3foreach.Token.line, as3foreach.Token.ptr, as3foreach.Token.sourceFile, "异常错误,获得的变量类型不正确"); } builder.buildExpression(env, as3foreach.ForExpr); RightValueBase enumerator = ExpressionBuilder.getRightValue(env, as3foreach.ForExpr.Value, as3foreach.ForExpr.token, builder); if (enumerator.valueType == RunTimeDataType.rt_void || enumerator.valueType < RunTimeDataType.unknown ) { enumerator = ExpressionBuilder.addCastOpStep(env, enumerator, RunTimeDataType._OBJECT, new SourceToken(as3foreach.ForExpr.token.line, as3foreach.ForExpr.token.ptr, as3foreach.ForExpr.token.sourceFile) , builder); } //Register regSaveEnumerator = env.getAdditionalRegister(); Variable varSaveEnumerator = new Variable("@saveEnumeraor_" + env.block.scope.members.Count, env.block.scope.members.Count, env.block.id); env.block.scope.members.Add(varSaveEnumerator); varSaveEnumerator.valueType = (RunTimeDataType.rt_void); { //**IEnumerator Get And Reset(); OpStep opGetEnumerator = new OpStep(OpCode.foreach_get_enumerator, new SourceToken(as3foreach.Token.line, as3foreach.Token.ptr, as3foreach.Token.sourceFile) ); opGetEnumerator.reg = varSaveEnumerator; opGetEnumerator.regType = RunTimeDataType.rt_void; opGetEnumerator.arg1 = enumerator; opGetEnumerator.arg1Type = enumerator.valueType; env.block.opSteps.Add(opGetEnumerator); } string loopstart = "LOOP_START_" + lblid; string loopbody = "LOOP_BODY_" + lblid; string loopcontinue = "LOOP_CONTINUE_" + lblid; string loopend = "LOOP_END_" + lblid; { OpStep lbl_loopstart = new OpStep(OpCode.flag, new SourceToken(as3foreach.Token.line, as3foreach.Token.ptr, as3foreach.Token.sourceFile)); lbl_loopstart.flag = loopstart; env.block.opSteps.Add(lbl_loopstart); } StackSlotAccessor eaxismovenext = env.getAdditionalRegister(); eaxismovenext.setEAXTypeWhenCompile(RunTimeDataType.rt_boolean); { //**IEnumerator MoveNext() OpStep opMoveNext = new OpStep(OpCode.enumerator_movenext, new SourceToken(as3foreach.Token.line, as3foreach.Token.ptr, as3foreach.Token.sourceFile) ); opMoveNext.reg = eaxismovenext; opMoveNext.regType = RunTimeDataType.rt_boolean; opMoveNext.arg1 = varSaveEnumerator; opMoveNext.arg1Type = varSaveEnumerator.valueType; env.block.opSteps.Add(opMoveNext); } { OpStep op = new OpStep(OpCode.if_jmp, new SourceToken(as3foreach.ForExpr.token.line, as3foreach.ForExpr.token.ptr, as3foreach.ForExpr.token.sourceFile)); op.reg = null; op.regType = RunTimeDataType.unknown; op.arg1 = eaxismovenext; op.arg1Type = eaxismovenext.valueType; op.arg2 = new ASBinCode.rtData.RightValue( new ASBinCode.rtData.rtString(loopbody)); op.arg2Type = RunTimeDataType.rt_string; env.block.opSteps.Add(op); } { ASTool.AS3.AS3StmtExpressions jumptoend = new ASTool.AS3.AS3StmtExpressions(as3foreach.Token); jumptoend.as3exprlist = new List <ASTool.AS3.AS3Expression>(); ASTool.AS3.AS3Expression expression = new ASTool.AS3.AS3Expression(as3foreach.Token); expression.exprStepList = new ASTool.AS3.Expr.AS3ExprStepList(); ASTool.AS3.Expr.AS3ExprStep step = new ASTool.AS3.Expr.AS3ExprStep(as3foreach.Token); step.Type = ASTool.AS3.Expr.OpType.GotoFlag; step.OpCode = loopend; expression.exprStepList.Add(step); jumptoend.as3exprlist.Add(expression); builder.buildStmt(env, jumptoend); } { OpStep lbl_loopbody = new OpStep(OpCode.flag, new SourceToken(as3foreach.Token.line, as3foreach.Token.ptr, as3foreach.Token.sourceFile)); lbl_loopbody.flag = loopbody; env.block.opSteps.Add(lbl_loopbody); } { RightValueBase loadValue = env.getAdditionalRegister(); ((StackSlotAccessor)loadValue).setEAXTypeWhenCompile(RunTimeDataType.rt_void); //**IEnumerator Current() OpStep opCurrent = new OpStep(OpCode.enumerator_current, new SourceToken(as3foreach.Token.line, as3foreach.Token.ptr, as3foreach.Token.sourceFile) ); opCurrent.reg = (StackSlotAccessor)loadValue; opCurrent.regType = RunTimeDataType.rt_void; opCurrent.arg1 = varSaveEnumerator; opCurrent.arg1Type = varSaveEnumerator.valueType; env.block.opSteps.Add(opCurrent); if (varvalue.valueType != RunTimeDataType.rt_void) { loadValue = ExpressionBuilder.addCastOpStep(env, loadValue, varvalue.valueType, new SourceToken(as3foreach.Token.line, as3foreach.Token.ptr, as3foreach.Token.sourceFile) , builder ); } var op = new OpStep(OpCode.assigning, new SourceToken(as3foreach.Token.line, as3foreach.Token.ptr, as3foreach.Token.sourceFile)); op.reg = varvalue; op.regType = varvalue.valueType; op.arg1 = loadValue; op.arg1Type = loadValue.valueType; op.arg2 = null; op.arg2Type = RunTimeDataType.unknown; env.block.opSteps.Add(op); } if (as3foreach.Body != null) { for (int i = 0; i < as3foreach.Body.Count; i++) { builder.buildStmt(env, as3foreach.Body[i]); } } { OpStep lbl_loopcontinue = new OpStep(OpCode.flag, new SourceToken(as3foreach.Token.line, as3foreach.Token.ptr, as3foreach.Token.sourceFile)); lbl_loopcontinue.flag = loopcontinue; env.block.opSteps.Add(lbl_loopcontinue); } { //强行跳回开始 ASTool.AS3.AS3StmtExpressions jumptostart = new ASTool.AS3.AS3StmtExpressions(as3foreach.Token); jumptostart.as3exprlist = new List <ASTool.AS3.AS3Expression>(); ASTool.AS3.AS3Expression expression = new ASTool.AS3.AS3Expression(as3foreach.Token); expression.exprStepList = new ASTool.AS3.Expr.AS3ExprStepList(); ASTool.AS3.Expr.AS3ExprStep step = new ASTool.AS3.Expr.AS3ExprStep(as3foreach.Token); step.Type = ASTool.AS3.Expr.OpType.GotoFlag; step.OpCode = loopstart; expression.exprStepList.Add(step); jumptostart.as3exprlist.Add(expression); builder.buildStmt(env, jumptostart); } { //结束标记 OpStep lbl_loopend = new OpStep(OpCode.flag, new SourceToken(as3foreach.Token.line, as3foreach.Token.ptr, as3foreach.Token.sourceFile)); lbl_loopend.flag = loopend; env.block.opSteps.Add(lbl_loopend); } { OpStep opClose = new OpStep(OpCode.enumerator_close, new SourceToken(as3foreach.Token.line, as3foreach.Token.ptr, as3foreach.Token.sourceFile)); opClose.reg = null; opClose.regType = RunTimeDataType.unknown; opClose.arg1 = varSaveEnumerator; opClose.arg1Type = RunTimeDataType.rt_void; opClose.arg2 = null; opClose.arg2Type = RunTimeDataType.rt_void; env.block.opSteps.Add(opClose); } } }