1.6 KiB
Introduction
Write a static analyzer for ruby.
Used an existing parser for ruby called `ruby-parse`.
`ruby-parse` can generate an AST in JSON format.
This made the task of writing a ruby parser simpler: Haskell comes with a great JSON parser. So we just have to specify how to convert from the AST defined by `ruby-parse` to our own AST.
Implementation
ADTs
Purpose
Defining an Abstract Syntax Tree (AST) for Ruby using Algebraic Data Types (ADTs).
Example
– Value represents any JSON data (object, string, number, null, array) Args = Value Name = Value Block = [Definition] Definition = Module | Function | Send Namespace = [Name] Send = {args : Args, namespace : Namespace, name :: Name} Module = {name : Name, block : Block} Function = {name : Name, args : Args, block :: Block}
Live coding
Define `Function`
Higher-order types
Missing a good example here.
Type classes
Purpose
Be able to concert unstructured JSON data into our ADT.
Example
Consider the class
class FromJSON a where parseJSON :: Value -> Parser a
It's saying that `a` is convertible from json if there is a function `parseJSON` that takes a (json) `Value` and returns a `Parser a`. `Parser a` can be thought of as a procedure for generating a value of type `a`.
So for instance. The monomorphic type `Parser Function` is a procedure that generates a value of type `Function`:
Live coding
Define an instance for `FromJSON` for `Function`.
Define an instance for `FromJSON` for `Definition`.