Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new file: .gitignore new file: .project new file: .settings/org.eclipse.jdt.core.prefs new file: License new file: README.txt new file: bench/data/erlang_kilim_ping_pong.xls new file: bench/data/erlang_kilim_task_creation.xls new file: bench/data/kilim_sunfire_pingpong.xls new file: bench/erlang/bigpingpong.erl new file: bench/erlang/numprocs.erl new file: bench/erlang/pingpong.erl new file: bench/erlang/taskstart.erl new file: bench/haskell/Chain new file: bench/haskell/Chain.hi new file: bench/haskell/Chain.hs new file: bench/haskell/Chain.o new file: bench/kilim/bench/BigPingPong.java new file: bench/kilim/bench/Chain.java new file: bench/kilim/bench/Ex_vs_Ret.java new file: bench/kilim/bench/Jetlang.java new file: bench/kilim/bench/LotsOfTasks.java new file: bench/kilim/bench/PingPong.java new file: bench/kilim/bench/Rec.java new file: bench/kilim/bench/Ring.java new file: bench/kilim/bench/Sleep.java new file: bench/kilim/bench/Stopwatch.java new file: bench/kilim/bench/ThreadBench.java new file: bench/kilim/bench/ThreadPipePingPong.java new file: bench/kilim/bench/Unwind.java new file: bench/kilim/bench/rmi/RMI.java new file: bench/scala/BigPingPong.scala new file: bench/scala/Msg.scala new file: bench/scala/PingPongEx.scala new file: bench/scala/oBigPingPong.scala new file: build.sh new file: build.xml new file: docs/IFAQ.txt new file: docs/internals/fiber_states.graffle new file: docs/internals/fiber_states.pdf new file: docs/internals/task_states.graffle new file: docs/internals/task_states.pdf new file: docs/internals/task_states.txt new file: docs/kilim_ecoop08.pdf new file: docs/manual.html new file: docs/manual.txt new file: docs/style.css new file: docs/thread_of_ones_own.pdf new file: examples/kilim/examples/Chain.java new file: examples/kilim/examples/Fib.java new file: examples/kilim/examples/Group.java new file: examples/kilim/examples/SimpleTask.java new file: examples/kilim/examples/SimpleTask2.java new file: examples/kilim/examples/TimedTask.java new file: examples/kilim/examples/Tree.java new file: libs/asm-all-2.2.3.jar new file: libs/junit.jar new file: src/kilim/Cell.java new file: src/kilim/Constants.java new file: src/kilim/Event.java new file: src/kilim/EventPublisher.java new file: src/kilim/EventSubscriber.java new file: src/kilim/ExitMsg.java new file: src/kilim/Fiber.java new file: src/kilim/Generator.java new file: src/kilim/KilimException.java new file: src/kilim/Mailbox.java new file: src/kilim/NotPausable.java new file: src/kilim/Pausable.java new file: src/kilim/PauseReason.java new file: src/kilim/ReentrantLock.java new file: src/kilim/RingQueue.java new file: src/kilim/Scheduler.java new file: src/kilim/State.java new file: src/kilim/Task.java new file: src/kilim/TaskDoneReason.java new file: src/kilim/TaskGroup.java new file: src/kilim/WorkerThread.java new file: src/kilim/YieldReason.java new file: src/kilim/analysis/AsmDetector.java new file: src/kilim/analysis/BBList.java new file: src/kilim/analysis/BasicBlock.java new file: src/kilim/analysis/CallWeaver.java new file: src/kilim/analysis/ClassFlow.java new file: src/kilim/analysis/ClassInfo.java new file: src/kilim/analysis/ClassWeaver.java new file: src/kilim/analysis/Detector.java new file: src/kilim/analysis/FileLister.java new file: src/kilim/analysis/Frame.java new file: src/kilim/analysis/Handler.java new file: src/kilim/analysis/IncompatibleTypesException.java new file: src/kilim/analysis/MethodFlow.java new file: src/kilim/analysis/MethodWeaver.java new file: src/kilim/analysis/NopInsn.java new file: src/kilim/analysis/Range.java new file: src/kilim/analysis/TypeDesc.java new file: src/kilim/analysis/Usage.java new file: src/kilim/analysis/Utils.java new file: src/kilim/analysis/Value.java new file: src/kilim/tools/Asm.java new file: src/kilim/tools/DumpClass.java new file: src/kilim/tools/FlowAnalyzer.java new file: src/kilim/tools/P.java new file: src/kilim/tools/Weaver.java new file: test.sh new file: test/kilim/test/All.java new file: test/kilim/test/AllNotWoven.java new file: test/kilim/test/AllWoven.java new file: test/kilim/test/Base.java new file: test/kilim/test/TaskTestClassLoader.java new file: test/kilim/test/TestBasicBlock.java new file: test/kilim/test/TestExprs.java new file: test/kilim/test/TestFlow.java new file: test/kilim/test/TestFrame.java new file: test/kilim/test/TestGenerics.java new file: test/kilim/test/TestInterface.java new file: test/kilim/test/TestInvalidPausables.java new file: test/kilim/test/TestJSR.java new file: test/kilim/test/TestLock.java new file: test/kilim/test/TestMailbox.java new file: test/kilim/test/TestRing.java new file: test/kilim/test/TestTypeDesc.java new file: test/kilim/test/TestUsage.java new file: test/kilim/test/TestValue.java new file: test/kilim/test/TestYield.java new file: test/kilim/test/TestYieldExceptions.java new file: test/kilim/test/TestYieldJSR.java new file: test/kilim/test/ex/ExA.java new file: test/kilim/test/ex/ExB.java new file: test/kilim/test/ex/ExBasicBlock.java new file: test/kilim/test/ex/ExC.java new file: test/kilim/test/ex/ExCatch.java new file: test/kilim/test/ex/ExD.java new file: test/kilim/test/ex/ExEx.java new file: test/kilim/test/ex/ExException.java new file: test/kilim/test/ex/ExExpr.java new file: test/kilim/test/ex/ExFlow.java new file: test/kilim/test/ex/ExFrame.java new file: test/kilim/test/ex/ExGenerics.java new file: test/kilim/test/ex/ExInterfaceImpl.java new file: test/kilim/test/ex/ExInvalid.java new file: test/kilim/test/ex/ExInvalidSynchronized.java new file: test/kilim/test/ex/ExJSR.j new file: test/kilim/test/ex/ExPausable.java new file: test/kilim/test/ex/ExTaskArgTypes.java new file: test/kilim/test/ex/ExYieldBase.java new file: test/kilim/test/ex/ExYieldConstants.java new file: test/kilim/test/ex/ExYieldDups.java new file: test/kilim/test/ex/ExYieldStack.java new file: test/kilim/test/ex/ExYieldSub.j new file: test/kilim/test/ex/TaskStatusCB.java
- Loading branch information
sriram srinivasan
authored and
sriram srinivasan
committed
Mar 4, 2009
0 parents
commit e8a4c11
Showing
152 changed files
with
18,080 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
s@panther.local.302 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<classpath> | ||
<classpathentry kind="src" path="src"/> | ||
<classpathentry kind="src" path="examples"/> | ||
<classpathentry kind="src" path="bench"/> | ||
<classpathentry kind="src" path="test"/> | ||
<classpathentry kind="lib" path="libs/asm-all-2.2.3.jar"/> | ||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> | ||
<classpathentry kind="lib" path="libs/junit.jar"/> | ||
<classpathentry kind="output" path="classes"/> | ||
</classpath> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
classes/**/* | ||
testclasses/**/* | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<projectDescription> | ||
<name>kilim</name> | ||
<comment></comment> | ||
<projects> | ||
</projects> | ||
<buildSpec> | ||
<buildCommand> | ||
<name>org.eclipse.jdt.core.javabuilder</name> | ||
<arguments> | ||
</arguments> | ||
</buildCommand> | ||
</buildSpec> | ||
<natures> | ||
<nature>org.eclipse.jdt.core.javanature</nature> | ||
</natures> | ||
</projectDescription> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#Mon Jul 28 11:20:18 BST 2008 | ||
eclipse.preferences.version=1 | ||
org.eclipse.jdt.core.builder.cleanOutputFolder=clean | ||
org.eclipse.jdt.core.builder.duplicateResourceTask=warning | ||
org.eclipse.jdt.core.builder.invalidClasspath=abort | ||
org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore | ||
org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch | ||
org.eclipse.jdt.core.circularClasspath=error | ||
org.eclipse.jdt.core.classpath.exclusionPatterns=enabled | ||
org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled | ||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled | ||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 | ||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve | ||
org.eclipse.jdt.core.compiler.compliance=1.5 | ||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate | ||
org.eclipse.jdt.core.compiler.debug.localVariable=generate | ||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate | ||
org.eclipse.jdt.core.compiler.maxProblemPerUnit=100 | ||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error | ||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error | ||
org.eclipse.jdt.core.compiler.source=1.5 | ||
org.eclipse.jdt.core.incompatibleJDKLevel=ignore | ||
org.eclipse.jdt.core.incompleteClasspath=error |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
====================================================================== | ||
This license is a copy of the MIT license. | ||
- Sriram Srinivasan (kilim@malhar.net) | ||
====================================================================== | ||
Copyright (c) 2006 Sriram Srinivasan | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining | ||
a copy of this software and associated documentation files (the | ||
"Software"), to deal in the Software without restriction, including | ||
without limitation the rights to use, copy, modify, merge, publish, | ||
distribute, sublicense, and/or sell copies of the Software, and to | ||
permit persons to whom the Software is furnished to do so, subject to | ||
the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
Kilim v0.5 | ||
Copyright (c) 2006 Sriram Srinivasan. | ||
(kilim _at_ malhar.net) | ||
====================================================================== | ||
|
||
This software is released under an MIT-style licesne (please see the | ||
License file). | ||
|
||
Please see docs/manual.txt and docs/kilim_ecoop08.pdf for a brief | ||
introduction. | ||
|
||
This software depends on the ASM bytecode library (v 3.0). | ||
|
||
To build, you can either run "build.sh" on Unix or ant from the top | ||
directory. Run "test.sh" or "ant test" to test. | ||
|
||
To run an example, type (say) | ||
java -cp ./classes:$CLASSPATH kilim.examples.Chain 10 | ||
|
||
Please send comments, queries, code fixes, constructive criticisms to | ||
kilim _at_ malhar.net | ||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
-module(bigpingpong). | ||
-export([bench/1, start/1, recv/2]). | ||
|
||
% Create N procs. Each proc sends a message to every other (n-1), | ||
% and waits for n-1 msgs from the others, before signalling | ||
% to a collector proc that it is done. Elapsed time is measured. | ||
% N procs => Num Msgs = n(n+1). (Including extra msg initially | ||
% to each proc to start. | ||
|
||
bench(N) -> bench(10, N). % Run benchmark 10 times | ||
|
||
bench(0, _) -> done; | ||
bench(M, N) -> | ||
start(N), | ||
% Wait a little for possible background cleanup to occur | ||
receive | ||
after 1000 | ||
-> done | ||
end, | ||
bench(M-1, N). | ||
|
||
start(NumProcesses) -> | ||
statistics(runtime), | ||
Pids = spawnN(NumProcesses, NumProcesses, self(), []), | ||
lists:foreach( | ||
fun(Pid) -> | ||
Pid ! {start, Pids} | ||
end, | ||
Pids), | ||
wait(NumProcesses, NumProcesses). | ||
|
||
wait(0, _) -> %wait(0, OrigN) -> | ||
{_, T} = statistics(runtime), | ||
% if T == 0 -> | ||
% io:format("Elapsed: ~p ms ~n", [T]); | ||
% true -> | ||
% io:format("Elapsed: ~p ms, ~p tasks/ms ~n", [T, OrigN/T]) | ||
% end; | ||
io:format("~p~n", [T]); | ||
|
||
wait(N, OrigN) -> | ||
receive | ||
done -> | ||
wait(N-1, OrigN) | ||
end. | ||
|
||
|
||
% Spawn N procs and return list of pids | ||
spawnN(0, _, _, ListAlreadySpawned) -> ListAlreadySpawned; | ||
spawnN(N, OrigN, MainPid, ListAlreadySpawned) -> | ||
Pid = spawn(bigpingpong, recv, [MainPid, OrigN]), | ||
spawnN(N-1, OrigN, MainPid, [Pid|ListAlreadySpawned]). | ||
|
||
% Rcv | ||
recv(_, 1) -> done; % Done after n-1 msgs | ||
recv(MainPid, OrigN) -> | ||
receive | ||
{start, Pids} -> | ||
lists:foreach( | ||
fun(E) -> | ||
if | ||
% Skip self | ||
not (E == self()) -> | ||
E ! ping; | ||
true -> pass | ||
end | ||
end, | ||
Pids), | ||
MainPid ! done, | ||
recv(MainPid, OrigN); | ||
|
||
ping -> | ||
$ wait for n-1 msgs | ||
recv(MainPid, OrigN-1) | ||
end. | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
-module(numprocs). | ||
-export([bbench/1, bench/1, bench/2, start/1, start/2, recv/1]). | ||
|
||
|
||
% create N processes, wait for them to send a msg and die. | ||
% bench repeats this experiments a few times | ||
bench(N) -> bench(10, N). | ||
|
||
|
||
% spawn N processes that block. Measure time taken to spawn. Not | ||
% a good round-trip test. | ||
% bbench repeats this experiments a few times | ||
bbench(N) -> bbench(10, N). | ||
|
||
%====================================================================== | ||
|
||
bench(0,_) -> done; | ||
bench(M,N) -> | ||
start(N), | ||
% Wait a little for possible background cleanup to occur | ||
receive | ||
after 1000 | ||
-> done | ||
end, | ||
bench(M-1, N). | ||
|
||
bbench(0, _) -> done; | ||
bbench(M, N) -> | ||
start(N, block), | ||
receive | ||
after 1000 -> done | ||
end, | ||
bbench(M-1, N). | ||
|
||
start(N) -> | ||
statistics(runtime), | ||
%io:format("spawning ~p procs~n", [N]), | ||
spawnN(N, self()), | ||
%io:format("waiting for them to finish~n"), | ||
wait(N, N). | ||
|
||
start(N, block) -> | ||
statistics(runtime), | ||
spawnN(N, nil), | ||
{_, T} = statistics(runtime), | ||
if T == 0 -> | ||
%io:format("Elapsed: ~p ms ~n", [T]); | ||
io:format("~p~n", [T]); | ||
true -> | ||
%io:format("Elapsed: ~p ms, ~p tasks/ms ~n", [T, N/T]) | ||
io:format("~p~n", [T]) | ||
end. | ||
|
||
wait(0, _) -> %wait(0, Total) -> | ||
{_, T} = statistics(runtime), | ||
if T == 0 -> | ||
%io:format("Elapsed: ~p ms ~n", [T]); | ||
io:format("~p~n", [T]); | ||
true -> | ||
%io:format("Elapsed: ~p ms, ~p tasks/ms ~n", [T, Total/T]) | ||
io:format("~p~n", [T]) | ||
end; | ||
wait(N, Total) -> | ||
receive | ||
done -> | ||
wait(N-1, Total) | ||
end. | ||
|
||
|
||
spawnN(0, _) -> done; | ||
spawnN(N, Main) -> | ||
% if (N rem 50000 == 0) -> | ||
% io:format("#Procs: ~p ~n", [N]); | ||
% true -> true | ||
% end, | ||
spawn(numprocs, recv, [Main]), | ||
spawnN(N-1, Main). | ||
|
||
recv(Main) -> | ||
if is_pid(Main) -> | ||
Main ! done; | ||
true -> | ||
receive | ||
hello -> recv(Main) | ||
end | ||
end. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
-module(pingpong). | ||
-export([start/0, ping/3, pong/0]). | ||
|
||
start() -> | ||
Pong = spawn(pingpong, pong, []), | ||
spawn(pingpong, ping, [Pong, erlang:now(), 100000]). | ||
|
||
ping(_, StartTime, 0) -> | ||
io:format("Elapsed: ~p~n", [timer:now_diff(erlang:now(), StartTime)]); | ||
|
||
ping(Pong, StartTime, N) -> | ||
%io:format("ping ~p~n", [N]), | ||
Pong ! {ping, self()}, | ||
receive | ||
pong -> | ||
ping(Pong, StartTime, N-1) | ||
end. | ||
|
||
|
||
pong() -> | ||
receive | ||
{ping, Ping} -> | ||
%io:format("Received ping~n"), | ||
Ping ! pong, | ||
pong() | ||
end. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
-module(taskstart). | ||
-export([start/0, startRound/1, launch/1]). | ||
|
||
start() -> | ||
Reporter = spawn(taskstart, startRound, [10]), | ||
register(reporter, Reporter). | ||
|
||
%--------------------------------------------------------------------- | ||
% Reporter | ||
% Spawns a ring in each of n rounds, and waits for the ring | ||
% to signal completion. | ||
%--------------------------------------------------------------------- | ||
startRound(0)-> | ||
erlang:halt(); | ||
|
||
startRound(N)-> | ||
StartTime = erlang:now(), | ||
spawn(taskstart, launch, [100000]), | ||
receive | ||
EndTime -> | ||
io:format("~p ~p~n", [N, timer:now_diff(EndTime, StartTime)]) | ||
end, | ||
startRound(N-1). | ||
|
||
%--------------------------------------------------------------------- | ||
%Ring | ||
% Each process m spawns process m-1. The last process sends the | ||
% current time to the reporter. | ||
%--------------------------------------------------------------------- | ||
|
||
launch(0) -> | ||
EndTime = erlang:now(), | ||
whereis(reporter) ! EndTime; | ||
|
||
launch(M) -> | ||
spawn(taskstart, launch, [M-1]). | ||
|
||
|
||
|
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
-- Set up n threads in a chain. Each thread retrieves from its MVar and | ||
-- dumps that value on the next MVar | ||
|
||
-- This benchmark adapted from Bryan O'Sullivan's blog. The difference is | ||
-- that the threads are each given their own MVar to reduce contention. | ||
|
||
-- Compile with ghc -O2 --make Chain.hs | ||
-- Run ./Chain 100000 | ||
-- Compare to java kilim.bench.Chain -ntasks 100000 -nmsgs 1 | ||
|
||
module Main where | ||
|
||
import Control.Applicative | ||
import Control.Concurrent.MVar | ||
import Control.Concurrent | ||
import System.Environment | ||
import Data.Time | ||
|
||
main = do | ||
mv <- newEmptyMVar | ||
start <- getCurrentTime | ||
lastmv <- (loop mv =<< read . head <$> getArgs) | ||
end <- getCurrentTime | ||
putStrLn $ "creation time: " ++ show (diffUTCTime end start) | ||
putMVar mv 0 | ||
lastnum <- takeMVar lastmv | ||
fin <- getCurrentTime | ||
putStrLn $ "message time: " ++ show (diffUTCTime fin end) | ||
putStrLn $ "Threads: " ++ show lastnum | ||
|
||
loop :: MVar Int -> Int -> IO (MVar Int) | ||
loop mv n | n <= 0 = return mv | ||
| otherwise = do | ||
nextmv <- newEmptyMVar | ||
forkIO $ do | ||
m <- takeMVar mv | ||
putMVar nextmv $! m+1 | ||
loop nextmv $! n-1 | ||
|
Binary file not shown.
Oops, something went wrong.