From c68be3366cb67ff96ec88904ccc9d1efd7a78bed Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Mon, 8 Dec 2014 20:36:41 -0400 Subject: Added modules. --- src/lang.clj | 24 ++++++++++-- src/lang/compiler.clj | 102 +++++++++++++++++++++++++++++--------------------- src/lang/parser.clj | 5 +++ 3 files changed, 85 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/lang.clj b/src/lang.clj index 77235dcf0..6502c3a29 100644 --- a/src/lang.clj +++ b/src/lang.clj @@ -14,12 +14,28 @@ _ (prn 'tokens tokens) syntax (&parser/parse tokens) _ (prn 'syntax syntax) - class-data (&compiler/compile syntax)] - (write-file "output.class" class-data)) + class-data (&compiler/compile "test2" syntax)] + (write-file "test2.class" class-data)) (->> (slurp "test2.lang") &lexer/lex &parser/parse - &compiler/compile - (write-file "output.class")) + (&compiler/compile "test2") + (write-file "test2.class")) + + ;; TODO: Define the Function abstract class. + ;; TODO: Define functions as classes inheriting Function. + ;; TODO: Add tuples. + ;; TODO: Add let. + ;; TODO: Add pattern-matching. + ;; TODO: Add tagged values. + ;; TODO: Do tail-call optimization. + ;; TODO: Add macros. + ;; TODO: Add type-level computations. + ;; TODO: Add interpreter. + ;; TODO: Add Java-interop. + ;; TODO: Add signatures & structures. + ;; TODO: Add type-system. + ;; TODO: Allow defining constants. + ;; TODO: ) diff --git a/src/lang/compiler.clj b/src/lang/compiler.clj index 52195d2f2..3e63fc801 100644 --- a/src/lang/compiler.clj +++ b/src/lang/compiler.clj @@ -13,13 +13,19 @@ ;; [Utils/General] (defmacro ^:private defcompiler [name match body] - `(defn ~name [~'*writer* ~'*form*] - (match ~'*form* - ~match - (do ~body - true) - _# - false))) + `(defn ~name [~'*state*] + (let [~'*name* (:name ~'*state*) + ~'*writer* (:writer ~'*state*) + ~'*form* (:form ~'*state*)] + (match ~'*form* + ~match + (do ~body + true) + _# + false)))) + +(defn compile-form* [writer form] + (compile-form {:writer writer, :form form})) (defn ^:private unwrap-ident [ident] (match ident @@ -61,9 +67,9 @@ (defcompiler ^:private compile-fn-call [::&parser/fn-call [::&parser/ident ?fn] ?args] (do (doseq [arg ?args] - (compile-form *writer* arg)) + (compile-form (assoc *state* :form arg))) (doto *writer* - (.visitMethodInsn Opcodes/INVOKESTATIC "output" ?fn "(Ljava/lang/Object;)Ljava/lang/Object;")))) + (.visitMethodInsn Opcodes/INVOKESTATIC *name* ?fn "(Ljava/lang/Object;)Ljava/lang/Object;")))) (defcompiler ^:private compile-static-access [::&parser/static-access ?class ?member] @@ -72,11 +78,11 @@ (defcompiler ^:private compile-dynamic-access [::&parser/dynamic-access ?object ?access] - (let [=object (compile-form *writer* ?object) + (let [=object (compile-form (assoc *state* :form ?object)) method (match ?access [::&parser/fn-call [::&parser/ident ?method] ?args] (do (doseq [arg ?args] - (compile-form *writer* arg)) + (compile-form (assoc *state* :form arg))) ?method))] (doto *writer* (.visitMethodInsn Opcodes/INVOKEVIRTUAL (->class "java.io.PrintStream") method "(Ljava/lang/Object;)V")))) @@ -89,13 +95,13 @@ [::&parser/if ?test ?then ?else] (let [else-label (new Label) end-label (new Label)] - (compile-form *writer* ?test) + (compile-form (assoc *state* :form ?test)) (.visitJumpInsn *writer* Opcodes/IFEQ else-label) - (compile-form *writer* ?then) + (compile-form (assoc *state* :form ?then)) (doto *writer* (.visitJumpInsn Opcodes/GOTO end-label) (.visitLabel else-label)) - (compile-form *writer* ?else) + (compile-form (assoc *state* :form ?else)) (.visitLabel *writer* end-label))) (defcompiler ^:private compile-def @@ -103,20 +109,27 @@ (match ?form [::&parser/fn-call [::&parser/ident ?name] ?args] (if (= "main" ?name) - (doto (.visitMethod *writer* (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) ?name "([Ljava/lang/String;)V" nil nil) - (.visitCode) - (compile-form ?body) - (.visitInsn Opcodes/RETURN) - (.visitMaxs 0 0) - (.visitEnd)) - (doto (.visitMethod *writer* (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) ?name "(Ljava/lang/Object;)Ljava/lang/Object;" nil nil) - (.visitCode) - (compile-form ?body) - (.visitInsn Opcodes/ARETURN) - (.visitMaxs 0 0) - (.visitEnd))) + (let [=method (doto (.visitMethod *writer* (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) ?name "([Ljava/lang/String;)V" nil nil) + (.visitCode))] + (compile-form (assoc *state* :writer =method :form ?body)) + (doto =method + (.visitInsn Opcodes/RETURN) + (.visitMaxs 0 0) + (.visitEnd))) + (let [=method (doto (.visitMethod *writer* (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) ?name "(Ljava/lang/Object;)Ljava/lang/Object;" nil nil) + (.visitCode))] + (compile-form (assoc *state* :writer =method :form ?body)) + (doto =method + (.visitInsn Opcodes/ARETURN) + (.visitMaxs 0 0) + (.visitEnd)))) )) +(defcompiler ^:private compile-module + [::&parser/module] + (.visit *writer* Opcodes/V1_5 (+ Opcodes/ACC_PUBLIC Opcodes/ACC_SUPER) + *name* nil "java/lang/Object" nil)) + (let [+compilers+ [compile-boolean compile-string compile-ident @@ -125,24 +138,29 @@ compile-dynamic-access compile-ann-class compile-if - compile-def]] - (defn ^:private compile-form [writer form] - (prn 'compile-form/form form) - (some #(% writer form) +compilers+))) + compile-def + compile-module]] + (defn ^:private compile-form [state] + (prn 'compile-form/state state) + (some #(% state) +compilers+))) ;; [Interface] -(defn compile [inputs] +(defn compile [class-name inputs] (prn 'inputs inputs) - (let [=class (doto (new ClassWriter ClassWriter/COMPUTE_MAXS) - (.visit Opcodes/V1_5 (+ Opcodes/ACC_PUBLIC Opcodes/ACC_SUPER) - "output" nil "java/lang/Object" nil))] - (doto (.visitMethod =class Opcodes/ACC_PUBLIC "" "()V" nil nil) - (.visitCode) - (.visitVarInsn Opcodes/ALOAD 0) - (.visitMethodInsn Opcodes/INVOKESPECIAL "java/lang/Object" "" "()V") - (.visitInsn Opcodes/RETURN) - (.visitMaxs 0 0) - (.visitEnd)) - (doall (map (partial compile-form =class) inputs)) + (let [=class (new ClassWriter ClassWriter/COMPUTE_MAXS) + ;; (doto (new ClassWriter ClassWriter/COMPUTE_MAXS) + ;; (.visit Opcodes/V1_5 (+ Opcodes/ACC_PUBLIC Opcodes/ACC_SUPER) + ;; "output" nil "java/lang/Object" nil)) + state {:name class-name + :writer =class + :form nil}] + ;; (doto (.visitMethod =class Opcodes/ACC_PUBLIC "" "()V" nil nil) + ;; (.visitCode) + ;; (.visitVarInsn Opcodes/ALOAD 0) + ;; (.visitMethodInsn Opcodes/INVOKESPECIAL "java/lang/Object" "" "()V") + ;; (.visitInsn Opcodes/RETURN) + ;; (.visitMaxs 0 0) + ;; (.visitEnd)) + (doall (map #(compile-form (assoc state :form %)) inputs)) (.visitEnd =class) (.toByteArray =class))) diff --git a/src/lang/parser.clj b/src/lang/parser.clj index f09d87145..5adf36030 100644 --- a/src/lang/parser.clj +++ b/src/lang/parser.clj @@ -103,6 +103,10 @@ (partition 2 ?bindings)))] (return [::let =bindings =expr]))) +(defparser ^:private parse-module + [::&lexer/list ([[::&lexer/ident "module"]] :seq)] + (return [::module])) + (defparser ^:private parse-tagged [::&lexer/list ([[::&lexer/tag ?tag] ?data] :seq)] (exec [=data (apply-m parse-form (list ?data))] @@ -185,6 +189,7 @@ parse-static-access parse-dynamic-access parse-ann-class + parse-module parse-fn-call])) ;; [Interface] -- cgit v1.2.3