internal void CompileExpression(ParserContext parser, ByteBuffer buffer, Expression expr, bool outputUsed) { if (expr is FunctionCall) { FunctionCallEncoder.Compile(this, parser, buffer, (FunctionCall)expr, outputUsed); } else if (expr is IntegerConstant) { ConstantEncoder.CompileInteger(parser, buffer, (IntegerConstant)expr, outputUsed); } else if (expr is Variable) { VariableEncoder.Compile(parser, buffer, (Variable)expr, outputUsed); } else if (expr is BooleanConstant) { ConstantEncoder.CompileBoolean(parser, buffer, (BooleanConstant)expr, outputUsed); } else if (expr is DotField) { DotFieldEncoder.Compile(this, parser, buffer, (DotField)expr, outputUsed); } else if (expr is BracketIndex) { BracketIndexEncoder.Compile(this, parser, buffer, (BracketIndex)expr, outputUsed); } else if (expr is OpChain) { OpChainEncoder.Compile(this, parser, buffer, (OpChain)expr, outputUsed); } else if (expr is StringConstant) { ConstantEncoder.CompileString(parser, buffer, (StringConstant)expr, outputUsed); } else if (expr is NegativeSign) { NegativeSignEncoder.Compile(this, parser, buffer, (NegativeSign)expr, outputUsed); } else if (expr is ListDefinition) { ListDefinitionEncoder.Compile(this, parser, buffer, (ListDefinition)expr, outputUsed); } else if (expr is Increment) { IncrementEncoder.Compile(this, parser, buffer, (Increment)expr, outputUsed); } else if (expr is FloatConstant) { ConstantEncoder.CompileFloat(parser, buffer, (FloatConstant)expr, outputUsed); } else if (expr is NullConstant) { ConstantEncoder.CompileNull(parser, buffer, (NullConstant)expr, outputUsed); } else if (expr is ThisKeyword) { ThisEncoder.Compile(parser, buffer, (ThisKeyword)expr, outputUsed); } else if (expr is Instantiate) { InstantiateEncoder.Compile(this, parser, buffer, (Instantiate)expr, outputUsed); } else if (expr is DictionaryDefinition) { DictionaryDefinitionEncoder.Compile(this, parser, buffer, (DictionaryDefinition)expr, outputUsed); } else if (expr is BooleanCombination) { BooleanCombinationEncoder.Compile(this, parser, buffer, (BooleanCombination)expr, outputUsed); } else if (expr is BooleanNot) { BooleanNotEncoder.Compile(this, parser, buffer, (BooleanNot)expr, outputUsed); } else if (expr is Cast) { CastEncoder.Compile(this, parser, buffer, (Cast)expr, outputUsed); } else if (expr is Ternary) { TernaryEncoder.Compile(this, parser, buffer, (Ternary)expr, outputUsed); } else if (expr is ListSlice) { ListSliceEncoder.Compile(this, parser, buffer, (ListSlice)expr, outputUsed); } else if (expr is NullCoalescer) { NullCoalescerEncoder.Compile(this, parser, buffer, (NullCoalescer)expr, outputUsed); } else if (expr is BaseMethodReference) { BaseMethodReferenceEncoder.Compile(parser, buffer, (BaseMethodReference)expr, outputUsed); } else if (expr is FunctionReference) { FunctionReferenceEncoder.Compile(parser, buffer, (FunctionReference)expr, outputUsed); } else if (expr is FieldReference) { FieldReferenceEncoder.Compile(parser, buffer, (FieldReference)expr, outputUsed); } else if (expr is CoreFunctionInvocation) { CoreFunctionInvocationEncoder.Compile(this, parser, buffer, (CoreFunctionInvocation)expr, null, null, outputUsed); } else if (expr is IsComparison) { IsComparisonEncoder.Compile(this, parser, buffer, (IsComparison)expr, outputUsed); } else if (expr is ClassReferenceLiteral) { ClassReferenceEncoder.Compile(parser, buffer, (ClassReferenceLiteral)expr, outputUsed); } else if (expr is Lambda) { LambdaEncoder.Compile(this, parser, buffer, (Lambda)expr, outputUsed); } else if (expr is PrimitiveMethodReference) { DotFieldEncoder.Compile(this, parser, buffer, (PrimitiveMethodReference)expr, outputUsed); } // The following parse tree items must be removed before reaching the byte code encoder. else if (expr is BaseKeyword) { this.CompileBaseKeyword(parser, buffer, (BaseKeyword)expr, outputUsed); } else if (expr is CompileTimeDictionary) { this.CompileCompileTimeDictionary((CompileTimeDictionary)expr); } else { throw new NotImplementedException(); } }
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()); } } }