Psi Programming Language (Classic)

2018-05-05

A programming language focused on safe, but dynamic programming.

software (29) programming-language (7)

Table of Contents
  1. Design
  2. Examples
  3. Abandonment
  4. Links

Magic at your fingertips!

Psi was a programming language experiment I did in 2018, where I was kinda unhappy with C++ and C# and wanted something that had a similar power level, but less abstraction work necessary.

Select anchorDesign

The language was designed to be easily typable, super orthogonal in all features and programmer-oriented. The goals were:

/***************************************************
* Example using some features of the Psi language. *
***************************************************/
import std;
import std.io;

const main = fn()
{
    var I : int;

    // Using an 'out' parameter
    set(I, 42);
    
    while(I > limit())
    {
        I = I - 1;
    }

    // Create a closure
    var print = fn()
    {
        print("I = ");
        print(I);
        print("\n");
    };

    // Call the local print variable
    print();
};

const set = fn(out dst : int, src : int)
{
    dst = src;
};

const limit = fn() -> int
{
    return 38;
};

Functions were just values, and option types looked pretty similar to what rust has now. Psi also featured reference semantics like in Java/.NET, but also raw pointer semantics, as well as enum literals. Another thing that was meant to be was a comptime system like Zig has.

Select anchorExamples

Typed enums:

type weight_unit = enum<real>(gram = 0.001, kilogram = 1.0, ton = 1000.0);
var amountOfFlour = 250.0 * :gram; // will result in 0.25

Complex numbers:

module complex
{
    type imag = record(real : real, imag : imag);

    const I = imag(real: 0, imag: 1);
}

Extension methods:

const print = fn(this I : int, j : int)
{
    io.write(I, ",", j, "\n");
}

const print = fn(this p : Point)
{
    io.write("(", p.x, ",", p.y, ")\n");
}

var pt = Point(x = 10, y = 20);
pt.print(); // Prints "(10,20)\n"
print(pt);  // Prints exactly the same
5.print(6); // Prints "5,6\n"

Reference semantics:

var foo : ref<Point> = new Point(x = 10);
var bar : ref<Point> = new Point(x = 20);

foo = bar;               # copy reference
foo = new Point(x = 40); # assign new reference

foo := Point(x = 30);    # assign new value
foo := bar'value;        # copy value
foo := bar;              # copy value with use of coercion

var baz : Point = bar;   # copy value with coercion

print(foo'value.x);      # access value member
print(foo.x);            # use dot-member propagation

Lambda expressions:

const apply = fn(this list : array<real>, f : fn(x:real) -> real) -> array<real>
{
    var res : array<real> = array<real>(list.length);
    for(I in list'range)
        res[I] = f(list[I]);
    return res;
}

var foo = [1.0, 2.0, 3.0].apply(\x => 2 * x);

Option type:

type ios = option<string,int>;

var val : ios = "Hello, World!";
switch(val.type)
{
    case string:
        print("s = %1".arg(string(val)));
        break;
    case int:
        print("I = %1".arg(int(val)));
        break;
    others:
        error "Not supported!";
}

Select anchorAbandonment

When I discovered Zig, I figured that most of the projects goals aligned perfectly with my own goals, but the approach was somewhat different.

I started using Zig more and more and at one point, I wasn’t really interested in finishing Psi anymore.

As the project never really took of, I adopted the name of the language for the programming language I want to have on the Ashet Home Computer. It will be in a Zig-like fashion, so syntactically very similar, but semantically even simpler.

But I honestly like the design I made and maybe at one point in the future, I’ll adapt it again under a new name, with better designed semantics and less weird properties like polymorphic variables.

Select anchorLinks