-
Notifications
You must be signed in to change notification settings - Fork 72
Analyzer
Analyzer takes read wisp code form and performs both syntax & macro expansions over it, producing AST nodes that are hash maps that implement following interface:
```clj
{:type :keyword
:form '(read data)}
```
The :type key is mapped to a keyword representing the AST variant type.
All the AST nodes produced by analyzer comply to some AST type interface
described by this document.
The :form key is mapped to an actual form that was analyzed producing
AST node containing it. Note that raw forms mapped to the key will also
typically have a metadata containing source location information of the
node.
Location information contains start (the position of the first character of the parsed source region) & and an end position (the position of the first character after the parsed source region):
Both :start and :end positions contain (0-indexed) :line number and
a (0-indexed) :column number that can be obtained as illustrated in the
examples below:
```clj
;; Start line position
(:line (:start (meta (:form node))))
;; Start column position
(:column (:start (meta (:form node))))
;; End line position
(:line (:end (meta (:form node))))
;; End columnt position
(:column (:end (meta (:form node))))
```
Primitive types are represented by an AST nodes of :literal types:
```clj
{:type :literal
:form Nil | String | Boolean | Number | Pattern | Keyword}
```
Forms in :literal AST node are mapped to primitive types and there
for they don't carry any metadata.
Identifier nodes typically represent either referces to a specific bindings or an identifiers that define bindings:
```clj
{:type :identifier
:form Symbol
:binding DeclarationNode}
```
The :binding is mapped to node representing definition of the binding
it references. If node is an identifier of the binding itself, it's
:binding is mapped to nil.
There are three types of bindings declarations, but they all implement generic declaration interface:
```clj
{:id IdentifierNode
:init Node
:depth Number
:shadow DeclarationNode
:form List}
```
The :id is mapped to an IdentifierNode that represents an identifier
of the binding itself and there for it's :binding field is mapped to
nil.
The :depth is a number representing a depth at which binding shadows
the outer scope binding with a same name. If binding does not shadows
any outer scope binding it's considered to be shadowing unresolved top
level binding and :depth is 1.
The :shadow is mapped to an another, outer scope, Binding node that
is being shadowed by this node. If binding node in the outer scope can't
be resolved it's mapped to a Binding node of :unresloved-binding type
node.
There are several type of declaration nodes:
```clj
{:type :parameter
:id IdentifierNode
:depth Number
:shadow DeclarationNode
:form Symbol}
```
```clj
{:type :binding
:id IdentifierNode
:depth Number
:shadow DeclarationNode
:init Node
:form List}
```
```clj
{:type :def
:doc String | nil
:id IdentifierNode
:init Node
:export Boolean
:depth Number
:shadow DeclarationNode
:init Node}
```
```clj
{:type :if
:test Node
:consequent Node
:alternate Node}
```clj
{:type :throw
:throw Node
:form List}
```
```clj
{:type :assignment
:target Node
:value Node
:form List}
```
{:type :instantiation
:constructor Node
:}