411 REFERENCE · Wikibooks
The Sway Reference Manual/Storing Code in Files
Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.
After a while, it gets rather tedious to
cut and paste into the Sway interpreter.
A more efficient method is to store
your program in a text file and then
load the file.
I use vim as my text editor. Vim is
an editor that was written by programmers
for programmers (emacs is another such
editor) and serious Computer Scientists
and Programmers should learn vim (or emacs).
Your first program
Create a text file named hello.s. The
name really doesn't matter and doesn't
have to end in .s (the .s is a convention
to remind us this file contains Sway source
code). Place in the file
println("hello, world!");
Save your work and exit the text editor.
Now execute the following command at the
system prompt (not the Sway interpreter prompt!):
sway hello.s
You should see the phrase:
hello, world!
displayed on your console. Here's a trace using Linux:
lusth@warka:~$ sway hello.s
hello, world!
lusth@warka:~$
The lusth@warka:~$ is my system prompt.
A Neat Macro
One of the more useful things you can do is set up a vim
macro. Edit (or create) the file .exrc in your home directory and
add these lines:
set ai sm sw=4
map @ :!sway %^V^M
The first line sets some useful parameters: autoindent and showmatch.
The sw=4 sets the indentation to four spaces.
The next line makes the '@' key,
when pressed,
run the Sway interpreter on
the file you are currently editing (save your work first before
tapping the @ key). The ^V^M part of the macro is not the four
characters ^ V ^ M, but two characters <Ctrl>-v and <Ctrl>-m.
It's just when you type <Ctrl>-v<Ctrl>-m, it will display as
^V^M.
Writing Sway Programs
A typical Sway program is composed of two sections. The first
section is composed of variable and function definitions.
The next section is composed of statements, which are Sway
expressions, each of which is (usually) followed by a
semicolon.
The hello.s file above was a program with no
definitions and a single statement. A Sway program composed
only of definitions will usually run with no output to the
screen. Such programs are usually written for the express
purpose of being included
into other programs.
Typically, one of the function definitions is a function
named main (by convention); this function takes no
arguments. The last line of the program is a call to main.
Here is a rewrite of hello.s using that convention.
function main()
{
println("hello, world!");
}
main();
This version's output is exactly the same as the previous version.
Order of definitions
A function or variable must be defined before it is used. This
program will generate an error:
var x = y * y;
var y = 3;
since x can't be given a value until y is defined.
This program is legal, however:
function x()
{
y() * y();
}
function y()
{
3;
}
x();
because even though the body of function x refers to
function y, function y is defined by the time
function x is called (the last statement of the program).
Including code
One can include one Sway module into another by use of the include
function:
include("moduleX.s");
where moduleX.s is the name of the file whose Sway definitions
you wish to include. Including a module imports all the top level
definitions in that module. The statements beyond the definitions in
the included module are ignored and are not evaluated.
If moduleX.s has includes, those modules will be
included as well.
Preventing multiple includes
Sometimes, in a complex implementation, a module can get included
more than once. Usually, this results in multiple definitions of
the same item and, while wasteful, usually does not cause any harm.
However,
consider the case where one module includes the
other and vice versa.
Here is an example.
One module, fact.s,
has the following implementation:
include("fib.s");
function fact(n)
{
if (n < 2,1,n * fact(n - 1));
}
println("fib(5) is ",fib(5));
println("fact(5) is ",fact(5));
The other module, fib.s, has this code:
include("fact.s");
function fib(n)
{
if (n < 2,v,fib(n - 2) * fib(n - 1));
}
println("fib(6) is ",fib(6));
println("fact(6) is ",fact(6));
Trying to run Sway on either module results in an
out of memory error, since each file
gets included over and over
(fib.s includes fact.s
which includes fib.s and so on).
One can prevent multiple includes by using
the includeOnce function. Here is a rewrite of each module.
fact.s
includeOnce(fib.s,"fib.s");
function fact(n)
{
if (n < 2,1,n * fact(n - 1));
}
println("fib(5) is ",fib(5));
println("fact(5) is ",fact(5));
fib.s
includeOnce(fact.s,"fact.s");
function fib(n)
{
if (n < 2,v,fib(n - 2) * fib(n - 1));
}
println("fib(6) is ",fib(6));
println("fact(6) is ",fact(6));
Running the fact.s program yields:
fib(5) is 5
fact(5) is 120
while running the fib.s program yields:
fib(6) is 8
fact(6) is 720
The first argument passed to the includeOnce
function must be a variable, but this variable
does not necessarily have to be defined.
The includeOnce function checks to see if its
first argument has already been defined.
If the variable already exists, no further action is
taken.
If not, includeOnce defines it with a value of
:true and
then includes the module named by the second argument.
Due to Sway's lax naming rules for variable names,
most file names (including Unix style paths)
without spaces are legal variable names.
By convention,
the variable name given to includeOnce is the name of the file containing the module; though
any variable name will suffice. If there is a name clash, however, and the variable is already
declared through some other means, the given module will not be included.
The includeOnce function only checks to see if the first
argument
is defined in the current local scope,
so the check against multiple includes will not
work if you include once again at a different scope level.
The include and includeOnce function are the only functions that
are considered definitions and thus can appear in the definition area
of a Sway module. It is legal, however, to call either
function in an expression, as in:
x = includeOnce(:module1.s,"module1.s");
Of course, such calls to include and
includeOnce are not
part of the definition area. In the following example, only the top level definitions from
modules B and C are included in A.
A.s
include("B.s");
...
B.s
include("C.s");
var x;
x = include("D.s");
The definitions from module D.s are not included
into A.s since only the
definition area of
B.s is included in A.s
(which causes an include of C.s).
The call to include D.s is in the
expression area and is ignored when B.s is included.
Functions More about Functions