internal ClassScope(AST name, GlobalScope scope) : base(scope) { this.name = name.ToString(); base.engine = scope.engine; base.fast = scope.fast; this.noExpando = true; base.isKnownAtCompileTime = true; this.owner = null; this.constructors = new JSConstructor[0]; ScriptObject parent = base.engine.ScriptObjectStackTop(); while (parent is WithObject) { parent = parent.GetParent(); } if (parent is ClassScope) { this.package = ((ClassScope) parent).GetPackage(); } else if (parent is PackageScope) { this.package = (PackageScope) parent; } else { this.package = null; } this.itemProp = null; this.outerClassField = null; this.inStaticInitializerCode = false; this.staticInitializerUsesEval = false; this.instanceInitializerUsesEval = false; }
internal bool inStaticInitializerCode; //Set this to true when partially evaluating the initializer of a static variable, false otherwise internal ClassScope(AST name, GlobalScope scope) : base(scope) { //The parent must be set to a proper value before the class can be used. this.name = name.ToString(); this.engine = scope.engine; this.fast = scope.fast; this.noExpando = true; this.isKnownAtCompileTime = true; this.owner = null; //set by Class constructor this.constructors = new JSConstructor[0]; ScriptObject enclosingScope = this.engine.ScriptObjectStackTop(); while (enclosingScope is WithObject) enclosingScope = enclosingScope.GetParent(); if (enclosingScope is ClassScope) this.package = ((ClassScope)enclosingScope).GetPackage(); else if (enclosingScope is PackageScope) this.package = (PackageScope)enclosingScope; else this.package = null; this.itemProp = null; this.outerClassField = null; this.inStaticInitializerCode = false; }
private void GetIRForSuperType(){ IReflect supIR = this.superIR = Typeob.Object; if (this.superTypeExpression != null){ this.superTypeExpression.PartiallyEvaluate(); supIR = this.superIR = this.superTypeExpression.ToIReflect(); } Type supType = supIR as Type; if (supType != null){ if (supType.IsSealed || supType.IsInterface || supType == typeof(ValueType) || supType == Typeob.ArrayObject){ if (this.superTypeExpression.Evaluate() is Namespace) this.superTypeExpression.context.HandleError(JSError.NeedType); else this.superTypeExpression.context.HandleError(JSError.TypeCannotBeExtended, supType.FullName); this.superTypeExpression = null; this.superIR = Typeob.Object; }else if (typeof(INeedEngine).IsAssignableFrom(supType)) this.needsEngine = false; }else if (supIR is ClassScope){ if (((ClassScope)supIR).owner.IsASubClassOf(this)){ this.superTypeExpression.context.HandleError(JSError.CircularDefinition); this.superTypeExpression = null; this.superIR = Typeob.Object; }else{ this.needsEngine = false; this.superClass = ((ClassScope)supIR).owner; if ((this.superClass.attributes & TypeAttributes.Sealed) != 0){ this.superTypeExpression.context.HandleError(JSError.TypeCannotBeExtended, this.superClass.name); this.superClass.attributes &= ~TypeAttributes.Sealed; this.superTypeExpression = null; }else if (this.superClass.isInterface){ this.superTypeExpression.context.HandleError(JSError.TypeCannotBeExtended, this.superClass.name); this.superIR = Typeob.Object; this.superTypeExpression = null; } } }else{ this.superTypeExpression.context.HandleError(JSError.TypeCannotBeExtended); this.superIR = Typeob.Object; this.superTypeExpression = null; } }
internal Class(Context context, AST id, TypeExpression superTypeExpression, TypeExpression[] interfaces, Block body, FieldAttributes attributes, bool isAbstract, bool isFinal, bool isStatic, bool isInterface, CustomAttributeList customAttributes) : base(context) { this.name = id.ToString(); this.superTypeExpression = superTypeExpression; this.interfaces = interfaces; this.body = body; this.enclosingScope = (ScriptObject)Globals.ScopeStack.Peek(1); this.attributes = TypeAttributes.Class|TypeAttributes.Serializable; this.SetAccessibility(attributes); if (isAbstract) this.attributes |= TypeAttributes.Abstract; this.isAbstract = isAbstract || isInterface; this.isAlreadyPartiallyEvaluated = false; if (isFinal) this.attributes |= TypeAttributes.Sealed; if (isInterface) this.attributes |= TypeAttributes.Interface | TypeAttributes.Abstract; this.isCooked = false; this.cookedType = null; this.isExpando = false; this.isInterface = isInterface; this.isStatic = isStatic; this.needsEngine = !isInterface; this.validOn = (AttributeTargets)0; this.allowMultiple = true; this.classob = (ClassScope)Globals.ScopeStack.Peek(); this.classob.name = this.name; this.classob.owner = this; this.implicitDefaultConstructor = null; if (!isInterface && !(this is EnumDeclaration)) this.SetupConstructors(); this.EnterNameIntoEnclosingScopeAndGetOwnField(id, isStatic); this.fields = this.classob.GetMemberFields(); this.superClass = null; this.superIR = null; this.superMembers = null; this.firstIndex = null; this.fieldInitializer = null; this.customAttributes = customAttributes; this.clsCompliance = CLSComplianceSpec.NotAttributed; this.generateCodeForExpando = false; this.expandoItemProp = null; this.getHashTableMethod = null; this.getItem = null; this.setItem = null; }
private bool IsASubClassOf(Class cl){ if (this.superTypeExpression != null){ this.superTypeExpression.PartiallyEvaluate(); IReflect supertype = this.superTypeExpression.ToIReflect(); if (supertype is ClassScope){ Class superclass = ((ClassScope)supertype).owner; if (superclass == cl) return true; else return superclass.IsASubClassOf(cl); } } return false; }
//--------------------------------------------------------------------------------------- // ParseClass // // Class : // 'class' identifier OptionalExtends ClassBody // // Extends : // 'extends' QualifiedIdentifier // //--------------------------------------------------------------------------------------- private AST ParseClass(FieldAttributes visibilitySpec, bool isStatic, Context classCtx, bool isAbstract, bool isFinal, CustomAttributeList customAttributes){ AST name = null; AST baseId = null; TypeExpression baseType = null; Block body = null; ArrayList interfaces = new ArrayList(); bool isInterface = JSToken.Interface == this.currentToken.token; GetNextToken(); if (JSToken.Identifier == this.currentToken.token){ name = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); }else{ ReportError(JSError.NoIdentifier); if (JSToken.Extends != this.currentToken.token && JSToken.Implements != this.currentToken.token && JSToken.LeftCurly != this.currentToken.token) SkipTokensAndThrow(); // what the is this? name = new IdentifierLiteral("##Missing Class Name##" + s_cDummyName++, CurrentPositionContext()); } GetNextToken(); if (JSToken.Extends == this.currentToken.token || JSToken.Implements == this.currentToken.token){ if (isInterface && JSToken.Extends == this.currentToken.token) this.currentToken.token = JSToken.Implements; if (JSToken.Extends == this.currentToken.token){ this.noSkipTokenSet.Add(NoSkipTokenSet.s_ClassExtendsNoSkipTokenSet); try{ baseId = ParseQualifiedIdentifier(JSError.NeedType); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_ClassExtendsNoSkipTokenSet, exc) == -1){ exc._partiallyComputedNode = null; throw exc; }else{ baseId = exc._partiallyComputedNode; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_ClassExtendsNoSkipTokenSet); } } if (JSToken.Implements == this.currentToken.token){ do{ AST typeId = null; this.noSkipTokenSet.Add(NoSkipTokenSet.s_ClassImplementsNoSkipTokenSet); try{ typeId = ParseQualifiedIdentifier(JSError.NeedType); interfaces.Add(new TypeExpression(typeId)); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_ClassImplementsNoSkipTokenSet, exc) == -1){ exc._partiallyComputedNode = null; throw exc; }else{ if (exc._partiallyComputedNode != null) interfaces.Add(new TypeExpression(exc._partiallyComputedNode)); } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_ClassImplementsNoSkipTokenSet); } }while (JSToken.Comma == this.currentToken.token); } } if (baseId != null) baseType = new TypeExpression(baseId); if (JSToken.LeftCurly != this.currentToken.token){ ReportError(JSError.NoLeftCurly); } // make a new state and save the old one ArrayList blockType = this.blockType; this.blockType = new ArrayList(16); SimpleHashtable labelTable = this.labelTable; this.labelTable = new SimpleHashtable(16); Globals.ScopeStack.Push(new ClassScope(name, ((IActivationObject)Globals.ScopeStack.Peek()).GetGlobalScope())); //Give declarations a place to go while building AST TypeExpression[] ifaces; try{ body = ParseClassBody(false, isInterface); classCtx.UpdateWith(body.context); ifaces = new TypeExpression[interfaces.Count]; interfaces.CopyTo(ifaces); Class result = new Class(classCtx, name, baseType, ifaces, body, visibilitySpec, isAbstract, isFinal, isStatic, isInterface, customAttributes); if (customAttributes != null) customAttributes.SetTarget(result); return result; }catch(RecoveryTokenException exc){ classCtx.UpdateWith(exc._partiallyComputedNode.context); ifaces = new TypeExpression[interfaces.Count]; interfaces.CopyTo(ifaces); exc._partiallyComputedNode = new Class(classCtx, name, baseType, ifaces, (Block)exc._partiallyComputedNode, visibilitySpec, isAbstract, isFinal, isStatic, isInterface, customAttributes); if (customAttributes != null) customAttributes.SetTarget(exc._partiallyComputedNode); throw exc; }finally{ Globals.ScopeStack.Pop(); this.blockType = blockType; this.labelTable = labelTable; } }
private AST ParseClass(FieldAttributes visibilitySpec, bool isStatic, Context classCtx, bool isAbstract, bool isFinal, CustomAttributeList customAttributes) { AST name = null; AST ast2 = null; TypeExpression superTypeExpression = null; Block body = null; TypeExpression[] expressionArray; AST ast4; ArrayList list = new ArrayList(); bool isInterface = JSToken.Interface == this.currentToken.token; this.GetNextToken(); if (JSToken.Identifier == this.currentToken.token) { name = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); } else { this.ReportError(JSError.NoIdentifier); if (((JSToken.Extends != this.currentToken.token) && (JSToken.Implements != this.currentToken.token)) && (JSToken.LeftCurly != this.currentToken.token)) { this.SkipTokensAndThrow(); } name = new IdentifierLiteral("##Missing Class Name##" + s_cDummyName++, this.CurrentPositionContext()); } this.GetNextToken(); if ((JSToken.Extends == this.currentToken.token) || (JSToken.Implements == this.currentToken.token)) { if (isInterface && (JSToken.Extends == this.currentToken.token)) { this.currentToken.token = JSToken.Implements; } if (JSToken.Extends == this.currentToken.token) { this.noSkipTokenSet.Add(NoSkipTokenSet.s_ClassExtendsNoSkipTokenSet); try { ast2 = this.ParseQualifiedIdentifier(JSError.NeedType); } catch (RecoveryTokenException exception) { if (this.IndexOfToken(NoSkipTokenSet.s_ClassExtendsNoSkipTokenSet, exception) == -1) { exception._partiallyComputedNode = null; throw exception; } ast2 = exception._partiallyComputedNode; } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_ClassExtendsNoSkipTokenSet); } } if (JSToken.Implements == this.currentToken.token) { do { AST expression = null; this.noSkipTokenSet.Add(NoSkipTokenSet.s_ClassImplementsNoSkipTokenSet); try { expression = this.ParseQualifiedIdentifier(JSError.NeedType); list.Add(new TypeExpression(expression)); } catch (RecoveryTokenException exception2) { if (this.IndexOfToken(NoSkipTokenSet.s_ClassImplementsNoSkipTokenSet, exception2) == -1) { exception2._partiallyComputedNode = null; throw exception2; } if (exception2._partiallyComputedNode != null) { list.Add(new TypeExpression(exception2._partiallyComputedNode)); } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_ClassImplementsNoSkipTokenSet); } } while (JSToken.Comma == this.currentToken.token); } } if (ast2 != null) { superTypeExpression = new TypeExpression(ast2); } if (JSToken.LeftCurly != this.currentToken.token) { this.ReportError(JSError.NoLeftCurly); } ArrayList blockType = this.blockType; this.blockType = new ArrayList(0x10); SimpleHashtable labelTable = this.labelTable; this.labelTable = new SimpleHashtable(0x10); this.Globals.ScopeStack.Push(new ClassScope(name, ((IActivationObject) this.Globals.ScopeStack.Peek()).GetGlobalScope())); try { body = this.ParseClassBody(false, isInterface); classCtx.UpdateWith(body.context); expressionArray = new TypeExpression[list.Count]; list.CopyTo(expressionArray); Class target = new Class(classCtx, name, superTypeExpression, expressionArray, body, visibilitySpec, isAbstract, isFinal, isStatic, isInterface, customAttributes); if (customAttributes != null) { customAttributes.SetTarget(target); } ast4 = target; } catch (RecoveryTokenException exception3) { classCtx.UpdateWith(exception3._partiallyComputedNode.context); expressionArray = new TypeExpression[list.Count]; list.CopyTo(expressionArray); exception3._partiallyComputedNode = new Class(classCtx, name, superTypeExpression, expressionArray, (Block) exception3._partiallyComputedNode, visibilitySpec, isAbstract, isFinal, isStatic, isInterface, customAttributes); if (customAttributes != null) { customAttributes.SetTarget(exception3._partiallyComputedNode); } throw exception3; } finally { this.Globals.ScopeStack.Pop(); this.blockType = blockType; this.labelTable = labelTable; } return ast4; }