ds26gte / pyret-lang

The Pyret language.
Other
2 stars 0 forks source link

Cond: last true branch evaluated instead of first #21

Closed Emmay closed 8 years ago

Emmay commented 8 years ago

Arrow keys aren't recognized in programs, including this basic one:

(define START (text "press a button" 60 "purple")) (define (draw-world word) (put-image word 250 150 (rectangle 500 300 "outline" "black"))) (define (keypress n key) (cond [(string=? key "up") (text "you pressed up" 60 "blue")] [(string=? key "down") (text "you pressed down" 60 "orange")] [(string=? key "left") (text "you pressed left" 60 "red")] [(string=? key "right") (text "you pressed right" 60 "purple")] [(string=? key "p") (text "you pressed p" 60 "green")] [(string=? key " ") (text "you pressed the spacebar" 40 "blue")] [else (text "oops" 60 "yellow")]))

(big-bang START (on-redraw draw-world) (on-key keypress))

schanzer commented 8 years ago

@Emmay , GREAT catch! I've been investigating, and you'll want to rename this one after you read this...it's not a key problem at all. :)

It looks like Spyret is changing the semantics of Cond, such that the last true branch is taken instead of the first. Getting rid of the else clause above will make the whole thing work (as long as you use an arrow key, p, or space).

Here's my diagnosis: When an else clause is present, the penultimate clause is somehow hoisted to the top of the decision tree. If the test for THAT clause is true, the result will be evaluated. Otherwise, execution drops right to the else clause (other clauses be damned).

Possibly the fault of https://github.com/ds26gte/code.pyret.org/blob/96dda7c7bdb6c2879d9a62e2c0ab36b6c52bb42a/src/web/js/spyret-parse.js#L7927-L7936

schanzer commented 8 years ago

Here's a fun test case. The only clause that works as-expected is whatever comes just before the else.

(define (foo x) (cond [(< x 10) "less than 10"] ; will be ignored [(< x 8) "less than 8"] ; will be ignored [(< x 6) "less than 6"] ; this one works! [else "too small"]))

(check-expect (foo 9) "less than 10") (check-expect (foo 7) "less than 8") (check-expect (foo 6) "less than 8") (check-expect (foo 5) "less than 6") (check-expect (foo 4) "too small") (check-expect (foo 3) "too small") (check-expect (foo 2) "too small")

Emmay commented 8 years ago

Weird! Renamed issue.

ds26gte commented 8 years ago

Fixed in ds26gte/code.pyret.org@0f2efb2.

(There was also another bug, the bar terminal wasn't being prepended to the otherwise terminal.)

A suggested test is a slight modification of Emu's (his 2nd and 3rd clauses are deadcode, and the else-clause states the opposite of what's happening):

(define (foo x)
  (cond
    [(> x 10) "greater than 10"]
    [(> x 8) "greater than 8"]
    [(> x 6) "greater than 6"]
    [else "too small"]))
schanzer commented 8 years ago

Awesome. Confirmed fixed. @Emmay or @ds26gte , can you close?