| 1 | (in-package :jss) |
|---|
| 2 | |
|---|
| 3 | (defvar *class-to-last-component* (make-hash-table :test 'equalp)) |
|---|
| 4 | |
|---|
| 5 | (defclass javaparser () ((parser :accessor parser))) |
|---|
| 6 | |
|---|
| 7 | (defmethod initialize-instance ((p javaparser)&key) |
|---|
| 8 | (call-next-method) |
|---|
| 9 | (setf (parser p) (new 'javaparser))) |
|---|
| 10 | |
|---|
| 11 | (defmacro def-java-read (ast-class class fields &body body) |
|---|
| 12 | (let ((jclass (find-java-class (concatenate 'string "com.github.javaparser.ast.expr." (string ast-class))))) |
|---|
| 13 | `(progn |
|---|
| 14 | (setf (gethash ,jclass *class-to-last-component*) ',ast-class) |
|---|
| 15 | (defmethod ,ast-class ((obj ,class) node &optional |
|---|
| 16 | ,@(loop for field in fields |
|---|
| 17 | collect `(,(intern (string-upcase field)) (get-java-field node ,field t)))) |
|---|
| 18 | ,@body)))) |
|---|
| 19 | |
|---|
| 20 | (defvar *object-for-this* (new 'lang.object)) |
|---|
| 21 | |
|---|
| 22 | (defmethod get-optional ((r javaparser) node) |
|---|
| 23 | (if (equal node (load-time-value (#"empty" 'java.util.Optional ))) nil (#"get" node))) |
|---|
| 24 | |
|---|
| 25 | (defmethod process-node ((r javaparser) node) |
|---|
| 26 | (when (jinstance-of-p node "java.util.Optional") |
|---|
| 27 | (setq node (get-optional r node))) |
|---|
| 28 | (when (null node) |
|---|
| 29 | (return-from process-node nil)) |
|---|
| 30 | (if (java-object-p node) |
|---|
| 31 | (funcall (gethash (jobject-class node) *class-to-last-component*) r node) |
|---|
| 32 | node)) |
|---|
| 33 | |
|---|
| 34 | (defmethod read-java-expression ((r javaparser) expression) |
|---|
| 35 | `(let ((this *object-for-this*)) |
|---|
| 36 | (declare (ignorable this)) |
|---|
| 37 | ,(process-node r (#"getResult" (#"parseExpression" (parser r) expression))))) |
|---|
| 38 | |
|---|
| 39 | (def-java-read LongLiteralExpr javaparser () |
|---|
| 40 | (read-from-string (#"replaceFirst" (#"getValue" node) "L" ""))) |
|---|
| 41 | |
|---|
| 42 | (def-java-read BooleanLiteralExpr javaparser () |
|---|
| 43 | (if (equal (#"getValue" node) "true") t nil)) |
|---|
| 44 | |
|---|
| 45 | (def-java-read IntegerLiteralExpr javaparser nil |
|---|
| 46 | (parse-integer (#"getValue" node))) |
|---|
| 47 | |
|---|
| 48 | (def-java-read DoubleLiteralExpr javaparser nil |
|---|
| 49 | (let ((raw (#"getValue" node))) |
|---|
| 50 | (setq raw (#"replaceAll" raw "_" "")) |
|---|
| 51 | (if (#"matches" raw ".*[dD]$") |
|---|
| 52 | (read-from-string (#"replaceFirst" (subseq raw 0 (1- (length raw))) "e" "d")) |
|---|
| 53 | (if (#"matches" raw ".*[fF]$") |
|---|
| 54 | (read-from-string (subseq raw 0 (1- (length raw)))) |
|---|
| 55 | (read-from-string raw))))) |
|---|
| 56 | |
|---|
| 57 | (def-java-read CharLiteralExpr javaparser nil |
|---|
| 58 | (#"getValue" node)) |
|---|
| 59 | |
|---|
| 60 | (def-java-read StringLiteralExpr javaparser nil |
|---|
| 61 | (#"getValue" node)) |
|---|
| 62 | |
|---|
| 63 | (def-java-read NullLiteralExpr javaparser nil |
|---|
| 64 | +null+) |
|---|
| 65 | |
|---|
| 66 | (def-java-read SimpleName javaparser () |
|---|
| 67 | (let ((symbol (intern (#"getIdentifier" node)))) |
|---|
| 68 | symbol)) |
|---|
| 69 | |
|---|
| 70 | (def-java-read NameExpr javaparser () |
|---|
| 71 | (let ((symbol (intern (#"getIdentifier" (#"getName" node))))) |
|---|
| 72 | symbol)) |
|---|
| 73 | |
|---|
| 74 | (eval-when (:compile-toplevel :load-toplevel :execute) |
|---|
| 75 | (defun read-invoke/javaparser (stream char arg) |
|---|
| 76 | (if (eql arg 1) |
|---|
| 77 | (if (ignore-errors |
|---|
| 78 | (jclass "com.github.javaparser.ParseStart")) ;; chosen randomly, TODO memoize |
|---|
| 79 | (read-sharp-java-expression stream) |
|---|
| 80 | ;; Deal with possiblity of not loading jar |
|---|
| 81 | (error "Cannot load javaparser code needed for the #1 macro")) |
|---|
| 82 | (read-invoke stream char arg))) |
|---|
| 83 | (set-dispatch-macro-character #\# #\" 'read-invoke/javaparser)) |
|---|
| 84 | |
|---|
| 85 | |
|---|