From 312cc7dc5f0be0ef0a48ea8470d8ee64b929bc7b Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Thu, 23 Aug 2018 19:02:47 -0400 Subject: "lux text char" is now unsafe/optimized. --- luxc/src/lux/analyser/proc/common.clj | 2 +- luxc/src/lux/compiler/jvm/proc/common.clj | 4 +- luxc/src/lux/compiler/jvm/rt.clj | 27 +-- .../lang/translation/jvm/procedure/common.jvm.lux | 4 +- .../luxc/lang/translation/jvm/runtime.jvm.lux | 14 -- stdlib/source/lux.lux | 25 +-- stdlib/source/lux/compiler/default/syntax.lux | 197 +++++++++------------ stdlib/source/lux/data/number.lux | 154 ++++++++-------- stdlib/source/lux/data/text.lux | 15 +- .../default/phase/analysis/procedure/common.lux | 2 +- 10 files changed, 184 insertions(+), 260 deletions(-) diff --git a/luxc/src/lux/analyser/proc/common.clj b/luxc/src/lux/analyser/proc/common.clj index b52589460..90db8a2cd 100644 --- a/luxc/src/lux/analyser/proc/common.clj +++ b/luxc/src/lux/analyser/proc/common.clj @@ -90,7 +90,7 @@ (|do [:let [(&/$Cons text (&/$Cons idx (&/$Nil))) ?values] =text (&&/analyse-1 analyse &type/Text text) =idx (&&/analyse-1 analyse &type/Nat idx) - _ (&type/check exo-type (&/$Apply &type/Nat &type/Maybe)) + _ (&type/check exo-type &type/Nat) _cursor &/cursor] (return (&/|list (&&/|meta exo-type _cursor (&&/$proc (&/T ["text" "char"]) diff --git a/luxc/src/lux/compiler/jvm/proc/common.clj b/luxc/src/lux/compiler/jvm/proc/common.clj index 90f7b6bcf..b5d0ea475 100644 --- a/luxc/src/lux/compiler/jvm/proc/common.clj +++ b/luxc/src/lux/compiler/jvm/proc/common.clj @@ -322,7 +322,9 @@ :let [_ (doto *writer* &&/unwrap-long (.visitInsn Opcodes/L2I) - (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "text_char" "(Ljava/lang/String;I)[Ljava/lang/Object;"))]] + (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/lang/String" "charAt" "(I)C") + (.visitInsn Opcodes/I2L) + &&/wrap-long)]] (return nil))) (defn ^:private compile-io-log [compile ?values special-args] diff --git a/luxc/src/lux/compiler/jvm/rt.clj b/luxc/src/lux/compiler/jvm/rt.clj index 97b767863..948f08805 100644 --- a/luxc/src/lux/compiler/jvm/rt.clj +++ b/luxc/src/lux/compiler/jvm/rt.clj @@ -339,30 +339,6 @@ (.visitEnd))] nil)) -(defn ^:private compile-LuxRT-text-methods [^ClassWriter =class] - (let [$from (new Label) - $to (new Label) - $handler (new Label)] - (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "text_char" "(Ljava/lang/String;I)[Ljava/lang/Object;" nil nil) - (.visitCode) - (.visitTryCatchBlock $from $to $handler "java/lang/IndexOutOfBoundsException") - (.visitLabel $from) - (.visitVarInsn Opcodes/ALOAD 0) - (.visitVarInsn Opcodes/ILOAD 1) - (.visitMethodInsn Opcodes/INVOKEVIRTUAL "java/lang/String" "charAt" "(I)C") - (.visitInsn Opcodes/I2L) - &&/wrap-long - (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "make_some" "(Ljava/lang/Object;)[Ljava/lang/Object;") - (.visitInsn Opcodes/ARETURN) - (.visitLabel $to) - (.visitLabel $handler) - (.visitInsn Opcodes/POP) - (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "make_none" "()[Ljava/lang/Object;") - (.visitInsn Opcodes/ARETURN) - (.visitMaxs 0 0) - (.visitEnd)) - nil)) - (def compile-LuxRT-class (|do [_ (return nil) :let [full-name &&/lux-utils-class @@ -467,7 +443,6 @@ (compile-LuxRT-pm-methods) (compile-LuxRT-adt-methods) (compile-LuxRT-int-methods) - (compile-LuxRT-frac-methods) - (compile-LuxRT-text-methods))]] + (compile-LuxRT-frac-methods))]] (&&/save-class! (second (string/split &&/lux-utils-class #"/")) (.toByteArray (doto =class .visitEnd))))) diff --git a/new-luxc/source/luxc/lang/translation/jvm/procedure/common.jvm.lux b/new-luxc/source/luxc/lang/translation/jvm/procedure/common.jvm.lux index a0a34d9ad..e45a6f8cf 100644 --- a/new-luxc/source/luxc/lang/translation/jvm/procedure/common.jvm.lux +++ b/new-luxc/source/luxc/lang/translation/jvm/procedure/common.jvm.lux @@ -233,8 +233,8 @@ (_.INVOKEVIRTUAL "java.lang.String" "concat" (_t.method (list $String) (#.Some $String) (list)) #0) (<|)] [text::char ..check-stringI jvm-intI - (_.INVOKESTATIC ///.runtime-class "text_char" (_t.method (list $String _t.int) (#.Some ///.$Variant) (list)) #0) - (<|)] + (_.INVOKEVIRTUAL "java.lang.String" "charAt" (_t.method (list _t.int) (#.Some _t.char) (list)) #0) + lux-intI] ) (do-template [ ] diff --git a/new-luxc/source/luxc/lang/translation/jvm/runtime.jvm.lux b/new-luxc/source/luxc/lang/translation/jvm/runtime.jvm.lux index 3c8563d75..05641fe22 100644 --- a/new-luxc/source/luxc/lang/translation/jvm/runtime.jvm.lux +++ b/new-luxc/source/luxc/lang/translation/jvm/runtime.jvm.lux @@ -129,19 +129,6 @@ (_.wrap #$.Double)))) )) -(def: clz-method Method ($t.method (list $t.long) (#.Some $t.int) (list))) - -(def: text-methods - Def - (|>> ($d.method #$.Public $.staticM "text_char" ($t.method (list $String $t.int) (#.Some $Variant) (list)) - (try-methodI - (|>> (_.ALOAD 0) - (_.ILOAD 1) - (_.INVOKEVIRTUAL "java.lang.String" "charAt" ($t.method (list $t.int) (#.Some $t.char) (list)) #0) - _.I2L - (_.wrap #$.Long)))) - )) - (def: pm-methods Def (let [tuple-sizeI (|>> (_.ALOAD 0) _.ARRAYLENGTH) @@ -320,7 +307,6 @@ (let [bytecode ($d.class #$.V1_6 #$.Public $.finalC //.runtime-class (list) ["java.lang.Object" (list)] (list) (|>> adt-methods frac-methods - text-methods pm-methods io-methods))] (do phase.Monad diff --git a/stdlib/source/lux.lux b/stdlib/source/lux.lux index 5abcab3dc..916b77797 100644 --- a/stdlib/source/lux.lux +++ b/stdlib/source/lux.lux @@ -3650,11 +3650,9 @@ (list input) (#Some idx) - (list& (default (error! "UNDEFINED") - (clip/2 0 idx input)) + (list& ("lux text clip" input 0 idx) (text/split splitter - (default (error! "UNDEFINED") - (clip/1 (n/+ 1 idx) input)))))) + ("lux text clip" input (n/+ 1 idx) ("lux text size" input)))))) (def: (nth idx xs) (All [a] @@ -4144,23 +4142,17 @@ _ (return [#.Nil parts]))) -(def: (split at x) - (-> Nat Text (Maybe [Text Text])) - (case [(..clip/2 0 at x) (..clip/1 at x)] - [(#.Some pre) (#.Some post)] - (#.Some [pre post]) - - _ - #.None)) +(def: (split! at x) + (-> Nat Text [Text Text]) + [("lux text clip" x 0 at) + ("lux text clip" x at ("lux text size" x))]) (def: (split-with token sample) (-> Text Text (Maybe [Text Text])) (do ..Monad [index (..index-of token sample) - pre+post' (split index sample) - #let [[pre post'] pre+post'] - _+post (split ("lux text size" token) post') - #let [[_ post] _+post]] + #let [[pre post'] (split! index sample) + [_ post] (split! ("lux text size" token) post')]] (wrap [pre post]))) (def: (replace-all pattern value template) @@ -5961,7 +5953,6 @@ (^multi (^ (list [_ (#Text input)])) (n/= 1 ("lux text size" input))) (|> ("lux text char" input 0) - (default (undefined)) nat$ list [compiler] #Right) diff --git a/stdlib/source/lux/compiler/default/syntax.lux b/stdlib/source/lux/compiler/default/syntax.lux index 69d214371..af7c7ae90 100644 --- a/stdlib/source/lux/compiler/default/syntax.lux +++ b/stdlib/source/lux/compiler/default/syntax.lux @@ -146,6 +146,29 @@ [!dec "lux i64 -" 1] ) +(template: (!clip from to text) + ("lux text clip" text from to)) + +(template: (!i/< reference subject) + ("lux int <" subject reference)) + +(do-template [ ] + [(template: ( param subject) + ( subject param))] + + [!n/+ "lux i64 +"] + [!n/- "lux i64 -"] + ) + +(template: (!with-char @source-code @offset @char @else @body) + (if (!i/< (:coerce Int ("lux text size" @source-code)) + ## TODO: Get rid of the above "lux text size" call. + ## The size should be calculated only once and re-used constantly. + (:coerce Int @offset)) + (let [@char ("lux text char" @source-code @offset)] + @body) + @else)) + (do-template [ ] [(def: ( parse source) (-> Parser Parser) @@ -157,20 +180,16 @@ (#error.Error error) (let [[where offset source-code] source] - (case ("lux text char" source-code offset) - (#.Some char) - (`` (case char - (^ (char (~~ (static )))) - (#error.Success [[(update@ #.column inc where) - (!inc offset) - source-code] - [where ( (list.reverse stack))]]) - - _ - (ex.throw unrecognized-input where))) - - _ - (#error.Error error))))))] + (<| (!with-char source-code offset char (#error.Error error)) + (`` (case char + (^ (char (~~ (static )))) + (#error.Success [[(update@ #.column inc where) + (!inc offset) + source-code] + [where ( (list.reverse stack))]]) + + _ + (ex.throw unrecognized-input where))))))))] ## Form and tuple syntax is mostly the same, differing only in the ## delimiters involved. @@ -191,38 +210,20 @@ (#error.Error error) (let [[where offset source-code] source] - (case ("lux text char" source-code offset) - (#.Some char) - (`` (case char - (^ (char (~~ (static ..close-record)))) - (#error.Success [[(update@ #.column inc where) - (!inc offset) - source-code] - [where (#.Record (list.reverse stack))]]) + (<| (!with-char source-code offset char (#error.Error error)) + (`` (case char + (^ (char (~~ (static ..close-record)))) + (#error.Success [[(update@ #.column inc where) + (!inc offset) + source-code] + [where (#.Record (list.reverse stack))]]) - _ - (ex.throw unrecognized-input where))) - - _ - (#error.Error error)))) + _ + (ex.throw unrecognized-input where)))))) (#error.Error error) (#error.Error error)))) -(template: (!clip from to text) - ("lux text clip" text from to)) - -(template: (!i/< reference subject) - ("lux int <" subject reference)) - -(do-template [ ] - [(template: ( param subject) - ( subject param))] - - [!n/+ "lux i64 +"] - [!n/- "lux i64 -"] - ) - (template: (!guarantee-no-new-lines content body) (case ("lux text index" content (static text.new-line) 0) (#.Some g!_) @@ -294,45 +295,23 @@ (#error.Error error) (#error.Error error))) -(def: (parse-nat start [where offset source-code]) - (-> Offset Parser) - (loop [end offset] - (case ("lux text char" source-code end) - (#.Some char) - (if (!digit?+ char) - (recur (!inc end)) - (!discrete-output number.Codec #.Nat)) - - _ - (!discrete-output number.Codec #.Nat)))) - -(def: (parse-int start [where offset source-code]) - (-> Offset Parser) - (loop [end offset] - (case ("lux text char" source-code end) - (#.Some char) - (if (!digit?+ char) - (recur (!inc end)) - (!discrete-output number.Codec #.Int)) - - _ - (!discrete-output number.Codec #.Int)))) - -(def: (parse-rev start [where offset source-code]) - (-> Offset Parser) - (loop [end offset] - (case ("lux text char" source-code end) - (#.Some char) - (if (!digit?+ char) - (recur (!inc end)) - (!discrete-output number.Codec #.Rev)) - - _ - (!discrete-output number.Codec #.Rev)))) +(do-template [ ] + [(def: ( start [where offset source-code]) + (-> Offset Parser) + (loop [end offset] + (<| (!with-char source-code end char (!discrete-output )) + (if (!digit?+ char) + (recur (!inc end)) + (!discrete-output )))))] + + [parse-nat number.Codec #.Nat] + [parse-int number.Codec #.Int] + [parse-rev number.Codec #.Rev] + ) -(template: (!parse-int offset where source-code) +(template: (!parse-int offset where source-code @end) (let [g!offset/1 (!inc offset)] - (<| (!with-char source-code g!offset/1 g!char/1) + (<| (!with-char source-code g!offset/1 g!char/1 @end) (if (!digit? g!char/1) (parse-int offset [where (!inc/2 offset) source-code]) (!parse-full-name offset [where (!inc offset) source-code] where #.Identifier))))) @@ -344,16 +323,12 @@ (def: (parse-name-part start [where offset source-code]) (-> Offset Source (Error [Source Text])) (loop [end offset] - (case ("lux text char" source-code end) - (#.Some char) - (cond (!name-char? char) - (recur (!inc end)) + (<| (!with-char source-code end char ) + (cond (!name-char? char) + (recur (!inc end)) - ## else - ) - - _ - )))) + ## else + ))))) (template: (!new-line where) (let [[where::file where::line where::column] where] @@ -364,14 +339,6 @@ (as-is [where (!inc offset/0) source-code]) (as-is [where (!inc/2 offset/0) source-code])] - (template: (!with-char @source-code @offset @char @body) - (case ("lux text char" @source-code @offset) - (#.Some @char) - @body - - _ - )) - (template: (!parse-half-name @offset//pre @offset//post @char @module) (let [@offset//post (!inc @offset//pre)] (cond (!name-char?|head @char) @@ -387,11 +354,11 @@ (`` (def: (parse-short-name current-module [where offset/0 source-code]) (-> Text Source (Error [Source Name])) - (<| (!with-char source-code offset/0 char/0) + (<| (!with-char source-code offset/0 char/0 ) (case char/0 (^ (char (~~ (static ..name-separator)))) (let [offset/1 (!inc offset/0)] - (<| (!with-char source-code offset/1 char/1) + (<| (!with-char source-code offset/1 char/1 ) (!parse-half-name offset/1 offset/2 char/1 current-module))) _ @@ -411,23 +378,19 @@ (case (..parse-name-part start source) (#error.Success [source' simple]) (let [[where' offset' source-code'] source'] - (case ("lux text char" source-code' offset') - (#.Some char/separator) - (case char/separator - (^ (char (~~ (static ..name-separator)))) - (let [offset'' (!inc offset')] - (case (..parse-name-part offset'' [where' offset'' source-code']) - (#error.Success [source'' complex]) - (#error.Success [source'' [simple complex]]) - - (#error.Error error) - (#error.Error error))) + (<| (!with-char source-code' offset' char/separator ) + (case char/separator + (^ (char (~~ (static ..name-separator)))) + (let [offset'' (!inc offset')] + (case (..parse-name-part offset'' [where' offset'' source-code']) + (#error.Success [source'' complex]) + (#error.Success [source'' [simple complex]]) + + (#error.Error error) + (#error.Error error))) - _ - ) - - _ - )) + _ + ))) (#error.Error error) (#error.Error error))))) @@ -444,7 +407,7 @@ (-> Text Aliases Source (Error [Source Code])) (let [parse' (parse current-module aliases)] (loop [[where offset/0 source-code] source] - (<| (!with-char source-code offset/0 char/0) + (<| (!with-char source-code offset/0 char/0 ) (`` (case char/0 ## White-space (^template [ ] @@ -477,7 +440,7 @@ ## Special code (^ (char (~~ (static ..sigil)))) (let [offset/1 (!inc offset/0)] - (<| (!with-char source-code offset/1 char/1) + (<| (!with-char source-code offset/1 char/1 ) (case char/1 (^template [ ] (^ (char )) @@ -509,14 +472,14 @@ (^ (char (~~ (static ..name-separator)))) (let [offset/1 (!inc offset/0)] - (<| (!with-char source-code offset/1 char/1) + (<| (!with-char source-code offset/1 char/1 ) (if (!digit? char/1) (parse-rev offset/0 [where (!inc offset/1) source-code]) (!parse-short-name current-module where #.Identifier)))) (^template [] (^ (char )) - (!parse-int offset/0 where source-code)) + (!parse-int offset/0 where source-code )) ([(~~ (static ..positive-sign))] [(~~ (static ..negative-sign))]) diff --git a/stdlib/source/lux/data/number.lux b/stdlib/source/lux/data/number.lux index f2845f48c..efd965d1b 100644 --- a/stdlib/source/lux/data/number.lux +++ b/stdlib/source/lux/data/number.lux @@ -178,9 +178,11 @@ ) ## [Values & Syntax] +(type: Char Nat) + (def: (get-char! full idx) - (-> Text Nat Text) - ("lux text clip" full idx ("lux i64 +" 1 idx))) + (-> Text Nat Char) + ("lux text char" full idx)) (def: (binary-character value) (-> Nat (Maybe Text)) @@ -190,10 +192,10 @@ _ #.None)) (def: (binary-value digit) - (-> Text (Maybe Nat)) + (-> Char (Maybe Nat)) (case digit - "0" (#.Some 0) - "1" (#.Some 1) + (^ (char "0")) (#.Some 0) + (^ (char "1")) (#.Some 1) _ #.None)) (def: (octal-character value) @@ -210,16 +212,16 @@ _ #.None)) (def: (octal-value digit) - (-> Text (Maybe Nat)) + (-> Char (Maybe Nat)) (case digit - "0" (#.Some 0) - "1" (#.Some 1) - "2" (#.Some 2) - "3" (#.Some 3) - "4" (#.Some 4) - "5" (#.Some 5) - "6" (#.Some 6) - "7" (#.Some 7) + (^ (char "0")) (#.Some 0) + (^ (char "1")) (#.Some 1) + (^ (char "2")) (#.Some 2) + (^ (char "3")) (#.Some 3) + (^ (char "4")) (#.Some 4) + (^ (char "5")) (#.Some 5) + (^ (char "6")) (#.Some 6) + (^ (char "7")) (#.Some 7) _ #.None)) (def: (decimal-character value) @@ -238,18 +240,18 @@ _ #.None)) (def: (decimal-value digit) - (-> Text (Maybe Nat)) + (-> Char (Maybe Nat)) (case digit - "0" (#.Some 0) - "1" (#.Some 1) - "2" (#.Some 2) - "3" (#.Some 3) - "4" (#.Some 4) - "5" (#.Some 5) - "6" (#.Some 6) - "7" (#.Some 7) - "8" (#.Some 8) - "9" (#.Some 9) + (^ (char "0")) (#.Some 0) + (^ (char "1")) (#.Some 1) + (^ (char "2")) (#.Some 2) + (^ (char "3")) (#.Some 3) + (^ (char "4")) (#.Some 4) + (^ (char "5")) (#.Some 5) + (^ (char "6")) (#.Some 6) + (^ (char "7")) (#.Some 7) + (^ (char "8")) (#.Some 8) + (^ (char "9")) (#.Some 9) _ #.None)) (def: (hexadecimal-character value) @@ -274,24 +276,24 @@ _ #.None)) (def: (hexadecimal-value digit) - (-> Text (Maybe Nat)) + (-> Char (Maybe Nat)) (case digit - "0" (#.Some 0) - "1" (#.Some 1) - "2" (#.Some 2) - "3" (#.Some 3) - "4" (#.Some 4) - "5" (#.Some 5) - "6" (#.Some 6) - "7" (#.Some 7) - "8" (#.Some 8) - "9" (#.Some 9) - (^or "a" "A") (#.Some 10) - (^or "b" "B") (#.Some 11) - (^or "c" "C") (#.Some 12) - (^or "d" "D") (#.Some 13) - (^or "e" "E") (#.Some 14) - (^or "f" "F") (#.Some 15) + (^ (char "0")) (#.Some 0) + (^ (char "1")) (#.Some 1) + (^ (char "2")) (#.Some 2) + (^ (char "3")) (#.Some 3) + (^ (char "4")) (#.Some 4) + (^ (char "5")) (#.Some 5) + (^ (char "6")) (#.Some 6) + (^ (char "7")) (#.Some 7) + (^ (char "8")) (#.Some 8) + (^ (char "9")) (#.Some 9) + (^or (^ (char "a")) (^ (char "A"))) (#.Some 10) + (^or (^ (char "b")) (^ (char "B"))) (#.Some 11) + (^or (^ (char "c")) (^ (char "C"))) (#.Some 12) + (^or (^ (char "d")) (^ (char "D"))) (#.Some 13) + (^or (^ (char "e")) (^ (char "E"))) (#.Some 14) + (^or (^ (char "f")) (^ (char "F"))) (#.Some 15) _ #.None)) (do-template [ ] @@ -337,17 +339,17 @@ (def: (int/sign?? representation) (-> Text (Maybe Int)) (case (get-char! representation 0) - "-" + (^ (char "-")) (#.Some -1) - "+" + (^ (char "+")) (#.Some +1) _ #.None)) (def: (int-decode-loop input-size repr sign ) - (-> Nat Text Int Int (-> Text (Maybe Nat)) Text (Error Int)) + (-> Nat Text Int Int (-> Char (Maybe Nat)) Text (Error Int)) (loop [idx 1 output +0] (if (n/< input-size idx) @@ -397,32 +399,36 @@ ("lux text clip" input 1 ("lux text size" input))) (do-template [ ] - [(structure: #export (Codec Text Rev) - (def: (encode value) - (let [raw-output (de-prefix (:: encode (:coerce Nat value))) - max-num-chars (n// 64) - raw-size ("lux text size" raw-output) - zero-padding (loop [zeroes-left (n/- raw-size max-num-chars) - output ""] - (if (n/= 0 zeroes-left) - output - (recur (dec zeroes-left) - ("lux text concat" "0" output)))) - padded-output ("lux text concat" zero-padding raw-output)] - ("lux text concat" "." padded-output))) - - (def: (decode repr) - (let [repr-size ("lux text size" repr)] - (if (n/>= 2 repr-size) - (case ("lux text char" repr 0) - (^multi (^ (#.Some (char "."))) - [(:: decode (de-prefix repr)) - (#error.Success output)]) - (#error.Success (:coerce Rev output)) - - _ - (#error.Error ("lux text concat" repr))) - (#error.Error ("lux text concat" repr))))))] + [(with-expansions [ (as-is (#error.Error ("lux text concat" repr)))] + (structure: #export (Codec Text Rev) + (def: (encode value) + (let [raw-output (de-prefix (:: encode (:coerce Nat value))) + max-num-chars (n// 64) + raw-size ("lux text size" raw-output) + zero-padding (loop [zeroes-left (n/- raw-size max-num-chars) + output ""] + (if (n/= 0 zeroes-left) + output + (recur (dec zeroes-left) + ("lux text concat" "0" output)))) + padded-output ("lux text concat" zero-padding raw-output)] + ("lux text concat" "." padded-output))) + + (def: (decode repr) + (let [repr-size ("lux text size" repr)] + (if (n/>= 2 repr-size) + (case ("lux text char" repr 0) + (^ (char ".")) + (case (:: decode (de-prefix repr)) + (#error.Success output) + (#error.Success (:coerce Rev output)) + + _ + ) + + _ + ) + )))))] [Binary@Codec Binary@Codec 1 "Invalid binary syntax: "] [Octal@Codec Octal@Codec 3 "Invalid octal syntax: "] @@ -442,9 +448,9 @@ (if (f/= +0.0 dec-left) ("lux text concat" "." output) (let [shifted (f/* dec-left) - digit (|> shifted (f/% ) frac-to-int .nat (get-char! ))] + digit-idx (|> shifted (f/% ) frac-to-int .nat)] (recur (f/% +1.0 shifted) - ("lux text concat" output digit))))))] + ("lux text concat" output ("lux text clip" digit-idx (inc digit-idx))))))))] ("lux text concat" whole-part decimal-part))) (def: (decode repr) @@ -826,7 +832,7 @@ (loop [idx 0 output (make-digits [])] (if (n/< length idx) - (case ("lux text index" "+0123456789" (get-char! input idx) 0) + (case ("lux text index" "+0123456789" ("lux text clip" input idx (inc idx)) 0) #.None #.None diff --git a/stdlib/source/lux/data/text.lux b/stdlib/source/lux/data/text.lux index c33ab03a3..18ad49032 100644 --- a/stdlib/source/lux/data/text.lux +++ b/stdlib/source/lux/data/text.lux @@ -38,7 +38,9 @@ (def: #export (nth idx input) (-> Nat Text (Maybe Nat)) - ("lux text char" input idx)) + (if (n/< ("lux text size" input) idx) + (#.Some ("lux text char" input idx)) + #.None)) (def: #export (index-of' pattern from input) (-> Text Nat Text (Maybe Nat)) @@ -204,12 +206,11 @@ (loop [idx 0 hash 0] (if (n/< length idx) - (let [char (|> idx ("lux text char" input) (maybe.default 0))] - (recur (inc idx) - (|> hash - (i64.left-shift 5) - (n/- hash) - (n/+ char)))) + (recur (inc idx) + (|> hash + (i64.left-shift 5) + (n/- hash) + (n/+ ("lux text char" input idx)))) hash))))))) (def: #export concat diff --git a/stdlib/test/test/lux/compiler/default/phase/analysis/procedure/common.lux b/stdlib/test/test/lux/compiler/default/phase/analysis/procedure/common.lux index cfc164df9..108b350d0 100644 --- a/stdlib/test/test/lux/compiler/default/phase/analysis/procedure/common.lux +++ b/stdlib/test/test/lux/compiler/default/phase/analysis/procedure/common.lux @@ -165,7 +165,7 @@ (test "Can query the size/length of a text." (check-success+ "lux text size" (list subjectC) Nat)) (test "Can obtain the character code of a text at a given index." - (check-success+ "lux text char" (list subjectC fromC) (type (Maybe Nat)))) + (check-success+ "lux text char" (list subjectC fromC) Nat)) (test "Can clip a piece of text between 2 indices." (check-success+ "lux text clip" (list subjectC fromC toC) Text)) )))) -- cgit v1.2.3