diff options
author | Eduardo Julian | 2016-08-14 21:47:23 -0400 |
---|---|---|
committer | Eduardo Julian | 2016-08-14 21:47:23 -0400 |
commit | 9a71b2703cab8b61a6234f6705730ce451db1c49 (patch) | |
tree | 52f768645b0874f242961712c6073c461e96a4ef | |
parent | 6b8810bbafca750414cebecd4bb32ea9010ade7d (diff) |
- Added support for natural numbers (unsigned integers).
-rw-r--r-- | src/lux/analyser.clj | 4 | ||||
-rw-r--r-- | src/lux/analyser/base.clj | 1 | ||||
-rw-r--r-- | src/lux/analyser/case.clj | 23 | ||||
-rw-r--r-- | src/lux/analyser/host.clj | 62 | ||||
-rw-r--r-- | src/lux/base.clj | 5 | ||||
-rw-r--r-- | src/lux/compiler.clj | 3 | ||||
-rw-r--r-- | src/lux/compiler/host.clj | 224 | ||||
-rw-r--r-- | src/lux/compiler/lux.clj | 1 | ||||
-rw-r--r-- | src/lux/compiler/type.clj | 4 | ||||
-rw-r--r-- | src/lux/lexer.clj | 3 | ||||
-rw-r--r-- | src/lux/optimizer.clj | 14 | ||||
-rw-r--r-- | src/lux/parser.clj | 3 | ||||
-rw-r--r-- | src/lux/type.clj | 32 | ||||
-rw-r--r-- | src/lux/type/host.clj | 8 |
14 files changed, 363 insertions, 24 deletions
diff --git a/src/lux/analyser.clj b/src/lux/analyser.clj index d6cc5cfda..2ad3745d8 100644 --- a/src/lux/analyser.clj +++ b/src/lux/analyser.clj @@ -71,6 +71,10 @@ (|do [_ (&type/check exo-type &type/Bool)] (return (&/|list (&&/|meta exo-type cursor (&&/$bool ?value))))) + (&/$NatS ?value) + (|do [_ (&type/check exo-type &type/Nat)] + (return (&/|list (&&/|meta exo-type cursor (&&/$nat ?value))))) + (&/$IntS ?value) (|do [_ (&type/check exo-type &type/Int)] (return (&/|list (&&/|meta exo-type cursor (&&/$int ?value))))) diff --git a/src/lux/analyser/base.clj b/src/lux/analyser/base.clj index fed65bb29..45d111249 100644 --- a/src/lux/analyser/base.clj +++ b/src/lux/analyser/base.clj @@ -12,6 +12,7 @@ ;; [Tags] (defvariant ("bool" 1) + ("nat" 1) ("int" 1) ("real" 1) ("char" 1) diff --git a/src/lux/analyser/case.clj b/src/lux/analyser/case.clj index 8b1ee3a89..bccbd4a07 100644 --- a/src/lux/analyser/case.clj +++ b/src/lux/analyser/case.clj @@ -18,6 +18,7 @@ (defvariant ("DefaultTotal" 1) ("BoolTotal" 2) + ("NatTotal" 2) ("IntTotal" 2) ("RealTotal" 2) ("CharTotal" 2) @@ -29,6 +30,7 @@ ("NoTestAC" 0) ("StoreTestAC" 1) ("BoolTestAC" 1) + ("NatTestAC" 1) ("IntTestAC" 1) ("RealTestAC" 1) ("CharTestAC" 1) @@ -265,6 +267,11 @@ =kont kont] (return (&/T [($BoolTestAC ?value) =kont]))) + (&/$NatS ?value) + (|do [_ (&type/check value-type &type/Nat) + =kont kont] + (return (&/T [($NatTestAC ?value) =kont]))) + (&/$IntS ?value) (|do [_ (&type/check value-type &type/Int) =kont kont] @@ -394,6 +401,9 @@ [($BoolTotal total? ?values) ($NoTestAC)] (return ($BoolTotal true ?values)) + [($NatTotal total? ?values) ($NoTestAC)] + (return ($NatTotal true ?values)) + [($IntTotal total? ?values) ($NoTestAC)] (return ($IntTotal true ?values)) @@ -418,6 +428,9 @@ [($BoolTotal total? ?values) ($StoreTestAC ?idx)] (return ($BoolTotal true ?values)) + [($NatTotal total? ?values) ($StoreTestAC ?idx)] + (return ($NatTotal true ?values)) + [($IntTotal total? ?values) ($StoreTestAC ?idx)] (return ($IntTotal true ?values)) @@ -442,6 +455,12 @@ [($BoolTotal total? ?values) ($BoolTestAC ?value)] (return ($BoolTotal total? (&/$Cons ?value ?values))) + [($DefaultTotal total?) ($NatTestAC ?value)] + (return ($NatTotal total? (&/|list ?value))) + + [($NatTotal total? ?values) ($NatTestAC ?value)] + (return ($NatTotal total? (&/$Cons ?value ?values))) + [($DefaultTotal total?) ($IntTestAC ?value)] (return ($IntTotal total? (&/|list ?value))) @@ -527,6 +546,10 @@ (return (or ?total (= #{true false} (set (&/->seq ?values)))))) + ($NatTotal ?total _) + (|do [_ (&type/check value-type &type/Nat)] + (return ?total)) + ($IntTotal ?total _) (|do [_ (&type/check value-type &type/Int)] (return ?total)) diff --git a/src/lux/analyser/host.clj b/src/lux/analyser/host.clj index be69dc54c..110bf253f 100644 --- a/src/lux/analyser/host.clj +++ b/src/lux/analyser/host.clj @@ -1054,6 +1054,53 @@ (return (&/|list (&&/|meta exo-type _cursor (&&/$proc (&/T ["lux" "=="]) (&/|list =left =right) (&/|list))))))))) +(do-template [<name> <proc> <input-type> <output-type>] + (defn <name> [analyse exo-type ?values] + (|do [:let [(&/$Cons x (&/$Cons y (&/$Nil))) ?values] + =x (&&/analyse-1 analyse <input-type> x) + =y (&&/analyse-1 analyse <input-type> y) + _ (&type/check exo-type <output-type>) + _cursor &/cursor] + (return (&/|list (&&/|meta <output-type> _cursor + (&&/$proc (&/T ["nat" <proc>]) (&/|list =x =y) (&/|list))))))) + + ^:private analyse-nat-add "add" &type/Nat &type/Nat + ^:private analyse-nat-sub "sub" &type/Nat &type/Nat + ^:private analyse-nat-mul "mul" &type/Nat &type/Nat + ^:private analyse-nat-div "div" &type/Nat &type/Nat + ^:private analyse-nat-rem "rem" &type/Nat &type/Nat + ^:private analyse-nat-eq "eq" &type/Nat &type/Bool + ^:private analyse-nat-lt "lt" &type/Nat &type/Bool + ) + +(defn ^:private analyse-nat-encode [analyse exo-type ?values] + (|do [:let [(&/$Cons x (&/$Nil)) ?values] + =x (&&/analyse-1 analyse &type/Nat x) + _ (&type/check exo-type &type/Text) + _cursor &/cursor] + (return (&/|list (&&/|meta &type/Text _cursor + (&&/$proc (&/T ["nat" "encode"]) (&/|list =x) (&/|list))))))) + +(defn ^:private analyse-nat-decode [analyse exo-type ?values] + (|do [:let [(&/$Cons x (&/$Nil)) ?values] + =x (&&/analyse-1 analyse &type/Text x) + _ (&type/check exo-type (&/$AppT &type/Maybe &type/Nat)) + _cursor &/cursor] + (return (&/|list (&&/|meta (&/$AppT &type/Maybe &type/Nat) _cursor + (&&/$proc (&/T ["nat" "decode"]) (&/|list =x) (&/|list))))))) + +(do-template [<name> <type> <op>] + (defn <name> [analyse exo-type ?values] + (|do [:let [(&/$Nil) ?values] + _ (&type/check exo-type <type>) + _cursor &/cursor] + (return (&/|list (&&/|meta <type> _cursor + (&&/$proc (&/T <op>) (&/|list) (&/|list))))))) + + ^:private analyse-nat-min-value &type/Nat ["nat" "min-value"] + ^:private analyse-nat-max-value &type/Nat ["nat" "max-value"] + ) + (defn analyse-host [analyse exo-type compilers category proc ?values] (|let [[_ _ compile-class compile-interface] compilers] (case category @@ -1078,6 +1125,21 @@ "put" (analyse-jvm-aastore analyse exo-type ?values) "remove" (analyse-array-remove analyse exo-type ?values) "size" (analyse-jvm-arraylength analyse exo-type ?values)) + + "nat" + (case proc + "+" (analyse-nat-add analyse exo-type ?values) + "-" (analyse-nat-sub analyse exo-type ?values) + "*" (analyse-nat-mul analyse exo-type ?values) + "/" (analyse-nat-div analyse exo-type ?values) + "%" (analyse-nat-rem analyse exo-type ?values) + "=" (analyse-nat-eq analyse exo-type ?values) + "<" (analyse-nat-lt analyse exo-type ?values) + "encode" (analyse-nat-encode analyse exo-type ?values) + "decode" (analyse-nat-decode analyse exo-type ?values) + "min-value" (analyse-nat-min-value analyse exo-type ?values) + "max-value" (analyse-nat-max-value analyse exo-type ?values) + ) "jvm" (case proc diff --git a/src/lux/base.clj b/src/lux/base.clj index 462bccd69..ba42f702d 100644 --- a/src/lux/base.clj +++ b/src/lux/base.clj @@ -70,6 +70,7 @@ ;; AST (defvariant ("BoolS" 1) + ("NatS" 1) ("IntS" 1) ("RealS" 1) ("CharS" 1) @@ -213,6 +214,7 @@ ;; Meta-data (defvariant ("BoolM" 1) + ("NatM" 1) ("IntM" 1) ("RealM" 1) ("CharM" 1) @@ -1044,6 +1046,9 @@ [_ ($BoolS ?value)] (pr-str ?value) + [_ ($NatS ?value)] + (Long/toUnsignedString ?value) + [_ ($IntS ?value)] (pr-str ?value) diff --git a/src/lux/compiler.clj b/src/lux/compiler.clj index 4548e71ab..19832d4e6 100644 --- a/src/lux/compiler.clj +++ b/src/lux/compiler.clj @@ -52,6 +52,9 @@ (&o/$bool ?value) (&&lux/compile-bool ?value) + (&o/$nat ?value) + (&&lux/compile-nat ?value) + (&o/$int ?value) (&&lux/compile-int ?value) diff --git a/src/lux/compiler/host.clj b/src/lux/compiler/host.clj index ae4b98f9f..cdfc7dc7e 100644 --- a/src/lux/compiler/host.clj +++ b/src/lux/compiler/host.clj @@ -779,26 +779,106 @@ (.visitInsn Opcodes/RETURN) (.visitMaxs 0 0) (.visitEnd)) + _ (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "log" "(Ljava/lang/Object;)Ljava/lang/Object;" nil nil) + (.visitCode) + (.visitFieldInsn Opcodes/GETSTATIC "java/lang/System" "out" "Ljava/io/PrintStream;") + (.visitLdcInsn "LOG: ") + (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/io/PrintStream" "print" "(Ljava/lang/Object;)V") + (.visitFieldInsn Opcodes/GETSTATIC "java/lang/System" "out" "Ljava/io/PrintStream;") + (.visitVarInsn Opcodes/ALOAD 0) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/io/PrintStream" "println" "(Ljava/lang/Object;)V") + (.visitVarInsn Opcodes/ALOAD 0) + (.visitInsn Opcodes/ARETURN) + (.visitMaxs 0 0) + (.visitEnd)) + _ (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "make_none" "()Ljava/lang/Object;" nil nil) + (.visitCode) + (.visitLdcInsn (->> #'&/$None meta ::&/idx int)) ;; I + (.visitInsn Opcodes/ACONST_NULL) ;; I? + (.visitLdcInsn &/unit-tag) ;; I?U + (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "sum_make" "(ILjava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object;") + (.visitInsn Opcodes/ARETURN) + (.visitMaxs 0 0) + (.visitEnd)) + _ (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "make_some" "(Ljava/lang/Object;)Ljava/lang/Object;" nil nil) + (.visitCode) + (.visitLdcInsn (->> #'&/$Some meta ::&/idx int)) ;; I + (.visitInsn Opcodes/ACONST_NULL) ;; I? + (.visitVarInsn Opcodes/ALOAD 0) ;; I?O + (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "sum_make" "(ILjava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object;") + (.visitInsn Opcodes/ARETURN) + (.visitMaxs 0 0) + (.visitEnd)) _ (let [$end (new Label) - $else (new Label)] - (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "log" "(Ljava/lang/Object;)Ljava/lang/Object;" nil nil) + ;; $then (new Label) + $else (new Label) + $from (new Label) + $to (new Label) + $handler (new Label)] + (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "decode_nat" "(Ljava/lang/String;)Ljava/lang/Object;" nil nil) (.visitCode) - (.visitFieldInsn Opcodes/GETSTATIC "java/lang/System" "out" "Ljava/io/PrintStream;") - (.visitLdcInsn "LOG: ") - (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/io/PrintStream" "print" "(Ljava/lang/Object;)V") - (.visitFieldInsn Opcodes/GETSTATIC "java/lang/System" "out" "Ljava/io/PrintStream;") (.visitVarInsn Opcodes/ALOAD 0) - (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/io/PrintStream" "println" "(Ljava/lang/Object;)V") + (.visitLdcInsn "+") + (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/lang/String" "startsWith" "(Ljava/lang/String;)Z") + (.visitJumpInsn Opcodes/IFEQ $else) (.visitVarInsn Opcodes/ALOAD 0) + (.visitLdcInsn (int 1)) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/lang/String" "substring" "(I)Ljava/lang/String;") + (.visitTryCatchBlock $from $to $handler "java/lang/Exception") + (.visitLabel $from) + (.visitMethodInsn Opcodes/INVOKESTATIC "java/lang/Long" "parseUnsignedLong" "(Ljava/lang/String;)J") + (.visitLabel $to) + ;; (.visitJumpInsn Opcodes/GOTO $then) + ;; (.visitLabel $then) + (&&/wrap-long) + (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "make_some" "(Ljava/lang/Object;)Ljava/lang/Object;") + (.visitFrame Opcodes/F_NEW 1 (to-array ["java/lang/String"]) 1 (to-array ["java/lang/Object"])) + (.visitJumpInsn Opcodes/GOTO $end) + (.visitLabel $handler) + (.visitFrame Opcodes/F_NEW 1 (to-array ["java/lang/String"]) 1 (to-array ["java/lang/Exception"])) + (.visitInsn Opcodes/POP) + (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "make_none" "()Ljava/lang/Object;") + (.visitFrame Opcodes/F_NEW 1 (to-array ["java/lang/String"]) 1 (to-array ["java/lang/Object"])) + (.visitJumpInsn Opcodes/GOTO $end) + (.visitLabel $else) + (.visitFrame Opcodes/F_NEW 1 (to-array ["java/lang/String"]) 0 (to-array [])) + (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "make_none" "()Ljava/lang/Object;") + (.visitLabel $end) + (.visitFrame Opcodes/F_NEW 1 (to-array ["java/lang/String"]) 1 (to-array ["java/lang/Object"])) (.visitInsn Opcodes/ARETURN) (.visitMaxs 0 0) (.visitEnd))) _ (doto =class - (compile-LuxRT-adt-methods) - (compile-LuxRT-pm-methods))]] + (compile-LuxRT-pm-methods) + (compile-LuxRT-adt-methods))]] (&&/save-class! (second (string/split &&/lux-utils-class #"/")) (.toByteArray (doto =class .visitEnd))))) +(defn ^:private compile-jvm-try [compile ?values special-args] + (|do [:let [(&/$Cons ?body (&/$Cons ?catch (&/$Nil))) ?values + ;; (&/$Nil) special-args + ] + ^MethodVisitor *writer* &/get-writer + :let [$from (new Label) + $to (new Label) + $handler (new Label) + $end (new Label)] + :let [_ (doto *writer* + (.visitTryCatchBlock $from $to $handler "java/lang/Exception") + (.visitLabel $from))] + _ (compile ?body) + :let [_ (doto *writer* + (.visitJumpInsn Opcodes/GOTO $end) + (.visitLabel $to) + (.visitLabel $handler))] + _ (compile ?catch) + :let [_ (doto *writer* + (.visitTypeInsn Opcodes/CHECKCAST &&/function-class) + (.visitInsn Opcodes/SWAP) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL &&/function-class &&/apply-method (&&/apply-signature 1)))] + :let [_ (.visitLabel *writer* $end)]] + (return nil))) + (do-template [<name> <op> <from-class> <from-method> <from-sig> <to-class> <to-sig>] (defn <name> [compile _?value special-args] (|do [:let [(&/$Cons ?value (&/$Nil)) _?value] @@ -1406,6 +1486,117 @@ (.visitLabel $end))]] (return nil))) +(do-template [<name> <opcode> <wrapper-class> <value-method> <value-method-sig> <wrap>] + (defn <name> [compile ?values special-args] + (|do [:let [(&/$Cons ?x (&/$Cons ?y (&/$Nil))) ?values] + :let [+wrapper-class+ (&host-generics/->bytecode-class-name <wrapper-class>)] + ^MethodVisitor *writer* &/get-writer + _ (compile ?x) + :let [_ (doto *writer* + (.visitTypeInsn Opcodes/CHECKCAST +wrapper-class+) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL +wrapper-class+ <value-method> <value-method-sig>))] + _ (compile ?y) + :let [_ (doto *writer* + (.visitTypeInsn Opcodes/CHECKCAST +wrapper-class+) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL +wrapper-class+ <value-method> <value-method-sig>)) + _ (doto *writer* + (.visitInsn <opcode>) + (<wrap>))]] + (return nil))) + + ^:private compile-nat-add Opcodes/LADD "java.lang.Long" "longValue" "()J" &&/wrap-long + ^:private compile-nat-sub Opcodes/LSUB "java.lang.Long" "longValue" "()J" &&/wrap-long + ^:private compile-nat-mul Opcodes/LMUL "java.lang.Long" "longValue" "()J" &&/wrap-long + ) + +(do-template [<name> <wrapper-class> <value-method> <value-method-sig> <wrap> <comp-method> <comp-sig>] + (defn <name> [compile ?values special-args] + (|do [:let [(&/$Cons ?x (&/$Cons ?y (&/$Nil))) ?values] + :let [+wrapper-class+ (&host-generics/->bytecode-class-name <wrapper-class>)] + ^MethodVisitor *writer* &/get-writer + _ (compile ?x) + :let [_ (doto *writer* + (.visitTypeInsn Opcodes/CHECKCAST +wrapper-class+) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL +wrapper-class+ <value-method> <value-method-sig>))] + _ (compile ?y) + :let [_ (doto *writer* + (.visitTypeInsn Opcodes/CHECKCAST +wrapper-class+) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL +wrapper-class+ <value-method> <value-method-sig>)) + _ (doto *writer* + (.visitMethodInsn Opcodes/INVOKESTATIC +wrapper-class+ <comp-method> <comp-sig>) + (&&/wrap-long))]] + (return nil))) + + ^:private compile-nat-div "java.lang.Long" "longValue" "()J" &&/wrap-long "divideUnsigned" "(JJ)J" + ^:private compile-nat-rem "java.lang.Long" "longValue" "()J" &&/wrap-long "remainderUnsigned" "(JJ)J" + ) + +(do-template [<name> <cmpcode> <cmp-output> <wrapper-class> <value-method> <value-method-sig> <comp-method> <comp-sig>] + (defn <name> [compile ?values special-args] + (|do [:let [(&/$Cons ?x (&/$Cons ?y (&/$Nil))) ?values] + :let [+wrapper-class+ (&host-generics/->bytecode-class-name <wrapper-class>)] + ^MethodVisitor *writer* &/get-writer + _ (compile ?x) + :let [_ (doto *writer* + (.visitTypeInsn Opcodes/CHECKCAST +wrapper-class+) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL +wrapper-class+ <value-method> <value-method-sig>))] + _ (compile ?y) + :let [_ (doto *writer* + (.visitTypeInsn Opcodes/CHECKCAST +wrapper-class+) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL +wrapper-class+ <value-method> <value-method-sig>)) + $then (new Label) + $end (new Label) + _ (doto *writer* + (.visitMethodInsn Opcodes/INVOKESTATIC +wrapper-class+ "compareUnsigned" "(JJ)I") + (.visitLdcInsn (int <cmp-output>)) + (.visitJumpInsn Opcodes/IF_ICMPEQ $then) + (.visitFieldInsn Opcodes/GETSTATIC (&host-generics/->bytecode-class-name "java.lang.Boolean") "FALSE" (&host-generics/->type-signature "java.lang.Boolean")) + (.visitJumpInsn Opcodes/GOTO $end) + (.visitLabel $then) + (.visitFieldInsn Opcodes/GETSTATIC (&host-generics/->bytecode-class-name "java.lang.Boolean") "TRUE" (&host-generics/->type-signature "java.lang.Boolean")) + (.visitLabel $end))]] + (return nil))) + + ^:private compile-nat-eq Opcodes/LCMP 0 "java.lang.Long" "longValue" "()J" "compareUnsigned" "(JJ)I" + ^:private compile-nat-lt Opcodes/LCMP -1 "java.lang.Long" "longValue" "()J" "compareUnsigned" "(JJ)I" + ) + +(defn ^:private compile-nat-encode [compile ?values special-args] + (|do [:let [(&/$Cons ?x (&/$Nil)) ?values] + :let [+wrapper-class+ (&host-generics/->bytecode-class-name "java.lang.Long")] + ^MethodVisitor *writer* &/get-writer + _ (compile ?x) + :let [_ (doto *writer* + (.visitTypeInsn Opcodes/CHECKCAST +wrapper-class+) + (.visitMethodInsn Opcodes/INVOKEVIRTUAL +wrapper-class+ "longValue" "()J"))] + :let [_ (doto *writer* + (.visitMethodInsn Opcodes/INVOKESTATIC +wrapper-class+ "toUnsignedString" "(J)Ljava/lang/String;"))]] + (return nil))) + +(defn ^:private compile-nat-decode [compile ?values special-args] + (|do [:let [(&/$Cons ?x (&/$Nil)) ?values] + :let [+wrapper-class+ (&host-generics/->bytecode-class-name "java.lang.String")] + ^MethodVisitor *writer* &/get-writer + _ (compile ?x) + :let [_ (doto *writer* + (.visitTypeInsn Opcodes/CHECKCAST +wrapper-class+))] + :let [_ (doto *writer* + (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "decode_nat" "(Ljava/lang/String;)Ljava/lang/Object;"))]] + (return nil))) + +(do-template [<name> <instr> <wrapper>] + (defn <name> [compile ?values special-args] + (|do [:let [(&/$Nil) ?values] + ^MethodVisitor *writer* &/get-writer + :let [_ (doto *writer* + <instr> + <wrapper>)]] + (return nil))) + + ^:private compile-nat-min-value (.visitLdcInsn 0) &&/wrap-long + ^:private compile-nat-max-value (.visitLdcInsn -1) &&/wrap-long + ) + (defn compile-host [compile proc-category proc-name ?values special-args] (case proc-category "lux" @@ -1425,6 +1616,21 @@ "array" (case proc-name "get" (compile-array-get compile ?values special-args)) + + "nat" + (case proc-name + "add" (compile-nat-add compile ?values special-args) + "sub" (compile-nat-sub compile ?values special-args) + "mul" (compile-nat-mul compile ?values special-args) + "div" (compile-nat-div compile ?values special-args) + "rem" (compile-nat-rem compile ?values special-args) + "eq" (compile-nat-eq compile ?values special-args) + "lt" (compile-nat-lt compile ?values special-args) + "encode" (compile-nat-encode compile ?values special-args) + "decode" (compile-nat-decode compile ?values special-args) + "max-value" (compile-nat-max-value compile ?values special-args) + "min-value" (compile-nat-min-value compile ?values special-args) + ) "jvm" (case proc-name diff --git a/src/lux/compiler/lux.clj b/src/lux/compiler/lux.clj index 87113b538..83bb2ac44 100644 --- a/src/lux/compiler/lux.clj +++ b/src/lux/compiler/lux.clj @@ -45,6 +45,7 @@ (.visitMethodInsn Opcodes/INVOKESPECIAL <class> "<init>" <sig>))]] (return nil))) + compile-nat "java/lang/Long" "(J)V" long compile-int "java/lang/Long" "(J)V" long compile-real "java/lang/Double" "(D)V" double compile-char "java/lang/Character" "(C)V" char diff --git a/src/lux/compiler/type.clj b/src/lux/compiler/type.clj index bf6ec5539..f51165ea3 100644 --- a/src/lux/compiler/type.clj +++ b/src/lux/compiler/type.clj @@ -30,6 +30,7 @@ (<tag> value))) ^:private bool$ &a/$bool "(-> Bool Analysis)" + ^:private nat$ &a/$nat "(-> Nat Analysis)" ^:private int$ &a/$int "(-> Int Analysis)" ^:private real$ &a/$real "(-> Real Analysis)" ^:private char$ &a/$char "(-> Char Analysis)" @@ -109,6 +110,9 @@ (&/$BoolM value) (variant$ #'&/$BoolM (bool$ value)) + (&/$NatM value) + (variant$ #'&/$NatM (nat$ value)) + (&/$IntM value) (variant$ #'&/$IntM (int$ value)) diff --git a/src/lux/lexer.clj b/src/lux/lexer.clj index 9754456b9..690a25106 100644 --- a/src/lux/lexer.clj +++ b/src/lux/lexer.clj @@ -15,6 +15,7 @@ ("White_Space" 1) ("Comment" 1) ("Bool" 1) + ("Nat" 1) ("Int" 1) ("Real" 1) ("Char" 1) @@ -157,6 +158,7 @@ (return (&/T [meta (<tag> token)])))) lex-bool $Bool #"^(true|false)" + lex-nat $Nat #"^\+(0|[1-9][0-9]*)" lex-int $Int #"^-?(0|[1-9][0-9]*)" lex-real $Real #"^-?(0\.[0-9]+|[1-9][0-9]*\.[0-9]+)(e-?[1-9][0-9]*)?" ) @@ -233,6 +235,7 @@ lex-comment lex-bool lex-real + lex-nat lex-int lex-char lex-text diff --git a/src/lux/optimizer.clj b/src/lux/optimizer.clj index c03515370..fd859d90d 100644 --- a/src/lux/optimizer.clj +++ b/src/lux/optimizer.clj @@ -10,6 +10,7 @@ ;; [Tags] (defvariant ("bool" 1) + ("nat" 1) ("int" 1) ("real" 1) ("char" 1) @@ -34,6 +35,7 @@ ("PopPM" 0) ("BindPM" 1) ("BoolPM" 1) + ("NatPM" 1) ("IntPM" 1) ("RealPM" 1) ("CharPM" 1) @@ -58,6 +60,10 @@ (&/|list ($BoolPM _value) $PopPM) + (&a-case/$NatTestAC _value) + (&/|list ($NatPM _value) + $PopPM) + (&a-case/$IntTestAC _value) (&/|list ($IntPM _value) $PopPM) @@ -129,6 +135,11 @@ ($BoolPM _pre-value) ($AltPM pre post)) + [($NatPM _pre-value) ($NatPM _post-value)] + (if (= _pre-value _post-value) + ($NatPM _pre-value) + ($AltPM pre post)) + [($IntPM _pre-value) ($IntPM _post-value)] (if (= _pre-value _post-value) ($IntPM _pre-value) @@ -342,6 +353,9 @@ (&a/$bool value) (&/T [meta ($bool value)]) + (&a/$nat value) + (&/T [meta ($nat value)]) + (&a/$int value) (&/T [meta ($int value)]) diff --git a/src/lux/parser.clj b/src/lux/parser.clj index 5b0bfce57..d5b4a54cd 100644 --- a/src/lux/parser.clj +++ b/src/lux/parser.clj @@ -76,6 +76,9 @@ (&lexer/$Bool ?value) (return (&/|list (&/T [meta (&/$BoolS (Boolean/parseBoolean ?value))]))) + (&lexer/$Nat ?value) + (return (&/|list (&/T [meta (&/$NatS (Long/parseUnsignedLong ?value))]))) + (&lexer/$Int ?value) (return (&/|list (&/T [meta (&/$IntS (Long/parseLong ?value))]))) diff --git a/src/lux/type.clj b/src/lux/type.clj index e79cfe46d..7ca4145a6 100644 --- a/src/lux/type.clj +++ b/src/lux/type.clj @@ -28,6 +28,7 @@ (def empty-env &/$Nil) (def Bool (&/$NamedT (&/T ["lux" "Bool"]) (&/$HostT "java.lang.Boolean" &/$Nil))) +(def Nat (&/$NamedT (&/T ["lux" "Nat"]) (&/$HostT "#Nat" &/$Nil))) (def Int (&/$NamedT (&/T ["lux" "Int"]) (&/$HostT "java.lang.Long" &/$Nil))) (def Real (&/$NamedT (&/T ["lux" "Real"]) (&/$HostT "java.lang.Double" &/$Nil))) (def Char (&/$NamedT (&/T ["lux" "Char"]) (&/$HostT "java.lang.Character" &/$Nil))) @@ -120,25 +121,28 @@ ;; BoolM Bool (&/$SumT - ;; IntM - Int + ;; NatM + Nat (&/$SumT - ;; RealM - Real + ;; IntM + Int (&/$SumT - ;; CharM - Char + ;; RealM + Real (&/$SumT - ;; TextM - Text + ;; CharM + Char (&/$SumT - ;; IdentM - Ident + ;; TextM + Text (&/$SumT - ;; ListM - (&/$AppT List DefMetaValue) - ;; DictM - (&/$AppT List (&/$ProdT Text DefMetaValue))))))))) + ;; IdentM + Ident + (&/$SumT + ;; ListM + (&/$AppT List DefMetaValue) + ;; DictM + (&/$AppT List (&/$ProdT Text DefMetaValue)))))))))) ) &/$VoidT)))) diff --git a/src/lux/type/host.clj b/src/lux/type/host.clj index b3858d2e5..a3252ddb7 100644 --- a/src/lux/type/host.clj +++ b/src/lux/type/host.clj @@ -16,6 +16,7 @@ ;; [Exports] (def array-data-tag "#Array") (def null-data-tag "#Null") +(def nat-data-tag "#Nat") ;; [Utils] (defn ^:private trace-lineage* [^Class super-class ^Class sub-class] @@ -267,7 +268,12 @@ (and (= array-data-tag e!name) (not= array-data-tag a!name)) (check-error "" (&/$HostT e!name e!params) (&/$HostT a!name a!params)) - + + (and (or (= nat-data-tag e!name) + (= "java.lang.Long" e!name)) + (= nat-data-tag a!name)) + (return fixpoints) + :else (let [e!name (as-obj e!name) a!name (as-obj a!name)] |