Cicada ---> Online Help Docs ---> Reference

Errors

When an error happens in a Cicada script, one of two things happens. If the error happened inside of a trap() function, then Cicada falls out of the trap() call, printing an error message if trap()’s arguments began with a code marker or semicolon. If there was no trap(), then the script crashes with an error message. Table 5 lists the error message by error code (the number passed to throw() and returned by trap()). The rest of this section explains each error message, in alphabetical order.


ID name ID name
0 passed (no error) 26 member is void
1 out of memory 27 cannot step to multiple members
2 out of range 28 incomplete member
3 initialization error 29 incomplete variable
4 mismatched indices 30 invalid index
5 error reading string 31 multiple indices not allowed
6 error reading number 32 invalid index
7 overflow 33 variable has no parent
8 underflow 34 not a variable
9 unknown command 35 not a function
10 unexpected token 36 not composite
11 [ token ] expected 37 string expected
12 argument expected 38 illegal target
13 left-hand argument expected 39 target was deleted
14 right-hand argument expected 40 unequal data sizes
15 no left-hand argument allowed 41 not a number
16 no right-hand argument allowed 42 overlapping alias
17 type mismatch 43 nonexistent Cicada function
18 illegal command 44 call() can’t find C function
19 code overflow 45 wrong number of arguments
20 inaccessible code 46 error in argument
21 jump to middle of command 47 self reference
22 division by zero 48 recursion depth too high
23 member not found 49 I/O error
24 variable has no member 50 [ return flag ]
25 no member leads to variable 51 [ exit signal ]

Table 5: Error messages, by error code


Argument expected (#12)

There was an empty expression where there shouldn’t be. For example, the expression 5+() causes this error because there was nothing inside the parentheses.


call() can’t find C function (#44)

A call() statement or $myCFunction() command was instructed to run a C/C++ function that does not seem to exist. call() takes either a function name or a function ID. If it is a name, a string corresponding to that name must appear in the UserFunctionSet array (in userfn.c). If it is an ID, it must be on the interval 1-N (if there are N user-defined C/C++ functions). Thus


    call(0)
   

will produce this error.


Cannot step to multiple members (#27)

Cicada tried to step into two or more members at once. This is not allowed; the user can step to multiple indices of an array, but never two members. So, for example,


    a :: [2] double
    a[<1, 2>]
   

is legal, whereas


    b :: { one :: two :: double }
    b[<1, 2>]
   

causes an error on the second line.


Code overflow (#19)

transform() was given bytecode that did not seem to end in the way it was supposed to. For example, the constant-string command gives a string length followed by the characters of the string; if the length of the string is greater than the remaining length of bytecode, this error will be thrown. All scripts must end with a 0 terminating code word.


Division by zero (#22)

This warning is caused when the user tries to divide by zero at runtime. Cicada still performs the division, resulting in either infinity or a not-a-number value. And if on some machines a divide-by-zero crashes the computer, then the computer will crash.


Error in argument (#46)

There was a problem with a parameter passed to a built-in function. This is a catch-all error for miscellaneous problems with arguments. It can be caused by: compile() if the fourth (variable-names) argument is not a string array, or transform() if the bytecode string length is not a multiple of the size of an integer.


Error reading number (#6)

The compiler tried to read a number that didn’t follow the expected format. This can be caused by the compiler or by the read_string() function.


Error reading string (#5)

A string didn’t follow the allowed format. Strings begin and end with a double-quotation-mark character: ". The string must all be written on one line; the line-continuation operator ‘&’ does not work inside strings. A line break (other than a comma) within a string causes this error, as does the presence of a null character. Certain special characters can be encoded with escape sequences: \r (carriage return), \t (tab), \n (end-of-line) and \\ (backslash). General characters can be encoded using hexadecimal codes beginning with a backslash (e.g. \3D is an equals character).


Exit signal (#51)

This error code, thrown by the exit command, is a bookkeeping device that causes Cicada to fall out of the program. It does not mean that anything went wrong in the code. If an exit command is written inside of a trap() function, the program does not quit, but instead falls out of the trap() with error code 51. Typing throw(51) is equivalent to typing exit.


I/O error (#49)

One of the following built-in functions couldn’t perform the action instructed of it: load(), save(), input() or print(). The usual cause of this is that the user tried to read a non-existent file, or read or write a file with a bad pathname or without the necessary read/write permissions. Specifically, this error is thrown if a file cannot be opened or closed, or if data could not be read or written properly to a file or the standard input or output.


Illegal command (#18)

Cicada found a nonsensical command in bytecode that it was trying to transform into memory. For example, the string-constant bytecode command has a string length word -- if the string length is less than zero then this error will be thrown. Or, Cicada may hit a command ID that simply doesn’t exist in any of its tables, which will also cause this error.


Illegal target (#38)

Cicada tried to make an alias to something other than a variable or the void.


Inaccessible code (#20)

This warning is thrown by transform(). It indicates that a null end-of-script bytecode word was encountered before the end of the bytecode was reached. The code will still run, but the spurious code-terminating marker will prevent the last part of the bytecode from being used.


Incomplete member (#28)

There are two situations that cause this error. The first is that the user tried to redefine or re-alias a part of an array --- these are operations that must be done to the entire array. For example:


    myArray :: [5] int
    myArray[3] = @nothing    | not legal
   

will cause this error. The second scenario is that we tried to step into only some indices of an array starting from a range of indices. This is due to a technical limitation -- Cicada is only able to reference contiguous blocks of memory. So once we step into more than one index of an array, each subsequent step must be into the full range of indices. So this code


    b :: [5][2] double
    print( b[<1, 3>][1] )       | causes an error
   

also causes an incomplete-member error.


Incomplete variable (#29)

Only a partial variable was used for some operation that can only be done on an entire variable: redefining or re-aliasing, or adding/removing indices. For example, for a hypothetical array a :: [3][2] int the following causes an incomplete-variable error.


    a[1][^4]
   

If we want to resize the second dimension we have to do that for the entire array: a[*][^4].


Initialization error (#3)

An uninitialized linked list was passed to a linked list routine (other than newLinkedList()). An uninitialized linked list is marked by a null pointer in its memory field. To initialize a list one must first clear the memory field, then make a successful call to newLinkedList()..


Invalid index (#30, #32)

The most common cause of this error is that the user requested an index of an array that does not exist: e.g. array[5] when it only has only four indices, or array[0] under any circumstance. Remember that hidden members do not contribute to the total index count. A second possibility is that an index range was given where the second index was (more than one) lower than the first, which is not allowed: array[<4, 2>] for example. (However array[<4, 3>] is allowed and just returns zero indices.) This error also is thrown if we resize an array to a size less than zero, or try to add a huge number of indices (more than INT_MAX).

The fact that this error has two error codes is irrelevant to the user, having only to do with the way Cicada keeps its books.


Jump to middle of command (#21)

transform() found a goto statement pointing somewhere other than the beginning of a bytecode command. The specific bytecode commands that can cause this error are: jump-always, jump-if-true and jump-if-false.


Left-hand argument expected (#13)

An operator is missing its left-hand argument. For example,


    a = + 3
   

will cause this error because the + operator expects a number to the left, after the equals sign.


Member is void (#26)

Cicada attempted to step into a void member (one that has no target). Here is the most common sort of situation that will cause a void-member error:


    x :: *
    x = 2
   

Many built-in functions throw this error if any of their parameters are void.

A void-member error can also happen when we try to use an ‘unjammed’ member: a member defined as unjammable whose target variable was later resized. This typically only happens to members of sets. For example, this code will unjam the only member of set and cause a void-member error:


    array :: [5] int
    set :: { array[<1, 5>] }
   
    remove array[3]      | unjams the alias in our set
    set[1][1] = 2        | the second '[1]' causes the error 
   

Had we defined the member of set explicitly:


    set :: { alias := @array[<1, 5>] }
   

we would have gotten an overlapping-alias error when we tried deleting the array element.


Member not found (#23)

The user gave a member name that Cicada could not find. If the missing member is at the beginning of the path, for example if it flags member list in


    print(list[5])
   

then Cicada is telling us that that member (list) was not to be found anywhere along the search path: the current function or any enclosing object up through the workspace. If the problematic member was some intermediate point in the path, for example if list is flagged in


    data[5].list = anotherList
   

then the missing member (list) was not immediately inside the given path (data[5]).

If possible, Cicada gives the member name in single quotes along with the error message, as in: “member ’header’ not found”.


Mismatched indices (#4)

Usually, this error means that the user either tried to copy or compare data between arrays of different sizes, or else alias one array to another of a different size. For example, the following will cause this error regardless of how ‘a’ and ‘b’ were defined.


    a[<1, 3>] = b[<1, 2>]
   

Notice that this can happen when working inside of an array; for example:


    q :: int
    threeQs :: [3] { qAlias := @q }
   

which is basically equivalent to threeQs[*].qAlias := @q.

Note that arrays of different dimensions can be copied/compared if their indices are specified manually and the total number of indices is the same (and each is a contiguous block of memory -- see the section on arrays). So, for example, the following is legal:


    q :: [4] int
    r :: [2][2] int
    q[*] = @r[*][*]
   

If the last index of the array on the left-hand side of a compare or equate is a ‘[*]’ or ‘[]’, then Cicada will automatically resize it if that will prevent a mismatched-indices error. Sometimes this does not work; for example, in the case below:


    a :: [2][3] string
    b :: [5] string
    a[*][*] = b[*]
   

we will get a mismatched-indices error because only the last index of ‘a’ can be resized, which is incompatible with ‘b’ having an odd number of indices. We would also get this error if the first dimension of ‘a’ was sized to zero, even if ‘b’ was also of zero size.

A mismatched-indices error can also be thrown by the linked list routines (used for working with Cicada strings in C). The only scenario where this would happen is when the two linked lists have different element sizes. Strings always have an element size of 1 (the byte size of a character), so this should never happen unless the linked list routines are being used for something else.


Multiple indices not allowed (#31)

Several instances of a variable were given where only one was expected. Whenever Cicada expects either a number or a string, that quantity has to be a constant, a single variable or a single element of an array. For example, the following causes this error.


    if 4 < a[<1, 2>] then print("dunno how this worked")
   

Likewise, the following expression is also (at present) disallowed for the same reason.


    a :: [2] { b :: int, if 4 < b then ... }
   

Many built-in Cicada functions will throw a multiple-indices error when passed an array parameter when only a single number or string was expected.


No left-hand argument allowed (#15)

An operator had a left-hand argument that it was not allowed to have. For example, the following line


    10 return
   

will cause this error because it interprets the return statement as having a left-hand argument 10. return is only supposed to have an argument on the right.


No member leads to variable (#25)

Cicada attempted an operation that involving a member, not just a variable, and it didn’t have one. For example, the define operator specializes the member type as well as the variable type. The following code


    f :: { code, return 5 }
    f() :: double
   

will generate this error since the return command returns only a variable, not the member of the function that points to it.

In addition to the define operator, both equate and forced-equate require a member in order to resize an array either using [^...], or via a [*] or [] operator. (That is because both the variable and the member have to be resized.) Finally, the insertion and removal operators operate on members and therefore will generate this error if none is provided.


No right-hand argument allowed (#16)

An operator had an argument to its right that it was not allowed to have. Depending on precedence, this problem can also cause a no-left-argument-allowed error.


Nonexistent Cicada function (#43)

The user invoked a built-in Cicada function with a function ID that does not exist. Cicada functions are those functions like call() and trap(), and these are distinguished in bytecode by a function ID immediately following built-in-function command. This number must fall in the range 0-29 because there are 30 built-in functions; any other number generates this error. This error should only happen if the user modified the language, or else wrote or modified bytecode by hand.


Not a function (#35)

The user tried to do something involving code with an object that doesn’t have code. For example:


    transform(compile(""), 2)
   

causes this error because transform() cannot put the transformed code into the primitive variable storing ‘2’. This error message is technically redundant with the ‘not-composite’ error message, because every composite object (i.e. defined using curly braces) is a function and vice versa.


Not a number (#41)

Cicada was given a non-numeric expression where it expected a number. For example:


    b := "7"
    2 + b
   

generates this error. In different contexts one can also get compile-time or other runtime errors; the phrase “2 + "7" generates “type mismatch”.


Not a variable (#34)

We tried to do some variable operation on a non-variable. For example, the define operator operates on both a member and a variable, so trying


    nothing :: string
   

will cause this error. Likewise, both equate and forced equate require an existing variable to copy data into. Likewise, the comparison operator ‘==’ requires two arguments that are either constants or variables. Code substitution and alias-comparisons both involve variables and can cause this error.


Not composite (#36)

Cicada expected a composite variable (i.e. one defined using curly braces), but was given a primitive variable instead. All of the ‘step’ operators -- ‘.’, ‘[]’, ‘[^]’, ‘[+]’, etc. -- must start from some composite variable. For example, the following generates a not-composite error:


    a :: double
    print(a.b)
   

This error can also be thrown by a number of built-in Cicada functions such as top() and transform(), which expect certain arguments to be composite.


Out of memory (#1)

Cicada was not able to allocate memory while it was running a script. Any memory error will cause this message: for example, if the computer is out of memory, or if the memory manager for some other reason refuses to allocate a block of the requested size. Cicada is not particularly well-designed to recover from run-time memory errors -- or at the very least, it has not been well-tested in this regard -- so it is recommended that the program be restarted if this error occurs.

The usual cause of a memory error is frequent creation and removal of variables within a loop. Due to Cicada’s incomplete garbage collection the deleted variables often do not get erased from memory until the loop is finished and the command prompt is brought up again. Calling springCleaning() periodically within the loop will force complete garbage collection.


Out of range (#2)

A number was used that was not within expected bounds. This error is often thrown as a warning. One common cause of this is that the user assigned a value too large or too negative for a given type, for example


    (a::char) = 400
   

This warning is not caused by rounding-off errors: for example, we can assign the value 1.9 to an integer variable, and Cicada will quietly round it off to 1 without raising any warning flag.

transform() can throw at out-of-range error (an actual error, not a warning) if some element of the character-positions list (optional 6th argument) is not within [1, num_chars]. It can also be caused by certain defective numbers passed to setCompiler(): a negative number of commands or precedence levels (2nd/4th arguments); a precedence level outside of bounds; an operator direction other than l_to_r or r_to_l; or an argument number or jump-to number in the bytecode (e.g. ‘a5’ or ‘j4’) beyond the number of arguments/jump positions (or outside the range 1-9). Finally, this error can be thrown by the linked list routines if a nonexistent/nonsensical element number of a list is passed (although InsertElements() allows the insertion point to be one greater than the top element). Remember that linked list indices begin at 1, not 0.


Overflow (#7)

The compiler tried to read a numeric constant that was larger than the maximum that will fit in a double-precision variable. For negative numbers this means that the number was less than the most negative allowed number. For example, writing the number 5e999 causes this error.


Overlapping alias (#42)

The user tried to do resize an array some of whose elements are also aliased elsewhere. For example:


    a :: [5] int
    b := @a[<2, 4>]
   
    a[+3]
   

Resizing one member (‘a’) does not affect any aliases (‘b’), so there would be a contradiction in the array if the resize were allowed. Notice that an alias to the array variable (as opposed to certain indices of the integer variable), as in


    c := @a
   

does not have this problem.


Recursion depth too high (#48)

Too many nested functions are being run. In order to avoid blowing the program stack, Cicada sets a limit to the number of nested functions that can be run inside one another. This limit is set in the glMaxRecursions variable at the top of bytecd.c -- Cicada comes with it set to 100. So if we have f1 call f2 which then calls f3, then there is no problem because the total depth is only 4 (the three functions plus the calling script). On the other hand, if we try


    f :: { f2 :: this }
   

then we will immediately get this error because defining ‘f’ requires an infinite level of recursion. (f creates f2 which creates its own f2, etc.)


Return flag (#50)

This error code is used internally to cause Cicada to fall out of a function when it hits a return statement. Since returning from functions is a perfectly legitimate thing to do, the error code is always set to 0 (no error) after the function has been escaped. Writing throw(50) in a script is the same as writing return.


Right-hand argument expected (#14)

An operator requiring a right-hand argument does not have one. For example,


    a = 5 +
   

causes an error because the + operator requires a number or expression to the left and the right.


Self reference (#47)

A variable with an alias to itself was given to an operation in which self-aliases are not allowed. It is fine for a variable to have aliases to itself, but we cannot sensibly, say, copy data to that variable since it has an infinite depth. For example, if we define:


    me :: { self := @this }
   

then me contains me.self, which contains me.self.self, etc. Therefore if we try to use this variable, or any enclosing variable, in an equate, comparison, forced equate, or the built-in functions print_string(), read_string, size(), load() or save(), we will get this error.


String expected (#37)

A built-in Cicada function requiring a string argument was passed something that was manifestly not a string. For example, call() expects either a string or a number as its first argument to specify the function to run, so writing


    call(true)
   

will generate this error.


Target was deleted (#39)

A member was removed while it was being aliased. One has to try hard to get this error.


[ Token ] expected (#11)

A multi-token command (like ‘while’ followed by ‘do’) was missing one of its parts. So a typical error message would be


    > while true
   
    Error: 'do' expected
   

Notice that the error message contains the name of the token that is missing.


Type mismatch (#17)

A member or variable does not have the expected type. This error can occur either when data is being copied or compared, when a variable or member is having its type altered (e.g. via the define operator), or when a built-in function is run with the wrong argument types.

When two variables are copied or compared, Cicada requires that they have identical structures with the proviso that numeric types are interchangeable. So if (any part of) the first variable is composite, the (corresponding part of) the second variable must also be composite, have the same number of (non-hidden) members, and each array member must have the same number of indices. Here are some commands that don’t work:


    { string, int } = { int, string }
    { [5] int } = { [4] int }
    string = char
   

and nor does substituting specific int-, char- and string-typed variables work. Numeric members in one variable must correspond to numeric variables in the other, strings with strings, Booleans with Booleans.

Cicada is also fastidious about redefining members and variables: it doesn’t care about the structure of the variables, but it does require that their old types exactly match or be compatible with the new types. A type can only change by being updated, using the inheritance operator. Redefining a variable as a different numeric type, as in


    myNum :: int
    myNum :: double
   

will cause this error, even though copying/comparing different numeric types (e.g. { int } = { double }) is legal.

One composite type can be changed (specialized) into another only if all of the existing N codes are also the first N codes in the new type, in the same order. Thus if we define var1 to be of type a:b, then we can specialize it into a:b:c but not c:a:b or b:a:c.


Underflow (#8)

A number was encountered which was so small that it was read as zero. 1e-400 will do the trick on most machines.


Unequal data sizes (#40)

Cicada was not able to perform a forced equate because the byte-sizes of the left- and right-hand arguments were different. For example, the following fails:


    (a :: double) =! (b :: int)
   

even though a normal equate would have worked in this situation.

Before throwing this error, the forced-equate operator explores two options for making the data fit. 1) If the final step into the left-hand variable involved a [*] operator it tries to resize that last member. 2) If the left-hand variable contains a string, that string can soak up excess bytes from the right-hand argument. If after (1) and (2) the data on the right still cannot fit into the variable on the left, then this error is thrown. If both (1) and (2) apply, Cicada may not able to figure out how to resize the array correctly in which case the user must resize the array manually.


Unexpected token (#10)

The compiler encountered a token that usually follows another token, but didn’t. For example, writing a do without a while will cause this error.


Unknown command (#9)

The compiler encountered some mysterious symbol which it cannot recognize as an operator. For example, the following will cause this error


    a = %
   

because a percent sign has no use in Cicada.


Variable has no member (#24)

A step was attempted into a variable without a member. For example {}[*] will cause this error. This error is also thrown if we use the top keyword (which is different from the top() function!) anywhere outside of array brackets.


Variable has no parent (#33)

A pathname tried to step to parent or \ when it was already at the beginning of the search path. Just typing parent at the command prompt will cause this error.


Wrong number of arguments (#45)

A built-in Cicada function was called with the wrong number of arguments. For example, the following expression will cause this error


    top(a, b)
   

because top() accepts only a single argument.


Prev: Linked list routines for handling Cicada strings in C   


Last update: May 8, 2024