Amethyst
Amethyst is a programming language designed by PSTF. It is influenced by Ruby, C++, Lua, Python and JavaScript.
Language Overview
Amethyst is a lightweight, high-level programming language that is primarily used to write cross-platform applications, data analytics, artificial intelligence, and more. Amethyst advocates a "villager" style of code – one that is quick to understand even for newbies.
Basic Syntax Concept
My first program
print("Hello, world!")
This program prints "Hello, world!".
Program mode
Interactive programming
Amethyst provides interactive programming. You can use amethyst
or amethyst -r
to call the terminal.
C:\Users\PrySigneToFry\> amethyst Amethyst 1.0 terminal on Win64 Neptune environment 2025 Mar 16, 15:10 at UTC+8 This programming terminal is in Neptune environment, and has been activated. If you want to inactivate your environment, run inactivate.ps in the environment directory(you can also find actiavte.ps in it). Type exit() or EOF for exit. Amethyst > print("Hello, world!") Hello, world! Amethyst >
Scripted programming
You could also save the script in an Amethyst file, its extension name is .ame.
print("Hello, world!") print("Welcome to Amethyst environment!")
To execute a script, use amethyst
command.
$ amethyst hello.ame Hello, world! Welcome to Amethyst environment! $ amethyst Amethyst 1.0 terminal on Linux Neptune environment 2025 Mar 16, 15:10 at UTC+8 This programming terminal is in Neptune environment, and has been activated. If you want to inactivate your environment, run inactivate.ps in the environment directory(you can also find actiavte.ps in it). Type exit() or EOF for exit. Amethyst >
You may also define the program directory.
#``usr/local/local/bin/amethyst print("Hello, world!") print("Welcome to Amethyst environment!")
$ ./hello.ame Hello, world! Welcome to Amethyst environment! $ amethyst Amethyst 1.0 terminal on Linux Neptune environment 2025 Mar 16, 15:10 at UTC+8 This programming terminal is in Neptune environment, and has been activated. If you want to inactivate your environment, run inactivate.ps in the environment directory(you can also find actiavte.ps in it). Type exit() or EOF for exit. Amethyst >
Comment
# I'm a comment, please ignore me. print("Hello, world!") # I'm also a comment. =begin I'm document comment. =end [[[ I'm comment block! ]]]
Data types
Numeric types
There are three basic types of numbers in Amethyst – integers, floats, and complexes.
Integer type
We use int for integer type.
Float type
We use float for float type. It can be expressed as fractions like 3/7 or as real number like 3.7.
Complex type
We use comp for complex type. Try to abs it will get its geometrical absolute value, such as 3+4j will return 5. 1j can't be expressed as j.
String
The string is basically a flow of bytes, quote by ""(\" for "). A non-ASCII will encode as UTF-8 by default except you wrote <code>#`` encoding:YourEncoding ``#</code>. '' is also accepted, \' for '. """""" and '''''' are accepted as document string.
Boolean
Boolean is a logical value. bool
for short.
Void
It has only one value: nil. Convert it to other type will set as default value.
Undefined behaviour
It occurs when you try to do something weird, such as 5÷0.
Array
Array is a serie of value, which enclosed in bracket. Arrays are 0-based indexing. However, -x means x-th item to the last item.
Variables
Global Variable
Global variable is a variable which will always remains at the environment until quit the environment. It uses dollar sign as prefix.
Attribute
Attribute is a variable that defined in a struct, or a class. It uses at sign as prefix.
Interihance-able attribute
It uses @@ as prefix, and can be interihancedd by every sub-class.
Local variable
Local variables do not have any prefixes and only take effect in a specific block of code – if defined outside of all blocks of code, they are only valid in the program.
Constant
Constants start with a single underscore. Once a constant is assigned, it cannot be modified. Attempting to access undefined constants will result in an error.
Pseudo-variable
They are special variables that have the appearance of local variables, but behave like constants. You can't assign any value to these variables.
- self: The receiver object of the current method.
- true: A value that represents true.
- false: A value that represents false.
- nil: Represents the value of undefined.
- __FILE__: The name of the current source file.
- __LINE__: The number of the current line in the source file.
Definition
variable_name = value
Conditional Jump
Amethyst provides several very common conditional structures. In this chapter, we will explain all the conditional statements and modifiers.
If-Elseif-Else
Code that in comment means you can ignore it.
if condition [[[then]]] code =begin elseif condition then code elseif... else code =end end
If expressions are used for conditional execution. The values false, nil, 0, and various empty objects are false, and all other values are true. Note that Ruby uses elsif, not else if and elif.
If the condition is true, code is executed. If the condition is not true, the code specified in the else clause is executed.
Usually we omit the reserved word then. If you want to write a complete if in a single line, you must separate the conditional and program blocks with then.
You may also write this: code if expression
.
Unless-Else
The unless expression is the opposite of the if expression. If the condition returns false, the specified code is executed.
unless condition [[[then]]] code =begin else code =end end
code unless expression
Loop
While
while condition [[[do/:]]] code end
This block of statements checks if the condition returns true before executing the code.
Repeat-while
repeat code end while condition
This block of statements checks if the condition returns true AFTER executing the code.
Until
until condition [[[do/:]]] code end
This block of statements checks if the condition returns false before executing the code.
Repeat-until
repeat code end until condition
This block of statements checks if the condition returns true AFTER executing the code.
For
for iter in container [[[:/do]]] code end
Statement block
We use a head of statement block(usually if, while, repeat, until, def, struct, do or class) and end to enclose a statement block. Two commands in one line must seperate with semicolon.
INIT and OK
The block of code in INIT must be the first to be executed, while the block of code in END must be the last to be executed.
print(2) INIT print(1) \INIT OK print(3) \OK
Output:
1 2 3
Function
Functions are defined as this:
def function_name(param_list) function_body return return_value end
Also there are lambda functions:
var a = [param_list]=>{function_body} a(argument_list)
Class
Class are defined as this:
class YourClassName: @@attributes @private_attributes def __init__(self): # initialization end methods end
To call a method or an attribute of a class, use a dot.
Struct
Unlike classes, structs can be used directly as types. All other characteristics are equal to the class. However, structs are represented as array.
struct YourStructName: @@attributes @private_attributes methods end
Example
struct pair: @@a = nil @@b = nil end pair x = [1, 5]; print(f"({x.a}, {x.b})")
Output: (1, 5)
I/O
With all that said, it's time to talk about inputs and outputs.
Output
print(*args, **kwargs, sep = ' ', end = '\n', file = sys.stdout)
Print a serie of arguments. sep is seperator(normal a space), end is terminator(normal a linebreak), file is file to output.
Input
input(__prompt, file = sys.stdin)
Input a string and return it. __prompt is prompt that output before input, file is file to read.
Evaluated input
There is no evaluated input. However there is a self-evaluating function:
eval(expr)
Thus you can write this for evaluated input:
eval(input())
Module and Package
Every program is a module that can import by this:
import lib_name
Or this:
from lib_name import module_name
There is also a C++ API for Amethyst, inspired by Lua.
I don't use Linux, but Windows instead. But for ease of introducing, we use Linux for our tutorial. Windows is similar to Linux.
The loadlib
function loads the specified library and connects to Amethyst, but it does not open the library (i.e. it does not call the initialization function), but instead returns the initialization function as a function of Amethyst, so that we can call it directly in Amethyst.
path = "usr/local/amethyst/cpplib/libamethystsocket.so" # or "C:\Windows\AmethystSocket.dll" if you're using Windows f = loadlib(path, "amethystopen_socket") # Import f() # Init
Error handling
Amethyst use this for handle error.
try: code if catch Exception: handling =begin elseif catch Exception: handling2 elseif catch... else: success finally: finally =end end
It try to do the code in try statement block, and if there is an exception, catch it, and handle it. If nothing catched, do else statement. The finally statement will run at final definitely.
Also, there is a retry
keyword that you can return to try statement block.
Such as:
a = 10 try: a += b if catch NameError: b = 5 retry else: print(a) end
It will output 15.
Regular expression
Works like JavaScript, I don't really want to write it!
Standard libraries
Example
A+B problem
print(num(input()) + num(input()))
Compare between struct
struct User: @username = nil @contributions = 0 end INIT from math import all \INIT User1(User) = ["Khlistera", 1900] User2(User) = ["Afefoj", 1901] def cmp(a(User), b(User)): return sgn(a.contributions - b.contributions) end print(cmp(User1, User2))
Usage of SYS library
import SYS def Brainfuck(code(string)): s = [] matches = {} tape = [0] * 100000000 for i, j in enumerate(code) do if j == '[' do s.append(i) end if j == ']' do m = s.pop() matches[m] = i; matches[i] = m end end cp = 0 p = 0 while cp < code.length(): tape[p] = (tape[p] + 1) % 4294967296 if code[cp] == '+' tape[p] = (tape[p] - 1) % 4294967296 if code[cp] == '-' print(chr(tape[p])) if code[cp] == '.' do c = sys.stdin.read(1); tape[p] = (ord(c) if c else 0) % 4294967296 end if code[cp] == ',' p = p + 1 if code[cp] == '>' p = p - 1 if code[cp] == '<' do cp = matches[cp] if tape[p] end if code[cp] == ']' do cp = matches[cp] if not tape[p] end if code[cp] == '[' end cp = cp + 1 end Brainfuck(sys.stdin.read())