Shaun Language Reference

Version 0.4 · the programming language where your compiler is Shaun and he is watching.

Shaun programs are written in .shaun files. The compiler (shaunc) turns them into real native programs (a Windows .exe or a Linux executable) with no other tools involved.

1. Quick start

Register

Shaun.Say("What is your name? ")
Student name = Shaun.Listen()
Shaun.ShaunOutput("Hello, " + name + "!")

Dismissed

Open Shaun Studio (studio.bat), paste this in, and press F5. Type your name in the box under the output when the program asks.

2. Program structure

Every program starts with Register and ends with Dismissed. Everything in between runs from top to bottom.

Register

// Lessons (functions) and statements go here
Shaun.ShaunOutput("Hello class")

Dismissed

3. Values and types

Type Written as Examples Notes
Number digits 0, 42, -7 Whole numbers (64-bit)
Words "double quotes" "Hello", "" Text. Escapes: \n new line, \t tab, \" quote, \\ backslash
Decimal digits with a point 3.14, 0.5, -2.75 Numbers with a fractional part (64-bit)
Correct / Wrong the two words Correct, Wrong True and false
List [ items ] [1, 2, 3], ["a", "b"] Many values of one kind in order (section 10)

A variable keeps the type of the first value you give it. You can't put words into a number variable. A decimal variable accepts a whole number (price = 5 becomes 5.0), but a number variable doesn't accept a decimal: start it with Student total = 0.0 if you will add decimals to it.

4. Variables: Student

Register
Student age = 15
Student name = "Stefan"
Student passed = Correct

age = age + 1
Shaun.ShaunOutput(age)

Dismissed

5. Operators

Operator Works on Meaning
+ - * / numbers, decimals add, subtract, multiply, divide. Two whole numbers give a whole number (so 7 / 2 is 3, rounded toward zero). If either side is a decimal, the answer is a decimal (7 / 2.0 is 3.5)
% whole numbers remainder
+ words (and anything) join: if either side is words, the other side becomes words too
< > <= >= numbers, decimals, words comparisons, give Correct/Wrong. Words go alphabetically (capitals come before small letters)
== != two values of the same type equal / not equal (words compare their letters)
! Correct/Wrong not (flips Correct and Wrong)
- (before a value) numbers negative

The logical operators are && (and) and || (or). They work on Correct/Wrong, and the right side only runs if it is needed.

Order of work (first to last): - ! · * / % · + - · < > <= >= · == != · && · ||. Use ( ) to be sure.

Register
Student age = 17
Shaun.ShaunOutput("In 10 years: " + (age + 10))   // joins words and a number
Shaun.ShaunOutput(age > 17 || age == 17)           // Correct
Shaun.ShaunOutput(-7 % 3)                          // -1
Dismissed

Dividing by zero stops the program with Shaun's disappointment.

6. Output

Function What it does
Shaun.ShaunOutput(value) prints the value, then starts a new line
Shaun.Say(value) prints the value and stays on the same line (good for questions)

Numbers print as digits, words print as text, and Correct/Wrong print as Correct / Wrong.

7. Input

Function Gives back What it does
Shaun.Listen() words waits for the user to type a line and press Enter
Shaun.ListenNumber() number same, but keeps asking until the user types a valid number (e.g. 42 or -5)
Shaun.ListenDecimal() decimal keeps asking until the user types a number like 3.5 (whole numbers such as 7 are fine too)
Register
Shaun.Say("Pick a number: ")
Student n = Shaun.ListenNumber()
Shaun.ShaunOutput("Double that is " + n * 2)
Shaun.Say("Press Enter to finish.")
Shaun.Listen()
Dismissed

8. Word tools

Functions for working with words. Positions start counting at 0 (the first letter is position 0).

Function Gives back What it does
Shaun.Length(words) number how many characters
Shaun.Upper(words) words CAPITAL letters
Shaun.Lower(words) words lower case letters
Shaun.Trim(words) words without spaces or tabs at the start and end
Shaun.Contains(words, part) Correct/Wrong is the part somewhere inside? (capitals matter)
Shaun.Find(words, part) number the position where the part first appears, or -1 if it isn't there
Shaun.Part(words, start, count) words a piece: count characters from position start
Shaun.ToNumber(words) number turns "42" or "-5" into a number (gives 0 if it isn't one)
Shaun.IsNumber(words) Correct/Wrong is it a whole number?
Register
Student name = "  shaun  "
Student clean = Shaun.Trim(name)
Shaun.ShaunOutput(Shaun.Upper(clean))                      // SHAUN
Shaun.ShaunOutput(Shaun.Length(clean))                     // 5
Shaun.ShaunOutput(Shaun.Find(clean, "un"))                 // 3
Shaun.ShaunOutput(Shaun.Part(clean, 0, 1))                 // s
Shaun.ShaunOutput(Shaun.ToNumber("40") + 2)                // 42
Dismissed

9. Decimals and maths

Write a decimal with a point: 3.14. Decimals mix freely with whole numbers (the answer is a decimal).

Function Gives back What it does
Shaun.Pi() decimal 3.141593...
Shaun.Root(x) decimal square root
Shaun.Power(x, n) same kind as x x multiplied by itself n times (n is a whole number, 0 or more)
Shaun.Absolute(x) same kind as x without the minus sign
Shaun.Floor(x) whole number rounds down
Shaun.Ceil(x) whole number rounds up
Shaun.Round(x) whole number nearest whole number (halves round away from zero: 2.5 is 3, -2.5 is -3)
Shaun.Fixed(x, places) words exactly that many digits after the point, for tidy output: Fixed(3.5, 2) is "3.50"
Shaun.ToDecimal(words) decimal "3.14" to 3.14 (0.0 if it isn't a number)
Shaun.IsDecimal(words) Correct/Wrong is it a number (with or without a point)?
Shaun.ListenDecimal() decimal read a decimal from the keyboard
Register

Shaun.Say("Price of one item: ")
Student price = Shaun.ListenDecimal()
Shaun.Say("How many? ")
Student count = Shaun.ListenNumber()

Student total = price * count
Shaun.ShaunOutput("Total: " + Shaun.Fixed(total, 2))
Shaun.ShaunOutput("With 20% VAT: " + Shaun.Fixed(total * 1.2, 2))

Dismissed

10. Lists

A list holds many values of the same kind, in order. Positions start at 0.

Register

Student scores = [72, 58, 91]
Shaun.ShaunOutput(scores)             // [72, 58, 91]
Shaun.ShaunOutput(scores[0])          // 72
scores[1] = 60                        // change an item
Shaun.Add(scores, 85)                 // put one on the end
Shaun.ShaunOutput(Shaun.Length(scores))   // 4

Dismissed
Function Gives back What it does
Shaun.Length(list) number how many items
Shaun.Add(list, item) nothing puts the item on the end
Shaun.RemoveAt(list, position) nothing takes out the item at that position
Shaun.Pop(list) the item takes the last item off and gives it back
Shaun.Sort(list) nothing smallest first (words alphabetically). Keeps equal items in their order
Shaun.Reverse(list) nothing turns the list round
Shaun.Shuffle(list) nothing random order
Shaun.Sum(list) number or decimal adds a list of numbers or decimals
Shaun.Max(list) / Shaun.Min(list) the item biggest / smallest (words: last / first alphabetically)
Shaun.Contains(list, item) Correct/Wrong is the item in the list?
Shaun.Find(list, item) number position of the first match, or -1
Shaun.Choose(list) the item a random item
Shaun.Join(list of words, separator) words glue words together: Join(["a", "b"], "-") is "a-b"
Shaun.Split(words, separator) list of words chop words up (an empty separator gives single letters)

Looping over a list: Homework(item in list) { ... } runs the block once for each item. It works on words too: Homework(letter in "hello"). LeaveEarly and SkipThis work as usual.

Register

Student names = ["Zoe", "Bob", "Amy"]
Shaun.Sort(names)

Homework(name in names) {
    Shaun.ShaunOutput("Hello, " + name)
}
Shaun.ShaunOutput(Shaun.Join(names, ", "))

Dismissed

Starting with an empty list: Student found = [] makes a list with nothing in it. The first Shaun.Add decides what it holds (numbers, words...). Until then Shaun can't tell, so you can't print it or loop over it yet.

11. Random numbers

Function Gives back What it does
Shaun.Pick(a, b) number random whole number from a to b, both included
Shaun.Random() decimal random decimal from 0 up to (not including) 1
Shaun.Choose(list) the item random item from a list
Shaun.Shuffle(list) nothing mix a list up
Register

Shaun.Say("How many dice? ")
Student count = Shaun.ListenNumber()
Student total = 0

Homework(i from 1 to count) {
    Student roll = Shaun.Pick(1, 6)
    Shaun.ShaunOutput("Dice " + i + ": " + roll)
    total = total + roll
}
Shaun.ShaunOutput("Total: " + total)

Dismissed

12. Decisions: Shaun.Checks and Detention

Register
Student mark = 62
Shaun.Checks(mark >= 70) {
    Shaun.ShaunOutput("Distinction")
} Detention {
    Shaun.Checks(mark >= 50) {
        Shaun.ShaunOutput("Pass")
    } Detention {
        Shaun.ShaunOutput("See me after class")
    }
}
Dismissed

Shaun.Checks(condition) { ... } runs the block if the condition is Correct. The optional Detention { ... } runs otherwise. The condition must be Correct/Wrong, not a number.

Else-if: put another Shaun.Checks straight after Detention to chain decisions without nesting:

Register
Student mark = 62
Shaun.Checks(mark >= 70) {
    Shaun.ShaunOutput("Distinction")
} Detention Shaun.Checks(mark >= 50) {
    Shaun.ShaunOutput("Pass")
} Detention {
    Shaun.ShaunOutput("See me after class")
}
Dismissed

The first condition that is Correct wins, and the rest are skipped.

13. Loops

UntilTheBell: repeat while something is true

Register
Student countdown = 3
UntilTheBell(countdown > 0) {
    Shaun.ShaunOutput(countdown)
    countdown = countdown - 1
}
Shaun.ShaunOutput("Bell!")
Dismissed

The condition is checked before each go. If it never becomes Wrong the program runs forever (Shaun Studio stops it after 60 seconds, or press Stop).

Homework: count from one number to another

Register
Homework(i from 1 to 5) {
    Shaun.ShaunOutput(i + " squared is " + i * i)
}
Dismissed

LeaveEarly and SkipThis

Inside any loop (UntilTheBell or Homework):

Register
Homework(i from 1 to 10) {
    Shaun.Checks(i % 2 == 0) {
        SkipThis
    }
    Shaun.Checks(i > 7) {
        LeaveEarly
    }
    Shaun.Say(i + " ")
}
Shaun.ShaunOutput("")
Dismissed

This prints 1 3 5 7. In a loop inside a loop, they only affect the inner loop. Using them outside a loop is an error.

14. Lessons (functions)

Register

Lesson Square(n) {
    HandIn n * n
}

Lesson Biggest(items) {
    Student best = items[0]
    Homework(i in items) {
        Shaun.Checks(i > best) {
            best = i
        }
    }
    HandIn best
}

Shaun.ShaunOutput(Square(5))
Shaun.ShaunOutput(Square(1.5))
Shaun.ShaunOutput(Biggest([3, 9, 2]))
Shaun.ShaunOutput(Biggest(["pear", "apple", "zebra"]))

Dismissed

15. Every word Shaun knows

Word Used for
Register, Dismissed start and end of a program
Student make a variable
Lesson, HandIn make a function, give back an answer
Shaun.Checks, Detention if / else
UntilTheBell, Homework loops
LeaveEarly, SkipThis leave a loop / skip to the next go
Shaun.ShaunOutput, Shaun.Say output
Shaun.Listen, Shaun.ListenNumber input
Shaun.Length, Upper, Lower, Trim, Contains, Find, Part, ToNumber, IsNumber word tools
Shaun.ToDecimal, IsDecimal, Root, Power, Absolute, Floor, Ceil, Round, Fixed, Pi, ListenDecimal decimals and maths
Shaun.Add, RemoveAt, Pop, Sort, Reverse, Sum, Max, Min, Join, Split lists
Shaun.Pick, Random, Choose, Shuffle random
Correct, Wrong true / false

These names can't be used for your own variables or lessons. (from, to and in are only special inside Homework( ... ).) Variable and lesson names use letters, numbers and _, and can't start with a number. Names are case-sensitive.

16. Errors and Shaun's mood

The compiler stops at the first mistake, tells you the line, and gets angrier the more mistakes you make in a row. Fix it and run successfully, and he calms down.

Mistakes in a row Shaun's reaction
1 disappointed
2 sighs
3 angry
4 FURIOUS (detention)
5+ calls your parents

In Shaun Studio the face in the bottom bar changes too (😊 😐 😒 😠 🤬). The command line remembers your streak for 30 minutes.

Common messages

Message (start) What went wrong
You didn't 'Register' for class the program doesn't start with Register
Class never ended no Dismissed at the end
Who is 'x'? That student isn't in my class you used a variable that doesn't exist (check the spelling, or its block)
'x' holds a number, but you gave it words wrong type in an assignment
There is already a student called 'x' two Student x in the same block
You can't compare a number with words == / != need the same type on both sides
'+' needs a number on both sides you tried to add something that isn't a number (use words on one side to join)
There is no Lesson called 'X' calling a lesson that isn't defined
Lesson 'X' needs 2 answers but you gave 1 wrong number of arguments
I expected '...' here missing bracket, quote or keyword
You forgot a closing '}' a { was never closed
You can't LeaveEarly when you're not in a loop LeaveEarly or SkipThis used outside UntilTheBell / Homework
Shaun.Length wants words here a word tool was given the wrong type
Shaun.Part needs 3 answers but you gave 2 wrong number of values for a word tool
'n' holds a number, but you gave it a decimal a whole-number student can't take decimals: start it with Student n = 0.0
Everything in a list must be the same kind a mixed list like [1, "a"]
I don't know what's in that list yet you used an empty list [] before adding anything to it
That list holds a number, but you tried to Add words wrong kind of item for the list
This lesson hands back a number in one place but words here the HandIns disagree
I can't tell yet what 'X' hands back a lesson calls itself before any plain HandIn

Errors while the program runs

Message Cause
Shaun: You can't divide by zero / or % with 0 on the right
Shaun: I've run out of paper the program used all of its 32 MB of word memory (for example, joining words in a huge loop)
Shaun: Nobody is answering Shaun.ListenNumber() was waiting but the input ended
Shaun: There's no item 7 a list position that doesn't exist (xs[7] when the list is shorter)
Shaun: There's no letter 7 a position past the end of some words
Shaun: You can't Pop from an empty list Shaun.Pop on a list with nothing in it
Shaun: That list is empty, so there's nothing to pick from Max, Min or Choose on an empty list
Shaun: You can't take the square root of a negative number Shaun.Root(-4)
Shaun: Power needs a whole number that isn't negative Shaun.Power(2, -1)

17. Limits (v0.4)

18. Tools

Command line

Command Does
shaunc studio opens Shaun Studio (add a folder to use it as your workspace)
shaunc file.shaun compiles to file.exe (Windows) or file (Linux)
shaunc file.shaun --run compile, then run
-o name choose the output name
--target windows or linux build for another system
--pause the program waits for Enter before closing (good for sharing)
--dump also print the machine code in hex

Sharing your programs (the Build button)

Press 📦 Build (or Ctrl+B) in Shaun Studio to make a standalone program from the lesson you have open.

Shaun Studio shortcuts

Keys Action
F5 or Ctrl+Enter run (or stop, while running)
Ctrl+S save
Ctrl+B build a shareable program
Ctrl+Space autocomplete
Hover a keyword short explanation

19. Example programs

Prime numbers

Register

Lesson IsPrime(n) {
    Shaun.Checks(n < 2) {
        HandIn 0
    }
    Student d = 2
    UntilTheBell(d * d <= n) {
        Shaun.Checks(n % d == 0) {
            HandIn 0
        }
        d = d + 1
    }
    HandIn 1
}

Homework(i from 1 to 50) {
    Shaun.Checks(IsPrime(i) == 1) {
        Shaun.Say(i + " ")
    }
}
Shaun.ShaunOutput("")

Dismissed

Guess the number

Register

Student secret = 42
Student guess = 0
Student tries = 0

UntilTheBell(guess != secret) {
    Shaun.Say("Your guess: ")
    guess = Shaun.ListenNumber()
    tries = tries + 1
    Shaun.Checks(guess < secret) {
        Shaun.ShaunOutput("Too low.")
    }
    Shaun.Checks(guess > secret) {
        Shaun.ShaunOutput("Too high.")
    }
}

Shaun.ShaunOutput("Correct! It took you " + tries + " tries.")

Dismissed

Vowel counter

Register

Shaun.Say("Type a word: ")
Student word = Shaun.Lower(Shaun.Trim(Shaun.Listen()))
Student vowels = 0

Homework(i from 0 to Shaun.Length(word) - 1) {
    Student letter = Shaun.Part(word, i, 1)
    Shaun.Checks(Shaun.Contains("aeiou", letter)) {
        vowels = vowels + 1
    }
}

Shaun.ShaunOutput(word + " has " + vowels + " vowels.")

Dismissed

Palindrome checker

Register

Shaun.Say("Type a word: ")
Student w = Shaun.Lower(Shaun.Trim(Shaun.Listen()))
Student n = Shaun.Length(w)
Student same = Correct

Homework(i from 0 to n - 1) {
    Shaun.Checks(Shaun.Part(w, i, 1) != Shaun.Part(w, n - 1 - i, 1)) {
        same = Wrong
        LeaveEarly
    }
}

Shaun.Checks(same) {
    Shaun.ShaunOutput(w + " is a palindrome.")
} Detention {
    Shaun.ShaunOutput(w + " is not a palindrome.")
}

Dismissed

Class marks

Register

Student marks = [72, 58, 91, 64, 85]
Shaun.Sort(marks)
Shaun.ShaunOutput("In order: " + marks)
Shaun.ShaunOutput("Lowest: " + Shaun.Min(marks) + ", highest: " + Shaun.Max(marks))

Student average = Shaun.Sum(marks) / 5.0
Shaun.ShaunOutput("Average: " + Shaun.Fixed(average, 1))

Student passed = []
Homework(m in marks) {
    Shaun.Checks(m >= 70) {
        Shaun.Add(passed, m)
    }
}
Shaun.ShaunOutput(Shaun.Length(passed) + " passed: " + passed)

Dismissed

Word counter

Register

Shaun.Say("Type a sentence: ")
Student words = Shaun.Split(Shaun.Trim(Shaun.Listen()), " ")

Shaun.ShaunOutput("That is " + Shaun.Length(words) + " words.")
Shaun.Sort(words)
Shaun.ShaunOutput(Shaun.Join(words, ", "))

Dismissed

Times table

Register

Shaun.Say("Which times table? ")
Student n = Shaun.ListenNumber()

Homework(i from 1 to 12) {
    Shaun.ShaunOutput(i + " x " + n + " = " + i * n)
}

Dismissed

20. How it works

shaunc has four stages, all written from scratch in C#:

  1. Lexer: turns text into tokens.
  2. Parser: builds a tree of the program and reports syntax mistakes.
  3. Code generator: checks types and writes x86-64 machine code directly. A tiny assembler turns instructions like mov rax, rcx into bytes.
  4. Executable writer: wraps the machine code in a Windows PE or Linux ELF file.

The built-in functions (printing, reading, joining words) are machine code too, included in every program. There is no C compiler, assembler or linker involved.

21. Version history and ideas