aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduardo Julian2017-05-07 02:36:32 -0400
committerEduardo Julian2017-05-07 02:36:32 -0400
commit42848dd5a3b2e1d02752201343e18f075a733645 (patch)
tree83ed869a644adfa5b14137da07073df080abfce1
parentdda9e7b3f998e7649104d478469b8a27c3c981ba (diff)
- Fully implemented Deg encoding/decoding in pure Lux.
- No longer relying in LuxRT-supported implementations.
-rw-r--r--luxc/src/lux/analyser/proc/common.clj3
-rw-r--r--luxc/src/lux/compiler/js/proc/common.clj5
-rw-r--r--luxc/src/lux/compiler/js/rt.clj112
-rw-r--r--luxc/src/lux/compiler/jvm/proc/common.clj25
-rw-r--r--luxc/src/lux/compiler/jvm/rt.clj518
-rw-r--r--stdlib/source/lux.lux11
-rw-r--r--stdlib/source/lux/data/number.lux128
7 files changed, 96 insertions, 706 deletions
diff --git a/luxc/src/lux/analyser/proc/common.clj b/luxc/src/lux/analyser/proc/common.clj
index 842efc9c5..b6727ff53 100644
--- a/luxc/src/lux/analyser/proc/common.clj
+++ b/luxc/src/lux/analyser/proc/common.clj
@@ -254,7 +254,6 @@
(return (&/|list (&&/|meta exo-type _cursor
(&&/$proc (&/T <decode-op>) (&/|list =x) (&/|list)))))))))
- ^:private analyse-deg-encode ["deg" "encode"] ^:private analyse-deg-decode ["deg" "decode"] &type/Deg
^:private analyse-real-encode ["real" "encode"] ^:private analyse-real-decode ["real" "decode"] &type/Real
)
@@ -572,8 +571,6 @@
"%" (analyse-deg-rem analyse exo-type ?values)
"=" (analyse-deg-eq analyse exo-type ?values)
"<" (analyse-deg-lt analyse exo-type ?values)
- "encode" (analyse-deg-encode analyse exo-type ?values)
- "decode" (analyse-deg-decode analyse exo-type ?values)
"min-value" (analyse-deg-min-value analyse exo-type ?values)
"max-value" (analyse-deg-max-value analyse exo-type ?values)
"to-real" (analyse-deg-to-real analyse exo-type ?values)
diff --git a/luxc/src/lux/compiler/js/proc/common.clj b/luxc/src/lux/compiler/js/proc/common.clj
index eb4e27857..2f872676e 100644
--- a/luxc/src/lux/compiler/js/proc/common.clj
+++ b/luxc/src/lux/compiler/js/proc/common.clj
@@ -148,9 +148,6 @@
(return (str "LuxRT$" <method> "(" =x ")"))
))
- ^:private compile-deg-encode "encodeD64"
- ^:private compile-deg-decode "decodeD64"
-
^:private compile-real-decode "decodeReal"
)
@@ -526,8 +523,6 @@
"%" (compile-deg-rem compile ?values special-args)
"=" (compile-deg-eq compile ?values special-args)
"<" (compile-deg-lt compile ?values special-args)
- "encode" (compile-deg-encode compile ?values special-args)
- "decode" (compile-deg-decode compile ?values special-args)
"max-value" (compile-deg-max-value compile ?values special-args)
"min-value" (compile-deg-min-value compile ?values special-args)
"to-real" (compile-deg-to-real compile ?values special-args)
diff --git a/luxc/src/lux/compiler/js/rt.clj b/luxc/src/lux/compiler/js/rt.clj
index d5f503f01..838598bbb 100644
--- a/luxc/src/lux/compiler/js/rt.clj
+++ b/luxc/src/lux/compiler/js/rt.clj
@@ -650,118 +650,6 @@
"var high = shifted | 0;"
"return LuxRT$makeI64(high,low);"
"})")
- "_add_deg_digit_powers" (str "(function LuxRT$_add_deg_digit_powers(left,right) {"
- "var output = new Array(64);"
- "var carry = 0;"
- (str "for(var idx = 63; idx >= 0; idx--) {"
- "var raw = left[idx] + right[idx] + carry;"
- "output[idx] = raw % 10;"
- "raw = (raw / 10)|0;"
- "}")
- "return output;"
- "})")
- "_times5" (str "(function LuxRT$_times5(exp,digits) {"
- "var carry = 0;"
- (str "for(var idx = exp; idx >= 0; idx--) {"
- "var raw = (digits[exp] * 5) + carry;"
- "digits[exp] = raw % 10;"
- "carry = (raw / 10)|0;"
- "}")
- "return digits;"
- "})")
- "_deg_digit_power" (str "(function LuxRT$_deg_digit_power(exp) {"
- "var digits = new Array(64);"
- "digits[exp] = 1;"
- (str "for(var idx = exp; idx >= 0; idx--) {"
- "digits = LuxRT$_times5(exp,digits);"
- "}")
- "return digits;"
- "})")
- "_bitIsSet" (str "(function LuxRT$_bitIsSet(input,idx) {"
- "idx &= 63;"
- (str "if(idx < 32) {"
- "return (input.L & (1 << idx)) !== 0;"
- "}")
- (str "else {"
- "return (input.H & (1 << (idx - 32))) !== 0;"
- "}")
- "})")
- "encodeD64" (str "(function LuxRT$encodeD64(input) {"
- (str "if(LuxRT$eqI64(input,LuxRT$ZERO)) {"
- "return '.0';"
- "}")
- "var digits = new Array(64);"
- (str "for(var idx = 63; idx >= 0; idx--) {"
- (str "if(LuxRT$_bitIsSet(input,idx)) {"
- "var power = LuxRT$_deg_digit_power(63 - idx);"
- "digits = LuxRT$_add_deg_digit_powers(digits,power);"
- "}")
- "}")
- "var raw = '.'.concat(digits.join(''));"
- "return raw.split(/0*$/)[0];"
- "})")
- "deg_text_to_digits" (str "(function LuxRT$deg_text_to_digits(input) {"
- "var output = new Array(64);"
- (str "for(var idx = input.length-1; idx >= 0; idx--) {"
- "output[idx] = parseInt(input.substring(idx, idx+1));"
- "}")
- "return output;"
- "})")
- "deg_digits_lt" (str "(function LuxRT$deg_digits_lt(l,r) {"
- (str "for(var idx = 0; idx < 64; idx++) {"
- (str "if(l[idx] < r[idx]) {"
- "return true;"
- "}"
- "else if(l[idx] > r[idx]) {"
- "return false;"
- "}")
- "}")
- "return false;"
- "})")
- "deg_digits_sub_once" (str "(function LuxRT$deg_digits_sub_once(target,digit,idx) {"
- (str "while(true) {"
- (str "if(target[idx] > digit) {"
- (str "target[idx] = target[idx] - digit;"
- "return target;")
- "}"
- "else {"
- (str "target[idx] = 10 - (digit - target[idx]);"
- "idx--;"
- "digit=1;")
- "}")
- "}")
- "})")
- "deg_digits_sub" (str "(function LuxRT$deg_digits_sub(l,r) {"
- (str "for(var idx = 63; idx >= 0; idx--) {"
- "l = LuxRT$deg_digits_sub_once(l,r[idx],idx);"
- "}")
- "return l;"
- "})")
- "decodeD64" (let [failure (str "return " const-none ";")]
- (str "(function LuxRT$decodeD64(input) {"
- "input = LuxRT$clean_separators(input);"
- (str "if(/^\\.\\d+$/.exec(input) && input.length <= 65) {"
- (str "try {"
- (str "var digits = LuxRT$deg_text_to_digits(input.substring(1));")
- "var output = LuxRT$makeI64(0,0);"
- (str "for(var idx = 0; idx < 64; idx++) {"
- "var power = LuxRT$deg_text_to_digits(idx);"
- (str "if(LuxRT$deg_digits_lt(power,digits)) {"
- (str "digits = LuxRT$deg_digits_sub(digits,power);"
- "var powerBit = LuxRT$shlI64(LuxRT$makeI64(0,1),(63-idx));"
- "output = LuxRT$orI64(output,powerBit);")
- "}")
- "}")
- (str "return " (make-some "output") ";")
- "}"
- "catch(ex) {"
- failure
- "}")
- "}"
- "else {"
- failure
- "}")
- "})"))
})
(def ^:private io-methods
diff --git a/luxc/src/lux/compiler/jvm/proc/common.clj b/luxc/src/lux/compiler/jvm/proc/common.clj
index b616f4bdf..1fe49d227 100644
--- a/luxc/src/lux/compiler/jvm/proc/common.clj
+++ b/luxc/src/lux/compiler/jvm/proc/common.clj
@@ -387,29 +387,6 @@
^:private compile-real-negative-infinity (.visitLdcInsn Double/NEGATIVE_INFINITY) &&/wrap-double
)
-(do-template [<encode-name> <encode-method> <decode-name> <decode-method>]
- (do (defn <encode-name> [compile ?values special-args]
- (|do [:let [(&/$Cons ?x (&/$Nil)) ?values]
- ^MethodVisitor *writer* &/get-writer
- _ (compile ?x)
- :let [_ (doto *writer*
- &&/unwrap-long
- (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" <encode-method> "(J)Ljava/lang/String;"))]]
- (return nil)))
-
- (let [+wrapper-class+ (&host-generics/->bytecode-class-name "java.lang.String")]
- (defn <decode-name> [compile ?values special-args]
- (|do [:let [(&/$Cons ?x (&/$Nil)) ?values]
- ^MethodVisitor *writer* &/get-writer
- _ (compile ?x)
- :let [_ (doto *writer*
- (.visitTypeInsn Opcodes/CHECKCAST +wrapper-class+)
- (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" <decode-method> "(Ljava/lang/String;)Ljava/lang/Object;"))]]
- (return nil)))))
-
- ^:private compile-deg-encode "encode_deg" ^:private compile-deg-decode "decode_deg"
- )
-
(do-template [<name> <class> <signature> <unwrap>]
(defn <name> [compile ?values special-args]
(|do [:let [(&/$Cons ?input (&/$Nil)) ?values]
@@ -958,8 +935,6 @@
"%" (compile-deg-rem compile ?values special-args)
"=" (compile-deg-eq compile ?values special-args)
"<" (compile-deg-lt compile ?values special-args)
- "encode" (compile-deg-encode compile ?values special-args)
- "decode" (compile-deg-decode compile ?values special-args)
"max-value" (compile-deg-max-value compile ?values special-args)
"min-value" (compile-deg-min-value compile ?values special-args)
"to-real" (compile-deg-to-real compile ?values special-args)
diff --git a/luxc/src/lux/compiler/jvm/rt.clj b/luxc/src/lux/compiler/jvm/rt.clj
index aa0c881d0..31a2c800c 100644
--- a/luxc/src/lux/compiler/jvm/rt.clj
+++ b/luxc/src/lux/compiler/jvm/rt.clj
@@ -461,523 +461,7 @@
;; FINISH
(.visitInsn Opcodes/LRETURN)
(.visitMaxs 0 0)
- (.visitEnd))
- _ (let [$loop-start (new Label)
- $do-a-round (new Label)]
- (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "times5" "(I[B)[B" nil nil)
- (.visitCode)
- (.visitLdcInsn (int 0)) ;; {carry}
- (.visitLabel $loop-start)
- (.visitVarInsn Opcodes/ILOAD 0)
- (.visitJumpInsn Opcodes/IFGE $do-a-round)
- (.visitVarInsn Opcodes/ALOAD 1)
- (.visitInsn Opcodes/ARETURN)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; {carry}
- (.visitLabel $do-a-round)
- (.visitVarInsn Opcodes/ALOAD 1)
- (.visitVarInsn Opcodes/ILOAD 0)
- (.visitInsn Opcodes/BALOAD) ;; {carry, current-digit}
- (.visitLdcInsn (int 5))
- (.visitInsn Opcodes/IMUL)
- (.visitInsn Opcodes/IADD) ;; {next-raw-digit}
- (.visitInsn Opcodes/DUP)
- (.visitLdcInsn (int 10))
- (.visitInsn Opcodes/IREM) ;; {next-raw-digit, next-digit}
- (.visitVarInsn Opcodes/ALOAD 1)
- (.visitVarInsn Opcodes/ILOAD 0)
- swap2x1
- (.visitInsn Opcodes/BASTORE) ;; {next-raw-digit}
- (.visitLdcInsn (int 10))
- (.visitInsn Opcodes/IDIV) ;; {next-carry}
- ;; Decrement index
- (.visitVarInsn Opcodes/ILOAD 0)
- (.visitLdcInsn (int 1))
- (.visitInsn Opcodes/ISUB)
- (.visitVarInsn Opcodes/ISTORE 0)
- ;; Iterate
- (.visitJumpInsn Opcodes/GOTO $loop-start)
- (.visitMaxs 0 0)
- (.visitEnd)))
- _ (let [$loop-start (new Label)
- $do-a-round (new Label)]
- (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "deg_digit_power" "(I)[B" nil nil)
- (.visitCode)
- ;; Initialize digits array.
- (.visitLdcInsn (int deg-bits))
- (.visitIntInsn Opcodes/NEWARRAY Opcodes/T_BYTE) ;; {digits}
- (.visitInsn Opcodes/DUP)
- (.visitVarInsn Opcodes/ILOAD 0)
- (.visitLdcInsn (int 1))
- (.visitInsn Opcodes/BASTORE) ;; digits = 5^0
- (.visitVarInsn Opcodes/ASTORE 1)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitVarInsn Opcodes/ILOAD 0) ;; {times}
- (.visitLabel $loop-start)
- (.visitInsn Opcodes/DUP)
- (.visitJumpInsn Opcodes/IFGE $do-a-round)
- (.visitVarInsn Opcodes/ALOAD 1)
- (.visitInsn Opcodes/ARETURN)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $do-a-round)
- ;; {times}
- (.visitVarInsn Opcodes/ILOAD 0)
- (.visitVarInsn Opcodes/ALOAD 1)
- (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "times5" "(I[B)[B") ;; {digits*5, times}
- (.visitVarInsn Opcodes/ASTORE 1) ;; {times}
- ;; Decrement index
- (.visitLdcInsn (int 1))
- (.visitInsn Opcodes/ISUB)
- ;; {times-1}
- (.visitJumpInsn Opcodes/GOTO $loop-start)
- (.visitMaxs 0 0)
- (.visitEnd)))
- _ (let [$loop-start (new Label)
- $do-a-round (new Label)]
- (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "add_deg_digit_powers" "([B[B)[B" nil nil)
- (.visitCode)
- (.visitLdcInsn (int (dec deg-bits)))
- (.visitVarInsn Opcodes/ISTORE 2) ;; Index
- (.visitLdcInsn (int deg-bits))
- (.visitIntInsn Opcodes/NEWARRAY Opcodes/T_BYTE)
- (.visitVarInsn Opcodes/ASTORE 3) ;; added_digits
- (.visitLdcInsn (int 0)) ;; {carry}
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; {carry}
- (.visitLabel $loop-start)
- (.visitVarInsn Opcodes/ILOAD 2)
- (.visitJumpInsn Opcodes/IFGE $do-a-round)
- ;; {carry}
- (.visitVarInsn Opcodes/ALOAD 3)
- (.visitInsn Opcodes/ARETURN)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; {carry}
- (.visitLabel $do-a-round)
- (.visitVarInsn Opcodes/ALOAD 0)
- (.visitVarInsn Opcodes/ILOAD 2)
- (.visitInsn Opcodes/BALOAD) ;; {carry, dL}
- (.visitVarInsn Opcodes/ALOAD 1)
- (.visitVarInsn Opcodes/ILOAD 2)
- (.visitInsn Opcodes/BALOAD) ;; {carry, dL, dR}
- (.visitInsn Opcodes/IADD)
- (.visitInsn Opcodes/IADD) ;; {raw-next-digit}
- (.visitInsn Opcodes/DUP)
- (.visitLdcInsn (int 10))
- (.visitInsn Opcodes/IREM) ;; {raw-next-digit, next-digit}
- (.visitVarInsn Opcodes/ALOAD 3)
- (.visitVarInsn Opcodes/ILOAD 2)
- swap2x1
- (.visitInsn Opcodes/BASTORE) ;; {raw-next-digit}
- (.visitLdcInsn (int 10))
- (.visitInsn Opcodes/IDIV) ;; {next-carry}
- ;; Decrement index
- (.visitVarInsn Opcodes/ILOAD 2)
- (.visitLdcInsn (int 1))
- (.visitInsn Opcodes/ISUB)
- (.visitVarInsn Opcodes/ISTORE 2)
- ;; Iterate
- (.visitJumpInsn Opcodes/GOTO $loop-start)
- (.visitMaxs 0 0)
- (.visitEnd)))
- _ (let [$loop-start (new Label)
- $do-a-round (new Label)]
- (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "deg_digits_to_text" "([B)Ljava/lang/String;" nil nil)
- (.visitCode)
- (.visitLdcInsn (int (dec deg-bits)))
- (.visitVarInsn Opcodes/ISTORE 1) ;; Index
- (.visitLdcInsn "") ;; {text}
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $loop-start)
- (.visitVarInsn Opcodes/ILOAD 1)
- (.visitJumpInsn Opcodes/IFGE $do-a-round)
- (.visitInsn Opcodes/ARETURN)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $do-a-round)
- (.visitVarInsn Opcodes/ALOAD 0)
- (.visitVarInsn Opcodes/ILOAD 1)
- (.visitInsn Opcodes/BALOAD) ;; {text, digit}
- (.visitLdcInsn (int 10)) ;; {text, digit, radix}
- (.visitMethodInsn Opcodes/INVOKESTATIC "java/lang/Character" "forDigit" "(II)C") ;; {text, digit-char}
- (.visitMethodInsn Opcodes/INVOKESTATIC "java/lang/Character" "toString" "(C)Ljava/lang/String;") ;; {text, digit-char-text}
- (.visitInsn Opcodes/SWAP)
- (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/lang/String" "concat" "(Ljava/lang/String;)Ljava/lang/String;")
- ;; Decrement index
- (.visitVarInsn Opcodes/ILOAD 1)
- (.visitLdcInsn (int 1))
- (.visitInsn Opcodes/ISUB)
- (.visitVarInsn Opcodes/ISTORE 1)
- ;; Iterate
- (.visitJumpInsn Opcodes/GOTO $loop-start)
- (.visitMaxs 0 0)
- (.visitEnd)))
- _ (let [$loop-start (new Label)
- $do-a-round (new Label)
- $not-set (new Label)
- $next-iteration (new Label)
- $normal-path (new Label)]
- (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "encode_deg" "(J)Ljava/lang/String;" nil nil)
- (.visitCode)
- ;; A quick corner-case to handle.
- (.visitVarInsn Opcodes/LLOAD 0)
- (.visitLdcInsn (long 0))
- (.visitInsn Opcodes/LCMP)
- (.visitJumpInsn Opcodes/IFNE $normal-path)
- (.visitLdcInsn ".0")
- (.visitInsn Opcodes/ARETURN)
- (.visitLabel $normal-path)
- ;; Normal case
- (.visitLdcInsn (int (dec deg-bits)))
- (.visitVarInsn Opcodes/ISTORE 2) ;; Index
- (.visitLdcInsn (int deg-bits))
- (.visitIntInsn Opcodes/NEWARRAY Opcodes/T_BYTE)
- (.visitVarInsn Opcodes/ASTORE 3) ;; digits
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $loop-start)
- (.visitVarInsn Opcodes/ILOAD 2)
- (.visitJumpInsn Opcodes/IFGE $do-a-round)
- ;; Prepare text to return.
- (.visitVarInsn Opcodes/ALOAD 3)
- (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "deg_digits_to_text" "([B)Ljava/lang/String;")
- (.visitLdcInsn ".")
- (.visitInsn Opcodes/SWAP)
- (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/lang/String" "concat" "(Ljava/lang/String;)Ljava/lang/String;")
- ;; Trim unnecessary 0s at the end...
- (.visitLdcInsn "0*$")
- (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/lang/String" "split" "(Ljava/lang/String;)[Ljava/lang/String;")
- (.visitLdcInsn (int 0))
- (.visitInsn Opcodes/AALOAD)
- (.visitInsn Opcodes/ARETURN)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $do-a-round)
- (.visitVarInsn Opcodes/LLOAD 0)
- (.visitVarInsn Opcodes/ILOAD 2)
- bit-set-64?
- (.visitJumpInsn Opcodes/IFEQ $next-iteration)
- (.visitLdcInsn (int (dec deg-bits)))
- (.visitVarInsn Opcodes/ILOAD 2)
- (.visitInsn Opcodes/ISUB)
- (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "deg_digit_power" "(I)[B")
- (.visitVarInsn Opcodes/ALOAD 3)
- (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "add_deg_digit_powers" "([B[B)[B")
- (.visitVarInsn Opcodes/ASTORE 3)
- (.visitJumpInsn Opcodes/GOTO $next-iteration)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $next-iteration)
- ;; Decrement index
- (.visitVarInsn Opcodes/ILOAD 2)
- (.visitLdcInsn (int 1))
- (.visitInsn Opcodes/ISUB)
- (.visitVarInsn Opcodes/ISTORE 2)
- ;; Iterate
- (.visitJumpInsn Opcodes/GOTO $loop-start)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitMaxs 0 0)
- (.visitEnd)))
- _ (let [$loop-start (new Label)
- $do-a-round (new Label)
- $not-set (new Label)
- $next-iteration (new Label)]
- (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "deg_text_to_digits" "(Ljava/lang/String;)[B" nil nil)
- (.visitCode)
- (.visitVarInsn Opcodes/ALOAD 0)
- (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/lang/String" "length" "()I")
- (.visitLdcInsn (int 1))
- (.visitInsn Opcodes/ISUB)
- (.visitVarInsn Opcodes/ISTORE 1) ;; Index
- (.visitLdcInsn (int deg-bits))
- (.visitIntInsn Opcodes/NEWARRAY Opcodes/T_BYTE)
- (.visitVarInsn Opcodes/ASTORE 2) ;; digits
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $loop-start)
- (.visitVarInsn Opcodes/ILOAD 1)
- (.visitJumpInsn Opcodes/IFGE $do-a-round)
- (.visitVarInsn Opcodes/ALOAD 2)
- (.visitInsn Opcodes/ARETURN)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $do-a-round)
- (.visitVarInsn Opcodes/ALOAD 0)
- (.visitVarInsn Opcodes/ILOAD 1)
- (.visitVarInsn Opcodes/ILOAD 1)
- (.visitLdcInsn (int 1))
- (.visitInsn Opcodes/IADD)
- (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/lang/String" "substring" "(II)Ljava/lang/String;")
- (.visitMethodInsn Opcodes/INVOKESTATIC "java/lang/Byte" "parseByte" "(Ljava/lang/String;)B")
- ;; Set digit
- (.visitVarInsn Opcodes/ALOAD 2)
- (.visitVarInsn Opcodes/ILOAD 1)
- swap2x1
- (.visitInsn Opcodes/BASTORE)
- ;; Decrement index
- (.visitVarInsn Opcodes/ILOAD 1)
- (.visitLdcInsn (int 1))
- (.visitInsn Opcodes/ISUB)
- (.visitVarInsn Opcodes/ISTORE 1)
- ;; Iterate
- (.visitJumpInsn Opcodes/GOTO $loop-start)
- (.visitMaxs 0 0)
- (.visitEnd)))
- _ (let [$loop-start (new Label)
- $do-a-round (new Label)
- $is-less-than (new Label)
- $is-equal (new Label)]
- ;; [B0 <= [B1
- (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "deg_digits_lt" "([B[B)Z" nil nil)
- (.visitCode)
- (.visitLdcInsn (int 0))
- (.visitVarInsn Opcodes/ISTORE 2) ;; Index
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $loop-start)
- (.visitVarInsn Opcodes/ILOAD 2)
- (.visitLdcInsn (int deg-bits))
- (.visitJumpInsn Opcodes/IF_ICMPLT $do-a-round)
- (.visitLdcInsn false)
- (.visitInsn Opcodes/IRETURN)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $do-a-round)
- (.visitVarInsn Opcodes/ALOAD 0)
- (.visitVarInsn Opcodes/ILOAD 2)
- (.visitInsn Opcodes/BALOAD) ;; {D0}
- (.visitVarInsn Opcodes/ALOAD 1)
- (.visitVarInsn Opcodes/ILOAD 2)
- (.visitInsn Opcodes/BALOAD) ;; {D0, D1}
- (.visitInsn Opcodes/DUP2)
- (.visitJumpInsn Opcodes/IF_ICMPLT $is-less-than)
- (.visitJumpInsn Opcodes/IF_ICMPEQ $is-equal)
- ;; Is greater than...
- (.visitLdcInsn false)
- (.visitInsn Opcodes/IRETURN)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $is-less-than)
- (.visitInsn Opcodes/POP2)
- (.visitLdcInsn true)
- (.visitInsn Opcodes/IRETURN)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $is-equal)
- ;; Increment index
- (.visitVarInsn Opcodes/ILOAD 2)
- (.visitLdcInsn (int 1))
- (.visitInsn Opcodes/IADD)
- (.visitVarInsn Opcodes/ISTORE 2)
- ;; Iterate
- (.visitJumpInsn Opcodes/GOTO $loop-start)
- (.visitMaxs 0 0)
- (.visitEnd)))
- _ (let [$loop-start (new Label)
- $do-a-round (new Label)
- $simple-sub (new Label)]
- (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "deg_digits_sub_once" "([BBI)[B" nil nil)
- (.visitCode)
- (.visitLabel $loop-start)
- (.visitVarInsn Opcodes/ALOAD 0)
- (.visitVarInsn Opcodes/ILOAD 2) ;; {target-digit}
- (.visitInsn Opcodes/BALOAD)
- (.visitVarInsn Opcodes/ILOAD 1) ;; {target-digit, param-digit}
- (.visitInsn Opcodes/DUP2)
- (.visitJumpInsn Opcodes/IF_ICMPGE $simple-sub)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Since $0 < $1
- (.visitInsn Opcodes/SWAP)
- (.visitInsn Opcodes/ISUB) ;; $1 - $0
- (.visitLdcInsn (byte 10))
- (.visitInsn Opcodes/SWAP)
- (.visitInsn Opcodes/ISUB) ;; 10 - ($1 - $0)
- (.visitVarInsn Opcodes/ALOAD 0)
- (.visitVarInsn Opcodes/ILOAD 2)
- swap2x1
- (.visitInsn Opcodes/BASTORE)
- ;; Prepare to iterate...
- ;; Decrement index
- (.visitVarInsn Opcodes/ILOAD 2)
- (.visitLdcInsn (int 1))
- (.visitInsn Opcodes/ISUB)
- (.visitVarInsn Opcodes/ISTORE 2)
- ;; Subtract 1 from next digit
- (.visitLdcInsn (int 1))
- (.visitVarInsn Opcodes/ISTORE 1)
- ;; Iterate
- (.visitJumpInsn Opcodes/GOTO $loop-start)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $simple-sub)
- (.visitInsn Opcodes/ISUB)
- (.visitVarInsn Opcodes/ALOAD 0)
- (.visitVarInsn Opcodes/ILOAD 2)
- swap2x1
- (.visitInsn Opcodes/BASTORE)
- (.visitVarInsn Opcodes/ALOAD 0)
- (.visitInsn Opcodes/ARETURN)
- (.visitMaxs 0 0)
- (.visitEnd)))
- _ (let [$loop-start (new Label)
- $do-a-round (new Label)]
- (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "deg_digits_sub" "([B[B)[B" nil nil)
- (.visitCode)
- (.visitLdcInsn (int (dec deg-bits)))
- (.visitVarInsn Opcodes/ISTORE 2) ;; Index
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $loop-start)
- (.visitVarInsn Opcodes/ILOAD 2)
- (.visitJumpInsn Opcodes/IFGE $do-a-round)
- (.visitVarInsn Opcodes/ALOAD 0)
- (.visitInsn Opcodes/ARETURN)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $do-a-round)
- (.visitVarInsn Opcodes/ALOAD 0) ;; {target-digits}
- (.visitVarInsn Opcodes/ALOAD 1)
- (.visitVarInsn Opcodes/ILOAD 2)
- (.visitInsn Opcodes/BALOAD) ;; {target-digits, param-digit}
- (.visitVarInsn Opcodes/ILOAD 2) ;; {target-digits, param-digit, idx}
- (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "deg_digits_sub_once" "([BBI)[B")
- (.visitVarInsn Opcodes/ASTORE 0) ;; Update target digits
- ;; Decrement index
- (.visitVarInsn Opcodes/ILOAD 2)
- (.visitLdcInsn (int 1))
- (.visitInsn Opcodes/ISUB)
- (.visitVarInsn Opcodes/ISTORE 2)
- ;; Iterate
- (.visitJumpInsn Opcodes/GOTO $loop-start)
- (.visitMaxs 0 0)
- (.visitEnd)))
- _ (let [$from (new Label)
- $to (new Label)
- $handler (new Label)
- $loop-start (new Label)
- $do-a-round (new Label)
- $skip-power (new Label)
- $iterate (new Label)
- $bad-format (new Label)]
- (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "decode_deg" "(Ljava/lang/String;)Ljava/lang/Object;" nil nil)
- (.visitCode)
- ;; Check prefix
- (.visitVarInsn Opcodes/ALOAD 0)
- (.visitLdcInsn ".")
- (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/lang/String" "startsWith" "(Ljava/lang/String;)Z")
- (.visitJumpInsn Opcodes/IFEQ $bad-format)
- ;; Check if size is valid
- (.visitVarInsn Opcodes/ALOAD 0)
- (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/lang/String" "length" "()I")
- (.visitLdcInsn (int (inc deg-bits))) ;; It's increased, to account for the prefix .
- (.visitJumpInsn Opcodes/IF_ICMPGT $bad-format)
- ;; Initialization
- (.visitTryCatchBlock $from $to $handler "java/lang/Exception")
- (.visitVarInsn Opcodes/ALOAD 0)
- (.visitLdcInsn (int 1))
- (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/lang/String" "substring" "(I)Ljava/lang/String;")
- (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "clean_separators" "(Ljava/lang/String;)Ljava/lang/String;")
- (.visitLabel $from)
- (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "deg_text_to_digits" "(Ljava/lang/String;)[B")
- (.visitLabel $to)
- (.visitVarInsn Opcodes/ASTORE 0) ;; From test to digits...
- (.visitLdcInsn (int 0))
- (.visitVarInsn Opcodes/ISTORE 1) ;; Index
- (.visitLdcInsn (long 0))
- (.visitVarInsn Opcodes/LSTORE 2) ;; Output
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $loop-start)
- (.visitVarInsn Opcodes/ILOAD 1)
- (.visitLdcInsn (int deg-bits))
- (.visitJumpInsn Opcodes/IF_ICMPLT $do-a-round)
- (.visitVarInsn Opcodes/LLOAD 2)
- &&/wrap-long
- (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "make_some" "(Ljava/lang/Object;)[Ljava/lang/Object;")
- (.visitInsn Opcodes/ARETURN)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $do-a-round)
- (.visitVarInsn Opcodes/ALOAD 0)
- (.visitVarInsn Opcodes/ILOAD 1)
- (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "deg_digit_power" "(I)[B")
- (.visitInsn Opcodes/DUP2)
- (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "deg_digits_lt" "([B[B)Z")
- (.visitJumpInsn Opcodes/IFNE $skip-power)
- ;; Subtract power
- (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "deg_digits_sub" "([B[B)[B")
- (.visitVarInsn Opcodes/ASTORE 0)
- ;; Set bit on output
- (.visitVarInsn Opcodes/LLOAD 2)
- (.visitLdcInsn (long 1))
- (.visitVarInsn Opcodes/ILOAD 1)
- (.visitLdcInsn (int (dec deg-bits)))
- (.visitInsn Opcodes/SWAP)
- (.visitInsn Opcodes/ISUB)
- (.visitInsn Opcodes/LSHL)
- (.visitInsn Opcodes/LOR)
- (.visitVarInsn Opcodes/LSTORE 2)
- (.visitJumpInsn Opcodes/GOTO $iterate)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $skip-power)
- (.visitInsn Opcodes/POP2)
- ;; (.visitJumpInsn Opcodes/GOTO $iterate)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $iterate)
- (.visitVarInsn Opcodes/ILOAD 1)
- (.visitLdcInsn (int 1))
- (.visitInsn Opcodes/IADD)
- (.visitVarInsn Opcodes/ISTORE 1)
- ;; Iterate
- (.visitJumpInsn Opcodes/GOTO $loop-start)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $handler)
- (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "make_none" "()Ljava/lang/Object;")
- (.visitInsn Opcodes/ARETURN)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (.visitLabel $bad-format)
- (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "make_none" "()Ljava/lang/Object;")
- (.visitInsn Opcodes/ARETURN)
- (.visitMaxs 0 0)
- (.visitEnd)))]
+ (.visitEnd))]
nil))
(let [+wrapper-class+ (&host-generics/->bytecode-class-name "java.lang.Long")]
diff --git a/stdlib/source/lux.lux b/stdlib/source/lux.lux
index 9de477162..344925b1f 100644
--- a/stdlib/source/lux.lux
+++ b/stdlib/source/lux.lux
@@ -2272,11 +2272,6 @@
(|> value (i./ 10) Int/abs)
(|> value (i.% 10) Int/abs (_lux_:! Nat) digit-to-text)))))
-(def:''' (Deg/encode x)
- #Nil
- (-> Deg Text)
- (_lux_proc ["deg" "encode"] [x]))
-
(def:''' (Real/encode x)
#Nil
(-> Real Text)
@@ -2724,7 +2719,7 @@
(Int/encode value)
[_ (#Deg value)]
- (Deg/encode value)
+ (_lux_proc ["io" "error"] ["Undefined behavior."])
[_ (#Real value)]
(Real/encode value)
@@ -5042,7 +5037,6 @@
([#Bool Bool/encode]
[#Nat Nat/encode]
[#Int Int/encode]
- [#Deg Deg/encode]
[#Real Real/encode]
[#Char Char/encode]
[#Text Text/encode]
@@ -5064,6 +5058,9 @@
([#Form "(" ")" id]
[#Tuple "[" "]" id]
[#Record "{" "}" rejoin-all-pairs])
+
+ [new-cursor (#Deg value)]
+ (_lux_proc ["io" "error"] ["Undefined behavior."])
))
(def: (with-baseline baseline [file line column])
diff --git a/stdlib/source/lux/data/number.lux b/stdlib/source/lux/data/number.lux
index 40905d0d5..ee343e6ee 100644
--- a/stdlib/source/lux/data/number.lux
+++ b/stdlib/source/lux/data/number.lux
@@ -10,6 +10,10 @@
codec)
(data ["E" error])))
+(def: (clean-separators input)
+ (-> Text Text)
+ (_lux_proc ["text" "replace-all"] [input "_" ""]))
+
## [Structures]
(do-template [<type> <test>]
[(struct: #export _ (Eq <type>)
@@ -629,8 +633,8 @@
(_lux_proc ["array" "new"] [deg-bits]))
(def: (digits-get idx digits)
- (-> Nat Digits (Maybe Nat))
- (_lux_proc ["array" "get"] [digits idx]))
+ (-> Nat Digits Nat)
+ (default +0 (_lux_proc ["array" "get"] [digits idx])))
(def: (digits-put idx digit digits)
(-> Nat Nat Digits Digits)
@@ -647,7 +651,6 @@
output output]
(if (i.>= 0 (:! Int idx))
(let [raw (|> (digits-get idx output)
- (default +0)
(n.* +5)
(n.+ carry))]
(recur (n.dec idx)
@@ -671,7 +674,7 @@
all-zeroes? true
output ""]
(if (i.>= 0 (:! Int idx))
- (let [digit (default +0 (digits-get idx digits))]
+ (let [digit (digits-get idx digits)]
(if (and (n.= +0 digit)
all-zeroes?)
(recur (n.dec idx) true output)
@@ -692,13 +695,65 @@
(if (i.>= 0 (:! Int idx))
(let [raw ($_ n.+
carry
- (default +0 (digits-get idx param))
- (default +0 (digits-get idx subject)))]
+ (digits-get idx param)
+ (digits-get idx subject))]
(recur (n.dec idx)
(n./ +10 raw)
(digits-put idx (n.% +10 raw) output)))
output)))
+(def: (text-to-digits input)
+ (-> Text (Maybe Digits))
+ (let [length (_lux_proc ["text" "size"] [input])]
+ (if (n.<= deg-bits length)
+ (loop [idx +0
+ output (make-digits [])]
+ (if (n.< length idx)
+ (let [char (assume (_lux_proc ["text" "char"] [input idx]))]
+ (case (_lux_proc ["text" "index"]
+ ["0123456789"
+ (_lux_proc ["char" "to-text"] [char])
+ +0])
+ #;None
+ #;None
+
+ (#;Some digit)
+ (recur (n.inc idx)
+ (digits-put idx digit output))))
+ (#;Some output)))
+ #;None)))
+
+(def: (digits-lt param subject)
+ (-> Digits Digits Bool)
+ (loop [idx +0]
+ (and (n.< deg-bits idx)
+ (let [pd (digits-get idx param)
+ sd (digits-get idx subject)]
+ (if (n.= pd sd)
+ (recur (n.inc idx))
+ (n.< pd sd))))))
+
+(def: (digits-sub-once! idx param subject)
+ (-> Nat Nat Digits Digits)
+ (let [sd (digits-get idx subject)]
+ (if (n.>= param sd)
+ (digits-put idx (n.- param sd) subject)
+ (let [diff (|> sd
+ (n.+ +10)
+ (n.- param))]
+ (|> subject
+ (digits-put idx diff)
+ (digits-sub-once! (n.dec idx) +1))))))
+
+(def: (digits-sub! param subject)
+ (-> Digits Digits Digits)
+ (loop [idx (n.dec deg-bits)
+ output subject]
+ (if (i.>= 0 (nat-to-int idx))
+ (recur (n.dec idx)
+ (digits-sub-once! idx (digits-get idx param) output))
+ output)))
+
(struct: #export _ (Codec Text Deg)
(def: (encode input)
(let [input (:! Nat input)
@@ -719,35 +774,34 @@
)))))
(def: (decode input)
- (case (_lux_proc ["deg" "decode"] [input])
- (#;Some value)
- (#;Right value)
-
- #;None
- (#;Left (_lux_proc ["text" "append"]
- ["Could not decode Deg: " input])))
- ## (let [length (text-size input)]
- ## (if (and (starts-with? "." input)
- ## (n.<= (n.inc deg-bits) length))
- ## (let [input (|> input
- ## (substring +1 length)
- ## clean-separators)]
- ## (case (deg-text-to-digits input)
- ## (#;Some digits)
- ## (loop [digits digits
- ## idx +0
- ## output +0]
- ## (if (n.< deg-bits idx)
- ## (let [power (digits-power idx)]
- ## (if (deg-digits-lt power digits)
- ## ## Skip power
- ## (recur digits (n.inc idx) output)
- ## (recur (deg-digits-sub power digits)
- ## (n.inc idx)
- ## (bit-set idx output))))
- ## (#E;Success (:! Deg output))))
-
- ## #;None
- ## (#E;Error (_lux_proc ["text" "append"] ["Wrong syntax for Deg: " input]))))
- ## (#E;Error (_lux_proc ["text" "append"] ["Wrong syntax for Deg: " input]))))
+ (let [length (_lux_proc ["text" "size"] [input])
+ dotted? (case (_lux_proc ["text" "index"] [input "." +0])
+ (#;Some +0)
+ true
+
+ _
+ false)]
+ (if (and dotted?
+ (n.<= (n.inc deg-bits) length))
+ (case (|> (_lux_proc ["text" "clip"] [input +1 length])
+ assume
+ clean-separators
+ text-to-digits)
+ (#;Some digits)
+ (loop [digits digits
+ idx +0
+ output +0]
+ (if (n.< deg-bits idx)
+ (let [power (digits-power idx)]
+ (if (digits-lt power digits)
+ ## Skip power
+ (recur digits (n.inc idx) output)
+ (recur (digits-sub! power digits)
+ (n.inc idx)
+ (bit-set (n.- idx (n.dec deg-bits)) output))))
+ (#E;Success (:! Deg output))))
+
+ #;None
+ (#E;Error (_lux_proc ["text" "append"] ["Wrong syntax for Deg: " input])))
+ (#E;Error (_lux_proc ["text" "append"] ["Wrong syntax for Deg: " input]))))
))