def insert_table_record(constructor, key, value): array = constructor.array.contents records = constructor.records.contents if isinstance(key, nodes.MULTRES): assert len(records) == 0 or\ isinstance(records[-1], nodes.TableRecord) records.append(value) return while isinstance(key, nodes.Constant) and\ key.type == key.T_INTEGER and\ key.value >= 0: index = key.value if index == 1 and len(array) == 0: record = nodes.ArrayRecord() record.value = nodes.Primitive() record.value.type = nodes.Primitive.T_NIL array.append(record) if (index > len(array)): break record = nodes.ArrayRecord() record.value = value if len(array) == 0 or index == len(array): array.append(record) else: array[index] = record return record = nodes.TableRecord() record.key = key record.value = value if len(records) == 0: records.append(record) return last = records[-1] if isinstance(last, (nodes.FunctionCall, nodes.Vararg)): records.insert(-1, record) else: records.append(record)
def visit_table_constructor(self, node): self._write("{") if len(node.records.contents) + len(node.array.contents) > 0: self._end_line() self._start_block() array = node.array.contents records = node.records.contents all_records = nodes.RecordsList() all_records.contents = array + records if len(array) > 0: first = array[0].value all_records.contents.pop(0) if not isinstance(first, nodes.Primitive) \ or first.type != first.T_NIL: record = nodes.TableRecord() record.key = nodes.Constant() record.key.type = nodes.Constant.T_INTEGER record.key.value = 0 record.value = first all_records.contents.insert(0, record) self._visit(all_records) self._skip(node.array) self._skip(node.records) self._end_block() else: self._skip(node.array) self._skip(node.records) self._write("}")
def visit_table_constructor(self, node): self._write("{") # These are both delt with in the contents array, no need to visit them separately self._skip(node.array) self._skip(node.records) contents = node.array.contents + node.records.contents if len(node.array.contents) > 0: # Since we're using array+records in that order, the first # array item is also the first combined item. first = contents.pop(0).value if not isinstance(first, nodes.Primitive) or first.type != first.T_NIL: record = nodes.TableRecord() record.key = nodes.Constant() record.key.type = nodes.Constant.T_INTEGER record.key.value = 0 record.value = first contents.insert(0, record) if len(contents) == 1 and False: # TODO enable as part of a TdlQ-emulation option self._visit(contents[0]) elif len(contents) > 0: self._end_line() self._start_block() all_records = nodes.RecordsList() all_records.contents = contents self._visit(all_records) self._end_block() self._write("}")
def _build_table_copy(state, slot): node = nodes.TableConstructor() table = state.constants.complex_constants[slot] i = 0 for value in table.array: record = nodes.ArrayRecord() record.value = _build_table_record_item(value) node.array.contents.append(record) i += 1 for key, value in table.dictionary: record = nodes.TableRecord() record.key = _build_table_record_item(key) record.value = _build_table_record_item(value) node.records.contents.append(record) return node
def insert_table_record(constructor, key, value, replace, allow_duplicates=True): array = constructor.array.contents records = constructor.records.contents if isinstance(key, nodes.MULTRES): assert len(records) == 0 \ or isinstance(records[-1], nodes.TableRecord) records.append(value) return True while isinstance(key, nodes.Constant) \ and key.type == key.T_INTEGER \ and key.value >= 0: index = key.value if index == 1 and len(array) == 0: record = nodes.ArrayRecord() record.value = nodes.Primitive() record.value.type = nodes.Primitive.T_NIL array.append(record) if index > len(array): break record = nodes.ArrayRecord() record.value = value if len(array) == 0 or index == len(array): array.append(record) return True elif replace: array[index] = record return True else: current_value = array[index].value if isinstance(current_value, nodes.Primitive ) and current_value.type == nodes.Primitive.T_NIL: array[index] = record return True return False # Check for record duplicates # This isn't nearly as important as duplicate protection with arrays, since both values # end up in the table to the user can make sense of what happened. Nonetheless, we should still # reject stuff like this. if not allow_duplicates: for rec in records: if isinstance(rec, nodes.TableRecord): if is_equal(rec.key, key, strict=False): return False record = nodes.TableRecord() record.key = key record.value = value if len(records) == 0: records.append(record) return True last = records[-1] if isinstance(last, (nodes.FunctionCall, nodes.Vararg)): records.insert(-1, record) else: records.append(record) return True