forked from nim-works/nimskull
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
180a56d
commit 1bfc8a5
Showing
23 changed files
with
841 additions
and
5 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,10 @@ | ||
This directory contains specification for the most basic language parts - | ||
|
||
- what is an expression | ||
- what is a statement | ||
- what is "compile time" | ||
|
||
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. |
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,50 @@ | ||
## This test specifies basic operations used in other test. | ||
|
||
block builtin_assert: | ||
## `doAssert` command is used throughout the specification to assert | ||
## truhfullness of an expression | ||
doAssert true | ||
|
||
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: | ||
## Nim is a statically typed programming language, which means 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: | ||
## It is possible to get type of the expression explicitly, using `typeof()` | ||
## call. Name of the type can be converted to string using `$` operator. | ||
|
||
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,169 @@ | ||
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 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. | ||
|
||
block break_statement: | ||
## `break` statement can be used inside of loops - (`for`, `while`) and in | ||
## resence of surrounding blocks. | ||
|
||
block break_unnamed_block: | ||
var value = 0 | ||
block: | ||
value = 1 | ||
break | ||
value = 2 | ||
|
||
## Only single increment took place - `break` prevented second increment | ||
## from being executed. | ||
doAssert value == 1 | ||
|
||
block break_named_block: | ||
var value = 0 | ||
block name_1: | ||
value = 1 | ||
block name_2: | ||
value = 2 | ||
break name_1 | ||
value = 3 | ||
value = 4 | ||
|
||
## `break name_1` prevented third and fourth assignment from being executed. | ||
doAssert value == 2 | ||
|
||
block break_while_loop: | ||
## `break` in the `while` loop immediately stops loop execution. For more | ||
## details and interactions see tests for a 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: | ||
## Breka 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. | ||
|
||
var value = 0 | ||
for i in 0 .. 10: | ||
break | ||
value = 2 | ||
|
||
doAssert value == 2 | ||
|
||
block continue_statement: | ||
## `continue` statement can be used in the `while` and `for` loops to skip | ||
## execution of the current loop. | ||
|
||
block continue_in_while: | ||
var value = 0 | ||
var cond = true | ||
|
||
while cond: | ||
## First statement in the loop is executed. | ||
cond = false | ||
|
||
## Upon reaching `continue` control flow is transferred to the next | ||
## iteration. | ||
continue | ||
|
||
## 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` | ||
## 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 | ||
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 | ||
|
||
|
||
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. | ||
|
||
var value = 0 | ||
|
||
value = 1 | ||
|
||
proc execReturn() = | ||
value = 2 | ||
## When `return` is reached, control flow is immediately transferred out | ||
## of the procedure body | ||
return | ||
value = 3 | ||
|
||
execReturn() | ||
|
||
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. | ||
|
||
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 talls (if | ||
## any) until it reaches topmost level (main module 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: | ||
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. | ||
|
||
quit() | ||
|
||
## This statement will never be reached because `quit()` was called before. | ||
doAssert false |
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,100 @@ | ||
## Basic expressions. This section explains and tests basic expressions - | ||
## without using `if/when/case` expressions, procedure calls and so on. | ||
|
||
|
||
|
||
block basic_expression: | ||
## Any literal is an expression. Concrete type of the expression depends on | ||
## the type of literal used. | ||
|
||
## String literal is an expression of type `string` | ||
doAssert "literal" is string | ||
|
||
## Standalone integer literal is an expression of type `int` | ||
doAssert 12 is int | ||
|
||
## Floating point value literal is an expression of type `float` | ||
doAssert 3.14 is float | ||
|
||
## It is posssible to explicitly specify type of the numeric literal (integer | ||
## or float) using suffix - | ||
|
||
## Literal of type "unsigned 8-bit integer" | ||
doAssert 1'u8 is uint8 | ||
|
||
## "signed 8-bit integer" | ||
doAssert 1'i8 is int8 | ||
|
||
## Other types of integer literals include `16`, `32` and `64`-bit integers. | ||
|
||
doAssert 1'u16 is uint16 | ||
doAssert 1'i16 is int16 | ||
|
||
doAssert 1'u32 is uint32 | ||
doAssert 1'i32 is int32 | ||
|
||
doAssert 1'u64 is uint64 | ||
doassert 1'i64 is int64 | ||
|
||
block block_expressions: | ||
doAssert( | ||
block: | ||
## Block expression might contain multiple statements, including comments | ||
discard | ||
## Value of the last expression in block will be used as a resulting value | ||
## in the whole expression. | ||
true | ||
) | ||
|
||
doAssert( | ||
block: | ||
block: | ||
block: | ||
## It is possible to nest block expressions when needed | ||
true | ||
) | ||
|
||
|
||
## It is also possible to put multiple preceding statements on a single line | ||
## using semicolon (`;`) as a separator. | ||
|
||
var value = 0 | ||
|
||
## This expression allows to implement pre-increment action | ||
doAssert value == 0 | ||
doAssert ((inc value; value)) == 1 # QUESTION why double parens are necessary? | ||
doAssert value == 1 | ||
|
||
## This one is similar, but does a post-increment | ||
doAssert value == 1 | ||
doAssert ((let tmp = value; inc value; tmp)) == 1 | ||
doAssert value == 2 | ||
|
||
|
||
block statements_as_expressions: | ||
## It is possible to use `if`, `case`, `try` statements as expressions. | ||
|
||
## `if` can be used as inline expressions. For more examples on this see | ||
## specification for if statement. | ||
doAssert(if 12 == 12: true else: false) | ||
doAssert(if 12 == 13: true elif 12 == 12: true else: false) | ||
|
||
## Case statement cannot be used as a single-line expression, but it is still | ||
## possible to use it in any other form. For more examples and specific rules | ||
## on the case expression see specification for case statement. | ||
let vcase = case range[0..2](0): | ||
of 0: 13 | ||
of 1: 14 | ||
of 2: 15 | ||
|
||
doAssert vcase == 13 | ||
|
||
## `try` can be used as a single-line expression as well. For more examples on | ||
## and specific rules see specification for exception handling. | ||
let vtry = try: | ||
raise (ref OSError)() | ||
|
||
except: | ||
12 | ||
|
||
doAssert vcase == 12 |
Oops, something went wrong.