Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Coffeescript Static Analysis / Static Typechecking - Roadblocks

I think Coffeescript is an awesome language! I was looking for some projects / issues / features that add Static Analysis to Coffeescript. However after some searching I found that the Coffeescript faq and this page suggest that static analysis might not be viable.

I was wondering that if there is a fundamental issue in implementing static analysis / static type checking in Coffeescript, because of which something of this sort does not already exist in the compiler?

Also, is it something that is not possible to do for non trivial checks but might work only for straightforward analysis? When I say straightforward I mean checking for trivial stuff like, whether the user has defined a function twice by the same name (in a class) or on the top level (or perhaps on the top level in a collection of related .coffee files).

I would appreciate if anyone could please point out some examples that show why implementing static analysis / type checking is not straightforward / possible / worth spending time on?

Thank you very much!

like image 878
AAK Avatar asked Jun 03 '12 23:06

AAK


People also ask

Is CoffeeScript a programming language?

CoffeeScript is a programming language that compiles to JavaScript. It adds syntactic sugar inspired by Ruby, Python, and Haskell in an effort to enhance JavaScript's brevity and readability.

Does CoffeeScript compile to JavaScript?

CoffeeScript. CoffeeScript is a little language that compiles into JavaScript.

Why was CoffeeScript created?

Basically, CoffeeScript was made by people who hate JavaScript syntax, intended to be used by other people who hate JavaScript syntax. It's compatible with all flavors of JavaScript, and adds in “syntactic sugar” from other programming languages in the same way you sweeten up your morning cup of Joe – hence the name.


2 Answers

This answer is a bit of a brain dump since I'm interested in this also. Hope it helps.

I use the Google Closure Compiler to statically analyze the code that CoffeeScript generates. It has a really good static analyzer, and I'm not sure if there's a good reason to reinvent the wheel here. The easy way is to just write the annotations by hand:

###*
   * @param {number} x
   * @param {number} y
   * @return {number}
###
adder = (x, y) -> x + y

It's a bit verbose, but on the other hand you're borrowing the static analysis abilities of the closure compiler which is really powerful and is able to check a lot. I actually write type annotations in a slightly more concise way, then have a script to rewrite the coffee file. My code ends up looking like this:

#! {number} x {number} y @return {number}
adder = (x, y) -> x + y

I'm sure you can see that the rewriter is pretty straightforward.

A quick note before I move on. Be sure to compile your code with -b (bare) if you're running it through the closure compiler. The closure compiler is pretty good, but it's not smart enough to do data flow analysis. CoffeeScript wraps your code in an anonymous function by default, which will trip up the compiler.

Another option along the same path (this would break compatibility with CoffeeScript, but would be a lot cooler) would be to have the Coffee compiler compile something like this:

adder = (number x, number y): number -> x + y

into JS like this:

/***
  * @param {number} x
  * @param {number} y
  * @return {number
  */
var adder = function(x, y) {
  return x + y;
};

which could then be fed into the closure compiler on a compile - if there were no errors the compiler could then strip all the comments out.

Indeed, this guy appeared to be doing exactly this. Sadly, his work seems to be in an incomplete state.

In all of these cases, we defer the hard work - static typechecking - to the closure compiler. If you don't want to do this, I'd understand, but it'd be tough to convince me that it's worthwhile to build a whole new static analysis tool from scratch. :)

EDIT a year later: I just use typescript these days. :)

like image 121
thedayturns Avatar answered Sep 30 '22 07:09

thedayturns


I'm not an expert in CoffeeScript, so this might be the completely wrong answer, but it basically boils down to this: CoffeeScript is a very expressive language, with most of the semantics dynamically determined (and possibly strange edge cases). This is in much contrast to languages like Standard ML, which have a much more strictly defined semantics. In general, doing static analysis on higher order languages is considered very hard. I.e., static analysis on real higher order programs (Haskell, ML, especially javascript because of things like eval) is just hard because the flow of control is much more flexible. In fact, the static analysis solutions for higher order languages have really only been explored within the past twenty years or so. (Notably, see Matt Might's article on a tutorial style description of CFA.)

Basically, the reasons are this:

  • To do analysis, you have to deal with the problem of the expressive semantics coming form the flow control you get by slamming around higher order functions.
  • To do typing, typically these languages have a much richer set of types that are available. For example, there are very typically situations where if you try to assign a static type to a variable in Ruby (as in C, Java, ML, etc...) you get an error, but because certain paths of your program are never executed, it's all fine. Along with that, languages like Ruby others add a plethora of implicit type conversions that are really used to do cool programming. The notable work in this area with which I'm familar (dynamic analysis of static types for Ruby) comes from some of the people I work with, but there are certainly other examples.
  • Basically, the language is used in a much more dynamic way, with a much more expressive semantics, and reasoning about that statically is much harder, and prone to be imprecise. The basic front of approaching this (these days) is starting to look hybrid: you can statically analyze part of a program, and than also require the programmer give some test cases to do some kind of refined analysis.

I hope this somewhat answers your questions, again, sorry I can't address directly the direct concerns of your question as it applies to CoffeeScript, but there's a lot of work going on in analyzing things like JavaScript right now. I'll note that some of the real problems with Javascript come from it's strange semantics, the prototypical inheritance is hard to reason about, and especially eval()! Typically program analyses for these languages impose certain restrictions (for example, throwing out eval completely!) to make the analysis more feasible!

like image 31
Kristopher Micinski Avatar answered Sep 30 '22 09:09

Kristopher Micinski