2 stable releases
1.0.1 | Mar 19, 2024 |
---|---|
1.0.0 | Mar 5, 2024 |
#925 in Programming languages
255 downloads per month
Used in 3 crates
64KB
1.5K
SLoC
SAP (Simple As Possible)
SAP is a simple programming language designed to be easy to learn and use. It is a dynamically typed language with a simple syntax and a small set of features.
It is designed to be a good language for beginners to learn programming, sitting somewhere between a language like Python and Scratch.
SAP is implemented in Rust and uses a tree-walking interpreter to execute programs.
Features
SAP has a small set of simple, yet powerful features, including:
- Dynamic typing and type coercion
- Simple syntax (intuitive for beginners)
- Variables
- Repetition (looping)
- Functions
- Closures
- Control flow (conditionals)
- Displaying to console
- Error messages
- Command line tool
Quick start
There is an online playground available if you want try out the language without installing anything. To run SAP programs locally, you can install the sap
command line tool using Cargo:
cargo install sap-cli
Once installed, use sap --help
to see the available options, or to run a SAP program, use the sap
command followed by the path to the SAP program:
sap path/to/program.sap
Building from source
If you want to build the interpreter from source, you can clone the repository and build the workspace crate using build.bat
(Windows) or Cargo:
git clone https://github.com/Shuppin/sap.git
cd sap
cargo build --release
This will automatically build the sap
command line tool.
Examples
To see some examples of SAP programs, see the examples directory.
Here is a simple example of a SAP program that prints the first 10 numbers in the Fibonacci sequence:
defineFunction fib(n)
if n < 2 then
return n
otherwise
return fib(n - 1) + fib(n - 2)
end
end
set i = 0
repeat 10 times
display fib(i)
set i = i + 1
end
Implmentation
The SAP interpreter is implemented in Rust. The code is split into a number of crates, including:
lexer
: Tokenises the input source code.ast
: Defines the abstract syntax tree (AST) for the language.parser
: Parses the token stream into an abstract syntax tree (AST).interpreter
: Walks the AST and executes the program.cli
: Command line tool for running SAP programs.shared
: Shared code used by multiple modules.playground
: (Not part of the interpreter) Web-based playground for running SAP programs.
Code is parsed using a recursive descent parsing algorithm, and executed using a tree-walking algorithm.
Currently, error messages are not very helpful, but the framework is in place to improve this in the future.
Dependencies
SAP is designed to have minimal dependencies. The only external dependency is the serde
crate, which is used for serialising and deserialising the AST. The cli
crate also uses os_info
, ctrlc
, and clap
for command line argument parsing and handling.
Testing
SAP has a suite of unit tests. The unit tests are run using cargo test
. These tests cover all language features.
Documentation
Since this is a learning project, the code is heavily commented, a mixture of documentation and explanation of the code. I've tried to make the comments as helpful as possible, and the flow of the code as clear as possible, to make it easier for others to understand.
I will admit, the interpreter could be improved, the control flow is a bit of a mess, especially if you aren't familiar with the ControlFlow
type.
If you are here to learn, these are the resources I used to learn about interpreters and compilers:
- Let's Build a Simple Interpreter by Ruslan Spivak
- This series is aimed at beginners and is a great introduction to interpreters and compilers. (This is actually the series I followed when making the original version of SAP.)
- Writing An Interpreter In Go by Thorsten Ball
- This book delves into the details of writing an interpreter a bit quicker than the previous series, but is still very accessible.
Here's what I plan to read next:
- Writing a Compiler in Go by Thorsten Ball
- This book is a follow-up to the previous book, and covers writing a compiler.
- A Practical Approach to Compiler Construction by Des Watson
- This book is aimed at a more advanced audience, and covers the theory and practice of writing a compiler in much more detail.
Playground
The playground
crate wont compile in it's current state, as it is primarily designed for automatic deployment to GitHub Pages. If you wish to run the playground locally, follow these steps:
- Update line 1 of /playground/web/script.js to
import init, {interpret, parse, lex} from "../pkg/playground.js";
- Move the contents of /playground/web into /playground.
- Install wasm-pack using
cargo install wasm-pack
- Build the
playground
crate usingwasm-pack build ./playground --target web
- Serve the
playground
crate using whatever method you prefer (e.g.python -m http.server
).
lib.rs
:
Abstract Syntax Tree (AST) Module
The AST module contains the definitions for the abstract syntax tree (AST) nodes generated by the parser. The AST nodes are used to represent the structure of the source code in a tree-like format, which can be used to perform various analysis and evaluation tasks on the code.
The AST nodes are defined as Rust structs, and are serialisable to JSON using the
serde
library. This allows the AST to be easily converted to a JSON string for
debugging and analysis purposes.
The AST module is divided into sub-modules, each of which contains the definitions for a specific type of AST node, such as expressions, statements, and literals.
The AST module also contains a Program
struct, which is the root node for all
syntax trees generated by the parser. The Program
struct contains a list of
statements, which represent the top-level statements in the source code.
Dependencies
~0.7–1.6MB
~35K SLoC