profj is gone, profjWizard follows

svn: r15949
This commit is contained in:
Eli Barzilay 2009-09-10 01:26:50 +00:00
parent eda69b472a
commit a5049e9d03
17 changed files with 0 additions and 3176 deletions

View File

@ -1,83 +0,0 @@
(module assoc-list mzscheme
(require mzlib/class)
(provide assoc%)
(define assoc<%>
(interface ()
;; type X, Y
add ;; X Y -> Void
;; add (cons x y) to fields or update the existing association
remove ;; X -> Void
list ;; -> [Listof Y]
lookup ;; X -> Y
update ;; X Y -> Void
))
(define assoc%
(class object%
(super-new)
;; (Listof (Cons X Y))
(define fields '())
;; X Y -> Void
(define/public (add type name)
(define a (assq type fields))
(if a
(send this update type name)
(set! fields (cons (cons type name) fields))))
;; X -> Void
(define/public (remove type)
(set! fields
(let loop ([fields fields])
(cond
[(null? fields) '()]
[(eq? (caar fields) type) (cdr fields)]
[else (cons (car fields) (loop (cdr fields)))]))))
;; -> (Listof Y)
;; extract all y in the order in which they were entered
(define/public (list) (reverse (map (lambda (f) (cdr f)) fields)))
;; X -> Y
(define/public (lookup to-edit)
(let loop ([v fields])
(cond
[(null? v) (error 'internal "can't find field")]
[(eq? (caar v) to-edit) (cdar v)]
[else (loop (cdr v))])))
;; X Y -> Void
(define/public (update to-edit new-v)
(set! fields
(let loop ([v fields])
(cond
[(null? v) (error 'internal "can't find variant")]
[(eq? (caar v) to-edit) (cons (cons (caar v) new-v) (cdr v))]
[else (cons (car v) (loop (cdr v)))]))))))
#| Tests:
(require (lib "testing.scm" "testing"))
(define al (new assoc%))
(send al add 0 1)
(test== (send al list) (list 1))
(send al add 'a 'b)
(test== (send al list) (list 1 'b))
(send al update 0 33)
(test== (send al lookup 0) 33)
(send al remove 0)
(test== (send al list) (list 'b))
(send al remove 'a)
(test== (send al list) '())
|#
)

View File

@ -1,14 +0,0 @@
(module aux-class mzscheme
(require mzlib/class)
(provide
(all-from mzlib/class)
define/abstract ; (define/abstract <identifier>) :: <definition>
)
(define-syntax define/abstract
(syntax-rules ()
[(define/abstract id)
(define/public id (lambda x (error 'id "abstract")))]))
)

View File

@ -1,23 +0,0 @@
(module aux-contract mzscheme
(require-for-syntax (file "aux-syntax.scm"))
(require mzlib/contract)
(provide
define-as-contract ;; <definition>
)
;; (define-as-contract string (id x ...) body ...)
;; introduces id for export as a contract and
;; is-id? for local testing as a function
(define-syntax (define-as-contract stx)
(syntax-case stx ()
[(_ message (name . args) . body)
(with-syntax ([is-name (prefix-id-suffix "is-" (syntax name) "?")]
[ct-name (cap-id (syntax name))])
(syntax
(begin
(define (is-name . args) . body)
(define ct-name (flat-named-contract message is-name)))))]))
)

View File

@ -1,32 +0,0 @@
#cs(module aux-syntax mzscheme
(provide
prefix-id-suffix ; String Identifier String -> Identifier
add? ; Identifier -> Identifier
cap-id ; Identifier -> Identifier
)
(require mzlib/string)
(define (prefix-id-suffix prefix e suffix)
(datum->syntax-object
e (string->symbol (format "~a~a~a" prefix (syntax-e e) suffix))))
;; to add a ? at the end of an identifier
(define (add? e) (prefix-id-suffix "" e "?"))
(define (cap-id id-e)
(let* ([id-s (symbol->string (syntax-e id-e))]
[fst (substring id-s 0 1)]
[rst (substring id-s 1 (string-length id-s))])
(string-uppercase! fst)
(datum->syntax-object id-e (string->symbol (string-append fst rst)))))
#| Tests:
(define e (datum->syntax-object #f 'e))
(printf "~s~n" (eq? 'set-e! (syntax-e (prefix-id-suffix "set-" e "!"))))
(printf "~s~n" (eq? 'e? (syntax-e (add? e))))
(printf "~s~n" (eq? 'Hello (syntax-e (cap-id (datum->syntax-object #f 'hello)))))
|#
)

View File

@ -1,385 +0,0 @@
(module class mzscheme
(require "data-defs.scm"
mzlib/contract
mzlib/etc
mzlib/list
srfi/13/string
(only srfi/1 zip))
;; ------------------------------------------------------------------------
(provide/contract
[make-class ((Class) (boolean? boolean? string? Fields (listof Method)) . opt-> . string?)]
[method (Method . -> . string?)]
)
#| Usage:
(make-class a-class toString? template? language? Fields Methods)
create a Java class from the class specification (a-class) and add
Fields from super and Methods from the implementing interface.
The first optional boolean parameter specifies whether we want toString
in the class hiearchy. Default: true
The second optional boolean parameter specifies whether we want
a draft method template in comments. Default: true
The third optinal determines the language level.
|#
;; ------------------------------------------------------------------------
;; Construct individual Java classes
;; create class definition (as string) from name, super and list of fields
(define make-class
(opt-lambda (the-class [toString? #t][template? #t][language BEGINNER][super-fields '()][method-sigs '()])
(define no-public (or (eq? language BEGINNER) (or (eq? language INTERMEDIATE))))
(let ([type (car the-class)]
[super (cadr the-class)]
[fields (caddr the-class)]
[prps (class-purpose the-class)])
(define templates
(if (or (not template?) (eq? language BEGINNER))
""
(enumerate-with-separator
(map (lambda (ms)
(apply string-append (make-template ms super fields template? (not no-public))))
method-sigs)
"\n")))
(apply string-append
`( ,@(purpose-statement prps)
,(format classf type (implements super))
;; fields
,@(map (lambda (f) (format declaf (car f) (cadr f))) fields)
"\n"
;; constructor
,(class-constructor type fields super-fields)
;; optional template draft:
,templates
;; optional toString method:
,@(toString type fields no-public toString?)
,endclf)))))
;; String -> String
(define (implements super) (if (string=? "" super) "" (format implementsf super)))
;; String Fields Fields -> String
(define (class-constructor type fields super-fields)
(apply string-append
`( ,(format constf type (parameters (append super-fields fields)))
#| When we switch to super in beginner, this will need to change.
;; call to super(super-fields)
,@(if (null? super-fields) '()
(list (format superf (commas (map cadr super-fields)))))
|#
;; init for fields
,@(map (lambda (f) (format initif (cadr f) (cadr f)))
;; When we switch to super in beginner, ...
(append super-fields fields))
,endMet)))
;; Fields -> String
;; create a paremeter list from a field specifications
(define (parameters fs)
(enumerate-with-separator
(map (lambda (f) (format paraf (car f) (cadr f))) fs)))
;; String String Fields Boolean -> (listof String)
(define (make-template sig super fields template? public?)
(define head (format contef (method sig)))
(if (not template?)
(list "")
`("\n"
;; template method
,cmnt/*
,warnin
,(if public? (string-append " public " (string-trim head)) head)
,@(map (lambda (f) (if (string=? (car f) super)
(format temprf (cadr f) (cadr sig))
(format tempsf (cadr f))))
fields)
,endMet
,cmnt*/)))
;; Method -> String
(define (method m)
(define m+n (zip (cddr m) PARAS))
(define sig (map (lambda (x) (format "~a ~a" (car x) (cadr x))) m+n))
(format intff (car m) (cadr m) (enumerate-with-separator sig ",")))
(define PARAS '("x" "y" "z" "u" "v" "w" "s" "t"))
;; String Fields -> (cons String (listof String))
;; create a toString method for class type with _fields_
(define toString
(opt-lambda (type fields [special? #f][toString? #t])
(if (not toString?)
(list "")
(list "\n"
(string-append
(if special? toStrf pbStrf)
(format prefix type)
; (apply string-append)
(if (null? fields)
" + "
(format
" + ~a + " (enumerate-with-separator (map addToString fields) infix)))
postfix
endMet)))))
;(provide toString)
;; Field -> String
;; create a call to toString, if necessary
(define (addToString f)
(let ([t (car f)] [s (cadr f)])
(if (member t StringNative) s (format "~a.toString()" s))))
;; String -> (list String)
(provide/contract
[purpose-statement (-> string? (listof string?))])
(define (purpose-statement prps)
(if (string=? "" prps) '("") (list (format "// ~a~n" prps))))
;; identifiers ending in f are format strings, and require ~n for newline
;; Abstract Template
(define purpos " // purpose statement \n")
;; Class
(define classf "class ~a ~a{~n") (define implementsf "implements ~a ")
;; Fields
(define declaf " ~a ~a;~n")
;; Constructor
(define constf " ~a(~a) {~n") (define paraf "~a ~a")
(define superf " super(~a);~n")
(define initif " this.~a = ~a;~n")
(define endMet " }\n")
(provide endclf cmnt/* cmnt*/ warnin purpos)
(define endclf "}\n")
;; Concrete Template
(define warnin " // ** DRAFT TEMPLATE ** Edit as needed.\n")
(define intff "~a ~a(~a)")
(define contef " ~a {\n")
(define tempsf " ... this.~a ...\n")
(define temprf " ... this.~a.~a(...) ...\n")
;; toString
(define pbStrf " public String toString() {\n")
(define toStrf " String toString() {\n")
(define prefix " return \"new ~a(\"")
(define infix " + \",\" + ")
(define postfix "\")\";\n")
(define StringNative '("int" "boolean" "String" "double")) ;; and others
;; Comments
(define cmnt/* "/*\n")
(define cmnt*/ "*/\n")
;; ------------------------------------------------------------------------
;; Library
(provide/contract
[enumerate-with-separator (opt-> ((listof string?)) (string?) string?)])
;; (Listof String) -> String
;; create a comma-separated string from a list of strings
(define (enumerate-with-separator l . comma)
(let ([comma (if (null? comma) ", " (car comma))])
(if (null? l) ""
(apply string-append (car l)
(map (lambda (x) (string-append comma x)) (cdr l))))))
;; ------------------------------------------------------------------------
;; TESTS:
(define empty-template
`("/*\n"
,warnin
" ??? mmm() {\n"
" }\n"
"*/\n"
"\n"))
(define public-empty-template
`("/*\n"
,warnin
" public ??? mmm() {\n"
" }\n"
"*/\n"
"\n"))
#| Tests :
(require (lib "testing.scm" "testing"))
(test== (enumerate-with-separator '()) "")
(test== (enumerate-with-separator '("x" "y") ) "x, y")
(test== (enumerate-with-separator '("x" "y") " + ") "x + y")
(test== (parameters '()) "")
(test== (parameters '(("int" "x"))) "int x")
(test== (parameters '(("int" "x") ("foo" "y"))) "int x, foo y")
(test== (enumerate-with-separator '("x" "y") " + ") "x + y")
(test== (enumerate-with-separator '("x" "y" "z") " + ") "x + y + z")
(test== (cadr (toString "foo" '()))
(string-append
pbStrf
" return \"new foo(\" + \")\";\n"
endMet))
(test== (cadr (toString "foo" '() #t))
(string-append
toStrf
" return \"new foo(\" + \")\";\n"
endMet))
(test== (cadr (toString "Foo" '(("Foo" "x") ("Moo" "y"))))
(string-append
pbStrf
" return \"new Foo(\" + x.toString() + \",\" + y.toString() + \")\";\n"
endMet))
(test== (cadr (toString "Foo" '(("Foo" "x") ("Moo" "y")) #t))
(string-append
toStrf
" return \"new Foo(\" + x.toString() + \",\" + y.toString() + \")\";\n"
endMet))
(test== (cadr (toString "Foo" '(("int" "x"))))
(string-append
pbStrf
" return \"new Foo(\" + x + \")\";\n"
endMet))
(test== (cadr (toString "Foo" '(("Boolean" "x"))))
(string-append
pbStrf
" return \"new Foo(\" + x.toString() + \")\";\n"
endMet))
(test== (cadr (toString "Foo" '(("Foo" "x") ("int" "y") ("Z" "z"))))
(string-append
pbStrf
" return \"new Foo(\" + x.toString() + \",\" + y + \",\" + z.toString() + \")\";\n"
endMet))
(test== (toString "Foo" '(("Foo" "x") ("int" "y") ("Z" "z")) #f #f)
(list ""))
(test== (class-constructor "Node" '(("int" "x")) '(("Info" "i") ("ATree" "parent")))
(string-append
" Node(Info i, ATree parent, int x) {\n"
" this.i = i;\n"
" this.parent = parent;\n"
" this.x = x;\n"
" }\n"
)
"class constructor with super fields")
(test== (make-class (list "foo" "" '()) #t #t INTERMEDIATE '() '(("???" "mmm")))
(apply string-append
`( "class foo {\n"
"\n"
" foo() {\n"
" }\n"
"\n"
,@empty-template
,toStrf
" return \"new foo(\" + \")\";\n"
" }\n"
"}\n"))
"class with template in INTERMEDIATE")
(test== (make-class (list "moo" "foo" '()) #t #t PROFESSIONAL '() '(("???" "mmm")))
(apply string-append
`("class moo implements foo {\n"
"\n"
" moo() {\n"
" }\n"
"\n"
,@public-empty-template
,pbStrf
" return \"new moo(\" + \")\";\n"
" }\n"
"}\n")))
(test== (make-class (list "moo" "foo" '(("int" "x") ("foo" "f"))) #t #t PROFESSIONAL '() '(("???" "mmm")))
(apply string-append
`("class moo implements foo {\n"
" int x;\n"
" foo f;\n"
"\n"
" moo(int x, foo f) {\n"
" this.x = x;\n"
" this.f = f;\n"
" }\n"
"\n"
,cmnt/*
,warnin
" public ??? mmm() {\n"
" ... this.x ...\n"
" ... this.f.mmm(...) ...\n"
" }\n"
,cmnt*/
"\n"
,pbStrf
" return \"new moo(\" + x + \",\" + f.toString() + \")\";\n"
" }\n"
"}\n")))
(test== (make-class (list "CartPt" "" '(("int" "x") ("int" "y"))) #t #t PROFESSIONAL '() '(("???" "mmm")))
(apply string-append
`("class CartPt {\n"
" int x;\n"
" int y;\n"
"\n"
" CartPt(int x, int y) {\n"
" this.x = x;\n"
" this.y = y;\n"
" }\n"
"\n"
,cmnt/*
,warnin
" public ??? mmm() {\n"
" ... this.x ...\n"
" ... this.y ...\n"
" }\n"
,cmnt*/
"\n"
,pbStrf
" return \"new CartPt(\" + x + \",\" + y + \")\";\n"
" }\n"
"}\n")))
(test== (make-class (list "foo" "" '() "hello world") #t #t PROFESSIONAL '() '(("???" "mmm")))
(apply string-append
`( "// hello world\n"
"class foo {\n"
"\n"
" foo() {\n"
" }\n"
"\n"
,@public-empty-template
,pbStrf
" return \"new foo(\" + \")\";\n"
" }\n"
"}\n")))
(test== (make-class (list "foo" "" '() "hello world") #t #t INTERMEDIATE '() '(("???" "mmm")))
(apply string-append
`( "// hello world\n"
"class foo {\n"
"\n"
" foo() {\n"
" }\n"
"\n"
,@empty-template
,toStrf
" return \"new foo(\" + \")\";\n"
" }\n"
"}\n")))
|#
)

View File

@ -1,159 +0,0 @@
#| Data Defs
Class = (list Name SuperClass Fields [Comment])
;; the name of the class, the name of the supertype ("" if none), and
;; the class's fields
DataType = (make-union TypeName Methods VariantClasses Comment)
;; the name of the type and its variants
VariantClasses = (Listof VariantClass)
VariantClass = (list Name Fields [Comment])
Name = String
TypeName = String
SuperClass = String
Methods = (Listof Method)
Method = (cons String (cons String (listof String)))
Fields = (Listof Field)
Field = (list String String)
|#
#cs
(module data-defs mzscheme
(require string-constants)
;; Those languages for which methods that satisfy an interface
;; don't have to be decorated with public ---
(define BEGINNER (string-constant profj-beginner-lang))
(define INTERMEDIATE (string-constant profj-intermediate-lang))
(define PROFESSIONAL (string-constant profj-full-lang))
(define *languages* (list BEGINNER INTERMEDIATE PROFESSIONAL))
(define Language
(flat-named-contract "<Language>" (lambda (x) (member x *languages*))))
(provide BEGINNER INTERMEDIATE PROFESSIONAL Language)
(define-struct dt (type methods variants purpose))
(define (dt-fields . x) (error 'dt-fields "not implemented yet: ~a\n" x))
(provide dt-fields)
;; Examples
(define method1 '("int" "x"))
(define method2 '("int" "y" "boolean"))
(define method3 '("boolean" "b" "Foo" "Bar"))
(define methods (list method1 method2 method3))
(define vc1 (list "Leaf"))
(define vc2 (list "Node" '(("ATree" "left") ("ATree" "right"))))
(define datat1 (make-dt "ATree" methods (list vc1 vc2) "a tree for ints"))
(require "aux-contract.scm")
(require mzlib/contract)
(provide
Class ;; flat-contract
Union ;; flat-contract
Variant ;; flat-contract
Fields ;; flat-contract
Method ;; flat-contract
java-id? ;; Any -> Boolean
class-purpose ;; Class -> String
variant-purpose ;; Variant -> String
)
;; DataType -> String
;; (define (union-purpose dt) (if (null? (cddr dt)) "" (caddr dt)))
;; Class -> String
(define (class-purpose c) (if (null? (cdddr c)) "" (cadddr c)))
;; Variant -> String
(define (variant-purpose c) (if (null? (cddr c)) "" (caddr c)))
;; Any -> Boolean
;; the string isn't empty and contains no spaces
;; I should really import this from Kathy's parser or whatever
;; so I get qualified names and whatever right
(define (java-id? s)
(and (string? s) (not (string=? "" s)) (not (regexp-match "[ |\t|\n]" s))))
(define-as-contract "<Class>" (class c)
(and (pair? c) (pair? (cdr c)) (pair? (cddr c))
(or (null? (cdddr c))
(and (pair? (cdddr c))
(null? (cddddr c))
(string? (cadddr c))))
; (list? c) (= (length c) 3)
(java-id? (car c))
(let ([super (cadr c)])
(or (java-id? super) (string=? super "")))
(is-fields? (caddr c))))
(define-as-contract "<Methods>" (methods l)
(and (list? l) (andmap is-method? l)))
(define-as-contract "<Method>" (method l)
(and (list? l) (>= (length l) 2) (andmap java-id? l)))
(define-as-contract "<Fields>" (fields l)
(and (list? l) (andmap is-field? l)))
(define-as-contract "<Field in Class>" (field l)
(and (list? l) (= (length l) 2) (andmap java-id? l)))
(define-as-contract "<Union>" (union l) (dt? l))
(define (is-variants? l) (andmap is-variant? l))
(define-as-contract "<Variant>" (variant c)
(and (pair? c) (pair? (cdr c))
(or
(null? (cddr c))
(and
(pair? (cddr c))
(null? (cdddr c))
(string? (caddr c)))
; (list? c) (= (length c) 2)
(java-id? (car c))
(is-fields? (cadr c)))))
(provide/contract
(struct dt ((type java-id?)
(methods (listof is-method?))
(variants (listof is-variant?))
(purpose string?))))
#| Tests:
(require (lib "testing.scm" "testing"))
(test== (java-id? "oops no") #f)
(test== (java-id? " oops 2") #f)
(test== (java-id? " oops2 ") #f)
(test== (java-id? "") #f)
(test== (java-id? (string #\tab)) #f)
(test== (java-id? (string #\newline)) #f)
(test== (is-class? '("Foo" "" ())) #t)
(test== (is-class? '("Foo" "" () "hello world")) #t)
(test== (is-class? '("Foo" "Moo" (("int" "x") ("int" "y")) "hello world")) #t)
(test== (is-class? '("Foo" "Moo")) #f "no fields")
(test== (is-class? '("Foo" "Moo Oops" ())) #f "space in super name")
(test== (class-purpose '("a" "b" ())) "")
(test== (class-purpose '("a" "b" () "hello world")) "hello world")
(test== (is-variant? (list "B" '())) #t "variant class")
(test== (andmap is-variant? (list (list "B" '()) (list "C" '()))) #t "variants")
(test== (java-id? "A") #t)
(test== (is-union? (make-dt "A" '() (list (list "B" '()) (list "C" '())) "")) #t)
(test== (is-method? method1) #t)
(test== (is-method? method2) #t)
(test== (is-method? method3) #t)
(test== (is-methods? methods) #t)
|#
)

View File

@ -1,129 +0,0 @@
#| Data Defs
Class = (list Name SuperClass Fields [Comment])
;; the name of the class, the name of the supertype ("" if none), and
;; the class's fields
DataType = (list TypeName VariantClasses [Comment])
;; the name of the type and its variants
VariantClasses = (Listof VariantClass)
VariantClass = (list Name Fields [Comment])
Name = String
TypeName = String
SuperClass = String
Fields = (Listof Field)
Field = (list String String)
|#
#cs
(module data-defs mzscheme
;; Examples
(define field1 '("int" "x"))
(define field2 '("int" "y"))
(define field3 '("boolean" "b"))
(define fields (list field1 field2 field3))
(define vc1 (list "Leaf" (list field1)))
(define vc2 (list "Node" '(("ATree" "left") ("ATree" "right"))))
(define datat1 (list "ATree" (list vc1 vc2) "a tree for ints"))
(require "aux-contract.scm")
(require mzlib/contract)
(provide
Class ;; flat-contract
Union ;; flat-contract
Variant ;; flat-contract
java-id? ;; Any -> Boolean
class-purpose ;; Class -> String
union-purpose ;; Union -> String
variant-purpose ;; Variant -> String
)
;; DataType -> String
(define (union-purpose dt) (if (null? (cddr dt)) "" (caddr dt)))
;; Class -> String
(define (class-purpose c) (if (null? (cdddr c)) "" (cadddr c)))
;; Variant -> String
(define (variant-purpose c) (if (null? (cddr c)) "" (caddr c)))
;; Any -> Boolean
;; the string isn't empty and contains no spaces
;; I should really import this from Kathy's parser or whatever
;; so I get qualified names and whatever right
(define (java-id? s)
(and (string? s) (not (string=? "" s)) (not (regexp-match "[ |\t|\n]" s))))
(define-as-contract "<Class representation>" (class c)
(and (pair? c) (pair? (cdr c)) (pair? (cddr c))
(or (null? (cdddr c))
(and (pair? (cdddr c))
(null? (cddddr c))
(string? (cadddr c))))
; (list? c) (= (length c) 3)
(java-id? (car c))
(let ([super (cadr c)])
(or (java-id? super) (string=? super "")))
(is-fields? (caddr c))))
(define (is-fields? l)
(and (list? l) (andmap is-field? l)))
(define (is-field? l)
(and (pair? l) (pair? (cdr l)) (null? (cddr l))
(java-id? (car l)) (java-id? (cadr l))))
(define-as-contract "<Union (datatype) representation>" (union l)
(and (pair? l) (pair? (cdr l))
(or (null? (cddr l))
(and (pair? (cddr l))
(null? (cdddr l))
(string? (caddr l))))
(java-id? (car l))
(andmap is-variant? (cadr l))))
(define-as-contract "<Variant (in a union)>" (variant c)
(and (pair? c) (pair? (cdr c))
(or
(null? (cddr c))
(and
(pair? (cddr c))
(null? (cdddr c))
(string? (caddr c)))
; (list? c) (= (length c) 2)
(java-id? (car c))
(is-fields? (cadr c)))))
#| Tests:
(require (lib "testing.scm" "testing"))
(test== (java-id? "oops no") #f)
(test== (java-id? " oops 2") #f)
(test== (java-id? " oops2 ") #f)
(test== (java-id? "") #f)
(test== (java-id? (string #\tab)) #f)
(test== (java-id? (string #\newline)) #f)
(test== (is-class? '("Foo" "" ())) #t)
(test== (is-class? '("Foo" "" () "hello world")) #t)
(test== (is-class? '("Foo" "Moo" (("int" "x") ("int" "y")) "hello world")) #t)
(test== (is-class? '("Foo" "Moo")) #f "no fields")
(test== (is-class? '("Foo" "Moo Oops" ())) #f "space in super name")
(test== (class-purpose '("a" "b" ())) "")
(test== (class-purpose '("a" "b" () "hello world")) "hello world")
(test== (is-variant? (list "B" '())) #t "variant class")
(test== (andmap is-variant? (list (list "B" '()) (list "C" '()))) #t "variants")
(test== (java-id? "A") #t)
(test== (is-union? (list "A" (list (list "B" '()) (list "C" '())))) #t)
|#
)

View File

@ -1,45 +0,0 @@
TODO:
- purpose statement for each interface method
- one day, not now: blank out error messages somehow on the next event
- one day, not now: a common abstract class
;; Information about the union's common fields:
(add-button info-pane "Add Common Field"
(lambda (x e) (send field-panel add)))
(define field-panel
(new field-panel%
(parent info-pane) (window this)
(error-message (lambda (x) (error-message x)))))
--------------------------------------------------------------------------------
adapted wizard to interfaces (from abstract classes)
unions are interfaces plus implementing classes
signatures of common methods
| construction attributes --- presentation only
|
Languages | template toString diagram
------------------------------------------------------------------
BEGINNER | -- -- okay
INTERMEDIATE | no "public" no "public" okay
PROFESSIONAL | okay okay okay
--------------------------------------------------------------------------------
view0:
design interfaces by hand
abstract into functions
abstract common pieces via multiple values
view:
replace the multiple values abstraction with classes
data-def0
everything is a list
data-def
unions (dt) becomes a struct so that I could add common fields
draw-txt0
explorative prototype

View File

@ -1,466 +0,0 @@
#cs
(module draw-txt mzscheme
(require "data-defs.scm"
"class.scm"
mzlib/etc
mzlib/list
mzlib/contract)
(provide/contract
[dt-draw (Union . -> . string?)]
[class-draw ((Class) (listof Method) . opt-> . string?)])
;; ---------------------------------------------------------------------------
;; Deal with a Union of classes
;; DataType -> String
(define (dt-draw dt)
(define spr (dt-type dt))
(define vts (dt-variants dt))
(define mt* (dt-methods dt))
;; String -> Number
(define (vbar-pos s)
(let loop ([i (- (string-length s) 1)])
(cond [(< i 0) (error 'find-bar "can't happen: ~e" s)]
[(char=? (string-ref s i) #\|) i]
[else (loop (- i 1))])))
(if (null? vts)
(class-draw (list spr "" '()))
(let-values ([(vts:str rec?) (variants*-to-strings vts spr mt*)])
(define wth (sum (map (lambda (x) (string-length (car x))) vts:str)))
(define fst-vrt (car (car vts:str)))
(define lst-vrt (car (last vts:str)))
(define fst-bar (vbar-pos fst-vrt))
(define lst-bar (vbar-pos lst-vrt))
(define diagram
(append
(type-to-string spr mt* wth rec?)
(refinement-connector wth fst-bar (string-length lst-vrt) lst-bar)
(flatten-string-matrix vts:str)))
(define d/recur (if rec? (add-recursion-connector diagram) diagram))
(strings->string-as-lines d/recur))))
;; (Listof String) -> (Listof String)
;; add
;;
;; --+ // on second line
;; |
;; --+ // on last line
;; to los
(define (add-recursion-connector los)
(unless (and (andmap string? los) (>= (length los) 3))
(error 'add-recursive-connector "bad inputs: ~s\n" los))
(let* ([fst (car los)]
[snd (cadr los)]
[lst (last los)]
[BLK " "]
[CON "--+"]
[LIN " |"])
(define (frame l)
(cond
[(null? (cdr l)) (list (string-append lst CON))]
[else (cons (string-append (car l) LIN) (frame (cdr l)))]))
(cons (string-append fst BLK)
(cons (string-append snd CON) (frame (cddr los))))))
;; Number Number Number Number -> (Listof String)
;; create a refinement connector of the proper width like this
;;
;; |
;; / \
;; ---
;; |
;; +----------+
;; | |
;;
(define (refinement-connector width frst-bar width-of-last last-bar)
(define REFINEMENT-ARROW
(list " | "
"/ \\"
"---"
" | "))
(append
(map (lambda (x) (centered x width)) REFINEMENT-ARROW)
(list (string-append
(make-string frst-bar #\space)
(make-string (- width frst-bar (- width-of-last +1 last-bar)) #\-)
(make-string (- width-of-last +1 last-bar) #\space)))))
;; Class Fields Number Boolean-> (Listof String)
;; create a list of strings that represent the abstract class of a union
;; center the strings with respect to width, add a "recursion" arrow (needed?)
(define (type-to-string spr methods width recursive)
(define (range-contract result)
(unless (= (string-length (car result)) width)
(error 'type-to-string "bad result: ~s\n" result))
result)
(define class-as-strings (class-to-strings (list spr "" '()) methods))
(define width-of-classes (string-length (car class-as-strings)))
(define super-line (centered (cadr class-as-strings) width))
(range-contract
(cons
(centered (car class-as-strings) width)
(cons (if recursive (add-<-- super-line) super-line)
(map (lambda (x) (centered x width)) (cddr class-as-strings))))))
;; String -> String
;; add the containment arrow to an abstract class from the right fringe
(define (add-<-- x0)
(list->string
(reverse
(let loop ([x (reverse (string->list x0))])
(cond
[(char=? (cadr x) #\|) (cons #\< (cdr x))]
[else (cons #\- (loop (cdr x)))])))))
;; VariantClasses Super -> (Listof String)
;; for testing and printing only
(define (variants*-draw variants spr methods)
(let-values ([(s b) (variants*-to-strings variants spr methods)])
(flatten-string-matrix s)))
;; VariantClasses Super (Listof Method) -> (Listof (Listof String)) Boolean
;; turns a list of Variants into a list of strings, one per line
(define (variants*-to-strings variants spr methods)
(let* ([d (apply max (map (lambda (vc) (length (second vc))) variants))]
[recursion #f])
(values
(let loop ([v variants][cnnctd #f])
(cond
[(null? v) (set! recursion cnnctd) '()]
[else (let-values ([(s b) (variant-to-strings (car v) spr cnnctd d methods)])
(cons s (loop (cdr v) (or cnnctd b))))]))
;; ordering: begin
recursion)))
;; VariantClass Super Boolean Number -> String
#;(define (variant-draw class super left-connected depth)
(define-values (s b) (variant-to-strings class super left-connected depth))
(strings->string-as-lines s))
;; VariantClass Super Boolean Number (Listof Method) ->* String Boolean
;; turns a variant class into a list of strings,
;; computes whether the class points to super
;; with hooks for refinement arrows and for recursive containment arrows
;; with depth :: max number of fields in a variant class of the uion
;; with left-connected :: whether or not a variant to the left is already rec
;; with super :: the name of the datatype
(define (variant-to-strings variant super left-connected depth methods)
(let* ([cs (class-to-strings (cons (car variant) (cons super (cdr variant))) methods)]
[head (list (car cs) (cadr cs) (caddr cs))]
[tail (cdddr cs)]
[fields (second variant)]
[types (map first fields)]
[recursion #f]
[CON "-+"]
[CN2 " +"]
[STG "--"] ;; (= (string-length CON) (string-length BLK))
[BLK " "] ;; (= (string-length CON) (string-length BLK))
[LIN " |"] ;; (= (string-length CON) (string-length LIN))
[junk (lambda _ (symbol->string (gensym)))]
[width (string-length (car cs))]
[mkln (lambda (lft ch str)
(string-append lft (make-string width ch) str))])
(values
(append
(list (string-append BLK (centered "|" width) BLK))
(map (lambda (line type)
(string-append BLK
line
(cond
[(string=? type super) (set! recursion #t) CON]
[recursion LIN]
[else BLK])))
cs
;; pad types with junk lines for class header and class bottom
(append (map junk head) types (list (junk))
(map junk methods)
(if (null? methods) '() (list (junk)))))
(build-list (- depth -1 (length fields))
(lambda _ (mkln BLK #\space (if recursion LIN BLK))))
(list
(if left-connected
(mkln STG #\- (if recursion CON STG))
(mkln BLK #\space (if recursion CN2 BLK)))))
recursion)))
;; ---------------------------------------------------------------------------
;; Deal with a single class
;; Class [(listof Method)] opt-> String
(define (class-draw class . ms)
(strings->string-as-lines (apply class-to-strings class ms)))
;; Class [(Listof Method)] opt-> (cons String (cons String (cons String (Listof String))))
;; turns a class into a list of strings that represents the class
(define (class-to-strings class . ms)
(let* ([name (first class)]
[super (second class)]
[fields (third class)]
[types (map first fields)]
[names (map second fields)]
;; start drawing
[fields (create-field-declarations fields)]
[methds (if (pair? ms) (apply create-method-declarations ms) ms)]
[width (width-class name (append methds fields))]
[separat (make-separator-line width)])
`(,separat
,((make-line width) name)
,separat
,@(map (make-line width) fields)
,separat
,@(if (null? methds) '() (map (make-line width) methds))
,@(if (null? methds) '() (list separat)))))
;; (Listof Field) -> (Listof String)
;; create text lines from Fields
(define (create-field-declarations fields)
(map (lambda (f) (string-append (string-append (first f) " " (second f))))
fields))
;; (Listof Method) -> (Listof String)
;; create text lines from Methods
(define (create-method-declarations fields) (map method fields))
;; Number -> String
;; make a separator line (+----+) of width
(define (make-separator-line width)
(string-append
LFT+
(make-string (- width (string-length LFT+) (string-length RGT+)) #\-)
RGT+))
;; Number -> (String -> String)
;; make one line in class of width from txt
(define (make-line width)
(lambda (txt)
(string-append
LEFT
txt
(make-string
(- width (string-length txt) (string-length LEFT) (string-length RIGHT))
#\space)
RIGHT)))
;; String (Cons String (Listof String)) -> Number
;; compute width of class as the widest field/name
(define (width-class name fields)
(+ (string-length LEFT)
;; longest field spec of name/class and fields
(apply max (map string-length (cons name fields)))
(string-length RIGHT)))
;; ---------------------------------------------------------------------------
;; Library
;; (Listof String) -> String
;; turn the list of strings into a single string, separating lines with newline
(define (strings->string-as-lines s)
(apply string-append (map (lambda (x) (string-append x "\n")) s)))
;; (Listof (Listof String)) -> (Listof String)
;; contract: (apply = (map length smatrix))
;; this requires Pretty Big, it could be written in Intermediate
(define (flatten-string-matrix smatrix)
(apply map (lambda l (apply string-append l)) smatrix))
;; String Number -> String
;; place str in the center of an otherwise blank string
(define (centered str width)
(let* ([len-str (string-length str)]
[lft (quotient (- width len-str) 2)]
[rgt (- width len-str lft)])
(string-append (make-string lft #\space) str (make-string rgt #\space))))
;; (cons X (listof X)) -> X
(define (last l) (car (last-pair l)))
;; (Listof Number) -> Number
(define (sum l) (foldr + 0 l))
;; ---------------------------------------------------------------------------
;; Constants
(define LEFT "| ")
(define LFT+ "+-")
(define RIGHT " |")
(define RGT+ "-+") ; (= (string-length RIGHT) (string-length RGT+))
; (define HOOK " |-o") ; (= (string-length RIGHT) (string-length HOOK))
#|Tests:
(require (lib "testing/testing.scm"))
(test== (centered "|" 2) "| ")
(test== (centered "|" 3) " | ")
"testing classes"
(define class1 (list "Class" "Super" '(("int" "capacity") ("hello" "world"))))
(define class2 (list "Class" "Super" '()))
(define expected-class
(list
"+--------------+"
"| Class |"
"+--------------+"
"| int capacity |"
"| hello world |"
"+--------------+"))
(define expected-class2
(list
"+-------+"
"| Class |"
"+-------+"
"+-------+"))
(test== (class-draw class1 '()) (strings->string-as-lines expected-class))
(test== (class-draw class2 '()) (strings->string-as-lines expected-class2))
; (printf "~a~n" (class-draw class1))
"testing variants"
(define vclass1 (list "Variant1" '()))
(define vclass2 (list "Variant2" '(("int" "x") ("boolean" "y") ("Super" "z"))))
(define vclass3 (list "Variant3" '(("String" "x") ("Super" "y") ("Super" "z"))))
(define expected-variant1
(list
" | "
" +----------+ "
" | Variant1 | "
" +----------+ "
" +----------+ "
" "
" "
" "
" "
" "))
(define expected-variant2
(list
" | "
" +-----------+ "
" | Variant2 | "
" +-----------+ "
" | int x | "
" | boolean y | "
" | Super z |-+"
" +-----------+ |"
" |"
" +"))
(define expected-variant3
(list
" | "
" +----------+ "
" | Variant3 | "
" +----------+ "
" | String x | "
" | Super y |-+"
" | Super z |-+"
" +----------+ |"
" |"
"---------------+"))
(test== (let-values ([(s b) (variant-to-strings vclass1 "Super" #f 3 '())]) s)
expected-variant1)
#;(test== (variant-draw vclass1 "Super" #f 3)
(strings->string-as-lines expected-variant1))
#;(test== (variant-draw vclass2 "Super" #f 3)
(strings->string-as-lines expected-variant2))
#;(test== (variant-draw vclass3 "Super" #t 3)
(strings->string-as-lines expected-variant3))
(test== (let-values
([(s b)
(variants*-to-strings (list vclass1 vclass2 vclass3) "Super" '())])
s)
(list expected-variant1 expected-variant2 expected-variant3))
(test== (variants*-draw (list vclass1 vclass2 vclass3) "Super" '())
(flatten-string-matrix
(list expected-variant1 expected-variant2 expected-variant3)))
(define aclass-exp ;; 19
(list " +-------+ "
" | Super |<----"
" +-------+ "
" +-------+ "))
(test== (type-to-string "Super" '() 19 #t)
aclass-exp)
(test== (dt-draw
(make-dt "Class"
'()
'()
""))
(strings->string-as-lines expected-class2))
(dt-draw (make-dt "Super" '() (list vclass1 vclass2 vclass3) ""))
(test== (dt-draw
(make-dt "Super" '() (list vclass1 vclass2 vclass3) ""))
(strings->string-as-lines
'(
" +-------+ "
" | Super |<---------------------+"
" +-------+ |"
" +-------+ |"
" | |"
" / \\ |" ;; note escape
" --- |"
" | |"
" ---------------------------------- |"
" | | | |"
" +----------+ +-----------+ +----------+ |"
" | Variant1 | | Variant2 | | Variant3 | |"
" +----------+ +-----------+ +----------+ |"
" +----------+ | int x | | String x | |"
" | boolean y | | Super y |-+ |"
" | Super z |-+ | Super z |-+ |"
" +-----------+ | +----------+ | |"
" | | |"
" +---------------+--+"
)))
(string-delta (dt-draw
(make-dt "Super"
'(("int" "x"))
'(("VC1" (("int" "x")))
("VC2" (("boolean" "b") ("int" "y")))
("VC3" (("String" "s"))))
""))
(strings->string-as-lines
'(
" +---------+ "
" | Super | "
" +---------+ "
" +---------+ "
" | int x() | "
" +---------+ "
" | "
" / \\ "
" --- "
" | "
" -------------------------------- "
" | | | "
" +-------+ +-----------+ +----------+ "
" | VC1 | | VC2 | | VC3 | "
" +-------+ +-----------+ +----------+ "
" | int x | | boolean b | | String s | "
" +-------+ | int y | +----------+ "
" +-----------+ "
" "
" "
)))
|#
)

View File

@ -1,333 +0,0 @@
#| Class Representation:
Class = (list String (Listof Field))
Field = (list String String)
|#
(module draw-txt mzscheme
(require mzlib/etc
mzlib/list)
;; Class (Listof Classes) -> (Listof String)
(define (class-union-to-strings utype variants)
(let* ([ac (class-to-strings utype)]
[classes (classes-to-strings variants (car utype))]
[v (flatten-string-matrix classes)]
[Lv (string-length (first v))]
[the-core
(append
(center-picture Lv ac)
(center-picture Lv REFINEMENT-ARROW)
(center-picture Lv (refinement-connectors classes))
v)]
[foo 0])
(map (lambda (x)
(set! foo (+ foo 1))
(cond
[(> foo 2) (string-append x "|")]
[(= foo 1) x]
[(= foo 2) (replace-end-with-back-arrow x)]))
the-core)))
;; String -> String
;; add the containment arrow to an abstract class from the right fringe
(define (replace-end-with-back-arrow x0)
(list->string
(reverse!
(cons #\+
(let loop ([x (reverse (string->list x0))])
(cond
[(char=? (cadr x) #\|) (cons #\< (cdr x))]
[else (cons #\- (loop (cdr x)))]))))))
;; (Listof String) -> (Listof String)
(define (refinement-connectors class-pictures)
(let ([center-char
(lambda (line c l r)
(car (center-picture (string-length line) (list c) l r)))])
(list
(string-append
(center-char (caar class-pictures) "+" #\space #\-)
(let loop ([cp (rest class-pictures)])
(cond
[(null? (rest cp))
(center-char (caar cp) "+" #\- #\space)]
[else (string-append (center-char (caar cp) "+" #\- #\-)
(loop (rest cp)))])))
(foldr (lambda (f r)
(string-append (car (center-picture (string-length (car f)) (list "|"))) r))
""
class-pictures)
)))
;; Number (Listof String) -> (Listof String)
(define center-picture
(opt-lambda (Lv ac (l #\space)[r #\space])
(let* ([delta (- Lv (string-length (first ac)))]
[lft (quotient delta 2)])
(map (pad-lines (make-string lft l) (make-string (- delta lft) r)) ac))))
(define REFINEMENT-ARROW
(list "/ \\"
"---"
" | "))
;; Class String *-> String
(define (classes-draw classes . super)
(strings->string-as-lines (apply classes-to-strings classes super)))
;; Class -> String
(define (class-draw class)
(strings->string-as-lines (class-to-strings class)))
;; (Listof Class) String *-> (Listof (Listof String))
;; take a list of classes and produce a single "line" (listof string-lines)
(define (classes-to-strings classes0 . super)
(let* (;; (Listof (Listof String))
[classes (map (lambda (c) (apply class-to-strings c super)) classes0)]
[L (apply max (map length classes))]
[FOO " "]
[classes (foldr (lambda (class-los is-self-recursive rest)
(if (null? super)
(map (pad-lines FOO FOO)
(if (>= (length class-los) L)
class-los
(pad-class-with-blank-lines L class-los)))
(cons
(append
(map (pad-lines FOO FOO)
(if (>= (length class-los) L)
class-los
(pad-class-with-blank-lines L class-los)))
(list
(case is-self-recursive
[(long)
(string-append
"--"
(make-string (string-length (first class-los)) #\-)
CROSS
(if (null? rest) "--" ""))]
[(short)
(string-append
" "
(make-string (string-length (first class-los)) #\space)
CROSS
(if (null? rest) "--" ""))]
[(conn)
(string-append
"--"
(make-string (string-length (first class-los)) #\-)
NOCROSS
(if (null? rest) "--" ""))
]
[(none)
(string-append
" "
(make-string (string-length (first class-los)) #\space)
FOO)])))
rest)))
'()
classes
(let loop ([c classes0][prior #f])
(cond
[(null? c) '()]
[else (let ([self-recursive (apply is-recursive? (car c) super)])
(cond
[(and self-recursive prior) (cons 'long (loop (cdr c) #t))]
[self-recursive (cons 'short (loop (cdr c) #t))]
[prior (cons 'conn (loop (cdr c) #t))]
[else (cons 'none (loop (cdr c) #f))]))])))])
classes))
(define is-recursive?
(case-lambda
[(class) #f]
[(class super)
(let* ([name (first class)]
[fields (second class)]
[types (map first fields)])
(member super types))]))
(define CROSS "-+-")
(define NOCROSS "---")
;; Number (Cons String (Listof String)) -> (Listof String)
(define (pad-class-with-blank-lines n l)
(let ([blanks (make-string (string-length (first l)) #\space)])
(append l (build-list (- n (length l)) (lambda (i) blanks)))))
;; Class String *-> (Listof String)
;; the presence of super suggests that we want to draw a line to super
(define (class-to-strings class . super)
(let* ([is-super? (if (null? super)
(lambda (x) false)
(lambda (x) (string=? (car super) x)))]
[name (first class)]
[fields (second class)]
[types (map first fields)]
[names (map second fields)]
[fields (create-field-declarations fields)]
[width (width-class name fields)]
[separat (make-separator-line width)]
[separat-hasa (make-separator-line width #t)]
[start-hasa #f])
(cond
[(and (cons? super) (ormap is-super? types))
`(,separat
,((make-line width) name)
,separat
,@(map (lambda (line type)
(cond
[(is-super? type) (set! start-hasa #t) [(make-line width HOOK) line]]
[start-hasa [(make-line width HASA) line]]
[else ((make-line width) line)]))
fields types)
,separat-hasa)]
[else
`(,separat
,((make-line width) name)
,separat
,@(map (make-line width) fields)
,separat)])))
;; (Listof Field) -> (Listof String)
(define (create-field-declarations fields)
(map (lambda (f) (string-append (string-append (first f) " " (second f))))
fields))
;; String Boolean *-> String
(define (make-separator-line width . hasa)
(string-append LFT+ (make-string (- width (string-length LFT+) (string-length RGT+)) #\-)
(if (null? hasa) RGT+ HASA+)))
;; Number String -> String
;; make one line in class of width from txt
(define (make-line width . rgt)
(lambda (txt)
(string-append
LEFT
txt
(make-string
(- width (string-length txt) (string-length LEFT) (string-length RIGHT))
#\space)
(if (null? rgt) RIGHT (car rgt)))))
(define LEFT " | ")
(define LFT+ " +-")
(define RIGHT " | ")
(define HOOK " |-o") ; (= (string-length RIGHT) (string-length HOOK))
(define RGT+ "-+ ") ; (= (string-length RIGHT) (string-length RGT+))
(define HASA " | |") ; (= (string-length RIGHT) (string-length HASA))
(define HASA+ "-+ |") ; (= (string-length RIGHT) (string-length RGT+))
;; String (Cons String (Listof String)) -> Number
;; compute width of class as the widest field/name
(define (width-class name fields)
(+ (string-length LEFT)
;; longest field spec of name/class and fields
(apply max (map string-length (cons name fields)))
(string-length RIGHT)))
;; String String -> (String -> String)
;; add lft and rgt to txt
(define (pad-lines lft rgt) (lambda (txt) (string-append lft txt rgt)))
;; (Listof (Listof String)) -> (Listof String)
;; contract: (apply = (map length smatrix))
;; this requires Pretty Big, it could be written in Intermediate
(define (flatten-string-matrix smatrix)
(apply map (lambda l (apply string-append l)) smatrix))
;; (Listof String) -> String
;; turn the list of strings into a single string, separating lines with newline
(define (strings->string-as-lines s)
(apply string-append (map (lambda (x) (string-append x "\n")) s)))
;; Basic Tests:
(equal?
(flatten-string-matrix
(list (list "a1" "a2" "a3") (list "b1" "b2" "b3") (list "c1" "c2" "c3")))
(list "a1b1c1" "a2b2c2" "a3b3c3"))
;; Tests
(define aTrain (list"Train"'(("int" "capacity") ("hello" "world"))))
(define sTrain (list"Train"'(("int" "capacity"))))
(test== (width-class (car aTrain) (create-field-declarations (cadr aTrain)))
(+ 12 (string-length LEFT) (string-length RIGHT)))
(test== ([make-line (+ 12 (string-length LEFT) (string-length RIGHT))] "int capacity")
" | int capacity | ")
(test== (make-separator-line (+ 12 (string-length LEFT) (string-length RIGHT)))
" +--------------+ ")
(define expected-class
(list
" +--------------+ \n"
" | Train | \n"
" +--------------+ \n"
" | int capacity | \n"
" | hello world | \n"
" +--------------+ \n"))
(test== (class-draw aTrain)
(apply string-append expected-class))
(test== (classes-to-strings (list sTrain aTrain))
'((" +--------------+ "
" | Train | "
" +--------------+ "
" | int capacity | "
" +--------------+ "
" ")
(" +--------------+ "
" | Train | "
" +--------------+ "
" | int capacity | "
" | hello world | "
" +--------------+ ")))
;; Union: ARiver = Source(Location) | Confluence(Location, ARiver, ARiver)
(define ARiver
(list "ARiver" '()))
(define Source
(list "Source" '(("Location" "loc"))))
(define Confluence
(list "Confluence" '(("Location" "loc") ("ARiver" "left") ("ARiver" "right"))))
(test== (strings->string-as-lines
(class-union-to-strings ARiver (list Source Confluence)))
(strings->string-as-lines
'(" +--------+ "
" | ARiver |<---------------------+"
" +--------+ |"
" +--------+ |"
" / \\ |" ;; note escape
" --- |"
" | |"
" +--------------------------+ |"
" | | |"
" +--------------+ +--------------+ |"
" | Source | | Confluence | |"
" +--------------+ +--------------+ |"
" | Location loc | | Location loc | |"
" +--------------+ | ARiver left |-o |"
" | ARiver right |-o |"
" +--------------+ | |"
" -+----|")))
(test== (replace-end-with-back-arrow "| ARiver | ")
"| ARiver |<----+"
"replace end with back arrow")
(printf "~a" (strings->string-as-lines (class-union-to-strings ARiver (list Source Confluence))))
)

View File

@ -1,11 +0,0 @@
#lang setup/infotab
(define name "ProfessorJ Wizard")
(define tools '(("tool.ss")))
(define tool-names '("ProfessorJ Wizard"))
(define compile-omit-paths
'("draw-txt0.ss"
"macro-class.scm"
"view0.scm"
"data-defs0.scm"))

View File

@ -1,46 +0,0 @@
#cs(module macro-class mzscheme
(require-for-syntax (file "class.scm") (file "aux-syntax.scm"))
(provide
class ;; (class Name Super (Type Name) ...)
union ;; (union Type [Class (Type Name) ...] ...)
)
(define-syntax (class stx)
(syntax-case stx ()
[(class Name Super (FType FName) ...)
(printf
(make-class
(list (identifier->string (syntax Name))
(identifier->string (syntax Super))
(map (lambda (x)
(let* ([x (syntax-e x)]
[type (identifier->string (car x))]
[name (identifier->string (cadr x))])
(list type name)))
(syntax->list (syntax ((FType FName) ...)))))))
(syntax (void))]))
(define-syntax (union stx)
(syntax-case stx (withToString withTemplate)
[(union Type [Class (FType FName) ...] ... withToString)
(syntax 10)]
[(union Type [Class (FType FName) ...] ...)
(printf
(make-union
(list (identifier->string (syntax Type))
(map (lambda (x)
(let* ([x (syntax-e x)]
[class (identifier->string (car x))]
[fields (map (lambda (f)
(let* ([x (syntax->list f)]
[type (identifier->string (car x))]
[name (identifier->string (cadr x))])
`(,type ,name)))
(cdr x))])
(cons class fields)))
(syntax->list (syntax ((Class (FType FName) ...) ...)))))))
(syntax (void))]))
)

View File

@ -1,59 +0,0 @@
#|
The Java Wizard helps programmers create
* classes
* datatypes via classes.
The class wizard requests class name, superclass, and field specifications.
From these, it generates a class, its constructor, and optionally a partial
template for methods, a toString method, and a diagram.
The union wizard requests a union name and specifications for the variants.
From these, it generates an abstract class (for the union name) and one
variant class that extends the abstract class per variant specification.
Again, it optionally adds templates, a toString method, and a diagram.
Both wizards generate their text in a language-sensitive manner. For
Beginner and Intermediate, they omit privacy specifications.
The wizards are added to the Special menu and insert text at the current
point.
At the moment they cannot read back code and help with natural program
edits and transformations.
The two major files are:
wizard.ss, which is the view and provides the user interaction
class.scm, which is the model and provides the functions for turning
a spec into a string that represents a class or a union.
Also, class.scm does not use the Java implementation to perform basic
checks on the information. It just leaves this to the programmer. So, for
example, if a programmer says a field has type "moo" and "moo" doesn't
exist as a class, then the wizard inserts a buggy class.
|#
BUGS:
* union:
** when a programmer changes the name of the Union after the variants have
been specified, the wizard fails to change the type name in the
variants.
* drawing:
** the Union wizard draws the method specs into the boxes for the
classes. The book "thinks" of them as inherited.
view
FEATURES:
** re-enable the method template creation in view
== the creation of method stubs depends on language level
** allow the introduction of an abstract class for common features in
Unions (common fields, common methods)
** specification of mutually recursive features

View File

@ -1,108 +0,0 @@
(module tool mzscheme
(require "class.scm"
"union.ss"
"view.scm"
"draw-txt.ss"
"data-defs.scm"
drscheme/tool
(only drscheme/private/drsig drscheme:language-configuration^)
framework
mred
mzlib/unit
mzlib/etc
mzlib/class
string-constants
mzlib/contract)
(provide tool@)
(define tool@
(unit
(import drscheme:tool^)
(export drscheme:tool-exports^)
(define (phase1) (void))
(define (phase2) (void))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Wire up to DrScheme
;;
;; insert a Java Class
(define (java-class-wizard-mixin %)
(class %
(inherit get-insert-menu get-edit-target-object register-capability-menu-item)
(super-new)
#;
(define-syntax tee
(syntax-rules ()
((_ x)
(let* ([a (format "--> ~a\n" 'x)]
[y x]
[b (format "==> ~a\n" y)])
(message-box "error" (format "~a~a" a b))
y))))
(define (tee x) x)
;; String (LANGUAGE-LEVEL -> X) (X ... -> String) (X ... -> String) -> Void
;; create a menu item for inserting classes and interfaces
(define (make-menu-item% descr get-info make draw)
(define (A menu event)
;; ---------------------------------------------------------------
;; does the current language need 'public' for 'interface methods'
(define foo (send this get-current-tab))
(define bar (send foo get-defs))
(define moo (send bar get-next-settings))
(define koo
(drscheme:language-configuration:language-settings-language moo))
(define current-language* (tee (send koo get-language-position)))
;; ---------------------------------------------------------------
(define language-level
(let* ([simple* (tee (member "ProfessorJ" current-language*))]
[begin-> (tee (and simple* (cadr simple*)))])
(tee
(cond
[begin-> begin->]
[(boolean? simple*) PROFESSIONAL]
[(eq? (cadr simple*) BEGINNER) BEGINNER]
[(eq? (cadr simple*) INTERMEDIATE) INTERMEDIATE]
[else PROFESSIONAL]))))
;; get the editor and insert the desired items ...
(define editor (get-edit-target-object))
(define-values (b class-as-info) (get-info language-level))
;; ... the class
(when class-as-info
(let ([class-as-text (apply make (append class-as-info (list language-level)))])
(when b
;; ... the diagram
(send editor insert (format "/*~n~a~n*/~n~n" (draw (car class-as-info)))))
(send editor insert class-as-text))))
(define (enable mi)
(send mi enable ((get-edit-target-object) . is-a? . text%)))
(new menu-item%
(label descr)
(parent (get-insert-menu))
(callback A)
(demand-callback enable)))
(make-menu-item% (string-constant profjWizward-insert-java-class) get-class-info make-class class-draw)
(register-capability-menu-item 'profjWizard:special:java-class
(get-insert-menu))
(make-menu-item% (string-constant profjWizard-insert-java-union) get-union-info make-union dt-draw)
(register-capability-menu-item 'profjWizard:special:java-union
(get-insert-menu))))
(drscheme:get/extend:extend-unit-frame java-class-wizard-mixin)
(drscheme:language:register-capability 'profjWizard:special:java-class
(flat-contract boolean?) #f)
(drscheme:language:register-capability 'profjWizard:special:java-union
(flat-contract boolean?) #f)
))
)

View File

@ -1,239 +0,0 @@
#cs
(module union mzscheme
(require "data-defs.scm"
"class.scm"
mzlib/contract
mzlib/etc
mzlib/list)
(provide/contract
[make-union ((Union) (boolean? boolean? string?) . opt-> . string?)]
)
#| Usage:
(make-union a-union toString? template?)
create a Java implementation of a datatype specification using an
interface and N variants.
The first optional boolean parameter specifies whether we want toString
in the class hiearchy. Default: true
The second optional boolean parameter specifies whether we want
a draft method template in comments. Default: true
|#
;; ------------------------------------------------------------------------
;; Construct a union as a collection of Java classes
;; String (Listof VariantClass) -> String
(define make-union
(opt-lambda (the-union [toString? #t][template? #t][language BEGINNER])
(define type (dt-type the-union))
(define met* (dt-methods the-union))
(string-append
(car (purpose-statement (dt-purpose the-union)))
(interface type template? met*)
"\n"
(enumerate-with-separator
(map (lambda (sc)
(make-class `(,(car sc) ,type ,(cadr sc) ,(variant-purpose sc))
toString?
template?
language
'()
met*))
(dt-variants the-union))
"\n"))))
;; String Boolean [Listof Method] -> String
(define (interface type template? methods)
(apply string-append
`(,(format abstractF type)
;; constant fields, e.g.,
;; int NORTH = 0;
;; shouldn't be allowed yet
,@(map (lambda (x) (format " ~a;\n" (method x))) methods)
;; optional abstract template
""
,endclf)))
;; String (listof Field) Boolean? -> String
(define (abstractClass type fields template?)
`(...
,@(if (not template?)
(list "")
`( ,cmnt/*
,warnin
,purpos
,absteg
,cmnt*/))
...))
;; Abstract Class
(define abstractF "interface ~a {\n")
(define absteg " abstract ??? mmm();\n")
#| Tests:
(require (lib "testing/testing.scm"))
(test== (interface "Foo" #f '())
(string-append
"interface Foo {\n"
"}\n")
"simple interface")
(test== (interface "Foo" #f '(("double" "distance" "int" "int")))
(string-append
"interface Foo {\n"
" double distance(int x,int y);\n"
"}\n")
"simple interface with methods")
(make-union
(make-dt "AList" '() '(("MT" ()) ("Cons" (("int" "first") ("AList" "rest")))) "")
#f #f)
(test==
(make-union
(make-dt "AList" '() '(("MT" ()) ("Cons" (("int" "first") ("AList" "rest")))) "")
#f #f)
(apply string-append
`(
"interface AList {\n"
"}\n"
"\n"
"class MT implements AList {\n"
"\n"
" MT() {\n"
" }\n"
"}\n"
"\n"
"class Cons implements AList {\n"
" int first;\n"
" AList rest;\n"
"\n"
" Cons(int first, AList rest) {\n"
" this.first = first;\n"
" this.rest = rest;\n"
" }\n"
"}\n"
)
)
"partial make union")
(test==
(make-union
(make-dt "AList"
;; common methods:
'(("???" "mmm"))
;; variants:
'(("MT" ())
("Cons" (("int" "first") ("AList" "rest")))) "")
#t #t PROFESSIONAL)
(apply string-append
`(
"interface AList {\n"
" ??? mmm();\n"
"}\n"
"\n"
"class MT implements AList {\n"
"\n"
" MT() {\n"
" }\n"
"\n"
"/*\n"
,warnin
" public ??? mmm() {\n"
" }\n"
"*/\n"
"\n"
" public String toString() {\n"
" return \"new MT(\" + \")\";\n"
" }\n"
"}\n"
"\n"
"class Cons implements AList {\n"
" int first;\n"
" AList rest;\n"
"\n"
" Cons(int first, AList rest) {\n"
" this.first = first;\n"
" this.rest = rest;\n"
" }\n"
"\n"
"/*\n"
,warnin
" public ??? mmm() {\n"
" ... this.first ...\n"
" ... this.rest.mmm(...) ...\n"
" }\n"
"*/\n"
"\n"
" public String toString() {\n"
" return \"new Cons(\" + first + \",\" + rest.toString() + \")\";\n"
" }\n"
"}\n"
)
)
"full make union")
(test==
(make-union
(make-dt "AList" '() '(("MT" ()) ("Cons" (("int" "first") ("AList" "rest")))) "hello world")
#f #f)
(apply string-append
`("// hello world\n"
"interface AList {\n"
"}\n"
"\n"
"class MT implements AList {\n"
"\n"
" MT() {\n"
" }\n"
"}\n"
"\n"
"class Cons implements AList {\n"
" int first;\n"
" AList rest;\n"
"\n"
" Cons(int first, AList rest) {\n"
" this.first = first;\n"
" this.rest = rest;\n"
" }\n"
"}\n"
)
)
"make union with purpose statement")
(test==
(make-union
(make-dt
"AList" '() '(("MT" ()) ("Cons" (("int" "first") ("AList" "rest")) "pair")) "hello world")
#f #f)
(apply string-append
`("// hello world\n"
"interface AList {\n"
"}\n"
"\n"
"class MT implements AList {\n"
"\n"
" MT() {\n"
" }\n"
"}\n"
"\n"
"// pair\n"
"class Cons implements AList {\n"
" int first;\n"
" AList rest;\n"
"\n"
" Cons(int first, AList rest) {\n"
" this.first = first;\n"
" this.rest = rest;\n"
" }\n"
"}\n"
)
)
"make union with purpose statement for variants")
|#
)

View File

@ -1,642 +0,0 @@
(module view mzscheme
(require "assoc-list.scm"
"aux-class.scm"
"data-defs.scm"
"class.scm"
"union.ss"
mred
mzlib/class
mzlib/etc
mzlib/list
srfi/13/string
mzlib/contract)
(provide/contract
[get-class-info (opt->* () [Language] [boolean? (union false/c (list/c Class boolean? boolean?))])]
[get-union-info (opt->* () [Language] [boolean? (union false/c (list/c Union boolean? boolean?))])])
(define CLASS-WIZARD "The Class Wizard")
(define UNION-WIZARD "The Union Wizard")
(define VARIANT-WIZD "The Variant Wizard")
(define VARIANT "Variant")
(define INSERT-CLASS "Insert Class")
(define INSERT-UNION "Insert Union")
(define INSERT-VARNT "Insert Variant")
(define ADD-FIELD "Add Field")
(define ADD-VARIANT "Add Variant")
(define ADD-INTERF "Add Interface Method")
(define ADD-TOSTRING "add toString()")
(define ADD-TEMPLATE "add method template")
(define ADD-DIAGRAM "add class diagram")
(define PURPOSE-CLASS "// purpose of class: ")
(define PURPOSE-UNION "// purpose of union: ")
(define CLASS "class")
(define SUPER "super")
(define IMPLEMENTS "implements")
(define EXTENDS "extends")
(define CHECK-NAME-F "check name of ~a")
(define CHECK-TYPE-F "check type for ~a")
(define CHECK-FIELD-NAME-F "check field name for ~a")
(define TYPE "type")
(define NAME "name")
(define ABORT "Cancel")
(define ERROR "Error")
(define DELETE "Delete")
(define EDIT "Edit")
#|
present a dialog to create a single class;
if programmer aborts, return #f
otherwise, produce a class and two booleans, requesting toString and draft
templates, respectively
|#
(define (get-class-info . opt)
(define ci (new class-info% (title CLASS-WIZARD)
(switches? (and (pair? opt) (not (eq? (car opt) BEGINNER))))
(insert-str INSERT-CLASS) (add-str ADD-FIELD)))
(send ci call))
(define (get-union-info . opt)
(define ui (new union-info% (title UNION-WIZARD)
(switches? (and (pair? opt) (not (eq? (car opt) BEGINNER))))
(insert-str INSERT-UNION) (add-str ADD-VARIANT)))
(send ui call))
#|
*---------------------*
| dialog% |
*---------------------*
|
|
/ \
*---------------------*
| class-union-wizard% |
*---------------------*
| tostring? |
| template? |
| error-message |
| call |
| A: produce |
| A: make-class-cb |
*---------------------*
|
|
/ \
--------------------------------------------
| |
*---------------------* *---------------------*
| class-info% | | union-info% |
*---------------------* *---------------------*
| |--+ | vart-panel |--+
*---------------------* *---------------------* |
|
|
|
|
*---------------------* *---------------------* |
| vertical-panel% | | horizontal-panel% | |
*---------------------* *---------------------* |
| | |
| | |
/ \ / \ |
*---------------------* *---------------------*
| field-panel% | | variant-panel% |
*---------------------* *---------------------*
| add | | add |
| add-on-return | | produce |
| produce | *---------------------*
*---------------------* | acquired: |
| acquired: | | get-type |
| window (?) | | error-message |
| error-message | *---------------------*
*---------------------*
|#
;; ------------------------------------------------------------------------
;; Set up the frame, including the info-panel where subclasses can
;; request specific information. The frame includes buttons for aborting
;; the edit process, for packaging up the information in the edit, and for
;; adding some component (field, variant)
;; String String String -> ClassUnionWizard
(define class-union-wizard%
(class dialog% (init-field title insert-str add-str (switches? #t) (no-diagram #f))
(super-new (label title) (width 500) (height 400))
(define p (new vertical-pane% (parent this)))
;; switches for toString methods and template in comments
(define switch-pane (add-horizontal-panel p))
(define-values (string #;template diagram)
(cond
[switches?
(values (make-checkbox switch-pane ADD-TOSTRING)
#;
(let ([c (make-checkbox switch-pane ADD-TEMPLATE)])
(send c set-value #t)
c)
(make-checkbox switch-pane ADD-DIAGRAM))]
[no-diagram (values #f #;#f #f)]
[else (values #f #;#f (make-checkbox switch-pane ADD-DIAGRAM))]))
(define (get-switch x)
(cond
[(eq? x diagram) (and (not no-diagram) (send x get-value))]
[switches? (send x get-value)]
[else #f]))
(define/public (tostring?) (get-switch string))
(define/public (template?) #;(get-switch template) #f)
(define/public (diagram?) (get-switch diagram))
;; --------------------------------------------------------------------
;; info panel
(field (info-pane (new vertical-panel% (parent p) (style '(border)))))
;; --------------------------------------------------------------------
;; error handling
;; String -> false
(define/public (error-message ctl m)
(when (ctl . is-a? . text-field%)
(send ctl focus)
(let ([e (send ctl get-editor)])
(send e set-position 0 (send e last-position))))
(message-box ERROR
m
(send ctl get-top-level-window)
'(ok stop))
(raise an-error))
;; TextField (union false String) -> java-id?
(define/public (produce-name-from-text name msg)
(let ([x (string-trim-both (send name get-value))])
(cond
[(not msg) x]
[(java-id? x) x]
[else (error-message name (format CHECK-NAME-F msg))])))
;; --------------------------------------------------------------------
;; Buttons
(define button-panel
(new horizontal-panel% (parent p) (stretchable-height #f) (alignment '(right center))))
(define abort? #t) ;; assume bad things happen
(define (quit x e) (send this show #f))
(add-button button-panel ABORT quit)
(define/abstract make-class-cb)
(new button% (label insert-str) (parent button-panel)
(style '(border))
(callback
(lambda (x e)
(when (make-class-cb x e)
(set! abort? #f)))))
;; --------------------------------------------------------------------
;; call in
(define/public (call)
(send this show #t)
(values (diagram?) (if abort? #f (produce))))
(define/abstract produce)))
;; ------------------------------------------------------------------------
;; String String String [String] [String] -> ClassUnionWizard
;; get information about a class (fields, purpose statement, ...)
(define class-info%
(class class-union-wizard%
(init-field (a-super null) (a-v-class null))
(super-new)
(inherit-field info-pane)
(inherit tostring? template? diagram? error-message produce-name-from-text)
;; --------------------------------------------------------------------
;; filling the info-pane
;; Information about the class in general:
(define purpose
;; it is not the kind of textbox that make-text-field creates
(new text-field% (parent info-pane) (label PURPOSE-CLASS) (callback void)))
(define class-pane (add-horizontal-panel info-pane))
; (define class-privacy (make-modifier-menu class-pane))
(define class-name (make-text-field class-pane CLASS))
(define (super-cb x e) (send field-panel add-on-return x e))
(define super-name (make-text-field class-pane IMPLEMENTS super-cb))
;; Information about the class's fields:
(define field-pane (new vertical-panel% (parent info-pane) (style '(border))))
(define field++ (add-button field-pane ADD-FIELD (lambda (x y) (send field-panel add))))
(define field-panel
(new field-panel%
(parent field-pane) (window this)
(error-message (lambda (ctl x) (error-message ctl x)))))
;; --------------------------------------------------------------------
;; creating the class from the specification
;; -> (union false (list Class boolean? boolean?))
(define/override (produce)
(with-handlers ([an-error? (lambda _ #f)])
(list (list (produce-name-from-text class-name CLASS)
(produce-name-from-text
super-name (if (null? a-super) #f SUPER))
(send field-panel produce)
(send purpose get-value))
(tostring?)
(template?))))
;; if the class specification is proper, hide dialog
(define/override (make-class-cb x e)
(and (produce) (send this show #f)))
;; --------------------------------------------------------------------
;; setting it all up
;; String -> Void
;; set up the super class, uneditable
(define (setup-super a-super)
(send super-name set-value a-super)
(send (send super-name get-editor) lock #t))
;; init depending on inputs ...
(cond
[(and (null? a-super) (null? a-v-class))
(send field-panel add)]
[(null? a-v-class)
(send field-panel add)
(setup-super a-super)]
[(null? a-super)
(error 'internal "can't happen: no super, but class provided")]
[else ;
(setup-super a-super)
(let ([name (car a-v-class)]
[the-fields (cadr a-v-class)])
(send class-name set-value name)
(for-each (lambda (f) (send field-panel add f)) the-fields)
(send purpose set-value (variant-purpose a-v-class)))])))
;; Panel Window (String -> Void) -> FieldPanel
;; manage text fields to add fields to the class in a stack like fashion;
;; add one on <return>, allow users to delete one
;; produce the field specs on demand
(define field-panel%
(class vertical-panel%
(init-field window error-message)
(super-new)
;; (Listof TextField)
;; the list of name TextFields that have been added via (add)
;; a stack in that the bottom field is always at beginning of list
;; if empty, there are no fields
(define the-last-field-name '())
;; TextField -> Void
;; push f on the-last-field-name
(define (add-field-name f)
(set! the-last-field-name (cons f the-last-field-name)))
;; TextField -> Void
;; remove from "stack"
(define (remove-field-name f)
(set! the-last-field-name (remove f the-last-field-name)))
;; TextField Event -> Void
;; a callback that on return creates a new "add field" panel when
;; it's the bottom most text field
(define/public (add-on-return x e)
(when (eq? (send e get-event-type) 'text-field-enter)
(when (or (null? the-last-field-name)
(eq? (car the-last-field-name) x))
(add))
(send window on-traverse-char (new key-event% (key-code #\tab)))))
;; -> TextField TextField
;; (list String String) -> TextField TextField
;; add a field panel so that a new field for the class can be specified
;; if one argument, it consists of two strings:
;; one for the type, one for name
(define/public add
(case-lambda
[()
(send window begin-container-sequence)
(let* ([fp (add-horizontal-panel this)]
; [modi (make-modifier-menu fp)]
[type (make-text-field fp " ")]
[name (make-text-field fp "" (lambda (x e) (add-on-return x e)))]
[get-values
(lambda () ; (send modi get-string-selection)
(list type name))])
(send type set-value "<field type>")
(send name set-value "<field name>")
(add-field-name name)
(send fields add type get-values)
(make-delete-button this fp (lambda ()
(send fields remove type)
(remove-field-name name)))
(send window end-container-sequence)
(values type name))]
[(a-field)
(let-values ([(type name) (add)])
(send type set-value (car a-field))
(send name set-value (cadr a-field)))]))
;; --------------------------------------------------------------------
;; managing the fields of the class
(define fields (new assoc%))
(define/public (produce)
(foldr ;; r gives me the right order
(lambda (v r)
(let* ([type-ctl (car v)]
[name-ctl (cadr v)]
[type (string-trim-both (send type-ctl get-value))]
[name (string-trim-both (send name-ctl get-value))])
(cond
[(and (java-id? type) (java-id? name))
(cons (list type name) r)]
[(java-id? type)
(error-message name-ctl (format CHECK-FIELD-NAME-F type))]
[(java-id? name)
(error-message type-ctl (format CHECK-TYPE-F name))]
[else r])))
'()
(map (lambda (th) (th)) (send fields list))))))
;; ---------------------------------------------------------------------------
;; -> UnionInfo
;; get information about a datatype union
(define union-info%
(class class-union-wizard%
(super-new)
(inherit-field info-pane switches?)
(inherit tostring? template? error-message produce-name-from-text)
;; -----------------------------------------------------------------------
;; filling in the info-pane
(define type-pane
(new vertical-panel% (parent info-pane)
(alignment '(center center)) (style '(border))
(min-height 50) (stretchable-height #f)))
(define purpose
(new text-field%
(parent type-pane) (label PURPOSE-UNION) (callback void)))
(define type-text (make-text-field type-pane TYPE))
;; -> String
(define (get-type) (produce-name-from-text type-text TYPE))
;; --- the variants of the union
(define meth-pane (new vertical-panel% (parent info-pane) (style '(border))))
(add-button meth-pane ADD-INTERF (lambda (x y) (send methods add)))
(define methods (new methods-pane% (window meth-pane) (error-message (lambda (ctl x) (error-message ctl x)))))
(send methods add)
(unless switches?
(send info-pane change-children (lambda (x) (remq meth-pane x))))
;; --- the variants of the union
(define vart-pane (new vertical-panel% (parent info-pane) (style '(border))))
(add-button vart-pane ADD-VARIANT (lambda (x y) (send vart-panel add)))
(define vart-panel
(new variant-panel%
(parent vart-pane)
(get-type (lambda () (get-type)))
(error-message (lambda (ctl x) (error-message ctl x)))))
;; -> Union
(define/override (produce)
(with-handlers ([an-error? (lambda _ #f)])
(define m (send methods produce))
(list
(make-dt (get-type)
m
(send vart-panel produce)
(send purpose get-value))
(tostring?)
(template?))))
(define/override (make-class-cb x e)
(and (produce) (send this show #f)))
;; make two variants to boot
;; allow people to add and delete a variant
(send vart-panel add)
(send vart-panel add)))
;; get information about all panels
(define methods-pane%
(class vertical-panel%
(init-field window error-message)
(super-new (parent window) (min-height 10) (stretchable-height #f))
(define methods (new assoc%))
;; add a pane to the window for specifying one method signature
(define/public (add)
(send window begin-container-sequence)
(new method-panel%
(parent window) (style '(border))
(window window) (error-message error-message) (methods methods))
(send window end-container-sequence))
(define/public (produce) (send methods list))))
;; get information about a single method signature
(define method-panel%
(class horizontal-panel%
(init-field window error-message methods)
(super-new)
;; -----------------------------------------------------------------------
;; the callbacks
;; remove this pane from the window and its information from the table
(define (remove _1 _2)
(send methods remove this)
(send this begin-container-sequence)
(send window change-children (lambda (x) (remq this x)))
(send window container-flow-modified)
(send this end-container-sequence))
;; [Listof TextField%]
(define pa* '())
;; (union false '_) '_ -> Void
;; add this parameter TextField% to pane
(define (add-parameter-field button-or-false _2)
(define _ (send this begin-container-sequence))
(define x (make-text-field this (if button-or-false "," "") void pt))
(set! pa* (append pa* (list x)))
(send this change-children
(lambda (y)
(remq y pa*)))
(send this end-container-sequence))
;; re-establish this pane so that programmers can edit the method info
(define (edit _1 _2)
(send this begin-container-sequence)
(send this change-children
(lambda (y) (append (list (car y)) (list ret nam opn) pa* end)))
(send this end-container-sequence))
;; retrieve, check, add method signature to table
(define (convert-info-to-signature button event)
(with-handlers ([an-error? (lambda (x) #f)])
(define sig
(let ([ctls (cons nam (cons ret pa*))])
(check-sig
(map (lambda (x) (send x get-value)) ctls)
ctls)))
(define _ (send this begin-container-sequence))
(define t (new message% (parent this) (label (method sig))))
(define e (new button% (parent this) (label EDIT) (callback edit)))
(send this change-children (lambda (y) (cons (car y) (list t e))))
(send e focus)
(send methods add this sig)
(send this end-container-sequence)))
;; (cons String (cons String (Listof String))) -> Method
;; check signature
(define (check-sig sig ctls)
(define name (string-trim-both (car sig)))
(define typ* (map string-trim-both (cdr sig)))
(unless (java-id? name)
(error-message (car ctls) (format "not a java id: ~s" name)))
(let ([typ*
(let loop ([types* typ*][ctls (cdr ctls)])
(cond
[(null? types*) '()]
[(string=? (car types*) "")
(if (null? (cdr types*))
'()
(error-message (car ctls) bad-para))]
[else
(if (java-id? (car types*))
(cons (car types*) (loop (cdr types*) (cdr ctls)))
(error-message (car ctls) (format no-type (car types*))))]))])
(cons (car typ*) (cons name (cdr typ*)))))
(define bad-para
"\"\" parameter type found, but not at the end of the parameter list")
(define no-type "not a java type: ~s")
(define pt "<parameter type>")
;; ---------------------------------------------------------------------
;; now set up the one-line pane for specifying a method signature
(send window begin-container-sequence)
(define sub (new button% (parent this) (label "-") (callback remove)))
;; (make-delete-button ... when purpose statement is added/?
(define ret (make-text-field this "" void "<return type>"))
(define nam (make-text-field this "" void "<method name>"))
(define opn (new message% (parent this) (label "(")))
(define pa+ (new button% (parent this) (label ", ...") (callback add-parameter-field)))
(define cls (new message% (parent this) (label ")")))
(define add (new button% (parent this) (label "+") (callback convert-info-to-signature)))
(define end (list pa+ cls add))
;; ---------------------------------------------------------------------
(add-parameter-field #f '__)
(send window end-container-sequence)))
;; (-> String) (String -> Void) (Any -> Boolean) -> VariantPanel
;; manage the variant panels and their content for union
(define variant-panel%
(class horizontal-panel%
(super-new (alignment '(center center)) (min-height 150) (stretchable-height #f))
(init get-type error-message)
;; -> Void
(define/public (add)
(send this begin-container-sequence)
(let* ([vp (new vertical-panel% (parent this)(style '(border)))]
[ms (new message% (parent vp) (label VARIANT))]
[bt (new button% (parent vp) (label EDIT)
(callback (create-variant ms)))])
(send variants add bt #f)
(make-delete-button this vp (lambda () (send variants remove bt)))
(send this end-container-sequence)))
;; Message -> (Button Event -> Void)
(define (create-variant ms)
(lambda (bt evt)
(with-handlers ([an-error? void])
(let*-values
([(type) (get-type)] ;; may raise an error message
[(class-in) (send variants lookup bt)]
[(b a-class) (send (new class-info%
(title VARIANT-WIZD)
(insert-str INSERT-VARNT)
(switches? #f) (no-diagram #t)
(add-str ADD-FIELD)
(a-super type)
(a-v-class (if class-in class-in '())))
call)])
(when a-class
(let* ([a-class (car a-class)]
[name (car a-class)])
;; no supertype needed: ;; remove (cadr a-class)
;; comments, if any, are in: (cadddr a-class)
(send variants update bt
(list name (caddr a-class) (class-purpose a-class)))
(send ms set-label name)))))))
;; --------------------------------------------------------------------
;; Managing the datatype: (list name fields [comment])
(define variants (new assoc%))
(define/public (produce)
(foldr (lambda (f r) (if f (cons f r) r)) '()
(send variants list)))))
;; ------------------------------------------------------------------------
;; Pane -> HorizontalPanel
;; add a fixed-width horizontal panel (50) to p
(define (add-horizontal-panel p)
(new horizontal-panel% (parent p) (min-height 50) (stretchable-height #f)))
;; String CallBack -> Button
(define (add-button bp l cb) ;; to button-panel
(new button% (label l) (parent bp) (callback cb)))
;; Panel String -> CheckBox
(define (make-checkbox p l)
(new check-box% (parent p) (label l) (callback void)))
;; Panel String [Callback] -> TextField
(define make-text-field
(opt-lambda (p l (c void) (init ""))
(new text-field%
(parent p) (label l) (callback c) (init-value init)
(min-width 50) (stretchable-width #f))))
;; Panel (-> Void) -> Button
;; create a button that deletes the button's immediate container from this
(define (make-delete-button this vp delete-from-model)
(new button% (parent vp) (label DELETE)
(callback (lambda (x e)
(delete-from-model)
(send this change-children
(lambda (cs)
(filter (lambda (c) (not (eq? vp c))) cs)))))))
(define an-error (cons 1 2))
;; Any -> Boolean
(define (an-error? x) (eq? an-error x))
;; ------------------------------------------------------------------------
#| Run, program, run:
(require (file "draw-txt.ss"))
#| |#
(define-values (b x) (get-class-info BEGINNER))
(if (and x b) (printf "/*~n~a~n*/~n" (class-draw (car x))))
(if x (printf "~a~n" (apply make-class x)))
#||#
(define-values (c y) (get-union-info #;BEGINNER INTERMEDIATE))
(if (and y c) (printf "/*~n~a~n*/~n" (dt-draw (car y))))
(if y (printf "~a~n" (apply make-union (append y (list INTERMEDIATE)))))
|#
)

View File

@ -1,402 +0,0 @@
#cs(module wizard mzscheme
(require mred
mzlib/class
mzlib/etc
mzlib/list
srfi/13/string
mzlib/contract)
(require (file "assoc-list.scm")
(file "data-defs.scm"))
(require-for-syntax (file "aux-syntax.scm"))
(provide/contract
[get-class-info
(() (string? Class) . opt-> . (union false? (list/p Class boolean? boolean?)))]
[get-union-info
(-> (union false? (list/p Union boolean? boolean?)))]
)
;; (define/abstract <identifier>) :: <definition>
;; introduce x as an abstract call back that raises an error
;; and set-x as a setter that defines the function finally
;; (mimic overriding)
(define-syntax (define/abstract e)
(syntax-case e ()
[(_ x)
(with-syntax ([set-x (prefix-id-suffix "set-" (syntax x) "")])
(syntax
(define-values (x set-x)
(let ([real-x (lambda y (error 'x "not initialized yet"))])
(values
(lambda y (apply real-x y))
(lambda (v) (set! real-x v)))))))]))
#|
present a dialog to create a single class;
if programmer aborts, return #f
otherwise, produce a class and two booleans, requesting toString and draft
templates, respectively
|#
(define get-class-info
(opt-lambda ([a-super null][a-v-class null])
;; -----------------------------------------------------------------------
;; Managing the class
;; (union false (list Class Boolean Boolean))
;; should the dialog return a class representation at the end
(define the-class #f)
(define fields (new assoc%))
;; (Listof (-> (list String String)) -> (list Class Boolean Boolean)
;; produce a class from fields
(define (produce-class-from-fields fields)
(with-handlers ([spec-error? (lambda _ #f)])
(let* ([class (string-trim-both (send class-name get-value))]
[super (string-trim-both (send super-name get-value))]
[field (map (lambda (th) (th)) (send fields list))]
[field
(foldr ;; r gives me the right order
(lambda (x r)
(let* ([v x] ; the privacy information isn't collecte
; [v (cdr x)] ; cdr means skip privacy attribute
[type (string-trim-both (car v))]
[name (string-trim-both (cadr v))])
(cond
[(and (java-id? type) (java-id? name))
(cons (list type name) r)]
[(java-id? type)
(error-message (format "check field name for ~a" type))]
[(java-id? name)
(error-message (format "check type for ~a" name))]
[else r])))
'()
field)])
(if (java-id? class)
(list (list class super field)
(send tostring? get-value)
(send template? get-value))
(error-message "check class name")))))
;; -----------------------------------------------------------------------
;; the layout
(define-values (f p tostring? template? set-make-class set-add-field)
(make-top "Class Wizard" "Insert Class" "Add Field"
(lambda (x e) (set! the-class #f) (send f show #f))))
;; -----------------------------------------------------------------------
;; information about the class
(define privacy-modifiers '("no modifier" "public" "private" "protected"))
;; Panel -> Choice
(define (make-modifier-menu p)
(new choice%
(label "") (choices privacy-modifiers) (parent p) (callback void)))
;; TextField Event -> Void
;; a callback that on return creates a new "add field" panel when
;; it's the bottom most text field
(define/abstract send/create-field)
;; Information about the class in general:
(define info-pane (new vertical-panel% (parent p) (style '(border))))
(define purpose
(new text-field%
(parent info-pane) (label "// purpose of class: ") (callback void)))
(define class-pane (add-horizontal-panel info-pane))
; (define class-privacy (make-modifier-menu class-pane))
(define class-name (make-text-field class-pane "class"))
(define super-name (make-text-field class-pane "extends" send/create-field))
;; Information about the class's fields:
(define field-panel (new vertical-panel% (parent info-pane)))
;; (list Modifier String String) *-> Void
;; add a field panel so that a new field for the class can be specified
;; if rest arguments, it consists of two strings:
;; one for the type, one for name
(define (add-field-panel . a-field)
(let* ([fp (add-horizontal-panel field-panel)]
; [modi (make-modifier-menu fp)]
[type (make-text-field fp "type:")]
[name (make-text-field fp "name:" send/create-field)]
[get-values (lambda ()
(list ;(send modi get-string-selection)
(send type get-value)
(send name get-value)))])
(when (pair? a-field)
(send type set-value (car a-field))
(send name set-value (cadr a-field)))
(add-field-name name)
(send fields add type get-values)
(new button%
(label "Delete Field") (parent fp)
(callback
(lambda (x e)
(send fields remove type)
(remove-field-name name)
(send field-panel change-children (remove-panel fp)))))))
;; Managing the creation of new "add field" panels
;; (Listof TextField)
;; the list of name TextFields that have been added via (add-field-panel)
;; a stack in that the bottom field is always at beginning of list
;; if empty, there are no fields
(define the-last-field-name '())
;; TextField -> Boolean
;; what is the current last
(define (should-create-new-add-field? x)
(or (null? the-last-field-name) (eq? (car the-last-field-name) x)))
;; TextField -> Void
;; push f on the-last-field-name
(define (add-field-name f)
(set! the-last-field-name (cons f the-last-field-name)))
;; TextField -> Void
;; remove from "stack"
(define (remove-field-name f)
(set! the-last-field-name (remove f the-last-field-name)))
(define _stupid_effect
(set-send/create-field
(lambda (x e)
(when (eq? (send e get-event-type) 'text-field-enter)
(when (should-create-new-add-field? x) (add-field-panel))
(send f on-traverse-char (new key-event% (key-code #\tab)))))))
;; -----------------------------------------------------------------------
(define-values (error-message spec-error?) (add-error-panel p))
;; -----------------------------------------------------------------------
;; setting it all up
;; String -> Void
;; set up the super class, uneditable
(define (setup-super a-super)
(send super-name set-value a-super)
(send (send super-name get-editor) lock #t))
(cond
[(and (null? a-super) (null? a-v-class))
(add-field-panel)]
[(null? a-v-class)
(add-field-panel)
(setup-super a-super)]
[(null? a-super)
(error 'internal "can't happen: no super, but class provided")]
[else ;
(setup-super a-super)
(let ([name (car a-v-class)]
[fields (cdr a-v-class)])
(send class-name set-value name)
(for-each (lambda (f) (apply add-field-panel f)) fields))])
(set-add-field (lambda (x e) (add-field-panel)))
(set-make-class
(lambda (x e)
(set! the-class (produce-class-from-fields fields))
(when the-class (send f show #f))))
(send f show #t)
the-class
))
#| -> (union #f (list Class Boolean Boolean)
present a modal dialog to create a union;
if programmer aborts, return #f
otherwise, produce a datatype and two booleans, requesting toString and draft
templates, respectively, for the entire datatype
|#
(define (get-union-info)
;; -------------------------------------------------------------------------
;; Managing the datatype
(define the-type #f)
(define variants (new assoc%))
;; -------------------------------------------------------------------------
;; GUI Layout
(define-values (f p toString? template? set-make-union set-add-var)
(make-top "Union Wizard" "Insert Union" "Add Variant"
(lambda (x e) (set! the-type #f) (send f show #f))))
(define type-pane
(new vertical-panel%
(parent p)
(alignment '(center center)) (style '(border))
(min-height 50) (stretchable-height #f)))
(define purpose
(new text-field%
(parent type-pane) (label "// purpose of union: ") (callback void)))
(define type-text (make-text-field type-pane "Type"))
(define vart-pane
(new horizontal-panel%
(parent p) (alignment '(center center)) (style '(border))
(min-height 150) (stretchable-height #f)))
(define-values (error-message spec-error?) (add-error-panel p))
;; -------------------------------------------------------------------------
;; Accessing and Mutating GUIs
;; -> String
(define (get-type)
(let ([t (string-trim-both (send type-text get-value))])
(if (java-id? t) t (error-message "check type name"))))
;; -> Void
(define add-variant-panel
(make-add-variant-panel vart-pane spec-error? variants get-type))
;; make two variants to boot
;; allow people to add and delete a variant
(add-variant-panel)
(add-variant-panel)
(set-make-union
(lambda (x e)
(set! the-type
(with-handlers ([spec-error? (lambda _ #f)])
(list
(list (get-type)
(foldr (lambda (f r) (if f (cons f r) r)) '()
(send variants list)))
(send toString? get-value)
(send template? get-value))))
(send f show #f)))
(set-add-var (lambda (x e) (add-variant-panel)))
(send f show #t)
the-type
)
;; Pane (Any -> Boolean) Assoc -> (-> Void)
;; create a function that adds "variant" panels to the get-union-info dialog
(define (make-add-variant-panel vart-pane spec-error? variants get-type)
(lambda ()
(let* ([vp (new vertical-panel% (parent vart-pane)(style '(border)))]
[ms (new message% (parent vp) (label "Variant"))]
[bt (new button% (parent vp) (label "Edit")
(callback
(lambda (bt evt)
(with-handlers ([spec-error? void])
(let* ([type (get-type)]
[class-in (send variants lookup bt)]
[a-class (if class-in
(get-class-info type class-in)
(get-class-info type))])
(when a-class
(let* ([a-class (car a-class)]
[name (car a-class)]
[fields (caddr a-class)])
;; no supertype needed: remove (cadr a-class)
(send variants update bt (list name fields))
(send ms set-label name))))))))])
(send variants add bt #f)
(new button% (parent vp) (label "Delete")
(callback
(lambda (x e)
(send variants remove bt)
(send vart-pane change-children (remove-panel vp))))))))
;; ---------------------------------------------------------------------------
;; String String String CallBack
;; ->
;; Frame Pane CheckBox CheckBox (Callback -> Void) (Callback -> Void)
;; set up the top of the frame
(define (make-top title insert add quit-cb)
(define f (new dialog% (label title) (width 500) (height 300)))
(define p (new vertical-pane% (parent f)))
(define button-panel (add-horizontal-panel p))
(define quit (add-button button-panel "Abort" quit-cb))
(define/abstract make-class-cb)
(define class-button (add-button button-panel insert make-class-cb))
(define/abstract add-field-cb)
(define add-field-button (add-button button-panel add add-field-cb))
(define switch-pane (add-horizontal-panel p))
(define toString-check (make-checkbox switch-pane "add toString()"))
(define template-check (make-checkbox switch-pane "add method template"))
(values f p toString-check template-check set-make-class-cb set-add-field-cb))
;; Panel String [Callback] -> TextField
(define make-text-field
(opt-lambda (p l (c void))
(new text-field%
(parent p) (label l) (callback c)
(min-width 50) (stretchable-width #f))))
;; Pane -> HorizontalPanel
;; add a fixed-width horizontal panel (50) to p
(define (add-horizontal-panel p)
(new horizontal-panel% (parent p) (min-height 50) (stretchable-height #f)))
;; Panel -> (Panels -> Panels)
;; remove vp from cs
(define (remove-panel vp)
(lambda (cs) (filter (lambda (c) (not (eq? vp c))) cs)))
;; String CallBack -> Button
(define (add-button bp l cb) ;; to button-panel
(new button% (label l) (parent bp) (callback cb)))
;; Panel String -> CheckBox
(define (make-checkbox p l)
(new check-box% (parent p) (label l) (callback void)))
;; Panel -> (String -> Void) (Any -> Boolean)
(define (add-error-panel p)
(define message-size 100)
(define spec-error (cons 1 2))
(define message
(new message%
(parent (add-horizontal-panel p)) (label (make-string 100 #\space))))
;; String -> false
(define (error-message m)
(send message set-label (string-append "error: "m))
(raise spec-error))
;; Any -> Boolean
(define (spec-error? x) (eq? spec-error x ))
(values error-message spec-error?))
#| run: emulate the actual wizard
(require (file "class.scm"))
(provide x y)
(define x (get-class-info))
(if x (printf "~a~n" (apply make-class x)))
(define y (get-union-info))
(if y (printf "~a~n" (apply make-union y)))
|#
)