# *********************************************************************
# Copyright (C) 2018-2022 Blue Brain Project
#
# This file is part of NMODL distributed under the terms of the GNU
# Lesser General Public License. See top-level LICENSE file for details.
# *********************************************************************

######################### NMODL Abstract Language Definition ##############################
#
# PURPOSE
# =======
#
# NMODL language specification in nmod.yaml takes care of representing NMODL language
# AST generation. This AST is sufficient for NMODL level analysis and optimizations.
# In order to perform code generation transformations, we need to perform various
# transoformations on AST and add new node types. For example, PROCEDURE and FUNCTION
# nodes in NMODL doesn't have return type (double by default).  Also, we can't represent
# code generation specific information (e.g. variable or function qualifiers) with the
# existing AST nodes. This yaml specification describe additional node types that can
# be used for code generation purpose. Note that they are using same inheritance
# hierarchy because we would like to use single AST to represent the NMODL with and
# without code generation transformations.

- AST:
    children:
      - Node:
          children:
            - Expression:
                children:
                  - Number:
                  - Identifier:
                  - Block:
                      children:
                        - NrnStateBlock:
                            nmodl: "NRN_STATE "
                            brief: "Represents the coreneuron nrn_state callback function"
                            members:
                              - solve_statements:
                                  brief: "solve blocks to be called or generated"
                                  type: Statement
                                  vector: true
                        - EigenNewtonSolverBlock:
                            brief: "Represent newton solver solution block based on Eigen"
                            nmodl: "EIGEN_NEWTON_SOLVE"
                            members:
                              - n_state_vars:
                                  brief: "number of state vars used in solve"
                                  type: Integer
                                  prefix: {value: "["}
                                  suffix: {value: "]"}
                              - variable_block:
                                  brief: "Statements to be declared in the functor"
                                  type: StatementBlock
                              - initialize_block:
                                  brief: "Statement block to be executed before calling newton solver"
                                  type: StatementBlock
                              - setup_x_block:
                                  brief: "update X from states"
                                  type: StatementBlock
                              - functor_block:
                                  brief: "odes as functor for eigen"
                                  type: StatementBlock
                              - update_states_block:
                                  brief: "update back states from X"
                                  type: StatementBlock
                              - finalize_block:
                                  brief: "Statement block to be executed after calling newton solver"
                                  type: StatementBlock
                        - EigenLinearSolverBlock:
                            brief: "Represent linear solver solution block based on Eigen"
                            nmodl: "EIGEN_LINEAR_SOLVE"
                            members:
                              - n_state_vars:
                                  brief: "number of state vars used in solve"
                                  type: Integer
                                  prefix: {value: "["}
                                  suffix: {value: "]"}
                              - variable_block:
                                  brief: "Statements to be declared in the functor"
                                  type: StatementBlock
                              - initialize_block:
                                  brief: "Statement block to be executed before calling linear solver"
                                  type: StatementBlock
                              - setup_x_block:
                                  brief: "update X from states"
                                  type: StatementBlock
                              - update_states_block:
                                  brief: "update back states from X"
                                  type: StatementBlock
                              - finalize_block:
                                  brief: "Statement block to be executed after calling linear solver"
                                  type: StatementBlock                                  
                  - WrappedExpression:
                      brief: "Wrap any other expression type"
                      members:
                        - expression:
                            brief: "Expression that is being wrapped"
                            type: Expression
                  - DerivimplicitCallback:
                      brief: "Represent a callback to NEURON's derivimplicit solver"
                      members:
                        - node_to_solve:
                            brief: "Block to be solved (typically derivative)"
                            type: Block
                  - SolutionExpression:
                      brief: "Represent solution of a block in the AST"
                      members:
                        - solve_block:
                            type: SolveBlock
                        - node_to_solve:
                            brief: "Block to be solved (callback node or solution node itself)"
                            type: Expression
            - Statement:
                brief: "Statement base class"
                children:
                  - UpdateDt:
                      nmodl: "dt"
                      members:
                        - value:
                            brief: "Value of new timestep"
                            type: Double
                            prefix: {value: " = "}
                      brief: "Statement to indicate a change in timestep in a given block"