Turbo Pascal 2.0 course cover
← Back to Courses
module
17

Your Own Types

Introduction

Warehouse is built of squares, and every square is one of a few things: a wall, a bit of floor, a goal, a crate. You could number them - 0 for a wall, 1 for floor - and remember which is which. Or you could tell Pascal what the things are called, and have it remember for you, and refuse to let a square be anything else. That is what your own types are for.

Enumerated Types

type
  Tile = (Wall, Floor, Goal, Crate);
var
  T: Tile;

This declares a new type, Tile, whose values are exactly the four names in brackets - in that order. A Tile variable can hold Wall, Floor, Goal or Crate, and nothing else:

T := Floor;
if T = Wall then ...

The names are new words in your program, as good as True and False.

Because the values have an order, several things you know from numbers work:

  • Ord(T) gives its position, counting from 0: Ord(Wall) is 0, Ord(Crate) is 3.
  • Succ and Pred give the next and previous values: Succ(Wall) is Floor.
  • Comparisons follow the order: Wall < Crate is true.
  • for runs through them: for T := Wall to Crate do, or downto.
  • case chooses on them.
  • And the type's name turns a number back into a value: Tile(3) is Crate.

They Cannot Be Printed

Turbo will not print an enumerated value: Writeln(T) is

Error 66: I/O are not allowed. Press <ESC>

The names are for you and the compiler; to show one, print its Ord, or - much better - write a procedure that shows each value as it should appear. That is this section's program, and in Warehouse it draws the board.

Subranges

A subrange is a type limited to part of another:

type
  Col = 1..20;
  Mark = 0..100;

A Col is an integer from 1 to 20. Subranges say what a variable is for - a column on a board of 20, a mark out of 100 - and, with range checking on, Turbo holds you to it.

Byte is a subrange Turbo already has, from 0 to 255, and it wraps like an integer: 255 plus 1 is 0.

Constants

A number that means something should have a name:

const
  Width = 20;
  Height = 16;
type
  Col = 1..Width;

The const section comes before type. A constant can be used anywhere its value could - in sums, in a subrange - and it cannot be changed: Width := 30 is Error 41. When the board grows to 24 wide, you change one line.

Range Checking

Here is a trap. With Turbo as it starts, nothing checks the limits. A Col variable will happily hold 50; C := 25 is not even an error when compiled; and Succ(Crate) gives a fifth, nameless tile with Ord 4. The limits you declared are documentation and nothing more.

Put this at the top of the program:

{$R+}

and Turbo checks assignments to subrange variables as the program runs. The first value out of range stops it:

Run-time error 91, PC=004E
Program aborted

and ESC shows you the assignment that did it. Borland's manual recommends {$R+} while a program is being developed, and taking it out once the program works, because the checking slows the program down.

The Code

program Tiles;
type
  Tile = (Wall, Floor, Goal, Crate);
var
  T: Tile;

procedure Show(What: Tile);
begin
  case What of
    Wall: Write('#');
    Floor: Write(' ');
    Goal: Write('.');
    Crate: Write('$');
  end;
end;

begin
  for T := Wall to Crate do
  begin
    Show(T);
    Writeln(' is tile ', Ord(T));
  end;
end.

These are the characters Warehouse will draw its board with: # for a wall, a space for floor, . for a goal and $ for a crate.

Starting from

Turbo freshly started, Y, a new work file called TILES.

What you should see

# is tile 0
  is tile 1
. is tile 2
$ is tile 3

The floor's line begins with its own character - a space.

Change One Thing

  • Change Show(T); to Writeln(T);. What does Turbo say?
  • Add a fifth value, Worker, to the end of the type, and change the loop to run to Worker. What is printed for it, and why?
  • Run the loop Crate downto Wall instead. What happens to the order?

Exercises

17.1 Declare Direction = (North, East, South, West) and write a function TurnRight that gives the next direction clockwise - with West turning back to North. Starting from North, turn right six times, printing Ord of each direction.

17.2 Declare Mark = 0..100, switch on range checking, set a Mark to 99 and add 2 to it. What happens?

17.3 Declare constants Width = 20 and Height = 16, and print how many squares a board that size has.

Worked solutions are in Appendix II.

When It Goes Wrong

SymptomCause
Error 66: I/O are not allowedWriting an enumerated value. Print its Ord, or show it through a case.
A variable holds a value outside its declared range{$R+} is not on; nothing checks.
Run-time error 91A value out of range with {$R+} on. ESC shows where.
Error 41 assigning to a constantConstants cannot change. Use a variable.
A case on your type does nothingThe value has no label - perhaps a value you added to the type later.

Summary

type Tile = (Wall, Floor, Goal, Crate); makes a type whose values are those names, in order; Ord, Succ, Pred, comparisons, for and case all work on it, but it cannot be printed. Subranges such as 1..20 limit a type; const names a value that never changes. Nothing is range-checked unless {$R+} is on, and then an out-of-range value is Run-time error 91.

Next

S18, Sets - "is this one of those?" in one test: the question Warehouse asks every time the worker moves.

Get the Newsletter

New guides, disk images and community finds, roughly once a quarter. No spam, we promise, this isn't Tatung's marketing department.
Your subscription could not be saved. Please try again.
Your subscription has been successful.

Newsletter

Subscribe to our newsletter and stay updated.