Progress Report #11

A number of little updates have been applied to the Copper interpreter and documentation this week including better type identification and string-related methods.

Type Handling

For a long time, Copper has relied on the user implementing the virtual method typename() in order to use the type_of() and are_same_type() built-in functions for distinguishing types. A long time ago, this made sense because user types all fell under the category “UnknownData”. However, along the way, mechanisms were changed such that users are now supposed to extend the ObjectType::Value enumeration.
Rather than forcing users to continue to implement the method typename(), I decided to create a new object type: TypeValue, which is represented by the C++ class ObjectTypeObject. This object simply wraps an ObjectType::Value value. The Copper function type_of() now returns this value, and are_same_type() now compares actual ObjectType::Value values instead of the strings from typename(). However, to preserve the old feature – which can provide more information for printing – I added the Copper functions typename_of() and have_same_typename(). The former returns the string from typename() (which was the former role of type_of()) and the latter compares typename() strings (which was the former role of are_same_type()). A new function are_type() compares a given ObjectType::Value to the types of all of the given objects. Finally, the new function are_same_type_values() compares the ObjectType::Value values of ObjectTypeObject instances.
One of the benefits of switching is faster type comparison; type comparison is now a simple enumeration rather than a string.
The second benefit is that type mechanisms are now more abstract. For example, I can create an abstract function prototype and use it to validate arguments before sending them to a different function, which may have certain expectations.
Suppose we want to evade warnings of a math function (cosine) by ensuring that the type we send it is a numeric type. For this, we compare the argument type with the type of the number zero, and little time is lost doing so:

checked_cosine = [arg] {
	if ( are_same_type(arg: 0) ) {
		ret( cos(arg:) )
	} else {
		ret(1); # Assume 0 #


checked_cosine = [arg] {
	if ( are_type(type_of(0) arg:) ) {
		ret( cos(arg:) )
	} else {
		ret(1); # Assume 0 #

Note that are_same_type(a,b) is the same as are_same_type_values(type_of(a) type_of(b)) but is internally faster than coding out the latter.

Transition to supportsInterface()

On a related note, in completing the transition to have all type identification be primarily through Object::supportsInterface(), extensions have been modified to use supportsInterface() and functions like isIntegerObject() and isDecimalNumObject() have been removed. NumericObject::SubType has also been removed, and it is now expected that users implement numbers as a continuation of the ObjectType::Value enumeration.

The ObjectType::Value enumeration now has a value called “UserTypeStart” that makes it alittle more apparent what value to start with. While not especially important that this value be used, values less that this number may be used for the extensions in the ext folder (so if you use a small value less that UserTypeStart, consider changing the extension type values).

String Functions

Copper was explicitly designed without string-handling methods so as to leave representation as a byte string. Internally, the engine doesn’t care. For utility, it has been treated as a UTF8 string for Copper Bridge, but only conversion on the part of the attributes exchange mechanism was needed (and this was transparent to the user).

However, it wasn’t long before I realized that string_map wouldn’t be sufficient, so I have added three new methods: str_overwrite(), str_byte_length(), and str_byte_at(). The latter two do as you would expect: return the number of bytes and the byte at the given index, respectively. The function str_overwrite() accepts a string to overwrite, an index where to start the overwrite, and another string that is used to overwrite the first string. Notably, this function takes the role that would have been “str_replace()” but for the sake of allowing Unicode strings – and because Copper has no concept of a single “character” – an overwrite method can be used instead.

There is no str_insert() because of the complexity of this operation. Eventually, I would like to add str_substring, but this is a Unicode-dependent operation, and therefore, the ASCII or byte-based version is likely to be called str_byte_substring().


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s