home *** CD-ROM | disk | FTP | other *** search
- <TITLE>ArmBob's datatypes</TITLE>
- <H2>ArmBob's datatypes</H2>
-
- As far as the programmer is concerned, all values in ArmBob programs
- have one of the following types.
- <UL>
- <LI> <A HREF="#nil">NIL</A>
- <LI> <A HREF="#integer">INTEGER</A>
- <LI> <A HREF="#real">REAL</A>
- <LI> <A HREF="#string">STRING</A>
- <LI> <A HREF="#bytecode">BYTECODE</A>
- <LI> <A HREF="#code">CODE</A>
- <LI> <A HREF="#iostream">IOSTREAM</A>
- <LI> <A HREF="#vector">VECTOR</A>
- <LI> <A HREF="#object">OBJECT</A>
- </UL>
- These names are predefined as synonyms for the numerical codes
- returned by the function <A HREF="Glossary#typeof"> <CODE>typeof</CODE> </A>.
- What the numerical codes are is not important, except that NIL has
- the value 0, and all other types have nonzero code.
- <P>
- Typing in ArmBob is implicit. Values carry their type around with them
- and typechecking occurs at run time. There are no type declarations.
- That is to say, types attach to values, not to variables or
- expressions (apart from literal expressions).
- <HR>
- <H3><A NAME="nil">NIL</A></H3>
- This type has only one value: <CODE> nil </CODE>. It is the
- default value for unassigned variables, and for functions with
- no <CODE> return </CODE> statement. As a conditional,
- <CODE> nil </CODE> counts as FALSE.
-
- <H3><A NAME="integer">INTEGER</A></H3>
- Integers must be in the range from -2147483648 to 2147483647. They
- may also be used in hexadecimal form, with a '&' as
- prefix, with lower case a,b,c,d,e,f denoting 10,11,12,13,14,15,
- in the range from &00000000 to &ffffffff.
- Characters are simply integers in the range 0-255. Single
- characters are enclosed in single forward quote characters
- <CODE> (') </CODE>. So <CODE> 'A' </CODE>
- also denotes the integer 65, for example.
- The character <CODE> '\' </CODE> is used as an escape character,
- with <CODE> '\n', '\t' </CODE> denoting the
- newline and tab characters.
-
- In conditional expressions, any nonzero integer is taken to represent
- truth, and zero or nil as falsity. TRUE is a synonym for 1 and FALSE
- is a synonym for 0.
-
- It isĀ also possible to use integers as addresses.
-
- <H3><A NAME="real">REAL</A></H3>
- Single precision floating point numbers are characterised by the
- presence of a decimal point. Thus <CODE> x = 0; </CODE> will make
- <CODE> x </CODE> an integer, but <CODE> x = 0.0; </CODE> will make
- <CODE> x </CODE> a real. Reals can be multiplied or divided by
- either reals or integers and the result is a real. So an integer can
- be converted to a real by multiplying it by 1.0.
- You may not add or subtract a real with an integer.
-
- <H3><A NAME="string">STRING</A></H3>
- Strings are arrays of bytes. They can be created either by a command
- of the form <CODE><PRE>
- string_name = newstring(size); </CODE></PRE>
- which creates a string of ASCII nulls, of size <CODE> size </CODE>,
- or by using literal strings. These are are enclosed in double quotes
- (") and may not contain the double quote character.
- The component characters of a string <CODE> s </CODE> are
- <CODE><PRE>
- s[0], s[1], ........ s[sizeof(s)-1]
- </PRE></CODE>
- As in Basic, strings may be concatenated using the operators
- <CODE> + </CODE> and <CODE> += </CODE>. So <CODE> s += t </CODE>
- is equivalent to <CODE> s = s + t </CODE>. In fact string handling
- in Armbob resembles Basic rather than C. The operator <CODE> + </CODE>
- can also be used to add characters to strings. This operator
- associates to the left, so that
- <CODE><PRE>
- 33+33+""
- </PRE></CODE>
- is the 1-element string <CODE> "B" </CODE>, while
- <CODE><PRE>
- ""+33+33
- </PRE></CODE>
- is the 2-element string <CODE> "!!" </CODE>.
- The function <CODE> val </CODE> will convert as much of a
- string into a number as it can. So
- <CODE> val(" +10x") </CODE> and
- <CODE> val("&a") </CODE> will both return 10.
- The comparison operators work with strings as well as numbers,
- and strings may be used after <CODE> case </CODE> in
- <CODE> switch </CODE> structures.
-
- <H3><A NAME="bytecode">BYTECODE</A></H3>
- This is the type of user defined functions and methods.
- These can only appear at the top level of a program.
- Every program must have one function called <CODE>main</CODE>
- defined. This determines the entry point for the program.
- Functions can be the values of variables. Note that the parenthesized
- list of formal parameters following the function name in a function
- definition is not part of the function name itself. Functions can be
- returned as values of functions. E.g. <CODE><PRE>
- add(x,y) { return x+y; }
- mul(x,y) { return x*y; }
- main()
- { print("+/*?");
- print(((input() == "*")?mul:add)(2,100),"\n"); }
- </PRE></CODE>
-
- <H3><A NAME="code">CODE</A></H3>
- This is the type of built-in functions. Although built-in and user
- defined functions are represented differently internally, and have
- different types, in all other respects they behave the same way.
-
- <H3><A NAME="iostream">IOSTREAM</A></H3>
- The following function, to type out the contents of a file, illustrates
- how iostreams are opened and closed.<CODE><PRE>
-
- typefile(filename)
- {
- local fp,c;
- if (fp = fopen(filename,"r"))
- {
- while ((c = getc(fp)) != EOF)
- putc(c,stdout);
- fclose(fp);
- }
- }
- </PRE></CODE> The iostreams
- <A HREF="Glossary#stderr"> <CODE>stderr</CODE> </A>,
- <A HREF="Glossary#stdin"> <CODE>stdin</CODE> </A>,
- <A HREF="Glossary#stdout"> <CODE>stdout</CODE> </A>,
- are built in. The following iostream handling functions are built in:
- <A HREF="Glossary#fclose"> <CODE>fclose</CODE> </A>,
- <A HREF="Glossary#fopen"> <CODE>fopen</CODE> </A>,
- <A HREF="Glossary#getc"> <CODE>getc</CODE> </A>,
- <A HREF="Glossary#putc"> <CODE>putc</CODE> </A>.
- The expression <CODE> fp << s </CODE> will output
- the string <CODE> s </CODE> to iostream <CODE> fp </CODE>.
- The value of this expression is <CODE> fp </CODE>, and
- <CODE> << </CODE> associates to the left, so that
- <CODE><PRE>
- fp << s1 << s2 .....
- </PRE></CODE>
- is equivalent to
- <CODE><PRE>
- fp << (s1 + s2 + ...... )
- </PRE></CODE>
-
- <H3><A NAME="vector">VECTOR</A></H3>
- Vectors are arrays of fixed size. Their components can have any type.
- In fact a vector can be one of its own components. Vectors allow one
- to construct complex datatypes.
- They can be created by statements of the form
- <CODE><PRE>
- v = newvector(size);
- </PRE></CODE>
- which creates a new vector with <CODE> size </CODE> components which are
- all <CODE> nil </CODE>. The components are
- <CODE><PRE>
- v[0], .... , v[size-1]
- </PRE></CODE>
- Alternatively, the expression
- <CODE><PRE>
- vector { <VAR>expr1</VAR>; ...... <VAR>exprn</VAR>; }
- </PRE></CODE>
- returns a new vector with components <VAR>expr1 ... exprn</VAR>.
- There must be at least one component and not more than 255 for
- this construction. Vectors have only one index. To define
- matrices we could define
- <CODE><PRE>
- newmatrix(m,n)
- {
- local matrix,i;
- matrix = newvector(m);
- for(i=0;i<m;i++)
- matrix[i] = newvector(n);
- return matrix;
- }
- </PRE></CODE>
- and <CODE> matrix[i][j] </CODE> will be the element in the
- <CODE> i </CODE>-th row and <CODE> j </CODE>-th column.
- This has the advantage that the <CODE> i </CODE>-th row is
- <CODE> matrix[i] </CODE>. When a vector is first created its
- components all have the value <CODE> nil </CODE>. We can replace
- the numerical indices by names using the
- <A HREF="Glossary#enum> <CODE>enum </CODE> </A>
- function. E.g.
- <CODE><PRE>
- _3_vector = enum { x, y, z };
- v = newvector(_3_vector);
- v[x] = v[y] = v[z] = 0.0;
- </PRE></CODE>
-
- <H3><A NAME="object">OBJECT</A></H3>
- Following the conventions of C++, for every class one must define a
- function with the same name as the class, to be used for creating
- instance objects of the class. This function must exit with the
- statement <CODE> return this; </CODE>. E.g.
- <CODE><PRE>
- class person {age; name;}
- <P>
- person::person(a,n) // for creating new persons
- { age = a; name = n; return this;}
- <P>
- person::has_age() // for getting the age of a person
- { return age; }
- <P>
- person::called() // for getting the name of a person
- { return name; }
- <P>
- person::older(y) // for making a person age
- { age += y; }
- <P>
- person::tell_age() // tell how old someone is
- {
- stdout << this->called()
- << " is "
- << this->has_age()
- << " years old.\n" ;
- }
- <P>
- main()
- {
- Fred = new person(30,"Fred"); // Fred is born 30 years old
- Fred->tell_age();
- Fred->older(10); // he ages 10 years
- Fred->tell_age();
- }
- </PRE></CODE>
- This example demonstrates the use of the all-important operators
- <A HREF="Glossary#colon2"> <CODE>:: </CODE> </A> and
- <A HREF="Glossary#arrow"> <CODE>-> </CODE> </A> for defining
- and using methods, and the keyword
- <A HREF="Glossary#new> <CODE>new </CODE> </A> for creating
- instance objects.
-