/// <summary> /// Implements the code to initialise the array. /// </summary> /// <param name="cg">The code generator object</param> public override void Generate(CodeGenerator cg) { if (cg == null) { throw new ArgumentNullException("cg"); } Symbol sym = Identifier.Symbol; // Simple array initialisation - just initialise the // specified element. More complex initialisation requires // a loop across the elements. Debug.Assert(sym.IsArray); if (Identifier.Indexes != null && Identifier.Indexes.Count > 0) { if (Identifier.Indexes.Count == 1) { NumberParseNode number = (NumberParseNode)Identifier.Indexes[0]; Debug.Assert(sym.Dimensions[0].LowerBound.IsConstant); int index = number.Value.IntValue + (0 - sym.Dimensions[0].LowerBound.Value.IntValue); GenerateStoreToArray(cg, sym, index, RangeValue); } else { Type [] paramTypes = new Type[Identifier.Indexes.Count + 1]; int index = 0; cg.LoadLocal(sym); while (index < Identifier.Indexes.Count) { NumberParseNode number = (NumberParseNode)Identifier.Indexes[index]; Debug.Assert(sym.Dimensions[index].LowerBound.IsConstant); cg.Emitter.LoadInteger(number.Value.IntValue + (0 - sym.Dimensions[index].LowerBound.Value.IntValue)); paramTypes[index++] = typeof(Int32); } cg.GenerateLoad(RangeValue); paramTypes[index] = Symbol.SymTypeToSystemType(RangeValue.Type); cg.Emitter.Call(cg.GetMethodForType(sym.SystemType, "Set", paramTypes)); } } else if (StartRange < EndRange + 4) { // When initialising arrays less than 4 values, unroll // the loop as it will be faster. int index = StartRange; while (index <= EndRange) { GenerateStoreToArray(cg, sym, index++, RangeValue); } } else { // For large arrays, generate code to initialise the elements // to a specific value. Label label1 = cg.Emitter.CreateLabel(); cg.Emitter.LoadInteger(StartRange); LocalDescriptor tempIndex = cg.Emitter.GetTemporary(typeof(int)); cg.Emitter.StoreLocal(tempIndex); cg.Emitter.MarkLabel(label1); GenerateStoreToArray(cg, sym, tempIndex.Index, RangeValue); cg.Emitter.LoadLocal(tempIndex); cg.Emitter.LoadInteger(1); cg.Emitter.Add(SymType.INTEGER); cg.Emitter.Dup(); cg.Emitter.StoreLocal(tempIndex); cg.Emitter.LoadInteger(EndRange); cg.Emitter.BranchLessOrEqual(label1); } }
/// <summary> /// Emit this code to load the value to the stack. /// </summary> /// <param name="cg">A CodeGenerator object</param> /// <param name="returnType">The type required by the caller</param> /// <returns>The symbol type of the value generated</returns> public override SymType Generate(CodeGenerator cg, SymType returnType) { if (cg == null) { throw new ArgumentNullException("cg"); } if (ID == ParseID.LABEL) { if (Symbol.IsFixedStatic) { cg.Emitter.LoadString(Symbol.Value.StringValue); return Type; } return cg.LoadLocal(Symbol); } Debug.Assert(false, "Unsupported parse ID for SymbolParseNode"); return Value.Type; }
// Emit code that writes the variant value to the given array index where // the array is specified by the symbol.. void GenerateStoreToArray(CodeGenerator cg, Symbol sym, int index, Variant value) { cg.LoadLocal(sym); cg.Emitter.LoadInteger(index); cg.GenerateLoad(value); cg.Emitter.ConvertType(value.Type, sym.Type); cg.Emitter.StoreElement(sym.Type); }
/// <summary> /// Emit this code to load the identifier to the stack. /// </summary> /// <param name="cg">A CodeGenerator object</param> /// <param name="returnType">The type required by the caller</param> /// <returns>The symbol type of the value generated</returns> public override SymType Generate(CodeGenerator cg, SymType returnType) { if (cg == null) { throw new ArgumentNullException("cg"); } Symbol sym = Symbol; SymType thisType; if (sym.Class == SymClass.INLINE) { GenerateInline(cg); thisType = sym.Type; } else if (sym.IsArray) { thisType = cg.GenerateLoadFromArray(this, false); } else if (sym.IsIntrinsic || sym.IsExternal) { cg.Emitter.LoadFunction(sym); thisType = SymType.INTEGER; } else if (sym.IsParameter) { cg.GenerateLoadArgument(sym); thisType = sym.Type; } else if (sym.Class == SymClass.FUNCTION) { cg.Emitter.LoadFunction(sym); thisType = SymType.INTEGER; } else if (sym.IsLocal) { cg.LoadLocal(sym); thisType = sym.Type; } else { Debug.Assert(false, "Unknown identifier type (not local OR parameter)"); thisType = SymType.NONE; } if (HasSubstring) { thisType = GenerateLoadSubstring(cg); } return thisType; }