273 lines
14 KiB
HTML
273 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<title>Felise - A walkthrough</title>
|
|
<style>
|
|
main,header{width: 900px;max-width: 90vw;margin: 3em auto}
|
|
pre {padding:1rem;width:calc(100% - 2rem);color:#EEE;border-radius:10px;background:#262626; margin: 3em auto}
|
|
samp > pre{color:lime}
|
|
pre{letter-spacing:1px;line-height:1.5em;font-size:1.2em;font-weight:bold}
|
|
pre .com{color:#5897bb;font-weight:normal}
|
|
pre .value{color:#f35e5e}
|
|
pre .type{color:#73ab23}
|
|
pre .sp1{color:#45af60}
|
|
pre .sp2{color:#d58d08}
|
|
pre .err{color:#bd80f9}
|
|
h1{color:rebeccapurple}
|
|
small{color: #444}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<h1>Felise<br><small>a concatenative procedural programming language</small></h1>
|
|
</header>
|
|
<main>
|
|
<p>This is a walkthrough of the <i>Felise</i> programming language. <i>Felise</i> is loosely situated as a concatenative programming language. It is an interpreted language (it requires the <i>felise</i> interpreter on the system to run programs) in its present form.</p>
|
|
<p>This walkthrough will be done by example. If you would like to follow along in the <abbr title="Read Evaluate Print Loop">repl</abbr>, you can clone the repository <a href="https://tildegit.org/sloum/felise" target="_blank">here</a>. The repl features tab completion for all procedures and has a few quality of life options. Feel free to skip around as your level of experience dictates. If you are fully new to stack based/concatenative programming, maybe try reading a bit of the <a href="https://en.wikipedia.org/wiki/Stack-oriented_programming" target="_blank">wikipedia article</a> on the subject first. With that said, let's get to it…</p>
|
|
<section>
|
|
<pre><code><span class="com"># This is a comment
|
|
|
|
| This is also a comment, but it is
|
|
used for docstrings (procedure
|
|
documentation). It is multiline.
|
|
More on this later. |</span>
|
|
|
|
|
|
<span class="com"># Add/View values to/on the stack
|
|
# ===============================</span>
|
|
|
|
<span class="value">5 1.3</span> <span class="value">"Hello"</span>
|
|
|
|
stackdump <span class="com"># Take a look at the stack</span>
|
|
drop <span class="com"># Throw away TOS ("Hello")</span>
|
|
println <span class="com"># Pop and print TOS w/ a newline</span>
|
|
print <span class="com"># Pop and print TOS w/ no newline</span>
|
|
|
|
stackdepth println <span class="com">#=> 0</span>
|
|
|
|
|
|
<span class="com"># Let's do some "math" on the stack
|
|
# =================================</span>
|
|
|
|
<span class="value">2 3</span> + println <span class="com">#=> 5</span>
|
|
<span class="value">2 3.2</span> + println <span class="com">#=> 5.2; INT coerces to FLOAT</span>
|
|
<span class="value">2.25 3.1</span> + println <span class="com">#=> 5.35</span>
|
|
<span class="value">"Hello" "World"</span> + println <span class="com">#=> HelloWorld</span>
|
|
<span class="value">"Hello" 55</span> + println <span class="com">#=> Hello55</span>
|
|
|
|
<span class="value">2 3</span> - println <span class="com">#=> -1</span>
|
|
<span class="value">2.25 3.1</span> - println <span class="com">#=> -0.8500000000000001</span>
|
|
<span class="value">"Hello World" "o"</span> - println <span class="com">#=> HellWrld</span>
|
|
<span class="value">"H3ll0 W0rld" 0</span> - println <span class="com">#=> H3ll Wrld ; 0 is INT & coerces to STRING</span>
|
|
[ <span class="value">"Hi" "Hello" "Hi"</span> ] <span class="value">"Hi"</span> - println <span class="com">#=> [ "Hello" ]</span>
|
|
[ <span class="value">1 2.25</span> <span class="value">"Hi"</span> ] <span class="value">2.25</span> - println <span class="com">#=> [ 1 "Hi" ]</span>
|
|
|
|
<span class="value">2 3</span> / println <span class="com">#=> 0</span>
|
|
<span class="value">2.25 3.1</span> / println <span class="com">#=> 0.7258064516129032</span>
|
|
<span class="value">"Hello World" " "</span> / println <span class="com">#=> [ "Hello" "World" ] ; split into LIST</span>
|
|
|
|
<span class="value">2 3</span> * println <span class="com">#=> 6</span>
|
|
<span class="value">2.25 3.1</span> * println <span class="com">#=> 6.9750000000000005</span>
|
|
<span class="value">"Hello World" 2</span> * println <span class="com">#=> Hello WorldHello World</span>
|
|
[ <span class="value">"Hello" "World"</span> ] <span class="value">"__"</span> * println <span class="com">#=> "Hello__World" ; Join LIST to STRING</span>
|
|
|
|
|
|
<span class="com"># Let's work with variables
|
|
# =========================
|
|
|
|
# Declare the type then the keyword
|
|
# then the variable name</span>
|
|
|
|
<span class="type">INT</span> <span class="sp1">var!</span> myInt
|
|
|
|
myInt println <span class="com">#=> 0
|
|
|
|
# The new var takes on the "zero" value of the type
|
|
# using 'myVar' above adds the value of myVar to TOS
|
|
|
|
# Set the variable as follows:</span>
|
|
<span class="value">5</span> <span class="sp1">set!</span> myInt
|
|
myInt println <span class="com">#=> 5
|
|
|
|
# You cannot set a variable to a value of a type that
|
|
# does not match the declared type:</span>
|
|
|
|
<span class="value">"Nope"</span> <span class="sp1">set!</span> myInt <span class="com">#=> ERROR!!!!!</span>
|
|
|
|
clearstack <span class="com">#=> Clears the stack</span>
|
|
|
|
<span class="com"># Note: variables are local to the scope they are
|
|
# created in, and are accessible to child scopes</span>
|
|
|
|
|
|
<span class="com"># Let's work boolean logic
|
|
# ========================
|
|
|
|
# Tip: false, 0, [], and {} are all falsy</span>
|
|
|
|
<span class="value">5 3</span> > println <span class="com">#=> true</span>
|
|
<span class="value">5 3</span> < println <span class="com">#=> false</span>
|
|
<span class="value">5 3</span> >= println <span class="com">#=> true</span>
|
|
<span class="value">5 3</span> <= println <span class="com">#=> false</span>
|
|
<span class="value">5 3</span> = println <span class="com">#=> false</span>
|
|
<span class="value">5 3</span> != println <span class="com">#=> true</span>
|
|
<span class="value">5 3</span> = not println <span class="com">#=> true</span>
|
|
<span class="value">true false</span> and <span class="com">#=> false</span>
|
|
<span class="value">true false</span> or <span class="com">#=> true</span>
|
|
<span class="value">5</span> type <span class="type">FLOAT</span> = <span class="com">#=> false</span>
|
|
<span class="value">5</span> type <span class="type">INT</span> = <span class="com">#=> false</span>
|
|
|
|
<span class="value">5 3</span> > <span class="sp2">if</span>
|
|
<span class="value">"Bigger"</span> println
|
|
<span class="sp2">else</span>
|
|
<span class="value">"Smaller"</span> println
|
|
<span class="sp2">end</span> <span class="com">#=> Bigger</span>
|
|
|
|
|
|
<span class="com"># Let's cast some values
|
|
# ======================
|
|
|
|
# The available types are:
|
|
# INT, FLOAT, STRING, BOOL, TYPE, LIST, DICT</span>
|
|
|
|
<span class="value">5</span> <span class="type">FLOAT</span> cast println <span class="com"># Our INT (5) is now a FLOAT (5.0)</span>
|
|
<span class="value">"5"</span> <span class="type">FLOAT</span> cast println <span class="com"># Our STRING ("5") is now a FLOAT (5.0)</span>
|
|
<span class="value">"5"</span> <span class="type">INT</span> cast println <span class="com"># Our STRING ("5") is now an INT (5)</span>
|
|
|
|
<span class="value">"5"</span> <span class="type">BOOL</span> cast println <span class="com"># Our STRING ("5") is now a BOOL (true)</span>
|
|
<span class="value">""</span> <span class="type">BOOL</span> cast println <span class="com"># Our STRING ("") is now a BOOL (false)</span>
|
|
<span class="value">0</span> <span class="type">BOOL</span> cast println <span class="com"># Our INT (0) is now a FLOAT (false)</span>
|
|
|
|
<span class="value">5</span> <span class="type">STRING</span> cast println <span class="com"># Our INT (5) is now a STRING ("5")</span>
|
|
|
|
|
|
<span class="com"># Let's use LISTs and DICTs
|
|
# =========================
|
|
|
|
# Get values (A LIST can hold any type, including LIST)</span>
|
|
[ <span class="value">"Hello" "world"</span> ] <span class="value">1</span> <- println <span class="com">#=> Hello</span>
|
|
[ <span class="value">"Hello" "world"</span> ] <span class="value">2</span> <- println <span class="com">#=> world</span>
|
|
[ <span class="value">"Hello" "world"</span> ] <span class="value">-1</span> <- println <span class="com">#=> world</span>
|
|
|
|
<span class="com"># It works mostly the same with a DICT
|
|
# Note that DICT keys must be STRINGs, but values
|
|
# can be of any type (including a DICT)</span>
|
|
{ <span class="value">
|
|
"age" 33
|
|
"weight" 150
|
|
"hair" "brown"
|
|
"smoker" false</span>
|
|
} <span class="value">"age"</span> <- println <span class="com">#=> 33</span>
|
|
|
|
<span class="com"># Append a new item...</span>
|
|
[ <span class="value">"Hello" "world"</span> ] <span class="value">false</span> => println <span class="com">#=> [ "Hello" "world" false ]</span>
|
|
|
|
<span class="com"># For a DICT just set a new key as a value...</span>
|
|
{ } <span class="value">"happy" true</span> -> println <span class="com">#=> { "happy" true }</span>
|
|
|
|
<span class="com"># Change the value of an existing index/key...</span>
|
|
[ <span class="value">"Hello" "world" false</span> ] <span class="value">3 "!"</span> -> println <span class="com">#=> [ "Hello" "world" "!" ]</span>
|
|
{ <span class="value">"age" 33 "weight" 150</span> } <span class="value">"age" 34</span> println <span class="com">#=> { "age" 34 "weight" 150 }</span>
|
|
|
|
|
|
<span class="com"># Let's write a procedure
|
|
# =======================
|
|
|
|
# We'll iterate over building a simple procedure
|
|
# Let's call it `square`. It will take a number
|
|
# (INT or FLOAT) and multiply it times itself</span>
|
|
|
|
<span class="sp2">proc</span> square
|
|
dup * <span class="com"># dup will add a copy of the top stack item to the stack</span>
|
|
<span class="sp2">end</span>
|
|
|
|
<span class="com"># That works, but let's make sure we don't
|
|
# get weird side effects (squaring a non-number)</span>
|
|
<span class="sp2">proc</span> square
|
|
dup type <span class="type">INT</span> = over type <span class="type">FLOAT</span> = or <span class="sp2">if</span>
|
|
dup *
|
|
<span class="sp2">else</span>
|
|
<span class="value">"`square` expected an INT, but found "</span>
|
|
swap type + <span class="com"># Move the STRING under the top stack
|
|
# value, get the type, and append it to the STRING</span>
|
|
<span class="err">throw</span> <span class="com"># then throw an error with a value of the STRING</span>
|
|
<span class="sp2">end
|
|
end</span>
|
|
|
|
<span class="com"># Let's add a docstring so people will know how to use it
|
|
# It is standard to include what it takes from the stack,
|
|
# if it forward reads a symbol, and what it puts on the stack.
|
|
# It is also good to leave a note that describes what happens.</span>
|
|
<span class="sp2">proc</span> square
|
|
<span class="com">| Stack: INT/FLOAT
|
|
Read :
|
|
Push : INT/FLOAT
|
|
Notes: Takes an INT or FLOAT and pushes the square of the same type to TOS |</span>
|
|
dup type <span class="type">INT</span> = over type <span class="type">FLOAT</span> = or <span class="sp2">if</span>
|
|
dup *
|
|
<span class="sp2">else</span>
|
|
<span class="value">"`square` expected an INT, but found "</span>
|
|
swap type + <span class="com"># Move the STRING under the top stack
|
|
# value, get the type, and append it to the STRING</span>
|
|
<span class="err">throw</span> <span class="com"># then throw an error with a value of the STRING</span>
|
|
<span class="sp2">end
|
|
end</span>
|
|
|
|
<span class="value">5</span> square println <span class="com">#=> 25</span>
|
|
|
|
<span class="com"># We can read the docstring, too...</span>
|
|
docstring! square println
|
|
<span class="com">#=>`square`
|
|
# Stack: INT/FLOAT
|
|
# Read :
|
|
# Push : INT/FLOAT
|
|
# Notes: Takes an INT or FLOAT and pushes the square of the same type to TOS |</span>
|
|
|
|
|
|
<span class="com"># Reading Internal Docs
|
|
# =====================
|
|
|
|
# To see all procedures the system knows about:</span>
|
|
words println
|
|
|
|
<span class="com"># The above will add a STRING to TOS that lists every proc name
|
|
# that the system knows. When you create a proc, it will show up
|
|
# in the STRING produced by `words`
|
|
|
|
# Now that you know the proc names, you can use `docstring!` to
|
|
# see what they do and how to use them:</span>
|
|
|
|
docstring! net-get println <span class="com">#=>
|
|
# `net-get`
|
|
# Stack: STRING
|
|
# Read :
|
|
# Push : DICT
|
|
# Notes: Takes a gemini, gopher, or http(s) url STRING from TOS.
|
|
# A response DICT will be left on the stack, key "success"
|
|
# will be a BOOL declaring whether or not the request was
|
|
# successful, key "status" will be the status code of the
|
|
# response (or -1 if there is no status code), key "body"
|
|
# will be the response body. If the response was successful
|
|
# key "body" will be the actual body of the response, if
|
|
# it was not successful it will be an error message.
|
|
|
|
# Try importing a library and seeing the listing in `words` change</span>
|
|
<span class="value">"strings"</span> import
|
|
words println
|
|
|
|
<span class="com"># Now you can see things like `string-to-lower`, which was not
|
|
# available before. Note: `import` consumes a string with
|
|
# a standard builtin package ("math", "paths", "stack",
|
|
# and "strings"), but you can also pass it a string that
|
|
# represents a filepath to a felise file to import</span>
|
|
|
|
docstring! string-to-lower println
|
|
</code></pre>
|
|
<p>
|
|
That is enough to get you going with the basics of felise. There are a lot more complicated things present in the language that allow meta-programming, functional programming, interacting with a *nix environment, etc. Plus a lot of built in procs that can do neat things. Play around and you will find cool things to do. The <a href="https://tildegit.org/sloum/felise/src/branch/master/README.md" target="_blank">README.md</a> that comes in the <a href="https://tildegit.org/sloum/felise" target="_blank">source code repository</a> has information about a number of these features, as well as some language "gotchas", installation information, and other good info.
|
|
</p>
|
|
</section>
|
|
</main>
|
|
</body>
|
|
</html>
|