INPUT /  OUTPUT /  LANGUAGE





Values

So far you've given fields values like {black}, true and 24,pt without thinking too hard about them. This chapter looks at the different kinds of value in ioL, how to write each one, and how they behave.

There are four kinds:

(There's also a fifth kind, the reference pointer, which you'll meet much later.)


Text

Inside a tag, text goes in braces: {like this}. Everything between the braces is part of the text, including spaces. You can use escape sequences in it, and tags, as you saw in the chapter on tags and fields.

Remember that your program's output as a whole is also treated as text, as if it were wrapped in an invisible pair of braces. That's why you don't need braces around the plain text you print.

When you put several values in a field without commas, any blocks of text that end up next to each other are joined together into one:

<box {Hello, } {world}>      <! the box contains one piece of text: "Hello, world" !>

Numbers

Numbers are written the way you'd expect, with no braces:

7    3.14    -28    0.5

Numbers and text are different things, even if they look alike. 42 is a number you can do arithmetic with, while {42} is just two characters of text. This matters when a field expects a number, such as a width or a size.

Other number systems

Just like in character codes, you can write numbers in binary, octal or hexadecimal by starting them with b, o or x:

Written asNumber systemValue
b1010binary10
o52octal42
x1Fhexadecimal31
b10110101.1binary, with a fractional part181.5

This only changes how you write the number. Once ioL has read it, it's just a number, and if it's displayed it appears in ordinary decimal. You've already used hexadecimal for colours: x2E8B57 is simply a number that ioL understands as a colour.

Hexadecimal digits A–F must be UPPERCASE. Here's why: xFADE is a number, but xfade could just as easily be a name you've chosen for something. Because the hexadecimal digits are always uppercase, ioL can tell them apart: x followed by uppercase digits is a number, and x followed by lowercase letters is a name.

Moving the point

An s at the end of a number, followed by a whole number, shifts the point that many places (to the left if the number is negative). It works in any number system:

Written asMeaningValue
52s-252 with the point moved 2 places left0.52
1.5s31.5 with the point moved 3 places right1500
b1011s4binary 1011, point moved 4 places rightb10110000 (176)

How big can a number be?

ioL stores whole numbers in a fixed amount of memory, so there's a limit to how big they can be: from -2,147,483,648 to 2,147,483,647. A calculation whose result goes past either end doesn't cause an error. Instead, it overflows: the result wraps round to the other end of the range, and you get a completely wrong answer, with no warning at all:

<add 2147483647, 1>       <! generates -2147483648, not 2147483648 !>
<mul 50000, 50000>        <! generates -1794967296, not 2500000000 !>

Numbers with a decimal point can be much bigger, but they're only stored to a limited number of digits, so very large or very precise results get rounded.

For the sizes, positions and scores in a typical interface, none of this matters. But if your numbers could get large, do the arithmetic in your program instead, where your programming language gives you more control.

Overflow is one of the oldest kinds of bug in computing, and it has caused serious failures ever since the early days of programming in the 1960s. A famous example is the first launch of the Ariane 5 rocket in 1996, which destroyed itself less than a minute after lift-off because a number in its guidance software became too large for the space it was stored in. Whenever you store a number, in any language, it's worth asking: how big could this get?

True and false

true and false are values in their own right, written without braces. Fields that switch something on or off, like bold or visible, take one of these.

When a field or tag needs a true-or-false answer but is given some other kind of value, ioL decides whether that value counts as true:

Counts as trueCounts as false
true
any number other than zero
any text that isn't empty, even {false} or {0}
false
0
empty text, {}
null

You'll use this a lot once you start making decisions in your code, in the chapter on logic.

Special values

null

null means "no value". It isn't zero, and it isn't empty text: it's the absence of any value at all. If null is displayed, nothing appears.

You'll often give a field the value null to say "I'm not choosing anything for this yet", for example backgroundColor=null. You'll see why that's useful in the chapter on instance names.

inf

inf means infinity. You'll usually only see it as the result of dividing by zero. There's no negative infinity in ioL: dividing a negative number by zero gives inf too.

invalid

invalid means "there's no sensible answer". It's what you get when something goes wrong: a name that doesn't exist, an impossible operation, or a value ioL couldn't make sense of. When invalid ends up on screen, it appears as a marker so you can see where the problem is, and the terminal usually shows an error message explaining why.

Each of these three special values (and true and false) can also be used to test whether something is exactly that value. You'll see how in the chapter on logic.

How values are displayed

When a tag displays values, it shows them one after another with nothing in between:

<box 1,2,3>               <! shows "123" !>
<box {Total: }, 42>       <! shows "Total: 42" !>
<box x1F>                 <! shows "31" !>
<box {x1F}>               <! shows "x1F", because this is text !>

If you want spaces or commas between them, you need to add them yourself. (There's a tag that does this for whole lists of values, called join, which you'll meet later.)

Raw data

Some data isn't text at all. An image file, for example, is a long series of bytes that would make no sense if you tried to read it as characters, and it can contain any byte at all, including } or >. You can't put data like that in braces, because ioL would have no way to know where it ends.

Instead, you tell ioL in advance exactly how many bytes are coming:

[number of bytes{the data}]

ioL reads exactly that many bytes, whatever they are, then expects }]. Raw data is a value of its own, like a number, so it goes in a field (<box [5{hello}]>). It can't go inside a block of text in braces, where [ is just an ordinary character. Escape sequences and comments don't work inside raw data: every byte is taken exactly as it is. In Python, you'd send the contents of a file like this:

import sys

def print_raw(filename):
    with open(filename, 'rb') as f:
        data = f.read()
    print('[' + str(len(data)) + '{', end='')
    sys.stdout.buffer.write(data)
    print('}]', end='')

The count is in bytes, not characters. That's the same thing for plain English text, but not for every character: é, for example, takes two bytes. You'll use raw data to display pictures and play sounds, in the chapter on images and media.


Try it

  1. Display the number 255 in a box, written in each of the four number systems. Do all four boxes show the same thing?
  2. What's the difference between <box {b1010}> and <box b1010>? Predict what each shows, then try it.
  3. Write width=xfade in a box. What appears in the terminal, and why?
  4. Use print_raw to send a short text file as raw data, as the primary field of a box.