Beispiel #1
0
		private void CompileClass(Parser parser, ByteBuffer buffer, ClassDefinition classDefinition)
		{
			bool hasStaticFieldsWithStartingValues = classDefinition.Fields
				.Where<FieldDeclaration>(fd =>
					fd.IsStaticField &&
					fd.DefaultValue != null &&
					!(fd.DefaultValue is NullConstant))
				.Count() > 0;

			if (hasStaticFieldsWithStartingValues)
			{
				if (classDefinition.StaticConstructor == null)
				{
					classDefinition.StaticConstructor = new ConstructorDefinition(null, new Token[0], new Expression[0], new Expression[0], new Executable[0], null, classDefinition);
				}

				List<Executable> staticFieldInitializers = new List<Executable>();
				foreach (FieldDeclaration fd in classDefinition.Fields)
				{
					if (fd.IsStaticField && fd.DefaultValue != null && !(fd.DefaultValue is NullConstant))
					{
						Executable assignment = new Assignment(new FieldReference(fd.FirstToken, fd, classDefinition), fd.NameToken, "=", fd.DefaultValue, classDefinition);
						staticFieldInitializers.Add(assignment);
					}
				}

				staticFieldInitializers.AddRange(classDefinition.StaticConstructor.Code);
				classDefinition.StaticConstructor.Code = staticFieldInitializers.ToArray();
			}

			if (classDefinition.StaticConstructor != null)
			{
				// All static field initializers are added here.
				this.CompileConstructor(parser, buffer, classDefinition.StaticConstructor);
			}

			this.CompileConstructor(parser, buffer, classDefinition.Constructor);

			foreach (FunctionDefinition fd in classDefinition.Methods)
			{
				int pc = buffer.Size;
				fd.FinalizedPC = pc;
				this.CompileFunctionDefinition(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<FieldDeclaration>(fd => fd.IsStaticField).Count();
			FieldDeclaration[] regularFields = classDefinition.Fields.Where<FieldDeclaration>(fd => !fd.IsStaticField).ToArray();
			FunctionDefinition[] regularMethods = classDefinition.Methods.Where<FunctionDefinition>(fd => !fd.IsStaticMethod).ToArray();
			List<int> members = new List<int>();
			List<FieldDeclaration> fieldsWithComplexValues = new List<FieldDeclaration>();
			foreach (FieldDeclaration fd in regularFields)
			{
				int memberId = fd.MemberID;
				int fieldNameId = parser.GetId(fd.NameToken.Value);
				int initInstruction;
				int literalId = 0;
				if (fd.DefaultValue is ListDefinition && ((ListDefinition)fd.DefaultValue).Items.Length == 0)
				{
					initInstruction = 1;
				}
				else if (fd.DefaultValue is DictionaryDefinition && ((DictionaryDefinition)fd.DefaultValue).Keys.Length == 0)
				{
					initInstruction = 2;
				}
				else
				{
					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});
			}

			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. It's just here to keep spacing consistent.
				});
			}

			ByteBuffer initializer = null;

			if (fieldsWithComplexValues.Count > 0)
			{
				initializer = new ByteBuffer();
				foreach (FieldDeclaration complexField in fieldsWithComplexValues)
				{
					this.CompileExpression(parser, initializer, complexField.DefaultValue, true);
					initializer.Add(complexField.FirstToken, OpCode.ASSIGN_THIS_STEP, complexField.MemberID);
				}
				initializer.Add(null, OpCode.RETURN, 0);
			}

			List<int> args = new List<int>()
			{
				classId,
				baseClassId,
				nameId,
				constructorId,
				initializer == null ? 0 : initializer.Size, // jump amount after initialization
				staticConstructorId,
				staticFieldCount,
			};

			args.AddRange(members);

			buffer.Add(classDefinition.FirstToken, OpCode.CLASS_DEFINITION, args.ToArray());

			if (initializer != null)
			{
				buffer.Concat(initializer);
			}
		}