sasagawa888 / eisl

ISLisp interpreter/compiler
Other
281 stars 23 forks source link

Bug report: defmodule doesn't permit class definitions #198

Closed wasamasa closed 2 years ago

wasamasa commented 2 years ago

Suppose I write the following test.lsp and run it with eisl -l test.lsp:

(defmodule util

(defclass <rect> ()
  ((size :accessor rect-size
         :initarg size)))

)

I get the following error:

Definition must be on top level at DEFCLASS (UTIL::<RECT> NIL ((UTIL::SIZE UTIL:::ACCESSOR UTIL::RECT-SIZE UTIL:::INITARG UTIL::SIZE)))
sasagawa888 commented 2 years ago

OK I will improve. Thank you.

sasagawa888 commented 2 years ago

I improved.

wasamasa commented 2 years ago

Alright, it does permit class definitions now, but how do I use the accessors now?

edit: Wild idea: Maybe it would be better to allow declaring what identifiers to export. Something like (declare (visible rect-size)). It could be used for functions, accessors, macros, ...

sasagawa888 commented 2 years ago

Write it like this:

(defmodule util

    (defclass <rect> () ((size :accessor rect-size :initarg size)))

    (defpublic foo ()
        (create (class <rect>) 'util::size 999) )

    (defpublic bar (x)
        (rect-size x) )

)

> (load "tests/bug.lsp")
T
> (defglobal a (foo))
A
> (bar a)
999
> 
wasamasa commented 2 years ago

Ok, so you'd need to define a wrapper function. A function to define a public alias would be convenient. This concept is known as reexport in other programming languages.

edit:

sasagawa888 commented 2 years ago

Why does the module name appear in the create call?

This is because the module-name :: is added to the symbol name in defmodule.

I cannot name the wrapper function the same as the original one because I otherwise run into a stack overflow due to mutual >recursion (should I open an issue for this? I'm used to Emacs and friends catching call stack overflows)

I would appreciate it if you could show me a concrete example of mutual recursion.

wasamasa commented 2 years ago
(defmodule util

    (defclass <rect> () ((size :accessor rect-size :initarg size)))

    (defpublic foo ()
        (create (class <rect>) 'util::size 999) )

    (defpublic rect-size (x)
        (rect-size x) )
)
> (load "tests/bug.lsp")
T
> (defglobal a (foo))
A
> (rect-size a)
zsh: segmentation fault (core dumped)  eisl -r
sasagawa888 commented 2 years ago

Thanks for the code example. I considered.

The code defines defclass inside the module. I think that this is the purpose of wanting to hide the generated class and instance. I don't feel the need to dare to expose the accessor to the outside.

You can use accessors in the following ways if you need them:

> (defglobal a (foo))
A
> (util::rect-size a)
999
>