Amethyst

From Esolang
Jump to navigation Jump to search

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

Amethyst/Standard Library

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())

Category