Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Language specification in form of tests #10

Closed
haxscramper opened this issue Oct 27, 2021 · 17 comments
Closed

Language specification in form of tests #10

haxscramper opened this issue Oct 27, 2021 · 17 comments
Assignees
Labels
documentation Improvements or additions to documentation

Comments

@haxscramper
Copy link
Collaborator

haxscramper commented Oct 27, 2021

Similarly to the https://github.com/nim-works/nimskull/tree/devel/tests/lang - implement language specification in form of proper tests. There are a lot of things to be checked, but a rough list includes at least (suggestions for more bullet points to test are welcome).

Example implementation PRs

@haxscramper haxscramper self-assigned this Oct 27, 2021
@haxscramper haxscramper added the documentation Improvements or additions to documentation label Oct 27, 2021
@krux02
Copy link
Contributor

krux02 commented Oct 27, 2021

Nice comment on macros.

@haxscramper
Copy link
Collaborator Author

For tests that involve types also check everything with distinct.

So it's good to put the 3 permutations of them in different places
A distinct to a type, a generic distinct, and a distinct of a generic distinct
Basically anywhere you should be able to put a type ensure you put those distincts

type
  A = distinct int
  B[T] = distinct A
  C = distinct B[string]

@haxscramper
Copy link
Collaborator Author

haxscramper commented Oct 30, 2021

I would much rather prefer to have some built-in language construct to assert compilation errors, instead of testament hack

let failure = getFailedNkErrorNodes:
  SomeCodeThatMakesNoSenseSemantically
doAssert failure.description.contains "illegal recursion in type 'Object'"
discard """
  cmd: "nim check $file"
  nimout: '''teffects1.nim(22, 28) template/generic instantiation from here
teffects1.nim(23, 13) Error: can raise an unlisted exception: ref IOError
teffects1.nim(22, 29) Hint: 'lier' cannot raise 'IO2Error' [XCannotRaiseY]
teffects1.nim(38, 21) Error: type mismatch: got <proc (x: int): string{.noSideEffect, gcsafe, locks: 0.}> but expected 'MyProcType = proc (x: int): string{.closure.}'
.raise effects differ'''
"""
{.push warningAsError[Effect]: on.}
type
  TObj {.pure, inheritable.} = object
  TObjB = object of TObj
    a, b, c: string

  IO2Error = ref object of IOError

proc forw: int {. .}

proc lier(): int {.raises: [IO2Error].} =
  #[tt.Hint                 ^ 'lier' cannot raise 'IO2Error' [XCannotRaiseY] ]#
  writeLine stdout, "arg" #[tt.Error
            ^  can raise an unlisted exception: ref IOError
  ]#

proc forw: int =
  raise newException(IOError, "arg")

{.push raises: [Defect].}

type
  MyProcType* = proc(x: int): string #{.raises: [ValueError, Defect].}

proc foo(x: int): string {.raises: [ValueError].} =
  if x > 9:
    raise newException(ValueError, "Use single digit")
  $x

var p: MyProcType = foo #[tt.Error
                    ^
type mismatch: got <proc (x: int): string{.noSideEffect, gcsafe, locks: 0.}> but expected 'MyProcType = proc (x: int): string{.closure.}'

]#
{.pop.}
{.pop.}

@haxscramper
Copy link
Collaborator Author

Todo items from specification PR reviews by @saem

  • areas of future improvement to be noted, precedence/parsing rules for how the command syntax collects arguments and interaction with other ones. link
  • Todo, to be noted for later, I think the formal semantics of this should be a lowering to a combination of procedures that takes the arguments, or not if default, and then have code in the body to carry out the expressions to access fields and stuff. link
  • Todo, noted for later, need to add in the rules for loop items/pairs inference. It should actually be changed, like either static interfaces, rows, concepts, or something to make it work nicely. link

@krux02
Copy link
Contributor

krux02 commented Nov 1, 2021

There is another thing important about generics. Generic instanciation time needs to be specified. Generally speaking generics are instanciated at first usage. And this alone wouldn't need a specificaiton, But nim doesn't order independent. The order in which functions are declared matters. And the amount of converters and functions and types known to the compiler at the time a generic is instanciated affects what the generic will eventually resolve to. It might be that the generic instanciates with a converter function too early. At a later instanciation time the generic might have found a better overload without conversion.

@disruptek
Copy link
Contributor

Maybe just a wtf directory, separated into tests which should fail but pass, and vice-versa.

@haxscramper
Copy link
Collaborator Author

haxscramper commented Nov 3, 2021

min/max value ranges for enums

type
  c_git_diff_option_t* = enum
    c_GIT_DIFF_NORMAL                          = 0 shl 0
    c_GIT_DIFF_IGNORE_BLANK_LINES              = 1 shl 31

^ ok for nim c and nim cpp, but fails for js Error: invalid order in enum 'c_GIT_DIFF_IGNORE_BLANK_LINES'

bors bot added a commit that referenced this issue Nov 3, 2021
28: Language spec tests r=alaviss a=haxscramper

Full spec todo - #10

Co-authored-by: haxscramper <haxscramper@gmail.com>
@ringabout
Copy link
Contributor

Error: invalid order in enum 'c_GIT_DIFF_IGNORE_BLANK_LINES'

int is 32 bit for JS VM/backend; this works

type
  c_git_diff_option_t* = enum
    c_GIT_DIFF_NORMAL                          = 0 shl 0
    c_GIT_DIFF_IGNORE_BLANK_LINES              = 1'i64 shl 31

@saem
Copy link
Collaborator

saem commented Nov 4, 2021

Thanks, @xflywind

@saem
Copy link
Collaborator

saem commented Nov 4, 2021

I'm poking at pragmas as part of nkError work, please add as tests.

For reference the nkRrror/pragma work is here: d2368ef#diff-1d1109c3f7bc16cf4e770fe792e9073bff67591721f3c72b96cb4b4a3b76bd88R806

@haxscramper
Copy link
Collaborator Author

I think it would be a good idea to also specify how compiler reads the environment - nim.cfg, project.nim.cfg, in which order, how configuration entries override each other and so on.

@haxscramper
Copy link
Collaborator Author

Maybe just a wtf directory, separated into tests which should fail but pass, and vice-versa.

https://github.com/nim-lang/Nim/labels/accepts%20invalid as a start

@haxscramper
Copy link
Collaborator Author

Specify and provide examples of where each defect is raised, and if possible - how it can be prevented (like cast to unchecked assign, maybe there are some extra features like these that I don't know of).

@haxscramper
Copy link
Collaborator Author

haxscramper commented Nov 7, 2021

Language specification should include specific explanation of some basic concepts that are considered as "no need to explain, obvious to everyone". If anything, this could be used as a basis for introducing newcomers to a fundamentally new concepts that might not exist in their language.

  • compile time
  • side effect
  • typed and untyped macros - this one is tricky, but the whole concept of semantic analysis is not something an average user probably familiar with, so it warrants special attention.

@saem
Copy link
Collaborator

saem commented Nov 7, 2021

Fundamental concepts that aren't or are poorly described:

  • errors
  • type inference
  • resolution, dispatch, and overloads
  • module resolution
  • type tagging, untagging, and comparison
  • differences between backends
  • core defines and the environment

haxscramper added a commit to haxscramper/hack that referenced this issue Nov 10, 2021
@haxscramper
Copy link
Collaborator Author

haxscramper commented Nov 10, 2021

From the tests above -

  • OrderedTable is not an object for some reason
  • Putting explicit generic parameters in load in the roundTrip leads to compiler thinking that seq is an enum and an object at the same time
  • F/Y/Z is not an object, but JsonNode is when doing overload, at the same time F is object yields true
  • F is object and F is object | tuple | ref object but F isnot Object where type Object = object | tuple | ref object

@haxscramper
Copy link
Collaborator Author

Split into smaller todo lists

bors bot added a commit that referenced this issue Nov 21, 2021
66: [DOC] Link to the spec project instead of #10 r=saem a=haxscramper



Co-authored-by: haxscramper <haxscramper@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

5 participants