SATire
SATire is an esolang by User:BoundedBeans made to look like the math section of a standardized test. It was lost due to accidental deletion, but this is a recreation with a lot of extra functionality.
Syntax
Before processing anything else, any text between ?|(
and ?|)
, as well as the those delimiters themselves, are removed from the program. These function as multiline comments, inline comments, and line splitters (insert a newline between them).
All programs start with Please fill out the following form.
, followed by a newline. Then there is a list of variable declarations, each on a separate line, of the form:
name: value
Names should contain only letters, underscores, and digits, and should not start with a digit. They are case-sensitive. They cannot be true
, false
, or None
. Variables starting with SATire_
are reserved for the language, SATireI_
for the implementation, SATireX_
for extensions to the language using getters and setters wrapping variables, and SATire[one or more decimal digits]_
for further reservations.
These do not support expressions, only the literals shown in #Types. To use full expressions, use the problems.
Variables are statically typed, and the variable's type depends on its initial value.
Then the program should contain the text Calculator section.
followed by a blank line (a.k.a. two newlines), and then the questions, each separated by a blank line.
Extension syntax elements such as custom operators or modifiers, as well as custom types, should begin with the caret character ^
. Further language additions will begin with ?
. Also, the syntax None-[valid variable name]-[valid variable name]-[valid variable name]
is reserved as follows, with earlier rules taking priority over later ones:
None-of-[name1]-[name2]
is for literal values by the languageNone-containing-[name1]-[name2]
is for literal values by extensionsNone-pertaining_to-[name1]-[name2]
is for other syntax by the languageNone-in-[name1]-[name2]
is for other syntax by extensionsNone-enum-[name1]-[name2]
represents a values of type None-enum.None-[name1]-[name2]-[name3]
, where name1 begins with a capital letter or underscore, is for anything by extensionsNone-[name1]-[name2]-[name3]
, where name1 begins with a lowercase letter, is for future language use
Types
Here are the different types:
Type name | Literal regex | Notes | ||||||
---|---|---|---|---|---|---|---|---|
Integer |
[0-9]+ |
Signed 64-bit | ||||||
String
|
"([^"?\\\n]|\\[0-9A-F][0-9A-F])*"
|
Strings support the escape sequence \[two hex digits] for arbitrary bytes. The hex digits A-F must be uppercase. Double quotes, backslashes, question marks, and newlines must be escaped this way. | ||||||
Boolean |
(true|false) |
|||||||
Stack
|
\[(L,)*\] where L is any other literal (not expressions, but things can be dynamically pushed using expressions in code)
|
The last element must still be succeeded by a comma. | ||||||
None-of-the-above
|
None-of-the-above
|
To check if a value is None-of-the-above, the best way to do it is to put it in a stack and check the stack for [] # None-of-the-above . In most useful cases that stack must be nested in another stack since None-of-the-above is also checked when a modifier is used.
| ||||||
Hashtable
|
\?\{\{(L,L,)*\?\}\} where L is any other literal (not full expressions, but pairs can be dynamically added using expressions in code)
|
The last element must still be succeeded by a comma. | ||||||
Function
|
\?FNS , where S is a string literal.
|
Represents a SATire program with the string literal as its text. Functions sometimes wrap a string of SATire code, such that the string can be retrieved, other times it encodes semantic meaning with no string.
Function code has an implicit variable of type Hashtable called
| ||||||
Class
|
\?CLH , where H is a Hashtable literal.
|
Values in the Hashtable should be Functions. The Functions will be called with their SATire_params value containing "Object" mapped to the object and "Params" mapped to a Hashtable containing the actual parameters, and the return value will be the entire SATire_params value when the function completes. Other string keys are reserved, while non-string keys are extension points.
| ||||||
Object
|
No literal, should always be created at runtime. Just use None-of-the-classes .
|
An Object is formed by attaching a Hashtable to a class. | ||||||
None-enum
|
None-enum-[A-Za-z_][A-Za-z_0-9]*-[A-Za-z_][A-Za-z_0-9]*
|
Each type also has an "undefined value" which is used in certain situations where the value is missing but that code might need to check.
Type | Undefined literal |
---|---|
Integer |
None-of-the-digits
|
String |
None-of-the-characters
|
Boolean |
None-of-the-logic
|
Stack |
None-of-the-entries
|
None-of-the-above |
None-of-the-Above (with capital A)
|
Hashtable |
None-of-the-hashes
|
Function |
None-of-the-code
|
Class |
None-of-the-methods
|
Object |
None-of-the-classes
|
None-enum |
None-of-the-enum_values
|
Questions
Questions follow the format:
([n]): Evaluate [e]. [m]. a. [e] b. [e] c. [e] d. [e]
Where [n] is the question number, cases of [e] are expressions, and [m] is a modifier.
Answers should always evaluate to stack expressions, so that the modifier can process them.
There must always be four answers, but an answer can be None-of-the-above to do a sort of else statement.
Modifiers
Modifiers make the questions check their answers with the top element of a stack expression, rather than checking them literally. The second element is used for other purposes.
Modifier | Action |
---|---|
Round down. | The second should be a string representing a variable name (the variable should be either of type String or of type Integer). Inputs the variable as a string or integer from standard input. |
Round up. | The second should be any value. Outputs that value. |
Justify your reasoning. | The second should be an integer from 0-255 which will be printed as a byte, the third should be an output stream identifier (the standard ones are "stdout" and "stderr" ).
|
Justify your thinking. | The second should be a string representing a variable name of type Integer, the third should be an input stream identifier (the standard one is "stdin" ). Inputs a byte as an integer from 0-255 and stores it in the variable.
|
Round to the nearest integer. | The second should be a number. Runs a goto to that question number. If the question number is zero, halts the program. |
Round to the nearest tenth. | The second should be a string representing a variable name, the third should be a value with the type matching the variable's type. Stores the third value into the variable. All variables set here must be declared at the top of the program, except for some special ones that may be defined by extensions or the core language. |
Execution
It starts at question 1. Each question, it checks the top element of each stack expression answer against the expression after "Evaluate", and checks if they are equal. If multiple answers are valid, the first one will be used. If none of them are valid, the rest of the process is skipped. It then does an operation on other elements on the stack depending on the modifier. After the question is done, if a goto is not used, it will move to the next question, or halt the program if there are no more questions. Questions with gotos that want to either jump to the next line or somewhere else must specify the next line explicitly.
Expressions
Literals are discussed in the types section. Expressions are made up of subexpressions, operators, literals, and variable references (notated by the variable's name). Subexpressions must be surrounded by parenthesis.
Operators
Operators should hold the property that an operator call with the same left type/operator/right type triplet should have the same result type.
[Left type] [Operator] [Right type] | Result type | Semantics |
---|---|---|
Integer + Integer
|
Integer | Addition |
String + Integer
|
String | If the integer is in the range 0-255, adds the byte onto the end of the string and returns the new string. |
String + None-of-the-above
|
Function | Converts the left operand into a dynamic function, ignoring the right operand. |
Function + Function
|
Function | Returns a Function that runs the left operand and passes its return value to the right operand, then returns the right operand's return value. |
Stack + Stack
|
Stack | Pushes all elements of the right stack onto the left, preserving order. |
Stack + Integer
|
Stack |
|
[T: Hashtable or Object] + Stack
|
T | The stack should contain two elements. The top element will be the key, the second element will be the value. Adds an entry to the Hashtable. |
[T: Hashtable or Object] + Hashtable
|
T | Combines the entries of the two Hashtables, with the right operand taking priority if they share keys. |
Hashtable + None-of-the-above
|
Class | Converts a Hashtable into a Class. |
Class + None-of-the-above
|
Hashtable | Converts a Class into a Hashtable. |
Class + Hashtable
|
Object | Creates an instance of an object. |
Object + None-of-the-above
|
Hashtable | Gets the underlying Hashtable of an object. |
Object + Stack
|
Hashtable | The right operand should contain two elements, the key to the function on the bottom, and the parameters to the function (which must be a hashtable) on top. The actual parameters passed to the function will be "Object" mapped to the Object, "Params" mapped to the parameters in the right operand, and "Key" mapped to the function's key. Other string keys are reserved, while non-string keys are extension points.
|
None-of-the-above + None-of-the-above
|
Function | Returns the currently-executing function, which you can use for recursion. |
Integer - Integer
|
Integer | Subtraction |
Stack - Stack
|
Stack | Pushes all elements of the right stack onto the left, in a pop-push loop, return the new stack. |
[T: Hashtable or Object] - [Anything]
|
T | Removes the right operand as a key from the Hashtable along with any corresponding value, returns the new Hashtable. If the key isn't in the Hashtable, return the Hashtable unchanged. |
Integer * Integer
|
Integer | Multiplication |
Stack * Integer
|
Stack | Gets N concatenated copies of the stack. |
Integer / Integer
|
Integer | Floor division |
Stack $ [T: Anything]
|
T | Peeks the top element of the stack. If the type is not the same as the type of the right operand, return the undefined value of the right operand's type. |
Integer $ Stack
|
Stack | Removes a number of elements from the right operand corresponding to the left operand, returns the new stack. |
[Hashtable or Object] $ [Anything]
|
Stack | Create an empty stack. Get a value from the Hashtable using the right argument as a key, and push it, except if the key is not mapped, in which case nothing should be pushed. Return the resulting stack. |
Function $ Hashtable
|
Hashtable | Calls the left operand. The implicit variable SATire_params is set to the right operand before the function runs anything, and is returned when the function is finished.
|
String $ Hashtable
|
Stack | Evaluates the left operand as an expression, using the Hashtable as a variable table if it contains only valid variable name strings as keys. If the Hashtable contains invalid keys, check for the key "level" for a number of enclosing scopes (like functions or this operator) to go up to retrieve a copy of the variable table. If there is no such key, or the Hashtable is None-of-the-hashes , use the current scope. If "level" exists but is mapped to something other than a positive integer, it's another extension point unless "level" is mapped to None-of-the-above which is reserved.
Returns the result of the expression pushed to the empty stack, or just the empty stack if there was an error. |
Stack # [Anything]
|
Stack | Returns a copy of the stack with the right side pushed onto it. |
String & String
|
String | Concatenation |
Integer & Integer
|
Boolean | Return true if the left integer is less than the right integer, otherwise return false. |
String @ Stack
|
String | The stack should have two numbers. takes the substring starting at the index of the top element, with the length of the second element. Indexes are zero-based. |
String @ String
|
Function | Takes the left argument as an extension class name, and the right argument as an individual extension function name. This allows custom functions to be added to programs by the user rather than the implementer. |
Boolean ??A Boolean
|
Boolean | AND gate |
Boolean ??O Boolean
|
Boolean | OR gate |
Boolean ??X Boolean
|
Boolean | XOR gate (use boolean ??X true for a NOT gate)
|
String ?-> None-of-the-above
|
Stack | Gets the value of the variable with the left operand as its name, pushes it onto an empty stack. If the variable does not exist, return an empty stack. Ignore the right-operand. |
a mod m
can be implemented as a - (m * (a / m))
.
Equality is checkable by the problems themselves, and you can use Round to the nearest tenth.
to store a boolean. You can then use an OR gate to create less than or equal, and reverse the order for greater than and greater than or equal.
Examples
Hello world
Please fill out the following form. greeting: "Hello, world!\0A" Calculator section. (1) Evaluate 1. Round up. a. ([] # greeting) # 1 b. ["",2,] c. ["",3,] d. ["",None-of-the-above,]
Truth-machine
Please fill out the following form. truth: 0 Calculator section. (1) Evaluate 1. Round down. a. ["truth",1,] b. ["truth",2,] c. ["truth",5,] d. ["truth",8,] (2) Evaluate truth. Round to the nearest integer. a. [5,0,] b. [3,1,] c. [2049,] # ([] # 19) d [9,"pi^2",] (3) Evaluate 1. Round up. a. ([] # truth) # 1 b. ([] # truth) # 396 c. ([] # truth) # 205 d. ([] # truth) # 2945 (4) Evaluate 1. Round to the nearest integer. a. [3,1,] b. [3,2,] c. [3,3,] d. [3,4,] (5) Evaluate 1. Round up. a. ([] # truth) # 1 b. ([] # truth) # 2 c. ([] # truth) # 5 d. ([] # truth) # 7
FizzBuzz
Please fill out the following form. index: 0 numRounds: 0 Calculator section. (1) Evaluate 1. Round down. a. ["numRounds",1,] b. ["numRounds",2,] c. ["numRounds",5,] d. ["numRounds",6,] ?|( Modulo operator emulation. ?|)(2) Evaluate index - (3 * (index / 3)). Round to the nearest integer. a. [4,0,] b. [3,1,] c. [3,2,] d. [3,None-of-the-above,] (3) Evaluate index - (5 * (index / 5)). Round to the nearest integer. a. [5,0,] b. [7,1,] c. [7,2,] d. [7,None-of-the-above,] (4) Evaluate index - (5 * (index / 5)). Round to the nearest integer. a. [9,0,] b. [11,1,] c. [11,2,] d. [11,None-of-the-above,] (5) Evaluate 1. Round up. a. ["Buzz\0A",1,] b. [1,2,] c. [1,3,] d. [1,4,] (6) Evaluate 1. Round to the nearest integer. a. [13,1,] b. [13,2,] c. [13,3,] d. [13,4,] (7) Evaluate 1. Round up. a. ([] # index) # 1 b. [1,2,] c. [1,3,] d. [1,4,] (8) Evaluate 1. Round to the nearest integer. a. [15,1,] b. [15,2,] c. [15,3,] d. [15,4,] (9) Evaluate 1. Round up. a. ["FizzBuzz\0A",1,] b. [1,2,] c. [1,3,] d. [1,4,] (10) Evaluate 1. Round to the nearest integer. a. [13,1,] b. [13,2,] c. [13,3,] d. [13,4,] (11) Evaluate 1. Round up. a. ["Fizz\0A",1,] b. [1,2,] c. [1,3,] d. [1,4,] (12) Evaluate 1. Round to the nearest integer. a. [13,1,] b. [13,2,] c. [13,3,] d. [13,4,] (13) Evaluate 1. Round to the nearest tenth. a. (([] # (index + 1)) # "index") # 1 b. [1,2,] c. [1,3,] d. [1,4,] (14) Evaluate numRounds - index. Round to the nearest integer. a. [0,0,] b. [2,1,] c. [2,2,] d. [2,None-of-the-above,] (15) Evaluate 1. Round up. ?|( Print a newline after numbers. ?|) a. ["\0A",1,] b. [0,2,] c. [0,3,] d. [0,4,] (16) Evaluate 1. Round to the nearest tenth. a. [13,1,] b. [13,2,] c. [13,3,] d. [13,4,]