justinethier / cyclone

:cyclone: A brand-new compiler that allows practical application development using R7RS Scheme. We provide modern features and a stable system capable of generating fast native binaries.
http://justinethier.github.io/cyclone/
MIT License
823 stars 42 forks source link

error in icyc's order of processing? #489

Closed Goldipox closed 2 years ago

Goldipox commented 2 years ago
Contemporary amd64 laptop, up-to-date Arch-based Linux, fresh Cyclone
install, everything seems ok.  I just found a bug in icyc:

  $ icyc -s
  cyclone> (begin (define-syntax foo (syntax-rules () ((foo) 123))) (foo))
  Error: Unknown procedure type -- EXECUTE-APPLICATION: (macro (lambda (expr$2$11$17 rename$3$12$18 compare$4$13$19) (car ((lambda (tmp$14$15$20) (if tmp$14$15$20 tmp$14$15$20 (cons (error/loc "no expansion for" expr$2$11$17) #f))) ((lambda (v.1$10$16$21) (if (null? v.1$10$16$21) (cons 123 #f) #f)) (cdr expr$2$11$17)))))) 
  cyclone> (foo)
  123
  cyclone> 

The code works in icyc without the begin wrapper, and works as-is when
compiled by cyclone and under many other Schemes.  The macro isn't being
compiled in time for the macro call following it in the begin, but it's
ready for the next top-level expression.

Nice Scheme.  Thoughtful text logo.  I don't like the invisible void.

          oldipo
         g      x
Regards,   Andy  @
         m      m
          oc.lia
justinethier commented 2 years ago

Thanks for trying Cyclone and for the report @Goldipox! Let me look into this.

Just curious, how are you used to void being handled? Is this just personal preference?

justinethier commented 2 years ago

Modified eval to guarantee sub-expressions of a begin are evaluated in order.

Unfortunately map is not guaranteed to evaluate its arguments in any given order because it could be optimized into another function such as Cyc-map-loop-1. Instead we just call that optimized function directly as a more general map is not required here and Cyc-map-loop-1 is guaranteed to process its argument list in a predicable order.

Anyway, this is good to go now on our main branch. Thanks again for the report @Goldipox !

Goldipox commented 2 years ago

still workin on response re void thinking  --Ag

Goldipox commented 2 years ago

Just curious, how are you used to void being handled? Is this just personal preference?

 

;; u(nless-)s(pecified-)o(therwise)

 

Call a spade a spade, I prefer a name based on void.  Keep void voidy, it doesn't even need an eval method, which helps finding errors.  I'm friendly with Oaklisp's Barak Pearlmutter, who sold me on fanning out void instances to indicate origin.  In undefined.oak, attached, you can safely ignore make-undefined-variable-value, it's just a forward reference placeholder.

 

I'm SRFIing "Consistent Conditionals".  An inductive if compatible with cond as in Arc, (if) is de facto conditional failure.  Failing conditionals yield false uso, see Emacs guts for compelling use-cases.  Empty clause bodies yield truthful uso (preferably void's incidental truth and not canonical #t), a nice contrast to failure is false, (else) is de facto success, factored with the form begin/if.  Lots more, very heavy with rationales.

 

Oaklisp uses traditional #<...> notation, which I dislike because it's rarely parseable, much less readable.  Oaklisp also provides nice readable

[...]  notation.  So, on fanning it out, we've generally got: #[void],

canonical; #[void conditional], success not failure; #[void uninitialized];

[void value], when nothing can be justified, like (begin) (got other

examples?); got other categories?  When all usage is delegated, canonical can be left to the programmer, as in Oaklisp.  Oh, and for an implementation with a single void instance, hrmm, well, it's an important concept, maybe follow #t's lead with #v?

 

It's unfortunate how many implementors decline, with void, the open invitation of explicitly unspecified behavior.  The void reflex.  Oaklisp usually specifies such things, eg set!, define, and print yield the value.

 

As to invisible void the symbol ok...  I think default interfaces should be straightforward--you can't second-guess all of the programmers all of the time.  That RnRS has declined to specify failing conditionals for over five decades doesn't matter, some git could come along any day (Real Soon Now, sigh) and clean 'em up.

 

Cyclone fares well vs my srfi:

Criminy, enough for now, Andy.

 

Want to see how "fun" this is?  Here's my first look at the do form, 42 Schemes vs (do () (11) 22).  Using if as in RnRS's formals, it should yield like if failure: 23/42 = 55% Schemes.  Similarly using cond with a guarded clause, it should yield the truthful guard: 7/42 = 17%.  And some reflex action, um, the nullier Schemes and a couple less-consistent Schemes showing a void reflex elsehwere, 6/42 = 14%.  That leaves 6 to explain.  5, ledger error with Kawa.  The rest aren't significant enough to change anyone's mind or interesting enough to inspire me to dig.  Now, I'll ponder whether (do () (11 => recipient) 22) is worth pursuing.  Yielding (if) is "faster", yielding the truthful guard is "nicer", it would be nice to have control over this.

 

Regards, Andy Gaynor, @.***

 

Goldipox commented 2 years ago

Did you find that void stuff interesting?

I'd like to hear your mind on the matter.

 

Regards, Andy

justinethier commented 2 years ago

Hmm. Do you have a list of what the void behavior is on various Schemes?

Goldipox commented 2 years ago

Hmm. Do you have a list of what the void behavior is on various Schemes?

 

I have 42 Schemes at hand and fairly up-to-date.  I only excluded one, already chock full of screwy when I noticed that void was a distinct false value, b'bye.  Void was a common probe result, so I did a few probes and saved its denotations, but nothing exhaustive.  It's interesting, though.

 

Given the nature of the beast, few Schemes do much with void.  Oaklisp's treatment is "elaborate".  Loko's denotation includes an address, something I haven't peek at yet.  Maybe I can make a couple good guess'ums.  How many repls suppress a single void result?  It's better to suppress reporting void than to obscure its denotation.  Of the 32/42 Schemes with void evident, 23/32 suppress reporting void, but the 9 that print void results are mostly big names.  The formality of the context warrants precision, but I understand the intended nicety and insulation from what's often undefined.  At least this slope doesn't seem all that slippery.

 

How do repls handle multiple values?  Of the 32/42 Schemes with non-broken multiple values, 5 repls print only 1 value or have other breakage (1 big name).  Of the remaining 27, 7 simply print a multiple-values object with all results.  Of the 20 that enumerate multiple results, 8 suppress void, mostly big names.  This I don't understand.  Multiple values is a sequence, count and position are relevant to nontrivial instances.  This suppression corrupts the sequence.

 

Another 13 bug reports for the heap.  Isn't this obvious?  I feel like I'm crazy.  I write the words but hardly believe them.

  Did you have anything specific in mind?  The survey results are a train-wreck-at-an-airliner-crash-sight mess, and I'd prefer not to distribute them before publishing.  For implementors and the like, though, I'd be happy

to share a few results or make some specific probes.

Regards, Andy