Mostrando postagens com marcador javascript. Mostrar todas as postagens
Mostrando postagens com marcador javascript. Mostrar todas as postagens

sábado, 23 de janeiro de 2010

jsmin para Chicken Scheme

Há pouco fiz o commit no repositório de extensões do sistema Chicken de uma tradução para Scheme do código C do jsmin, de Douglas Crockford.

A extensão fornece apenas dois procedimentos: jsmin-string e jsmin-file, as quais compactam o código javascript considerando como entrada, respectivamente, uma string e um arquivo.

O código Scheme traduzido de código C (sem uso da FFI) não é dos mais bonitos :-), pois a tradução foi feita praticamente linha-a-linha (inclusive mantendo os returns, implementados através de call/cc).

quinta-feira, 8 de maio de 2008

Apresentações em Scheme

Não sou um especialista em apresentações, mas de vez em quando surgem algumas para eu fazer. Não tenho o hábito de usar softwares para edição de apresentações como o Impress do Openoffice.org (é uma questão de preferência pessoal como usuário -- nada contra o Openoffice.org). Sobretudo, faço as apresentações com o visual mais simples possível, normalmente fundo branco com letras pretas, como uma página de livro tradicional.

Durante um bom tempo fui usuário de LaTeX (cheguei a fazer uma classe para apresentações -- Pauerpoint), mas algumas coisas são desnecessariamente difíceis de se fazer em LaTeX.

Então me ocorreu a idéia de implementar algo em Scheme para fazer apresentações. Com o uso de algumas coisas prontas em CSS e Javascript, a implementação em Scheme é surpreendentemente simples:

(use web-scheme)

(define (slide title-text . contents)
(div 'class "slide"
(h1 title-text)
(string-intersperse contents)))

(define (cover title-text . contents)
(div 'class "slide cover"
(h1 title-text)
(string-intersperse contents)))

(define (presentation . slides)
(ws:page
(string-intersperse slides)
additional-headers: (string-append
(link 'rel "stylesheet"
'type "text/css"
'media "screen, projection"
'href "show.css")
(script 'src "slidy.js"
'type "text/javascript"))))

O código acima, em Chicken Scheme, mostra as três funções para a montagem de uma apresentação. As partes de CSS e Javascript são do HTML Slidy.

Para criar uma apresentação, basta fazer algo como:

(presentation
(cover "Minha capa")
(slide "Introdução")
(slide "Fim"))

Para gerar o código HTML, que pode ser visualizado em qualquer browser, executo:

$ web-scheme2html minha-apresentacao.scm > minha-apresentacao.html

web-scheme2html é um script que acompanha a extensão web-scheme de Chicken.

Em http://g3pd.ucpel.tche.br/~mario/misc/upgrade-v2 está um exemplo de apresentação que fiz sobre programação para a Web com Scheme (boa parte da apresentação é sobre o básico da linguagem). O código fonte da apresentação está em http://g3pd.ucpel.tche.br/~mario/misc/upgrade-v2/index.ws.

terça-feira, 6 de maio de 2008

Compilador ingênuo de Scheme para Javascript

Por curiosidade, há algum tempo tentei ver como seria fazer um compilador simples de Scheme para Javascript. Obviamente, um compilador "de verdade" não é uma tarefa fácil, embora haja esforços nesta direção.

De qualquer forma, é impressionante o que dá para fazer com algumas poucas linhas de código. :-)

Várias formas básicas de Scheme não estão implementadas: cond, begin, call/cc e muitas outras.

#!/usr/bin/csi -script

(use (srfi 1))

(define (infix-op op args)
(string-intersperse
(map ->string (map scm->js args)) (->string op)))

(define (mapconcat elts #!optional sep)
(string-intersperse (map ->string elts) (or sep "")))

(define (scm-body->js body)
(let ((body-butlast (butlast body))
(last-expr (last body)))
(conc (mapconcat (map scm->js body-butlast) ";") ";"
"return " (scm->js last-expr) ";")))

(define (scm->js expr)
(if (atom? expr)
(cond ((string? expr)
(conc "'" expr "'"))
((boolean? expr)
(if (eq? expr '#t) "true" "false"))
(else expr))
(case (car expr)
((if) (let ((condition (cadr expr))
(branch1 (caddr expr))
(branch2 (and (= 4 (length expr))
(cadddr expr))))
(conc "(function(){if(" (scm->js condition)
"){return(" (scm->js branch1) ");}"
(if branch2
(conc "else{return("
(scm->js branch2) ");}")
"")
"})();")))
((return) (conc "return(" (scm->js (cadr expr))
");"))
((lambda)
(conc "function"
(if (null? (cadr expr))
"()"
(conc "(" (mapconcat (cadr expr) ",")
")")) "{"
(scm-body->js (cddr expr)) "}"))
((define) (conc ";var " (cadr expr) "="
(scm->js (caddr expr)) ";"))
((+ - * / < >) (infix-op (car expr) (cdr expr)))
((=) (infix-op '== (cdr expr)))
((or) (infix-op "||" (cdr expr)))
((and) (infix-op "&&" (cdr expr)))
((let) (conc "(function(){"
(string-intersperse
(map (lambda (binding)
(conc "var " (car binding) "="
(scm->js (cadr binding))
";"))
(cadr expr)))
(scm-body->js (cddr expr))
"})()"))
((let*) (scm->js (macroexpand expr)))
(else (conc (car expr) "("
(string-intersperse
(map ->string
(map scm->js (cdr expr)))
",") ")")))))

(define (js exprs)
(string-intersperse (map scm->js exprs) ""))

(print (js (read-file (car (command-line-arguments)))))

Alguns exemplos "práticos" estão a seguir. scm2js.scm é o compilador, implementado em Chicken Scheme; js é um interpretador de Javascript que pode ser executado na linha de comando.

Obs.: o código Javascript gerado é bastante indigesto:

$ ./scm2js.scm ex1.scm

;var fatorial=function(n){;return (function(){if(n<1){return(1);}else{return(n*fatorial(n-1));}})();;};print(fatorial(4))
$ cat ex1.scm

(define fatorial
(lambda (n)
(if (< n 1)
1
(* n (fatorial (- n 1))))))

(print (fatorial 4))

$ ./scm2js.scm ex1.scm | js
24

$ cat ex2.scm

(define a (lambda (n)
(print "aqui")
n))
(print (a 6))

$ ./scm2js.scm ex2.scm | js
aqui
6

$ cat ex3.scm

(define x (if #t "ok" "false"))
(print x)

 $ ./scm2js.scm ex3.scm | js
ok

$ cat ex4.scm

(define func
(lambda (a b c d)
(let* ((a (+ b c d))
(dif (- a b c d)))
(+ a dif))))

(print (func 1 2 3 4))

$ ./scm2js.scm ex4.scm | js
9