nendo 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/bin/nendo CHANGED
@@ -1,12 +1,47 @@
1
1
  #!/usr/local/bin/ruby -W0
2
+ # -*- encoding: utf-8 -*-
2
3
  #
3
- # Nendo: "Principle of Least Surprise (for Rubyist)"
4
+ # Nendo: "Nendo is a diarect of Lisp."
4
5
  #
5
6
  require 'nendo'
7
+ require 'getoptlong'
6
8
 
7
9
  def main
10
+ loadInit = true
8
11
  core = Nendo.new()
9
- core.loadInitFile
12
+
13
+ opts = GetoptLong.new(
14
+ [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
15
+ [ '--no-init-file', '-q', GetoptLong::NO_ARGUMENT ],
16
+ [ '--load', '-l', GetoptLong::REQUIRED_ARGUMENT ]
17
+ ).each { |opt, arg|
18
+ case opt
19
+ when '--help'
20
+ puts <<-EOF
21
+
22
+ nendo [OPTION] [script-file]
23
+
24
+ -h, --help:
25
+ show help
26
+
27
+ -q, --no-init-file:
28
+ Does not read the default initialization file.
29
+
30
+ -l, --load:
31
+ Does not read the default initialization file.
32
+
33
+ EOF
34
+ when '--no-init-file'
35
+ loadInit = false
36
+ when '--load'
37
+ core.load( arg )
38
+ STDERR.printf( "loaded file [%s]\n", arg )
39
+ end
40
+ }
41
+
42
+ if loadInit
43
+ core.loadInitFile
44
+ end
10
45
  if 0 < ARGV.length
11
46
  core.load( ARGV[0] )
12
47
  else
@@ -0,0 +1,100 @@
1
+ #!/bin/sh
2
+ :; #-*- mode: nendo; syntax: scheme -*-;;
3
+ :; exec /usr/local/bin/nendo $0 $*
4
+
5
+ (load-library "text/html-lite")
6
+ (load-library "text/tree")
7
+ (require "cgi")
8
+ (require "RMagick")
9
+
10
+ (define (response-dekamoji str pointsize)
11
+ (let* ((font-dots pointsize)
12
+ (margin (* pointsize 0.3))
13
+ (image (Magick::Image.new (+ (* str.size font-dots) margin) (+ font-dots margin)))
14
+ (imlist (Magick::ImageList.new))
15
+ (dr (Magick::Draw.new)))
16
+ (set! image.background_color "none")
17
+ (set! image.format "PNG")
18
+ (imlist.push image)
19
+ ;;(set! dr.font "/Volumes/Macintosh HD/Library/Fonts/ホリデイMDJP03")
20
+ ;;(set! dr.font "/Volumes/Macintosh HD/Library/Fonts/みかちゃん")
21
+ ;;(set! dr.font "/Volumes/Macintosh HD/Library/Fonts/ヒラギノ丸ゴ ProN W4.otf")
22
+ ;;(set! dr.font "/Volumes/Macintosh HD/Library/Fonts/ヒラギノ明朝 Pro W6.otf")
23
+ (set! dr.font "/Volumes/Macintosh HD/Library/Fonts/ヒラギノ明朝 Pro W3.otf")
24
+ (set! dr.pointsize pointsize)
25
+ (set! dr.fill "#404040")
26
+ (set! dr.stroke "#080808")
27
+ (set! dr.font_weight Magick::BoldWeight)
28
+ (set! dr.gravity Magick::CenterGravity)
29
+ (dr.annotate imlist 0 0 0 0 str)
30
+ (let1 blur (imlist.blur_image 1.0 1.0)
31
+ (blur.to_blob))))
32
+
33
+
34
+ (define default-wording "デカ文字")
35
+ (define default-size 2)
36
+ (define size-list '(
37
+ (1 . "サイズ小")
38
+ (2 . "サイズ中")
39
+ (3 . "サイズ大")
40
+ (4 . "サイズ特大")
41
+ ))
42
+
43
+
44
+ (define (top-page params)
45
+ (let* ((size (if (hash-table-exist? params "size")
46
+ (to-i (car (to-list (hash-table-get params "size"))))
47
+ default-size))
48
+ (wording (if (hash-table-exist? params "w")
49
+ (car (to-list (hash-table-get params "w")))
50
+ default-wording)))
51
+ (let* ((size (if (> 1 size) 1 size))
52
+ (size (if (< (length size-list) size) (length size-list) size)))
53
+ `(
54
+ ,(html-doctype)
55
+ ,(html:head
56
+ (html:title "デカ文字作成"))
57
+ ,(html:body
58
+ (html:div :style "text-align: center; "
59
+ (html:h1 "デカ文字作成")
60
+ (html:p
61
+ "下記に文章を入れて『画像化』ボタンを押して下さい")
62
+ (html:form
63
+ :method "GET"
64
+ :action "./dekamoji.cgi"
65
+ (html:input :name "w" :type "text" :cols 140 :value wording)
66
+ (map
67
+ (lambda (x)
68
+ (list
69
+ (html:input :name "size" :type "radio"
70
+ :value (car x)
71
+ :CHECKED (eq? (car x) size))
72
+ (cdr x)))
73
+ size-list)
74
+ (html:br)
75
+ (html:input :type "submit" :value "画像化"))
76
+ (html:hr)
77
+ (html:img :src (sprintf "./dekamoji.cgi?img=1&size=%d&w=%s" size wording))
78
+ (html:hr)))))))
79
+
80
+ (define fontsize-alist '(
81
+ ("1" . 40)
82
+ ("2" . 80)
83
+ ("3" . 160)
84
+ ("4" . 260)
85
+ ))
86
+
87
+ (let1 cgi (CGI.new)
88
+ (cond ((hash-table-exist? cgi.params "img")
89
+ (cgi.print
90
+ (cgi.header "image/png"))
91
+ (cgi.print
92
+ (response-dekamoji
93
+ (car (to-list (hash-table-get cgi.params "w")))
94
+ (assv-ref (car (to-list (hash-table-get cgi.params "size"))) fontsize-alist))))
95
+ (else
96
+ (cgi.print
97
+ (cgi.header))
98
+ (cgi.print
99
+ (tree->string
100
+ (top-page cgi.params))))))
@@ -0,0 +1,32 @@
1
+ #!/bin/sh
2
+ :; #-*- mode: nendo; syntax: scheme -*-;;
3
+ :; exec /usr/local/bin/nendo $0 $*
4
+
5
+ (load-library "text/html-lite")
6
+ (load-library "text/tree")
7
+ (require "cgi")
8
+
9
+ (define (params-list-page cgi)
10
+ `(
11
+ ,(html-doctype)
12
+ ,(html:head
13
+ (html:title "CGI parameter list"))
14
+ ,(html:body
15
+ (html:h1 "CGI parameter list")
16
+ (html:table :border 1
17
+ (html:tr
18
+ (html:th "key")
19
+ (html:th "value"))
20
+ (hash-table-for-each cgi.params
21
+ (lambda (key value)
22
+ (html:tr
23
+ (html:td key)
24
+ (html:td (string-join value.to_list "/")))))))))
25
+
26
+
27
+ (let1 cgi (CGI.new)
28
+ (cgi.print
29
+ (cgi.header))
30
+ (cgi.print
31
+ (tree->string
32
+ (params-list-page cgi))))
File without changes
@@ -1,6 +1,6 @@
1
1
  #!/bin/sh
2
- true; #-*- mode: nendo; syntax: scheme -*-;;
3
- true; exec /usr/local/bin/nendo $0 $*
2
+ :; #-*- mode: nendo; syntax: scheme -*-;;
3
+ :; exec /usr/local/bin/nendo $0 $*
4
4
 
5
5
  ;; fact
6
6
  (define (fact n)
@@ -1,6 +1,6 @@
1
1
  #!/bin/sh
2
- true; #-*- mode: nendo; syntax: scheme -*-;;
3
- true; exec /usr/local/bin/nendo $0 $*
2
+ :; #-*- mode: nendo; syntax: scheme -*-;;
3
+ :; exec /usr/local/bin/nendo $0 $*
4
4
 
5
5
  ;; FizzBuzz write in Nendo
6
6
  (define (fizzbuzz max)
@@ -0,0 +1,51 @@
1
+ #!/bin/sh
2
+ :; #-*- mode: nendo; syntax: scheme -*-;;
3
+ :; exec /usr/local/bin/nendo $0 $*
4
+
5
+ (load-library "text/html-lite")
6
+ (load-library "text/tree")
7
+
8
+ (define (page-sample)
9
+ `(
10
+ ,(html:head
11
+ (html:title "title of page"))
12
+ ,(html:body
13
+ (html:p "これはサンプルです")
14
+ (html:h1 "section 1")
15
+ (html:h2 "section 1-2")
16
+ (html:table :border 1
17
+ (html:tr
18
+ (html:th "head1")
19
+ (html:th "head2"))
20
+ (html:tr
21
+ (html:td "data1")
22
+ (html:td "data2"))
23
+ (html:tr
24
+ (html:td "data3")
25
+ (html:td "data4"))
26
+ (html:hr)))))
27
+
28
+ (write-tree
29
+ (page-sample))
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
@@ -4,8 +4,4 @@
4
4
  (enable-idebug)
5
5
  (define debug-print-length 256)
6
6
 
7
- "abc"
8
- "a\nb"
9
- "a\"b"
10
- "abc\"abc\""
11
- "abc\'abc\'"
7
+
File without changes
data/lib/init.nnd CHANGED
@@ -107,6 +107,8 @@
107
107
  (define (ninth lst) (nth 8 lst))
108
108
  (define (tenth lst) (nth 9 lst))
109
109
 
110
+ (define (x->string object) (to-s object))
111
+
110
112
  ;; ----------------------------------------
111
113
  ;; basic forms
112
114
  ;; ----------------------------------------
@@ -126,7 +128,9 @@
126
128
  (let ((condition (if (eq? 'else (car elem))
127
129
  true
128
130
  (car elem)))
129
- (body (cdr elem))
131
+ (body (if (null? (cdr elem))
132
+ '(#t)
133
+ (cdr elem)))
130
134
  (tmpsym (gensym)))
131
135
  ;;(display "CONDITION") (print condition)
132
136
  ;;(display "BODY") (print body)
@@ -311,6 +315,13 @@
311
315
  ;; don't touch
312
316
  `(let ,@lst))))
313
317
 
318
+ ;; ----------------------------------------
319
+ ;; errorf
320
+ ;; ----------------------------------------
321
+ (define errorf
322
+ (macro (format . args)
323
+ `(error
324
+ (sprintf ,format ,@args))))
314
325
 
315
326
  ;; ----------------------------------------
316
327
  ;; List utilities imported from TinyScheme
@@ -388,6 +399,13 @@
388
399
  (filter-map pred (cdr lst))))))
389
400
 
390
401
 
402
+ (define (find pred lst)
403
+ (let1 result (filter pred lst)
404
+ (if (null? result)
405
+ #f
406
+ (car result))))
407
+
408
+
391
409
  (define lambda
392
410
  (macro src
393
411
  (if (not (list? (cadr src)))
@@ -477,43 +495,80 @@
477
495
  (let*-expand exps body))))
478
496
 
479
497
 
498
+ ;; ----------------------------------------
499
+ ;; values
500
+ ;; ----------------------------------------
501
+ (define (values . args)
502
+ (case (length args)
503
+ ((1)
504
+ (car args))
505
+ (else
506
+ (make-values args))))
507
+
508
+
509
+ (define (call-with-values producer consumer)
510
+ (let ((v (producer)))
511
+ (if (values? v)
512
+ (apply consumer (values-values v))
513
+ (consumer v))))
514
+
515
+ ;; srfi-8
516
+ (define receive
517
+ (macro (vars expr . body)
518
+ `(call-with-values
519
+ (lambda () ,expr)
520
+ (lambda ,vars ,@body))))
521
+
522
+
523
+ ;; ----------------------------------------
524
+ ;; keyword
525
+ ;; ----------------------------------------
526
+ (define (get-keyword key kv-list . fallback)
527
+ (cond
528
+ ((or (not (list? kv-list)) (>= 2 (length kv-list)))
529
+ (if (null? fallback)
530
+ (errorf "Error: imcomplete key list: %s\n" (write-to-string kv-list))
531
+ (car fallback)))
532
+ (else
533
+ (let loop ((k (car kv-list))
534
+ (v (cadr kv-list))
535
+ (rest (cddr kv-list)))
536
+ (if (eq? k key)
537
+ v
538
+ (case (length rest)
539
+ ((0)
540
+ (if (null? fallback)
541
+ (errorf "Error: value for key %s is not provided : %s\n" (write-to-string key) (write-to-string kv-list))
542
+ (car fallback)))
543
+ ((1)
544
+ (errorf "Error: incomplete key list: %s\n" (write-to-string kv-list)))
545
+ (else
546
+ (loop (car rest)
547
+ (cadr rest)
548
+ (cddr rest)))))))))
549
+
480
550
  ;; ----------------------------------------
481
551
  ;; for Ruby interop
482
552
  ;; ----------------------------------------
483
- ;; dot_operator
484
553
  (define dot-operator
485
554
  (macro lst
486
- (letrec ((dot-operator-iter
555
+ (letrec ((generate-method-call-form
487
556
  (lambda (lst)
488
- (cond
489
- ((null? lst)
490
- '())
491
- ((pair? lst)
492
- (if (eq? 'dot-operator (car lst))
493
- (intern
494
- (string-join
495
- (map
496
- (lambda (x)
497
- (if (pair? x)
498
- (to-s (dot-operator-iter x))
499
- (if (symbol? x)
500
- (to-s x)
501
- (error (sprintf "dot-operator requires symbol, but got %s" x)))))
502
- (cdr lst))
503
- "."))
504
- (error "dot-operator requires symbol or (. symbol symbol) form.")))
505
- (else
506
- lst)))))
507
-
557
+ (let1 tmp (gensym)
558
+ (if (symbol? (first lst))
559
+ `(,(string->symbol (+ (to-s (first lst)) "." (to-s (second lst))))
560
+ ,@(cddr lst))
561
+ `(let ((,tmp ,(first lst)))
562
+ (,(string->symbol (+ (to-s tmp) "." (to-s (second lst))))
563
+ ,@(cddr lst))))))))
508
564
  (cond
509
- ((eq? 0 (length lst))
510
- (error ". operator requires argument"))
511
- ((and (eq? 1 (length lst))
512
- (symbol? (car lst)))
513
- (intern (+ "." (to-s (car lst)))))
565
+ ((> 2 (length lst))
566
+ (raise ArgumentError ". dot-operator requires 2+ arguments."))
514
567
  (else
515
- ((dot-operator-iter
516
- (cons 'dot-operator lst))))))))
568
+ (if (symbol? (second lst))
569
+ (generate-method-call-form lst)
570
+ (raise TypeError ". dot-operator requires method name as symbol.")))))))
571
+
517
572
 
518
573
  (define (with-open filename pred . lst)
519
574
  (let1 len (length lst)
@@ -538,6 +593,92 @@
538
593
  x))
539
594
 
540
595
 
596
+ (define (cons* arg . args)
597
+ (if (null? args)
598
+ arg
599
+ (cons arg (apply list* args))))
600
+ (define list* cons*)
601
+
602
+
603
+ ;; ----------------------------------------
604
+ ;; hash-table library functions
605
+ ;; ----------------------------------------
606
+ (define (make-hash-table)
607
+ (Hash.new))
608
+
609
+ (define (hash-table? h)
610
+ (h.is_a? Hash))
611
+
612
+ (define (hash-table-num-entries h)
613
+ (h.length))
614
+
615
+ (define (hash-table . kv-list)
616
+ (let1 h (make-hash-table)
617
+ (for-each
618
+ (lambda (entry)
619
+ (if (pair? (cdr entry))
620
+ (hash-table-put! h (car entry) (cadr entry))
621
+ (hash-table-put! h (car entry) (cdr entry))))
622
+ kv-list)
623
+ h))
624
+
625
+ (define (hash-table-exist? h key)
626
+ (h.has_key? key))
627
+
628
+ (define (hash-table-clear! h)
629
+ (h.clear))
630
+
631
+ (define (hash-table-delete! h key)
632
+ (h.delete key))
633
+
634
+ (define (hash-table-keys h)
635
+ (to-list (h.keys)))
636
+
637
+ (define (hash-table-values h)
638
+ (to-list (h.values)))
639
+
640
+ (define (hash-table-map h pred)
641
+ (let1 keys (hash-table-keys h)
642
+ (map
643
+ (lambda (key)
644
+ (pred key (hash-table-get h key)))
645
+ keys)))
646
+ (define hash-table-for-each hash-table-map)
647
+
648
+ (define (hash-table->alist h)
649
+ (if (not (h.is_a? Hash))
650
+ (raise TypeError "Error: hash-table->alist expects Hash instance.")
651
+ (let1 keys (hash-table-keys h)
652
+ (map
653
+ (lambda (key)
654
+ (cons key (hash-table-get h key)))
655
+ keys))))
656
+
657
+ (define (alist->hash-table alist)
658
+ (if (not (list? alist))
659
+ (raise TypeError "Error: alist->hash-table expects alist.")
660
+ (apply hash-table alist)))
661
+
662
+ ;; ----------------------------------------
663
+ ;; Ruby interop librarys
664
+ ;; ----------------------------------------
665
+ ;; I will implement in the future...
666
+ (define export
667
+ (macro (name)
668
+ `(define ,name nil)))
669
+
670
+ (define (load-library name)
671
+ (let* ((home (get-nendo-home))
672
+ (path (+ home "/" name)))
673
+ (cond
674
+ ((File.exist? (+ path ".nndc"))
675
+ (load-compiled-code (+ path ".nndc")))
676
+ ((File.exist? (+ path ".nnd"))
677
+ (load (+ path ".nnd")))
678
+ (else
679
+ (errorf "Error: can't load library file [%s]\n" path )))))
680
+
681
+
541
682
  ;; ----------------------------------------
542
683
  ;; Utility function for testing and debugging
543
684
  ;; ----------------------------------------