public StackSlotAccessor buildAccessThisMember(ASTool.Token matchtoken, CompileEnv env) { if (!(member is VariableBase)) { throw new BuildException(new BuildError( matchtoken.line, matchtoken.ptr, matchtoken.sourceFile, "包外数据期望一个Variable")); } VariableBase var = (VariableBase)member; var eax_member = env.getAdditionalRegister(); eax_member.setEAXTypeWhenCompile(var.valueType); OpStep op = new OpStep(OpCode.link_outpackagevairable, new SourceToken(matchtoken.line, matchtoken.ptr, matchtoken.sourceFile)); op.reg = eax_member; op.regType = eax_member.valueType; op.arg1 = var; op.arg1Type = var.valueType; op.arg2 = new ASBinCode.rtData.RightValue(new ASBinCode.rtData.rtInt(outscopeclass.classid)); op.arg2Type = RunTimeDataType.rt_int; env.block.opSteps.Add(op); return(eax_member); }
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 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); }
public LeftValueBase buildAccessThisMember(ASTool.Token matchtoken, CompileEnv env) { if ( !(classMember.bindField is VariableBase) && env.block.scope is ASBinCode.scopes.FunctionScope && env.block.scope.parentScope is ASBinCode.scopes.ObjectInstanceScope && ((ASBinCode.scopes.ObjectInstanceScope)env.block.scope.parentScope)._class == static_class._class ) { return((LeftValueBase)classMember.bindField); } else { OpStep stepInitClass = new OpStep(OpCode.init_staticclass, new SourceToken(matchtoken.line, matchtoken.ptr, matchtoken.sourceFile)); stepInitClass.arg1 = new ASBinCode.rtData.RightValue( new ASBinCode.rtData.rtInt(static_class._class.instanceClass.classid)); stepInitClass.arg1Type = static_class._class.getRtType(); env.block.opSteps.Add(stepInitClass); var _buildin_ = static_class; var eax_member = env.getAdditionalRegister(); eax_member.setEAXTypeWhenCompile(classMember.valueType); eax_member._regMember = classMember; eax_member._regMemberSrcObj = _buildin_; AccessBuilder.make_dotStep(env, classMember, matchtoken, eax_member, _buildin_); return(eax_member); } }
public void buildCatchVariable(CompileEnv env, ASTool.AS3.AS3Catch c, int i, int tryid, Builder builder) { //Variable rtVariable = // new Variable( "0"+ c.CatchVariable.Name + "_" + i + "_" + tryid // , env.block.scope.members.Count); //rtVariable.valueType = TypeReader.fromSourceCodeStr(c.CatchVariable.TypeStr, env, c.CatchVariable.token); //env.block.scope.members.Add(rtVariable); }
private void jumpTo(CompileEnv env, ASTool.AS3.AS3Try as3try, Builder builder, string label) { ASTool.AS3.AS3StmtExpressions jumptofinally = new ASTool.AS3.AS3StmtExpressions(as3try.Token); jumptofinally.as3exprlist = new List <ASTool.AS3.AS3Expression>(); ASTool.AS3.AS3Expression expression = new ASTool.AS3.AS3Expression(as3try.Token); expression.exprStepList = new ASTool.AS3.Expr.AS3ExprStepList(); ASTool.AS3.Expr.AS3ExprStep step = new ASTool.AS3.Expr.AS3ExprStep(as3try.Token); step.Type = ASTool.AS3.Expr.OpType.GotoFlag; step.OpCode = label; expression.exprStepList.Add(step); jumptofinally.as3exprlist.Add(expression); builder.buildStmt(env, jumptofinally); }
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 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 buildAS3YieldBreak(CompileEnv env, ASTool.AS3.AS3YieldBreak as3yieldbreak, Builder builder) { if (builder.buildingfunctons.Count > 0) { ASTool.AS3.AS3Function as3function = builder.buildingfunctons.Peek(); if (as3function.IsConstructor) { throw new BuildException(as3yieldbreak.Token.line, as3yieldbreak.Token.ptr, as3yieldbreak.Token.sourceFile, "构造函数不能用yield"); } OpStep opyieldbreak = new OpStep(OpCode.yield_break, new SourceToken(as3yieldbreak.Token.line, as3yieldbreak.Token.ptr, as3yieldbreak.Token.sourceFile)); env.block.opSteps.Add(opyieldbreak); } else { throw new BuildException(as3yieldbreak.Token.line, as3yieldbreak.Token.ptr, as3yieldbreak.Token.sourceFile, "yield break 只能在函数中"); } }
public void build_class(CompileEnv env, ASBinCode.rtti.Class _class, ASTool.Token token, Builder builder, StackSlotAccessor outeax, List <ASTool.AS3.Expr.AS3DataStackElement> args ) { //***查找构造函数** if (_class.constructor != null) { MethodGetterBase field = (MethodGetterBase)_class.constructor.bindField; //(Field)builder._classbuildingEnv[_class].block.scope.members[_class.constructor.index]; int blockid = field.refdefinedinblockid; var signature = builder.dictSignatures[blockid][field]; FuncCallBuilder funcbuilder = new FuncCallBuilder(); funcbuilder.createParaOp(args, signature, token, env, field, builder, true, _class); } else { OpStep opMakeArgs = new OpStep(OpCode.prepare_constructor_argement, new SourceToken(token.line, token.ptr, token.sourceFile)); opMakeArgs.arg1 = new ASBinCode.rtData.RightValue(new ASBinCode.rtData.rtInt(_class.classid)); opMakeArgs.arg1Type = RunTimeDataType.rt_int; env.block.opSteps.Add(opMakeArgs); } OpStep op = new OpStep(OpCode.new_instance, new SourceToken(token.line, token.ptr, token.sourceFile)); op.arg1 = new RightValue(new rtInt(_class.classid)); op.arg1Type = _class.getRtType(); outeax.setEAXTypeWhenCompile(_class.getRtType()); op.reg = outeax; op.regType = _class.getRtType(); env.block.opSteps.Add(op); }
public void buildInterfaceMembers(ASTool.AS3.AS3ClassInterfaceBase as3interface, Builder builder) { List <ASTool.AS3.IAS3Stmt> classstmts = as3interface.StamentsStack.Peek(); var cls = builder.buildingclasses[as3interface]; ASBinCode.CodeBlock block = new ASBinCode.CodeBlock(cls.blockid, cls.name, cls.classid, false); block.scope = new ASBinCode.scopes.ObjectInstanceScope(cls); CompileEnv env = new CompileEnv(block, false); builder._classbuildingEnv.Add(cls, env); for (int i = 0; i < classstmts.Count; i++) { buildInterfaceMember(env, classstmts[i], cls, builder); } //copyInheritsFromImplements(cls, env); }
public static ASBinCode.rtti.ClassMember findClassMember(ASBinCode.rtti.Class cls, string name, CompileEnv env, Builder builder ) { if (env.block.scope is ASBinCode.scopes.FunctionScope) { ASBinCode.scopes.FunctionScope funcscope = env.block.scope as ASBinCode.scopes.FunctionScope; if (!funcscope.function.IsAnonymous && funcscope.parentScope is ASBinCode.scopes.ObjectInstanceScope) { return(ASBinCode.ClassMemberFinder.find( cls, name, ((ASBinCode.scopes.ObjectInstanceScope)funcscope.parentScope)._class)); } } return(ASBinCode.ClassMemberFinder.find(cls, name, builder.getClassByRunTimeDataType(ASBinCode.RunTimeDataType._OBJECT) )); }
public void buildConstructor(CompileEnv env, ASTool.AS3.Expr.AS3ExprStep step, Builder builder) { if (step.OpCode == "new") { if (step.Arg1.IsReg) { ASBinCode.rtti.Class _class = null; if (step.Arg2.IsReg) { var cls = ExpressionBuilder.getRightValue(env, step.Arg2, step.token, builder); if (cls is ASBinCode.StaticClassDataGetter) { _class = builder.getClassByRunTimeDataType(cls.valueType).instanceClass; build_class(env, _class, step, builder); return; } else if (cls is MethodGetterBase) { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "Method cannot be used as a constructor.")); } else if (cls.valueType == ASBinCode.RunTimeDataType.rt_void || cls.valueType == ASBinCode.RunTimeDataType.rt_function) { //从Class对象中new build_void(env, cls, step, builder); return; } else if (cls.valueType > ASBinCode.RunTimeDataType.unknown) { _class = builder.getClassByRunTimeDataType(cls.valueType); if (_class.isInterface) { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, _class.name + " Interfaces cannot be instantiated with the new operator.")); } else if (_class.staticClass != null) { build_class(env, _class, step, builder); } else if (cls is StackSlotAccessor && ((StackSlotAccessor)cls).isFindByPath && _class.staticClass == null) { build_class(env, _class.instanceClass, step, builder); } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "类型" + cls.valueType + "不能new")); } return; } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "类型" + cls.valueType + "不能new")); } } else { //***查找对象类型 var find = TypeReader.findClassFromImports(step.Arg2.Data.Value.ToString(), builder, step.token); if (find.Count == 1) { _class = find[0]; if (_class.isInterface) { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, _class.name + " Interfaces cannot be instantiated with the new operator.")); } else if (_class.no_constructor) { } build_class(env, _class, step, builder); return; } else { var cls = ExpressionBuilder.getRightValue(env, step.Arg2, step.token, builder); if (cls is ASBinCode.StaticClassDataGetter) { _class = builder.getClassByRunTimeDataType(cls.valueType).instanceClass; build_class(env, _class, step, builder); return; } else if (cls is MethodGetterBase) { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "Method cannot be used as a constructor.")); } else if (cls.valueType == ASBinCode.RunTimeDataType.rt_void || cls.valueType == ASBinCode.RunTimeDataType.rt_function) { //从Class对象中new build_void(env, cls, step, builder); return; } else if (cls.valueType > RunTimeDataType.unknown && (builder.getClassByRunTimeDataType(cls.valueType).classid == 2 || builder.getClassByRunTimeDataType(cls.valueType).classid == 0 )) { build_void(env, cls, step, builder); return; } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "类型" + cls.valueType + "不能new")); } } } } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "编译异常 此处应该是个寄存器")); } } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "不支持的操作类型 " + step.Type + " " + step.OpCode)); } }
public void build_class(CompileEnv env, ASBinCode.rtti.Class _class, ASTool.Token token, Builder builder, StackSlotAccessor outeax, List <ASTool.AS3.Expr.AS3DataStackElement> args ) { var _cls = _class; if (_cls.staticClass == null) { _cls = _cls.instanceClass; } if (_cls.isLink_System) { OpStep stepInitClass = new OpStep(OpCode.init_staticclass, new SourceToken(token.line, token.ptr, token.sourceFile)); stepInitClass.arg1 = new ASBinCode.rtData.RightValue( new ASBinCode.rtData.rtInt(_cls.classid)); stepInitClass.arg1Type = _cls.staticClass.getRtType(); env.block.opSteps.Add(stepInitClass); } //***查找构造函数** if (_class.constructor != null) { MethodGetterBase field = (MethodGetterBase)_class.constructor.bindField; //(Field)builder._classbuildingEnv[_class].block.scope.members[_class.constructor.index]; int blockid = field.refdefinedinblockid; var signature = builder.dictSignatures[blockid][field]; FuncCallBuilder funcbuilder = new FuncCallBuilder(); OpStep opMakeArgs = null; funcbuilder.createParaOp(out opMakeArgs, args, signature, token, env, field, builder, true, _class); if (_cls.isLink_System) { if (signature.parameters.Count == 0) { opMakeArgs.opCode = OpCode.prepare_constructor_argement_linksystem; opMakeArgs.memregid1 = 0; } else { bool canconvert = true; for (int i = 0; i < signature.parameters.Count; i++) { if (signature.parameters[i].defaultValue != null || signature.parameters[i].isPara) { canconvert = false; } } if (canconvert) { opMakeArgs.opCode = OpCode.prepare_constructor_argement_linksystem; opMakeArgs.memregid1 = (short)signature.parameters.Count; } } } } else { OpStep opMakeArgs = new OpStep(OpCode.prepare_constructor_argement, new SourceToken(token.line, token.ptr, token.sourceFile)); opMakeArgs.arg1 = new ASBinCode.rtData.RightValue(new ASBinCode.rtData.rtInt(_class.classid)); opMakeArgs.arg1Type = RunTimeDataType.rt_int; env.block.opSteps.Add(opMakeArgs); if (_cls.isLink_System) { opMakeArgs.opCode = OpCode.prepare_constructor_argement_linksystem; opMakeArgs.memregid1 = 0; } } OpStep op = new OpStep(OpCode.new_instance, new SourceToken(token.line, token.ptr, token.sourceFile)); op.arg1 = new RightValue(new rtInt(_class.classid)); op.arg1Type = _class.getRtType(); outeax.setEAXTypeWhenCompile(_class.getRtType()); op.reg = outeax; op.regType = _class.getRtType(); env.block.opSteps.Add(op); }
private void buildInterfaceMember(CompileEnv env, ASTool.AS3.IAS3Stmt stmt, ASBinCode.rtti.Class cls, Builder builder ) { if (stmt is ASTool.AS3.AS3Block) { ASTool.AS3.AS3Block as3block = (ASTool.AS3.AS3Block)stmt; for (int i = 0; i < as3block.CodeList.Count; i++) { buildInterfaceMember(env, as3block.CodeList[i], cls, builder); } } else if (stmt is ASTool.AS3.AS3Function) { ASTool.AS3.AS3Function as3function = (ASTool.AS3.AS3Function)stmt; { if (!as3function.IsAnonymous) { //List<ASBinCode.rtti.ClassMember> tooverridefunctions = new List<ASBinCode.rtti.ClassMember>(); string funcname = as3function.Name; if (as3function.IsGet || as3function.IsSet) { funcname = "@" + as3function.Name + (as3function.IsGet ? "_get" : "_set"); } //for (int j = 0; j < cls.classMembers.Count; j++) //{ // if (cls.classMembers[j].name == funcname //as3function.Name // && // ( // cls.classMembers[j].inheritFrom == null // || // (cls.classMembers[j].isPublic && as3function.Access.IsPublic // ) // ) // && // ( // cls.classMembers[j].inheritFrom != null // && // !cls.classMembers[j].inheritFrom.classMembers[j].isConstructor // ) // ) // { // if (as3function.Access.IsOverride // ) // { // if (!(cls.classMembers[j].bindField is ClassMethodGetter) // || // cls.classMembers[j].inheritFrom.classMembers[j].isConstructor // ) // { // throw new BuildException( // new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, // "Method marked override must override another method.") // ); // } // if (cls.classMembers[j].isFinal) // { // throw new BuildException( // new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, // "Cannot redefine a final method.") // ); // } // tooverridefunctions.Add(cls.classMembers[j]); // continue; // } // if (cls.classMembers[j].inheritFrom == null // ) // { // throw new BuildException( // new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, // "重复的类成员:" + as3function.Name) // ); // } // else // { // throw new BuildException( // new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, // "Overriding a function that is not marked for override") // ); // } // } //} if (as3function.Access.IsStatic) { throw new BuildException( new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, "The static attribute may be used only on definitions inside a class.") ); } if (as3function.Access.IsOverride) { throw new BuildException( new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, "The override attribute can only be used on a method defined in a class.") ); } //***非访问器*** if (!as3function.IsGet && !as3function.IsSet) { ASBinCode.rtti.ClassMember member = new ASBinCode.rtti.ClassMember(as3function.Name, cls, new InterfaceMethodGetter(as3function.Name, cls, env.block.id) ); member.setTypeWhenCompile(RunTimeDataType.rt_function); member.isInternal = as3function.Access.IsInternal; member.isPrivate = as3function.Access.IsPrivate; member.isProtectd = as3function.Access.IsProtected; member.isPublic = as3function.Access.IsPublic; member.isStatic = as3function.Access.IsStatic; member.isConst = true; member.isOverride = as3function.Access.IsOverride; member.isFinal = as3function.Access.IsFinal; member.isGetter = as3function.IsGet; member.isSetter = as3function.IsSet; member.isConstructor = as3function.IsConstructor; if (member.isPrivate) { ((MethodGetterBase)member.bindField).setNotReadVirtual(); } int s = 0; if (member.isPrivate) { s++; } if (member.isPublic) { s++; } if (member.isProtectd) { s++; } if (member.isInternal) { s++; } if (s != 0) { throw new BuildException( new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, "Members of an interface cannot be declared public, private, protected, or internal.") ); } member.isPublic = true; if (as3function.FunctionBody.Nodes.Count > 0) { throw new BuildException( new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, "Methods defined in an interface must not have a body.") ); } cls.classMembers.Add(member); builder._buildingmembers.Add(member, as3function); } else { ASBinCode.rtti.ClassMember member = new ASBinCode.rtti.ClassMember("@" + as3function.Name + (as3function.IsGet ? "_get" : "_set"), cls, new InterfaceMethodGetter("@" + as3function.Name + (as3function.IsGet ? "_get" : "_set"), cls, env.block.id) ); member.setTypeWhenCompile(RunTimeDataType.rt_function); member.isInternal = as3function.Access.IsInternal; member.isPrivate = as3function.Access.IsPrivate; member.isProtectd = as3function.Access.IsProtected; member.isPublic = as3function.Access.IsPublic; member.isStatic = as3function.Access.IsStatic; member.isConst = true; member.isOverride = as3function.Access.IsOverride; member.isFinal = as3function.Access.IsFinal; member.isGetter = as3function.IsGet; member.isSetter = as3function.IsSet; member.isConstructor = as3function.IsConstructor; if (member.isGetter && member.isSetter) { throw new BuildException( new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, "不能同时是getter和setter") ); } int s = 0; if (member.isPrivate) { s++; } if (member.isPublic) { s++; } if (member.isProtectd) { s++; } if (member.isInternal) { s++; } if (s != 0) { throw new BuildException( new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, "Members of an interface cannot be declared public, private, protected, or internal.") ); } member.isPublic = true; if (as3function.FunctionBody.Nodes.Count > 0) { throw new BuildException( new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, "Methods defined in an interface must not have a body.") ); } cls.classMembers.Add(member); builder._buildingmembers.Add(member, as3function); //***查找ClassPropertyGetter**** ClassPropertyGetter pg = null; for (int i = 0; i < cls.classMembers.Count; i++) { if (cls.classMembers[i].name == as3function.Name && cls.classMembers[i].inheritFrom == null) { if (cls.classMembers[i].bindField is ClassPropertyGetter) { pg = (ClassPropertyGetter)cls.classMembers[i].bindField; if (member.isGetter && pg.getter != null && cls.classMembers[pg.getter.indexOfMembers].inheritFrom == null ) { throw new BuildException( new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, "属性访问器重复") ); } else if (member.isSetter && pg.setter != null && cls.classMembers[pg.setter.indexOfMembers].inheritFrom == null ) { throw new BuildException( new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, "属性设置器重复") ); } } else { throw new BuildException( new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, "期望一个属性") ); } } } if (pg == null) { pg = new ClassPropertyGetter(as3function.Name, cls, cls.classMembers.Count); ASBinCode.rtti.ClassMember m = new ASBinCode.rtti.ClassMember(as3function.Name, cls, pg); cls.classMembers.Add(m); m.isPublic = true; m.isStatic = member.isStatic; } if (member.isGetter) { pg.getter = (MethodGetterBase)member.bindField; } else { pg.setter = (MethodGetterBase)member.bindField; } } } else { throw new BuildException( new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, "'function' is not allowed here") ); } } } else if (stmt is ASTool.AS3.AS3Variable) { //字段 数据成员 throw new BuildException( new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, "A 'var' declaration is not permitted in an interface.") ); // } else if (stmt is ASTool.AS3.AS3Const) { throw new BuildException( new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, "A 'const' declaration is not permitted in an interface.") ); } else { throw new BuildException( new BuildError(stmt.Token.line, stmt.Token.ptr, stmt.Token.sourceFile, "接口成员中不能出现" + stmt) ); } }
public void buildAS3IF(CompileEnv env, ASTool.AS3.AS3IF as3if, Builder builder) { if (!string.IsNullOrEmpty(as3if.label)) { //**包装一个block** ASTool.AS3.AS3Block tempblock = new ASTool.AS3.AS3Block(as3if.Token); tempblock.CodeList = new List <ASTool.AS3.IAS3Stmt>(); tempblock.CodeList.Add(as3if); tempblock.label = as3if.label; as3if.label = null; builder.buildStmt(env, tempblock); } else { //***先编译条件*** builder.buildStmt(env, as3if.Condition); //**取判断条件*** ASTool.AS3.AS3Expression expr = as3if.Condition.as3exprlist[as3if.Condition.as3exprlist.Count - 1]; //if true goto TRUE_LBL //*** //goto IF_END_LBL //TRUE_LBL //*** //IF_END_LBL string truelabel = env.makeLabel("IF_TRUE"); string endlabel = env.makeLabel("IF_END"); { ASTool.AS3.AS3StmtExpressions conditionsJump = new ASTool.AS3.AS3StmtExpressions(as3if.Condition.Token); ASTool.AS3.AS3Expression expression = new ASTool.AS3.AS3Expression(as3if.Condition.Token); expression.exprStepList = new ASTool.AS3.Expr.AS3ExprStepList(); ASTool.AS3.Expr.AS3ExprStep step = new ASTool.AS3.Expr.AS3ExprStep(as3if.Token); step.Type = ASTool.AS3.Expr.OpType.IF_GotoFlag; step.OpCode = truelabel; step.Arg1 = expr.Value; expression.exprStepList.Add(step); conditionsJump.as3exprlist = new List <ASTool.AS3.AS3Expression>(); conditionsJump.as3exprlist.Add(expression); builder.buildStmt(env, conditionsJump); } { //false部分 if (as3if.FalsePass != null) { for (int i = 0; i < as3if.FalsePass.Count; i++) { builder.buildStmt(env, as3if.FalsePass[i]); } } //跳转到end; ASTool.AS3.AS3StmtExpressions jumptoend = new ASTool.AS3.AS3StmtExpressions(as3if.Token); jumptoend.as3exprlist = new List <ASTool.AS3.AS3Expression>(); ASTool.AS3.AS3Expression expression = new ASTool.AS3.AS3Expression(as3if.Token); expression.exprStepList = new ASTool.AS3.Expr.AS3ExprStepList(); ASTool.AS3.Expr.AS3ExprStep step = new ASTool.AS3.Expr.AS3ExprStep(as3if.Token); step.Type = ASTool.AS3.Expr.OpType.GotoFlag; step.OpCode = endlabel; expression.exprStepList.Add(step); jumptoend.as3exprlist.Add(expression); builder.buildStmt(env, jumptoend); //**写入true标记 OpStep lbl_true = new OpStep(OpCode.flag, new SourceToken(as3if.Token.line, as3if.Token.ptr, as3if.Token.sourceFile)); lbl_true.flag = truelabel; env.block.opSteps.Add(lbl_true); } { //true部分 if (as3if.TruePass != null) { for (int i = 0; i < as3if.TruePass.Count; i++) { builder.buildStmt(env, as3if.TruePass[i]); } } //**写入end标记 OpStep lbl_end = new OpStep(OpCode.flag, new SourceToken(as3if.Token.line, as3if.Token.ptr, as3if.Token.sourceFile)); lbl_end.flag = endlabel; env.block.opSteps.Add(lbl_end); } } }
public static ASBinCode.IMember find(string name, CompileEnv env, bool isStaticMember, Builder builder, ASTool.Token token) { //List<IScope> findpath = new List<IScope>(); //List<IScope> outscopes = new List<IScope>();//查找顺序,最后查找包外代码 //Dictionary<IScope, ASBinCode.rtti.Class> finderclass = new Dictionary<IScope, ASBinCode.rtti.Class>(); //{ // ASBinCode.rtti.Class defineClass = null; // IScope s = env.block.scope; // while (s !=null) // { // if (s is ASBinCode.scopes.ObjectInstanceScope) // { // ASBinCode.rtti.Class cls = ((ASBinCode.scopes.ObjectInstanceScope)s)._class; // if (isStaticMember && cls.staticClass != null) // { // cls = cls.staticClass; // } // if (defineClass == null) // { // defineClass = cls; // if (cls.mainClass != null) // { // defineClass = cls.mainClass; // } // } // } // finderclass.Add(s,defineClass); // if (s is ASBinCode.scopes.OutPackageMemberScope && !(ReferenceEquals(s,env.block.scope))) // { // outscopes.Add(s); // } // else // { // findpath.Add(s); // } // s = s.parentScope; // } // findpath.AddRange(outscopes); //} //ASBinCode.IScope scope = null; //for (int j = 0; j < findpath.Count; j++) //{ // scope = findpath[j]; // if (scope is ASBinCode.scopes.ObjectInstanceScope) // { // //查找类方法 // ASBinCode.rtti.Class cls = ((ASBinCode.scopes.ObjectInstanceScope)scope)._class; // var fm = ASBinCode.ClassMemberFinder.find(cls, name, finderclass[scope]); // if (fm != null) // { // return fm.bindField; // } // } // if (!(scope is ASBinCode.scopes.OutPackageMemberScope) // || // ( // finderclass[scope] == null // || // ((ASBinCode.scopes.OutPackageMemberScope)scope).mainclass == finderclass[scope] // ) // ) // { // //从后往前找。可解决catch块同名变量e问题 // for (int i = scope.members.Count - 1; i >= 0; i--) // { // if (scope.members[i].name == name // ) // { // return scope.members[i].clone(); // } // } // } //} bool skipoutpackagescope = false; ASBinCode.rtti.Class defineClass = null; ASBinCode.IScope scope = env.block.scope; while (scope != null) { if (scope is ASBinCode.scopes.ObjectInstanceScope) { //查找类方法 ASBinCode.rtti.Class cls = ((ASBinCode.scopes.ObjectInstanceScope)scope)._class; if (defineClass == null) { defineClass = cls; } if (!isStaticMember && cls.staticClass == null) { defineClass = defineClass.instanceClass; skipoutpackagescope = true; break; } else { var fm = ASBinCode.ClassMemberFinder.find(cls, name, defineClass); if (fm != null) { return(fm.bindField); } else { break; } } } if (!(scope is ASBinCode.scopes.OutPackageMemberScope) || ( defineClass == null || ((ASBinCode.scopes.OutPackageMemberScope)scope).mainclass == defineClass ) ) { //从后往前找。可解决catch块同名变量e问题 for (int i = scope.members.Count - 1; i >= 0; i--) { if (scope.members[i].name == name ) { return(scope.members[i].clone()); } } } scope = scope.parentScope; } //***如果成员未找到,查找@__buildin__// if (!env.isEval) { var buildin = TypeReader.findClassFromImports("@__buildin__", builder, token); if (buildin.Count == 1) { var bi = buildin[0].staticClass; var member = ClassMemberFinder.find(bi, name, bi); if (member != null && !(member.bindField is ClassPropertyGetter) && member.inheritFrom == null && member.name != "Object" ) { FindStaticMember sm = new FindStaticMember(); sm.classMember = member; sm.static_class = new StaticClassDataGetter(bi); return(sm); //return member.bindField; } } } //***在静态成员中查找*** var findstaticclass = defineClass; while (findstaticclass != null && findstaticclass.staticClass != null) { var bi = findstaticclass.staticClass; var member = ClassMemberFinder.find(bi, name, defineClass.staticClass); if (member != null) { if (member != null && member.bindField is ClassPropertyGetter && name == "prototype") { throw new BuildException(token.line, token.ptr, token.sourceFile, "Access of possibly undefined property prototype."); } FindStaticMember sm = new FindStaticMember(); sm.classMember = member; sm.static_class = new StaticClassDataGetter(bi); return(sm); //return member.bindField; } findstaticclass = findstaticclass.super; } if (skipoutpackagescope) { return(null); } if (defineClass != null && defineClass.mainClass != null) { defineClass = defineClass.mainClass; } //***在包外代码中查找**** if (defineClass != null && defineClass.staticClass != null) { IScope outpackagescope = null; if (defineClass.mainClass == null) { outpackagescope = builder._class_outScopeBlock[defineClass].scope; } else { outpackagescope = builder._class_outScopeBlock[defineClass.mainClass].scope; } for (int i = outpackagescope.members.Count - 1; i >= 0; i--) { if (outpackagescope.members[i].name == name ) { //return outpackagescope.members[i].clone(); FindOutPackageScopeMember fo = new FindOutPackageScopeMember(); fo.member = outpackagescope.members[i].clone(); fo.outscopeclass = ((ASBinCode.scopes.OutPackageMemberScope)outpackagescope).mainclass; return(fo); //return fo; } } } return(null); }
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 buildAS3Break(CompileEnv env, ASTool.AS3.AS3Break as3break) { if (string.IsNullOrEmpty(as3break.breakFlag)) { //throw new BuildException(as3break.Token.line, as3break.Token.ptr, as3break.Token.sourceFile, // "语句关联break尚未实现"); //***向上查找 //int l = 0; Stack <string> flagstack = new Stack <string>(); for (int i = env.block.opSteps.Count - 1; i >= 0; i--) { var s = env.block.opSteps[i]; if (s.opCode == OpCode.flag) { if (s.flag.StartsWith("LOOP_END_") || s.flag.StartsWith("SWITCH_END_")) { flagstack.Push(s.flag); //l--; } if (s.flag.StartsWith("LOOP_START_") || s.flag.StartsWith("SWITCH_START_")) { if (flagstack.Count == 0) { string header = null; if (s.flag.StartsWith("LOOP_START_")) { header = "LOOP_END_"; } else { header = "SWITCH_END_"; } string id = s.flag.Substring(header.Length + 2); //label标记跳转 OpStep op = new OpStep(OpCode.jmp, new SourceToken(as3break.Token.line, as3break.Token.ptr, as3break.Token.sourceFile)); op.reg = null; op.regType = RunTimeDataType.unknown; op.arg1 = new ASBinCode.rtData.RightValue( new ASBinCode.rtData.rtString(header + id)); op.arg1Type = RunTimeDataType.rt_string; op.arg2 = null; op.arg2Type = RunTimeDataType.unknown; env.block.opSteps.Add(op); return; } else { string p = flagstack.Pop(); if ((p.StartsWith("LOOP_END_") && s.flag.StartsWith("LOOP_START_")) || (p.StartsWith("SWITCH_END_") && s.flag.StartsWith("SWITCH_START_"))) { } else { throw new BuildException(as3break.Token.line, as3break.Token.ptr, as3break.Token.sourceFile, "switch或loop开关不匹配"); } //l++; } } } } throw new BuildException(as3break.Token.line, as3break.Token.ptr, as3break.Token.sourceFile, "break的关联块未找到"); } else { //语句块break int l = 0; for (int i = 0; i < env.block.opSteps.Count; i++) { var s = env.block.opSteps[i]; if (s.opCode == OpCode.flag) { if (s.flag == "Label" + env.labelblocks + "_End_" + as3break.breakFlag) { l--; } else if (s.flag == "Label" + env.labelblocks + "_Start_" + as3break.breakFlag) { l++; } } } if (l < 1) { throw new BuildException(as3break.Token.line, as3break.Token.ptr, as3break.Token.sourceFile, "break的关联标记[" + as3break.breakFlag + "]未找到"); } //label标记跳转 OpStep op = new OpStep(OpCode.jmp, new SourceToken(as3break.Token.line, as3break.Token.ptr, as3break.Token.sourceFile)); op.reg = null; op.regType = RunTimeDataType.unknown; op.arg1 = new ASBinCode.rtData.RightValue( new ASBinCode.rtData.rtString("Label" + env.labelblocks + "_End_" + as3break.breakFlag)); op.arg1Type = RunTimeDataType.rt_string; op.arg2 = null; op.arg2Type = RunTimeDataType.unknown; env.block.opSteps.Add(op); } }
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); } } }
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); } }
public void buildAS3Switch(CompileEnv env, ASTool.AS3.AS3Switch as3switch, Builder builder) { if (!string.IsNullOrEmpty(as3switch.label)) { //**包装一个block** ASTool.AS3.AS3Block tempblock = new ASTool.AS3.AS3Block(as3switch.Token); tempblock.CodeList = new List <ASTool.AS3.IAS3Stmt>(); tempblock.CodeList.Add(as3switch); tempblock.label = as3switch.label; as3switch.label = null; builder.buildStmt(env, tempblock); } else { //***先编译条件*** ASTool.AS3.AS3StmtExpressions expressions = new ASTool.AS3.AS3StmtExpressions(as3switch.Token); expressions.as3exprlist = new List <ASTool.AS3.AS3Expression>(); expressions.as3exprlist.Add(as3switch.Expr); builder.buildStmt(env, expressions); //**取判断条件*** ASTool.AS3.AS3Expression expr = as3switch.Expr; int defaults = 0; for (int i = 0; i < as3switch.CaseList.Count; i++) { ASTool.AS3.AS3SwitchCase c = as3switch.CaseList[i]; if (c.IsDefault) { defaults++; } if (defaults > 1) { throw new BuildException(c.token.line, c.token.ptr, c.token.sourceFile, "switch只能有1个default:"); } } List <string> switchlabels = new List <string>(); for (int i = 0; i < as3switch.CaseList.Count; i++) { ASTool.AS3.AS3SwitchCase c = as3switch.CaseList[i]; if (!c.IsDefault) { switchlabels.Add(env.makeLabel("SWITCH_CASE")); } else { switchlabels.Add(env.makeLabel("SWITCH_DEFAULT")); } } for (int i = 0; i < as3switch.CaseList.Count; i++) { ASTool.AS3.AS3SwitchCase c = as3switch.CaseList[i]; if (!c.IsDefault) { RunTimeValueBase v = ExpressionEval.Eval(c.Condition); if (v != null && c.Condition.Value.IsReg) { OpStep op = new OpStep(OpCode.assigning, new SourceToken(c.token.line, c.token.ptr, c.token.sourceFile)); var eax = env.createASTRegister(c.Condition.Value.Reg); eax.setEAXTypeWhenCompile(v.rtType); op.reg = eax; op.regType = eax.valueType; op.arg1 = new ASBinCode.rtData.RightValue(v); op.arg1Type = v.rtType; env.block.opSteps.Add(op); } else { ASTool.AS3.AS3StmtExpressions caseExpr = new ASTool.AS3.AS3StmtExpressions(c.token); caseExpr.as3exprlist = new List <ASTool.AS3.AS3Expression>(); caseExpr.as3exprlist.Add(c.Condition); builder.buildStmt(env, caseExpr); } { ASTool.AS3.Expr.AS3ExprStep step = new ASTool.AS3.Expr.AS3ExprStep(c.token); step.Type = ASTool.AS3.Expr.OpType.LogicEQ; step.OpCode = "=="; step.Arg1 = c.holdreg; step.Arg2 = expr.Value; step.Arg3 = c.Condition.Value; ASTool.AS3.AS3StmtExpressions compare = new ASTool.AS3.AS3StmtExpressions(c.token); ASTool.AS3.AS3Expression expression = new ASTool.AS3.AS3Expression(c.token); expression.exprStepList = new ASTool.AS3.Expr.AS3ExprStepList(); expression.exprStepList.Add(step); expression.Value = c.holdreg; compare.as3exprlist = new List <ASTool.AS3.AS3Expression>(); compare.as3exprlist.Add(expression); builder.buildStmt(env, compare); } { ASTool.AS3.AS3StmtExpressions conditionsJump = new ASTool.AS3.AS3StmtExpressions(c.token); ASTool.AS3.AS3Expression expression = new ASTool.AS3.AS3Expression(c.token); expression.exprStepList = new ASTool.AS3.Expr.AS3ExprStepList(); ASTool.AS3.Expr.AS3ExprStep step = new ASTool.AS3.Expr.AS3ExprStep(c.token); step.Type = ASTool.AS3.Expr.OpType.IF_GotoFlag; step.OpCode = switchlabels[i]; step.Arg1 = c.holdreg; expression.exprStepList.Add(step); conditionsJump.as3exprlist = new List <ASTool.AS3.AS3Expression>(); conditionsJump.as3exprlist.Add(expression); builder.buildStmt(env, conditionsJump); } } else { ASTool.AS3.AS3StmtExpressions jump = new ASTool.AS3.AS3StmtExpressions(c.token); ASTool.AS3.AS3Expression expression = new ASTool.AS3.AS3Expression(c.token); expression.exprStepList = new ASTool.AS3.Expr.AS3ExprStepList(); ASTool.AS3.Expr.AS3ExprStep step = new ASTool.AS3.Expr.AS3ExprStep(c.token); step.Type = ASTool.AS3.Expr.OpType.GotoFlag; step.OpCode = switchlabels[i]; expression.exprStepList.Add(step); jump.as3exprlist = new List <ASTool.AS3.AS3Expression>(); jump.as3exprlist.Add(expression); builder.buildStmt(env, jump); } } int lblid = env.getLabelId(); OpStep lbl_case_start = new OpStep(OpCode.flag, new SourceToken(as3switch.Token.line, as3switch.Token.ptr, as3switch.Token.sourceFile)); lbl_case_start.flag = "SWITCH_START_" + lblid; env.block.opSteps.Add(lbl_case_start); for (int i = 0; i < as3switch.CaseList.Count; i++) { ASTool.AS3.AS3SwitchCase c = as3switch.CaseList[i]; //if (!c.IsDefault) { OpStep lbl_case = new OpStep(OpCode.flag, new SourceToken(c.token.line, c.token.ptr, c.token.sourceFile)); lbl_case.flag = switchlabels[i]; env.block.opSteps.Add(lbl_case); } if (c.Body != null) { for (int j = 0; j < c.Body.Count; j++) { builder.buildStmt(env, c.Body[j]); } } } OpStep lbl_case_end = new OpStep(OpCode.flag, new SourceToken(as3switch.Token.line, as3switch.Token.ptr, as3switch.Token.sourceFile)); lbl_case_end.flag = "SWITCH_END_" + lblid; env.block.opSteps.Add(lbl_case_end); } }
public void buildAccess(CompileEnv env, ASTool.AS3.Expr.AS3ExprStep step, Builder builder) { if (step.OpCode == ".") { if (step.Arg1.IsReg) { ASBinCode.RightValueBase v1 = ExpressionBuilder.getRightValue(env, step.Arg2, step.token, builder); if (step.Arg3.Data.FF1Type == ASTool.AS3.Expr.FF1DataValueType.identifier) { if (step.Arg3.Data.Value.ToString() == "null") { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "Syntax error: 'null' is not allowed here")); } } //ASBinCode.IRightValue v2 = ExpressionBuilder.getRightValue(env, step.Arg3, step.token, builder); if (v1 is ASBinCode.StaticClassDataGetter) { if (step.Arg3.Data.FF1Type == ASTool.AS3.Expr.FF1DataValueType.identifier) { ASBinCode.StaticClassDataGetter sd = (ASBinCode.StaticClassDataGetter)v1; var cls = sd._class; build_class(env, step, v1, cls, builder); } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "静态成员名期待一个identifier")); } } else if (v1 is PackagePathGetter) { if (step.Arg3.Data.FF1Type == ASTool.AS3.Expr.FF1DataValueType.identifier) { PackagePathGetter pd = (PackagePathGetter)v1; string path = pd.path + "." + step.Arg3.Data.Value.ToString(); //**尝试查找类*** var found = TypeReader.findClassFromProject(path, builder, step.token); if (found.Count == 1) { var item = found[0]; OpStep stepInitClass = new OpStep(OpCode.init_staticclass, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); stepInitClass.arg1 = new ASBinCode.rtData.RightValue( new ASBinCode.rtData.rtInt(item.classid)); stepInitClass.arg1Type = item.staticClass.getRtType(); env.block.opSteps.Add(stepInitClass); ASBinCode.StackSlotAccessor eax = env.createASTRegister(step.Arg1.Reg); eax.setEAXTypeWhenCompile(item.staticClass.getRtType()); eax.isFindByPath = true; //eax._pathGetter = new PackagePathGetter(path); OpStep op = new OpStep(OpCode.assigning, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); op.reg = eax; op.arg1 = new StaticClassDataGetter(item.staticClass); op.arg1Type = item.staticClass.getRtType(); env.block.opSteps.Add(op); } else if (found.Count > 1) { throw new BuildException(step.token.line, step.token.ptr, step.token.sourceFile, "类型" + path + "不明确." ); } else { //没找到 PackagePathGetter g = new PackagePathGetter(path); ASBinCode.StackSlotAccessor eax = env.createASTRegister(step.Arg1.Reg); eax.setEAXTypeWhenCompile(RunTimeDataType.unknown); eax._pathGetter = g; } } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "静态成员名期待一个identifier")); } } else if (v1 is ThisPointer && v1.valueType == RunTimeDataType.rt_void) { //throw new BuildException( // new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, // "动态查找成员 还没弄")); if (step.Arg3.Data.FF1Type == ASTool.AS3.Expr.FF1DataValueType.identifier) { build_dot_name(env, step, v1); } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "静态成员名期待一个identifier")); } } else if (v1.valueType == RunTimeDataType.unknown) { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "遇到了unknown类型")); } else if (v1.valueType > RunTimeDataType.unknown) { ASBinCode.rtti.Class cls = builder.getClassByRunTimeDataType(v1.valueType); if (cls == null) { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "编译异常 类型" + v1.valueType + "未找到")); } else { build_class(env, step, v1, cls, builder); } } else { if (v1.valueType != RunTimeDataType.rt_void && v1.valueType < RunTimeDataType.unknown) { if ( builder.bin != null && builder.bin.primitive_to_class_table[v1.valueType] != null) { var cls = builder.bin.primitive_to_class_table[v1.valueType]; v1 = ExpressionBuilder.addCastOpStep(env, v1, builder.bin.primitive_to_class_table[v1.valueType].getRtType(), new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile) , builder ); build_class(env, step, v1, cls, builder); } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "基础类型" + v1.valueType + "无法转换为引用类型")); } } else { if (step.Arg3.Data.FF1Type == ASTool.AS3.Expr.FF1DataValueType.identifier) { build_dot_name(env, step, v1); } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "静态成员名期待一个identifier")); } } } } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "编译异常 此处应该是个寄存器")); } } else if (step.OpCode == "[") //和.作用相同 { if (step.Arg1.IsReg) { ASBinCode.RightValueBase v1 = ExpressionBuilder.getRightValue(env, step.Arg2, step.token, builder); if (v1 is ASBinCode.StaticClassDataGetter) { build_bracket_access(env, step, v1, builder); } else if (v1 is PackagePathGetter) { if (step.Arg3.Data.FF1Type == ASTool.AS3.Expr.FF1DataValueType.identifier) { PackagePathGetter pd = (PackagePathGetter)v1; string path = pd.path + "." + step.Arg3.Data.Value.ToString(); //**尝试查找类*** //查找导入的类 var found = TypeReader.findClassFromImports(path, builder, step.token); if (found.Count == 1) { var item = found[0]; OpStep stepInitClass = new OpStep(OpCode.init_staticclass, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); stepInitClass.arg1 = new ASBinCode.rtData.RightValue( new ASBinCode.rtData.rtInt(item.classid)); stepInitClass.arg1Type = item.staticClass.getRtType(); env.block.opSteps.Add(stepInitClass); ASBinCode.StackSlotAccessor eax = env.createASTRegister(step.Arg1.Reg); eax.setEAXTypeWhenCompile(item.getRtType()); OpStep op = new OpStep(OpCode.assigning, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); op.reg = eax; op.arg1 = new StaticClassDataGetter(item.staticClass); op.arg1Type = item.staticClass.getRtType(); env.block.opSteps.Add(op); build_bracket_access(env, step, v1, builder); } else { throw new BuildException(step.token.line, step.token.ptr, step.token.sourceFile, "类型" + path + "不明确." ); } } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "静态成员名期待一个identifier")); } } else if (v1 is ThisPointer && v1.valueType == RunTimeDataType.rt_void) { if (step.Arg3.Data.FF1Type == ASTool.AS3.Expr.FF1DataValueType.identifier) { build_bracket_access(env, step, v1, builder); } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "静态成员名期待一个identifier")); } } else if (v1.valueType == RunTimeDataType.unknown) { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "遇到了unknown类型")); } else if (v1.valueType > RunTimeDataType.unknown) { ASBinCode.rtti.Class cls = builder.getClassByRunTimeDataType(v1.valueType); if (cls == null) { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "编译异常 类型" + v1.valueType + "未找到")); } else { //**todo**检查如果是数组的情况**** build_bracket_access(env, step, v1, builder); } } else { if (v1.valueType == RunTimeDataType.rt_array) { var v2 = ExpressionBuilder.getRightValue(env, step.Arg3, step.token, builder); if (v2.valueType == RunTimeDataType.rt_int || v2.valueType == RunTimeDataType.rt_number || v2.valueType == RunTimeDataType.rt_uint) { build_bracket_access(env, step, v1, builder); } else { v1 = ExpressionBuilder.addCastOpStep(env, v1, builder.bin.primitive_to_class_table[v1.valueType].getRtType(), new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile) , builder ); build_bracket_access(env, step, v1, builder); } } else if (v1.valueType != RunTimeDataType.rt_void && v1.valueType < RunTimeDataType.unknown ) { if (builder.bin.primitive_to_class_table[v1.valueType] != null) { v1 = ExpressionBuilder.addCastOpStep(env, v1, builder.bin.primitive_to_class_table[v1.valueType].getRtType(), new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile) , builder ); build_bracket_access(env, step, v1, builder); } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "基础类型" + v1.valueType + "无法转换为引用类型")); } } else { build_bracket_access(env, step, v1, builder); } } } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "编译异常 此处应该是个寄存器")); } } else { throw new BuildException( new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "不支持的操作类型 " + step.Type + " " + step.OpCode)); } }
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 int trydepth; public void buildAS3Try(CompileEnv env, ASTool.AS3.AS3Try as3try, Builder builder) { //***先编译Try块 //trydepth++; int tryid = as3try.holdTryId; //string LBL_BEGIN_TRY = "BEGIN_TRY_" + tryid; //string LBL_END_TRY = "END_TRY_" + tryid; string LBL_BEGIN_FINALLY = "BEGIN_FINALLY_" + tryid; string LBL_END_FINALLY = "END_FINALLY_" + tryid; string LBL_CATCH = "BEGIN_CATCH_" + tryid; //OpStep begintry = new OpStep(OpCode.flag, new SourceToken(as3try.Token.line, as3try.Token.ptr, as3try.Token.sourceFile)); //begintry.flag = LBL_BEGIN_TRY; //env.block.opSteps.Add(begintry); //**包装一个block** ASTool.AS3.AS3Block tempblock = new ASTool.AS3.AS3Block(as3try.Token); tempblock.CodeList = as3try.TryBlock; tempblock.label = as3try.label; { OpStep enter_try = new OpStep(OpCode.enter_try, new SourceToken(as3try.Token.line, as3try.Token.ptr, as3try.Token.sourceFile)); enter_try.arg1 = new ASBinCode.rtData.RightValue(new ASBinCode.rtData.rtInt(tryid)); enter_try.arg1Type = RunTimeDataType.rt_int; env.block.opSteps.Add(enter_try); } builder.buildStmt(env, tempblock); { OpStep quit_try = new OpStep(OpCode.quit_try, new SourceToken(as3try.Token.line, as3try.Token.ptr, as3try.Token.sourceFile)); quit_try.arg1 = new ASBinCode.rtData.RightValue(new ASBinCode.rtData.rtInt(tryid)); quit_try.arg1Type = RunTimeDataType.rt_int; env.block.opSteps.Add(quit_try); } //OpStep endtry= new OpStep(OpCode.flag, new SourceToken(as3try.Token.line, as3try.Token.ptr, as3try.Token.sourceFile)); //endtry.flag = LBL_END_TRY; //env.block.opSteps.Add(endtry); //***跳转到Finally块*** { jumpTo(env, as3try, builder, LBL_BEGIN_FINALLY); } OpStep startCatch = new OpStep(OpCode.flag, new SourceToken(as3try.Token.line, as3try.Token.ptr, as3try.Token.sourceFile)); startCatch.flag = LBL_CATCH; env.block.opSteps.Add(startCatch); //***编译Catch块*** for (int i = 0; i < as3try.CatchList.Count; i++) { var c = as3try.CatchList[i]; //c.CatchVariable.Name = "0"+c.CatchVariable.Name + "_" + i; VariableBase rtVariable = new Variable(c.CatchVariable.Name, env.block.scope.members.Count, true, env.block.id); rtVariable.valueType = TypeReader.fromSourceCodeStr(c.CatchVariable.TypeStr, c.CatchVariable.token, builder); env.block.scope.members.Add(rtVariable); //builder.buildVariables(env, c.CatchVariable); //string catchvariablename = "0" + c.CatchVariable.Name + "_" + i + "_" + tryid; //Variable rtVariable = (Variable)MemberFinder.find(catchvariablename, env); //rtVariable.resetName(c.CatchVariable.Name); //rtVariable.valueType = RunTimeDataType.rt_void; OpStep op = new OpStep(OpCode.catch_error, new SourceToken(c.CatchVariable.token.line, c.CatchVariable.token.ptr, c.CatchVariable.token.sourceFile)); op.reg = rtVariable; op.regType = TypeReader.fromSourceCodeStr(c.CatchVariable.TypeStr, c.CatchVariable.token, builder); op.arg1 = new ASBinCode.rtData.RightValue(new ASBinCode.rtData.rtInt(tryid)); op.arg1Type = RunTimeDataType.rt_int; op.arg2 = null; op.arg2Type = RunTimeDataType.unknown; env.block.opSteps.Add(op); { OpStep enter_catch = new OpStep(OpCode.enter_catch, new SourceToken(c.CatchVariable.token.line, c.CatchVariable.token.ptr, c.CatchVariable.token.sourceFile)); enter_catch.arg1 = new ASBinCode.rtData.RightValue(new ASBinCode.rtData.rtInt(tryid)); enter_catch.arg1Type = RunTimeDataType.rt_int; env.block.opSteps.Add(enter_catch); } int bstidx = env.block.opSteps.Count; for (int j = 0; j < c.CatchBlock.Count; j++) { builder.buildStmt(env, c.CatchBlock[j]); } for (int k = bstidx; k < env.block.opSteps.Count; k++) { var oop = env.block.opSteps[k]; if (Equals(oop.reg, rtVariable)) { ((Variable)oop.reg).resetName("0" + rtVariable.name + "_" + i + "_" + tryid); } if (Equals(oop.arg1, rtVariable)) { ((Variable)oop.arg1).resetName("0" + rtVariable.name + "_" + i + "_" + tryid); } if (Equals(oop.arg2, rtVariable)) { ((Variable)oop.arg2).resetName("0" + rtVariable.name + "_" + i + "_" + tryid); } } rtVariable.resetName("0" + rtVariable.name + "_" + i + "_" + tryid); { OpStep quit_catch = new OpStep(OpCode.quit_catch, new SourceToken(c.CatchVariable.token.line, c.CatchVariable.token.ptr, c.CatchVariable.token.sourceFile)); quit_catch.arg1 = new ASBinCode.rtData.RightValue(new ASBinCode.rtData.rtInt(tryid)); quit_catch.arg1Type = RunTimeDataType.rt_int; env.block.opSteps.Add(quit_catch); } { jumpTo(env, as3try, builder, LBL_BEGIN_FINALLY); } } //FINALLY { OpStep finallylbl = new OpStep(OpCode.flag, new SourceToken(as3try.Token.line, as3try.Token.ptr, as3try.Token.sourceFile)); finallylbl.flag = LBL_BEGIN_FINALLY; env.block.opSteps.Add(finallylbl); { OpStep enter_finally = new OpStep(OpCode.enter_finally, new SourceToken(as3try.Token.line, as3try.Token.ptr, as3try.Token.sourceFile)); enter_finally.arg1 = new ASBinCode.rtData.RightValue(new ASBinCode.rtData.rtInt(tryid)); enter_finally.arg1Type = RunTimeDataType.rt_int; env.block.opSteps.Add(enter_finally); } if (as3try.FinallyBlock != null) { for (int i = 0; i < as3try.FinallyBlock.Count; i++) { builder.buildStmt(env, as3try.FinallyBlock[i]); } } else { if (as3try.CatchList.Count == 0) { throw new BuildException(as3try.Token.line, as3try.Token.ptr, as3try.Token.sourceFile, "try块至少要有1个catch块或1个finally块."); } } { OpStep quit_finally = new OpStep(OpCode.quit_finally, new SourceToken(as3try.Token.line, as3try.Token.ptr, as3try.Token.sourceFile)); quit_finally.arg1 = new ASBinCode.rtData.RightValue(new ASBinCode.rtData.rtInt(tryid)); quit_finally.arg1Type = RunTimeDataType.rt_int; env.block.opSteps.Add(quit_finally); } OpStep endfinally = new OpStep(OpCode.flag, new SourceToken(as3try.Token.line, as3try.Token.ptr, as3try.Token.sourceFile)); endfinally.flag = LBL_END_FINALLY; env.block.opSteps.Add(endfinally); } //trydepth--; //throw new BuildException(as3try.Token.line,as3try.Token.ptr,as3try.Token.sourceFile,"try catch finally编译没实现"); }
private void build_class(CompileEnv env, ASBinCode.rtti.Class _class, ASTool.AS3.Expr.AS3ExprStep step, Builder builder) { //***参数检查*** List <ASTool.AS3.Expr.AS3DataStackElement> args; if (!step.Arg2.IsReg && step.Arg2.Data.FF1Type == ASTool.AS3.Expr.FF1DataValueType.as3_vector) { ASTool.AS3.AS3Vector vector = (ASTool.AS3.AS3Vector)step.Arg2.Data.Value; if (vector.Constructor == null) { args = new List <ASTool.AS3.Expr.AS3DataStackElement>(); } else { if (vector.isInitData) { args = new List <ASTool.AS3.Expr.AS3DataStackElement>(); } else { args = (List <ASTool.AS3.Expr.AS3DataStackElement>)vector.Constructor.Data.Value; } } } else { if (step.Arg3 != null) { args = (List <ASTool.AS3.Expr.AS3DataStackElement>)step.Arg3.Data.Value; } else { args = new List <ASTool.AS3.Expr.AS3DataStackElement>(); } } StackSlotAccessor insEax = env.createASTRegister(step.Arg1.Reg); build_class(env, _class, step.token, builder, insEax, args ); if (!step.Arg2.IsReg && step.Arg2.Data.FF1Type == ASTool.AS3.Expr.FF1DataValueType.as3_vector) { ASTool.AS3.AS3Vector vector = (ASTool.AS3.AS3Vector)step.Arg2.Data.Value; if (vector.Constructor != null && vector.isInitData) { //***追加初始化Vector*** var initdata = (List <ASTool.AS3.Expr.AS3DataStackElement>)vector.Constructor.Data.Value; var vt = builder.bin.dict_Vector_type[_class]; for (int i = 0; i < initdata.Count; i++) { var d = ExpressionBuilder.getRightValue(env, initdata[i], step.token, builder); if (!ASRuntime.TypeConverter.testImplicitConvert(d.valueType, vt, builder)) { throw(new BuildException(new BuildError(step.token.line, step.token.ptr, step.token.sourceFile, "不能将[" + d.valueType + "]类型存入Vector.<" + vt + ">"))); } if (d.valueType != vt) { d = ExpressionBuilder.addCastOpStep(env, d, vt, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile) , builder); } OpStep oppush = new OpStep(OpCode.vector_push, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); oppush.reg = null; oppush.regType = RunTimeDataType.unknown; oppush.arg1 = insEax; oppush.arg1Type = insEax.valueType; oppush.arg2 = d; oppush.arg2Type = d.valueType; env.block.opSteps.Add(oppush); } //throw new NotImplementedException(); } } ////***查找构造函数** //if (_class.constructor != null) //{ // ClassMethodGetter field = (ClassMethodGetter)_class.constructor.bindField; //(Field)builder._classbuildingEnv[_class].block.scope.members[_class.constructor.index]; // int blockid = field.refdefinedinblockid; // var signature = // builder.dictSignatures[blockid][field]; // //***参数检查*** // List<ASTool.AS3.Expr.AS3DataStackElement> args; // if (step.Arg3 != null) // { // args = (List<ASTool.AS3.Expr.AS3DataStackElement>)step.Arg3.Data.Value; // } // else // { // args = new List<ASTool.AS3.Expr.AS3DataStackElement>(); // } // FuncCallBuilder funcbuilder = new FuncCallBuilder(); // funcbuilder.createParaOp(args, signature, step, env, field, builder, true, _class); //} //else //{ // OpStep opMakeArgs = new OpStep(OpCode.prepare_constructor_argement, // new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); // opMakeArgs.arg1 = new ASBinCode.rtData.RightValue(new ASBinCode.rtData.rtInt(_class.classid)); // opMakeArgs.arg1Type = RunTimeDataType.rt_int; // env.block.opSteps.Add(opMakeArgs); //} //OpStep op = new OpStep(OpCode.new_instance, new SourceToken(step.token.line, step.token.ptr, step.token.sourceFile)); //op.arg1 = new RightValue(new rtInt(_class.classid)); //op.arg1Type = _class.getRtType(); //Register eax = env.createASTRegister(step.Arg1.Reg.ID); //eax.setEAXTypeWhenCompile(_class.getRtType()); //op.reg = eax; //op.regType = _class.getRtType(); //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 void buildAS3Continue(CompileEnv env, ASTool.AS3.AS3Continue as3continue, Builder builder) { if (string.IsNullOrEmpty(as3continue.continueFlag)) { int l = 0; for (int i = env.block.opSteps.Count - 1; i >= 0; i--) { var s = env.block.opSteps[i]; if (s.opCode == OpCode.flag) { if (s.flag.StartsWith("LOOP_END_")) { l--; } if (s.flag.StartsWith("LOOP_START_")) { if (l == 0) { string id = s.flag.Substring(11); //label标记跳转 OpStep op = new OpStep(OpCode.jmp, new SourceToken(as3continue.Token.line, as3continue.Token.ptr, as3continue.Token.sourceFile)); op.reg = null; op.regType = RunTimeDataType.unknown; op.arg1 = new ASBinCode.rtData.RightValue( new ASBinCode.rtData.rtString("LOOP_CONTINUE_" + id)); op.arg1Type = RunTimeDataType.rt_string; op.arg2 = null; op.arg2Type = RunTimeDataType.unknown; env.block.opSteps.Add(op); return; } else { l++; } } } } throw new BuildException(as3continue.Token.line, as3continue.Token.ptr, as3continue.Token.sourceFile, "continue的关联块未找到"); } else { //命名label的continue; int l = 0; int stidx = 0; for (int i = 0; i < env.block.opSteps.Count; i++) { var s = env.block.opSteps[i]; if (s.opCode == OpCode.flag) { if (s.flag == "LOOP_LABEL_END_" + as3continue.continueFlag) { l--; } else if (s.flag == "LOOP_LABEL_START_" + as3continue.continueFlag) { l++; stidx = i; } } } if (l < 1) { throw new BuildException(as3continue.Token.line, as3continue.Token.ptr, as3continue.Token.sourceFile, "continue的关联标记[" + as3continue.continueFlag + "]未找到"); } //**查找关联的循环** for (int i = stidx; i < env.block.opSteps.Count; i++) { var s = env.block.opSteps[i]; if (s.opCode == OpCode.flag) { if (s.flag.StartsWith("LOOP_START_")) { string id = s.flag.Substring(11); //label标记跳转 OpStep op = new OpStep(OpCode.jmp, new SourceToken(as3continue.Token.line, as3continue.Token.ptr, as3continue.Token.sourceFile)); op.reg = null; op.regType = RunTimeDataType.unknown; op.arg1 = new ASBinCode.rtData.RightValue( new ASBinCode.rtData.rtString("LOOP_CONTINUE_" + id)); op.arg1Type = RunTimeDataType.rt_string; op.arg2 = null; op.arg2Type = RunTimeDataType.unknown; env.block.opSteps.Add(op); return; } } } throw new BuildException(as3continue.Token.line, as3continue.Token.ptr, as3continue.Token.sourceFile, "continue的关联标记[" + as3continue.continueFlag + "]未找到"); } }
public void buildAS3For(CompileEnv env, ASTool.AS3.AS3For as3for, Builder builder) { if (!string.IsNullOrEmpty(as3for.label)) { //**包装一个block** ASTool.AS3.AS3Block tempblock = new ASTool.AS3.AS3Block(as3for.Token); tempblock.CodeList = new List <ASTool.AS3.IAS3Stmt>(); tempblock.CodeList.Add(as3for); tempblock.label = as3for.label; as3for.label = null; OpStep lbl_forlabel = new OpStep(OpCode.flag, new SourceToken(as3for.Token.line, as3for.Token.ptr, as3for.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(as3for.Token.line, as3for.Token.ptr, as3for.Token.sourceFile)); lbl_forlabel_end.flag = "LOOP_LABEL_END_" + tempblock.label; env.block.opSteps.Add(lbl_forlabel_end); } else { //*** //FOR_LOOPSTART //***For_Part2*** //***if_true goto FOR_LOOPBODY //***goto FOR_END //FOR_LOOPBODY //***ForBody //FOR_CONTINUE //***For_Part3 //**goto FOR_LOOPSTART //FOR_END int lblid = env.getLabelId(); 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(as3for.Token.line, as3for.Token.ptr, as3for.Token.sourceFile)); lbl_loopstart.flag = loopstart; env.block.opSteps.Add(lbl_loopstart); } if (as3for.Part2 != null) { builder.buildStmt(env, as3for.Part2); ASTool.AS3.AS3Expression expr = as3for.Part2.as3exprlist[as3for.Part2.as3exprlist.Count - 1]; { ASTool.AS3.AS3StmtExpressions conditionsJump = new ASTool.AS3.AS3StmtExpressions(as3for.Part2.Token); ASTool.AS3.AS3Expression expression = new ASTool.AS3.AS3Expression(as3for.Part2.Token); expression.exprStepList = new ASTool.AS3.Expr.AS3ExprStepList(); ASTool.AS3.Expr.AS3ExprStep step = new ASTool.AS3.Expr.AS3ExprStep(as3for.Part2.Token); step.Type = ASTool.AS3.Expr.OpType.IF_GotoFlag; step.OpCode = loopbody; step.Arg1 = expr.Value; expression.exprStepList.Add(step); conditionsJump.as3exprlist = new List <ASTool.AS3.AS3Expression>(); conditionsJump.as3exprlist.Add(expression); builder.buildStmt(env, conditionsJump); } { ASTool.AS3.AS3StmtExpressions jumptoend = new ASTool.AS3.AS3StmtExpressions(as3for.Part2.Token); jumptoend.as3exprlist = new List <ASTool.AS3.AS3Expression>(); ASTool.AS3.AS3Expression expression = new ASTool.AS3.AS3Expression(as3for.Part2.Token); expression.exprStepList = new ASTool.AS3.Expr.AS3ExprStepList(); ASTool.AS3.Expr.AS3ExprStep step = new ASTool.AS3.Expr.AS3ExprStep(as3for.Part2.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(as3for.Token.line, as3for.Token.ptr, as3for.Token.sourceFile)); lbl_loopbody.flag = loopbody; env.block.opSteps.Add(lbl_loopbody); } if (as3for.Body != null) { for (int i = 0; i < as3for.Body.Count; i++) { builder.buildStmt(env, as3for.Body[i]); } } { OpStep lbl_loopcontinue = new OpStep(OpCode.flag, new SourceToken(as3for.Token.line, as3for.Token.ptr, as3for.Token.sourceFile)); lbl_loopcontinue.flag = loopcontinue; env.block.opSteps.Add(lbl_loopcontinue); } if (as3for.Part3 != null) { builder.buildStmt(env, as3for.Part3); } { //强行跳回开始 ASTool.AS3.AS3StmtExpressions jumptostart = new ASTool.AS3.AS3StmtExpressions(as3for.Token); jumptostart.as3exprlist = new List <ASTool.AS3.AS3Expression>(); ASTool.AS3.AS3Expression expression = new ASTool.AS3.AS3Expression(as3for.Token); expression.exprStepList = new ASTool.AS3.Expr.AS3ExprStepList(); ASTool.AS3.Expr.AS3ExprStep step = new ASTool.AS3.Expr.AS3ExprStep(as3for.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(as3for.Token.line, as3for.Token.ptr, as3for.Token.sourceFile)); lbl_loopend.flag = loopend; env.block.opSteps.Add(lbl_loopend); } } }