aboutsummaryrefslogtreecommitdiff
path: root/src/lang
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lang.clj2
-rw-r--r--src/lang/analyser.clj31
-rw-r--r--src/lang/compiler.clj80
-rw-r--r--src/lang/parser.clj7
4 files changed, 84 insertions, 36 deletions
diff --git a/src/lang.clj b/src/lang.clj
index 5d5dd0c66..7e71a1a62 100644
--- a/src/lang.clj
+++ b/src/lang.clj
@@ -96,7 +96,6 @@
(STATIC-METHOD w x y z)))))))))
- ;; TODO: Allow using other modules.
;; TODO: Define functions as classes inheriting Function.
;; TODO: Add tuples.
;; TODO: Add pattern-matching.
@@ -115,4 +114,5 @@
;; jar cvf test2.jar test2 test2.class
;; java -cp "test2.jar" test2
;; jar cvf test2.jar test2 test2.class && java -cp "test2.jar" test2
+ ;; jar cvf test2.jar test2 test2.class another.class && java -cp "test2.jar" test2
)
diff --git a/src/lang/analyser.clj b/src/lang/analyser.clj
index abf8fa638..115204570 100644
--- a/src/lang/analyser.clj
+++ b/src/lang/analyser.clj
@@ -1,7 +1,7 @@
(ns lang.analyser
(:refer-clojure :exclude [resolve])
- (:require [clojure.core.match :refer [match]]
- [clojure.string :as string]
+ (:require [clojure.string :as string]
+ [clojure.core.match :refer [match]]
(lang [util :as &util :refer [exec return* return fail fail*
repeat-m try-m try-all-m map-m
apply-m within]]
@@ -48,11 +48,20 @@
short-name =class})
nil]])))
+(defn ^:private require-module [name alias]
+ (fn [state]
+ [::&util/ok [(assoc-in state [:deps alias] name)
+ nil]]))
+
(defn ^:private resolve [ident]
(fn [state]
- (if-let [resolved (get-in state [:env :mappings ident])]
- [::&util/ok [state resolved]]
- [::&util/failure (str "Unresolved identifier: " ident)])))
+ (if-let [[_ ?alias ?binding] (re-find #"^(.*)/(.*)$" ident)]
+ (let [?module (get-in state [:deps ?alias])]
+ (prn 'resolve ?module ?alias ?binding)
+ [::&util/ok [state (annotated [::global ?module ?binding] ::&type/nothing)]])
+ (if-let [resolved (get-in state [:env :mappings ident])]
+ [::&util/ok [state resolved]]
+ [::&util/failure (str "Unresolved identifier: " ident)]))))
(defmacro ^:private defanalyser [name match return]
`(def ~name
@@ -190,6 +199,14 @@
(exec [_ (import-class ?class (last (string/split ?class #"\.")))]
(return (annotated [::import ?class] ::&type/nothing))))
+(defanalyser analyse-require
+ [::&parser/require ?file ?alias]
+ (let [_ (prn `[require ~?file ~?alias])
+ module-name (re-find #"[^/]+$" ?file)
+ _ (prn 'module-name module-name)]
+ (exec [_ (require-module module-name ?alias)]
+ (return (annotated [::require ?file ?alias] ::&type/nothing)))))
+
(def ^:private analyse-form
(try-all-m [analyse-boolean
analyse-string
@@ -204,12 +221,14 @@
analyse-defclass
analyse-definterface
analyse-def
- analyse-import]))
+ analyse-import
+ analyse-require]))
;; [Interface]
(defn analyse [module-name tokens]
(match ((repeat-m analyse-form) {:name module-name,
:forms tokens
+ :deps {}
:env {:counter 0
:mappings {}}
:types &type/+init+})
diff --git a/src/lang/compiler.clj b/src/lang/compiler.clj
index d6a6f5125..8ef129dc0 100644
--- a/src/lang/compiler.clj
+++ b/src/lang/compiler.clj
@@ -3,6 +3,7 @@
(:require [clojure.string :as string]
[clojure.core.match :refer [match]]
(lang [type :as &type]
+ [lexer :as &lexer]
[parser :as &parser]
[analyser :as &analyser])
:reload)
@@ -11,9 +12,14 @@
ClassWriter
MethodVisitor)))
-(declare compile-form)
+(declare compile-form
+ compile)
;; [Utils/General]
+(defn ^:private write-file [file data]
+ (with-open [stream (java.io.BufferedOutputStream. (java.io.FileOutputStream. file))]
+ (.write stream data)))
+
(def ^:private +variant-class+ "test2.Tagged")
(defmacro ^:private defcompiler [name match body]
@@ -86,7 +92,7 @@
(defcompiler ^:private compile-call
[::&analyser/call ?fn ?args]
- (do ;; (prn 'compile-call ?fn)
+ (do (prn 'compile-call (:form ?fn) ?fn ?args)
(doseq [arg ?args]
(compile-form (assoc *state* :form arg)))
(match (:form ?fn)
@@ -142,32 +148,33 @@
(defcompiler ^:private compile-def
[::&analyser/def ?form ?body]
- (match ?form
- (?name :guard string?)
- (let [=type (:type ?body)
- ;; _ (prn '?body ?body)
- ]
- (doto (.visitField *writer* (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) ?name (->java-sig =type) nil nil)
- (.visitEnd)))
-
- [?name ?args]
- (if (= "main" ?name)
- (let [=method (doto (.visitMethod *writer* (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) ?name "([Ljava/lang/String;)V" nil nil)
- (.visitCode))]
- ;; (prn 'FN/?body ?body)
- (assert (compile-form (assoc *state* :writer =method :form ?body)) (str "Body couldn't compile: " (pr-str ?body)))
- (doto =method
- (.visitInsn Opcodes/RETURN)
- (.visitMaxs 0 0)
+ (do (prn 'compile-def ?form)
+ (match ?form
+ (?name :guard string?)
+ (let [=type (:type ?body)
+ ;; _ (prn '?body ?body)
+ ]
+ (doto (.visitField *writer* (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) ?name (->java-sig =type) nil nil)
(.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))))
- ))
+
+ [?name ?args]
+ (if (= "main" ?name)
+ (let [=method (doto (.visitMethod *writer* (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) ?name "([Ljava/lang/String;)V" nil nil)
+ (.visitCode))]
+ ;; (prn 'FN/?body ?body)
+ (assert (compile-form (assoc *state* :writer =method :form ?body)) (str "Body couldn't compile: " (pr-str ?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-defclass
[::&analyser/defclass [?package ?name] ?members]
@@ -226,6 +233,22 @@
[::&analyser/import ?class]
nil)
+(defcompiler compile-require
+ [::&analyser/require ?file ?alias]
+ (let [module-name (re-find #"[^/]+$" ?file)
+ _ (prn 'module-name module-name)
+ source-code (slurp (str module-name ".lang"))
+ _ (prn 'source-code source-code)
+ tokens (&lexer/lex source-code)
+ _ (prn 'tokens tokens)
+ syntax (&parser/parse tokens)
+ _ (prn 'syntax syntax)
+ ann-syntax (&analyser/analyse module-name syntax)
+ _ (prn 'ann-syntax ann-syntax)
+ class-data (compile module-name ann-syntax)]
+ (write-file (str module-name ".class") class-data)
+ nil))
+
(let [+compilers+ [compile-literal
compile-variant
compile-local
@@ -239,7 +262,8 @@
compile-def
compile-defclass
compile-definterface
- compile-import]]
+ compile-import
+ compile-require]]
(defn ^:private compile-form [state]
;; (prn 'compile-form/state state)
(or (some #(% state) +compilers+)
diff --git a/src/lang/parser.clj b/src/lang/parser.clj
index f756a8b14..3149cf5d4 100644
--- a/src/lang/parser.clj
+++ b/src/lang/parser.clj
@@ -102,6 +102,10 @@
[::&lexer/list ([[::&lexer/ident "import"] [::&lexer/ident ?class]] :seq)]
(return [::import ?class]))
+(defparser ^:private parse-require
+ [::&lexer/list ([[::&lexer/ident "require"] [::&lexer/string ?file] [::&lexer/ident "as"] [::&lexer/ident ?alias]] :seq)]
+ (return [::require ?file ?alias]))
+
(defparser ^:private parse-defclass
[::&lexer/list ([[::&lexer/ident "defclass"] [::&lexer/ident ?name] [::&lexer/tuple ?fields]] :seq)]
(let [fields (for [field ?fields]
@@ -200,9 +204,10 @@
parse-static-access
parse-dynamic-access
parse-ann-class
- parse-import
parse-defclass
parse-definterface
+ parse-import
+ parse-require
parse-fn-call]))
;; [Interface]