MuffinScript is a delectably simple programming language baked for fun, not for fame. It’s not going to win any speed records (it’s built on Python), can't be used for integrated circuits, nor will it dazzle you with cutting-edge features. What it will do is make writing tiny scripts feel like a treat.
MuffinScript is all about the basics: variables, arithmetic, strings, lists, loops, and conditionals, served up with a syntax that’s easy to read and a parser that’s forgiving enough for beginners but robust enough for tinkerers. You get a REPL for instant feedback, clear error messages with a dash of color, and a standard library that covers the essentials (printing, type checking, string concatenation, sleeping, etc).
It’s a proof of concept, a playground, and a learning tool. If you want to see how a programming language is built from scratch, MuffinScript is your open kitchen.
- Data types:
str
(either"
or'
work),int
,float
,bool
,list
,null
- Arithmetic:
+
,-
,*
,/
,%
- Comparison operators:
==
,!=
,>
,>=
,<
,<=
- Variable assignment:
foo = "hello world"
- String interpolation:
foo = "hello #{bar}"
- Type coercion:
str(2)
,int("2")
,float("2.5")
- If statements:
if (foo == bar) { ... }
- Else statements:
if (...) { ... } else { ... }
- Else statements:
- Foor loops:
for (item in myList) { ... }
- Lists:
[1, 2, 3]
- Lists:
- Comments (inline and standalone):
// This is a comment
- Clear, colored error messages:
ERROR - Invalid expression | line: 3
- REPL: Use
muffin
to enter - Standard library
- Print to console:
p("hello world")
- Type checking:
type("hello world")
- String concatenation:
cat("hello ", foo)
- Sleep:
sleep(10.5)
- Print to console:
- Debug mode by passing
MUFFIN_DEBUG=true
# Homebrew install
brew tap justintime50/formulas
brew install muffinscript
# Install locally
just install
# Build from source
just build
NOTE: All variables are global (this includes item
in for loops).
// Variable assignment and printing
foo = "hello world"
p(foo)
// Simple arithmetic (add, subtract, multiply, divide, modulo)
p(2 + 2.5)
// Concatenate strings
p(cat("I say ", foo))
// If statements
if (foo == bar) {
p(true)
} else {
p(false)
}
// For loops
for (item in [1, 2, 3]) {
p(item + 1)
}
Commands:
# Run the Muffin interpreter on a Muffinscript file
muffin filename.ms
# REPL
muffin
# Help
muffin --help
# Version
muffin --version
Check out the MuffinScript VS Code Extension to get syntax highlighting for MuffinScript.
The AST is the recipe book for MuffinScript. It defines the basic ingredients like what counts as a string, a number, or a variable.
The lexer is the kitchen assistant. It takes raw text and chops it up into tokens by identifying keywords, numbers, strings, and symbols.
- Example: p("hello world") becomes p, (, "hello world", )
- Spots errors in characters
- Converts tokens to their proper types
The parser is the chef who checks the recipe. It looks at the tokens and makes sure they follow MuffinScript’s grammar rules.
- Decides which combinations of tokens are valid
- Catches syntax mistakes
The interpreter is the baker. It reads the AST and actually runs your code by printing values, assigning variables, and more executing the code.
- BUG: line numbers for errors are off in block statements (eg:
if
,for
) due to us buffering the entire block and parsing it as one set of tokens instead of each line of tokens individually (the parser will only know the line number of the end of the block by the time it runs error checking) - Variables don't have their own node in the AST but should
- List operations (append, pop, index)
- Functions
- Error handling
- Imports
- Package manager (StudMuffin)
- Call the directory packages are stored
oven
and the packagesingredients
- Use GitHub as source of packages
- Call the directory packages are stored
- Automate releasing
Releasing must be done manually for now:
- Clean any temp files (coverage, venv, etc)
- Run
just build
locally - Tar up repo:
tar -czvf v0.1.0.tar.gz dist
- Upload
tar
to release - Update Homebrew formula tar link and checksum:
shasum -a 256 v0.1.0.tar.gz