I switched the ZUZU project to use Mercurial as its source repository in place of Subversion. This will allow me the ability to have fast access to the entire repository on my laptop and to manage individual commits when then network is unavailable (such as when I am on vacation later this summer).
The Subversion repository still exists on googlecode, but I do not plan to do any further checkins to Subversion.
I am using TortoiseHg on my Vista machine and have also installed the Mercurial Eclipse plugin as well. [Update 2010-02-07: I have since switched to the HgEclipse plugin, a fork of the earlier project which appears to be better maintained and more mature than the other.]
I also recommend "Mercurial: The Definitive Guide", which just came out this week. It is also available online.
2009-07-03
2009-06-27
Configuring debuggability in Curl
Debuggability is an attribute of Curl processes that controls how the code is compiled and whether debugger features are enabled for the applet. Debuggability controls the following features/attributes:
The principle disadvantage to making your applets debuggable is that the combination of disabled optimizations and insertion of extra noop instructions to support debugging will result in slower code, and in some cases debuggable applets may be dramatically slower. In these cases, the developer may want to be applet to run the same applet debuggable when using debugger or coverage features, but otherwise use a non-debuggable version.
At least up through version 7.0 of the RTE, debuggability of Curl applets in is controlled solely by the list of directories listed in the Debugger pane of the Curl RTE Control Panel. When the RTE starts a new applet, it consults this list to see if the applet should be made debuggable. If the applet's starting URL is in the specified directory, it will be made debuggable.
So for developers to run the same applet with different debuggability settings, they must either add and remove entries to the debuggability settings in the Control Panel every time they want to run the applet differently or they find a way to run the same applet from different paths. The latter is obviously preferrable. On linux (and Mac OSX) this can easily be accomplished by creating symbolic links using the 'ln' command. For instance, on the linux machines I use at work, I have started putting all of my Curl projects in a subdirectory named 'ws' (short for workspace), and have made a symbolic link named 'non-debug-ws' to the 'ws' directory, so that I can configure my debuggability settings to use paths beginning with "file:///u/cbarber/ws/" to load applets from the source with debuggability enabled, and those beginning with "file:///u/cbarber/non-debug-ws/" to run non-debuggable versions.
On Windows, however, this is not so easy, since there is no equivalent command in Windows nor is there any way to accomplish the same thing in the Explorer UI. It turns out that it is indeed possible to create the equivalent of a unix symbol link on Windows NTFS file systems -- the default file system used by Windows NT and later -- a NTFS "junction point", but this ability is only available in low-level system programming APIs. Fortunately, there are a number of open source solutions that give you the ability to create them. The one that I favor is an open-source shell extension called NTFS Link, which adds entries for creating NTFS hardlinks and junction points to the Windows Explorer's "New" submenu. The one gotcha is that you must be careful not to delete junction points in the explorer until you have unlinked it from its target directory, or else you will end up deleting the target directory contents as well!
P.S. In case it is not already obvious, that the debuggable path is the same as the path you use in your development environment. The non-debug path does not have to be reflected in your development environment since it is not expected to cause breakpoints to be triggered, and so on.
- The ability to set breakpoints, and step through code in the IDE debugger.
- The ability to measure code coverage of running code.
- Syntax errors are reported in the Curl IDE in debuggable applets, where the developer may easily click on the error and navigate to the offending code. In non-debuggable applets they are only reported in the applet's main window.
- Lazy compilation is disabled in debuggable applets. In non-debuggable applets, functions are not compiled (and errors not detected) until they are first used, which may not happen until well after the application has been started.
- Compiler optimizations like function inlining and register allocation are disabled in debuggable applets.
- The Curl performance profiler can report information about source lines in debuggable applets; otherwise only function-level information is available. However, because optimizations are disabled, profiling debuggable applets may produce significantly different results than non-debuggable ones.
The principle disadvantage to making your applets debuggable is that the combination of disabled optimizations and insertion of extra noop instructions to support debugging will result in slower code, and in some cases debuggable applets may be dramatically slower. In these cases, the developer may want to be applet to run the same applet debuggable when using debugger or coverage features, but otherwise use a non-debuggable version.
At least up through version 7.0 of the RTE, debuggability of Curl applets in is controlled solely by the list of directories listed in the Debugger pane of the Curl RTE Control Panel. When the RTE starts a new applet, it consults this list to see if the applet should be made debuggable. If the applet's starting URL is in the specified directory, it will be made debuggable.
So for developers to run the same applet with different debuggability settings, they must either add and remove entries to the debuggability settings in the Control Panel every time they want to run the applet differently or they find a way to run the same applet from different paths. The latter is obviously preferrable. On linux (and Mac OSX) this can easily be accomplished by creating symbolic links using the 'ln' command. For instance, on the linux machines I use at work, I have started putting all of my Curl projects in a subdirectory named 'ws' (short for workspace), and have made a symbolic link named 'non-debug-ws' to the 'ws' directory, so that I can configure my debuggability settings to use paths beginning with "file:///u/cbarber/ws/" to load applets from the source with debuggability enabled, and those beginning with "file:///u/cbarber/non-debug-ws/" to run non-debuggable versions.
On Windows, however, this is not so easy, since there is no equivalent command in Windows nor is there any way to accomplish the same thing in the Explorer UI. It turns out that it is indeed possible to create the equivalent of a unix symbol link on Windows NTFS file systems -- the default file system used by Windows NT and later -- a NTFS "junction point", but this ability is only available in low-level system programming APIs. Fortunately, there are a number of open source solutions that give you the ability to create them. The one that I favor is an open-source shell extension called NTFS Link, which adds entries for creating NTFS hardlinks and junction points to the Windows Explorer's "New" submenu. The one gotcha is that you must be careful not to delete junction points in the explorer until you have unlinked it from its target directory, or else you will end up deleting the target directory contents as well!
P.S. In case it is not already obvious, that the debuggable path is the same as the path you use in your development environment. The non-debug path does not have to be reflected in your development environment since it is not expected to cause breakpoints to be triggered, and so on.
2009-03-28
Poor man's union types
The original design of the Curl language anticipated support of user defined "union types", that is, the ability to define an abstract data type representing values that may belong to two or more unrelated types. (For an example from another dynamic language, see Dylan's type-union syntax.)
The proposed syntax was:
In early versions of the language, one-of was defined as a macro that simply resolved to 'any', which is the supertype of all scalar types in Curl, with the intention of implementing a correct version at a later time. Of course, such an implementation does not do the desired compile-time checking and served only as an indication of the programmers intent. However, when we started looking into implementing this concept for real, it quickly became evident that the amount of effort required to implement it was not justified by the relative infrequency of its anticipated use, so we dropped it from our development schedules and removed the syntactic placeholder.
Nevertheless, there are times when such a type would come in handy. One example can be found in Curl's built-in 'evaluate' function, whose first argument is declared as 'any', but which actually accepts one of 'CurlSource', 'StringInterface', or 'Url'. Because the argument is declared as taking 'any', you can write code that passes an unsupported type and the compiler will not generate an error; an error will not be thrown until the function is actually executed with a bad value. If the function could have been declared as taking a union type, the compiler would be able to detect such errors at compile time.
Fortunately, it turns out that it is possible to define a class type that while not implementing the full semantics of a union type, still provides us with the most important feature you want from a union type: i.e., the type checking of assignments. The trick is to define a class with a 'any' field to hold the value, and an implicit constructor for each type in the union:
Each implicit constructor supports implicit conversion from the argument type when assigning to a variable or argument of the class type, and since the field is constant and can only be initialized by one of the constructors, you can safely assume that the value is a member of one of the specified types (or null 'uninitialized-value-for-type' would return null for one of the types).
It would be tedious to have to define such a class every time you needed to use this pattern, but it is straightforward to define a parameterized versions of this class for different numbers of arguments, and a macro that picks the correct parameterized class based on the number of arguments, and this is exactly what I did last week. I added a new ZUZU.LIB.TYPES package to the ZUZU.LIB project, which contain the macros 'One-of' and 'AnyOne-of' along with associated parameterized value classes. The 'One-of' type represents the value using a field of type '#Object' and can only be used when all of the types in the unions are subtypes of 'Object'; 'AnyOne-of' uses an 'any' field and can be used with any types. Here is a small example:
The proposed syntax was:
{one-of T1, T2 [,...]}
In early versions of the language, one-of was defined as a macro that simply resolved to 'any', which is the supertype of all scalar types in Curl, with the intention of implementing a correct version at a later time. Of course, such an implementation does not do the desired compile-time checking and served only as an indication of the programmers intent. However, when we started looking into implementing this concept for real, it quickly became evident that the amount of effort required to implement it was not justified by the relative infrequency of its anticipated use, so we dropped it from our development schedules and removed the syntactic placeholder.
Nevertheless, there are times when such a type would come in handy. One example can be found in Curl's built-in 'evaluate' function, whose first argument is declared as 'any', but which actually accepts one of 'CurlSource', 'StringInterface', or 'Url'. Because the argument is declared as taking 'any', you can write code that passes an unsupported type and the compiler will not generate an error; an error will not be thrown until the function is actually executed with a bad value. If the function could have been declared as taking a union type, the compiler would be able to detect such errors at compile time.
Fortunately, it turns out that it is possible to define a class type that while not implementing the full semantics of a union type, still provides us with the most important feature you want from a union type: i.e., the type checking of assignments. The trick is to define a class with a 'any' field to hold the value, and an implicit constructor for each type in the union:
{define-class public IntOrString
field public constant value:any
{constructor public implicit {from-int i:int}
set self.value = i
}
{constructor public implicit {from-String s:String}
set self.value = s
}
}
Each implicit constructor supports implicit conversion from the argument type when assigning to a variable or argument of the class type, and since the field is constant and can only be initialized by one of the constructors, you can safely assume that the value is a member of one of the specified types (or null 'uninitialized-value-for-type' would return null for one of the types).
It would be tedious to have to define such a class every time you needed to use this pattern, but it is straightforward to define a parameterized versions of this class for different numbers of arguments, and a macro that picks the correct parameterized class based on the number of arguments, and this is exactly what I did last week. I added a new ZUZU.LIB.TYPES package to the ZUZU.LIB project, which contain the macros 'One-of' and 'AnyOne-of' along with associated parameterized value classes. The 'One-of' type represents the value using a field of type '#Object' and can only be used when all of the types in the unions are subtypes of 'Object'; 'AnyOne-of' uses an 'any' field and can be used with any types. Here is a small example:
Subscribe to:
Posts (Atom)