Skip to content
Io, the language, in Go, the language
Go Io
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
addons synchronize individual slots Dec 31, 2019
cmd synchronize individual slots Dec 31, 2019
io synchronize individual slots Dec 31, 2019
testutils optimize for objects with only one proto Jan 2, 2020
.gitignore Fix builds for Darwin with a Darwin built dependent file module Nov 15, 2019
LICENSE updated LICENSE years Jan 26, 2019
README.md correct location of REPL in README Nov 15, 2019
addon.go use coreInstall rather than SetSlot for normal Core protos Jan 3, 2020
block.go faster slots experiment Jan 22, 2020
bool.go
cfunction.go
collector.go use coreInstall rather than SetSlot for normal Core protos Jan 3, 2020
control.go ensure ExitStop overrides every form of control flow Jan 1, 2020
coroutine.go
date.go Date: It mysteriously started working after a push! Dec 23, 2019
debugger.go synchronize individual slots Dec 31, 2019
directory.go swap names of NewObject and ObjectWith Nov 3, 2019
doc.go use asBoolean for conditions, not isTrue Dec 21, 2019
duration.go swap names of NewObject and ObjectWith Nov 3, 2019
exception.go
file.go synchronize individual slots Dec 31, 2019
file_darwin.go add File groupId and userId Dec 24, 2019
file_js.go add File groupId and userId Dec 24, 2019
file_plan9.go add File groupId and userId Dec 24, 2019
file_unix.go add File groupId and userId Dec 24, 2019
file_windows.go
future.go
go.mod Date: Turns out datesaurus completely unnecessary, whoops Dec 23, 2019
go.sum Date: Turns out datesaurus completely unnecessary, whoops Dec 23, 2019
lex.go lex from io.RuneScanner instead of specifically bufio.Reader Sep 28, 2019
lex_test.go lex from io.RuneScanner instead of specifically bufio.Reader Sep 28, 2019
list.go synchronize individual slots Dec 31, 2019
map.go synchronize individual slots Dec 31, 2019
message.go synchronize individual slots Dec 31, 2019
message_test.go
number.go synchronize individual slots Dec 31, 2019
object.go faster slots experiment Jan 22, 2020
object_test.go optimize for objects with only one proto Jan 2, 2020
optable.go synchronize individual slots Dec 31, 2019
optable_test.go synchronize individual slots Dec 31, 2019
parse.go
parse_test.go make testutils subpackage Dec 16, 2019
path.go use coreInstall rather than SetSlot for normal Core protos Jan 3, 2020
scheduler.go synchronize individual slots Dec 31, 2019
sequence.go synchronize individual slots Dec 31, 2019
sequence_immutable.go synchronize individual slots Dec 31, 2019
sequence_math.go fix performing while holding locks in various Sequence math methods Dec 26, 2019
sequence_mutable.go rename sequence-*.go to sequence_*.go Nov 3, 2019
sequence_string.go
slots.go
system.go use coreInstall rather than SetSlot for normal Core protos Jan 3, 2020
system_js.go
system_plan9.go replace all init functions outside tests with sync.Once Nov 3, 2019
system_unix.go replace all init functions outside tests with sync.Once Nov 3, 2019
system_windows.go replace all init functions outside tests with sync.Once Nov 3, 2019
testutils_test.go
vm.go optimize for objects with only one proto Jan 2, 2020
vm_init.go synchronize individual slots Dec 31, 2019
vm_test.go optimize for objects with only one proto Jan 2, 2020

README.md

iolang

This is a pure Go implementation of Io. Much of the hard work has been done, but hard work still remains.

To embed an iolang interpreter into a Go program, one would use the NewVM() function to get a *VM, use SetSlot() to make available any extras, then feed the VM code to evaluate with its DoString() and DoReader() methods. The VM also has methods like NewNumber(), NewString(), NewObject(), &c. to create primitives. The API is currently incomplete and may change.

The cmd/io directory contains a REPL as an example of embedding iolang.

This implementation does not always behave identically to the original.

Io Primer

"Hello, world!" println

Io is a programming language primarily inspired by Self, Smalltalk, and Lisp. Execution is implemented by message passing: the phrase Object slot, when evaluated, creates a message with the text slot and sends it to Object, which is itself a message passed to the default Lobby object. Messages can also be provided with arguments, which are simply additional messages to provide more information with the message, in parentheses. Object slot(arg1, arg2) provides the arg1 and arg2 messages as arguments to the call. The only syntactic elements other than messages are numeric and string literals and comments.

When an object receives a message, it checks for a slot on the object with the same name as the message text. If the object has such a slot, then it is activated and produces a value. Slots can be added to objects using the := or ::= assignment operators; Object x := 1 creates a slot on Object named x that will produce the value 1 when activated.

Certain objects have special behavior when activated. Methods are encapsulated messages that, when activated, send that message to the receiver of the message which activated the method. For example, with println being an Object method, x println executes println's message in the context of x, meaning that the default location for slot lookups becomes x instead of Lobby. Methods also have their own locals, so new slots created within them exist only inside the method body, and they can take arguments, setting slots on the locals object for each argument.

If an object does not own a slot with the same name as a message passed to it, the object will instead check for that slot in its prototypes. Objects can have any number of protos, and the search proceeds in depth-first order without duplicates. If the slot is found in one of the protos, then it is activated, but still with the original object as the receiver. This implements an inheritance-like concept, but with "superclasses" being themselves objects. (If there isn't any proto with the slot, then the message is sent to the object's forward slot, and if that slot doesn't exist, either, then an exception is raised.)

Producing "subclasses" is done using the clone method. A clone of an object, say x, is another object which has (initially) empty slots and x as its only prototype. If we say y := x clone, then y will respond to the same messages as x via delegation; new slots can be created which will be activated in place of the proto's, providing polymorphism. The typical pattern to implement a new "type" is to say NewType := Object clone do(x := y; z := w), where do is an Object method which evaluates code in the context of its receiver. Then, "instances" of the new "class" can be created using instance := NewType clone. Notice that clone is the method used both to create a new type and an instance of that type - this is prototype-based programming.

An important aspect of Io lacking syntax beyond messages is that control flow is implemented as Object methods. if is a method taking one to three arguments: if(cond, message when cond is true, message when cond is false) evaluates its first argument, then the second if it is true or the third if it is false. Because message arguments are themselves messages, the other argument is not evaluated. When any of the arguments are not supplied, the evaluation result is returned instead, which enables alternate forms of branching: if(cond) then(message when cond is true) elseif(cond2, different message) else(last thing to try). There are also loops, including for to loop over a range with a counter, while to perform a loop as long as a condition is true, loop to perform a loop forever, and others. continue, break, and return generally do what you expect. Each of these methods is an expression, and the last value produced during evaluation of each is returned.

For a more in-depth introduction to Io, check out the official guide and reference. There are more code examples at the original implementation's GitHub repository as well.

You can’t perform that action at this time.