@@ -1614,5 +1614,234 @@ public void inheritedField_lazyClosure_uses_enclosing_receiver() {
16141614 );
16151615 }
16161616
1617+ @ Test
1618+ public void arrayListInClosure () {
1619+ testAssertOkLines (true ,
1620+ "package Hello" ,
1621+ "import NoWurst" ,
1622+ "" ,
1623+ "native testSuccess()" ,
1624+ "" ,
1625+ "public class ArrayList<T:>" ,
1626+ " private static T array store" ,
1627+ " private static int nextFreeIndex = 0" ,
1628+ "" ,
1629+ " private static constant int MAX_FREE_SECTIONS = 256" ,
1630+ " private static int array freeSectionStart" ,
1631+ " private static int array freeSectionCapacity" ,
1632+ " private static int freeSectionCount = 0" ,
1633+ "" ,
1634+ " private int startIndex" ,
1635+ " private int capacity" ,
1636+ " private int size = 0" ,
1637+ " private static constant int INITIAL_CAPACITY = 16" ,
1638+ "" ,
1639+ " static function getNextFreeIndex() returns int" ,
1640+ " return nextFreeIndex" ,
1641+ "" ,
1642+ " construct()" ,
1643+ " allocateStorage(INITIAL_CAPACITY)" ,
1644+ "" ,
1645+ " construct(int initialCapacity)" ,
1646+ " allocateStorage(initialCapacity)" ,
1647+ "" ,
1648+ " private function allocateStorage(int cap)" ,
1649+ " for i = 0 to freeSectionCount - 1" ,
1650+ " if freeSectionCapacity[i] >= cap" ,
1651+ " startIndex = freeSectionStart[i]" ,
1652+ " capacity = freeSectionCapacity[i]" ,
1653+ "" ,
1654+ " for j = i to freeSectionCount - 2" ,
1655+ " freeSectionStart[j] = freeSectionStart[j + 1]" ,
1656+ " freeSectionCapacity[j] = freeSectionCapacity[j + 1]" ,
1657+ " freeSectionCount--" ,
1658+ " return" ,
1659+ "" ,
1660+ " if nextFreeIndex + cap > 10000" ,
1661+ " compactFreeList()" ,
1662+ "" ,
1663+ " if nextFreeIndex + cap > 10000" ,
1664+ " nextFreeIndex = 0" ,
1665+ "" ,
1666+ " startIndex = nextFreeIndex" ,
1667+ " capacity = cap" ,
1668+ " nextFreeIndex += cap" ,
1669+ "" ,
1670+ " private static function compactFreeList()" ,
1671+ " if freeSectionCount <= 1" ,
1672+ " return" ,
1673+ "" ,
1674+ " for i = 1 to freeSectionCount - 1" ,
1675+ " let keyStart = freeSectionStart[i]" ,
1676+ " let keyCap = freeSectionCapacity[i]" ,
1677+ " var j = i - 1" ,
1678+ "" ,
1679+ " while j >= 0 and freeSectionStart[j] > keyStart" ,
1680+ " freeSectionStart[j + 1] = freeSectionStart[j]" ,
1681+ " freeSectionCapacity[j + 1] = freeSectionCapacity[j]" ,
1682+ " j--" ,
1683+ "" ,
1684+ " freeSectionStart[j + 1] = keyStart" ,
1685+ " freeSectionCapacity[j + 1] = keyCap" ,
1686+ "" ,
1687+ " var writeIdx = 0" ,
1688+ " for readIdx = 0 to freeSectionCount - 1" ,
1689+ " if writeIdx > 0 and freeSectionStart[writeIdx - 1] + freeSectionCapacity[writeIdx - 1] == freeSectionStart[readIdx]" ,
1690+ " freeSectionCapacity[writeIdx - 1] += freeSectionCapacity[readIdx]" ,
1691+ " else" ,
1692+ " if writeIdx != readIdx" ,
1693+ " freeSectionStart[writeIdx] = freeSectionStart[readIdx]" ,
1694+ " freeSectionCapacity[writeIdx] = freeSectionCapacity[readIdx]" ,
1695+ " writeIdx++" ,
1696+ "" ,
1697+ " freeSectionCount = writeIdx" ,
1698+ "" ,
1699+ " if freeSectionCount > 0" ,
1700+ " let lastIdx = freeSectionCount - 1" ,
1701+ " if freeSectionStart[lastIdx] + freeSectionCapacity[lastIdx] == nextFreeIndex" ,
1702+ " nextFreeIndex = freeSectionStart[lastIdx]" ,
1703+ " freeSectionCount--" ,
1704+ "" ,
1705+ " private function freeStorage()" ,
1706+ " if capacity <= 0" ,
1707+ " return" ,
1708+ "" ,
1709+ " if freeSectionCount < MAX_FREE_SECTIONS" ,
1710+ " freeSectionStart[freeSectionCount] = startIndex" ,
1711+ " freeSectionCapacity[freeSectionCount] = capacity" ,
1712+ " freeSectionCount++" ,
1713+ "" ,
1714+ " if startIndex + capacity == nextFreeIndex" ,
1715+ " nextFreeIndex = startIndex" ,
1716+ " freeSectionCount--" ,
1717+ " else" ,
1718+ " compactFreeList()" ,
1719+ "" ,
1720+ " if freeSectionCount < MAX_FREE_SECTIONS" ,
1721+ " freeSectionStart[freeSectionCount] = startIndex" ,
1722+ " freeSectionCapacity[freeSectionCount] = capacity" ,
1723+ " freeSectionCount++" ,
1724+ "" ,
1725+ " private function grow()" ,
1726+ " let newCapacity = capacity * 2" ,
1727+ " let oldStart = startIndex" ,
1728+ " let oldCapacity = capacity" ,
1729+ "" ,
1730+ " allocateStorage(newCapacity)" ,
1731+ "" ,
1732+ " for i = 0 to size - 1" ,
1733+ " store[startIndex + i] = store[oldStart + i]" ,
1734+ "" ,
1735+ " let tempStart = startIndex" ,
1736+ " let tempCap = capacity" ,
1737+ " startIndex = oldStart" ,
1738+ " capacity = oldCapacity" ,
1739+ " freeStorage()" ,
1740+ " startIndex = tempStart" ,
1741+ " capacity = tempCap" ,
1742+ "" ,
1743+ " ondestroy" ,
1744+ " for i = 0 to size - 1" ,
1745+ " store[startIndex + i] = null" ,
1746+ "" ,
1747+ " // Return storage to free pool" ,
1748+ " freeStorage()" ,
1749+ "" ,
1750+ " /** Adds one or more elements to the end of the list (amortized O(1)) */" ,
1751+ " function add(vararg T elems)" ,
1752+ " for elem in elems" ,
1753+ " if size >= capacity" ,
1754+ " grow()" ,
1755+ " store[startIndex + size] = elem" ,
1756+ " size++" ,
1757+ "" ,
1758+ " /** Returns the element at the specified index (O(1)) */" ,
1759+ " function get(int index) returns T" ,
1760+ " if index < 0 or index >= size" ,
1761+ " return store[startIndex + index]" ,
1762+ "" ,
1763+ " /** Removes the element at the given index and returns it (O(n) - shifts elements) */" ,
1764+ " function removeAt(int index) returns T" ,
1765+ " if index < 0 or index >= size" ,
1766+ "" ,
1767+ " let elem = store[startIndex + index]" ,
1768+ "" ,
1769+ " // Shift elements left" ,
1770+ " for i = index to size - 2" ,
1771+ " store[startIndex + i] = store[startIndex + i + 1]" ,
1772+ "" ,
1773+ " size--" ,
1774+ " return elem" ,
1775+ "" ,
1776+ " /** Returns the size of the list (O(1)) */" ,
1777+ " function size() returns int" ,
1778+ " return size" ,
1779+ "" ,
1780+ " /** Checks whether this list is empty (O(1)) */" ,
1781+ " function isEmpty() returns boolean" ,
1782+ " return size == 0" ,
1783+ "" ,
1784+ "" ,
1785+ "public function lazy<T:>(Lazy<T> l) returns Lazy<T>" ,
1786+ " return l" ,
1787+ "" ,
1788+ "public abstract class Lazy<T:>" ,
1789+ " T val = null" ,
1790+ " var wasRetrieved = false" ,
1791+ "" ,
1792+ " abstract function retrieve() returns T" ,
1793+ "" ,
1794+ " function get() returns T" ,
1795+ " if not wasRetrieved" ,
1796+ " val = retrieve()" ,
1797+ " wasRetrieved = true" ,
1798+ " return val" ,
1799+ "" ,
1800+ "public class CFBuilding" ,
1801+ " CFBuilding precursor = null" ,
1802+ " ArrayList<CFBuilding> upgrades = null" ,
1803+ "" ,
1804+ " Lazy<boolean> hasAAUpgrade = lazy<boolean>(() -> begin" ,
1805+ " var result = false" ,
1806+ " if upgrades != null" ,
1807+ " result = true" ,
1808+ " // perform iterative search through \" tree\" " ,
1809+ " var toCheck = new ArrayList<CFBuilding>()" ,
1810+ " // toCheck.addAll(upgrades)" ,
1811+ " while not toCheck.isEmpty()" ,
1812+ " let b = toCheck.removeAt(0)" ,
1813+ " if b.isAntiAir" ,
1814+ " result = true" ,
1815+ " break" ,
1816+ " if b.upgrades != null" ,
1817+ " // toCheck.addAll(b.upgrades)" ,
1818+ "" ,
1819+ " destroy toCheck" ,
1820+ " return result" ,
1821+ " end)" ,
1822+ "" ,
1823+ " var netWorthDiv100 = lazy<real>(() -> begin" ,
1824+ " var worth = 0" ,
1825+ " var cur = this" ,
1826+ " while cur != null" ,
1827+ " worth += cur.goldCost" ,
1828+ " cur = cur.precursor" ,
1829+ " return worth / 200." ,
1830+ " end)" ,
1831+ "" ,
1832+ " var goldCost = 0" ,
1833+ " var isAntiAir = false // Is the building an anti air unit" ,
1834+ "" ,
1835+ "init" ,
1836+ " let b = new CFBuilding()" ,
1837+ " b.upgrades = new ArrayList<CFBuilding>()" ,
1838+ " let aa = b" ,
1839+ " .hasAAUpgrade.get()" ,
1840+ " if aa == true" ,
1841+ " testSuccess()" ,
1842+ ""
1843+ );
1844+ }
1845+
16171846
16181847}
0 commit comments