Integ

From Esolang
Jump to navigation Jump to search
Integ
Paradigm(s) imperative
Designed by User:kerbal
Appeared in 2017
Memory system cell-based
Dimensions one-dimensional
Computational class Turing complete
Reference implementation [1]
File extension(s) .int

Integ is a tape-based esoteric programming language designed by User:kerbal in 2017. The current version is 1.3.

Language Overview

"An esoteric programming language
composed of nothing but parentheses"
            -User:rdococ

Integ is an esoteric programming language in which the only datatype is the integer and the only storage is one large, arbitrary-length, one-way tape of arbitrary-precision integers. Cells on the tape are accessed through non-negative addresses, beginning at 0.

Syntax

Integ has three major types of syntax features: Operators, Overcomments, and Integer Constants. Integ completely ignores tabs, spaces, and newlines; therefore, one is free to format one's code in any way one wants.

Operators

With operators, the program interacts with the tape and performs computations. Operators, which always have one character, use a parentheses-heavy form of prefix notation; the operator character comes first, followed by the operands in parentheses. Operators may be nested. They are implicitly sequenced; in code of the form xyz where x, y, and z are operators, x, y, and z will be evaluated in that order and z will be returned.

The following table lists the basic operators found in Integ.

Operator Description
}xy Writes the integer y to address x. Returns y.
{x Returns the integer at address x.
_x Deallocates all addresses between the maximum address and x, returning x.
@x x is a dummy operand. Returns the maximum assigned storage address.
]x Writes the character whose code is x if possible to the standard output. Returns x.
[x x is a dummy operand. Returns a character code where the character is from the input. Implementations that use a list of input characters instead of interactive input (like Integbot on #esoteric-blah) will select a random number between -1000 and 1000 if the list is exhausted.
+xy Returns x + y.
-xy Returns x - y.
*xy Returns x * y.
/xy Returns, using truncation division, x / y, discarding the remainder.
%xy Returns, using truncation division, the remainder of x / y.
"x x is a dummy operand. Returns the time in seconds since the start of the epoch, rounded down.
`xy Returns the random number between x and y, inclusive, where x and y do not have to be in any particular order. Exact source of randomness is implementation-dependent.
<xy Returns 0 if x < y and 1 otherwise.
?xyz Returns and evaluates y if x is 0 and returns and evaluates z otherwise.
~xy Evaluates y while x equals 0. Returns y unless y was not evaluated; in that case, returns 0.

Starting in Integ 1.2, programs may define their own operators. User-defined operators are always alphabetical characters and, in addition to any arguments explicitly required by the programmer, always require a special offset operand to handle any memory that the operator may use.

Overcomments

With overcomments, a program can, if appropriate, save information located in an overcomment while the overcomment itself is removed from the body of the program. Overcomments do not use prefix notation; instead, they use surround notation, which allows them to be placed almost anywhere within a program. The components of an overcomment are not surrounded by parentheses.

Currently, there are three types of overcomments: comments, operator definitions, and OpPack imports. Comments are of the form #x# where x is the text of the comment, and operator definitions are of the form :abc: where a is the number of operands with which the operator will be called minus one, b is an alphabetical character by which the operator will be called, and c is the code that will be executed by the operator. OpPack imports are of the form .x. where x is a unique identification number. Comments are parsed before OpPack imports, and OpPack imports are parsed before operator definitions.

No comment information is retained by the parser.

Operator definitions

The rules surrounding user-defined operators are fairly complex.

Operator definitions are treated similarly to comments; they can be positioned literally anywhere in Integ code as their contents will be noted and removed by the parser before code execution. Operator definitions may be positioned before, after, or even during calls to the operators they define; as a result, Integ does not allow the same operator to be defined multiple times. Note that because code executed during an interactive shell session is persistent until the session concludes, one must clear the user-defined operators that have already been defined to be able to redefine them. To do so, one must use , which is not an operator. , which must be written on its own line in the interactive prompt, will remove all of the user-defined operator definitions. Note that , only works in the interactive prompt, not in regular programs.

As mentioned, the first non-whitespace, non-hash character of an operator definition must be a non-negative integer of operands with which the operator will be called minus one. User-defined operators must be called with a special operand, the offset operand. As code executed by user-defined operators uses storage, the operator must be provided with an offset, which is basically the first position on Integ's array of integers that the operator is allowed to access. For instance, if the operator was called with an offset of 5, the operator would only be able to write and read to the array starting with address 5. Note that the offset is used to calculate relative addresses; to a user-defined operator and its definition, storage starts at 0. For instance, an address that would be considered address 3 by a user-defined operator called with offset 5 is actually 5 + 3 = absolute address 8. Therefore, if the operator tried to write to address 3, it would actually be writing to absolute address 8 and can be accessed at address 8 outside of the operator. Certain relative addresses have special significance for a user-defined operator. Relative address 0 is the output address; the value that it holds when the code in the body of the operator definition finishes executing is the value that the operator will return. Integ automatically writes the value 0 to this relative address when the operator is called; to give it a different value, one must simply write to it as one would write to a normal location in the body of the operator.

If the user specified a value of a (where :abc:) other than 0 (which is allowed; in this case, the only expected operand is the offset operand), a additional operands will be expected during an operator call. The values passed to these operands can be accessed by reading from relative storage addresses 1 - a. For instance, if a = 5, the operator will expect 5 operands that will be automatically written to addresses 1 - 5. The first operand in the call (besides the offset operand, which is not written anywhere) will go to 1, the second to 2, and so forth.

As mentioned, b in :abc: is the single alphabetical character by which the operator will be called. At the moment, this means that an Integ program may have a maximum of 52 user-defined operators.

c in :abc: is the code that will be executed when the operator is called. All of the regular Integ operators are available, but, as noted, addresses are offset to the starting address defined in the offset operator. Relative memory address 0 is reserved for output and relative memory addresses 1 - a are reserved for input. One can do what one wants with all other addresses greater than a, but one should be careful not to overwrite something important on the tape in the process; remember that relative addresses translate to absolute addresses. All user-defined operators (including the one being defined) are also available. Recursive calls are possible; however, the reference implementation generates an error if recursion exceeds a certain depth (determined by Python) because the underlying Python implementation generates an error if recursion exceeds a certain depth. Still, this matter is officially implementation dependent; implementations where recursion causes no issues are free to allow as much recursion as they wish.

This operator definition creates an operator, a, that prints its first non-offset operand and then calls itself again (this operator assumes that it will have an offset of 2):

:1a]({(1))a(2)({(1)):

This operator can then be called:

a(2)(97)

where 2 is the offset and 97 is the code of the character (a) that will be printed.

OpPack Imports

OpPacks (other Integ programs) are imported using the syntax .x. where x is the identification number of the OpPack not surrounded by parentheses. OpPacks are executed and removed before the program importing the OpPack is executed; as a result, OpPack imports may be placed almost anywhere within a program. Imports do not return a value; however, the OpPack will be executed like a regular program, so OpPacks can print to output and import other OpPacks. Most usefully, user-defined operators in an OpPack can be used by the importing program, hence the name OpPack. User-defined operators from OpPacks have the same properties and calling behavior as User-defined operators from the importing program. I recommend (but will not force) OpPack creators to use uppercase letters for operator characters so that importing programs can at least use the lowercase letters.

The Integ standard library has identification number 0 and therefore may be imported with 0.

To import an OpPack, the Integ interpreter connects to a GitHub repository (at [2]) and finds the file with the name corresponding to the OpPack's identification number. The file contains a URL to the OpPack's actual location online. Integ retrieves the file at the URL and executes it. Therefore, one must have an internet connection to use OpPacks. Also note that OpPacks must always be retrieved through the Internet.

Right now, Integbot in the #esoteric-blah freenode IRC channel allows users to add OpPacks to the GitHub and to get info on individual OpPacks.

Integer Constants

Integ supports positive, negative, and zero arbitrary-precision integer constants. As noted, it supports no other datatype. In an operand, an empty set of parentheses is read as the integer constant 0; therefore, }()() is equivalent to }(0)(0). However, in an operator definition, the first character must be an integer even if the integer is 0.

Computational class

Integ is probably Turing-complete; Integ handles memory very much like a Turing machine. However, there is no formal proof yet that Integ belongs to this computational class.

Examples

Hello, world!

](104)
](101)
](108)
](108)
](111)
](44)
](32)
](119)
](111)
](114)
](108)
](100)
](10)

Cat program

}()()~(?(-(](}({())([())))(13))(1)())(}()(+(1)({())))

Quine

}(000)(00)}(001)(02)}(002)(94)}(003)(08)}(004)(15)}(005)(08)}(006)(91)}(007)
(08)}(008)(16)}(009)(09)}(010)(09)}(011)(08)}(012)(18)}(013)(19)}(014)(16)}
(015)(09)}(016)(09)}(017)(08)}(018)(61)}(019)(08)}(020)(17)}(021)(18)}(022)
(21)}(023)(09)}(024)(61)}(025)(08)}(026)(20)}(027)(16)}(028)(09)}(029)(61)}
(030)(08)}(031)(11)}(032)(08)}(033)(20)}(034)(24)}(035)(09)}(036)(08)}(037)
(15)}(038)(08)}(039)(91)}(040)(08)}(041)(16)}(042)(09)}(043)(09)}(044)(08)}
(045)(17)}(046)(16)}(047)(16)}(048)(09)}(049)(09)}(050)(09)}(051)(61)}(052)
(08)}(053)(11)}(054)(08)}(055)(20)}(056)(24)}(057)(09)}(058)(08)}(059)(05)}
(060)(08)}(061)(15)}(062)(08)}(063)(91)}(064)(08)}(065)(16)}(066)(09)}(067)
(09)}(068)(08)}(069)(17)}(070)(16)}(071)(09)}(072)(09)}(073)(08)}(074)(17)}
(075)(16)}(076)(09)}(077)(09)}(078)(09)}(079)(61)}(080)(08)}(081)(11)}(082)
(08)}(083)(20)}(084)(24)}(085)(09)}(086)(08)}(087)(05)}(088)(08)}(089)(91)}
(090)(08)}(091)(16)}(092)(09)}(093)(09)}(094)(08)}(095)(17)}(096)(16)}(097)
(09)}(098)(09)}(099)(09)}(100)(61)}(101)(08)}(102)(20)}(103)(17)}(104)(09)}
(105)(61)}(106)(08)}(107)(20)}(108)(16)}(109)(09)}(110)(61)}(111)(08)}(112)
(11)}(113)(08)}(114)(20)}(115)(24)}(116)(09)}(117)(08)}(118)(15)}(119)(08)}
(120)(91)}(121)(08)}(122)(91)}(123)(08)}(124)(16)}(125)(09)}(126)(09)}(127)
(09)}(128)(08)}(129)(17)}(130)(16)}(131)(09)}(132)(09)}(133)(09)}(134)(61)}
(135)(08)}(136)(11)}(137)(08)}(138)(20)}(139)(24)}(140)(09)}(141)(08)}(142)
(05)}(143)(08)}(144)(91)}(145)(08)}(146)(91)}(147)(08)}(148)(16)}(149)(09)}
(150)(09)}(151)(09)}(152)(08)}(153)(17)}(154)(16)}(155)(09)}(156)(09)}(157)
(09)}(158)(61)}(159)(08)}(160)(20)}(161)(17)}(162)(09)}(163)(93)}(164)(08)}
(165)(16)}(166)(09)}(167)(08)}(168)(11)}(169)(08)}(170)(17)}(171)(09)}(172)
(08)}(173)(91)}(174)(08)}(175)(16)}(176)(09)}(177)(09)}(178)(09)}(179)(09)}
(180)(94)}(181)(08)}(182)(15)}(183)(08)}(184)(91)}(185)(08)}(186)(17)}(187)
(09)}(188)(09)}(189)(08)}(190)(18)}(191)(19)}(192)(16)}(193)(09)}(194)(09)}
(195)(08)}(196)(61)}(197)(08)}(198)(11)}(199)(08)}(200)(19)}(201)(18)}(202)
(09)}(203)(08)}(204)(91)}(205)(08)}(206)(91)}(207)(08)}(208)(17)}(209)(09)}
(210)(09)}(211)(09)}(212)(09)}(213)(93)}(214)(08)}(215)(17)}(216)(09)}(217)
(08)}(218)(11)}(219)(08)}(220)(17)}(221)(09)}(222)(08)}(223)(91)}(224)(08)}
(225)(17)}(226)(09)}(227)(09)}(228)(09)}(229)(09)~(/({(0))(230))(](125)]
(40)](+(48)(/({(0))(100)))](+(48)(%(/({(0))(10))(10)))](+(48)(%({(0))(10)))]
(41)](40)](+(48)(/({({(0)))(10)))](+(48)(%({({(0)))(10)))](41)}(0)(+(1)
({(0))))~(/({(1))(230))(](+(32)({({(1))))}(1)(+(1)({(1))))

A shorter quine is

}()(12872430441100276982898287331888341273694712212561754032457387972966053390121885560971120465568914029739991532252291383312910885004797316378038489445182646423771046386470134709527072922468161172180445227065244725860831882888079650601385257741999212883854949376079644467447663461959335745044107344)
](125)](40)](41)](40)
~(/(9)(}(+(1)(@()))(/({(@()))(10))))()~(](+(48)(%({(@()))(10)))?(@())(1)())(_(@()))
~(](+(37)(%({())(90)))/(1)(}()(/({())(90))))()

Truth-machine

}()([())?(-(48)({()))(](48))(?(-(49)({()))(~()(](49)))())

Implementations

Python

The Python reference implementation can be found at [3]. This implementation features an interactive interpreter (to exit the interpreter, type $ on its own line).

The Python reference implementation attempts to closely and flawlessly model the Integ standard listed here and in other places, such as the GitHub and the .py file containing the implementation.

Integbot

Integbot is a bot written in Python designed to respond to Integ commands in IRC. Because it is designed to work in IRC, Integbot has a few limitations compared to the reference implementation; execution of a command will terminate after 5 seconds, and commands cannot print an unlimited number of characters to the output. Nonetheless, Integbot is often more convenient to use than the reference implementation; nothing must be downloaded to one's computer.

If Integbot is online, it will be in #esoteric-blah, the esolang community's bot testing channel.

External resources