Skip to content

Commit 26d4a38

Browse files
committed
Update GenericsWithTypeclassesTests.java
1 parent 89f5a71 commit 26d4a38

1 file changed

Lines changed: 310 additions & 0 deletions

File tree

de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/GenericsWithTypeclassesTests.java

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,5 +1531,315 @@ public void mixingLegacyOwner_newType_insideGenericClassMethod() {
15311531
);
15321532
}
15331533

1534+
@Test
1535+
public void arrayListInClosure() {
1536+
testAssertOkLinesWithStdLib(true,
1537+
"package Hello",
1538+
"import NoWurst",
1539+
"import Integer",
1540+
"import Printing",
1541+
"",
1542+
"native testSuccess()",
1543+
"",
1544+
"public class ArrayList<T:>",
1545+
" private static T array store",
1546+
" private static int nextFreeIndex = 0",
1547+
"",
1548+
" // Memory management structures",
1549+
" private static constant int MAX_FREE_SECTIONS = 256",
1550+
" private static int array freeSectionStart",
1551+
" private static int array freeSectionCapacity",
1552+
" private static int freeSectionCount = 0",
1553+
"",
1554+
" private int startIndex",
1555+
" private int capacity",
1556+
" private int size = 0",
1557+
" private static constant int INITIAL_CAPACITY = 16",
1558+
"",
1559+
" static function getNextFreeIndex() returns int",
1560+
" return nextFreeIndex",
1561+
"",
1562+
" /** Creates a new empty list with default capacity (16) */",
1563+
" construct()",
1564+
" allocateStorage(INITIAL_CAPACITY)",
1565+
"",
1566+
" /** Creates a new list with specified initial capacity - RECOMMENDED for performance */",
1567+
" construct(int initialCapacity)",
1568+
" allocateStorage(initialCapacity)",
1569+
"",
1570+
" /** Allocates storage section - tries to reuse freed sections first */",
1571+
" private function allocateStorage(int cap)",
1572+
" // Try to find a freed section that fits",
1573+
" for i = 0 to freeSectionCount - 1",
1574+
" if freeSectionCapacity[i] >= cap",
1575+
" startIndex = freeSectionStart[i]",
1576+
" capacity = freeSectionCapacity[i]",
1577+
"",
1578+
" // Remove this section from free list",
1579+
" for j = i to freeSectionCount - 2",
1580+
" freeSectionStart[j] = freeSectionStart[j + 1]",
1581+
" freeSectionCapacity[j] = freeSectionCapacity[j + 1]",
1582+
" freeSectionCount--",
1583+
" return",
1584+
"",
1585+
" // No suitable free section, allocate new",
1586+
" if nextFreeIndex + cap > JASS_MAX_ARRAY_SIZE",
1587+
" // Try to compact free sections",
1588+
" compactFreeList()",
1589+
"",
1590+
" if nextFreeIndex + cap > JASS_MAX_ARRAY_SIZE",
1591+
" // Still not enough, wrap around (dangerous!)",
1592+
" print(\"ArrayList: WARNING - Memory store exhausted, wrapping around!\")",
1593+
" nextFreeIndex = 0",
1594+
"",
1595+
" startIndex = nextFreeIndex",
1596+
" capacity = cap",
1597+
" nextFreeIndex += cap",
1598+
"",
1599+
" /** Compacts the free list by merging adjacent sections */",
1600+
" private static function compactFreeList()",
1601+
" if freeSectionCount <= 1",
1602+
" return",
1603+
"",
1604+
" // Sort free sections by start index using insertion sort",
1605+
" for i = 1 to freeSectionCount - 1",
1606+
" let keyStart = freeSectionStart[i]",
1607+
" let keyCap = freeSectionCapacity[i]",
1608+
" var j = i - 1",
1609+
"",
1610+
" while j >= 0 and freeSectionStart[j] > keyStart",
1611+
" freeSectionStart[j + 1] = freeSectionStart[j]",
1612+
" freeSectionCapacity[j + 1] = freeSectionCapacity[j]",
1613+
" j--",
1614+
"",
1615+
" freeSectionStart[j + 1] = keyStart",
1616+
" freeSectionCapacity[j + 1] = keyCap",
1617+
"",
1618+
" // Merge adjacent sections",
1619+
" var writeIdx = 0",
1620+
" for readIdx = 0 to freeSectionCount - 1",
1621+
" if writeIdx > 0 and freeSectionStart[writeIdx - 1] + freeSectionCapacity[writeIdx - 1] == freeSectionStart[readIdx]",
1622+
" // Merge with previous",
1623+
" freeSectionCapacity[writeIdx - 1] += freeSectionCapacity[readIdx]",
1624+
" else",
1625+
" // Keep as separate section",
1626+
" if writeIdx != readIdx",
1627+
" freeSectionStart[writeIdx] = freeSectionStart[readIdx]",
1628+
" freeSectionCapacity[writeIdx] = freeSectionCapacity[readIdx]",
1629+
" writeIdx++",
1630+
"",
1631+
" freeSectionCount = writeIdx",
1632+
"",
1633+
" // Update nextFreeIndex if last section extends to it",
1634+
" if freeSectionCount > 0",
1635+
" let lastIdx = freeSectionCount - 1",
1636+
" if freeSectionStart[lastIdx] + freeSectionCapacity[lastIdx] == nextFreeIndex",
1637+
" nextFreeIndex = freeSectionStart[lastIdx]",
1638+
" freeSectionCount--",
1639+
"",
1640+
" /** Frees this list's storage section for reuse */",
1641+
" private function freeStorage()",
1642+
" if capacity <= 0",
1643+
" return",
1644+
"",
1645+
" // Add to free list if there's space",
1646+
" if freeSectionCount < MAX_FREE_SECTIONS",
1647+
" freeSectionStart[freeSectionCount] = startIndex",
1648+
" freeSectionCapacity[freeSectionCount] = capacity",
1649+
" freeSectionCount++",
1650+
"",
1651+
" // If this was at the end, we can reclaim it immediately",
1652+
" if startIndex + capacity == nextFreeIndex",
1653+
" nextFreeIndex = startIndex",
1654+
" freeSectionCount--",
1655+
" else",
1656+
" // Free list full, try to compact",
1657+
" compactFreeList()",
1658+
"",
1659+
" // Try again after compaction",
1660+
" if freeSectionCount < MAX_FREE_SECTIONS",
1661+
" freeSectionStart[freeSectionCount] = startIndex",
1662+
" freeSectionCapacity[freeSectionCount] = capacity",
1663+
" freeSectionCount++",
1664+
"",
1665+
" /** Grows the capacity (doubles it) - EXPENSIVE OPERATION! */",
1666+
" private function grow()",
1667+
" let newCapacity = capacity * 2",
1668+
" let oldStart = startIndex",
1669+
" let oldCapacity = capacity",
1670+
"",
1671+
" // Try to allocate new section",
1672+
" allocateStorage(newCapacity)",
1673+
"",
1674+
" // Copy elements to new location",
1675+
" for i = 0 to size - 1",
1676+
" store[startIndex + i] = store[oldStart + i]",
1677+
"",
1678+
" // Free old section",
1679+
" let tempStart = startIndex",
1680+
" let tempCap = capacity",
1681+
" startIndex = oldStart",
1682+
" capacity = oldCapacity",
1683+
" freeStorage()",
1684+
" startIndex = tempStart",
1685+
" capacity = tempCap",
1686+
"",
1687+
" ondestroy",
1688+
" // Clear references to allow garbage collection",
1689+
" for i = 0 to size - 1",
1690+
" store[startIndex + i] = null",
1691+
"",
1692+
" // Return storage to free pool",
1693+
" freeStorage()",
1694+
"",
1695+
" /** Debug function to get memory layout info */",
1696+
" function getMemoryInfo() returns string",
1697+
" return \"Start: \" + startIndex.toString() + \", Capacity: \" + capacity.toString() + \", Size: \" + size.toString()",
1698+
"",
1699+
" /** Static function to get global memory state */",
1700+
" static function getGlobalMemoryInfo() returns string",
1701+
" return \"NextFree: \" + nextFreeIndex.toString() + \", FreeSections: \" + freeSectionCount.toString() + \", Used: \" + (nextFreeIndex - freeSectionCount).toString()",
1702+
"",
1703+
" // ============================================================================",
1704+
" // BASIC OPERATIONS",
1705+
" // ============================================================================",
1706+
"",
1707+
" /** Adds one or more elements to the end of the list (amortized O(1)) */",
1708+
" function add(vararg T elems)",
1709+
" for elem in elems",
1710+
" if size >= capacity",
1711+
" grow()",
1712+
" store[startIndex + size] = elem",
1713+
" size++",
1714+
"",
1715+
" /** Returns the element at the specified index (O(1)) */",
1716+
" function get(int index) returns T",
1717+
" if index < 0 or index >= size",
1718+
" print(\"ArrayList: Index out of bounds: \" + index.toString())",
1719+
" return store[startIndex + index]",
1720+
"",
1721+
" /** Sets the element at the specified index (O(1)) */",
1722+
" function set(int index, T elem)",
1723+
" if index < 0 or index >= size",
1724+
" print(\"ArrayList: Index out of bounds: \" + index.toString())",
1725+
" store[startIndex + index] = elem",
1726+
"",
1727+
" /** Returns the index of the specified element or -1 if it doesn't exist (O(n)) */",
1728+
" function indexOf(T elem) returns int",
1729+
" for i = 0 to size - 1",
1730+
" if store[startIndex + i] == elem",
1731+
" return i",
1732+
" return -1",
1733+
"",
1734+
" /** Returns whether the list contains the specified element (O(n)) */",
1735+
" function has(T elem) returns boolean",
1736+
" return indexOf(elem) >= 0",
1737+
"",
1738+
" /** Removes the element at the given index and returns it (O(n) - shifts elements) */",
1739+
" function removeAt(int index) returns T",
1740+
" if index < 0 or index >= size",
1741+
" print(\"ArrayList: Index out of bounds: \" + index.toString())",
1742+
"",
1743+
" let elem = store[startIndex + index]",
1744+
"",
1745+
" // Shift elements left",
1746+
" for i = index to size - 2",
1747+
" store[startIndex + i] = store[startIndex + i + 1]",
1748+
"",
1749+
" size--",
1750+
" return elem",
1751+
"",
1752+
" /** Removes the element at the given index by swapping with last element (O(1) - DOES NOT PRESERVE ORDER!) */",
1753+
" function removeSwap(int index) returns T",
1754+
" if index < 0 or index >= size",
1755+
" print(\"ArrayList: Index out of bounds: \" + index.toString())",
1756+
"",
1757+
" let elem = store[startIndex + index]",
1758+
"",
1759+
" // Replace with last element",
1760+
" size--",
1761+
" if index < size",
1762+
" store[startIndex + index] = store[startIndex + size]",
1763+
"",
1764+
" return elem",
1765+
"",
1766+
" /** Removes the first occurrence of the element from the list (O(n)) */",
1767+
" function remove(T elem) returns bool",
1768+
" let index = indexOf(elem)",
1769+
" if index >= 0",
1770+
" removeAt(index)",
1771+
" return true",
1772+
" return false",
1773+
"",
1774+
" /** Returns the size of the list (O(1)) */",
1775+
" function size() returns int",
1776+
" return size",
1777+
"",
1778+
" /** Checks whether this list is empty (O(1)) */",
1779+
" function isEmpty() returns boolean",
1780+
" return size == 0",
1781+
"",
1782+
"",
1783+
"public function lazy<T:>(Lazy<T> l) returns Lazy<T>",
1784+
" return l",
1785+
"",
1786+
"public abstract class Lazy<T:>",
1787+
" T val = null",
1788+
" var wasRetrieved = false",
1789+
"",
1790+
" abstract function retrieve() returns T",
1791+
"",
1792+
" function get() returns T",
1793+
" if not wasRetrieved",
1794+
" val = retrieve()",
1795+
" wasRetrieved = true",
1796+
" return val",
1797+
"",
1798+
"public class CFBuilding",
1799+
" CFBuilding precursor = null",
1800+
" ArrayList<CFBuilding> upgrades = null",
1801+
"",
1802+
" Lazy<boolean> hasAAUpgrade = lazy<boolean>(() -> begin",
1803+
" var result = false",
1804+
" if upgrades != null",
1805+
" result = true",
1806+
" // perform iterative search through \"tree\"",
1807+
" var toCheck = new ArrayList<CFBuilding>()",
1808+
" // toCheck.addAll(upgrades)",
1809+
" while not toCheck.isEmpty()",
1810+
" let b = toCheck.removeAt(0)",
1811+
" if b.isAntiAir",
1812+
" result = true",
1813+
" break",
1814+
" if b.upgrades != null",
1815+
" // toCheck.addAll(b.upgrades)",
1816+
"",
1817+
" destroy toCheck",
1818+
" return result",
1819+
" end)",
1820+
"",
1821+
" var netWorthDiv100 = lazy<real>(() -> begin",
1822+
" var worth = 0",
1823+
" var cur = this",
1824+
" while cur != null",
1825+
" worth += cur.goldCost",
1826+
" cur = cur.precursor",
1827+
" return worth / 200.",
1828+
" end)",
1829+
"",
1830+
" var goldCost = 0",
1831+
" var isAntiAir = false // Is the building an anti air unit",
1832+
"",
1833+
"init",
1834+
" let b = new CFBuilding()",
1835+
" b.upgrades = new ArrayList<CFBuilding>()",
1836+
" let aa = b",
1837+
" .hasAAUpgrade.get()",
1838+
" if aa == true",
1839+
" testSuccess()",
1840+
""
1841+
);
1842+
}
1843+
15341844

15351845
}

0 commit comments

Comments
 (0)