Skip to content

Commit

Permalink
[DOC] Control flow with procedure calls
Browse files Browse the repository at this point in the history
  • Loading branch information
haxscramper committed Nov 14, 2021
1 parent 4206347 commit 805d122
Show file tree
Hide file tree
Showing 16 changed files with 350 additions and 25 deletions.
9 changes: 6 additions & 3 deletions tests/lang/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ core properties (`yield`, control transfer, state preservation), then
expand the definition by providing a specification for interactions with
other language constructs (`break`, `continue`, `defer`).

The only part of the specification that does not follow these rules is
"atoms" section, that describes fundamental capabilities of the language
such as *expressions*, *statements*, *type*, as well as a constructs used
in the tests themselves.


## Contributing tests

Expand Down Expand Up @@ -106,6 +111,4 @@ block failing_example:
## File naming

- `t01_feature_name.nim` - start file name with number to explicitly order features.
- `t01_feature_name_run_fail.nim` - show example of the runtime failure
- `t01_feature_name_comp_fail.nim` - show compilation error related to the feature
- `t01_feature_name_warning.nim` - show compilation warning related to the feature
- `t01_feature_name_fail.nim` - show example of the runtime failure
16 changes: 8 additions & 8 deletions tests/lang/s01_basics/s00_atoms/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

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,
- expression
- statement
- "compile time"
- "type"

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.

46 changes: 37 additions & 9 deletions tests/lang/s01_basics/s05_primitive_types/t01_integer.nim
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ target: "c cpp js"
# - narrowing conversions for `int` literals (compile time) are compile time
# checked, and if they fit are done implicitly

block:
block type_conversion_to_8:
let
a: int8 = 1
min: int8 = -128
Expand All @@ -25,7 +25,7 @@ block:
doAssert typeOf(max) is int8, "auto-narrow: literal `int`->`int8` - max"
# xxx: cover the over under flows in separate tests

block:
block type_conversion_to_unsigned_8:
let
a: uint8 = 1
min: uint8 = 0
Expand All @@ -35,7 +35,7 @@ block:
doAssert typeOf(max) is uint8, "auto-narrow: literal `int`->`uint8` - max"
# xxx: cover the over under flows in separate tests

block:
block type_conversion_to_16:
let
a: int16 = 1
min: int16 = -32_768
Expand All @@ -45,7 +45,7 @@ block:
doAssert typeOf(max) is int16, "auto-narrow: literal `int`->`int16` - max"
# xxx: cover the over under flows in separate tests

block:
block type_conversion_to_unsigned_16:
let
a: uint16 = 1
min: uint16 = 0
Expand All @@ -55,7 +55,7 @@ block:
doAssert typeOf(max) is uint16, "auto-narrow: literal `int`->`uint16` - max"
# xxx: cover the over under flows in separate tests

block:
block type_conversion_to_32:
let
a: int32 = 1
min: int32 = -2_147_483_648
Expand All @@ -68,7 +68,7 @@ block:
# at this point, it starts depending upon the platform whether it's a narrowing
# or widening of the type

block:
block type_conversion_to_unsigned_32:
let
a: uint32 = 1
min: uint32 = 0
Expand All @@ -78,7 +78,7 @@ block:
doAssert typeOf(max) is uint32, "auto-conv: literal `int`->`uint32` - max"
# xxx: cover the over under flows in separate tests

block:
block type_conversion_to_64:
let
a: int64 = 1
min: int64 = -9_223_372_036_854_775_808
Expand All @@ -91,12 +91,40 @@ block:
# automatic/implied widening and contrast with narrowing
# xxx: need to add more coverage

block:
block type_conversion_to_unsigned_64:
let
a = 6'i8
b: int = 10
narrow = a + 10
widened = a + b
doAssert typeof(narrow) is int8, "integer operations with literals narrow"
doAssert typeof(widened) is int, "runtime integer operations widened types"
doAssert narrow == widened, "the values are comparable and equal"
doAssert narrow == widened, "the values are comparable and equal"

block negative_literals:
doAssert -1 == -(1)

doAssert -1'i8 == -(1'i8)
doAssert -1'i8 == -(1'i8)
doAssert -1'i16 == -(1'i16)
doAssert -1'i16 == -(1'i16)
doAssert -1'i32 == -(1'i32)
doAssert -1'i32 == -(1'i32)
doAssert -1'i64 == -(1'i64)
doAssert -1'i64 == -(1'i64)


block literal_prefixes:
## Integer literals may be given in decimal (no prefix), binary (prefix `0b`), octal
## (prefix `0o`), and hexadecimal (prefix `0x`) notation.
block binary_literals:
doAssert 0b10 == 2
doAssert 0b00 == 0

block octal_literals:
doAssert 0o1 == 1
doAssert 0o10 == 8

block hexadecimal_literals:
doAssert 0x1 == 1
doAssert 0xA == 10
167 changes: 162 additions & 5 deletions tests/lang/s01_basics/s08_control_flow/t06_procedure_calls.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,162 @@
## This specifices how control flow is transferred in the procedure body. It
## also shows how exceptions, `defer` and `return` affect the control flow.
## Note - even though exceptions are used in this section. it is **not** a specification
## on how exceptions in general are to be used - (used-defined exceptions, coercion to a
## parent exception types in `as` blocks, exception message, stack trace and so on).
## This specifices how control flow is transferred in the procedure body.
## It also shows how exceptions, `defer` and `return` affect the control
## flow. Note - even though exceptions are used in this section. it is
## **not** a specification on how exceptions in general are to be used -
## (used-defined exceptions, coercion to a parent exception types in `as`
## blocks, exception message, stack trace and so on).

block simple_procedure:
var values: seq[string]

proc impl() =
values.add "in proc"

values.add "before proc"
impl()
values.add "after proc"

doAssert values == @[
"before proc",
"in proc",
"after proc"
]

block call_other:
var values: seq[string]

proc impl2() =
values.add "in-in proc"

proc impl1() =
values.add "in-before proc"
impl2()
values.add "in-after proc"

impl1()

doAssert values == @[
"in-before proc",
"in-in proc",
"in-after proc",
]

block self_recursive:
var values: seq[string]
var counter = 0

proc recurse() =
let depth = $counter
values.add "pre recurse " & depth

inc counter
if counter < 3:
recurse()

values.add "post recurse " & depth

recurse()

doAssert values == @[
"pre recurse 0",
"pre recurse 1",
"pre recurse 2",
"post recurse 2",
"post recurse 1",
"post recurse 0",
]

block single_defer:
var values: seq[string]

proc impl() =
defer:
values.add "defer"

values.add "body"

impl()
doAssert values == @["body", "defer"]

block multiple_defers:
## `defer` statements are executed in reverse order of their encontering
## in procedure body.
var values: seq[string]
proc impl() =
defer: values.add "defer 1"
defer: values.add "defer 2"
defer:
## Nesting does not affect defer - code will be executed in regular
## (sequential) manner.
values.add "defer 3"
defer:
values.add "defer 4"

values.add "body"

impl()

doAssert values == @[
"body",
"defer 3",
"defer 4",
"defer 2",
"defer 1",
]

block exception:
var values: seq[string]

proc raised() =
values.add "before"
raise (ref CatchableError)()
values.add "after"

try: raised() except: discard

doAssert values == @["before"]



block call_other_exceptino:
var values: seq[string]

proc impl2() =
values.add "in-in proc"
raise (ref CatchableError)()

proc impl1() =
values.add "in-before proc"
impl2()
values.add "in-after proc"

try: impl1() except: discard

doAssert values == @[
"in-before proc",
"in-in proc",
]

block self_recursive_raise:
var values: seq[string]
var counter = 0

proc recurse() =
let depth = $counter
values.add "pre recurse " & depth

inc counter
if counter < 3:
recurse()

else:
raise (ref CatchableError)()

values.add "post recurse " & depth

try: recurse() except: discard

doAssert values == @[
"pre recurse 0",
"pre recurse 1",
"pre recurse 2"
]
35 changes: 35 additions & 0 deletions tests/lang/s02_core/s01_user_defined_data_types/t07_typeclass.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
discard """
description: '''
PLACEHOLDER
'''
"""

block builtin_typeclasses:
block object_class:
type Obj = object

doAssert Obj() is object
doAssert Obj is object
doAssert Obj is typedesc
doAssert Obj() isnot typedesc

block enum_class:
type Enum = enum a

doAssert Enum is enum
doAssert a is enum

block distinct_class:
type Dist = distinct int

doAssert Dist is distinct
doAssert Dist(12) is distinct

block proc_class:
proc test(): int = discard

doAssert test is proc

block tuple_Class:
doAssert (1, 2) is tuple
doAssert (1, 2) is (int, int)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
discard """
description: '''
Specification of the experimental dot operators feature
'''
cmd: "nim $target -r -d:nimPreviewDotLikeOps $options $file"
"""

{.experimental: "dotOperators".}

block int_dot_operator:
template `.`(lhs: int, field: untyped): int = 1

doAssert 1.test == 1
Loading

0 comments on commit 805d122

Please sign in to comment.