import { StoreObject } from './storeObject'; import { ArrayType } from '../../typeSystem/array_type'; import { ArrayStoreValue } from './value/array_store_value'; import { Location } from "../../memory/location"; import { IStoreValue } from './value/istore_value'; import { StoreValue } from './value/store_value'; export class StoreObjectArray extends StoreObject { constructor (type: ArrayType, private _lines:number, private _columns:number, private loc_addresses: number[], readOnly = false) { super(type, -1, readOnly); } get lines () { return this._lines; } get columns () { return this._columns; } isCompatible (another: IStoreValue): boolean { if(another instanceof ArrayStoreValue) { const cols = another.columns == null ? 0 : another.columns; if(this.lines === another.lines && this.columns === cols) { return super.isCompatible(another); } } return false; } get isVector () { return (this.type as ArrayType).dimensions === 1; } /**@override * Returns the list of values stored by this array. * All returned values are compatible with @prop{StoreObject.type} */ get value () { const values = []; for(let i = 0; i < this.addresses.length; i += 1) { const address = Location.find(this.addresses[i]); if (address != null) { values.push(address.value); } else { throw new Error("!!!Critical Error: variable "+this.id+" does not have a valid address. Loc-Address "+ this.locAddress); } } return values; } destroy () { let bool = true; for(let i = 0; i < this.addresses.length; i += 1) { bool = bool && Location.deallocate(this.addresses[i]); } return bool; } /** * @override * * Returns the address that contains a list of all addresses of the values present in the array */ get locAddress (): number { throw new Error("!!!Internal Error: Cannot invoke locAddress on StoreObjectArray"); } protected get addresses (): number[] { return this.loc_addresses; } getAt (line: number, column?: number): any { if(this.isVector) { if(column != null) { throw new Error(this.id + " is not a matrix!"); } column = line; line = 0; } else if (column == null) { // this is a whole line... const values = []; for(let col = 0; col < this.columns; col += 1) { const index = this.getIndexOf(line, col); const address = Location.find(this.addresses[index])!; values.push(address.value); } return values; } const index = this.getIndexOf(line, column); const address = Location.find(this.addresses[index])!; return address.value; } setAt (value: StoreValue, line:number, column?: number): void { let used_dims = 1; if(column != null) { used_dims += 1; } if(!(this.type as ArrayType).canAccept(value.type, used_dims)) { throw new Error("!!!Internal Error: Attempting to insert an invalid value inside array "+this.id); } if(this.isVector) { if(column != null) { throw new Error(this.id + " is not a matrix!"); } column = line; line = 0; } else if (column == null) { throw new Error("!!!Internal Error: Attempting to insert a line into matrix "+ this.id ); } const pos = this.getIndexOf(line, column); Location.updateAddress(this.addresses[pos], value.get()); } protected getIndexOf (line: number, column: number): number { return line * this.columns + column; } getLocAddressOf (line: number, column?: number): number | number[] { if(this.isVector) { if(column != null) { throw new Error(this.id + " is not a matrix!"); } column = line; line = 0; } else if (column == null) { // this is a whole line... const values: number[] = []; for(let col = 0; col < this.columns; col += 1) { const index = this.getIndexOf(line, col); values.push(this.addresses[index]); } return values; } const index = this.getIndexOf(line, column); return this.addresses[index]; } }