Kean Walmsley

July 2009

Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

Twitter Updates

    follow me on Twitter



    « Getting the total volume of 3D solids in an AutoCAD model using F# | Main | Visual Studio 2008 & .NET Framework 3.5 released »

    November 19, 2007

    Metaprogramming with AutoCAD - Part 1

    A recent comment on one of my F# articles got me thinking about this topic (thanks, Thomas! :-), so I thought I’d write a few posts on it. Next week is AU, and the week after that I’m attending a training class in Boston, so posts may be a little sparse over the coming weeks.

    Metaprogramming  – according to the definition on Wikipedia – is the act of writing code that writes or manipulates other programs (or itself). But what is it really all about? The vast majority of programmers are actually metaprogramming without realizing it has such a fancy name.

    To help understand metaprogramming, we’re going to focus on two ways of categorizing the various types of metaprogramming activity. Metaprogramming is usually either static or dynamic and homogeneous or heterogeneous (there are other classifications, but we’re not going to worry about those in this article).

    • Static = at compile-time
    • Dynamic = at runtime
    • Homogeneous = the same output language is used as on the input
    • Heterogeneous = a different output language is used to the input language

    The most obvious form of metaprogramming is to create machine-code using a compiler (or even an interpreter) for a high-level language. This is a static, heterogeneous act of metaprogramming (although using an interpreter would presumably make this dynamic). Here are a few more interesting examples of metaprogramming I’ve used myself:

    • C++ templates or pre-processor macros to generate lower-level code at compile-time
      • Static (compile-time) and heterogeneous (the generation language is different from the output language)
    • Generation of a series of LISP expressions that are evaluated at runtime
      • Dynamic (runtime) and homogeneous (the generation and output languages are the same)
    • Programmatic creation (perhaps using LISP, C#, VB(A) or C++) of an AutoCAD script that is then executed
      • Dynamic and heterogeneous
    • Composing a SQL statement on-the-fly and using it to query a database
      • Dynamic and heterogeneous

    The focus of this series of posts is on dynamic metaprogramming, which allows the modification of code at runtime (rather than compile-time). A further, somewhat more complex, example of dynamic metaprogramming is to redefine functions at runtime (something that’s possible with LISP, for instance), which allows applications to evolve, such as when developing expert systems that “learn” over time.

    LISP was really one of the early programming environments that enabled metaprogramming, primarily through its ability to evaluate expression using (eval) and to redefine functions at runtime using (defun). This has been immensely valuable to AutoLISP programmers over the years. When AutoLISP was first introduced it was purely an interpreted language, so dynamic metaprogramming was provided pretty much automatically. In order for metaprogramming to work after the introduction of Visual LISP (which is fundamentally a compiled environment, albeit to an intermediate language), a runtime component supporting dynamic compilation was needed and provided. Very little change was needed in AutoLISP code, although in some rare cases (defun-q) now needs to be used, if it’s important to provide access to the internal representation of functions.

    We’ll see this is a common thread for dynamic metaprogramming: by definition you either need to be working in an interpreted environment or will need to have a runtime component available that supports some kind of compilation (probably JIT). Visual LISP provides this, as does VBA and .NET (via the CLR).

    Back to AutoLISP: one very common activity is to interpret a string using (read) and then call (eval) on it. The string may have been stored in a drawing, a text file, an external database, or generated on-the-fly. For example:

    Command: (eval (read "(* 5 (getvar \"ZOOMFACTOR\"))"))

    300

    VBA also has native support for dynamic metaprogramming via the Eval() function:

    Eval "MsgBox ThisDrawing.Name"

    VB6 doesn't have direct support for Eval(), but it seems you can make use of it either by embedding a Script Control or by calling across to the VBA runtime (Googling "VB6 Eval" returned a number of options). I don't know whether it's possible to evaluate and make use of AutoCAD-specific variables - such as ThisDrawing - when using these techniques, however.

    Metaprogramming with .NET is not quite so automatic, but is altogether possible, as I’ll show in my next post.

    TrackBack

    TrackBack URL for this entry:
    http://www.typepad.com/services/trackback/6a00d83452464869e200e54f9c22cc8834

    Listed below are links to weblogs that reference Metaprogramming with AutoCAD - Part 1:

    » Through the Interface: Metaprogramming with AutoCAD - Part 1 from CadKicks.com
    You've been kicked (a good thing) - Trackback from CadKicks.com [Read More]

    Comments

    OK, .. its peeked my curiosity, can't wait for part 2.

    You've been kicked (a good thing) - Trackback from CadKicks.com
    http://cadkicks.com/adkautocad/Through_the_Interface_Metaprogramming_with_AutoCAD_Part_1

    >> (eval (read "(* 5 (getvar \"ZOOMFACTOR\"))"))

    Ugh... That's a bit Walker-esqe, along the same lines as the "autoload" business.

    This would be the 'pure' homogenous form:

    (eval (list '* 5 (list 'getvar "ZOOMFACTOR")))

    Tony,

    The point of using a string is to handle the case where we store, retrieve and evaluate code. Of course you can use the quoted version - which allows some level of dynamic behaviour - but that doesn't address the storage requirement.

    Regards,

    Kean

    Hi Kean.

    Regarding "The point of using a string is to handle the case where we store, retrieve and evaluate code".

    That's a precise description of what we do every time we save lisp code in a .LSP file, that we then load and execute :)

    The point to my comment is that LISP code, in its native form, takes the form of a LISP list, rather than a series of strings.

    Hence, lisp code that dynamically generates other LISP code, does so by constructing a list via the usual means of doing that. And that list can then be passed to (eval) to be executed as code.

    In case anyone isn't aware of it, the (vl-prin1-to-string) function is a cool and easy way to convert a LISP expression (whether it be data or a list that represents LISP code) into a string which can be persisted and retrieved in that form.

    hello
    I got one for you. I am running a VBA I created and its running in LDD 06--I am just adding xrefs to my drawings with VBA through a script--but after 25 minutes into the project--it errors out saying;

    Semantic error(s) in DCL file ade.dcl.
    See file acad.dec for details

    I can't find anyone to help--any ideas.
    thanks
    Paul

    Hi Paul,

    This appears to be specific to LDT (and possibly Map 3D), as it refers to ade.dcl. I don't have any experience with these products - you should try submitting the question via the ADN website (if you're an Autodesk Developer Network member) or posting to the AutoCAD Land Desktop Customization Discussion Group.

    Regards,

    Kean

    Verify your Comment

    Previewing your Comment

    This is only a preview. Your comment has not yet been posted.

    Working...
    Your comment could not be posted. Error type:
    Your comment has been posted. Post another comment

    The letters and numbers you entered did not match the image. Please try again.

    As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

    Having trouble reading this image? View an alternate.

    Working...

    Post a comment

    Feed & Share

    Search