---
Summary: Representing Python Programs using PyNodes
Updated: June 2016
git-hash: b7f7cd879a726d7a88adf78704784e08bd62c9dd
---
Representing Python Programs using PyNodes
==========================================

When the python program is parsed, the parser creates an AST using PyNodes.

PyNodes represent various parts of the python program. 

The semantics of the AST is stored in objects that derive from a class called PyNode.

PyNode itself however is a subclass of a Tree type which is used to provide basic tree structure.

At present this is more than a little confused because PyNode *also*
constructs a tree from attributes it presents, so something is clearly wrong
there.
 That tree type seems rather redundant and needs to be changed.


This is in part due to the increasing complexity of structures as Pyxie gets
more complex.

This file documents the existing structure - based on a spreadsheet analysis - to aid with simplification.


Class hierarchy:


    Tree 
      PyNode(Tree):  | base_nodes.py
        PyProgram(PyNode):		| structural.py
        PyBlock(PyNode):		| structural.py
        PyStatements(PyNode):		| structural.py
        PyExprList(PyNode):		| structural.py
        PyAttribute(PyNode):		| values.py                    (*** HMM ***)
        PyAttributeAccess(PyNode):	| values.py                    (*** HMM ***)

        PyStatement(PyNode): 	| base_nodes.py
          PyAssignment(PyStatement):		| statements.py
          PyExpressionStatement(PyStatement):	| statements.py
          PyFunctionCall(PyStatement):		| statements.py
          PyForLoop(PyStatement):		| statements.py
          PyWhileStatement(PyStatement):	| statements.py
          PyIfStatement(PyStatement):		| statements.py
          PyElIfClause(PyStatement):		| statements.py
          PyElseClause(PyStatement):		| statements.py
          PyEmptyStatement(PyStatement):	| statements.py
          PyPassStatement(PyStatement):		| statements.py
          PyBreakStatement(PyStatement):	| statements.py
          PyContinueStatement(PyStatement):	| statements.py
          PyPrintStatement(PyStatement):	| statements.py

        PyValueLiteral(PyNode):		| values.py
          PyString(PyValueLiteral):		| values.py
          PyCharacter(PyValueLiteral):		| values.py
          PyBoolean(PyValueLiteral):		| values.py
          PyIdentifier(PyValueLiteral):		| values.py
          PyNumber(PyValueLiteral):		| values.py

            PyFloat(PyNumber):			| values.py
            PyInteger(PyNumber):		| values.py
            PySignedLong(PyNumber):		| values.py
            PyUnSignedLong(PyNumber):		| values.py
            PyHex(PyNumber):			| values.py
            PyOctal(PyNumber):			| values.py
            PyBinary(PyNumber):			| values.py

        PyOperation(PyNode):		   | base_nodes.py
          PyComparisonOperator(PyOperation):	| operators.py
          PyOperator(PyOperation):		| operators.py

            PyTimesOperator(PyOperator):	| operators.py
            PyDivideOperator(PyOperator):	| operators.py
            PyPowerOperator(PyOperator):	| operators.py
            PyPlusOperator(PyOperator):		| operators.py
            PyMinusOperator(PyOperator):	| operators.py

          PyBoolOperator(PyOperation):		| operators.py
            PyNotOperator(PyBoolOperator):	| operators.py
            PyAndOperator(PyBoolOperator):	| operators.py
            PyOrOperator(PyAndOperator):	| operators.py  (WTAF?)


Tree Nodes have the following:
  * Attributes:
    * children = [] # default value
  * Methods:
    * __pson__ - returns a "Python structure object notation" representation of the tree.
                 This boils down to a structure based on:
                     { "nId" : str(id(self)),
                       "nStr" : str(self)[:40],
                       "nchildren" : [x.__pson__() for x in self.children] }

    * add_child(self, node): -> Add given node to children
    * add_children(self, *nodes): -> Add given nodes as children


    * depth_walk(self): -> "Return a generator that is a depth first walk of the tree"

        -- This could actually be integrated directly into PyNode

USED IN:
   ./model/pynodes/structural.py:  for node in self.depth_walk():  --- Used for finding vafriables in the AST...(!)
    ./model/transform.py:           for node in AST.depth_walk():        --- Used for finding variables in the AST... (?!)



UNUSED
     * _breadth_walk_children -- Internal implementation function for breadth_walk

UNUSED def breadth_walk(self):
     * breadth_walk -> Return a generator that is a breadth first walk of the tree, not optimised, copes with unbalanced trees
        -> UNUSED

UNUSED def breadth_walk_up(self):
     * breadth_walk_up -> Return a generator that is a breadth first walk of the tree. Starts with lowest layers. Not optimised, copes with unbalanced trees
        -> UNUSED
