Cobra Release 0.8
Cobra 0.8 adds built-in sets, extensions, bitwise operators, a configurable number type, a -turbo option and numerous refinements. There are also 30 bugfixes.
Some of the bugs fixed in this release are in support of using the GTK# and Tao.SDL libraries.
There are new How-To's that accompany this release:
The How to Write Basic Syntax now covers if statements, while loops, putting statements on the same line and line continuation. The "Translate Psuedo Code To Cobra" How-To's linked above also cover declaring methods that accept references to methods.
Additions
Built-in Sets
ISet<of T> and Set<of T> are now part of the Cobra standard library. Sets are unordered collections of arguments with fast membership testing via element in someSet or someSet.contains(element). Depending on the size of the collection, testing for membership can be hundreds of times faster with a set than with a list.
As with lists and dictionaries, there are literals for sets such as {1, 2, 3} and {,}. Sets are enumerable so they can be used with for..in loops and passed wherever an enumerable is expected. Sets and lists both have an initializer that accepts an enumerable argument, so converting between the two is easy.
The equality operators, == and <>, are available for sets which are considered equal if their contents are equal (regardless of whether their generic type argument is equal).
The empty dictionary literal is now {:} to distinguish it from an empty set. The literal {} still works for empty dictionaries, but generates a warning to use {:} or {,}.
Extension Methods
You can now add methods to existing types, even ones from DLLs that you don't have the source for. This feature is similar to Smalltalk and Objective-C categories, and C# and VB's extension methods. Unlike C# and VB, you can use this feature even in .NET 2.0.
Here is an example taken from CobraLang.cobra which now enhances lists to have a "swap" convenience method:
So now you can write someList.swap(i, j). You can also extend classes and structs such as String and DateTime.
In addition to "enhancing" library classes, another use would be to organize your code. For example, you could add UI oriented methods to domain objects, but put them in extensions in a separate file. Then if you implement another form of UI (say WUI vs. GUI), you can easily exclude the old UI methods.
Note that the compiler will only "see" extension methods that are in your current namespace or brought in via "use" directives (as in use Some.Name.Space).
As with ordinary methods, you can have test sections and contracts.
There are some limitations to extensions that will be addressed in the future:
- Cannot effectively extend primitive types such as "int" and "bool".
- Cannot extend generic types.
- Cannot overload against a method in the extended type (but you can overload within the extension you are writing).
- Cannot read extension methods found in .NET 3.5 standard libraries.
Numeric Additions
- Bitwise operatiors. The usual C-style operators for manipulating bits are now available: & | ^ << >> ~. And their augmented assignment versions: &= |= ^= <<= >>=
- Built-in unsigned int. The word uint is now a built-in type and reserved word. Like the int type, the size defaults to 32 bits, but in this case it is unsigned. As before, you can explicitly state sizes such as uint8 and int64.
- Float types. Cobra already had float, but now has float32 and float64 types as well. The float type is now defined as an alias for float64. Also, fractional literals can be suffixed with _f32 or _f64 to indicate their type. The underscores are optional and the _f suffix is still available for float. For further convenience, you can now write 50f instead of having to include the decimal portion as in 50.0f.
- Configurable number type. The previously reserved keyword number is now a primitive type which aliases to decimal by default. You can change its definition with the -number:<type> command line option. The type choices are the fractional numeric types in the language: float32, float64, float and decimal. The option sets the type for number and also for unsuffixed fractional literals such as 3.5.
This option enables you to experiment with decimal vs. float64 vs. float32 in order to see how the choice of numeric type affects performance, memory consumption and accuracy. This option is also important for keeping Cobra convenient when libraries for math, games, simulation, etc. use a non-decimal numeric type (typically float64).
- Numeric for loop. The syntax for the "numeric for loop" has been reworked to reuse concepts from other parts of the language. The old syntax will still be supported for one year, but its arcane use of .., ++ and — didn't match anything else in the language. The new syntax starts with the same form of for x in ... as an "enumerable for loop" while the rest of the statement matches slicing (list[start:stop:step]):
Unlike the old numeric for loop, the parameters to the loop are evaluated only once. In other words, the stop and the step are not re-evaluated each iteration of the loop. If you need that kind of behavior, use the general purpose while loop.
Command Line Additions
- -turbo[:no|yes] Maximum run-time performance. This is a convenience for: -contracts:none -include-asserts:no -include-tests:no -optimize
- -include-asserts[:no|yes] Determines if assert statements are included in the compiled program. The default is "yes".
- -pkg:NAME References a package via the command line tool "pkg-config —libs". This is on Mono and tested only on Unix-like systems to date. The driver for this was GTK#.
- -sharp-compiler Cobra uses the C# compiler as its backend for various benefits (compatibility, high quality byte code generation, etc.). This new option enables an explicit specification of the C# compiler to use. Hint: To see the C# compilation line Cobra issues, run cobra.exe with -v:2.
- Mono on MS Windows is now properly supported. Prior versions of Cobra may have picked up the .NET C# compiler if it was present even if running under Mono.
Minor Language and Compiler Refinements
- The for expression can now work on anything enumerable, not just lists and arrays. Another example of something enumerable is the Set type described above.
- The restriction that class level variables (also called "fields" in .NET) start with an underscore has been lifted. While declaring public properties wrapped around protected or private variables is still the de facto style in Cobra, using public variables can give a minor performance boost. Most applications won't notice the difference in speed, but for the few that do, this approach is now available.
- If a local variable name is unknown, which results in an error, give a list of similar member names that the programmer may have been trying to refer to. For example, you wrote getHashCode which yields the suggestion .getHashCode.
- An argument may be incompatible with a parameter type only because of being nilable when the parameter is expecting non-nilable. The former error message for this could be confusing and has been improved:
Argument 1 of method "bar" expects a non-nilable type (A), but the call is supplying a nilable type (B?).
- In further assistance to Python programmers, there is a new warning when def __init__ in encountered: Initializers are named "init" with no surrounding underscores.
- There is a new warning for duplicate modifiers such as a method marked shared inside a shared block. Formerly, this would cause a compilation error.
Bugfixes
- Fixed: On MS .NET, cobra.exe can throw an exception when printing help if its output is redirected.
- Fixed: Class names containing 'of' can cause false compilation errors.
- Fixed: Accessing shared members of a type with the same name as property could result in a false compilation error.
- Fixed: The declaration var _t as List<of int>= List<of int>() gives a false compliation error due to the >=.
- Fixed: Invoking a method with args that has MustUseResultAttribute, but whose result is not being used, causes an internal exception instead of a warning.
- Fixed: Putting ref in front a variable causes an internal exception instead of a normal error message.
- Fixed: Cyclical inheritance causes a stack overflow in the compiler instead of a normal error message.
- Fixed: Using descendants of a common base class in the expression if(cond, a, b) causes a false compilation error rather than inferring the common base class as the type of the if expression.
- Fixed: "cobra -exception-report -detailed-stack-trace foo.cobra" (also, "cobra -er -dst foo.cobra") gives an error if _any_ method in the program uses the "yield" statement.
- Fixed: Calling Application.init in a GTK application causes a false compilation error.
- Fixed: Using the less-than operator after a typecast causes a false compilation error.
- Fixed: Simply using a namespace with its own Object class (such as Gtk) causes false compilation error messages in unexpected places.
- Fixed: Cannot use the "enum call/combine" syntax with qualified enums such as SomeNameSpace.SomeEnum(MemberA, MemberB).
- Fixed: Using descendants of a common base class in the expression if(cond, a, b) causes a false compilation error rather than inferring the common base class as the type if the if expression.
- Fixed: Accessing a local variable, such as x, outside of a code block such as an invariant condition list or class var initialization, causes an internal error rather than a normal error message.
- Fixed: Cobra erroneously recognizes shared/static events in DLLs as being instance.
- Fixed: While Cobra offers suggestions for unknown identifiers and dotted calls that have similar member names, it does not do so for calls on identifiers.
- Fixed: Referring to read/write fields in a DLL gives a false compliation error that the field does not exist.
- Fixed: Referring to a nested class type causes false compilation errors.
- Fixed: Accessing qualified class names under some circumstances gives false compilation errors.
- Fixed: Compilation gives false errors for some method names found in DLLs.
- Fixed: The -lib option doesn't work with filenames with spaces.
- Fixed: Cannot refer to a type with the same name as its containing class without getting false compilation errorsz.
- Fixed: References to System.Configuration.* are ignored by Cobra.
- Fixed: Using the inherits operator with a generic parameter causes an internal error.
- Fixed: Integer literals like 0 and 1 cannot be assigned to valid integer types like uint16 without casting.
- Fixed: An if-statement with an expression such as .foo that has no return type produces an internal error instead of a normal error message.
- Fixed: A stray space on a blank line triggers a false error message about indentation.
- Fixed: The "cobra -test" command chokes on generic classes.
- Fixed: Cannot read non-CLS compliant DLL-based classes that have members differing only by case. Note: Cobra will read these now but only "sees" the first one it encounters. Libraries with this problem will also cause problems with Visual Basic which is fully case-insensitive.