toki pi ilo nanpa

From Esolang
Jump to navigation Jump to search


toki pi ilo nanpa
Paradigm(s) imperative
Designed by User:Olus2000
Appeared in 2021
Computational class Turing-complete
Reference implementation Python
Influenced by toki pona
Lua
File extension(s) .tin
.til(bytecode)

toki pi ilo nanpa ("computer language" in toki pona) is a Pseudonatural programming language in development based on toki pona (language of good), a minimalistic constructed language invented by Sonja Lang, and Lua, a popular scripting language. The aim of the esolang is to make it's programs resemble valid toki pona sentences as closely as possible.

Lexical conventions

Identifiers in toki can be any word viable under toki pona word building rules, excluding the rules about banned letter pairs. This means an identifier must start with a (C)V(n) capitalised syllable and continue using CV(n) syllables, all using letters avaliable in toki pona: aeioujklmnpstw. Identifiers are used to name variables.

The following keywords are currently used in the language. Note that even if they were not reserved they wouldn't be viable identifiers because of their lack of capitalisation.

ala ale ali e en ijo kepeken kipisi kulupu la li lili lon luka lukin mute nanpa ni nimi o open pali pana pi pini sin sitelen suli tu wan

The other tokens are . for ending sentences and " for literal strings.

Literal strings are prefixed by nimi, have to be delimited by a pair of double quotes and can contain any characters. Allowed escape sequences are '\"' for a literal double quote, '\\' for a literal backslash and '\n' for a newline.

A numerical constant is prefixed with nanpa and consists of a ala for a 0 or a non-decreasing series of toki pona number words with values as follows:

word ale/ali mute luka tu wan ala
value 100 20 5 2 1 0

Values and types

toki pi ilo nanpa is a dynamically typed language. This means that variables do not have types; only values do. There are no type definitions in the language. Values carry their own type.

All values in toki are first class values, meaning they can be stored in variables, passed to functions and returned as results.

There are seven basic data types in toki: ala, lon, nanpa, nimi, kulupu, pali and lipu. ala is the type of value ala, whose main property is to be different from the other value. It usually represents the absence of a useful value. It's similar to 'Nil' or 'None' from other languages. lon is type of values lon and it's inverse - lon ala which represent boolean values of true and false. Both ala and lon ala make a condition false; any other values make it true. nanpa represents integer values, optimally unbounded but that may depend on the implementation; every implementation must allow for positive and negative integers. There is no way to get non-integer values in toki as it lacks any form of division operation, although users are encouraged to implement their own real number system with the tools given by the language. nimi represents arrays of characters. It can contain any of the 8-bit character values including embedded zeros.

kulupu implements associative arrays (later called 'tables'), that is, arrays that can be indexed not only with numbers, but with any value (including ala). Tables can be heterogeneous; that is, they can contain values of all types (including ala). Tables are the sole data structuring mechanism in toki; they can be used to represent ordinary arrays, symbol tables, sets, records, graphs, trees, etc. To represent records, toki uses the field name as an index. There is only one way to create a new table in toki: expression kulupu evaluates to a new empty table.

pali is a type of a paragraph - a set of sentences to be executed in order. Variables holding a pali value is similar to functions from other languages. A value holding a refernece to the paragraph currently being executed can be obtained using an expression pali ni.

lipu is a type of a file open for reading or writing. It is created using the verb open and is used as an argument to verbs sitelen (for writing) and lukin (for reading).

kulupu and pali are not stored directly in the variables. Variables contain only references to these values. This means that parameter passing, assignment and function returns will copy a reference, not the full value. It also means that they can be freely used as table keys.

Expressions and operators

The basic expressions in toki are the following:

expr := literal
expr := var
expr := nanpa nasa
expr := expr binop expr
expr := expr ala

nanpa nasa evaluates to a random integer between some boundaries. Original implementation uses a random byte but it is allowed to vary between implementations.

toki uses two binary operators:

  • pi - returns value of a field of table from the first argument indexed by the second argument or a character of the string from the first argument indexed by the second argument (first character being 0). If there is no such field or character or the first argument isn't a table or string returns ala. Takes precedence over en.
  • en - adds two numbers, concatenates two strings or boolean add two boolean values; if arguments aren't strings, numbers or booleans or have different types returns ala.

toki has one unary postfix operator ala which takes precedence before en but not pi and serves as a negation operator: if given a number it will return its integer negative, and if given a boolean it will return its boolean negative. In other cases it returns ala.

Binary operator precedence allows for arithmetic on table contents, but not for arithmetic on table indexes which should be calculated beforehand and stored in variables.

Sentences

Sentences are to toki what statements are to usual programming languages. They include assignments, control structures and function calls. Each sentence ends with a .. The most basic sentence is o expr. which evaluates 'expr' and discards its value.

Assignment

Assignments are the second sentence type and their syntax is var li expr.. expr can be any expression. var can be one of the three types of variable declarations/references:

  • ijo lili Identifier - declares/references a local variable "Identifier" (obviously "Identifier" is not a legal identifier, it's only used here as a placeholder)
  • ijo suli Identifier - declares/references a global variable "Identifier"
  • ijo Identifier - searches for variable "Identifier" from the top layer of local variables through locals declared by parent paragraphs ending with the global variables and references the first one found. If found none then declares a global variable.
  • table_expr pi key_expr - sets a field of the table returned by table_expr indexed by the value of key_expr.

Control structures

The only control structure in toki is a conditional prefix. To achieve loops use recursion.

Conditionals work by prepending a conditional prefix to any sentence. The sentence is then skipped if the prefix evaluates to lon ala or ala and executed otherwise. If the sentence opens a paragraph the whole paragraph is skipped or executed. Any number of conditions can be prepended to any sentence; they will be evaluated from left to right until one fails or all pass and the main sentence is executed.

There are four types of conditional prefixes:

  • expr la - uses the value of the expression
  • expr li lili la - lon if expr is numeric and less than zero, lon ala otherwise
  • expr li suli la - lon if expr is numeric and more than zero, lon ala otherwise
  • expr li expr la - lon if expressions are equal, lon ala otherwise

Verb sentences

Verb sentences have a verb expression instead of their main expression. The verb operators may take a main argument introduced with e and a list of subarguments, each introduced with kepeken. Excess arguments are ignored and lacking arguments are assumed to be ala. The general syntax of verb sentences is:

[condition la ...] o verb [e expr [kepeken expr ...]].
[condition la ...] var li verb [e expr [kepeken expr ...]].

The list and specification of verb operators may change between implementations, but there is a list proposed by the author:

  • pali e pali_expr kepeken Arg1 (...) kepeken ArgN - execute paragraph pali_exp with arguments Arg1 through ArgN and return it's value. Returns ala if pali_exp is not of type pali.
  • pana e expr - stop executing the current paragraph and return expr.
  • lukin e lipu_expr - returns a string - a single line read from lipu_expr, or the standard input if lipu_expr is not of type lipu and open for reading, including the trailing newline if present. Returns empty strings after reading through the whole input.
  • sitelen e nimi_expr kepeken lipu_expr - writes its argument to lipu_expr, or standard output if lipu_expr is not of type lipu and open for writing. Non-string values are converted to [type_name] strings.
  • kipisi e nimi_expr kepeken nanpa_expr1 kepeken nanpa_expr2 - return a substring of nimi_expr starting from nanpa_expr1 (zero-indexed) up to but not including nanpa_expr2. If nimi_expr is not a nimi returns ala. If nanpa_expr1 is not nanpa or is smaller than 0 it's corrected to 0. If nanpa_expr2 is not nanpa or is bigger than the string's length it's corrected to the string's length. If nanpa_expr1 is greater or equal nanpa_expr2 the resulting string is empty.
  • open e nimi_expr kepeken mode - tries to open file nimi_epxr and return it as a lipu value. If it fails or nimi_expr is not of type nimi returns ala. If mode evaluates to nimi "sitelen" the file is open for writing, otherwise it's open for reading.
  • pini e lipu_expr - closes the file lipu_expr which makes sure any data written to it is saved on disc. Prevents any further reads or writes to or from the file.

Paragraph definitions

Paragraph definitions are a special case of sentences that start new paragraphs. The defined paragraph is then passed as a value of a pali sin expression. There are three types of paragraph definitions corresponding to assignment, verb and verb assignment sentences:

o pali e pali sin [kepeken expr ...].
var li pali sin.
var li pali e pali sin [kepeken expr ...].

Each of those types can also have conditional prefixes like any sentence. Paragraphs opened with a paragraph definition end with pali sin li pini.

Paragraphs

Paragraphs are multiple sentences executed sequentially. Every paragraph including the main program is stored as a pali type value. Local variables are local to the paragraph they were declared in but can be used or changed by paragraphs called from within the paragraph they were declared in. A new paragraph definition starts after a paragraph definition sentence and ends with a sentence pali sin li pini. at which point the pali sin expression in the paragraph definition sentence will return a value of type pali containing the paragraph. Paragraphs are executed using the verb pali.

Any paragraph can recieve arguments. The arguments are specified with pali ni li kepeken e ijo Arg1 (...) e ijo ArgN. on the first sentence of the paragraph. If the any arguments are passed to the paragraph when it's called their values are assigned to their respective variables. Any excessive arguments are discarded, and any variables that didn't get an argument are assigned ala. The main paragraph (the whole program) is called with two arguments: a string with a script name and a table of command line arguments.

Any paragraph will return a single value. The value returned and the return point of the paragraph can be specified with the verb pana. Executing this sentence will exit the current paragraph. After executing the last sentence in the paragraph it will return ala.

Errors and exceptions

The only errors possible in toki are parsing errors which are left to be implemented in the interpreters/compilers. Correct toki pi ilo nanpa code always executes without errors, although it may turn some values to ala if things don't go as planned.

Missing features

There's a lot of features in standard programming languages that toki pi ilo nanpa lacks. This section is dedicated to implementing them and working around the minimalism.

Comments

toki doesn't have comments, but it's very easy to write code that will do nothing when executed and can carry an arbitrary message: o nimi "comment".. Such comment may span any number of lines and be inserted in any place in code a normal sentence could, because it is just a sentence. The main drawback of this approach is the amount of additional useless strings the interpreter will be forced to store, although a well implemented interpreter would find and eliminate such constructs at parse-time.

Loops

Loops in toki are implemented with recursion; this is the main motivation behind pali ni construct. To create a while loop simply put a o pali e pali ni. under a condition at the end of a paragraph. An iterator can be passed to the looping paragraph to emulate a for loop. Using pseudocode:

loop_start_condition la o pali e pali sin kepeken iterator_starting_value.
    pali ni li kepeken e ijo iterator.
    loop body.
    loop_continue_condition la o pali e pali ni kepeken changed_iterator.
pali sin li pini.

Finding length of a string/table

Getting the length of the string or a table that is used as a continous array is a very useful feature that toki lacks. Fortunately it can be easily implemented by binary-searching and checking if an element of a certain number exists. The function has O(log(n))) complexity.

pali ni li kepeken e ijo Kulupu e ijo I.
o nimi "Kulupu is the string/table we are measuring, I is an iterator, should be initialised at one".
ijo lili Ansa li nanpa ala.
ijo lili Seme li lon.
ijo Kulupu pi ijo I li ala la ijo Seme li lon ala.
o nimi "Run this recursively doubling the I until you jump over the end of string/table".
ijo Seme la ijo Ansa li pali e pali ni kepeken ijo Kulupu kepeken ijo I en ijo I.
ijo lili En li ijo Ansa en ijo I en nanpa wan ala.
ijo Seme li lon.
ijo Kulupu pi ijo En li ala la ijo Seme li lon ala.
ijo Seme la o pana e ijo Ansa en ijo I.
o pana e ijo Ansa.

Multiplication

These two of the basic math operations are not present in toki. Multiplication can be implemented using a simple loop in O(n) or using a binary method in O(log(n)):

pali ni li kepeken e ijo A e ijo E.
o nimi "Make sure we are iterating over a smaller number".
ijo lili Seme li lon ala.
ijo A en ijo E ala li suli la ijo lili Seme li lon.
ijo Seme la ijo lili Ansa li pali e pali ni kepeken ijo E kepeken ijo A.
ijo Seme la o pana e ijo Ansa.

o nimi "The actual multiplication loop".
ijo lili Ansa li pali e pali sin kepeken ijo A kepeken ijo E kepeken nanpa wan.
    pali ni li kepeken e ijo A e ijo E e ijo I.
    ijo lili Ansa li kulupu.
    ijo Ansa pi nanpa wan li nanpa ala. o nimi "Ansa[1] holds how much we already multiplied".
    ijo Ansa pi nanpa tu li nanpa ala.  o nimi "Ansa[2] holds the current multiplication outcome".
    ijo I en ijo A ala li lili la
        ijo lili Ansa li pali e pali ni kepeken ijo A kepeken ijo E en ijo E kepeken ijo I en ijo I.
    ijo lili Seme li lon.
    ijo Ansa pi nanpa wan en ijo I en ijo A ala li suli la ijo lili Seme li lon ala.
    ijo Seme la ijo Ansa pi nanpa wan li ijo Ansa pi nanpa wan en ijo I.
    ijo Seme la ijo Ansa pi nanpa tu li ijo Ansa pi nanpa tu en ijo E.
    o pana e ijo Ansa.
pali sin li pini.
o pana e ijo Ansa pi nanpa tu.

Division and modulo

Division and modulo are similar problems to multiplication and can be implemented using a single binary divmod method in O(log(n)):

pali ni li kepeken e ijo A e ijo E.
ijo lili Ansa li kulupu.
ijo Ansa pi nanpa wan li nanpa ala. o nimi "Ansa[1] stores the outcome".
ijo Ansa pi nanpa tu li ijo A.      o nimi "Ansa[2] stores the retmainder".
ijo E en ijo A ala li lili la ijo Ansa li pali e pali ni kepeken ijo A kepeken ijo E en ijo E.
ijo Ansa pi nanpa wan li ijo Ansa pi nanpa wan en ijo Ansa pi nanpa wan.
ijo lili Seme li lon.
ijo E en ijo Ansa pi nanpa tu ala li suli la ijo Seme li lon ala.
ijo Seme la ijo Ansa pi nanpa tu li ijo Ansa pi nanpa tu en ijo E ala.
ijo Seme la ijo Ansa pi nanpa wan li ijo Ansa pi nanpa wan en nanpa wan.
o pana e ijo Ansa.

Computational class

toki is Turing-complete because it can be used to simulate Bitwise Cyclic Tag using the following code, and BCT is Turing-complete.

ijo Kote li lukin. o nimi "First line of input is the BCT program".
ijo Tata li lukin. o nimi "Second line of input is the data-string".
ijo Kote pi nanpa ala li ala la o pana.
ijo Tata pi nanpa ala li ala la o pana.
o nimi "The interpreter will print out any deleted bits as an output".
ijo Tata pi nanpa ala li nimi "\n" la ijo Tata li kipisi e ijo Tata kepeken nanpa wan.
o pali e pali sin.
    ijo Kote pi nanpa ala li nimi "\n" la ijo Kote li kipisi e ijo Kote kepeken nanpa wan.
    ijo Kon li ijo Kote pi nanpa ala.
    ijo Kote li kipisi e ijo Kote kepeken nanpa wan.
    ijo Kote li ijo Kote en ijo Kon.
    ijo Kote pi nanpa ala li nimi "\n" la ijo Kote li kipisi e ijo Kote kepeken nanpa wan.
    ijo Kon li nimi "0" la o pali e pali sin.
        o sitelen e ijo Tata pi nanpa ala.
        ijo Tata li kipisi e ijo Tata kepeken nanpa wan.
        ijo Tata pi nanpa ala li nimi "\n" la ijo Tata li kipisi e ijo Tata kepeken nanpa wan.
    pali sin li pini.
    ijo Kon li nimi "0" la ijo Tata pi nanpa ala li ala la o pana.
    ijo Kon li nimi "1" la o pali e pali sin.
        ijo Tata pi nanpa ala li nimi "1" la ijo Tata li ijo Tata en ijo Kote pi nanpa ala.
        ijo Kote li ijo Kote en ijo Kote pi nanpa ala.
        ijo Kote li kipisi e ijo Kote kepeken nanpa wan.
    pali sin li pini.
    o pali e pali ni.
pali sin li pini.

See also

External resources