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

Multiple pragmas break recursive types #1

Open
omentic opened this issue Sep 22, 2023 · 1 comment
Open

Multiple pragmas break recursive types #1

omentic opened this issue Sep 22, 2023 · 1 comment

Comments

@omentic
Copy link

omentic commented Sep 22, 2023

Hi metagn, this is a really cool library. I ran into a little bit of an issue. The following code fails to compile:

import skinsuit

type Expr {.sum, equals.} = ref object
  case kind: _
  of Name: _: string
  of Int: _: int
  of App:
    param: Expr
    fn: Expr
  of Func: _: tuple[a: string, b: Expr]
  of Plus: _: tuple[a, b: Expr]
  of Minus: _: tuple[a, b: Expr]

The problem seems to be that the sum pragma expands to

type
    ExprKind = enum
      Name, Int, App, Func, Plus, Minus
    ExprName = object _: string
    ExprInt = object _: int
    ExprApp = object
    
    ExprFunc = object _: tuple[a: string, b: Expr]
    ExprPlus = object _: tuple[a, b: Expr]
    ExprMinus = object _: tuple[a, b: Expr]
    Expr {.equals.} = ref object

, which is fine, but when the equals pragma expands it places Expr in a separate type block, which breaks things.

type
    Expr {..} = ref object
    
  proc ==(a, b: Expr): bool {.used, noSideEffect.} =
    ...
@metagn
Copy link
Owner

metagn commented Sep 22, 2023

This is a Nim limitation with type section pragma macros. I recently made it so you can use equals in statement form, so you should be able to do this instead:

import skinsuit

type Expr {.sum.} = ref object
  case kind: _
  of Name: _: string
  of Int: _: int
  of App:
    param: Expr
    fn: Expr
  of Func: _: tuple[a: string, b: Expr]
  of Plus: _: tuple[a, b: Expr]
  of Minus: _: tuple[a, b: Expr]

equals Expr
# or:
equals *Expr # exported

Might document this limitation later so keeping open

Edit: Also, for mutually recursive types you have to add forward declarations before the equals calls, like:

proc `==`*(a, b: Expr): bool {.noSideEffect.}

Might also add equalsForwardDecl to do this

metagn added a commit that referenced this issue Sep 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants