samrushing/irken-compiler

need (attr x rec) .. which is equivalent to rec.x

jeske opened this issue · 4 comments

jeske commented

Irken does not like the form (fn 1).x, when x returns a record {x=1}.

If I instead store (fn 1) in a variable, then I can do variable.x just fine.

(include "lib/basis.scm")

(define (a r) {x=r})
(define b (a 1))

(printf (int b.x))
; (printf (int (a 10).x)) ; this produces a compile error

This is an issue with the the lisp reader. By doing it 'properly' I have to special-case the symbol ... Using . on anything that's not a symbol is pushing into that "too far from lisp" territory, since it's a postfix operator. i.e., it's likely to horrify people coming from the lisp world. They will vastly prefer something like this: (attr x (fn 1)). I think on my working branch I have an %%attr special form for exactly this.

jeske commented

I'm fine with (attr x (fn 1))

jeske commented

Here is another use-case for (attr x rec) equivlant to rec.x:

One way to code optional named arguments is with macros. However, in the macro below, the rec let-variable is not hygenic. In order to make it hygenic, we need to use $rec to define it in my-fn and then pass it's hygenic name to the my-fn-args macro, which would then use (attr optional rec) instead of rec.optional:

this macro hygene can also be fixed by patch 51 supporting macro argument replacements in record field expressions and attribute expression sources. Making the (attr optional rec) syntax unnecessary.

(define (my-fn-inner a rest) (format a rest.optional))
(defmacro my-fn-args
  (my-fn-args <optional=> opt) -> (set! rec.optional opt)
  (my-fn-args name value rest ...) -> 
       (begin (my-fn-args name value) (my-fn-args rest ...)))

(defmacro my-fn
  (my-fn a rest ...) ->
     (let ((rec {optional="Missing"}))
        (my-fn-args rec rest ...)
        (my-fn-inner a rec)))

(my-fn "1" optional= "Present")

With (attr x rec) this macro would be written hygenically as:

(include "lib/basis.scm")

(define (my-fn-inner a rest) (format a rest.optional))
(defmacro my-fn-args
  (my-fn-args rec <optional=> opt) -> (set! (attr optional rec) opt)
  (my-fn-args rec name value rest ...) -> 
      (begin (my-fn-args rec name value) (my-fn-args rec rest ...)))

(defmacro my-fn
  (my-fn a rest ...) ->
     (let (($rec {optional="Missing"}))
        (my-fn-args $rec rest ...)
        (my-fn-inner a $rec)))

(my-fn "1" optional= "Present")

It's possible that what you were trying to do here can now be done given the recent changes in ada1d42.
Look carefully at lib/enum.scm - it uses a single macro expression to generate a new datatype and related tables and functions. In addition to the requested %%attr, there are now %%constructor, %%symbol, and %splice which also help generated code.