| 1 | (in-package :jss) |
|---|
| 2 | |
|---|
| 3 | (defclass sharp-quote-expression-reader (javaparser) ()) |
|---|
| 4 | |
|---|
| 5 | (defun read-sharp-java-expression (stream) |
|---|
| 6 | (read-sharp-quote-expression |
|---|
| 7 | (with-output-to-string (s) |
|---|
| 8 | (loop with embedded-string = nil |
|---|
| 9 | for last = #\space then char |
|---|
| 10 | for char = (read-char stream) |
|---|
| 11 | until (and (char= char #\") |
|---|
| 12 | ;; really end if: we've established embedded string and the peek is a space |
|---|
| 13 | ;; we're not about to start embedded string. We're about to start embedded string if next character isn't #\). |
|---|
| 14 | ;; we're not embedded-string and not about to start one |
|---|
| 15 | (cond ((null (peek-char nil stream nil)) t) ;; eof |
|---|
| 16 | (embedded-string (system:whitespacep (peek-char nil stream))) ; embedded " needs "<space>" to end |
|---|
| 17 | ((find last ",(+=" :test 'char=) |
|---|
| 18 | (setq embedded-string t) |
|---|
| 19 | nil) |
|---|
| 20 | (t t))) |
|---|
| 21 | do |
|---|
| 22 | (write-char char s))))) |
|---|
| 23 | |
|---|
| 24 | |
|---|
| 25 | (defun read-sharp-quote-expression (string) |
|---|
| 26 | (multiple-value-bind (bindings de-lisped) (extract-lisp-expressions string) |
|---|
| 27 | (let ((read (read-java-expression (make-instance 'sharp-quote-expression-reader) de-lisped))) |
|---|
| 28 | (loop for (var nil) in bindings |
|---|
| 29 | do (setq read (tree-replace (lambda(e) (if (equalp e (string var)) var e)) read ))) |
|---|
| 30 | (if bindings |
|---|
| 31 | `(let ,bindings ,read) |
|---|
| 32 | read)))) |
|---|
| 33 | |
|---|
| 34 | (defun extract-lisp-expressions (string) |
|---|
| 35 | (let ((bindings nil)) |
|---|
| 36 | (let ((de-lisped |
|---|
| 37 | (replace-all string "\\{(.*?)\\}" |
|---|
| 38 | (lambda(match) |
|---|
| 39 | (let ((replacevar (find-symbol-not-matching string (mapcar 'car bindings)))) |
|---|
| 40 | (push (list replacevar (read-from-string match)) bindings) |
|---|
| 41 | (string replacevar))) |
|---|
| 42 | 1))) |
|---|
| 43 | (values bindings de-lisped)))) |
|---|
| 44 | |
|---|
| 45 | (defun find-symbol-not-matching (string already) |
|---|
| 46 | (loop for candidate = (format nil "JSS_~a" (random 10000)) |
|---|
| 47 | until (and (not (member candidate already :test 'equalp :key 'string)) |
|---|
| 48 | (not (search string already))) |
|---|
| 49 | finally (return-from find-symbol-not-matching (intern candidate :jss)))) |
|---|
| 50 | |
|---|
| 51 | (defun maybe-class (el) |
|---|
| 52 | (if (and (symbolp el) (upper-case-p (char (string el) 0)) (not (eql (search "JSS_" (string el)) 0))) |
|---|
| 53 | `(find-java-class ',el) |
|---|
| 54 | (if (symbolp el) |
|---|
| 55 | (intern (string-upcase el)) |
|---|
| 56 | el))) |
|---|
| 57 | |
|---|
| 58 | (def-java-read ObjectCreationExpr sharp-quote-expression-reader () |
|---|
| 59 | `(new ',(process-node obj (#"getName" (#"getType" node))) ,@(mapcar (lambda(e) (process-node obj e)) (j2list (#"getArguments" node)))) |
|---|
| 60 | ) |
|---|
| 61 | |
|---|
| 62 | (def-java-read MethodCallExpr sharp-quote-expression-reader () |
|---|
| 63 | (let* ((scope1 (process-node obj (process-node obj (#"getScope" node)))) |
|---|
| 64 | (how (if (and (symbolp scope1) (not (null scope1)) (upper-case-p (char (string scope1) 0))) |
|---|
| 65 | 'jstatic |
|---|
| 66 | 'jcall))) |
|---|
| 67 | (if (and (symbolp scope1) (not (null scope1)) (upper-case-p (char (string scope1) 0))) |
|---|
| 68 | (setq scope1 `(find-java-class ',scope1))) |
|---|
| 69 | `(,how ,(#"getIdentifier" (#"getName" node)) ,(or scope1 'this) ,@(mapcar 'maybe-class |
|---|
| 70 | (mapcar (lambda(el) (process-node obj el)) |
|---|
| 71 | (j2list (#"getArguments" node))))) |
|---|
| 72 | )) |
|---|
| 73 | |
|---|
| 74 | (def-java-read FieldAccessExpr sharp-quote-expression-reader () |
|---|
| 75 | (let ((scope (process-node obj (#"getScope" node)))) |
|---|
| 76 | (if (and (symbolp scope) (upper-case-p (char (string scope) 0))) |
|---|
| 77 | `(get-java-field ',(process-node obj (#"getScope" node)) ,(#"getIdentifier" (#"getName" node)) t) |
|---|
| 78 | `(get-java-field ,(maybe-class (process-node obj (#"getScope" node))) ,(#"getIdentifier" (#"getName" node)) t)))) |
|---|
| 79 | |
|---|
| 80 | (def-java-read ArrayAccessExpr sharp-quote-expression-reader () |
|---|
| 81 | (let ((index (process-node obj (#"getIndex" node)))) |
|---|
| 82 | (if (symbolp index) (setq index (intern (string-upcase index)))) |
|---|
| 83 | `(aref ,(process-node obj (#"getName" node)) ,index))) |
|---|
| 84 | |
|---|
| 85 | (def-java-read ClassExpr sharp-quote-expression-reader () |
|---|
| 86 | (let ((name (process-node obj (#"getName" (#"getType" node))))) |
|---|
| 87 | (if (eql (search "JSS_" (string name) :test 'equalp) 0) |
|---|
| 88 | name |
|---|
| 89 | `(find-java-class ',name)))) |
|---|
| 90 | |
|---|
| 91 | (def-java-read NameExpr sharp-quote-expression-reader () |
|---|
| 92 | (process-node obj (#"getName" node))) |
|---|
| 93 | |
|---|