-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
commit 79ab24b Author: haxscramper <[email protected]> Date: Fri Nov 12 14:49:30 2021 +0300 [REVIEW] commit bc9d020 Author: shayanhabibi <[email protected]> Date: Tue Nov 9 16:33:03 2021 +0800 review fixes commit 1dee7e6 Author: shayanhabibi <[email protected]> Date: Tue Nov 9 16:04:36 2021 +0800 'progress' as they say commit 4911131 Author: haxscramper <[email protected]> Date: Mon Nov 8 14:21:41 2021 +0300 [REVIEW] Compiletime test corrections commit 35f52bc Author: haxscramper <[email protected]> Date: Mon Nov 8 13:53:49 2021 +0300 [TEST] All lang specification tests pass locally commit be7ae6d Author: haxscramper <[email protected]> Date: Sun Nov 7 23:38:27 2021 +0300 [DOC] Assorted test edits, mostly enum/arrays commit 1bfc8a5 Author: haxscramper <[email protected]> Date: Sun Nov 7 17:08:45 2021 +0300 [DOC} Language specification tests
- Loading branch information
1 parent
f89d809
commit f447707
Showing
63 changed files
with
1,738 additions
and
134 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Atoms | ||
|
||
This directory contains specifications for basic language components: | ||
|
||
- 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. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
discard """ | ||
description: ''' | ||
This test specifies basic operations used in other tests. | ||
''' | ||
targets:"c cpp js" | ||
""" | ||
|
||
block builtin_assert: | ||
## `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: | ||
## Built-in operations on integer values | ||
|
||
## Declare integer variable with initial value of `0` | ||
var value: int = 0 | ||
|
||
## Assert equality of the variable using `==` operator | ||
doAssert value == 0 | ||
|
||
## Increment value of the variale using `inc` command | ||
inc value | ||
|
||
doAssert value == 1 | ||
|
||
## Decrement value using `dec` command | ||
dec value | ||
|
||
## Value of the variable returned to 0 | ||
doAssert value == 0 | ||
|
||
block assert_type_of_the_expression: | ||
## Every expression has a type. This can be checked for using `is` operator | ||
## (or it's reverse `isnot`). | ||
|
||
## Declare variable of type `int` and check if expression `value` has this | ||
## type. | ||
var value: int = 0 | ||
|
||
doAssert value is int | ||
doAssert value == 0 | ||
|
||
block get_type_of_the_expression_explicitly: | ||
## 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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
discard """ | ||
description: ''' | ||
This test covers statements, sequential evaluation and control flow. | ||
''' | ||
joinable: false | ||
targets:"c cpp js" | ||
""" | ||
|
||
## This section of specification explains what *statemetn* is, and two different | ||
## types of statemets - "basic" and "noreturn". Examples of the noreturn statement | ||
## should not be confused with general specification of control-flow alteration that | ||
## is documented in :idx:`s09_control_flow/*.nim` | ||
|
||
block sequential_control_flow: | ||
## Multiple statements placed on the same level will be sequentially executed | ||
## unless interrupted by a noreturn statement. | ||
|
||
## Statement 1 - declares a variable | ||
var value = 0 | ||
|
||
## Statement 2 - assign 1 to a variable | ||
value = 1 | ||
|
||
## Statement 3 - asserts value of the variable is equal to 1 | ||
doAssert value == 1 | ||
|
||
block noreturn_statement: | ||
## 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 | ||
## `block` expressions. | ||
|
||
block break_unnamed_block: | ||
# Entered `block break_unnamed_block` path | ||
var value = 0 | ||
block: | ||
# Entered `block` path | ||
value = 1 | ||
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` 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 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 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. | ||
break | ||
value = 1 | ||
|
||
doAssert value == 0 | ||
|
||
block break_for_loop: | ||
## Break in the `for` loop operates identically to the `while` case - when | ||
## `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. 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: | ||
## This cyclic path is only 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 | ||
## iteration. | ||
continue | ||
## The control flow will now 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` 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`. | ||
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 | ||
|
||
## Statement placed after continue is never reached | ||
doAssert postContinue == 0 | ||
|
||
## 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 | ||
## # 1, 2, 3... | ||
## 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 | ||
## # 1, 2, 3... | ||
## i = 4 | ||
## preContinue = preContinue + i | ||
## postContinue = 9 | ||
## ``` | ||
|
||
block return_statement: | ||
## `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 their respective section of the specification. | ||
|
||
var value = 0 | ||
proc raiseInside() = | ||
value = 1 | ||
|
||
## Specific type of the exception is not important in this case - | ||
## `ValueError` would not be any different from `OSError` and alike | ||
raise newException(ValueError, "") | ||
value = 2 | ||
|
||
try: | ||
## 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. |
Oops, something went wrong.