summaryrefslogtreecommitdiff
path: root/src/lisp/clojure.lisp
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2007-09-22 22:32:46 +0000
committerRich Hickey <richhickey@gmail.com>2007-09-22 22:32:46 +0000
commitb6db84aea2db2ddebcef58918971258464cbf46f (patch)
treea02f6e2d758da84f1358c2e647464ff563a7f00c /src/lisp/clojure.lisp
parent07060b8e569c6fd9073da42bcb80f3ab26251195 (diff)
refactoring dumping unused classes
Diffstat (limited to 'src/lisp/clojure.lisp')
-rw-r--r--src/lisp/clojure.lisp1597
1 files changed, 0 insertions, 1597 deletions
diff --git a/src/lisp/clojure.lisp b/src/lisp/clojure.lisp
deleted file mode 100644
index 1d9952de..00000000
--- a/src/lisp/clojure.lisp
+++ /dev/null
@@ -1,1597 +0,0 @@
-;/**
-; * Copyright (c) Rich Hickey. All rights reserved.
-; * The use and distribution terms for this software are covered by the
-; * Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
-; * which can be found in the file CPL.TXT at the root of this distribution.
-; * By using this software in any fashion, you are agreeing to be bound by
-; * the terms of this license.
-; * You must not remove this notice, or any other, from this software.
-; **/
-
-(defpackage "clojure"
- (:export :load-types :*namespace-separator*
- :newobj :@ :compile-to :*clojure-source-path* :*clojure-target-path*
- "in-module"
- "defn*" "def" "defn" "fn"
- "if" "and" "or" "not" "when" "unless"
- "block" "let" "let*" "letfn"
- "set" "pset" "set*" "do"
- "try" "ex"
- "char" "boolean" "byte" "short" "int" "long" "float" "double"
- "import"))
-
-(in-package "clojure")
-
-(defvar *namespace-separator* nil
- "set to #\/ for JVM, #\. for CLI")
-
-
-(defconstant +MAX-POSITIONAL-ARITY+ 5)
-
-(defvar *host* nil) ; :jvm or :cli
-(defvar *clojure-source-path*)
-(defvar *clojure-target-path*)
-(defvar *symbols*)
-(defvar *keywords*)
-(defvar *vars*)
-(defvar *accessors*)
-(defvar *defvars*)
-(defvar *defns*)
-(defvar *quoted-aggregates* nil)
-(defvar *nested-fn-bindings*)
-(defvar *var-env* nil)
-(defvar *frame* nil)
-(defvar *next-id*)
-
-(defvar *imports*)
-
-;dynamic functions
-(defvar *reference-var*)
-
-#|
-;build the library
-(let ((*clojure-source-path* #p"/dev/clojure/src/lisp/")
- (*clojure-target-path* #p"/dev/clojure/classes/"))
- (compile-to :jvm "clojure.lib" "Clojure"
- "lib.lisp"))
-(let ((*clojure-source-path* #p"/dev/clojure/src/lisp/")
- (*clojure-target-path* #p"/dev/clojure/classes/test/"))
- (compile-to :cli "clojure.lib" "Clojure"
- "lib.lisp"))
-
-|#
-
-
-; a simple attribute object lib
-(defun newobj (&rest attrs)
- (let ((obj (make-hash-table)))
- (do* ((attrs attrs (nthcdr 2 attrs)))
- ((null attrs))
- (let ((attr (first attrs))
- (val (second attrs)))
- (setf (gethash attr obj) val)))
- obj))
-
-(defmacro @ (attr obj)
- `(gethash ',attr ,obj))
-
-
-(defun file-type ()
- (ecase *host*
- (:jvm "java")
- (:cli "cs")))
-
-;from c.l.l.
-(defun lex-string (string &key (whitespace
- '(#\space #\newline)))
- "Separates a string at whitespace and returns a list of strings"
- (flet ((whitespace? (char
-
- ) (member char whitespace :test #'char=)))
- (let ((tokens nil))
- (do* ((token-start
- (position-if-not #'whitespace? string)
- (when token-end
- (position-if-not #'whitespace? string :start (1+ token-end))))
- (token-end
- (when token-start
- (position-if #'whitespace? string :start token-start))
- (when token-start
- (position-if #'whitespace?
- string :start token-start))))
- ((null token-start) (nreverse tokens))
- (push (subseq string token-start token-end) tokens)))))
-
-(defun file-path (package-name)
- (ecase *host*
- (:jvm (lex-string package-name :whitespace '(#\.)))
- (:cli (list ""))))
-
-(defun package-open-format-string ()
- (ecase *host*
- (:jvm "package ~A;~2%")
- (:cli "namespace ~A {~2%")))
-
-(defun package-close-string ()
- (ecase *host*
- (:jvm "")
- (:cli "}")))
-
-(defun package-import-format-string ()
- (ecase *host*
- (:jvm "import ~A.*;~2%")
- (:cli "using ~A;~2%")))
-
-(defun system-import-string ()
- (ecase *host*
- (:jvm "")
- (:cli "using System;~2%")))
-
-(defun var-member-name (symbol)
- (format nil "~A__~A"
- (munge-name (package-name (symbol-package symbol)))
- (munge-name (symbol-name symbol))))
-
-(defun accessor-member-name (symbol)
- (format nil "ACC__~A"
- (subseq (symbol-name symbol) 1)))
-
-(defun symbol-member-name (symbol)
- (format nil "SYM__~A"
- (munge-name (symbol-name symbol))))
-
-(defun keyword-member-name (symbol)
- (format nil "KEY__~A"
- (munge-name (symbol-name symbol))))
-
-(defun munge-name (name)
- (setf name (string name))
- (when (digit-char-p (char name 0))
- (setf name (concatenate 'string "NUM__" name)))
- (labels ((rep (c)
- (second (assoc c
- '((#\- #\_)
- (#\. #\_)
- (#\+ "PLUS__")
- (#\> "GT__")
- (#\< "LT__")
- (#\= "EQ__")
- (#\~ "TILDE__")
- (#\! "BANG__")
- (#\@ "AT__")
- (#\# "SHARP__")
- (#\$ "DOLLAR__")
- (#\% "PCT__")
- (#\^ "CARAT__")
- (#\& "AMP__")
- (#\* "STAR__")
- (#\{ "LBRACE__")
- (#\} "RBRACE__")
- (#\[ "LBRACKET__")
- (#\] "RBRACKET__")
- (#\/ "SLASH__")
- (#\\ "BSLASH__")
- (#\? "QMARK__")))))
- (translate (c)
- (let ((r (rep c)))
- (or r c))))
- (if (find-if #'rep name)
- (format nil "~{~A~}" (map 'list #'translate name))
- name)))
-
-(defun begin-static-block (class-name)
- (ecase *host*
- (:jvm (format nil "static {~%"))
- (:cli (format nil "static ~A(){~%" class-name))))
-
-
-(defun compile-to (host package-name class-name &rest files)
- (let* ((*host* host)
- (orig-package *package*)
- (*features* (list* :clojure host *features*))
- (outpath (make-pathname
- :name class-name
- :type (file-type)
- :defaults (merge-pathnames
- (make-pathname :directory
- (list* :relative (file-path package-name)))
- *clojure-target-path*)))
- (*symbols* (list '|t|))
- (*defns* nil)
- (*defvars* nil)
- (*vars* nil)
- (*keywords* nil)
- (*accessors* nil))
- (with-open-file (target outpath :direction :output :if-exists :supersede)
- (format target "/* Generated by Clojure */~2%")
- (format target (package-open-format-string) package-name)
- (format target (system-import-string))
- (format target (package-import-format-string) "clojure.lang")
- (format target "public class ~A{~%" class-name)
- (unwind-protect
- (dolist (file files)
- (with-open-file (source (merge-pathnames file *clojure-source-path*))
- (labels
- ((process-form (form)
- (case (first form)
- (|in-module| (setf *package* (find-package (second form))))
- (|import| (|import| (second form) (second (third form))))
- ((|block|) (mapc #'process-form (rest form)))
- ((|defn*| |def| |defparameter| |defmain|)
- (let* ((target-sym (second form)))
- (princ target-sym)
- (terpri)
- (let ((*standard-output* target))
- (convert form))))
- (t
- (if (macro-function (car form))
- (process-form (macroexpand-1 form))
- (error "Unsupported form ~A" form))))))
- (let ((*readtable* (copy-readtable nil))
- (*imports* (make-hash-table :test #'equal)))
- (setf (readtable-case *readtable*) :preserve)
- (do ((form (read source nil 'eof) (read source nil 'eof)))
- ((eql form 'eof))
- (process-form form))))))
- (setf *package* orig-package))
- (dolist (sym *symbols*)
- (format target "static Symbol ~A = Symbol.intern(~S);~%"
- (symbol-member-name sym)
- (munge-name (symbol-name sym))))
- (dolist (keyword *keywords*)
- (format target "static Keyword ~A = (Keyword)Symbol.intern(~S);~%"
- (keyword-member-name keyword)
- (concatenate 'string ":" (munge-name (symbol-name keyword)))))
- (dolist (var *vars*)
- (format target "static Var ~A = Namespace.intern(~S,~S);~%"
- (var-member-name var)
- (munge-name (package-name (symbol-package var)))
- (munge-name (symbol-name var))))
- (dolist (accessor *accessors*)
- (format target "static Accessor ~A = (Accessor)Symbol.intern(~S);~%"
- (accessor-member-name accessor)
- (symbol-name accessor)))
- (format target "~Atry{~%" (begin-static-block class-name))
- ;(format target "~%static public void __load() ~A{~%" (exception-declaration-string lang))
- (dolist (var *defns*)
- (format target "Namespace.intern(~S,~S).bind(new ~A());~%"
- (munge-name (package-name (symbol-package var)))
- (munge-name (symbol-name var))
- (munge-name var)))
- (dolist (var-and-init *defvars*)
- (let ((var (@ :var var-and-init))
- (init (@ :init var-and-init)))
- (format target "Namespace.internVar(~S,~S).bind((new ~A()).invoke());~%"
- (munge-name (package-name (symbol-package var)))
- (munge-name (symbol-name var))
- (munge-name init))))
- (format target "}catch(Exception e){}~%}~%")
- ;(format target "}~%")
- (format target "public static void __init(){}~%")
- (format target "}~%")
- (format target "~A~%" (package-close-string)))))
-
-(defun convert (form)
- (let ((tree (analyze :top (macroexpand form)))
- (*next-id* 0))
- ;(print tree)
- (format t "/* Generated by Clojure from the following Lisp:~%")
- (pprint form)
- (format t "~%~%*/~2%")
- (emit :top tree)
- ;tree
- ))
-
-(defun get-next-id ()
- (incf *next-id*))
-
-(defun listize (x)
- (if (listp x)
- x
- (list x)))
-
-(defun |import| (package-string class-symbols)
- (dolist (c (listize class-symbols))
- (when (gethash (symbol-name c) *imports*)
- (error "Class ~A already imported from ~A" (symbol-name c) (gethash (symbol-name c) *imports*)))
- (setf (gethash (symbol-name c) *imports*) package-string)))
-
-(defun fully-qualified-class-name (class-name)
- (let ((package-string (gethash class-name *imports*)))
- (if package-string
- (let* ((assembly-point (position #\, package-string))
- (package (subseq package-string 0 assembly-point)))
- (concatenate 'string package "." class-name
- (when assembly-point (subseq package-string assembly-point))))
- (error "Can't find class ~A in imports" class-name))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; macros ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defmacro |defn| (name params &body body)
- `(|defn*| ,name (,params ,@body)))
-
-(defmacro |fn| (params &body body)
- `(|fn*| (,params ,@body)))
-
-(defmacro |when| (test &rest result)
- `(|if| ,test (|block| ,@result)))
-
-(defmacro |unless| (test &rest result)
- `(|if| ,test nil (|block| ,@result)))
-
-(defmacro |cond| (&rest args)
- (if (null args)
- nil
- (let ((clause (first args)))
- (if (rest clause)
- `(|if| ,(first clause)
- (|block| ,@(rest clause))
- (|cond| ,@(rest args)))
- `(|or| ,(first clause)
- (|cond| ,@(rest args)))))))
-
-(defun pairize (lst)
- (if (null lst)
- nil
- (cons (cons (first lst) (second lst))
- (pairize (rest (rest lst))))))
-
-(defmacro |set*| (&rest args)
- (unless (evenp (length args))
- (error "odd number of arguments"))
- (labels ((recurse (sets)
- (when sets
- (cons (list '|set| (first sets) (second sets))
- (recurse (rest (rest sets)))))))
- (when args
- `(|block| ,@(recurse args)))))
-
-(defmacro |pset| (&rest args)
- (unless (evenp (length args))
- (error "odd number of arguments"))
- (let* ((pairs (pairize args))
- (syms (mapcar #'(lambda (x) (declare (ignore x))(gensym))
- pairs)))
- `(|let| ,(mapcar #'list
- syms
- (mapcar #'rest pairs))
- (|set*| ,@(mapcan #'list
- (mapcar #'first pairs)
- syms)))))
-
-(defmacro |do| (binds (test &optional result) &rest body)
- `(|let| ,(mapcar #'list (mapcar #'first binds) (mapcar #'second binds))
- (|loop|
- (|when| ,test
- (|break| ,result))
- ,@body
- (|pset| ,@(mapcan #'list
- (mapcar #'first binds)
- (mapcar #'third binds))))))
-
-
-
-(defmacro |defcomparator| (op prim)
- `(|defn*| ,op
- ((x) t)
- ((x y)
- (,prim x y))
- ((x y & rest)
- (|and| (,prim x y)
- (|apply| ,op y rest)))))
-
-;(defmacro |block| (&body body)
-; `(|let| nil ,@body))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; analyze and emit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun analyze (context form)
- "context - one of :top :return :statement :expression :fn"
- (cond
- ((consp form) (analyze-op context (first form) form))
- ((or (null form)(eql '|nil| form)) nil)
- ((eql '|t| form) t)
- ((symbolp form) (analyze-symbol context form))
- (t form)))
-
-(defun analyze-op (context op form)
- (case op
- (quote (analyze-quote context form))
- (|defn*| (analyze-defn* context form))
- (|def| (analyze-def context form))
- (|defmain| (analyze-defmain context form))
- (|block| (analyze-block context form))
- (|fn*| (analyze-fn* context form))
- (|if| (analyze-if context form))
- ((|not| |null|) (analyze-not context form))
- (|and| (analyze-and context form))
- (|or| (analyze-or context form))
- (|set| (analyze-set context form))
- (|let| (analyze-let context form))
- (|letfn| (analyze-letfn context form))
- (|let*| (analyze-let* context form))
- (|loop| (analyze-loop context form))
- (|break| (analyze-break context form))
- (|try| (analyze-try context form))
- (|bind| (analyze-bind context form))
- (|instance?| (analyze-instance? context form))
- ((|char| |boolean| |byte| |short| |int| |long| |float| |double|)
- (analyze-cast context form))
- (t (analyze-invoke context op form))))
-
-(defmacro emit-to-string (&body body)
- `(with-output-to-string (s)
- (let ((*standard-output* s))
- ,@body)))
-
-(defun emit (context expr)
- (cond
- ((null expr) (emit-nil context))
- ((typep expr 'hash-table) ;objs
- (ccase (@ :type expr)
- (:defn* (emit-defn* context expr))
- (:main (emit-main context expr))
- (:fn* (emit-fn* context expr))
- (:binding (emit-binding context expr))
- (:accessor (emit-accessor context expr))
- (:keyword (emit-keyword context expr))
- (:global-binding (emit-global-binding context expr))
- (:block (emit-block context expr))
- (:invoke (emit-invoke context expr))
- (:let (emit-let context expr))
- (:if (emit-if context expr))
- (:not (emit-not context expr))
- (:or (emit-or context expr))
- (:and (emit-and context expr))
- (:set (emit-set context expr))
- (:loop (emit-loop context expr))
- (:break (emit-break context expr))
- (:try (emit-try context expr))
- (:bind(emit-bind context expr))
- (:quoted-aggregate (emit-quoted-aggregate context expr))
- (:host-symbol (emit-host-static-member context expr))
- (:cast (emit-cast context expr))
- (:instance? (emit-instance? context expr))))
- (t (emit-other context expr))))
-
-(defun emit-other (context expr)
- (ccase context
- (:statement);no-op
- (:return (emit-return expr))
- (:expression
- (cond
- ((null expr) (emit-nil context))
- ((eql t expr) (format t "RT.T"))
- ((stringp expr) (format t "~S" expr))
- ((characterp expr) (format t "RT.box('~A')" expr))
- ((numberp expr)
- (case expr
- (0 (format t "Num.ZERO"))
- (1 (format t "Num.ONE"))
- (t (format t "Num.from(~A)" expr))))
- ((symbolp expr)
- (cond
- ((keywordp expr)
- (format t "~A" (keyword-member-name expr)))
- ((accessor? expr)
- (format t "~A" (accessor-member-name expr)))
- ((host-symbol? expr)
- (multiple-value-bind (class-name member-name)
- (host-class-and-member-strings expr)
- (format t "Reflector.getStaticField(~S,~S)" member-name class-name)))
- (t (format t "~A" (var-member-name expr)))))
- ((consp expr)
- (format t "RT.arrayToList(new Object[]{~{~A~^, ~}})"
- (mapcar (lambda (e)
- (emit-to-string (emit :expression e)))
- expr)))))))
-
-(defun emit-host-static-member (context expr)
- (ccase context
- (:statement);no-op
- (:return (emit-return expr))
- (:expression
- (multiple-value-bind (class-name member-name)
- (host-class-and-member-strings (@ :symbol expr))
- (format t "Reflector.getStaticField(~S,~S)" member-name class-name)))))
-
-(defun emit-return (expr)
- (format t "return ")
- (emit :expression expr)
- (format t ";~%"))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; quote ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun analyze-quote (context form)
- (let ((q (second form)))
- (cond
- ((symbolp q)
- (cond
- ((keywordp q)
- (register-keyword-reference q))
- ((host-symbol? q) (error "Can't quote host symbols"))
- ((accessor? q)
- (register-accessor-reference q))
- (t (register-var-reference q)))
- q)
- ((atom q) q)
- (t
- (let* ((ql (newobj :type :quoted-aggregate :symbol (gensym "QA__") :form q)))
- (register-quoted-aggregate ql)
- ql)))))
-
-(defun emit-quoted-aggregate (context expr)
- (ccase context
- (:return (emit-return expr))
- (:expression
- (format t "~A" (munge-name (@ :symbol expr))))))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cast/instance? ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun analyze-cast (context form)
- (declare (ignore context))
- (newobj :type :cast
- :to (first form)
- :expr (analyze :expression (macroexpand (second form)))))
-
-(defun emit-cast (context expr)
- (ccase context
- (:return (emit-return expr))
- (:expression
- (format t "RT.box(RT.~ACast(" (symbol-name (@ :to expr)))
- (emit :expression (@ :expr expr))
- (format t "))"))))
-
-(defun analyze-instance? (context form)
- (declare (ignore context))
- (assert (host-type-symbol? (third form)))
- (newobj :type :instance?
- :expr (analyze :expression (macroexpand (second form)))
- :sym (analyze-symbol :statement (third form))))
-
-(defun emit-instance? (context expr)
- (ccase context
- (:return (emit-return expr))
- (:expression
- (format t "(")
- (emit :expression (@ :expr expr))
- (format t" ~A ~A?RT.T:null)"
- (instanceof-string)
- (multiple-value-bind (class-name member-name)
- (host-class-and-member-strings (@ :symbol (@ :sym expr)))
- ;trim off any assembly cruft
- (subseq class-name 0 (position #\, class-name)))))))
-
-(defun instanceof-string ()
- (ccase *host*
- (:jvm "instanceof")
- (:cli "is")))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; set ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun analyze-set (context form)
- ;expecting one of
- ;(set local val) => local = val;
- ;(set var val) => var.setValue(val);
- ;(set class.member val) => Reflector.setStaticField("member","java.lang.Class",val);
- ;(set (:key x) val) => key.invoke(x,val);
- ;(set (.accessor x) val) => accessor.invoke(x, val);
- ;(set (global x y z ...) val)) => global.setfn.invoke(val, x, y, z)
- (declare (ignore context))
- (let ((val (analyze :expression (macroexpand (third form)))))
- (if (atom (second form))
- (let ((target (analyze-symbol :statement (second form))))
- (when (eql (@ :type target) :binding)
- (setf (@ :assigned? target) t))
- (newobj :type :set
- :target target
- :val val))
- (let* ((place (second form))
- (name (analyze-symbol :statement (first place)))
- (args (mapcar (lambda (e)
- (analyze :expression (macroexpand e)))
- (rest place))))
- (ccase (@ :type name)
- ((:keyword :accessor :global-binding)
- (newobj :type :set
- :name name
- :args args
- :val val)))))))
-
-(defun emit-set (context expr)
- (if (eql context :return)
- (emit-return expr)
- (progn
- (when (member context '(:expression :fn))
- (format t "("))
- (let ((val (@ :val expr))
- (name (@ :name expr)))
- (if name ;must be a place
- (ccase (@ :type name)
- ((:keyword :accessor)
- (emit :expression name)
- (format t ".invoke(")
- (emit :expression (first (@ :args expr)))
- (format t ", ")
- (emit :expression val)
- (format t ")"))
- (:global-binding
- (format t "~A.setfn.invoke(" (var-member-name (@ :symbol name)))
- (emit :expression val)
- (format t "~{, ~A~}"
- (mapcar (lambda (e)
- (emit-to-string (emit :expression e)))
- (@ :args expr)))
- (format t ")")))
- (let ((target (@ :target expr)))
- (ccase (@ :type target)
- (:binding
- (emit :expression target)
- (format t " = ")
- (emit :expression val))
- (:global-binding
- (format t "~A.setValue(" (var-member-name (@ :symbol target)))
- (emit :expression val)
- (format t ")"))
- (:host-symbol
- (multiple-value-bind (class-name member-name)
- (host-class-and-member-strings (@ :symbol target))
- (format t "Reflector.setStaticField(~S, ~S, " member-name class-name)
- (emit :expression val)
- (format t ")")))))))
- (when (member context '(:expression :fn))
- (format t ")"))
- (when (eql context :statement)
- (format t ";~%")))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; if ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun analyze-if (context form)
- (if (eql (second form) '|t|)
- ;optimize macro-generated (if t ...) forms
- (analyze context (macroexpand (third form)))
- (let* ((test (analyze :expression (macroexpand (second form))))
- (negate (and (hash-table-p test)(eql :not (@ :type test)))))
- (newobj :type :if
- :test (if negate (@ :expr test) test)
- :comp (if negate "==" "!=")
- :then (analyze context (macroexpand (third form)))
- :else (when (fourth form)
- (analyze context (macroexpand (fourth form))))
- :else-p (= 4 (length form))))))
-
-(defun emit-if (context expr)
- (let ((test (@ :test expr))
- (then (@ :then expr))
- (else (@ :else expr))
- (else-p (@ :else-p expr))
- (comp (@ :comp expr)))
- (ccase context
- (:expression
- (format t "(")
- (emit :expression test)
- (format t " ~A null?" comp)
- (emit :expression then)
- (format t ":")
- (emit :expression else)
- (format t ")"))
- (:statement
- (format t "if(")
- (emit :expression test)
- (format t " ~A null)~%{~%" comp)
- (emit context then)
- (format t "}~%")
- (when (and else-p else)
- (format t "else~%{~%")
- (emit context else)
- (format t "}~%")))
- (:return
- (format t "if(")
- (emit :expression test)
- (format t " ~A null)~%{~%" comp)
- (emit context then)
- (format t "}~%")
- (format t "else~%{~%")
- (if else-p
- (emit context else)
- (format t "return null;~%"))
- (format t "}~%")))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; not/null ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun analyze-not (context form)
- (declare (ignore context))
- (newobj :type :not :expr (analyze :expression (macroexpand (second form)))))
-
-(defun emit-not (context expr)
- (ccase context
- ;just for side effects if statement, no negation
- (:return (emit-return expr))
- (:statement
- (emit context (@ :expr expr)))
- ((:fn :expression)
- (format t "((")
- (emit :expression (@ :expr expr))
- (format t ")==null?RT.T:null)"))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; or ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun analyze-or (context form)
- (let ((temp (newobj :type :binding :symbol (gensym))))
- (unless (eql context :statement)
- (register-local-binding temp))
- (newobj :type :or
- :temp temp
- :exprs (mapcar (lambda (e)
- (analyze :expression (macroexpand e)))
- (rest form)))))
-
-(defun emit-or (context expr)
- (let ((temp (@ :temp expr))
- (exprs (@ :exprs expr)))
- (ccase context
- (:return (emit-return expr))
- (:statement
- (format t "if(~{(~A != null)~^||~})~%;~%"
- (mapcar (lambda (e)
- (emit-to-string (emit :expression e)))
- exprs)))
- ((:expression :fn)
- (format t "((~{((~A = ~A) != null)~^||~})?~A:null)"
- (mapcan (lambda (e)
- (list (binding-name temp) (emit-to-string (emit :expression e))))
- exprs)
- (binding-name temp))))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; and ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-(defun analyze-and (context form)
- (declare (ignore context))
- (newobj :type :and
- :exprs (mapcar (lambda (e)
- (analyze :expression (macroexpand e)))
- (rest form))))
-
-(defun emit-and (context expr)
- (let ((exprs (@ :exprs expr)))
- (ccase context
- (:return (emit-return expr))
- (:statement
- (format t "if(~{(~A != null)~^&&~})~%;~%"
- (mapcar (lambda (e)
- (emit-to-string (emit :expression e)))
- exprs)))
- ((:expression :fn)
- (format t "((~{(~A != null)~^&&~})?~A:null)"
- (mapcar (lambda (e)
- (emit-to-string (emit :expression e)))
- (butlast exprs))
- (emit-to-string (emit :expression (first (last exprs)))))))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; invoke ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun analyze-invoke (context op form)
- (declare (ignore context))
- ;if we hit this unspecialized method, it is not a special op, presume function invocation
- (newobj :type :invoke
- :fexpr (if (symbolp op)
- (analyze-symbol :fn op)
- (analyze :fn op))
- :args (mapcar (lambda (e)
- (analyze :expression e))
- (rest form))))
-
-(defun emit-invoke (context expr)
- (ccase context
- (:statement
- (emit :expression expr)
- (format t ";~%"))
- (:return
- (emit-return expr))
- ((:expression :fn)
- (let* ((fexpr (@ :fexpr expr))
- (global-binding? (eql :global-binding (@ :type fexpr)))
- (host-symbol? (eql :host-symbol (@ :type fexpr)))
- (static-method? (will-be-static-method fexpr))
- (args (@ :args expr)))
- (cond
- (host-symbol?
- (multiple-value-bind (class-name member-name)
- (host-class-and-member-strings (@ :symbol fexpr))
- (format t "Reflector.invokeStaticMethod(~S,~S,new Object[]{~{~A~^,~}})"
- member-name
- class-name
- (mapcar (lambda (e)
- (emit-to-string
- (emit :expression e)))
- args))))
- (t
- (when (not (or global-binding? static-method?))
- (format t "((IFn)"))
- (emit :fn fexpr)
- (when (not (or global-binding? static-method?))
- (format t ")"))
- (unless static-method?
- (format t ".invoke"))
- (format t "(")
- (when static-method?
- (let ((closes (@ :closes (first (@ :methods (@ :fn fexpr))))))
- (format t "~{~A~^, ~}"
- (mapcar (lambda (b)
- (binding-name b))
- closes))))
- (format t "~{~A~^, ~}"
- (mapcar (lambda (e)
- (emit-to-string
- (emit :expression e)))
- args))
- (format t ")")))))))
-
-
-
-(defun emit-global-binding (context expr)
- (ccase context
- (:return
- (emit-return expr))
- ((:expression :return)
- (format t "~A.getValue()" (var-member-name (@ :symbol expr))))
- (:fn
- (format t "~A.fn()" (var-member-name (@ :symbol expr))))
- (:statement)))
-
-(defun emit-accessor (context expr)
- (declare (ignore context))
- (format t "~A" (accessor-member-name (@ :symbol expr))))
-
-(defun emit-keyword (context expr)
- (declare (ignore context))
- (format t "~A" (keyword-member-name (@ :symbol expr))))
-
-(defun emit-new-closure-instance (name-binding-fn)
- (format t "(new ~A(~{~A~^, ~}))"
- (binding-name name-binding-fn)
- (mapcar (lambda (b)
- (binding-name b))
- (@ :closes (first (@ :methods (@ :fn name-binding-fn)))))))
-
-(defun emit-binding (context expr)
- (ccase context
- (:statement) ;var statement is a no-op
- ((:expression :fn)
- (if (and (@ :anonymous-fn? expr) (not (will-be-static-method expr)))
- (emit-new-closure-instance expr)
- (format t "~A~:[~;.val~]" (binding-name expr) (needs-box expr))))
- (:return (emit-return expr))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;; let ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun normalize-let-bindings (binding-list)
- (mapcar (lambda (b)
- (if (atom b)
- (list b nil)
- b))
- binding-list))
-
-(defun analyze-let (context form)
- (let ((bindings (normalize-let-bindings (second form)))
- (body (rest (rest form))))
- (cond
- ;special case of (let () expr) ==> expr
- ((not (or bindings (> (length body) 1)))
- (analyze context (macroexpand (third form))))
- ((eql context :expression)
- (analyze :expression `((|fn*| (,(mapcar #' first bindings) ,@body))
- ,@(mapcar #'second bindings))))
- (t (let* ((binding-inits
- ;init exprs are analyzed prior to adding bindings to env
- (mapcar (lambda (b)
- (newobj :binding (newobj :type :binding :symbol (first b))
- :init (analyze :expression (second b))))
- bindings))
- (*var-env* *var-env*))
- (mapc (lambda (binit)
- (register-local-binding (@ :binding binit))
- (add-to-var-env (@ :binding binit)))
- binding-inits)
- (newobj :type :let
- :binding-inits binding-inits
- :body (analyze-body context body)))))))
-
-(defun analyze-let* (context form)
- (let ((bindings (normalize-let-bindings (second form)))
- (body (rest (rest form))))
- (cond
- ;special case of (let () expr) ==> expr
- ((not (or bindings (> (length body) 1)))
- (analyze context (macroexpand (third form))))
- ((eql context :expression)
- (analyze :expression `((|fn*| (() ,form)))))
- (t (let* ((*var-env* *var-env*)
- (binding-inits
- (mapcar (lambda (b)
- ;sequential binding
- (let ((binit
- (newobj :binding (newobj :type :binding :symbol (first b))
- :init (analyze :expression (second b)))))
- (register-local-binding (@ :binding binit))
- (add-to-var-env (@ :binding binit))
- binit))
- bindings)))
- (newobj :type :let
- :binding-inits binding-inits
- :body (analyze-body context body)))))))
-
-(defun analyze-letfn (context form)
- (cond
- ((eql context :expression)
- (analyze :expression `((|fn*| (() ,form)))))
- (t
- (let* ((*var-env* *var-env*)
- (binding-exprs
- ;adding all bindings to env first, mark as assigned to allow for recursion and mutual reference
- (mapcar (lambda (b)
- (destructuring-bind (name params &rest body) b
- (let ((binding (newobj :type :binding :symbol name
- :assigned? t
- )))
- (register-local-binding binding)
- ;(register-nested-fn-binding binding)
- (add-to-var-env binding)
- ;don't analyze lambdas yet
- (list binding `(|fn*| (,params ,@body))))))
- (second form))))
- (newobj :type :let
- :binding-inits (mapcar (lambda (be)
- (let ((binding (first be))
- (fn (analyze :expression (second be))))
- (setf (@ :fn binding) fn)
- (setf (@ :binding fn) binding)
- (newobj :binding binding :init fn)))
- binding-exprs)
- :body (analyze-body context (rest (rest form))))))))
-
-(defun emit-let (context expr)
- (let ((binding-inits (@ :binding-inits expr))
- (body (@ :body expr)))
- (dolist (bi binding-inits)
- (unless (will-be-static-method (@ :binding bi))
- (emit :expression (@ :binding bi))
- (format t " = ")
- (emit :expression (@ :init bi))
- (format t ";~%")))
- (emit-body context body)))
-
-(defun analyze-body (context exprs)
- (when exprs
- (case context
- (:statement
- (mapcar (lambda (expr)
- (analyze :statement (macroexpand expr)))
- exprs))
- (:return
- (append (mapcar (lambda (expr)
- (analyze :statement (macroexpand expr)))
- (butlast exprs))
- (list (analyze :return (macroexpand (first (last exprs))))))))))
-
-(defun emit-body (context body)
- (case context
- (:return
- (dolist (e (butlast body))
- (emit :statement e))
- (if body
- (emit :return (first (last body)))
- (format t "return null;~%")))
- (:statement
- (dolist (e body)
- (emit :statement e)))))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; bind ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-