Author: fperrad
Date: Fri Feb 2 12:01:17 2007
New Revision: 16867
Modified:
trunk/languages/lua/lib/luaaux.pir
trunk/languages/lua/lib/luabasic.pir
trunk/languages/lua/lib/luastring.pir
trunk/languages/lua/lib/luatable.pir
trunk/languages/lua/t/shootout.t
trunk/languages/lua/t/table.t
Log:
[Lua]
- remove getn() in luaaux.pir
- refactor checknumber()
- implement table.sort()
- and add tests
Modified: trunk/languages/lua/lib/luaaux.pir
==============================================================================
--- trunk/languages/lua/lib/luaaux.pir (original)
+++ trunk/languages/lua/lib/luaaux.pir Fri Feb 2 12:01:17 2007
@@ -71,22 +71,19 @@
.sub 'checknumber'
.param pmc arg
- .local float val
$S0 = "no value"
if_null arg, L0
$S0 = typeof arg
$I0 = isa arg, 'LuaNumber'
unless $I0 goto L1
- val = arg
- .return (val)
+ .return (arg)
L1:
$I0 = isa arg, 'LuaString'
unless $I0 goto L0
$P0 = arg.'tonumber'()
$I0 = isa $P0, 'LuaNumber'
unless $I0 goto L0
- val = $P0
- .return (val)
+ .return ($P0)
L0:
tag_error($S0, "number")
.end
@@ -173,18 +170,6 @@
.end
-=item C<getn (table)>
-
-=cut
-
-.sub 'getn'
- .param pmc table
- $P0 = table.'len'()
- $I0 = $P0
- .return ($I0)
-.end
-
-
=item C<mkarg (argv)>
Support variable number of arguments function call.
Modified: trunk/languages/lua/lib/luabasic.pir
==============================================================================
--- trunk/languages/lua/lib/luabasic.pir (original)
+++ trunk/languages/lua/lib/luabasic.pir Fri Feb 2 12:01:17 2007
@@ -260,7 +260,7 @@
.sub '_lua_dofile' :anon
.param pmc filename :optional
- $S0 = optstring(filename, "")
+ $S0 = optstring(filename, '')
not_implemented()
.end
@@ -361,18 +361,16 @@
ipairs = _G.'rawget'(key_ipairs)
.local pmc zero
new zero, .LuaNumber
- zero = 0.0
+ set zero, 0.0
.return (ipairs, t, zero)
L0:
- $N0 = checknumber(i)
- inc $N0
+ $P0 = checknumber(i)
+ $P1 = clone $P0
+ inc $P1
.local pmc ret
- .local pmc n
- new n, .LuaNumber
- n = $N0
- ret = t.'rawget'(n)
+ ret = t.'rawget'($P1)
unless ret goto L1
- .return (n, ret)
+ .return ($P1, ret)
L1:
.return ()
.end
@@ -829,7 +827,7 @@
.local int e
.local int n
checktype(list, 'table')
- $I0 = getn(list)
+ $I0 = list.'len'()
$I1 = optint(i, 1)
e = optint(j, $I0)
n = e - $I1
Modified: trunk/languages/lua/lib/luastring.pir
==============================================================================
--- trunk/languages/lua/lib/luastring.pir (original)
+++ trunk/languages/lua/lib/luastring.pir Fri Feb 2 12:01:17 2007
@@ -151,12 +151,13 @@
$P0 = split '', specials
L6:
$I0 = $P0
- unless $I0 > 0 goto L3
+ unless $I0 goto L5
$S0 = shift $P0
$I0 = index $S2, $S0
- unless $I0 >= 0 goto L5
+ if $I0 >= 0 goto L3
goto L6
L5:
+ # do a plain search
.local int idx
$S1 = substr $S1, $I3
idx = index $S1, $S2
@@ -166,11 +167,11 @@
new start, .LuaNumber
$I0 = $I3 + idx
inc $I0
- start = $I0
+ set start, $I0
new end, .LuaNumber
$I0 = $I3 + idx
$I0 += $I2
- end = $I0
+ set end, $I0
.return (start, end)
L3:
.local int anchor
@@ -184,6 +185,7 @@
s1 = substr $S1, $I3
not_implemented()
L7:
+ # not found
.local pmc ret
new ret, .LuaNil
.return (ret)
@@ -234,7 +236,7 @@
dec $I0
$I1 = ord $S0, $I0
new $P0, .LuaNumber
- $P0 = $I1
+ set $P0, $I1
ret[i] = $P0
inc i
goto L3
@@ -275,7 +277,7 @@
goto L1
L2:
new ret, .LuaString
- ret = b
+ set ret, b
.return (ret)
.end
@@ -467,7 +469,7 @@
$S0 = checkstring(s)
$I0 = length $S0
new ret, .LuaNumber
- ret = $I0
+ set ret, $I0
.return (ret)
.end
@@ -486,7 +488,7 @@
$S0 = checkstring(s)
downcase $S0
new ret, .LuaString
- ret = $S0
+ set ret, $S0
.return (ret)
.end
@@ -526,7 +528,7 @@
L0:
$S1 = repeat $S0, $I0
new ret, .LuaString
- ret = $S1
+ set ret, $S1
.return (ret)
.end
@@ -557,7 +559,7 @@
L2:
$S1 = join '', $P0
new ret, .LuaString
- ret = $S1
+ set ret, $S1
.return (ret)
.end
@@ -598,7 +600,7 @@
$S1 = ''
L3:
new ret, .LuaString
- ret = $S1
+ set ret, $S1
.return (ret)
.end
@@ -617,7 +619,7 @@
$S0 = checkstring(s)
upcase $S0
new ret, .LuaString
- ret = $S0
+ set ret, $S0
.return (ret)
.end
Modified: trunk/languages/lua/lib/luatable.pir
==============================================================================
--- trunk/languages/lua/lib/luatable.pir (original)
+++ trunk/languages/lua/lib/luatable.pir Fri Feb 2 12:01:17 2007
@@ -100,7 +100,7 @@
$S0 = optstring(sep, '')
checktype(table, 'table')
$I0 = optint(i, 1)
- $I1 = getn(table)
+ $I1 = table.'len'()
last = optint(j, $I1)
$S1 = ''
new idx, .LuaNumber
@@ -186,7 +186,7 @@
.local int n
checktype(table, 'table')
checktype(f, 'function')
- n = getn(table)
+ n = table.'len'()
i = 0
new index, .LuaNumber
L1:
@@ -239,7 +239,7 @@
.local int pos
new index, .LuaNumber
checktype(table, 'table')
- e = getn(table)
+ e = table.'len'()
inc e
unless_null arg3, L1
pos = e
@@ -262,7 +262,7 @@
goto L4
L2:
index = pos
- table[index] = value
+ table.'rawset'(index, value)
.end
@@ -314,7 +314,7 @@
.local int e
.local int ipos
checktype(table, 'table')
- e = getn(table)
+ e = table.'len'()
ipos = optint(pos, e)
unless e <= 0 goto L1
new ret, .LuaNil
@@ -367,8 +367,6 @@
The sort algorithm is I<not> stable; that is, elements considered equal by
the given order may have their relative positions changed by the sort.
-NOT YET IMPLEMENTED (see auxsort).
-
=cut
.sub '_table_sort' :anon
@@ -376,31 +374,149 @@
.param pmc comp :optional
.local int n
checktype(table, 'table')
- n = getn(table)
+ n = table.'len'()
if_null comp, L1
- if comp goto L1
+ $I0 = isa comp, 'LuaNil'
+ if $I0 goto L1
checktype(comp, 'function')
- goto L2
L1:
- .const .Sub lessthan = 'lessthan'
- comp = lessthan
-L2:
- auxsort(table, comp, n)
+ auxsort(table, comp, 1, n)
.end
.sub 'auxsort' :anon
.param pmc table
.param pmc comp
+ .param int l
.param int u
- not_implemented()
+ .local pmc index
+ .local int i
+ .local int j
+ .local int tmp
+ new index, .LuaNumber
+L1:
+ unless l < u goto L2
+ # sort elements a[l], a[(l+u)/2] and a[u]
+ set index, l
+ $P1 = table.'rawget'(index)
+ set index, u
+ $P2 = table.'rawget'(index)
+ $I0 = sort_comp(comp, $P2, $P1) # a[u] < a[l]?
+ unless $I0 goto L3
+ # swap a[l] - a[u]
+ set index, l
+ table.'rawset'(index, $P2)
+ set index, u
+ table.'rawset'(index, $P1)
+L3:
+ tmp = u - l
+ if tmp == 1 goto L2 # break: only 2 elements
+ i = l + u
+ i /= 2
+ set index, i
+ $P1 = table.'rawget'(index)
+ set index, l
+ $P2 = table.'rawget'(index)
+ $I0 = sort_comp(comp, $P1, $P2) # a[i]<a[l]?
+ unless $I0 goto L4
+ set index, i
+ table.'rawset'(index, $P2)
+ set index, l
+ table.'rawset'(index, $P1)
+ goto L5
+L4:
+ set index, u
+ $P2 = table.'rawget'(index)
+ $I0 = sort_comp(comp, $P2, $P1) # a[u]<a[i]?
+ unless $I0 goto L5
+ set index, i
+ table.'rawset'(index, $P2)
+ set index, u
+ table.'rawset'(index, $P1)
+L5:
+ tmp = u - l
+ if tmp == 2 goto L2 # break: only 3 elements
+ set index, i
+ $P1 = table.'rawget'(index) # Pivot
+ tmp = u - 1
+ set index, tmp
+ $P2 = table.'rawget'(index)
+ set index, i
+ table.'rawset'(index, $P2)
+ set index, tmp
+ table.'rawset'(index, $P1)
+ # a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
+ i = l
+ j = u - 1
+L6: # invariant: a[l..i] <= P <= a[j..u]
+ # repeat ++i until a[i] >= P
+ inc i
+ set index, i
+ $P2 = table.'rawget'(index)
+ $I0 = sort_comp(comp, $P2, $P1)
+ unless $I0 goto L7
+ unless i > u goto L6
+ error("invalid order function for sorting")
+ goto L6
+L7:
+ # repeat --j until a[j] <= P
+ dec j
+ set index, j
+ $P3 = table.'rawget'(index)
+ $I0 = sort_comp(comp, $P1, $P3)
+ unless $I0 goto L8
+ unless j < l goto L7
+ error("invalid order function for sorting")
+ goto L7
+L8:
+ if j < i goto L9
+ set index, i
+ table.'rawset'(index, $P3)
+ set index, j
+ table.'rawset'(index, $P2)
+ goto L6
+L9:
+ tmp = u - 1
+ set index, tmp
+ $P1 = table.'rawget'(index)
+ set index, i
+ $P2 = table.'rawget'(index)
+ # swap pivot (a[u-1]) with a[i]
+ set index, tmp
+ table.'rawset'(index, $P2)
+ set index, i
+ table.'rawset'(index, $P1)
+ # a[l..i-1] <= a[i] == P <= a[i+1..u]
+ # adjust so that smaller half is in [j..i] and larger one in [l..u]
+ tmp += l
+ unless i < tmp goto L10
+ j = l
+ i = i - 1
+ l = i + 2
+ goto L11
+L10:
+ j = i + 1
+ i = u
+ u = j - 2
+L11:
+ # call recursively the smaller one
+ auxsort(table, comp, j, i)
+ # repeat the routine for the larger one
+ goto L1
+L2:
.end
-.sub 'lessthan' :anon
- .param pmc l
- .param pmc r
- .local int ret
- ret = cmp l, r
- .return (ret)
+.sub sort_comp
+ .param pmc comp
+ .param pmc a
+ .param pmc b
+ if_null comp, L1
+ unless comp goto L1
+ $P0 = comp(a, b)
+ $I0 = istrue $P0
+ .return ($I0)
+L1:
+ $I0 = islt a, b
+ .return ($I0)
.end
=back
Modified: trunk/languages/lua/t/shootout.t
==============================================================================
--- trunk/languages/lua/t/shootout.t (original)
+++ trunk/languages/lua/t/shootout.t Fri Feb 2 12:01:17 2007
@@ -34,15 +34,10 @@
# Hashtable update and k-nucleotide strings
#
-TODO:
-{
- local $TODO = 'table.sort is not implemented';
-
$code = Parrot::Test::slurp_file(File::Spec->catfile( @dir,
'knucleotide.lua-2.lua' ));
$out = Parrot::Test::slurp_file(File::Spec->catfile( @dir,
'knucleotide-output.txt' ));
$in = File::Spec->catfile( 'languages', @dir, 'knucleotide-input.txt' );
language_output_is( 'lua', $code, $out, 'k-nucleotide', params => "< $in" );
-}
#
# partial-sums
Modified: trunk/languages/lua/t/table.t
==============================================================================
--- trunk/languages/lua/t/table.t (original)
+++ trunk/languages/lua/t/table.t Fri Feb 2 12:01:17 2007
@@ -27,7 +27,7 @@
use FindBin;
use lib "$FindBin::Bin";
-use Parrot::Test tests => 13;
+use Parrot::Test tests => 16;
use Test::More;
language_output_is( 'lua', << 'CODE', << 'OUTPUT', 'function concat' );
@@ -185,6 +185,106 @@
/'setn' is obsolete/
OUTPUT
+language_output_is( 'lua', << 'CODE', << 'OUTPUT', 'function sort' );
+lines = {
+ luaH_set = 10,
+ luaH_get = 24,
+ luaH_present = 48,
+}
+
+a = {}
+for n in pairs(lines) do a[#a + 1] = n end
+table.sort(a)
+for i,n in ipairs(a) do print(n) end
+CODE
+luaH_get
+luaH_present
+luaH_set
+OUTPUT
+
+language_output_is( 'lua', << 'CODE', << 'OUTPUT', 'function sort' );
+lines = {
+ luaH_set = 10,
+ luaH_get = 24,
+ luaH_present = 48,
+}
+
+function pairsByKeys (t, f)
+ local a = {}
+ for n in pairs(t) do a[#a + 1] = n end
+ table.sort(a, f)
+ local i = 0 -- iterator variable
+ return function () -- iterator function
+ i = i + 1
+ return a[i], t[a[i]]
+ end
+end
+
+for name, line in pairsByKeys(lines) do
+ print(name, line)
+end
+CODE
+luaH_get 24
+luaH_present 48
+luaH_set 10
+OUTPUT
+
+language_output_is( 'lua', << 'CODE', << 'OUTPUT', 'function sort (all
permutations)' );
+function permgen (a, n)
+ n = n or #a
+ if n <= 1 then
+ coroutine.yield(a)
+ else
+ for i=1,n do
+ a[n], a[i] = a[i], a[n]
+ permgen(a, n - 1)
+ a[n], a[i] = a[i], a[n]
+ end
+ end
+end
+
+function permutations (a)
+ local co = coroutine.create(function () permgen(a) end)
+ return function ()
+ local code, res = coroutine.resume(co)
+ return res
+ end
+end
+
+local t = {}
+for _, v in ipairs{'a', 'b', 'c', 'd', 'e', 'f', 'g'} do
+ table.insert(t, v)
+ local ref = table.concat(t, ' ')
+ print(ref)
+ local n = 0
+ for p in permutations(t) do
+ local c = {}
+ for i, v in ipairs(p) do
+ c[i] = v
+ end
+ table.sort(c)
+ assert(ref == table.concat(c, ' '), table.concat(p, ' '))
+ n = n + 1
+ end
+ print(n)
+end
+CODE
+a
+1
+a b
+2
+a b c
+6
+a b c d
+24
+a b c d e
+120
+a b c d e f
+720
+a b c d e f g
+5040
+OUTPUT
+
# Local Variables:
# mode: cperl
# cperl-indent-level: 4