# Project 1

## Project description

### Project

The main task of the project is to write a function `getFlow()`. The purpose of this function is to analyze a body of a function given as an argument. The analysis is concerned with assignments done within the body of an argument function. Technically, the `getFlow()` function takes a function as an argument (object with a base type `closure`) and returns an object containing a list of all assignments together with conditions (resulting from `if` / `else` phrases). Below are usage examples of my simple implementation of this idea.

I start with a simple example. Let's see how the `getFlow()` deals with a function containing a single unconditional assignment.

```### Function definition
f <- function(a) {
x <- a + rnorm(1)
x
}

fFlow <- getFlow(f)
fFlow

```
```x  <-  a + rnorm(1)  ||| TRUE
```

The `getFlow()` returns an object containing a list of assignments with conditions attached. In my implementation, the list of assignments is an instance of a new class `assignmentList`, and each element of this list is an instance of another new class `assignment`. For both classes, I implemented `print` methods and `c` methods for convenience. In the above example, the list contains a single element: an assignment with a condition `TRUE` indicating that this is an unconditional assignment.

Let's see another slightly more complicated example.

```### Function definition
f <- function(a, b) {
b <- abs(b)
x <- a ^ b
x
}

fFlow <- getFlow(f)
fFlow

```
```b  <-  abs(b)  ||| TRUE
x  <-  a^b     ||| TRUE
```

The computation flow here is also very simple for the above function as it comprises only two unconditional assignments.

Next, let's see how the `getFlow()` works for functions containing conditional statements.

```### Function definition
f <- function(z, b) {
if( z <= 0) {
stop("Only positive values of z are allowed.", call. = FALSE)
} else {
x <- z ^ b
}
x
}

fFlow <- getFlow(f)
fFlow

```
```x  <-  z^b  ||| not z <= 0  and TRUE
```

The behavior of the functions is a little bit more complicated. There is still only one assignment. It is, however, a more complicated one as this time it contains a condition resulting from the `else` clause. Such conditions are marked with a `not` keyword.

Let's see an even more complicated example with multiple conditional statements.

```### Function definition
f <- function(a, b) {
x <- rnorm(1)
if(a < 0)
{
a <- abs(a)
if(b == 2L)
{
y <- a ^ 2
y <- y + x
}
} else
{
y <- a ^ b
y <- y + x
}
y
}

fFlow <- getFlow(f)
fFlow

```
```x  <-  rnorm(1)  ||| TRUE
a  <-  abs(a)    ||| a < 0  and TRUE
y  <-  a^2       ||| a < 0  and b == 2L  and TRUE
y  <-  y + x     ||| a < 0  and b == 2L  and TRUE
y  <-  a^b       ||| not a < 0  and TRUE
y  <-  y + x     ||| not a < 0  and TRUE
```

As expected, the flow of computations is a notch more complicated here. The first assignment is unconditional. The second one contains a simple condition resulting from the first level of the `if` clause. The two following assignments have compound conditions resulting from two `if` clauses. The last two assignments have negated conditions of the first `if` clause resulting from the `else` statement.

I can apply the getFlow() function to any function. An example is below.

```### Simple application
getFlow(setOldClass)

```
```simpleCase  <-  is.null(prototype)                            ||| TRUE
mainClass  <-  Classes[[1L]]                                  ||| TRUE
prevDef  <-  getClassDef(mainClass, where, inherits = FALSE)  ||| TRUE
clName  <-  S4Class                                           ||| !missing(S4Class)  and !is(S4Class, "classRepresentation")  and is.character(S4Class)  and TRUE
S4Class  <-  getClass(S4Class)                                ||| !missing(S4Class)  and !is(S4Class, "classRepresentation")  and is.character(S4Class)  and TRUE
S4prototype  <-  S4Class@prototype                            ||| !missing(S4Class)  and !is.null(prototype)  and TRUE
S4Class@prototype  <-  .mergeAttrs(prototype, S4prototype)    ||| !missing(S4Class)  and !is.null(prototype)  and TRUE
prevClass  <-  "oldClass"                                     ||| TRUE
S3Class  <-  character()                                      ||| TRUE
S3table  <-  new.env()                                        ||| is.null(S3table <- where\$.S3MethodsClasses)  and TRUE
dataPartClass  <-  NULL                                       ||| TRUE
S3Class  <-  c(cl, S3Class)                                   ||| TRUE
def  <-  getClass(cl, where)                                  ||| isClass(cl, where)  and TRUE
cl1  <-  .validDataPartClass(cl, where, dataPartClass)        ||| isClass(cl, where)  and !extends(def, prevClass)  and TRUE
prevP  <-  def@prototype                                      ||| isClass(cl, where)  and not !extends(def, prevClass)  and TRUE
prevS3Class  <-  attr(prevP, ".S3Class")                      ||| isClass(cl, where)  and not !extends(def, prevClass)  and TRUE
useP  <-  TRUE                                                ||| not isClass(cl, where)  and TRUE
useP  <-  FALSE                                               ||| TRUE
def  <-  getClassDef(cl, where)                               ||| not isClass(cl, where)  and TRUE
attr(clp, ".S3Class")  <-  S3Class                            ||| not isClass(cl, where)  and TRUE
def@prototype  <-  .notS4(clp)                                ||| not isClass(cl, where)  and TRUE
prevClass  <-  cl                                             ||| TRUE
```

There are many more assignments here, and the conditions are also more complicated, resulting from many nested if / else statements. However, this way of looking at the code tells more about the computation flow and inherently about the code's complexity.

My implementation of the `getFlow()` function has several limitations. One of those limitations is the lack of analysis of the condition statement in the `if` clause. You can observe this in the above example, where one of the conditions contains an assignment. While doing the project, you can also ignore this case.

### Technical conditions

The project should be solved in a single R file. The file should contain the solution (implementation) and examples of use (you can use the above examples). Solutions without examples will not be excepted. You are not allowed to use any additional packages except for `stringr`, if necessary. Please, do not use polish diacritics.

Date: 2021-05-01 Sat 00:00

Created: 2021-05-03 Mon 18:22

Validate