Frequently Asked Questions

## B Frequently Asked Questions

What does `$(type``1``,type``2``)` mean? What does `$(expr``1``, expr``2``)` mean?
What does `int @` mean?
What does `int *{``37}` mean?
What does `int *`r` mean?
What does ``H` mean?
What does `int @{``37}```r` mean?
What does `int ?` mean?
What is a pointer type's region when it's omitted?
What does ``a` mean?
What is a ``suitable'' type for a type variable?
How do I cast from `void *`?
What does `_` (underscore) mean in types?
What do ``a::B`, ``a::M`, ``a::A`, ``a::R`, and ``a::E` mean?
What does it mean when type variables don't have explicit kinds?
What does `struct List<`a,`r::R>` mean?
What are `@tagged` unions?
What is `abstract`?
What are the Cyclone keywords?
What are `namespace` and `using`?
What is `fallthru`?
What is `new`?
How do I use tuples?
What is `{``for i < expr``1``: expr``2``}`?
How do I throw and catch exceptions?
How efficient is exception handling?
What does `let` mean?
What is a pattern and how do I use it?
What does `_` mean in a pattern?
What does it mean when a function has an argument with type ``a`?
Do functions with type variables get duplicated like C++ template functions?
Is there run-time overhead for using type variables?
Can I use varargs?
Why can't I declare types within functions?
What casts are allowed?
Why can't I implicitly fall-through to the next `switch` case?
Do I have to initialize global variables?
Are there threads?
Can I use `setjmp` and `longjmp`?
What types are allowed for union members?
Why can't I do anything with values of type `void *`?
What is `aprintf`?
How do I access command-line arguments?
Why can't I pass a stack pointer to certain functions?
Why do I get an incomprehensible error when I assign a local's address to a pointer variable?
How much pointer arithmetic can I do?
What is the type of a literal string?
Are strings NUL-terminated?
How do I use `malloc`?
Can I call free?
Is there a garbage collector?
How can I make a stack-allocated array?
Can I use `salloc` or `realloc`?
Why do I have to cast from `*` to `@` if I've already tested for `NULL`?
Why can't a function parameter or struct field have type ``a::M`?
Can I see how Cyclone compiles the code?
Can I use `gdb` on the output?
Can I use `gprof` on the output?
Is there an Emacs mode for Cyclone?
Does Cyclone have something to do with runtime code generation?
What platforms are supported?
Why aren't there more libraries?
Why doesn't `List::imp_rev(l)` change `l` to its reverse?
Can I inline functions?
If Cyclone is safe, why does my program crash?
What are compile-time constants?
How can I get the size of an array?

What does `$(type``1``,type``2``)` mean? What does `$(expr``1``, expr``2``)` mean?

  Cyclone has tuples, which are anonymous structs with fields numbered 0, 1, 2, .... For example, `$(int,string_t)` is a pair of an `int` and a `string_t`. An example value of this type is `$(4,"cyclone")`. To extract a field from a tuple, you use array-like notation: you write `x[0]`, not `x.0`.

What does `int @` mean?

  In Cyclone `@` is a pointer that is guaranteed not to be `NULL`. The Cyclone compiler guarantees this through static or dynamic checks. For example,

        int *x = NULL;

  is not an error, but

        int @x = NULL;

  is an error. Note that ```int @`'' is shorthand for the more verbose ```int *@notnull`''.

What does `int *{``37}` mean?

  This is the type of (possibly-null) pointers to a sequence of at least 37 integers, which can also be written as ```int *@numelts(37)`''. The extra length information is used by Cyclone to prevent buffer overflows. For example, Cyclone will compile `x[expr``]` into code that will evaluate expr, and check that the result is less than 37 before accessing the element. Note that `int *` is just shorthand for `int *{1}`. Currently, the expression in the braces must be a compile-time constant.

What does `int *`r` mean?

  This is the type of a pointer to an `int` in region ``r`. This can also be written as ```int *@region(`r)`''. A region indicates conceptually where in memory an object is stored; different regions have different lifetimes and deallocation strategies, and the aliasing into certain regions may be restricted. Cyclone uses this region information to prevent dereferencing a pointer whose storage has been deallocated. See Section 8 for more information on regions.

What does ``H` mean?

  This is Cyclone's heap region: objects in this region cannot be explicitly freed, only garbage-collected. Effectively, this means that pointers into the heap region can always be safely dereferenced.

What does `int @{``37}```r` mean?

  A pointer can come with all or none of the nullity, bound, and region annotation. This type is the type of non-`null` pointers to at least 37 consecutive integers in region ``r`. When the bound is omitted it default to 1.

What is a pointer type's region when it's omitted?

  Every pointer type has a region; if you omit it, the compiler chooses a region name you implicitly. The name chosen depends on where the pointer type occurs. In function arguments, a fresh region variable is used. In function results and type definitions (including `typedef`), the heap region (``H`) is used. In function bodies, the compiler looks at the uses (using unification) to try to determine a region. See Section 2.3 and Section 8 for more information.

What does `int ?` mean?

  The `?` a special kind of pointer that carries along bounds information. It is a ``questionable'' pointer: it might be NULL or pointing out of bounds. An `int ?` is a pointer to an integer, along with some information that allows Cyclone to check whether the pointer is in bounds at run-time. These are the only kinds of pointers that you can use for pointer arithmetic in Cyclone.

What does ``a` mean?

  ``a` is a type variable. Type variables are typically used in polymorphic functions. For example, if a function takes a parameter of type ``a`, then the function can be called with a value of any suitable type. If there are two arguments of type ``a`, then any call will have to give values of the same type for those parameters. And if the function returns a type ``a`, then it must return a result of the same type as the the argument. Syntactically, a type variable is any identifier beginning with ``` (backquote).

What is a ``suitable'' type for a type variable?

  The last question said that a type variable can stand for a ``suitable'' type. Unfortunately, not all types are ``suitable.'' Briefly, the ``suitable'' types are those that fit into a general-purpose machine register, typically including `int`, and pointers. Non-suitable types include `float`, `struct` types (which can be of arbitrary size), tuples, and questionable pointers. Technically, the suitable types are the types of ``box kind,'' described below.

How do I cast from `void *`?

  You can't do this in Cyclone. A `void *` in C really does not point to `void`, it points to a value of some type. However, when you cast from a `void *` in C, there is no guarantee that the pointer actually points to a value of the expected type. This can lead to crashes, so Cyclone doesn't permit it. Cyclone's polymorphism and tagged unions can often be used in places where C needs to use `void *`, and they are safe. Note that you can generally cast to a `void *` in Cyclone, you just won't be able to cast back.

What does `_` (underscore) mean in types?

  Underscore is a ``wildcard'' type. It stands for some type that the programmer doesn't want to bother writing out; the compiler is expected to fill in the type for the programmer. Sometimes, the compiler isn't smart enough to figure out the type (you will get an error message if so), but usually there is enough contextual information for the compiler to succeed. For example, if you write

        _ x = new Pair(3,4);

  the compiler can easily infer that the wildcard stands for `struct Pair @`. In fact, if `x` is later assigned `NULL`, the compiler will infer that `x` has type `struct Pair *` instead.
  Note that only in restricted cases is `_` allowed as part of top-level declarations.

What do ``a::B`, ``a::M`, ``a::A`, ``a::R`, ``a::Q` and ``a::E` mean?

  Types are divided into different groups, which we call kinds. There are six kinds: B (for Box), M (for Memory), A (for Any), E (for Effect), R (for Region), and Q (for alias-Qualifier). The notation typevar`::`kind says that a type variable belongs to a kind. A type variable can only be instantiated by types that belong to its kind.
  Box types include `int`, `long`, `region_t`, `tag_t`, enums, and non-`@fat` pointers. Memory types include all box types, `void`, `char`, `short`, `long long`, `float`, `double`, arrays, tuples, `datatype` and `@extensible datatype` variants, `@fat` pointers, and non-abstract structs and unions. Any types include all types that don't have kind R, E or Q. For the region types, R indicates regions like the heap, stack, and dynamic regions; Q indicates alias qualifiers like ALIASABLE, UNIQUE, REFCNT or RESTRICTED; Effect types are sets of regions (these are explained elsewhere).

What does it mean when type variables don't have explicit kinds?

  Every type variable has a kind, but usually the programmer doesn't have to write it down. In function prototypes, the compiler will infer the most permissive kind. For example,

        void f(`a *`b x, `c * y, `a z);

  is shorthand for

      void f(`a::B *`b::R x, `c::M * y, `a::B z)

  In type definitions, no inference is performed: an omitted kind is shorthand for `::B`. For example,

      struct S<`a,`r::R> { `a *`r x; };

  is shorthand for

      struct S<`a::B,`r::R> { `a *`r x;};

  but

      struct S<`a,`r>{`a *`r x;};

  is not.

What does `struct List<`a,`r::R>` mean?

  `struct List` takes a type of box kind and a region and produces a type. For example, `struct List<int, `H>` is a type, and `struct List<struct List<int,`H>@, `H>` is a type. `struct List<`a,`r::R>` is a list whose elements all have type ``a` and live in region ``r`.

What is a `@tagged` union?

  In C, when a value has a `union` type, you know that in fact it has one of the types of the union's fields, but there is no guarantee which one. This can lead to crashes in C. Cyclone's @tagged unions are like C unions with some additional information (a tag) that lets the Cyclone compiler determine what type the underlying value actually has, thus helping to ensure safety.

What is `abstract`?

  `abstract` is a storage-class specifier, like `static` or `extern`. When attached to a top-level type declaration, it means that other files can use the type but cannot look at the internals of the type (e.g., other files cannot access the fields of an abstract struct). Otherwise, abstract has the same meaning as the `auto` (default) storage class. Hence `abstract` is a way to state within a Cyclone file that a type's representation cannot be exported.

What are the Cyclone keywords?

  In addition to the C keywords, the following have special meaning and cannot be used as identifiers: `abstract`, `catch`, `datatype`, `fallthru`, `let`, `malloc`, `namespace`, `new`, `NULL`, `region_t`, `regions`, `rmalloc`, `rnew`, `throw`, `try`, `using`. As in gcc, `__attribute__` is reserved as well.

What are `namespace` and `using`?

  These constructs provide a convenient way to help avoid name clashes. namespace X prepends X:: to the declarations in its body (rest of file in case of namespace X;) and using X makes the identifiers prepended with X:: available without having to write the X::.

What is `fallthru`?

  In Cyclone, you cannot implicitly fall through from one switch case to the next (a common source of bugs in C). Instead, you must explicitly fall through with a `fallthru` statement. So, to port C code, place `fallthru;` at the end of each case that implicitly falls through; note that `fallthru` may not appear in the last case of a `switch`.
  `fallthru` is useful for more than just catching bugs. For instance, it can appear anywhere in a case; its meaning is to immediately goto the next case. Second, when the next case of the `switch` has pattern variables, a `fallthru` can (and must) be used to specify expressions that will be bound to those variables in the next case. Hence `fallthru` is more powerful (but more verbose) than ``or patterns'' in ML.

What is `new`?

  `new` expr allocates space in the heap region, initializes it with the result of evaluating `expr`, and returns a pointer to the space. It is roughly equivalent to

       type @temp = malloc(sizeof(type));
       *temp = expr;

  where `type` is the type of expr. You can also write

        new { for i < expr1 : expr2 }

  to heap-allocate an array of size expr1 with the `i`th element initialized to expr2 (which may mention `i`).

How do I use tuples?

  A tuple type is written `$(type``0``, ..., type``n``)`. A value of the type is constructed by `$(expr``0``, ..., expr``n``)`, where expri has type typei. If expr has type `$(type``0``, ..., type``n``)`, you can extract the component `i` using expr`[i]`. The expression in the brackets must be a compile-time constant. In short, tuples are like anonymous structs where you use expr`[i]` to extract fields instead of expr`.i`. There is no analogue of the `->` syntax that can be used with pointers of structs; if expr has type `$(type``1``, ..., type``n``) *`, you can extract component `i` by `(*expr``)[i]`.

What is `{``for i < expr``1``: expr``2``}`?

  This is an array initializer. It can appear where array initializers appear in C, and it can appear as the argument to `new`. It declares an identifier (in this case, `i`) whose scope is expr2. expr1 is an expression which is evaluated to an unsigned integer giving the desired size of the array. The expression expr2 is evaluated expr1 times, with `i` ranging over 0, 1, ..., expr1-1; the result of each evaluation initializes the `i`th element of the array.
  The form `new {``for i < expr``1``: expr``2``}` allocates space for a new array and initializes it as just described. This form is the only way to create arrays whose size depends on run-time information. When `{``for i < expr``1``: expr``2``}` is not an argument to `new`, expr1 must be constant and expr2 may not mention `i`. This restriction includes all uses at top-level (for global variables).

How do I throw and catch exceptions?

  A new exception is declared as in

        datatype exn { MyExn };

  The exception can be thrown with the statement

        throw MyExn;

  You can catch the expression with a `try`/`catch` statement:

        try  statement1 catch { case MyExn:  statement2 }

  If statement1 throws an `MyExn` and no inner `catch` handles it, control transfers to statement2.
  The `catch` body can have any number of `case` clauses. If none match, the exception is re-thrown.
  Exceptions can carry values with them. For example, here's how to declare an exception that carries an integer:

        datatype exn { MyIntExn(int) };

  Values of such exceptions must be heap-allocated. For example, you can create and throw a `MyIntExn` exception with

        throw new MyIntExn(42);

  To catch such an exception you must use an `&`-pattern:

        try  statement1
        catch {
          case &MyIntExn(x):  statement2
        }

  When the exception is caught, the integer value is bound to `x`.
  The `exn` type is just a pre-defined `@extensible datatype` type. Therefore, all the standard rules for extending, creating objects, and destructing objects of a datatype apply.

How efficient is exception handling?

  Entering a `try` block is implemented using `setjmp`. Throwing an exception is implemented with `longjmp`. Pattern-matching a `datatype` against each case variant in the catch clause is a pointer-comparsion. In short, exception handling is fairly lightweight.

What does `let` mean?

  In Cyclone, `let` is used to declare variables. For example,

        let x,y,z;

  declares the three variables `x`, `y`, and `z`. The types of the variables do not need to be filled in by the programmer, they are filled in by the compiler's type inference algorithm. The `let` declaration above is equivalent to

        _ x;
        _ y;
        _ z;

  There is a second kind of `let` declaration, with form

        let  pattern =  expr;

  It evaluates expr and matches it against pattern, initializing the pattern variables of pattern with values drawn from `expr`. For example,

        let x = 3;

  declares a new variable `x` and initializes it to 3, and

        let $(y,z) = $(3,4);

  declares new variables `y` and `z`, and initializes `y` to 3 and `z` to 4.

What is a pattern and how do I use it?

  Cyclone's patterns are a convenient way to destructure aggregate objects, such as structs and tuples. They are also the only way to destructure datatypes. Patterns are used in Cyclone's `let` declarations, `switch` statements, and `try`/`catch` statements.

What does `_` mean in a pattern?

  It is a wildcard pattern, matching any value. For example, if `f` is a function that returns a pair, then

        let $(_,y) = f(5);

  is a way to extract the second element of the pair and bind it to a new variable `y`.

What does it mean when a function has an argument with type ``a`?

  Any type that looks like ``` (backquote) followed (without whitespace) by an identifier is a type variable. If a function parameter has a type variable for its type, it means the function can be called with any pointer or with an int. However, if two parameters have the same type variable, they must be instantiated with the same type. If all occurrences of ``a` appear directly under pointers (e.g., ``a *`), then an actual parameter can have any type, but the restrictions about using the same type still apply. This is called parametric polymorphism, and it's used in Cyclone as a safe alternative to casts and `void *`.

Do functions with type variables get duplicated like C++ template functions? Is there run-time overhead for using type variables?

  No and no. Each Cyclone function gives rise to one function in the output, and types are not present at run-time. When a function is called, it does not need to know the types with which the caller is instantiating the type variables, so no instantiation actually occurs---the types are not present at run-time. We do not have to duplicate the code because we either know the size of the type or the size does not matter. This is why we don't allow type variables of memory kind as parameters---doing so would require code duplication or run-time types.

Can I use varargs?

  Yes, Cyclone has a way of supporting variable-argument functions. It is not quite the same as C's, but it is safe. For instance, we have written type-safe versions of printf and scanf all within Cyclone. See the documentation on varargs for more information.

Why can't I declare types within functions?

  We just haven't implemented this support yet. For now, you need to hoist type declarations and typedefs to the top-level.

What casts are allowed?

  Cyclone doesn't support all of the casts that C does, because incorrect casts can lead to crashes. Instead, Cyclone supports a safe subset of C's casts. Here are some examples.
  All of C's numeric casts, conversions, and promotions are unchanged.
  You can always cast between type`@``{`const-expr`}`, type`*``{`const-expr`}`, and type`?`. A cast from type`?` to one of the other types includes a run-time check that the pointer points to a sequence of at least const-expr objects. A cast to type`@``{`const-expr`}`from one of the other types includes a run-time check that the pointer is not `NULL`. No other casts between these type have run-time checks. A failed run-time check throws `Null_Exception`. A pointer into the heap can be cast to a pointer into another region. A pointer to a `struct` or `tuple` can be cast to a pointer to another `struct` or `tuple` provided the ``target type'' is narrower (it has fewer fields after ``flattening out'' nested `structs` and `tuples`) and each (flattened out) field of the target type could be the target of a cast from the corresponding field of the source type. A pointer can be cast to `int`. The type type`*``{`const-expr1`}`can be cast to type`*``{`const-expr2`}`provided const-expr2 < const-expr1, and similarly for type`@``{`const-expr1`}`and type`@``{`const-expr2`}`.
  An object of type `datatype T.A @` can be cast to `datatype T @`. The current implementation isn't quite as lenient as it should be. For example, it rejects a cast from `int *{``4}` to `$(int,int)*{``2}`, but this cast is safe.
  For all non-pointer-containing types type, you can cast from a type `?` to a `char ?`. This allows you to make frequent use of `memcpy`, `memset`, etc.

Why can't I implicitly fall-through to the next `switch` case?

  We wanted to add an explicit `fallthru` construct in conjunction with pattern matching, and we decided to enforce use of `fallthru` in all cases because this is a constant source of bugs in C code.

Do I have to initialize global variables?

  You currently must provide explicit initializers for global variables that may contain pointers, so that the compiler can be sure that uninitialized memory containing pointers is not read. In the future, we expect to provide some support for initializing globals in constructor functions.
  Two techniques help with initializing global arrays. First, if an array element could be 0 or NULL, the compiler will insert 0 for any elements you do not specify. For example, you can write

        int x[37];

  to declare a global array `x` initialized with 37 elements, all 0. Second, you can use the comprehension form

        int x[37] = { for i < expr1 : expr2 }

  provided that expr1 and expr2 and constant expressions. Currently, expr2 may not use the variable `i`, but in the future it will be able to. Note that it is not possible to have a global variable of an abstract type because it is impossible to know any constant expression of that type.

Are there threads?

  Cyclone does not yet have a threads library and some of the libraries are not re-entrant. In addition, because Cyclone uses unboxed structs of three words to represent fat pointers, and updating them is not an atomic operation, it's possible to introduce unsoundnesses by adding concurrent threads. However, in the future, we plan to provide support for threads and a static analysis for preventing these and other forms of data races.

Can I use `setjmp` and `longjmp`?

  No. However, Cyclone has exceptions, which can be used for non-local control flow. The problem with `setjmp` and `longjmp` is that safety demands we prohibit a `longjmp` to a place no longer on the stack. A future release may have more support for non-local control flow.

What types are allowed for union members?

  Currently, `union` members can be just about any type, other than those with kind (`A`) (see question on kinds, above). Examples include numeric types (including bit fields and enumerations), structs and tuples of allowable union-member types, and other unions. However, if a union contains a pointer type, you can only write the pointer, not read it. This prevents effectively casting an `int` to a pointer by writing an `int` member and then reading the pointer, for example. To use pointers as normal within a union, you must use `@tagged` unions.

Why can't I do anything with values of type `void *`?

  Because we cannot know the size of an object pointed to by a pointer of type void *, we prohibit derefencing the pointer or casting it to a different pointer type. To write code that works for all pointer types, use type variables and polymorphism. Tagged unions can also substitute in some cases where `void *` is used in C.

What is `aprintf`?

  The `aprintf` function is just like `printf`, but the output is placed in a new string allocated on the heap. Note that you can use the more general function `rprintf` to allocate the output in a region of your choosing.

How do I access command-line arguments?

  The type of `main` should be

        int main(int argc, char ?? argv);

  As in C, `argc` is the number of command-line arguments and `argv[i]` is a string with the `i`th argument. Unlike C, `argv` and each element of `argv` carry bounds information. Note that `argc` is redundant---it is always equal to `numelts(argv)`.

Why can't I pass a stack pointer to certain functions?

  If the type of a function parameter is a pointer into the heap region, it cannot be passed a stack parameter. Pointer types in typedef and struct definitions refer to the heap region unless there is an explicit region annotation.

Why do I get an incomprehensible error when I assign a local's address to a pointer variable?

  If the pointer variable has a type indicating that it points into the heap, then the assignment is illegal. Try initializing the pointer variable with the local's address, rather than delaying the assignment until later.

How much pointer arithmetic can I do?

  On fat pointers, you can add or subtract an int (including via increment/decrement), as in C. It is okay for the result to be outside the bounds of the object pointed to; it is a run-time error to dereference outside of the bounds. (The compiler inserts bounds information and a run-time check; an exception is thrown if the check fails.) You can also do pointer arithmetic on zero-terminated pointers. Currently, we do not support pointer arithmetic on the other pointer types. As in C, you can subtract two pointers of the same type; the type of the result is `unsigned int`.

What is the type of a literal string?

  The type of the string constant `"foo"` is `char @{``4}` (remember the trailing null character). However, there are implicit casts from `char @{``4}` to `char @{``2}`, `char *{``4}`, and `char ?`, so you shouldn't have to think too much about this.

Are strings NUL-terminated?

  Cyclone follows C's lead on this. String literals like `"foo"` are NUL-terminated. Many of the library functions consider a NUL character to mark the end of a string. And library functions that return strings often ensure that they are NUL terminated. However, there is no guarantee that a string is NUL terminated. For one thing, as in C, the terminating NUL may be overwritten by any character. In C this can be exploited to cause buffer overflows. To avoid this in Cyclone, strings generally have type `char ?`, that is, they carry bounds information. In Cyclone a string ends when a NUL character is found, or when the bounds are exceeded.

How do I use `malloc`?

  `malloc` is a Cyclone primitive, not a library function. Currently it has an extremely restricted syntax: You must write `malloc(sizeof(type``))`. The result has type type`@`, so usually there is no need to explicitly cast the result (but doing so is harmless). Usually the construct `new` expr is more convenient than malloc followed by initialization, but `malloc` can be useful for certain idioms and when porting C code.
  Notice that you cannot (yet) use `malloc` to allocate space for arrays (as in the common idiom, `malloc(n*sizeof(type))`. Also, the type-checker uses a conservative analysis to ensure that the fields of the allocated space are written before they are used.

Can I call free?

  Yes and no. Individual memory objects may not be freed. In future versions, we may support freeing objects for which you can prove that there are no other pointers to the object. Until then, you must rely on a garbage collector to reclaim heap objects or use regions (similar to ``arenas'' or ``zones'') for managing collections of objects.
  For porting code, we have defined a `free` function that behaves as a no-op, having type

        void free(`a::A ?);

Is there a garbage collector?

  Yes, we use the Boehm-Demers-Weiser conservative collector. If you don't want to use the garbage collector (e.g., because you know that your program does little or no heap allocation), you can use the `-nogc` flag when linking your executable. This will make the executable smaller.
  If you link against additional C code, that code must obey the usual rules for conservative garbage collection: no wild pointers and no calling `malloc` behind the collector's back. Instead, you should call `GC_malloc`. See the collector's documentation for more information.
  Note that if you allocate all objects on the stack, garbage collection will never occur. If you allocate all objects on the stack or in regions, it is very unlikely collection will occur and nothing will actually get collected.

How can I make a stack-allocated array?

  As in C, you declare a local variable with an array type. Also as in C, all uses of the variable, except as an argument to `sizeof` and `&`, are promoted to a pointer. If your declaration is

      int x[256];

  then uses of `x` have type `int @`L{``256}` where `L` is the name of the block in which `x` is declared. (Most blocks are unnamed and the compiler just makes up a name.)
  Stack-allocated arrays must be initialized when they are declared (unlike other local variables). Use an array-initializer, as in

        int y[] = { 0, 1, 2, 3 };
        int z[] = { for i < 256 : i };

  To pass (a pointer to) the array to another function, the function must have a type indicating it can accept stack pointers, as explained elsewhere.

Can I use `salloc` or `realloc`?

  Currently, we don't provide support for `salloc`. For `realloc`, we do provide support, but only on heap-allocated `char ?` buffers.

Why do I have to cast from `*` to `@` if I've already tested for `NULL`?

  Our compiler is not as smart as you are. It does not realize that you have tested for `NULL`, and it insists on a check (the cast) just to be sure. You can leave the cast implicit, but the compiler will emit a warning. We are currently working to incorporate a flow analysis to omit spurious warning. Because of aliasing, threads, and undefined evaluation order, a sound analysis is non-trivial.

Why can't a function parameter or struct field have type ``a::M`?

  Type variables of memory kind can be instantiated with types of any size. There is no straightforward way to compile a function with an argument of arbitrary size. The obvious way to write such a function is to manipulate a pointer to the arbitrary size value instead. So your parameter should have type ``a::M *` or ``a::M @`.

Can I see how Cyclone compiles the code?

  Just compile with flags `-save-c` and `-pp`. This tells the compiler to save the C code that it builds and passes to gcc, and print it out using the pretty-printer. You will have to work to make some sense out of the C code, though. It will likely contain many `extern` declarations (because the code has already gone through the preprocessor) and generated type definitions (because of tuples, tagged unions, and questionable pointers). Pattern-matching code gets translated to a mess of temporary variables and `goto` statements. Array-bounds checks and `NULL` checks can clutter array-intensive and pointer-intensive code. And all `typedef`s are expanded away before printing the output.

Can I use `gdb` on the output?

  You can run `gdb`, but debugging support is not all the way there yet. By default, source-level debugging operations within `gdb` will reference the C code generated by the Cyclone compiler, not the Cyclone source itself. In this case, you need to be aware of three things. First, you have to know how Cyclone translates top-level identifiers to C identifiers (it prepends `Cyc_` and separates namespaces by `_` instead of `::`) so you can set breakpoints at functions. Second, it can be hard to print values because many Cyclone types get translated to `void *.` Third, we do not yet have source correlation, so if you step through code, you're stepping through C code, not Cyclone code.
  To improve this situation somehwat, you can compile your files with the option `--lineno`. This will insert `#line` directives in the generated C code that refer to the original Cyclone code. This will allow you to step through the program and view the Cyclone source rather than the generated C. However, doing this has two drawbacks. First, it may occlude some operation in the generated C code that is causing your bug. Second, compilation with `--lineno` is significantly slower than without. Finally, the result is not bug-free; sometimes the debugger will fall behind the actual program point and print the wrong source lines; we hope to fix this problem soon.
  Two more hints: First, on some architectures, the first memory allocation appears to seg fault in `GC_findlimit`. This is correct and documented garbage-collector behavior (it handles the signal but `gdb` doesn't know that); simply continue execution. Second, a common use of `gdb` is to find the location of an uncaught exception. To do this, set a breakpoint at `throw` (a function in the Cyclone runtime).

Can I use `gprof` on the output?

  Yes, just use the `-pg` flag. You should also rebuild the Cyclone libraries and the garbage collector with the `-pg` flag. The results of `gprof` make sense because a Cyclone function is compiled to a C function.
  Notes for Cygwin users: First, the versions of `libgmon.a` we have downloaded from cygnus are wrong (every call gets counted as a self-call). We have modified libgmon.a to fix this bug, so download our version and put it in your cygwin/lib directory. Second, timing information should be ignored because `gprof` is only sampling 100 or 1000 times a second (because it is launching threads instead of using native Windows profiling). Neither of these problems are Cyclone-specific.

Is there an Emacs mode for Cyclone?

  Sort of. In the `doc/` directory of the distribution you will find a `font-lock.el` file and elisp code (in `cyclone_dot_emacs.el`) suitable for inclusion in your `.emacs` file. However, these files change C++ mode and use it for Cyclone rather than creating a new Cyclone mode. Of course, we intend to make our own mode rather than destroy C++-mode's ability to be good for C++. Note that we have not changed the C++ indentation rules at all; our elisp code is useful only for syntax highlighting.

Does Cyclone have something to do with runtime code generation?

  Cyclone has its roots in Popcorn, a language which was safe but not as compatible with C. An offshoot of Popcorn added safe runtime code generation, and was called Cyclone. The current Cyclone language is a merger of the two, refocused on safety and C compatibility. Currently, the language does not have support for runtime code generation.

What platforms are supported?

  You need a platform that has gcc, GNU make, ar, sed, either bash or ksh, and the ability to build the Boehm-Demers-Weiser garbage collector. Furthermore, the size of `int` and all C pointers must be the same. We actively develop Cyclone in Cygwin (a Unix emulation layer for Windows 98, NT, 2K), Linux, and Mac OS X. Versions have run on OpenBSD and FreeBSD.

Why aren't there more libraries?

  We are eager to have a wider code base, but we are compiler writers with limited resources. Let us know of useful code you write.

Why doesn't `List::imp_rev(l)` change `l` to its reverse?

  The library function `List::imp_rev` mutates its argument by reversing the `tl` fields. It returns a pointer to the new first cell (the old last cell), but `l` still points to the old first cell (the new last cell).

Can I inline functions?

  Functions can be declared inline as in ISO C99. You can get additional inlining by compiling the Cyclone output with the `-O2` flag. Whether a function is inlined or not has no effect on Cyclone type-checking.

If Cyclone is safe, why does my program crash?

  There are certain classes of errors that Cyclone does not attempt to prevent. Two examples are stack overflow and various numeric traps, such as division-by-zero. It is also possible to run out of memory. Other crashes could be due to compiler bugs or linking against buggy C code (or linking incorrectly against C code).
  Note that when using `gdb`, it may appear there is a seg fault in GC_findlimit(). This behavior is correct; simply continue execution.

What are compile-time constants?

  Cyclone's compile-time constants are `NULL`, integer and character constants, and arithmetic operations over compile-time constants. Unlike C, `sizeof(t)` is not an integral constant expression in our current implementation of Cyclone because our compiler does not know the actual size of aggregate types; we hope to repair this in a future version. Constructs requiring compile-time constants are: tuple-subscript (e.g., `x[3]` for tuple `x`), sizes in array declarations (e.g., `int y[37]`), and sizes in pointer bounds (e.g., `int * x{``124}`).

How can I get the size of an array?

  If expr is an array, then `numelts(expr)` returns the number of elements in the array. If expr is a pointer to an array, `numelts(expr)` returns the number of elements in the array pointed to. If expr is a fat pointer, then the number of elements is calculated at runtime from the bounds information contained in the fat pointer. For other types, the size is determined at compile-time.