This commit is contained in:
2026-06-08 13:21:57 +02:00
parent 823130e3ac
commit 8bee76328b
23 changed files with 734 additions and 382 deletions
+35 -6
View File
@@ -1,9 +1,38 @@
let title = document.getElementById("title");
title.innerHTML = "Hello from js-maker";
title.addEventListener("click", function (evt) {
// exercise01
function replaceParagraphHtml(html) {
{
console.log("clicked");
return true;
const p3 = document.querySelector("p");
{
let p = p3;
p.innerHTML = html;
return p.innerHTML;
}
}
}
});
// exercise02
function addSourceLink() {
{
const p8 = document.querySelector("p");
{
let p = p8;
p.insertAdjacentHTML("afterend", "<a href=\"https://forcemipsum.com/\">Source</a>");
return true;
}
}
}
// exercise03
function paragraphText() {
{
const p15 = document.querySelector("p");
{
let p = p15;
return p.textContent;
}
}
}
+43 -10
View File
@@ -2,17 +2,50 @@
(require "../main.rkt")
(provide generated-js)
(provide exercise01
exercise02
exercise03
all-dom-exercises
show-dom-exercises)
(define generated-js
;; These demos intentionally use only the compact js-maker 3 surface language:
;; define, let/let*, return, set!, send, js-dot and ordinary function calls.
;; Exercise 01: replace the paragraph HTML.
(define exercise01
(js
(define title (send document getElementById "title"))
(set! (js-dot title innerHTML) "Hello from js-maker")
(send title addEventListener "click"
(lambda (evt)
(begin
(send console log "clicked")
(return #t))))))
(define (replaceParagraphHtml html)
(let ([p (send document querySelector "p")])
(set! (js-dot p innerHTML) html)
(return (js-dot p innerHTML))))))
;; Exercise 02: add a source link after the paragraph tag.
(define exercise02
(js
(define (addSourceLink)
(let ([p (send document querySelector "p")])
(send p insertAdjacentHTML
"afterend"
"<a href=\"https://forcemipsum.com/\">Source</a>")
(return #t)))))
;; Exercise 03: read text content from the first paragraph.
(define exercise03
(js
(define (paragraphText)
(let ([p (send document querySelector "p")])
(return (js-dot p textContent))))))
(define all-dom-exercises
`((exercise01 . ,exercise01)
(exercise02 . ,exercise02)
(exercise03 . ,exercise03)))
(define (show-dom-exercises)
(for ([entry (in-list all-dom-exercises)])
(displayln (format "// ~a" (car entry)))
(displayln (cdr entry))
(newline)))
(module+ main
(display generated-js))
(show-dom-exercises))
+50 -12
View File
@@ -1,25 +1,63 @@
let answer = 42;
function square(x) {
return x * x;
// random-number
function randomBetween1And5() {
return Math.floor(Math.random() * 5) + 1;
}
function sum_to(n) {
// unique-values
function uniqueValues(xs) {
return Array.from(new Set(xs));
}
// array-at
function arrayAt(xs, i) {
return xs[i];
}
// sum-to
function sumTo(n) {
{
const i7 = 0;
const acc8 = 0;
const i20 = 0;
const acc21 = 0;
{
let i = i7;
let acc = acc8;
let i = i20;
let acc = acc21;
while (true) {
if (i > n) {
return acc;
} else {
const i11 = i + 1;
const acc12 = acc + i;
i = i11;
acc = acc12;
const i24 = i + 1;
const acc25 = acc + i;
i = i24;
acc = acc25;
continue;
}
}
}
}
}
// make-adder
function makeAdder(x) {
return function (y) {
return x + y;
};
}
// set-html
function setHtml(id, html) {
{
const el38 = document.getElementById(id);
{
let el = el38;
el.innerHTML = html;
return el.innerHTML;
}
}
}
+69 -7
View File
@@ -2,18 +2,80 @@
(require "../main.rkt")
(provide generated-js)
(provide usecase-random-number
usecase-unique-values
usecase-array-at
usecase-sum-to
usecase-make-adder
usecase-set-html
all-js-usecases
show-js-usecases
write-js-usecases-file)
(define generated-js
;; Use case 01: generate a random integer between 1 and 5.
(define usecase-random-number
(js
(define answer 42)
(define (square x)
(return (* x x)))
(define (sum-to n)
(define (randomBetween1And5)
(return (+ (send Math floor (* (send Math random) 5)) 1)))))
;; Use case 02: get unique values from an array with duplicates using Set.
(define usecase-unique-values
(js
(define (uniqueValues xs)
(return (send Array from (new Set xs))))))
;; Use case 03: indexed array access with js-ref.
(define usecase-array-at
(js
(define (arrayAt xs i)
(return (js-ref xs i)))))
;; Use case 04: named let as a loop. The branch that leaves the loop uses an
;; explicit return, because js-maker 3 is statement-oriented.
(define usecase-sum-to
(js
(define (sumTo n)
(let loop ([i 0] [acc 0])
(if (> i n)
(return acc)
(loop (+ i 1) (+ acc i)))))))
;; Use case 05: return a JavaScript function value.
(define usecase-make-adder
(js
(define (makeAdder x)
(return (lambda (y)
(return (+ x y)))))))
;; Use case 06: small DOM setter. It uses send, js-dot and set!.
(define usecase-set-html
(js
(define (setHtml id html)
(let ([el (send document getElementById id)])
(set! (js-dot el innerHTML) html)
(return (js-dot el innerHTML))))))
(define all-js-usecases
`((random-number . ,usecase-random-number)
(unique-values . ,usecase-unique-values)
(array-at . ,usecase-array-at)
(sum-to . ,usecase-sum-to)
(make-adder . ,usecase-make-adder)
(set-html . ,usecase-set-html)))
(define (show-js-usecases)
(for ([entry (in-list all-js-usecases)])
(displayln (format "// ~a" (car entry)))
(displayln (cdr entry))
(newline)))
(define (write-js-usecases-file [path "demo/js-usecases.generated.js"])
(call-with-output-file path #:exists 'replace
(lambda (out)
(for ([entry (in-list all-js-usecases)])
(displayln (format "// ~a" (car entry)) out)
(displayln (cdr entry) out)
(newline out)))))
(module+ main
(display generated-js))
(show-js-usecases))
+22 -7
View File
@@ -1,11 +1,26 @@
#lang racket/base
(require (prefix-in use: "js-usecases.rkt")
(prefix-in dom: "dom-exercises.rkt"))
(require "../main.rkt")
(define examples
`((simple-function . ,(js (define (add1 x) (return (+ x 1)))))
(ordinary-let . ,(js (define (ordinaryLet x)
(let ([x 1] [y x])
(return y)))))
(let-star . ,(js (define (sequentialLet x)
(let* ([x 1] [y x])
(return y)))))
(named-let . ,(js (define (sumTo n)
(let loop ([i 0] [acc 0])
(if (> i n)
(return acc)
(loop (+ i 1) (+ acc i)))))))))
(define (show-examples)
(for ([entry (in-list examples)])
(displayln (format "// ~a" (car entry)))
(displayln (cdr entry))
(newline)))
(module+ main
(displayln ";; js-usecases")
(display use:generated-js)
(newline)
(displayln ";; dom-exercises")
(display dom:generated-js))
(show-examples))
+11 -8
View File
@@ -2,12 +2,15 @@
(require "../main.rkt")
;; There is no separate optimizer in js-maker 3. This demo shows the compact
;; named-let loop output produced directly by the `js` macro.
;; js-maker 3 does not have a separate optimizer pass. The notable direct
;; lowering is named let to a while(true) loop with parallel updates.
(define optimized-example
(js
(define (sumTo n)
(let loop ([i 0] [acc 0])
(if (> i n)
(return acc)
(loop (+ i 1) (+ acc i)))))))
(module+ main
(display
(js (define (factorial n)
(let loop ([i n] [acc 1])
(if (<= i 1)
(return acc)
(loop (- i 1) (* acc i))))))))
(displayln optimized-example))