Copper Reference Manual
This is a draft, it is not complete yet.
Instructions are separated by an end of line. The end of line is ignored when something more is expected, e.g. a line terminated with:
( , : = + - * ...
Comments starts with two slashes.
// This is a comment
An identifier is a sequence of letters, digits and underscores starting with a letter or underscore.
Identifiers are case sensitives.
A convention is to start type names with an upper case letter, other identifiers starting with a lower case letter.
A symbol is an identifier starting with a single quote.
List of reserved keywords:
and attr break case cond const do else elsif end enum extend function if import method not or ref repeat return static struct stype switch var while yield
true false nil Anything Bool Int8 Int16 Int32 Int64 Nil Size Unsigned8 Unsigned16 Unsigned32 Unsigned64
These constants are not keywords: the same name can be used for functions, methods or attributes as long as they take one or more argument.
Some types can be used in place of another type:
- A structure can inherit from another structure
- An enumeration is an integer
|Unsigned8||unsigned 8 bit integer|
|Unsigned16||unsigned 16 bit integer|
|Unsigned32||unsigned 32 bit integer|
|Unsigned64||unsigned 64 bit integer|
|Int8||signed 8 bit integer|
|Int16||signed 16 bit integer|
|Int32||signed 32 bit integer|
|Int64||signed 64 bit integer|
|Size||unsigned integer with the size of a pointer|
|Anything||special type matching all types|
|Nil||the type of the 'nil' constant|
Pointer to Type.
[n] Type  Type
n is a positive integer.  Type is an alias for  Type.
 Int32 // an array of 10 integers   Int32 // a two dimension array of integer * Char // a pointer to an array of character
& (Type1, Type2, ...) & (Type1, Type2, ...) -> (Return-Type1, Return-Type2, ...)
This type is a pointer, but the * is implicit.
& (Int32, Int32) -> (Int32) & (Int32) & -> (Int32) // A function without argument
A named type is an identifier that can be:
- a basic type
- the name of a structure
- the name of an enumeration
- the name of a sub-type
- an alias to another type (const)
- Decimals: (+|-)?[0-9]+
- Hexadecimals: (+|-)?0x[0-9a-fA-F]+
- ASCII: $c where c is any ASCII character from 33 to 126
- "aaaa" // 8 or 16 bit character string
A string can includes special escaped characters:
|\f||Form Feed (12)|
|\n||Line Feed (10)|
|\r||Cariage Return (13)|
|\v||Vertical Tab (11)|
The initializer is always evaluated depending on the expected type. If there is no expected type, the expression can be preceded with the type
The type must be a pointer either to a structure or an array. Arguments must match the type. Each argument must be a constant.
Function and Methods References
ref function-name ref function-name (list-of-types) ref (type) method-name ref (type) method-name (list-of-types)
function-name is the name of the function followed by the types of arguments between parenthesis. Do not put parenthesis if the function has no parameter.
nil is a pointer with value to 0 and its type is a special pointer type that matches with all pointer types, i.e. this value can be used anywhere a pointer value is expected.
A symbol is an identifier starting with a quote representing a constant value.
A symbol is always defined in a type and is resolved using the expected type. If no type is expected, it must be preceded by the correct one.
A tuple is a list of values separated by commas
12, 34, "hello"
It can also includes expressions returning multiples values:
If f(x) returns two values, this tuple has a cardinality of 3.
+ - * / %
== <> < > <= >=
Bitwise Logical Operators
|and||and, eval 2nd expr if and only if 1st is true|
|or||or, eval 2nd expr if and only if 1st is false|
v1, v2, ..., vn = e1, e2, ..., em
assigns each value of the tuple e1, ..., em to each left value v1, v2, ..., vn. The cardinality of the right tuple must match the number of left values.
All expressions are evaluated before assignment, so a code like this to swap two variables is perfectly valid:
x, y = y, x
Combined Assignment and Operators
value OP= exp
is equivalent to:
value = value OP exp
Shortcuts for increment and decrement:
value ++ value --
The value must be a l-value. exp is an expression evaluating to a single value.
boolean-value cond e1 else e2
If the boolean value is true, the expression is evaluated to e1, e2 otherwise. e1 and e2 must have the same cardinality and must be compatible.
Only the expression corresponding to the boolean value is evaluated.
e is an expression of type pointer
If the target type is not a simple type, the operator has no effect as the operator will return the effective address of the complex object.
- e is a pointer to an array
- n is an integer
e is an alias for e
- e can also be of another type if the operator is redefined.
- the operator can take several arguments of any type when redefined:
e[e1, e2, ...]
Function Call Operator
e call e call (e1, e2, ...)
- e is a pointer to a function
- e1, e2, ... are the arguments
e : Type
The type must be a simple type (an integer, a boolean or a pointer).
An integer cannot be directly converted to or from a pointer. It must be converted to or from a Size type first.
The type of the expression.
Function and Method Calls
Functions and methods without block:
f f (arg1) f (arg1, arg2, ...) arg1 f arg1 f (arg2, ...)
Functions and methods with block without parameters:
arg1 f (arg2, ...) do instr1 instr2 ... end
Functions with block and parameters:
arg1 f (arg1, arg2, ...) do x1, x2, ... instr1 instr2 ... end
Returns the size in bytes of the type.
Returns the target of a pointer type.
Returns the cell type of an array type.
Returns a null pointer of type *Type
Returns x unchanged but the type is the parent type of x. It applies only to pointer to structures.
if cond1 ... elsif cond2 ... elsif ... ... else ... end
- cond1, cond2 are boolean expressions.
- elsif and else statements are optionals
while cond ... end
Repeat the block as long as the boolean expression cond evaluates to true.
repeat ... end
A synonym for while true, and endless loop can that only be interrupted by a break.
switch e case c1 ... case c2 ... case ... ... else ... end
e is an integer or character expression. c1 and c2 are constant integers or characters. The else statement is optional.
The break statement can interrupt a while or repeat loop.
return return e1 return e1, e2, ..., en
Returns zero, one or more values from a function.
yield yield e1 yield e1, e2, ..., en
This statement evaluates the block passed to the function. The arguments of the yield are passed to the block as parameters. If there is more than one yield, all must have a compatible signature.
function loop(n) var i = 1 while i <= n yield i i ++ end function main loop (10) do x printf("%d\n", j) end
vargs_each do arg // Do something with arg end
Enumerates all additional arguments of a function having variadic arguments.
function f (a, b, ...) vargs_each do arg print (arg) end end
An expression such as:
f (Int32 1, Int32 2, Int16 3, String "hello", true)
will be generate an instance of f like this:
function f (a: Int32, b: Int32, arg1: Int16, arg2: String, arg3: Bool) print (arg1) print (arg2) print (arg3) end
function name (arg1: Type1, arg2: Type2, ...) ... end
The type of each argument can be omitted. In such a case the function is generic: one function will be instanciated for each different type of argument.
// Fully generic function name (arg1, arg2, ...) // Mixed function name (arg1, arg2: Type2, ...)
The return type of a function is automatically computed by the compiler.
Types of arguments cannot be structures or array, they must be pointers or basic types, i.e. values that can be stored in registers.
There is no end marker to functions, a functions ends when a new global definition starts.
Redefinition of Operators
Operators are just functions or methods with special name
struct Name [: Parent]
Creates a structure named Name.
A structure can include
- Imported methods
- Imported statics
A structure can inherit from another structure, all attributes are inherited: it is equivalent to add them at the beginning. A pointer to a structure is also considered as a pointer to its parent structure.
attr name: Type
An attribute is accessed with the same syntax as a method without parameter:
method [+] name (...) instr1 instr2 instr3 end
A method is just a function defined inside a structure. There is a first implicit parameter that is a pointer to the structure, the value of the enum or the value of the extended type. The parameter is named self.
The optional + means that self is a generic parameter: The type of self is the actual type instead of the type where the method is defined. It means that a new method is instanciated for each derived type of self.
static [+] name (...) instr1 instr2 instr3 end
A static is a method that is added to the meta-type instead of the type. The first implicit parameter is self and correspond to the type.
struct Point attr x : Integer attr y : Integer static new var pt = Point allocate pt x = 0 pt y = 0 return self end end function test var pt = Point new end
The optional + means that self is a generic parameter: The type of self is the actual type instead of the type where the method is defined. It means that a new static is instanciated for each derived type of self.
enum name [: Type] 'item1 [= value1] 'item2 [= value2] ... method name1 (...) ... end
Defines an enumeration. If Type is not provided, the enumeration is a 32 bit signed integer.
Each item can have a value assigned to it. If the value is not specified, it gets the value of its predecessor plus one or zero for the first item.
stype name : Type 'item1 [= value1] ... method name1 (...) ... end
Defines a derived type of Type. The parent must be a simple type: either a pointer, an integer or a boolean.
stype String : *Unsigned8 method isEmpty return self  = 0 end end
const name = value const name = Type
Defines an alias to a constant value or a type.
There is no expected type when evaluating the value, so it must be explicitely specified. e.g.
const screenWidth = Integer 640
To import public declarations of another module:
The name of the module is the path relative to the include path plus the filename without the extension (.co).
Circular imports is not permitted: modules cannot be inter-dependents.
To import an external function:
import function ["public-name"] name (Type1, Type2, ...) import function ["public-name"] name (Type1, Type2, ...) -> (R1, R2, ...)
To import an external method:
import method ["public-name"] name (Type1, Type2, ...) import method ["public-name"] name (Type1, Type2, ...) -> (R1, R2, ...)
To import an external static:
import static ["public-name"] name (Type1, Type2, ...) import static ["public-name"] name (Type1, Type2, ...) -> (R1, R2, ...)
It allows to add methods to any existing type.
extend Int32 method high return self >> 16 end end
var name = value var name : Type
Creates a global variable with or without an initial value. The initial value must be a constant.
var name = value var name : Type
Defines a local variable in a function or a method with or without an initial value.