diff --git a/tests/lang/s01_basics/s00_atoms/readme.md b/tests/lang/s01_basics/s00_atoms/readme.md index bba8779de70..0edab0d4d6f 100644 --- a/tests/lang/s01_basics/s00_atoms/readme.md +++ b/tests/lang/s01_basics/s00_atoms/readme.md @@ -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. \ No newline at end of file +- 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. \ No newline at end of file diff --git a/tests/lang/s01_basics/s00_atoms/t00_builtins.nim b/tests/lang/s01_basics/s00_atoms/t00_builtins.nim index 390fe98a817..a72a2f19d50 100644 --- a/tests/lang/s01_basics/s00_atoms/t00_builtins.nim +++ b/tests/lang/s01_basics/s00_atoms/t00_builtins.nim @@ -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: @@ -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" \ No newline at end of file diff --git a/tests/lang/s01_basics/s00_atoms/t01_statement.nim b/tests/lang/s01_basics/s00_atoms/t01_statement.nim index 10032a2813c..b88f9129158 100644 --- a/tests/lang/s01_basics/s00_atoms/t01_statement.nim +++ b/tests/lang/s01_basics/s00_atoms/t01_statement.nim @@ -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. @@ -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. @@ -58,11 +81,12 @@ 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 @@ -70,19 +94,29 @@ block noreturn_statement: 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 @@ -90,15 +124,17 @@ block noreturn_statement: 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 @@ -107,19 +143,63 @@ 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 @@ -127,14 +207,19 @@ block noreturn_statement: 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() = @@ -146,8 +231,8 @@ 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` @@ -155,6 +240,7 @@ block noreturn_statement: raiseInside() except: + # `try`, `except`, `finally`, will be explored in their respective section. discard doAssert value == 1 @@ -162,8 +248,12 @@ block noreturn_statement: 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.