Skip to content

Commit

Permalink
'progress' as they say
Browse files Browse the repository at this point in the history
  • Loading branch information
shayanhabibi committed Nov 9, 2021
1 parent 4911131 commit 1dee7e6
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 42 deletions.
18 changes: 10 additions & 8 deletions tests/lang/s01_basics/s00_atoms/readme.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
This directory contains specification for the most basic language parts -
# Atoms

- what is an expression
- what is a statement
- what is "compile time"
This directory contains specifications for basic language components:

For a lot of these things it is impossible to demonstrate them without using
concepts from subsequent specification parts, but it was decided to put them
as a first entry in the specification. When more "advanced" entries are used
they should be referenced.
- What is an expression
- What is a statement
- What is "compile time"

For a lot of these, it is difficult to demonstrate without using
concepts from subsequent specification tests; but, it was decided to put them
as a first entry in the specification. When more "advanced" entries are used,
these should be referenced.
22 changes: 16 additions & 6 deletions tests/lang/s01_basics/s00_atoms/t00_builtins.nim
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
## This test specifies basic operations used in other test.
discard """
description: '''
This test specifies basic operations used in other tests.
'''
"""

block builtin_assert:
## `doAssert` command is used throughout the specification to assert
## truhfullness of an expression
## `doAssert` command is used throughout the specification to demonstrate
## the correctness of an expression; ergo, it `doAssert` evaluates the
## expression which must return `true`.

## If the expression is evaluated as true then the assertion is successful
doAssert true

## `0 == 0` is evaluated as true, the assertion is succesful
doAssert 0 == 0

block built_integer_operations:
Expand Down Expand Up @@ -39,11 +47,13 @@ block assert_type_of_the_expression:
doAssert value == 0

block get_type_of_the_expression_explicitly:
## It is possible to get type of the expression explicitly, using `typeof()`
## call. Name of the type can be converted to string using `$` operator.
## Using `typeof()` procedure, you can get the type of the expression explicitly.
## Name of the type can be converted to string using `$` operator.
## The `$` operator is an inbuilt operation that converts built-in types to
## string. This will be discussed further in subsequent documents.

var value: int = 0

doAssert value is int
doAssert $int == "int"
doAssert $typeof(value) == "int"
doAssert $typeof(value) == "int"
146 changes: 118 additions & 28 deletions tests/lang/s01_basics/s00_atoms/t01_statement.nim
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
discard """
description: '''
This test covers statements, sequential evaluation and control flow.
'''
"""

block sequential_control_flow:
## Multiple statements placed on the same level will be sequentially executed
## unless interrupted by a noreturn statement.
Expand All @@ -12,42 +18,59 @@ block sequential_control_flow:
doAssert value == 1

block noreturn_statement:
## noreturn statements allow to affect control flow of the program in
## different ways, depending on the context. Each specific type of the control
## flow-altering statement is more thoroughly discussed in the respective
## sections, this one only provides a higher-level overview of the subject.
## noreturn statements enable manipulation of control flow for the program in
## different ways (depending on the context). Each specific type of the control
## flow-altering statement is more thoroughly discussed in their respective
## sections; here we will provide a basic overview of the subject.

block break_statement:
## `break` statement can be used inside of loops - (`for`, `while`) and in
## resence of surrounding blocks.
## `block` expressions.

block break_unnamed_block:
# Entered `block break_unnamed_block` path
var value = 0
block:
# Entered `block` path
value = 1
break
break # `break` out of `block` path -> return to previous path of execution.
value = 2
# We now resume `block break_unnamed_block` path of execution

## Only single increment took place - `break` prevented second increment
## from being executed.
## Only single increment took place - `break` ended the flow of
## the block and resumed its parent flow; therefore, it prevented
## the second expression `value = 2` from being executed.
doAssert value == 1

block break_named_block:
## Unless specified by the `break` operation, it will break only its
## local path of execution. By specifying the name of the `block` you
## wish to break, you can escape several paths of execution at the same
## time.

# enter `break_named_block` path
var value = 0
block name_1:
# enter `name_1` path
value = 1
block name_2:
# enter `name_2` path
value = 2
break name_1
break name_1 # break out of `name_1` path; since `name_2` is a branch
# of `name_1`, we logically must end its execution too.
value = 3
value = 4

## `break name_1` prevented third and fourth assignment from being executed.
doAssert value == 2

## Should we have instead used `break` or `break name_2` instead of
## `break name_1`, this doAssert would fail; the correct assertion would
## instead be `doAssert value == 4`.

block break_while_loop:
## `break` in the `while` loop immediately stops loop execution. For more
## details and interactions see tests for a while statements.
## `break` in a `while` loop immediately stops the cyclic path execution. For more
## details and interactions see tests for `while` statements.
var value = 0
while true:
## Break in the `while` loop terminates it's execution.
Expand All @@ -58,47 +81,60 @@ block noreturn_statement:

block break_for_loop:
## Break in the `for` loop operates identically to the `while` case - when
## `break` is reached loop body execution is stopped. For more details see
## specification on iterators.
## `break` is reached, the loop 'body' or 'path' of execution is stopped. For more details see
## specification on `iterators`.

var value = 0
for i in 0 .. 10:
## Break in the `for` loop terminates it's execution.
break
value = 2

doAssert value == 0

block continue_statement:
## `continue` statement can be used in the `while` and `for` loops to skip
## execution of the current loop.
## execution of the current loop. It effectively ends the current cyclic path
## of execution and returns to the beginning of the cyclic path. This is different
## to `break` which ends the cyclic path altogether and instead returns to
## its parent path.

block continue_in_while:
var value = 0
var cond = true

while cond:
while cond: # This cyclic path can only be entered if `cond` is true.

## First statement in the loop is executed.
cond = false
## Setting this variable to false will mean the next iteration of the
## cyclic path will not proceed since `cond` is no longer true.

## Upon reaching `continue` control flow is transferred to the next
## Upon reaching `continue`, control flow is transferred to the next
## iteration.
continue
# The control flow will return to the beginning of the cyclic path;
# it will re-evaluate `cond` as false and therefore not proceed with
# the next iteration of the cyclic path.


## Assignment to value is never reached.
value = 1

doAssert value == 0

block continue_in_for:
## `continue` handling in the `for` loop is also identical to the `while`
## `continue` in the `for` loop is identical to the `while`
## loop - when reached, it transfers control to the next iteration. For
## more details see specification for the iteratrors.
## more details see specification for the `iteratrors`.
var preContinue = 0
var postContinue = 0

for i in 0 .. 4:
## Statement before `continue` is executed
preContinue = preContinue + i
## Upon reaching `continue`, control flow is returned to the beginning
## of the cyclic path for the next iteration.
continue
postContinue = 9

Expand All @@ -107,34 +143,83 @@ block noreturn_statement:

## Statement placed before `continue` is executed on every loop iteration
doAssert preContinue == 0 + 1 + 2 + 3 + 4


## If you flatten out the for loop; this is what you would see:
## ```nim
## i = 0
## preContinue = preContinue + i
##
## i = 1
## preContinue = preContinue + i
##
## i = 2
## preContinue = preContinue + i
##
## i = 3
## preContinue = preContinue + i
##
## i = 4
## preContinue = preContinue + i
## ```
##
## If we did not have the `continue` operation; we would instead see this:
## ```nim
## i = 0
## preContinue = preContinue + i
## postContinue = 9
##
## i = 1
## preContinue = preContinue + i
## postContinue = 9
##
## i = 2
## preContinue = preContinue + i
## postContinue = 9
##
## i = 3
## preContinue = preContinue + i
## postContinue = 9
##
## i = 4
## preContinue = preContinue + i
## postContinue = 9
## ```

block return_statement:
## `return` statement can be used in procedure or macro declaration bodies.
## When reached, it immediately trasnfers control flow outside of the
## function body. `return` can also be used to set resulting value of a
## procedure or macros - this functionality is covered in the respective
## sections.
## `return` can be used in procedures or macro declaration bodies.
## When reached, it immediately transfers control flow back to the caller of the
## function body (outside the function body). `return` can also be used to
## set resulting value of a procedure or macros - this functionality is
## covered in their respective sections.

var value = 0

value = 1

# Unlike with `block` expressions, we do not immediately enter the `proc`
# path/flow of execution. We first define it, and then enter it when the
# procedure is called. Subsequently, breaking that path of execution would
# return control to where the path was entered, not where it was defined.

proc execReturn() =
value = 2
## When `return` is reached, control flow is immediately transferred out
## of the procedure body
return
value = 3

## We execute the `execReturn` procedure - effectively we have entered the
## path of executions for that procedure. Procedures are looked at in more
## detail in their respective section.
execReturn()
# Path of operations continues when the procedure path reaches its end or
# is `return`ed.

doAssert value == 2

block raise_statement:
## `raise` statement can be used inside of a procedure body or macro to
## create an exception. Concrete details about exceptions, their types and
## handling can be seen in the respective section of the specification.
## handling can be seen in their respective section of the specification.

var value = 0
proc raiseInside() =
Expand All @@ -146,24 +231,29 @@ block noreturn_statement:
value = 2

try:
## When exception is raised it propagates through all function talls (if
## any) until it reaches topmost level (main module from which the first
## When exception is raised it propagates through all function calls (if
## any) until it reaches the topmost level (main module/path from which the first
## function was called) or a `try` statement. For particular details on
## how exceptions affect control flow see respective part of the
## specification. In this case `try` was needed so subsequent `doAssert`
## would be executed correctly.
raiseInside()

except:
# `try`, `except`, `finally`, will be explored in their respective section.
discard

doAssert value == 1

block noreturn_annotation:
## Another type of a noreturn statement is a `quit()` procedure - it
## immediatelly terminates whole execution of the program once called.
## If looking at this from a paths or flow perspective, this is effectively
## ending every path of the program.

quit()

## This statement will never be reached because `quit()` was called before.
doAssert false
## If the statement was reached, then the assertion would fail, and the
## test would return a FAIL.

0 comments on commit 1dee7e6

Please sign in to comment.