# Evaluation of Calculated Expressions
This expression allows for dynamic calculation of answers to questions as other questions are answered. It behaves similarly to initialExpression extension, but instead of only setting its value when the QuestionnaireResponse is originally created or when a question is enabled, the value updates continuously as the answers to dependent questions change. This expression will be most commonly used for displaying scores, but can be used for any calculated element - patient age (based on current date and birth date), BMI (based on recent weight and height), estimated cost (based on selected items and quantities), etc.
## Recommended implementation
The FHIR form evaluator must scan the FHIR document and track all items in the questionnaire as and when it is available to the logical scope, to find out all items with valueExpression. All such items should be identified when those should be evaluated.
Once the point of evaluation is identified then an internal map has to be maintained in the application which maps such as following.
|Item|Depending Items|Eval Proc|
|----|---------------|-------------|
|```'Given Name'```|```['First Name', 'Family Name']```|```function () { // generated code to evaluate based on value expression }``` |

For reference we can call it as an evaluation map.

The `Eval Proc` function must be generated at run time which internally evaluate the expression using `fhirpath js` and set the value in the questionnaire.

The `Given Name`, `First Name` and `Family Name` could be replaced with respective link ids for reference. The `Depending Items` could be an empty array if the valueExpression doesn't have any dependent items as given below example.
### Expression with no dependencies
```json
"item": [
    {
    "extension": [
        {
        "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
        "valueExpression": {
            "description": "deadline for submission",
            "language": "text/fhirpath",
            "expression": "today() + 7 days"
            }
        }
    ],
    "linkId": "3.1.b",
    "text": "Deadline for submission (7 days from now)",
    "type": "date",
    "readOnly": true
    }
]
```
Whenever user changes an input in the questionnaire do the following:
1. Traverse through evaluation map and
2. Find out all the items with empty depending items
   1. Invoke `Eval Proc` set questionnaire response and raise `changed` event as described [here](https://github.com/terveys/fhirform_viewer_poc/blob/master/design/basics.md#events)
   2. Update evaluted value in the questionnaire response
3. Find out all the items with having the changed item as the depending item 
   1. Invoke `Eval Proc` set questionnaire response and raise `changed` event as described [here](https://github.com/terveys/fhirform_viewer_poc/blob/master/design/basics.md#events)
   2. Update evaluted value in the questionnaire response

Identifying dependencies
Any FHIR path expression can be converted to an AST (Abstract Syntax Tree) by using a generated ANTLR4 parser and visitor based on the published ANTLR4 grammar given below.
```antlr4
grammar fhirpath;

// Grammar rules

//prog: line (line)*;
//line: ID ( '(' expr ')') ':' expr '\r'? '\n';

expression
        : term                                                      #termExpression
        | expression '.' invocation                                 #invocationExpression
        | expression '[' expression ']'                             #indexerExpression
        | ('+' | '-') expression                                    #polarityExpression
        | expression ('*' | '/' | 'div' | 'mod') expression         #multiplicativeExpression
        | expression ('+' | '-' | '&') expression                   #additiveExpression
        | expression ('is' | 'as') typeSpecifier                    #typeExpression
        | expression '|' expression                                 #unionExpression
        | expression ('<=' | '<' | '>' | '>=') expression           #inequalityExpression
        | expression ('=' | '~' | '!=' | '!~') expression           #equalityExpression
        | expression ('in' | 'contains') expression                 #membershipExpression
        | expression 'and' expression                               #andExpression
        | expression ('or' | 'xor') expression                      #orExpression
        | expression 'implies' expression                           #impliesExpression
        //| (IDENTIFIER)? '=>' expression                             #lambdaExpression
        ;

term
        : invocation                                            #invocationTerm
        | literal                                               #literalTerm
        | externalConstant                                      #externalConstantTerm
        | '(' expression ')'                                    #parenthesizedTerm
        ;

literal
        : '{' '}'                                               #nullLiteral
        | ('true' | 'false')                                    #booleanLiteral
        | STRING                                                #stringLiteral
        | NUMBER                                                #numberLiteral
        | DATETIME                                              #dateTimeLiteral
        | TIME                                                  #timeLiteral
        | quantity                                              #quantityLiteral
        ;

externalConstant
        : '%' identifier
        ;

invocation                          // Terms that can be used after the function/member invocation '.'
        : identifier                                            #memberInvocation
        | function                                              #functionInvocation
        | '$this'                                               #thisInvocation
        | '$index'                                              #indexInvocation
        | '$total'                                              #totalInvocation
        ;

function
        : identifier '(' paramList? ')'
        ;

paramList
        : expression (',' expression)*
        ;

quantity
        : NUMBER unit?
        ;

unit
        : dateTimePrecision
        | pluralDateTimePrecision
        | STRING // UCUM syntax for units of measure
        ;

dateTimePrecision
        : 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond'
        ;

pluralDateTimePrecision
        : 'years' | 'months' | 'weeks' | 'days' | 'hours' | 'minutes' | 'seconds' | 'milliseconds'
        ;

typeSpecifier
        : qualifiedIdentifier
        ;

qualifiedIdentifier
        : identifier ('.' identifier)*
        ;

identifier
        : IDENTIFIER
        | DELIMITEDIDENTIFIER
        | 'as'
        | 'is'
        ;


/****************************************************************
    Lexical rules
*****************************************************************/

// Not sure why, but with these as lexical rules, when the grammar is imported into CQL, they are not correctly recognized
// Moving the same rules into the literal production rule above corrects the issue
//EMPTY
//        : '{' '}'
//        ;                      // To create an empty array (and avoid a NULL literal)

//BOOL
//        : 'true'
//        | 'false'
//        ;

DATETIME
        : '@'
            [0-9][0-9][0-9][0-9] // year
            (
                '-'[0-9][0-9] // month
                (
                    '-'[0-9][0-9] // day
                    (
                        'T' TIMEFORMAT
                    )?
                 )?
             )?
             'Z'? // UTC specifier
        ;

TIME
        : '@' 'T' TIMEFORMAT
        ;

fragment TIMEFORMAT
        :
            [0-9][0-9] (':'[0-9][0-9] (':'[0-9][0-9] ('.'[0-9]+)?)?)?
            ('Z' | ('+' | '-') [0-9][0-9]':'[0-9][0-9])? // timezone
        ;

IDENTIFIER
        : ([A-Za-z] | '_')([A-Za-z0-9] | '_')*            // Added _ to support CQL (FHIR could constrain it out)
        ;

DELIMITEDIDENTIFIER
        : '`' (ESC | .)*? '`'
        ;

STRING
        : '\'' (ESC | .)*? '\''
        ;

// Also allows leading zeroes now (just like CQL and XSD)
NUMBER
        : [0-9]+('.' [0-9]+)?
        ;

// Pipe whitespace to the HIDDEN channel to support retrieving source text through the parser.
WS
        : [ \r\n\t]+ -> channel(HIDDEN)
        ;

COMMENT
        : '/*' .*? '*/' -> channel(HIDDEN)
        ;

LINE_COMMENT
        : '//' ~[\r\n]* -> channel(HIDDEN)
        ;

fragment ESC
        : '\\' ([`'\\/fnrt] | UNICODE)    // allow \`, \', \\, \/, \f, etc. and \uXXX
        ;

fragment UNICODE
        : 'u' HEX HEX HEX HEX
        ;

fragment HEX
        : [0-9a-fA-F]
        ;
```
Once a ANTLR4 [Vistor](https://github.com/antlr/antlr4/blob/master/doc/javascript-target.md) is generated then we can travese through the tree and find out the depending items.

## Eval Proc Generation
An evaluation procedure can be generated with a similar code snippet as given below.

```javascript
const evalProc = eval(`function () {
    // code to evaluate FHIR path using fhirpath js
    // code to set value in questionnaire response
    // code to raise changed event
}`);
```