diff options
author | Eduardo Julian | 2014-12-26 14:20:19 -0400 |
---|---|---|
committer | Eduardo Julian | 2014-12-26 14:20:19 -0400 |
commit | db3fecf46f602320b48e7ce82ee770a46bba7ba6 (patch) | |
tree | 8b98d608ef6d467028d0b59542ea9886584bae34 /src/lang/compiler.clj | |
parent | 0a0300b129df4499782cbe47aeaee581f57cc3db (diff) |
Pattern-matching has been enriched with sub-structural matching.
Diffstat (limited to 'src/lang/compiler.clj')
-rw-r--r-- | src/lang/compiler.clj | 111 |
1 files changed, 76 insertions, 35 deletions
diff --git a/src/lang/compiler.clj b/src/lang/compiler.clj index e425fa0f1..f26d111a4 100644 --- a/src/lang/compiler.clj +++ b/src/lang/compiler.clj @@ -288,46 +288,87 @@ (defcompiler ^:private compile-case ;; [::&analyser/case ?variant ?branches] [::&analyser/case ?base ?variant ?registers ?branches] - (do ;; (prn [:case ?base ?variant ?registers ?branches]) - (match (:form ?base) - [::&analyser/local _ ?base-idx] - (let [start-label (new Label) - end-label (new Label)] - (dotimes [idx ?registers] - (.visitLocalVariable *writer* (str "__" idx "__") (->java-sig ::&type/any) nil start-label end-label (+ ?base-idx idx))) - (.visitLabel *writer* start-label) - (compile-form (assoc *state* :form ?variant)) - (.visitVarInsn *writer* Opcodes/ASTORE ?base-idx) - (let [variant-class* (->class +variant-class+)] + (let [variant-class* (->class +variant-class+)] + ;; (prn [:case ?base ?variant ?registers ?branches]) + (match (:form ?base) + [::&analyser/local _ ?base-idx] + (let [start-label (new Label) + end-label (new Label) + default-label (new Label)] + (dotimes [idx ?registers] + (.visitLocalVariable *writer* (str "__" idx "__") (->java-sig ::&type/any) nil start-label end-label (+ ?base-idx idx))) + (.visitLabel *writer* start-label) + (compile-form (assoc *state* :form ?variant)) + (.visitTypeInsn *writer* Opcodes/CHECKCAST variant-class*) + (.visitVarInsn *writer* Opcodes/ASTORE ?base-idx) (doseq [?branch ?branches :let [else-label (new Label)]] (match ?branch [::&analyser/branch-adt ?tag ?members ?body] - (let [tuple-class (str "test2/Tuple" (count ?members))] - (when (not (empty? ?members)) - (do (doto *writer* - (.visitVarInsn Opcodes/ALOAD ?base-idx) - (.visitFieldInsn Opcodes/GETFIELD variant-class* "value" (->type-signature "java.lang.Object")) - (.visitTypeInsn Opcodes/CHECKCAST tuple-class)) - (doseq [[?tfield member] (map vector (range (count ?members)) ?members)] - (match member - [:lang.analyser/local 0 ?idx] + (doto *writer* + (.visitVarInsn Opcodes/ALOAD ?base-idx) + (.visitFieldInsn Opcodes/GETFIELD variant-class* "tag" (->type-signature "java.lang.String")) + (.visitLdcInsn ?tag) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL oclass "equals" equals-sig) + (.visitJumpInsn Opcodes/IFEQ else-label) + (do (when (not (empty? ?members)) + (let [tuple-class (str "test2/Tuple" (count ?members)) + mk-sub-fold (fn mk-sub-fold [cleanup-level default-label tuple-class] + (fn sub-fold [?tfield member] + (let [next-label (new Label)] + (match member + [::&analyser/local 0 ?idx] + (doto *writer* + (.visitInsn Opcodes/DUP) + (.visitFieldInsn Opcodes/GETFIELD tuple-class (str "_" ?tfield) (->type-signature "java.lang.Object")) + (.visitVarInsn Opcodes/ASTORE ?idx)) + + [::&analyser/subcase ?subtag ?submembers] + (let [tuple-class* (str "test2/Tuple" (count ?submembers)) + cleanup-label (new Label)] + (doto *writer* + (.visitInsn Opcodes/DUP) + (.visitFieldInsn Opcodes/GETFIELD tuple-class (str "_" ?tfield) (->type-signature "java.lang.Object")) + (.visitTypeInsn Opcodes/CHECKCAST variant-class*) + (.visitInsn Opcodes/DUP) + (.visitFieldInsn Opcodes/GETFIELD variant-class* "tag" (->type-signature "java.lang.String")) + (.visitLdcInsn ?subtag) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL oclass "equals" equals-sig) + (.visitJumpInsn Opcodes/IFEQ cleanup-label) + (.visitFieldInsn Opcodes/GETFIELD variant-class* "value" (->type-signature "java.lang.Object")) + (.visitTypeInsn Opcodes/CHECKCAST tuple-class*) + (do (dorun (map (mk-sub-fold (inc cleanup-level) default-label tuple-class*) + (range (count ?submembers)) + ?submembers))) + (.visitInsn Opcodes/POP) + (.visitJumpInsn Opcodes/GOTO next-label) + (.visitLabel cleanup-label) + (-> (doto (.visitInsn Opcodes/POP)) + (->> (dotimes [_ (inc cleanup-level)]))) + (.visitJumpInsn Opcodes/GOTO default-label) + (.visitLabel next-label) + ))))))] (doto *writer* - (.visitInsn Opcodes/DUP) - (.visitFieldInsn Opcodes/GETFIELD tuple-class (str "_" ?tfield) (->type-signature "java.lang.Object")) - (.visitVarInsn Opcodes/ASTORE ?idx)))) - (.visitInsn *writer* Opcodes/POP))) - (doto *writer* - (.visitVarInsn Opcodes/ALOAD ?base-idx) - (.visitFieldInsn Opcodes/GETFIELD variant-class* "tag" (->type-signature "java.lang.String")) - (.visitLdcInsn ?tag) - (.visitMethodInsn Opcodes/INVOKEVIRTUAL oclass "equals" equals-sig) - (.visitJumpInsn Opcodes/IFEQ else-label) - (do (compile-form (assoc *state* :form ?body))) - (.visitJumpInsn Opcodes/GOTO end-label) - (.visitLabel else-label)))))) - (.visitInsn *writer* Opcodes/ACONST_NULL) - (.visitLabel *writer* end-label))) + (.visitVarInsn Opcodes/ALOAD ?base-idx) + (.visitFieldInsn Opcodes/GETFIELD variant-class* "value" (->type-signature "java.lang.Object")) + (.visitTypeInsn Opcodes/CHECKCAST tuple-class)) + (dorun (map (mk-sub-fold 1 default-label tuple-class) + (range (count ?members)) + ?members)) + (.visitInsn *writer* Opcodes/POP))) + (compile-form (assoc *state* :form ?body))) + (.visitJumpInsn Opcodes/GOTO end-label) + (.visitLabel else-label)))) + ;; Default branch + (let [ex-class (->class "java.lang.IllegalStateException")] + (doto *writer* + (.visitLabel default-label) + (.visitInsn Opcodes/ACONST_NULL) + (.visitTypeInsn Opcodes/NEW ex-class) + (.visitInsn Opcodes/DUP) + (.visitMethodInsn Opcodes/INVOKESPECIAL ex-class "<init>" "()V") + (.visitInsn Opcodes/ATHROW))) + (.visitLabel *writer* end-label))) ))) (defcompiler ^:private compile-let |