[racket] Compiler for despair 1

From: Gustavo Massaccesi (gustavo at oma.org.ar)
Date: Sat Nov 8 08:30:42 EST 2014

I'd like to propose a stronger challenge. Try to write this compiler
following the style guide in
http://docs.racket-lang.org/style/Textual_Matters.html . In the
current implementation, some of the indentation is not standard and
the functions and variables names should be longer.

The code is difficult to understand with one letter variables.

Some functions have too many arguments, so using complete words would
break the 30 chars per line rule. You can try at least to use three or
four letters names for the arguments. (Many parts of the internal
Racket code use "str" or "stx" as the name of the argument of the
function instead of "string" or "syntax".)

Perhaps you can put both versions in github and get a few ideas/patches.


Also, I have some improvements for prs. You can replace for/list with
map and use string-join with the default joiner. So you get:

(define-for-syntax (prs xpr)
  (with-input-from-string
    (string-join
     (map fix (brk xpr)))
    read))

But I prefer a slightly different version: (It looks better, but I
don't know why. Perhaps because it looks more functional.)

(define-for-syntax (prs xpr)
  (read
   (open-input-string
    (string-join
     (map fix (brk xpr))))))

(Additionally, you can put read and open-input-string in the same line
if you don't mind breaking the guidelines.)

Gustavo

On Wed, Nov 5, 2014 at 5:06 PM, Eduardo Costa <edu500ac at gmail.com> wrote:
> Hi, Gustavo.
>
> Thank you for your suggestion. I incorporated it in my implementation and
> sent the resulting code to Junia Magellan, who published
> it in her page about DSL. Of course, I gave you full credit for the hack.
> Here is Junia's page address:
>
> http://strues.org
>
>
>
> 2014-11-03 9:21 GMT-02:00 Gustavo Massaccesi <gustavo at oma.org.ar>:
>
>>  Do you have a link to a complete reference of this language? I
>> couldn't find it with Google.
>>
>> Some ideas to gain a few lines:
>>
>>
>> ** Replace the ":" operator with "#%app"
>>
>> (http://docs.racket-lang.org/reference/application.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._~23~25app%29%29
>> )
>>
>> In file pref.rkt replace
>> Line 14:
>> -     [(:) 7]
>> +     [(#%app) 7]
>> Line 31:
>> -    (p (cons ': e) o a)]
>> +    (p (cons '#%app e) o a)]
>>
>> And now you can simplify "f" to
>> (define-for-syntax (f c y x r)
>>   (cons (list c y x) r)))
>> Or perhaps inline it.
>> If the ":" may appear explicitly in the source code, you must add a
>> line in despair.rkt to replace ":" by "#%app".
>>
>>
>> ** Rewrite w? with another implicit lambda:
>> (define-for-syntax ((w? e) x)
>>    (> (w (car e))(w x)))
>> (I prefer the name "w>?".)
>>
>>
>> ** Rewrite pre:
>> (define-for-syntax(pre x)
>>   (if (not (pair? x)) x
>>     (p (cdr x) '()
>>       (list (pre (car x))) ))))
>> (This is almost cheating and is a bad code style, but you can gain 1 LOC.)
>>
>> Gustavo
>>
>> On Fri, Oct 31, 2014 at 11:47 PM, Eduardo Costa <edu500ac at gmail.com>
>> wrote:
>> > I tried to implement despair 1 in Racket, and have a few questions about
>> > my
>> > solution. By the way, I am not a student trying to get my homework done
>> > by
>> > somebody else.
>> >
>> > The restrictions for despair 1 are:
>> >
>> > 1 - The whole implementation must have less than 100 lines. Comments and
>> > tests don't count as lines
>> >
>> > 2- No line should be longer than 30 chars
>> >
>> > 3- No function should have more than 12 lines
>> >
>> > 4- A blank line after each function is mandatory
>> >
>> > 5- The implementation can be done in any language and must pass despair
>> > stOne.dsp
>> >
>> >
>> > Here are two functions from stOne.dsp:
>> >
>> > def (fib n (f-1 1) (f-2 1))
>> >   if [n<2] then f-1
>> >   else (fib [n - 1]
>> >         [f-1+f-2] f-1)
>> >   end
>> > end
>> >
>> > def (fibo n)
>> >  let loop
>> >    local (i n) (a 1) (b 1)//
>> >    cond
>> >     ift [i<2] then a//
>> >     otherwise
>> >       (loop [i - 1] [a+b] a)//
>> >    end
>> >  end
>> > end
>> >
>> > My question is about the Implementation of the infix to prefix function.
>> > My
>> > pref macro consumed almost half of the allowed number of lines. The
>> > algorithm used is described in Lisp by Winston and Horn, third edition,
>> > chapter 32. Is there a way to reduce the size of the pref macro (perhaps
>> > changing the algorithm)?
>> >
>> > In order to keep the (p e o a) function in the 12 lines limit, I was
>> > forced
>> > to move the w? predicate out of (p e o a). Since Racket match requires
>> > one
>> > parameter predicates, (w? e) returns a closure. My question is: Does
>> > Racket
>> > rebuilds the closure for each iteration of (p e o a)? If this is the
>> > case,
>> > the algorithm is very inefficient. I hope that Racket somehow builds the
>> > closure just once. Thanks in advance for any piece of information or
>> > suggestion on how to improve the program.
>> >
>> > Special thanks to any member of this group who could tell me how to
>> > transform my implementation into  #lang despair (no need to maintain the
>> > restriction of 100 lines). By the way, I tried to understand the chapter
>> > about building new language in the Racket documentation, but it still
>> > puzzles me.
>> >
>> > ;File: pref.rkt
>> > #lang racket
>> > (require (for-syntax racket))
>> > (provide pref)
>> >
>> > (define-for-syntax(w s)
>> >  (case s ;10 lines
>> >   [(or) 1] [(and) 2]
>> >   [(< = > >= <=) 3]
>> >   [(+ -) 4] [(* /) 5]
>> >   [(^) 6][(:) 7]
>> >   [else 9]))
>> >
>> > (define-for-syntax(:? x)
>> >   (= (w x) 9))
>> >
>> >  (define-for-syntax(w? e)
>> >    (lambda(x)
>> >      (> (w (car e))(w x))))
>> >
>> > (define-for-syntax(pre x)
>> >   (if (pair? x)
>> >     (p (cdr x) '()
>> >        (list (pre (car x))) )
>> >       x))
>> >
>> > (define-for-syntax(p e o a)
>> >  (match/values (values e o a)
>> >   [('() '() (cons x _)) x]
>> >   [[(cons (? :?) _) _ _ ]
>> >    (p (cons ': e) o a)]
>> >   [[(list-rest x y es) (or
>> >       '()  (cons (? (w? e))_))_]
>> >    (p es (cons x o)
>> >       (cons (pre y) a))]
>> >   [[_ (cons c os)
>> >       (list-rest x y r)]
>> >    (p e os (f c y x r) )]))
>> >
>> > (define-for-syntax(f c y x r)
>> >   (if (equal? ': c)
>> >       (cons (list y x) r)
>> >       (cons (list c y x) r)))
>> >
>> > (define-syntax(pref s)
>> >  (datum->syntax s (pre
>> >    (cdr (syntax->datum s)))))
>> >
>> >
>> > ;File: despair.rkt
>> > #lang racket
>> > (require (for-syntax racket))
>> > (require "inf.rkt")
>> >
>> > (define-for-syntax(brk x)
>> >  (regexp-match*
>> >   (regexp (~a "\"[^\"]+\"|"
>> >       "#t|#f|[a-z]+->[a-z]+|"
>> >       "[a-z?A-Z~-]+[0-9-]*|"
>> >       "-?[0-9]+\\.?[0-9]*|"
>> >       "<=|>=|//|"
>> >       "[][()'&;*:<>=,+/^-]")) x))
>> >
>> > (define-for-syntax (fix x)
>> >   (match x
>> >     ["def" "(define"]
>> >     ["if" "(if"]
>> >     ["then" ""]
>> >     ["else" ""]
>> >     ["end" ")" ]
>> >     ["//" ")"]
>> >     ["cond" "(cond"]
>> >     ["ift" "("]
>> >     ["let" "(let"]
>> >     ["local" "("]
>> >     ["otherwise" "(else"]
>> >     ["[" "(pref"]
>> >     ["]" ")"]
>> >     [head head]))
>> >
>> > (define-for-syntax (prs xpr)
>> >   (with-input-from-string
>> >     (string-join (for/list
>> >        [(token (brk xpr))]
>> >        (fix token)) " ")
>> >     (λ() (read)) ))
>> >
>> > (define-for-syntax(tkn stx)
>> >   (~a "(" (file->string (cadr
>> >      (syntax->datum stx)))
>> >       ")"))
>> >
>> > (define-syntax(ld stx)
>> >  (datum->syntax stx
>> >    (cons 'begin
>> >      (prs (tkn stx)) )))
>> >
>> > (ld "stOne.dsp")
>> > (fibo 5)
>> >
>> > ____________________
>> >   Racket Users list:
>> >   http://lists.racket-lang.org/users
>> >
>
>


Posted on the users mailing list.