void BuildTable([NotNull] ZilTable zt, [NotNull] ITableBuilder tb) { if ((zt.Flags & TableFlags.Lexv) != 0) { var values = new IOperand[zt.ElementCount]; zt.CopyTo(values, (zo, isWord) => CompileConstant(zo), Game.Zero, Context); tb.AddByte((byte)(zt.ElementCount / 3)); tb.AddByte(0); for (int i = 0; i < values.Length; i++) { if (i % 3 == 0) { tb.AddShort(values[i]); } else { tb.AddByte(values[i]); } } } else { var values = new TableElementOperand?[zt.ElementCount]; TableElementOperand?ConvertElement(ZilObject zo, bool isWord) { // it's usually a constant value var constVal = CompileConstant(zo); if (constVal != null) { return(new TableElementOperand(constVal, isWord)); } // but we'll also allow a global name if the global contains a table if (zo is ZilAtom atom && Globals.TryGetValue(atom, out var global) && global.DefaultValue is ITableBuilder) { return(new TableElementOperand(global.DefaultValue, isWord)); } return(null); } var defaultFiller = new TableElementOperand(Game.Zero, null); zt.CopyTo(values, ConvertElement, defaultFiller, Context); for (int i = 0; i < values.Length; i++) { if (values[i] == null) { var rawElements = new ZilObject[zt.ElementCount]; zt.CopyTo(rawElements, (zo, isWord) => zo, null, Context); Context.HandleError(new CompilerError( zt.SourceLine, CompilerMessages.Nonconstant_Initializer_For_0_1_2, "table element", i, rawElements[i])); values[i] = defaultFiller; } } bool defaultWord = (zt.Flags & TableFlags.Byte) == 0; for (int i = 0; i < values.Length; i++) { Debug.Assert(values[i] != null); if (values[i].Value.IsWord ?? defaultWord) { tb.AddShort(values[i].Value.Operand); } else { tb.AddByte(values[i].Value.Operand); } } } }