SATire

From Esolang
Jump to navigation Jump to search

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 language
  • None-containing-[name1]-[name2] is for literal values by extensions
  • None-pertaining_to-[name1]-[name2] is for other syntax by the language
  • None-in-[name1]-[name2] is for other syntax by extensions
  • None-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 extensions
  • None-[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 SATire_params which will sent from the caller when the function is called, and returned back when the function is finished. The main program also has this variable, with the following keys:

Key Value
"ARGS" A stack with the number of command-line arguments at the top, and the command-line arguments from first to last, top to bottom of the stack, starting with the program name.
"ENV" A stack with the number of environment variables at the top, and then the environment variables in any order. The key is separated from the value by an =. In the key, \ is replaced by \B, and = is replaced by \E.
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
  • If the right argument is 0, return the length of the stack as an integer pushed to an empty stack.
  • If the right argument is 1, create an empty stack. Push a String corresponding to the type name in the tables defined in the [#Types] section of this specification, for the type of the top element on the stack. Push true if the top element is an undefined value, otherwise false.
  • Negative right arguments are for extensions. Further positive right arguments are reserved.
[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,]