Oblivion is a programming language that compiles to SVG files. It's a language designed to visualize code and create incredible illustrations!
Features:
Oblivion
is the perfect programming language for artists, researchers, programmers, and anyone who wants to use a functional approach to visualize their code.
Try out Oblivion on the playground, or read the guide to see how it all works!
Installation
To Install Oblivion, use the following shell command
`$ npm install -g oblivion-js
To compile an .obl
file, use the following oblivion
command
$ oblivion yourfilename.obl
The stdout will be logged to your console and the svg output will be written to a file.
Drawing a two-colored square:
f = #red |= (1,1) *> (1,100) *> (100,100)
draw f
g = #green |= (1,1) *> (100,1) *> (100,100)
draw g
Oblivion is a programming language that outputs a string representing an svg format graphic. This is called the SVGOut
. We can think of this output as a buffer. Similarly, the language can aslo "print" statements to another output called StdOut
. Both of these are accessed with the draw
keyword and print()
function respectively.
Oblivion's compiler is implemented in TypeScript, with it's parser generated from JavaScript. Unlike most web-based languages, Oblivion does not transcomple to JavaScript. It also does not run on a virtual machine.
Oblivion uses a self-evaluating abstract syntax tree with a pre-defined set of rules. A program is compiled by traversing the abstract syntax tree in a depth-first fashion, and using a node's rule to evaluate it's child arguments. The state of evaluation never changes as rules are the same.
In Oblivon, newlines, spaces, tabs and commas are treated as whitespace. This means you can put as many commas, spaces or newlines as you like, to allow for a customized spacing of code.
print(3, 4)
print(3,,,,,,,,,
,,,,,,,,,,,,4)
3
4
3
Oblivion has a relatively small number of types, allowing for a small variety of data to yield many combinations of uses and functionality.
Numbers in Oblivion represent both Integers and Floats. They are very similar to JavaScript numbers.
print(7 /6)
print(4 + 6)
1.1666666666666667
10
Bools or booleans represent true and false in Oblivion. They are the results of using logical operators. true
and false
can also be used in lists or returned from functions
d = true || false
print(d)
print(d && false)
true
false
Lists are a special type in Oblivion and are denoted with square brackets []
. They can contain any value, and are not statically typed. They are also immutable, you can only use operators to create new lists, you can never edit a list once it's created.
print([1,2,3])
print([1 2 3])
g = [1] & [2, 3]
print(g)
print(g & [2, 3 + 3])
[1,2,3]
[1,2,3]
[1,2,3]
[1,2,3,2,6]
Points are two member structs that contain two numbers, one that applies to the x and y coordinate of a point on a grid. SVG graphics are always arranged on a x-y grid system, thus points are an easy way to manage places on a grid.
You can access the x and y properties of a point, but points are always immutable
f = (3, 2)
print(f.x)
3
In Oblivion, a line is a data structure that represent a series of points connected by a line. It is immutable, like the rest of Oblivon's types. A line has both a printable form and a drawable form. They are connected via the ->
operator.
g = (1,8) -> (44, 9) -> (44,44)
print(g)
g = #red |= g
draw g
1,8 -> 44,9 -> 44,44
Shapes, also called polygons, are very similar to lines, but they are always filled
. This means that the shape is always colored. Shapes are connected via the *>
operator.
g = (1,8) *> (44, 9) *> (44,44) *> (0, 90)
print(g)
g = #tan |= g
draw g
1,8 *> 44,9 *> 44,44 *> 0,90
You can also connect shapes to lines, for more complex SVG arrangements.
g = (1,8) *> (44, 9) *> (44,44)
g = #red |= g
g = (100, 10) -> (80, 60) -> g
draw g
Colors are special types in Oblivion that allow you to color your lines and shapes. For now, you can use a small range of named colors, like red
or orange
, or a hex color, such as #fff
.
Unlike most functional languages, Oblivion uses a wide array of operators (and a minimal amount of parenthsis).
It is important to note all operators in Oblivion associate toward the left. There is no other operator precedence.
Oblivion has five arithmetic operators, +, -, *, /, %
. They are used like so:
print(3 + 3)
print(44 / 5 - 4)
print(6 % 2)
6
44
0
The !!
operator returns a random number between the left and right numbers argued with it respectively. Such as 3 !! 10
.
Oblivion makes use of several different logical operators. These can be used to compare values, and check if values are the same.
==
equality!=
inequality<
lesser>
greater<=
lesser or equal>=
greater or equal~=
absolute equalityprint(3 == 4)
print([4] ~= [4])
print(true == 3 == 3)
print(3 != 4)
print(5 <= 5 + 7 - 3 * 4)
false
true
true
true
The ~=
checks for absolute equality, and can compare lists against each other. The ==
operator will not work properly for lists.
Oblivion has two operators specifically for lists! The first is the extension operator, &
. It returns a new list that is extended by the right hand list or other element. If the right side is not a list, it acts as an appending operator.
Second is the set, =>
operator. It allows you to reference an index of a list and returns a new copy of the list that gets reassigned.
a = [1, 2, 3]
print(a & [4])
print(a.1 => [3])
[1,2,3,4]
[1,[3],3,4]
The |=
operator takes one color and a line shape or combo and colors it.
Warning
The color operator also colors the entire SVG object.
g = (1,8) *> (94, 9) *> (44,44) *> (1, 100)
g = #red |= g
g = #yellow |= (100, 10) -> (80, 60) -> g
draw g
Oblivions only conditional element is the if statement. It's constructed similarly to Ruby's if..else syntax. Like with all body statements, if statements end with a _, and can be nested.
d = (3,4) -> (5,6)
e = (3,4) -> (5,6)
if d ~= e
print(true)
else
print(false)
_
true
They can also be used with the draw
keyword
g = (88, 1) *> (5, 5)
if 3 == 3
draw (30, 30) *> g
_
if 3 == 4
draw (30, 30) *> g
else
draw #green |= (60, 30) *> g
_
repeat()
is a function that can take some function or process, and call it a specific number of times. Repeat is a tool used to make drawing repetitive structures easier.
line = {
draw #green |= (0, i) -> (i, 0)
}
plus = {
i = 8
call(line)
i = i + 1
}
repeat(3, plus)
Functions are the central feature in Oblivion used for computation. They work much like functions in languages like Ruby and Python. They even use the all so familiar def
keyword!
def fact(i)
if i == 0
return i
else
return i + fact(i - 1)
_
_
print(fact(8))
36
Functions can also be used with drawing!
def diagonal(n)
if n == 0
return (0, 0)
else
return (n, n) -> diagonal(n - 1)
_
_
draw diagonal(99)
Because Oblivion uses trampoline recursion, the limit for a recursive call is much deeper than with most other languages.
A Process in oblivion is a no parameter function denoted by {}
. It's meant to serve as a currying tool to aid in functional programming. It's also very useful for drawing.
f = [1]
f = f.0 => {return [2]}
print(f.0())
[2]
You can also use processes with the repeat
built-in function
f = [1]
f = f.0 => {print(3)}
repeat(4, f.0)
3
3
3
3
Here's an exmaple that uses two processes together to draw with random numbers!
getnum = {return 1 !! 70}
randline = {
draw #cyan |= (getnum(), getnum()) -> (getnum(), getnum())
}
repeat(10, randline)
Oblivion also has a variety of built in List functions that can slice, search, and insert items into a newly returned list.
print(range(8))
print(insert(range(7), 3, 88))
print(find(range(5), 77))
print(len(range(8)))
print(slice([1, 2, 3, 4], 2))
print(in([1, 2], 3))
[0,1,2,3,4,5,6,7]
[0,1,2,88,3,4,5,6]
false
[3,4]
8
false
in()
Checks if a list contains a valuerange()
Creates a list from 0 to some integer, or from some start integer to some end integerlen()
Takes the length of a listinsert()
Return a new list with some item inserted at an index in the list.slice()
Return a new list between, or starting at the index in the arguments.