internal void CompileTopLevelEntity(ParserContext parser, ByteBuffer buffer, TopLevelEntity entity) { if (entity is FunctionDefinition) { FunctionDefinitionEncoder.Compile(this, parser, buffer, (FunctionDefinition)entity, false); } else if (entity is ClassDefinition) { this.CompileClass(parser, buffer, (ClassDefinition)entity); } else { throw new NotImplementedException("Invalid target for byte code compilation"); } }
private void CompileClass(ParserContext parser, ByteBuffer buffer, ClassDefinition classDefinition) { bool hasStaticFieldsWithStartingValues = classDefinition.Fields .Where(fd => fd.Modifiers.HasStatic && fd.DefaultValue != null && !(fd.DefaultValue is NullConstant)) .Count() > 0; if (hasStaticFieldsWithStartingValues) { if (classDefinition.StaticConstructor == null) { classDefinition.StaticConstructor = new ConstructorDefinition(null, ModifierCollection.CreateStaticModifier(classDefinition.FirstToken), new AnnotationCollection(parser), classDefinition); classDefinition.StaticConstructor.Resolve(parser); } List <Executable> staticFieldInitializers = new List <Executable>(); foreach (FieldDefinition fd in classDefinition.Fields) { if (fd.Modifiers.HasStatic && fd.DefaultValue != null && !(fd.DefaultValue is NullConstant)) { FieldReference fieldRef = new FieldReference(fd.FirstToken, fd, fd); fieldRef.ResolvedType = fd.ResolvedFieldType; Executable assignment = new Assignment( fieldRef, null, fd.NameToken, Ops.EQUALS, fd.DefaultValue, fd); staticFieldInitializers.Add(assignment); } } staticFieldInitializers.AddRange(classDefinition.StaticConstructor.Code); classDefinition.StaticConstructor.Code = staticFieldInitializers.ToArray(); } if (classDefinition.StaticConstructor != null) { // All static field initializers are added here. ConstructorDefinitionEncoder.Compile(this, parser, buffer, classDefinition.StaticConstructor, null); } foreach (FunctionDefinition fd in classDefinition.Methods) { int pc = buffer.Size; fd.FinalizedPC = pc; FunctionDefinitionEncoder.Compile(this, parser, buffer, fd, true); } int classId = classDefinition.ClassID; int baseClassId = classDefinition.BaseClass != null ? classDefinition.BaseClass.ClassID : -1; int nameId = parser.GetId(classDefinition.NameToken.Value); int constructorId = classDefinition.Constructor.FunctionID; int staticConstructorId = classDefinition.StaticConstructor != null ? classDefinition.StaticConstructor.FunctionID : -1; int staticFieldCount = classDefinition.Fields.Where <FieldDefinition>(fd => fd.Modifiers.HasStatic).Count(); FieldDefinition[] regularFields = classDefinition.Fields.Where <FieldDefinition>(fd => !fd.Modifiers.HasStatic).ToArray(); FunctionDefinition[] regularMethods = classDefinition.Methods.Where <FunctionDefinition>(fd => !fd.Modifiers.HasStatic).ToArray(); List <int> members = new List <int>(); List <FieldDefinition> fieldsWithComplexValues = new List <FieldDefinition>(); foreach (FieldDefinition fd in regularFields) { int memberId = fd.MemberID; int fieldNameId = parser.GetId(fd.NameToken.Value); int initInstruction; int literalId = 0; // TODO: get rid of init instruction since everything is just 0 now. initInstruction = 0; literalId = parser.GetLiteralId(fd.DefaultValue); if (literalId == -1) { literalId = parser.GetNullConstant(); fieldsWithComplexValues.Add(fd); } members.AddRange(new int[] { 0, // flag for field memberId, fieldNameId, initInstruction, literalId, EncodeAccessModifier(fd.Modifiers) }); } foreach (FunctionDefinition fd in regularMethods) { int memberId = fd.MemberID; int methodNameId = parser.GetId(fd.NameToken.Value); int functionId = fd.FunctionID; members.AddRange(new int[] { 1, // flag for method memberId, methodNameId, functionId, 0, // ignored value. EncodeAccessModifier(fd.Modifiers), }); } ByteBuffer initializer = new ByteBuffer(); if (fieldsWithComplexValues.Count > 0) { foreach (FieldDefinition complexField in fieldsWithComplexValues) { this.CompileExpression(parser, initializer, complexField.DefaultValue, true); initializer.Add(complexField.FirstToken, OpCode.ASSIGN_THIS_FIELD, complexField.MemberID); } } ConstructorDefinitionEncoder.Compile(this, parser, buffer, classDefinition.Constructor, initializer); List <int> args = new List <int>() { classId, baseClassId, nameId, constructorId, staticConstructorId, staticFieldCount, classDefinition.CompilationScope.ScopeNumId, }; args.AddRange(members); string fullyQualifiedName = classDefinition.GetFullyQualifiedLocalizedName(parser.RootScope.Locale); buffer.Add(classDefinition.FirstToken, OpCode.CLASS_DEFINITION, fullyQualifiedName, args.ToArray()); foreach (FieldDefinition fd in classDefinition.Fields) { if (fd.ResolvedFieldType != parser.TypeContext.ANY && !fd.Modifiers.HasStatic) { List <int> typeArgs = new List <int>(); typeArgs.Add(classDefinition.ClassID); typeArgs.Add(fd.MemberID); // TODO: change the last boolean to an enum to include behavior for not including FLOAT/INT conversion info CastEncoder.EncodeTypeInfoToIntBuffer(typeArgs, fd.ResolvedFieldType, false); buffer.Add(null, OpCode.FIELD_TYPE_INFO, typeArgs.ToArray()); } } }