Portsy

From Esolang
Jump to navigation Jump to search
Portsy
Designed by User:RocketRace
Appeared in 2021
Computational class
Reference implementation Unimplemented
File extension(s) .pts

Portsy is a small C-like programming language embedded entirely within Python's module import syntax. The language was inspired by the semantics of Python modules and imports. It was designed by User:RocketRace in August of 2021.

Syntactic Features

Portsy programs consist of lines of the form from portsy import ..., replacing the ellipsis with some code. For the purposes of this article, the from portsy import preamble will be omitted. In the following sections, [name] will be written to represent any sequence of characters considered a valid identifier in Python 3. Note that strings that are reserved tokens in Python are invalid identifiers in Portsy.

Each line can either be a name ([name]), a label ([name] as [name]), a group (a comma-delimited list of names or labels enclosed in parentheses, with an optional trailing comma -- e.g. ([name], [name] as [name], [name],)), or an anchor (the literal string *). These lexical atoms build up Portsy's grammar. Code between a # character and a newline is ignored.

Portsy programs can be split up into blocks. While it is not necessary, by convention these are differentiated with an extra level of indentation, typically four spaces. A block begins with a name or label, and ends with an anchor. Blocks may contain other blocks, given each is properly delimited. Each inner block is higher than the previous lower one. An example is shown below, and will be explained in the Semantic Features section.

fn as first      # label, start of block
    (foo, bar)   # group, in block
    foo          # name, in block
*                # anchor, end of block

Semantic Features

Top-level source code consists of crates. Crates are declarations, evaluated before any entry point to the program is called. Each crate has rules for its syntax.

Program execution follows chains, which are sequences of imperatively executed operations. Chains contain lines of names, labels and groups, with the following kinds:

Said Shown Told
Lonely name foo A lonely name is treated as a handoff point. See fn, op and unit for more on handoff points. The name must be assigned a value, which will be handed off to a lower block.
Lonely label foo as bar A lonely label assigns the value of its left operand to the name in its right operand. The left name must have an assigned value.
Greedy name foo, (bar, baz) A greedy name is a name followed by a group (the meal). Like a lonely name, this is also a handoff point. Only certain names are greedy, some examples being fns.
Greedy label foo as bar, (baz, quz) A greedy label is a label followed by a group (the meal). Like a lonely label, this also assigns its value to its right operand (in this case bar). Only certain labels are greedy. If a name is greedy, the equivalent label is also greedy.
Lonely group (foo as bar, baz, _, bar) A lonely group interprets its innards as elements of a chain, with some alterations. These are the ingroup variants of each element.
  • If a name in a group is lonely, it is handed off to the group as-is.
  • If a label in a group is lonely, its value is assigned only for the duration of the group.
  • If a name in a group is greedy, any names following it are interpreted as its meal until either the _ element or the end of the group is reached. The resulting value is handed off to the group.
  • If a label in a group is greedy, the previous two concepts are conjoined.

The fn, op and unit crates

A fn defines a function. This begins a block with a group defining arguments and a chain defining the function body. Example definitions are shown below.

fn as foo # takes no arguments
    (_)   # (_) represents the empty group
    # chain   
*
fn as bar  # takes one argument
    (x)
    # chain 
*

or equivalently,

fn as bar # parentheses in single-element
    x     # groups can be omitted freely
    # chain
*

Inside the chain of a fn, upon being handed off a value, the fn will stop executing and evaluate to the handed-off value.

A fn can be executed using a greedy name or label, including ingroup greedy names and labels:

some_fn as some_name
(some, arguments, to, the, function)
(a, b, c, some_fn, some, ingroup, arguments, _, d, e, f)
(a, b, c, some_fn as some_name, some, ingroup, arguments, _, d, e, f)


An op defines a monadic operation. This is a special case of fn, with only one implicit operand X. The argument group is omitted.

op as foo # notice missing argument group
    X # this particular op just returns its argument
*

An op can only be called using lonely (potentially ingroup) labels. The right operand must additionally have a value assigned to it, and is treated as the argument to the op.

# foo is defined
some_op as foo # apply once to foo
some_op as foo # apply a second time

A unit is another special case of a fn, this time taking no arguments.

unit as foo
    # chain
*

An op can only be called using lonely (potentially ingroup) labels. The right operand need not have a value assigned to it.

some_unit as foo
some_unit as bar

The use crate

The use crate can be used to define names outside of chains. It pulls in a definition from an external bubble, be it a definition for a fn, op, unit, or other, and applies it to the current program. use begins a block containing the definitions that should be pulled from the specified bubble.

use as some_bubble
    some_definition
    some_other_definition as renamed_definition
    # ...
*

There are a number of external bubbles included in Portsy (see the Included Bubbles section), and more can be defined by third parties. The definitions inside the included portsy bubble are automatically pulled into Portsy programs, allowing the programmer to use them without explicitly asking for them. (See the Portsy Bubble section).

The value model

Every value in Portsy is either a signed integer or an array of values. Note that while a name may be assigned to a fn or other similar things, they are not values and cannot be interpreted as such.

Values can be manipulated using definitions from bubbles. The included bubbles provide a baseline for writing programs.

Included Bubbles

portsy

This bubble exports