Coffeescript and C Macros: Clean and Fast

Anyone who programs in C uses pre-processor macros to keep the code clean, maintainable and sometimes to improve run-time performance. You can use the same C pre-processor to include macros in Coffeescript or Javascript code, and it is easy!

The coffeescript file needs to be renamed with .c extension before running it thrrough gcc; otherwise, it gives a warning and doesn’t run the pre-processor. There may be some option to force it compile without checking the extension.

cp [source.coffe] [source.c]
gcc -E [source.c] > [processed.coffee]

Examples #

Improve performance #

This is the code with macros. It compares the time taken to calculate the sum of squares, using functions and macros.

square = (x) -> x * x

#define SQUARE(x) (x * x)

total = 0
console.time "no macro"
for i in [0...100000]
 total += square i
console.timeEnd "no macro"
console.log "Total #{total}"

total = 0

console.time "macro"
for i in [0...100000]
 total += SQUARE(i)

console.timeEnd "macro"
console.log "Total #{total}"

Compiled code:

# 1 "macro.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "macro.c"
square = (x) -> x * x



total = 0
console.time "no macro"
for i in [0...100000]
 total += square i
console.timeEnd "no macro"
console.log "Total #{total}"

total = 0

console.time "macro"
for i in [0...100000]
 total += (i * i)

console.timeEnd "macro"
console.log "Total #{total}"

Output:

no macro: 2ms
Total 333328333350000
macro: 1ms
Total 333328333350000

Debugging #

You can use you favorite DEBUG macro to define LOGS, and even __LINE__ and __FILE__

#define DEBUG

#ifdef DEBUG
#define LOG(x) console.log __LINE__ + ": " + (x)
#else
#define LOG(x)
#endif

n = 3
LOG("Root of #{n} = #{Math.sqrt(n)}")

There is a slight problem because # is used for comments in Coffeescript. All you need to do is to use ## instead of a single # when you want to add a comment.

#define DEBUG

##This is a comment

#ifdef DEBUG
## Define LOG macro
## Print line number
#define LOG(x) console.log __LINE__ + ": " + (x)
#else
#define LOG(x)
#endif

n = 3
LOG("Root of #{n} = #{Math.sqrt(n)}")
 
29
Kudos
 
29
Kudos

Now read this

Passing File Descriptors Between Processes Using Sendmsg() and Recvmsg()

Using this technique you can pass file descriptors between processes using sendmsg() and recvmsg() functions using UNIX Domain Protocol. Any descriptor can be passed using this method not just a file descriptor. This is quite useful when... Continue →