1///|
2/// copy_json copies bytes from a source reader until a valid JSON value is completed.
3/// It returns the Json value, the number of bytes copied, and any error that occurred during the process.
4pub fn (src : &ByteReader) -> (Json, Int64, IOError?)
copy_json copies bytes from a source reader until a valid JSON value is completed.
It returns the Json value, the number of bytes copied, and any error that occurred during the process.
copy_json(&ByteReader
src : &trait ByteReader {
read_byte(Self) -> (Byte, IOError?)
}
ByteReader is the interface that wraps the read_byte method.
read_byte reads and returns the next byte from the input or
any error encountered. If read_byte returns an error, no input
byte was consumed, and the returned byte value is undefined.
read_byte provides an efficient interface for byte-at-time
processing. A [Reader] that does not implement ByteReader
can be wrapped using bufio.NewReader to add this method.
ByteReader) -> (enum Json {
Null
True
False
Number(Double)
String(String)
Array(Array[Json])
Object(Map[String, Json])
}
Json, Int64
Int64, type! IOError String
An IOError can be tested with equality checks.
IOError?) {
5 let ParseContext
ctx = struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(r : &ByteReader) -> ParseContext
make(&ByteReader
src)
6 let Json
val = try ParseContext
ctx.(ctx : ParseContext) -> Json!ParseError
parse_value!() catch {
7 (String) -> ParseError
ParseError(String
e) => return (enum Json {
Null
True
False
Number(Double)
String(String)
Array(Array[Json])
Object(Map[String, Json])
}
Json::() -> Json
Creates a JSON null value.
Returns a JSON value representing null.
Example:
test "null" {
inspect(Json::null(), content="Null")
}
null(), 0, (IOError) -> IOError?
Some((String) -> IOError
An IOError can be tested with equality checks.
IOError(String
e.(self : String) -> String
Returns the string itself without any modifications. This method is primarily
used to implement the Show trait, which requires a to_string function.
Parameters:
string : The string value to be returned.
Returns the same string that was passed in.
Example:
test "String::to_string" {
let s = "hello"
inspect(s.to_string(), content="hello")
}
to_string())))
8 }
9 (Json
val, ParseContext
ctx.Int
offset.(self : Int) -> Int64
Converts a 32-bit signed integer to a 64-bit signed integer. All 32-bit
integers can be represented exactly in 64-bit integer format, so the
conversion is lossless.
Parameters:
self : The 32-bit signed integer to be converted.
Returns a 64-bit signed integer that represents the same numerical value as
the input.
Example:
test "Int::to_int64" {
let n = 42
inspect(n.to_int64(), content="42")
let neg = -42
inspect(neg.to_int64(), content="-42")
}
to_int64(), IOError?
None)
10}
11
12// The following code is based upon: https://github.com/moonbitlang/core/blob/main/json/parse.mbt
13// which has the following license:
14// Copyright 2025 International Digital Economy Academy
15//
16// Licensed under the Apache License, Version 2.0 (the "License");
17// you may not use this file except in compliance with the License.
18// You may obtain a copy of the License at
19//
20// http://www.apache.org/licenses/LICENSE-2.0
21//
22// Unless required by applicable law or agreed to in writing, software
23// distributed under the License is distributed on an "AS IS" BASIS,
24// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25// See the License for the specific language governing permissions and
26// limitations under the License.
27
28///|
29priv type! ParseError String
String derive((ParseError, &Logger) -> Unit
Trait for types that can be converted to String
Show, (ParseError, ParseError) -> Bool
Trait for types whose elements can test for equality
Eq)
30
31///|
32fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext) -> Json!ParseError
parse_value(ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext) -> enum Json {
Null
True
False
Number(Double)
String(String)
Array(Array[Json])
Object(Map[String, Json])
}
Json!type! ParseError String
ParseError {
33 let Token
tok = ParseContext
ctx.(ctx : ParseContext, allow_rbracket~ : Bool) -> Token!ParseError
lex_value!(Bool
allow_rbracket=false)
34 ParseContext
ctx.(ctx : ParseContext, tok : Token) -> Json!ParseError
parse_value2!(Token
tok)
35}
36
37///|
38fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext, tok : Token) -> Json!ParseError
parse_value2(
39 ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext,
40 Token
tok : enum Token {
Null
True
False
Number(Double)
String(String)
LBrace
RBrace
LBracket
RBracket
Comma
}
Token
41) -> enum Json {
Null
True
False
Number(Double)
String(String)
Array(Array[Json])
Object(Map[String, Json])
}
Json!type! ParseError String
ParseError {
42 match Token
tok {
43 Token
Null => enum Json {
Null
True
False
Number(Double)
String(String)
Array(Array[Json])
Object(Map[String, Json])
}
Json::() -> Json
Creates a JSON null value.
Returns a JSON value representing null.
Example:
test "null" {
inspect(Json::null(), content="Null")
}
null()
44 Token
True => true.(self : Bool) -> Json
to_json()
45 Token
False => false.(self : Bool) -> Json
to_json()
46 (Double) -> Token
Number(Double
n) => Double
n.(self : Double) -> Json
to_json()
47 (String) -> Token
String(String
s) => String
s.(self : String) -> Json
to_json()
48 Token
LBrace => ParseContext
ctx.(ctx : ParseContext) -> Json!ParseError
parse_object!()
49 Token
LBracket => ParseContext
ctx.(ctx : ParseContext) -> Json!ParseError
parse_array!()
50 Token
RBracket | Token
RBrace | Token
Comma =>
51 raise (String) -> ParseError
ParseError(
52 "invalid JSON: unexpected '\{Token
tok}' at offset \{ParseContext
ctx.Int
offset}",
53 )
54 }
55}
56
57///|
58fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext) -> Json!ParseError
parse_object(ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext) -> enum Json {
Null
True
False
Number(Double)
String(String)
Array(Array[Json])
Object(Map[String, Json])
}
Json!type! ParseError String
ParseError {
59 let Map[String, Json]
map = type Map[K, V]
Mutable linked hash map that maintains the order of insertion, not thread safe.
Example
let map = { 3: "three", 8 : "eight", 1 : "one"}
assert_eq(map.get(2), None)
assert_eq(map.get(3), Some("three"))
map.set(3, "updated")
assert_eq(map.get(3), Some("updated"))
Map::(capacity~ : Int = ..) -> Map[String, Json]
Create a hash map.
The capacity of the map will be the smallest power of 2 that is
greater than or equal to the provided [capacity].
new()
60 loop ParseContext
ctx.(ctx : ParseContext) -> Token!ParseError
In the context of {, try to lex token } or a property name,
otherwise raise an error.
lex_property_name!() {
61 Token
RBrace => Map[String, Json]
map.(self : Map[String, Json]) -> Json
to_json()
62 (String) -> Token
String(String
name) => {
63 ParseContext
ctx.(ctx : ParseContext) -> Unit!ParseError
lex_after_property_name!()
64 Map[String, Json]
map(Map[String, Json], String, Json) -> Unit
[name] = ParseContext
ctx.(ctx : ParseContext) -> Json!ParseError
parse_value!()
65 match ParseContext
ctx.(ctx : ParseContext) -> Token!ParseError
lex_after_object_value!() {
66 Token
Comma => continue ParseContext
ctx.(ctx : ParseContext) -> Token!ParseError
In the context of { ..., try to lex a property name,
otherwise raise an error.
since it is in comma context, } is not allowed.
lex_property_name2!()
67 Token
RBrace => Map[String, Json]
map.(self : Map[String, Json]) -> Json
to_json()
68 Token
tok =>
69 raise (String) -> ParseError
ParseError(
70 "invalid JSON: expected ',' or '}' at offset \{ParseContext
ctx.Int
offset}, got '\{Token
tok}'",
71 )
72 }
73 }
74 Token
tok =>
75 raise (String) -> ParseError
ParseError(
76 "invalid JSON: expected '}' or property name at offset \{ParseContext
ctx.Int
offset}, got '\{Token
tok}'",
77 )
78 }
79}
80
81///|
82fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext) -> Json!ParseError
parse_array(ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext) -> enum Json {
Null
True
False
Number(Double)
String(String)
Array(Array[Json])
Object(Map[String, Json])
}
Json!type! ParseError String
ParseError {
83 let Array[Json]
vec = []
84 loop ParseContext
ctx.(ctx : ParseContext, allow_rbracket~ : Bool) -> Token!ParseError
lex_value!(Bool
allow_rbracket=true) {
85 Token
RBracket => Array[Json]
vec.(self : Array[Json]) -> Json
to_json()
86 Token
tok => {
87 Array[Json]
vec.(self : Array[Json], value : Json) -> Unit
Adds an element to the end of the array.
If the array is at capacity, it will be reallocated.
Example
let v = []
v.push(3)
push(ParseContext
ctx.(ctx : ParseContext, tok : Token) -> Json!ParseError
parse_value2!(Token
tok))
88 let Token
tok2 = ParseContext
ctx.(ctx : ParseContext) -> Token!ParseError
lex_after_array_value!()
89 match Token
tok2 {
90 Token
Comma => continue ParseContext
ctx.(ctx : ParseContext, allow_rbracket~ : Bool) -> Token!ParseError
lex_value!(Bool
allow_rbracket=false)
91 Token
RBracket => Array[Json]
vec.(self : Array[Json]) -> Json
to_json()
92 _ => raise (String) -> ParseError
ParseError("unexpected '\{Token
tok2}' at offset \{ParseContext
ctx.Int
offset}")
93 }
94 }
95 }
96}
97
98///|
99priv struct ParseContext {
100 &ByteReader
r : &trait ByteReader {
read_byte(Self) -> (Byte, IOError?)
}
ByteReader is the interface that wraps the read_byte method.
read_byte reads and returns the next byte from the input or
any error encountered. If read_byte returns an error, no input
byte was consumed, and the returned byte value is undefined.
read_byte provides an efficient interface for byte-at-time
processing. A [Reader] that does not implement ByteReader
can be wrapped using bufio.NewReader to add this method.
ByteReader
101 Buffer
buf : struct Buffer {
mut b: Slice[Byte]
mut off: Int
}
Buffer
102 mut Int
offset : Int
Int
103}
104
105///|
106const Int
DEFAULT_BUFFER_SIZE = 1024
107
108///|
109fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(r : &ByteReader) -> ParseContext
make(&ByteReader
r : &trait ByteReader {
read_byte(Self) -> (Byte, IOError?)
}
ByteReader is the interface that wraps the read_byte method.
read_byte reads and returns the next byte from the input or
any error encountered. If read_byte returns an error, no input
byte was consumed, and the returned byte value is undefined.
read_byte provides an efficient interface for byte-at-time
processing. A [Reader] that does not implement ByteReader
can be wrapped using bufio.NewReader to add this method.
ByteReader) -> struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext {
110 { &ByteReader
r, Buffer
buf: struct Buffer {
mut b: Slice[Byte]
mut off: Int
}
Buffer::(size_hint~ : Int) -> Buffer
Buffer::new creates a new empty Buffer with an optional size hint.
The size hint is used to preallocate memory for the buffer, which can
improve performance when the size of the data to be written is known in advance.
new(Int
size_hint=Int
DEFAULT_BUFFER_SIZE), Int
offset: 0 }
111}
112
113///|
114priv type CharClass type Array[T]
An Array is a collection of values that supports random access and can
grow in size.
Array[(Char
Char, Char
Char)]
115
116///|
117fn type CharClass Array[(Char, Char)]
CharClass::(array : Array[(Char, Char)]) -> CharClass
of(Array[(Char, Char)]
array : type Array[T]
An Array is a collection of values that supports random access and can
grow in size.
Array[(Char
Char, Char
Char)]) -> type CharClass Array[(Char, Char)]
CharClass {
118 (Array[(Char, Char)]) -> CharClass
CharClass(Array[(Char, Char)]
array)
119}
120
121///|
122fn (self : CharClass, c : Char) -> Bool
contains(CharClass
self : type CharClass Array[(Char, Char)]
CharClass, Char
c : Char
Char) -> Bool
Bool {
123 for Int
left = 0, Int
right = CharClass
self.Array[(Char, Char)]
_.(self : Array[(Char, Char)]) -> Int
Returns the number of elements in the array.
Parameters:
array : The array whose length is to be determined.
Returns the number of elements in the array as an integer.
Example:
test "Array::length" {
let arr = [1, 2, 3]
inspect(arr.length(), content="3")
let empty : Array[Int] = []
inspect(empty.length(), content="0")
}
length(); Int
left (self_ : Int, other : Int) -> Bool
< Int
right; {
124 let Int
middle = (Int
left (self : Int, other : Int) -> Int
Adds two 32-bit signed integers. Performs two's complement arithmetic, which
means the operation will wrap around if the result exceeds the range of a
32-bit integer.
Parameters:
self : The first integer operand.
other : The second integer operand.
Returns a new integer that is the sum of the two operands. If the
mathematical sum exceeds the range of a 32-bit integer (-2,147,483,648 to
2,147,483,647), the result wraps around according to two's complement rules.
Example:
test "Int::op_add" {
inspect(42 + 1, content="43")
inspect(2147483647 + 1, content="-2147483648") // Overflow wraps around to minimum value
}
+ Int
right) (self : Int, other : Int) -> Int
Performs integer division between two 32-bit integers. The result is
truncated towards zero (rounds down for positive numbers and up for negative
numbers).
Parameters:
dividend : The first integer operand to be divided.
divisor : The second integer operand that divides the dividend.
Returns the quotient of the division operation.
Throws a panic if divisor is zero.
Example:
test "Int::op_div" {
inspect(10 / 3, content="3") // truncates towards zero
inspect(-10 / 3, content="-3")
inspect(10 / -3, content="-3")
}
test "panic Int::op_div/division_by_zero" {
ignore(42 / 0) // Panics with division by zero
}
/ 2
125 let (Char
min, Char
max) = CharClass
self.Array[(Char, Char)]
Retrieves an element from the array at the specified index.
Parameters:
array : The array to get the element from.
index : The position in the array from which to retrieve the element.
Returns the element at the specified index.
Throws a panic if the index is negative or greater than or equal to the
length of the array.
Example:
test "Array::op_get" {
let arr = [1, 2, 3]
inspect(arr[1], content="2")
}
test "panic Array::op_get/out_of_bounds" {
let arr = [1, 2, 3]
ignore(arr[3]) // Index out of bounds
}
_(Array[(Char, Char)], Int) -> (Char, Char)
Retrieves an element from the array at the specified index.
Parameters:
array : The array to get the element from.
index : The position in the array from which to retrieve the element.
Returns the element at the specified index.
Throws a panic if the index is negative or greater than or equal to the
length of the array.
Example:
test "Array::op_get" {
let arr = [1, 2, 3]
inspect(arr[1], content="2")
}
test "panic Array::op_get/out_of_bounds" {
let arr = [1, 2, 3]
ignore(arr[3]) // Index out of bounds
}
[middle]
126 if Char
c (self_ : Char, other : Char) -> Bool
< Char
min {
127 continue Int
left, Int
middle
128 } else if Char
c (self_ : Char, other : Char) -> Bool
> Char
max {
129 continue Int
middle (self : Int, other : Int) -> Int
Adds two 32-bit signed integers. Performs two's complement arithmetic, which
means the operation will wrap around if the result exceeds the range of a
32-bit integer.
Parameters:
self : The first integer operand.
other : The second integer operand.
Returns a new integer that is the sum of the two operands. If the
mathematical sum exceeds the range of a 32-bit integer (-2,147,483,648 to
2,147,483,647), the result wraps around according to two's complement rules.
Example:
test "Int::op_add" {
inspect(42 + 1, content="43")
inspect(2147483647 + 1, content="-2147483648") // Overflow wraps around to minimum value
}
+ 1, Int
right
130 } else {
131 break true
132 }
133 } else {
134 false
135 }
136}
137
138///|
139priv enum Token {
140 Token
Null
141 Token
True
142 Token
False
143 (Double) -> Token
Number(Double
Double)
144 (String) -> Token
String(String
String)
145 Token
LBrace
146 Token
RBrace
147 Token
LBracket
148 Token
RBracket
149 Token
Comma
150 // Colon
151} derive((Token, Token) -> Bool
Trait for types whose elements can test for equality
Eq, (Token, &Logger) -> Unit
Trait for types that can be converted to String
Show)
152
153///|
154let CharClass
non_ascii_whitespace : type CharClass Array[(Char, Char)]
CharClass = type CharClass Array[(Char, Char)]
CharClass::(array : Array[(Char, Char)]) -> CharClass
of([
155 ('\u00A0', '\u00A0'),
156 ('\u1680', '\u1680'),
157 ('\u2000', '\u200A'),
158 ('\u2028', '\u2029'),
159 ('\u202F', '\u202F'),
160 ('\u205F', '\u205F'),
161 ('\u3000', '\u3000'),
162 ('\uFEFF', '\uFEFF'),
163])
164
165///|
166fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext, allow_rbracket~ : Bool) -> Token!ParseError
lex_value(
167 ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext,
168 Bool
allow_rbracket~ : Bool
Bool
169) -> enum Token {
Null
True
False
Number(Double)
String(String)
LBrace
RBrace
LBracket
RBracket
Comma
}
Token!type! ParseError String
ParseError {
170 for {
171 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
172 (Char) -> Char?
Some('\t' | ' ' | '\n' | '\r') => continue
173 (Char) -> Char?
Some('{') => return Token
LBrace
174 (Char) -> Char?
Some('[') => return Token
LBracket
175 (Char) -> Char?
Some(']') =>
176 if Bool
allow_rbracket {
177 return Token
RBracket
178 } else {
179 ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Unit!ParseError
invalid_char!(']', Int
shift=-1)
180 }
181 (Char) -> Char?
Some('n') => {
182 ParseContext
ctx.(ctx : ParseContext, c : Byte) -> Unit!ParseError
ctx.expect_ascii_char(c) check the current context is c,
expect_ascii_char!(b'u')
183 ParseContext
ctx.(ctx : ParseContext, c : Byte) -> Unit!ParseError
ctx.expect_ascii_char(c) check the current context is c,
expect_ascii_char!(b'l')
184 ParseContext
ctx.(ctx : ParseContext, c : Byte) -> Unit!ParseError
ctx.expect_ascii_char(c) check the current context is c,
expect_ascii_char!(b'l')
185 return Token
Null
186 }
187 (Char) -> Char?
Some('t') => {
188 ParseContext
ctx.(ctx : ParseContext, c : Byte) -> Unit!ParseError
ctx.expect_ascii_char(c) check the current context is c,
expect_ascii_char!(b'r')
189 ParseContext
ctx.(ctx : ParseContext, c : Byte) -> Unit!ParseError
ctx.expect_ascii_char(c) check the current context is c,
expect_ascii_char!(b'u')
190 ParseContext
ctx.(ctx : ParseContext, c : Byte) -> Unit!ParseError
ctx.expect_ascii_char(c) check the current context is c,
expect_ascii_char!(b'e')
191 return Token
True
192 }
193 (Char) -> Char?
Some('f') => {
194 ParseContext
ctx.(ctx : ParseContext, c : Byte) -> Unit!ParseError
ctx.expect_ascii_char(c) check the current context is c,
expect_ascii_char!(b'a')
195 ParseContext
ctx.(ctx : ParseContext, c : Byte) -> Unit!ParseError
ctx.expect_ascii_char(c) check the current context is c,
expect_ascii_char!(b'l')
196 ParseContext
ctx.(ctx : ParseContext, c : Byte) -> Unit!ParseError
ctx.expect_ascii_char(c) check the current context is c,
expect_ascii_char!(b's')
197 ParseContext
ctx.(ctx : ParseContext, c : Byte) -> Unit!ParseError
ctx.expect_ascii_char(c) check the current context is c,
expect_ascii_char!(b'e')
198 return Token
False
199 }
200 (Char) -> Char?
Some('-') =>
201 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
202 (Char) -> Char?
Some('0') => {
203 let Double
n = ParseContext
ctx.(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_zero!(Int
start=ParseContext
ctx.Int
offset (self : Int, other : Int) -> Int
Performs subtraction between two 32-bit integers, following standard two's
complement arithmetic rules. When the result overflows or underflows, it
wraps around within the 32-bit integer range.
Parameters:
self : The minuend (the number being subtracted from).
other : The subtrahend (the number to subtract).
Returns the difference between self and other.
Example:
test "Int::op_sub" {
let a = 42
let b = 10
inspect(a - b, content="32")
let max = 2147483647 // Int maximum value
inspect(max - -1, content="-2147483648") // Overflow case
}
- 2)
204 return (Double) -> Token
Number(Double
n)
205 }
206 (Char) -> Char?
Some(Char
c2) => {
207 if Char
c2 is ('1'..='9') {
208 let Double
n = ParseContext
ctx.(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_integer!(Int
start=ParseContext
ctx.Int
offset (self : Int, other : Int) -> Int
Performs subtraction between two 32-bit integers, following standard two's
complement arithmetic rules. When the result overflows or underflows, it
wraps around within the 32-bit integer range.
Parameters:
self : The minuend (the number being subtracted from).
other : The subtrahend (the number to subtract).
Returns the difference between self and other.
Example:
test "Int::op_sub" {
let a = 42
let b = 10
inspect(a - b, content="32")
let max = 2147483647 // Int maximum value
inspect(max - -1, content="-2147483648") // Overflow case
}
- 2)
209 return (Double) -> Token
Number(Double
n)
210 }
211 ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Unit!ParseError
invalid_char!(Char
c2, Int
shift=-1)
212 }
213 Char?
None => raise (String) -> ParseError
ParseError("invalid eof")
214 }
215 (Char) -> Char?
Some('0') => {
216 let Double
n = ParseContext
ctx.(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_zero!(Int
start=ParseContext
ctx.Int
offset (self : Int, other : Int) -> Int
Performs subtraction between two 32-bit integers, following standard two's
complement arithmetic rules. When the result overflows or underflows, it
wraps around within the 32-bit integer range.
Parameters:
self : The minuend (the number being subtracted from).
other : The subtrahend (the number to subtract).
Returns the difference between self and other.
Example:
test "Int::op_sub" {
let a = 42
let b = 10
inspect(a - b, content="32")
let max = 2147483647 // Int maximum value
inspect(max - -1, content="-2147483648") // Overflow case
}
- 1)
217 return (Double) -> Token
Number(Double
n)
218 }
219 (Char) -> Char?
Some('1'..='9') => {
220 let Double
n = ParseContext
ctx.(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_integer!(Int
start=ParseContext
ctx.Int
offset (self : Int, other : Int) -> Int
Performs subtraction between two 32-bit integers, following standard two's
complement arithmetic rules. When the result overflows or underflows, it
wraps around within the 32-bit integer range.
Parameters:
self : The minuend (the number being subtracted from).
other : The subtrahend (the number to subtract).
Returns the difference between self and other.
Example:
test "Int::op_sub" {
let a = 42
let b = 10
inspect(a - b, content="32")
let max = 2147483647 // Int maximum value
inspect(max - -1, content="-2147483648") // Overflow case
}
- 1)
221 return (Double) -> Token
Number(Double
n)
222 }
223 (Char) -> Char?
Some('"') => {
224 let String
s = ParseContext
ctx.(ctx : ParseContext) -> String!ParseError
lex_string!()
225 return (String) -> Token
String(String
s)
226 }
227 (Char) -> Char?
Some(Char
c) => {
228 if Char
c (self_ : Char, other : Char) -> Bool
> '\u{7f}' (Bool, Bool) -> Bool
&& CharClass
non_ascii_whitespace.(self : CharClass, c : Char) -> Bool
contains(Char
c) {
229 continue
230 }
231 ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Unit!ParseError
invalid_char!(Char
c, Int
shift=-1)
232 }
233 Char?
None => raise (String) -> ParseError
ParseError("invalid eof") // InvalidEof
234 }
235 }
236}
237
238///|
239fn[T] struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext, c : Char, shift~ : Int = ..) -> T!ParseError
invalid_char(
240 ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext,
241 Char
c : Char
Char,
242 Int
shift~ : Int
Int = 0
243) -> type parameter T
T!type! ParseError String
ParseError {
244 ParseContext
ctx.Int
offset (self : Int, other : Int) -> Int
Adds two 32-bit signed integers. Performs two's complement arithmetic, which
means the operation will wrap around if the result exceeds the range of a
32-bit integer.
Parameters:
self : The first integer operand.
other : The second integer operand.
Returns a new integer that is the sum of the two operands. If the
mathematical sum exceeds the range of a 32-bit integer (-2,147,483,648 to
2,147,483,647), the result wraps around according to two's complement rules.
Example:
test "Int::op_add" {
inspect(42 + 1, content="43")
inspect(2147483647 + 1, content="-2147483648") // Overflow wraps around to minimum value
}
+= Int
shift
245 raise (String) -> ParseError
ParseError("invalid JSON: unexpected '\{Char
c}' at offset \{ParseContext
ctx.Int
offset}")
246}
247
248///|
249fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(self : ParseContext) -> Char?
read_new_byte(ParseContext
self : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext) -> Char
Char? {
250 let (Byte
b, IOError?
err) = ParseContext
self.&ByteReader
r.(&ByteReader) -> (Byte, IOError?)
read_byte()
251 guard IOError?
err is IOError?
None else { return Char?
None }
252 ParseContext
self.Int
offset (self : Int, other : Int) -> Int
Adds two 32-bit signed integers. Performs two's complement arithmetic, which
means the operation will wrap around if the result exceeds the range of a
32-bit integer.
Parameters:
self : The first integer operand.
other : The second integer operand.
Returns a new integer that is the sum of the two operands. If the
mathematical sum exceeds the range of a 32-bit integer (-2,147,483,648 to
2,147,483,647), the result wraps around according to two's complement rules.
Example:
test "Int::op_add" {
inspect(42 + 1, content="43")
inspect(2147483647 + 1, content="-2147483648") // Overflow wraps around to minimum value
}
+= 1
253 let (_, IOError?
err) = ParseContext
self.Buffer
buf.(self : Buffer, b : Byte) -> (Int, IOError?)
write_byte(Byte
b)
254 guard IOError?
err is IOError?
None else { return Char?
None }
255 let Char
current = (Int) -> Char
Int::(self : Int) -> Char
unsafe_to_char(Byte
b.(self : Byte) -> Int
Converts a byte value to a 32-bit signed integer. The resulting integer will
have the same binary representation as the byte value, preserving the
numerical value in the range [0, 255].
Parameters:
byte : The byte value to be converted to an integer.
Returns a 32-bit signed integer representing the same numerical value as the
input byte.
Example:
test "Byte::to_int" {
let b = b'\xFF' // byte with value 255
inspect(b.to_int(), content="255")
let zero = b'\x00'
inspect(zero.to_int(), content="0")
}
to_int())
256 (Char) -> Char?
Some(Char
current)
257}
258
259///|
260fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext) -> Char?
read_char(ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext) -> Char
Char? {
261 if ParseContext
ctx.Int
offset (self_ : Int, other : Int) -> Bool
< ParseContext
ctx.Buffer
buf.(self : Buffer) -> Int
length() {
262 let Byte
b = ParseContext
ctx.Buffer
buf(Buffer, Int) -> Byte
[ctx.Int
offset]
263 ParseContext
ctx.Int
offset (self : Int, other : Int) -> Int
Adds two 32-bit signed integers. Performs two's complement arithmetic, which
means the operation will wrap around if the result exceeds the range of a
32-bit integer.
Parameters:
self : The first integer operand.
other : The second integer operand.
Returns a new integer that is the sum of the two operands. If the
mathematical sum exceeds the range of a 32-bit integer (-2,147,483,648 to
2,147,483,647), the result wraps around according to two's complement rules.
Example:
test "Int::op_add" {
inspect(42 + 1, content="43")
inspect(2147483647 + 1, content="-2147483648") // Overflow wraps around to minimum value
}
+= 1
264 return (Char) -> Char?
Some((Int) -> Char
Int::(self : Int) -> Char
unsafe_to_char(Byte
b.(self : Byte) -> Int
Converts a byte value to a 32-bit signed integer. The resulting integer will
have the same binary representation as the byte value, preserving the
numerical value in the range [0, 255].
Parameters:
byte : The byte value to be converted to an integer.
Returns a 32-bit signed integer representing the same numerical value as the
input byte.
Example:
test "Byte::to_int" {
let b = b'\xFF' // byte with value 255
inspect(b.to_int(), content="255")
let zero = b'\x00'
inspect(zero.to_int(), content="0")
}
to_int()))
265 }
266 struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(self : ParseContext) -> Char?
read_new_byte(ParseContext
ctx)
267}
268
269///|
270/// low surrogate
271// const SURROGATE_LOW_CHAR = 0xD800
272
273///|
274/// high surrogate
275// const SURROGATE_HIGH_CHAR = 0xDFFF
276
277///|
278/// `ctx.expect_char(c)` check the current context is c,
279/// if it is, consume the character and return `()`,
280/// otherwise raise an error, when it is an error, the position is unspecified.
281fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext, c : Char) -> Unit!ParseError
ctx.expect_char(c) check the current context is c,
if it is, consume the character and return (),
otherwise raise an error, when it is an error, the position is unspecified.
expect_char(ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext, Char
c : Char
Char) -> Unit
Unit!type! ParseError String
ParseError {
282 // guard ctx.offset < ctx.end_offset else { raise ParseError("invalid eof") }
283 // let c1 = ctx.input.unsafe_charcode_at(ctx.offset)
284 // ctx.offset += 1
285 guard struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext) -> Char?
read_char(ParseContext
ctx) is (Char) -> Char?
Some(Char
c1) else {
286 raise (String) -> ParseError
ParseError("invalid eof")
287 }
288 if Char
c (x : Char, y : Char) -> Bool
!= Char
c1 {
289 raise (String) -> ParseError
ParseError(
290 "invalid JSON: unexpected '\{Char
c1}' at offset \{ParseContext
ctx.Int
offset}, wanted '\{Char
c}'",
291 )
292 }
293 // let c0 = c.to_int()
294 // if c0 < 0xFFFF {
295 // // c0 < SURROGATE_LOW_CHAR || c0 is (0xE000..=0XFFFF)
296 // // c0 is a valid char so only need check if c0<0xFFFF is BMP code point
297 // if c0 != c1 {
298 // ctx.invalid_char!(c0, shift=-1)
299 // }
300 // } else {
301 // // c0 is not bmp code point
302 // // c1 has to be surrogate pair otherwise it is invalid
303 // guard c1 is (SURROGATE_LOW_CHAR..=SURROGATE_HIGH_CHAR) &&
304 // ctx.offset < ctx.end_offset else {
305 // ctx.invalid_char!(c1, shift=-1)
306 // }
307 // let c2 = ctx.input.unsafe_charcode_at(ctx.offset)
308 // let c3 = (c1 << 10) + c2 - 0x35fdc00
309 // if c3 != c0 {
310 // ctx.invalid_char!(c3, shift=-1)
311 // } else {
312 // ctx.offset += 1 // consume and move forward
313 // }
314 // }
315}
316
317///|
318/// `ctx.expect_ascii_char(c)` check the current context is c,
319///
320fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext, c : Byte) -> Unit!ParseError
ctx.expect_ascii_char(c) check the current context is c,
expect_ascii_char(
321 ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext,
322 Byte
c : Byte
Byte
323) -> Unit
Unit!type! ParseError String
ParseError {
324 // guard ctx.offset < ctx.end_offset else { raise ParseError("invalid eof") }
325 // let c1 = ctx.input.unsafe_charcode_at(ctx.offset)
326 // ctx.offset += 1
327 // if c.to_int() != c1 {
328 // ctx.invalid_char!(c, shift=-1)
329 // }
330 struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext, c : Char) -> Unit!ParseError
ctx.expect_char(c) check the current context is c,
if it is, consume the character and return (),
otherwise raise an error, when it is an error, the position is unspecified.
expect_char!(ParseContext
ctx, (Int) -> Char
Int::(self : Int) -> Char
unsafe_to_char(Byte
c.(self : Byte) -> Int
Converts a byte value to a 32-bit signed integer. The resulting integer will
have the same binary representation as the byte value, preserving the
numerical value in the range [0, 255].
Parameters:
byte : The byte value to be converted to an integer.
Returns a 32-bit signed integer representing the same numerical value as the
input byte.
Example:
test "Byte::to_int" {
let b = b'\xFF' // byte with value 255
inspect(b.to_int(), content="255")
let zero = b'\x00'
inspect(zero.to_int(), content="0")
}
to_int()))
331}
332
333///|
334test "expect_char" {
335 let Buffer
buf = struct Buffer {
mut b: Slice[Byte]
mut off: Int
}
Buffer::(size_hint~ : Int) -> Buffer
Buffer::new creates a new empty Buffer with an optional size hint.
The size hint is used to preallocate memory for the buffer, which can
improve performance when the size of the data to be written is known in advance.
new(Int
size_hint=3)
336 Buffer
buf.(self : Buffer, s : String) -> (Int, IOError?)
write_string converts the MoonBit UTF-16 String to UTF-8 and
writes the bytes to the buffer.
write_string("abc") |> (t : (Int, IOError?)) -> Unit
Evaluates an expression and discards its result. This is useful when you want
to execute an expression for its side effects but don't care about its return
value, or when you want to explicitly indicate that a value is intentionally
unused.
Parameters:
value : The value to be ignored. Can be of any type.
Example:
test "ignore" {
let x = 42
ignore(x) // Explicitly ignore the value
let mut sum = 0
ignore([1, 2, 3].iter().each(fn(x) { sum = sum + x })) // Ignore the Unit return value of each()
}
ignore()
337 let ParseContext
ctx = struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(r : &ByteReader) -> ParseContext
make(Buffer
buf)
338 ParseContext
ctx.(ctx : ParseContext, c : Char) -> Unit!ParseError
ctx.expect_char(c) check the current context is c,
if it is, consume the character and return (),
otherwise raise an error, when it is an error, the position is unspecified.
expect_char!('a')
339 ParseContext
ctx.(ctx : ParseContext, c : Char) -> Unit!ParseError
ctx.expect_char(c) check the current context is c,
if it is, consume the character and return (),
otherwise raise an error, when it is an error, the position is unspecified.
expect_char!('b')
340 ParseContext
ctx.(ctx : ParseContext, c : Char) -> Unit!ParseError
ctx.expect_char(c) check the current context is c,
if it is, consume the character and return (),
otherwise raise an error, when it is an error, the position is unspecified.
expect_char!('c')
341 (obj : &Show, content~ : String, loc~ : SourceLoc = _, args_loc~ : ArgsLoc = _) -> Unit!InspectError
Tests if the string representation of an object matches the expected content.
Used primarily in test cases to verify the correctness of Show
implementations and program outputs.
Parameters:
object : The object to be inspected. Must implement the Show trait.
content : The expected string representation of the object. Defaults to
an empty string.
location : Source code location information for error reporting.
Automatically provided by the compiler.
arguments_location : Location information for function arguments in
source code. Automatically provided by the compiler.
Throws an InspectError if the actual string representation of the object
does not match the expected content. The error message includes detailed
information about the mismatch, including source location and both expected
and actual values.
Example:
test "inspect/basic" {
inspect(42, content="42")
inspect("hello", content="hello")
inspect([1, 2, 3], content="[1, 2, 3]")
}
inspect!(
342 ParseContext
ctx.(ctx : ParseContext, c : Char) -> Unit!ParseError
ctx.expect_char(c) check the current context is c,
if it is, consume the character and return (),
otherwise raise an error, when it is an error, the position is unspecified.
expect_char?('d').(self : Result[Unit, ParseError]) -> String
to_string(),
343 String
content=
344 #|Err(ParseError("invalid eof"))
345 ,
346 )
347}
348
349///|
350fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext) -> Unit
lex_skip_whitespace(ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext) -> Unit
Unit {
351 for {
352 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
353 (Char) -> Char?
Some('\t' | ' ' | '\n' | '\r') => continue
354 (Char) -> Char?
Some(Char
c) => {
355 if Char
c (self_ : Char, other : Char) -> Bool
> '\u{7f}' (Bool, Bool) -> Bool
&& CharClass
non_ascii_whitespace.(self : CharClass, c : Char) -> Bool
contains(Char
c) {
356 continue
357 }
358 ParseContext
ctx.Int
offset (self : Int, other : Int) -> Int
Performs subtraction between two 32-bit integers, following standard two's
complement arithmetic rules. When the result overflows or underflows, it
wraps around within the 32-bit integer range.
Parameters:
self : The minuend (the number being subtracted from).
other : The subtrahend (the number to subtract).
Returns the difference between self and other.
Example:
test "Int::op_sub" {
let a = 42
let b = 10
inspect(a - b, content="32")
let max = 2147483647 // Int maximum value
inspect(max - -1, content="-2147483648") // Overflow case
}
-= 1
359 break
360 }
361 Char?
None => break
362 }
363 }
364}
365
366///|
367fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext) -> Token!ParseError
lex_after_array_value(ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext) -> enum Token {
Null
True
False
Number(Double)
String(String)
LBrace
RBrace
LBracket
RBracket
Comma
}
Token!type! ParseError String
ParseError {
368 ParseContext
ctx.(ctx : ParseContext) -> Unit
lex_skip_whitespace()
369 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
370 (Char) -> Char?
Some(']') => Token
RBracket
371 (Char) -> Char?
Some(',') => Token
Comma
372 (Char) -> Char?
Some(Char
c) => ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Token!ParseError
invalid_char!(Char
c, Int
shift=-1)
373 Char?
None => raise (String) -> ParseError
ParseError("invalid eof")
374 }
375}
376
377///|
378fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext) -> Unit!ParseError
lex_after_property_name(ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext) -> Unit
Unit!type! ParseError String
ParseError {
379 ParseContext
ctx.(ctx : ParseContext) -> Unit
lex_skip_whitespace()
380 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
381 (Char) -> Char?
Some(':') => ()
382 (Char) -> Char?
Some(Char
c) => ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Unit!ParseError
invalid_char!(Char
c, Int
shift=-1)
383 Char?
None => raise (String) -> ParseError
ParseError("invalid eof")
384 }
385}
386
387///|
388fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext) -> Token!ParseError
lex_after_object_value(ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext) -> enum Token {
Null
True
False
Number(Double)
String(String)
LBrace
RBrace
LBracket
RBracket
Comma
}
Token!type! ParseError String
ParseError {
389 ParseContext
ctx.(ctx : ParseContext) -> Unit
lex_skip_whitespace()
390 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
391 (Char) -> Char?
Some('}') => Token
RBrace
392 (Char) -> Char?
Some(',') => Token
Comma
393 (Char) -> Char?
Some(Char
c) => ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Token!ParseError
invalid_char!(Char
c, Int
shift=-1)
394 Char?
None => raise (String) -> ParseError
ParseError("invalid eof")
395 }
396}
397
398///|
399/// In the context of `{`, try to lex token `}` or a property name,
400/// otherwise raise an error.
401fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext) -> Token!ParseError
In the context of {, try to lex token } or a property name,
otherwise raise an error.
lex_property_name(ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext) -> enum Token {
Null
True
False
Number(Double)
String(String)
LBrace
RBrace
LBracket
RBracket
Comma
}
Token!type! ParseError String
ParseError {
402 ParseContext
ctx.(ctx : ParseContext) -> Unit
lex_skip_whitespace()
403 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
404 (Char) -> Char?
Some('}') => Token
RBrace
405 (Char) -> Char?
Some('"') => {
406 let String
s = ParseContext
ctx.(ctx : ParseContext) -> String!ParseError
lex_string!()
407 (String) -> Token
String(String
s)
408 }
409 (Char) -> Char?
Some(Char
c) => ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Token!ParseError
invalid_char!(Char
c, Int
shift=-1)
410 Char?
None => raise (String) -> ParseError
ParseError("invalid eof")
411 }
412}
413
414///|
415/// In the context of `{ ...,` try to lex a property name,
416/// otherwise raise an error.
417/// since it is in comma context, `}` is not allowed.
418fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext) -> Token!ParseError
In the context of { ..., try to lex a property name,
otherwise raise an error.
since it is in comma context, } is not allowed.
lex_property_name2(ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext) -> enum Token {
Null
True
False
Number(Double)
String(String)
LBrace
RBrace
LBracket
RBracket
Comma
}
Token!type! ParseError String
ParseError {
419 ParseContext
ctx.(ctx : ParseContext) -> Unit
lex_skip_whitespace()
420 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
421 (Char) -> Char?
Some('"') => {
422 let String
s = ParseContext
ctx.(ctx : ParseContext) -> String!ParseError
lex_string!()
423 (String) -> Token
String(String
s)
424 }
425 (Char) -> Char?
Some(Char
c) => ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Token!ParseError
invalid_char!(Char
c, Int
shift=-1)
426 Char?
None => raise (String) -> ParseError
ParseError("invalid eof")
427 }
428}
429
430///|
431fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_integer(
432 ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext,
433 Int
start~ : Int
Int
434) -> Double
Double!type! ParseError String
ParseError {
435 for {
436 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
437 (Char) -> Char?
Some('.') => return ParseContext
ctx.(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_point!(Int
start~)
438 (Char) -> Char?
Some('e' | 'E') => return ParseContext
ctx.(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_exponent!(Int
start~)
439 (Char) -> Char?
Some(Char
c) => {
440 if Char
c (self_ : Char, other : Char) -> Bool
>= '0' (Bool, Bool) -> Bool
&& Char
c (self_ : Char, other : Char) -> Bool
<= '9' {
441 continue
442 }
443 ParseContext
ctx.Int
offset (self : Int, other : Int) -> Int
Performs subtraction between two 32-bit integers, following standard two's
complement arithmetic rules. When the result overflows or underflows, it
wraps around within the 32-bit integer range.
Parameters:
self : The minuend (the number being subtracted from).
other : The subtrahend (the number to subtract).
Returns the difference between self and other.
Example:
test "Int::op_sub" {
let a = 42
let b = 10
inspect(a - b, content="32")
let max = 2147483647 // Int maximum value
inspect(max - -1, content="-2147483648") // Overflow case
}
-= 1
444 return ParseContext
ctx.(ctx : ParseContext, start : Int, end : Int) -> Double!ParseError
lex_number_end!(Int
start, ParseContext
ctx.Int
offset)
445 }
446 Char?
None => return ParseContext
ctx.(ctx : ParseContext, start : Int, end : Int) -> Double!ParseError
lex_number_end!(Int
start, ParseContext
ctx.Int
offset)
447 }
448 }
449}
450
451///|
452fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_point(
453 ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext,
454 Int
start~ : Int
Int
455) -> Double
Double!type! ParseError String
ParseError {
456 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
457 (Char) -> Char?
Some(Char
c) =>
458 if Char
c (self_ : Char, other : Char) -> Bool
>= '0' (Bool, Bool) -> Bool
&& Char
c (self_ : Char, other : Char) -> Bool
<= '9' {
459 ParseContext
ctx.(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_fraction!(Int
start~)
460 } else {
461 ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Double!ParseError
invalid_char!(Char
c, Int
shift=-1)
462 }
463 Char?
None => raise (String) -> ParseError
ParseError("invalid eof")
464 }
465}
466
467///|
468fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_fraction(
469 ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext,
470 Int
start~ : Int
Int
471) -> Double
Double!type! ParseError String
ParseError {
472 for {
473 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
474 (Char) -> Char?
Some('e' | 'E') => return ParseContext
ctx.(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_exponent!(Int
start~)
475 (Char) -> Char?
Some(Char
c) => {
476 if Char
c (self_ : Char, other : Char) -> Bool
>= '0' (Bool, Bool) -> Bool
&& Char
c (self_ : Char, other : Char) -> Bool
<= '9' {
477 continue
478 }
479 ParseContext
ctx.Int
offset (self : Int, other : Int) -> Int
Performs subtraction between two 32-bit integers, following standard two's
complement arithmetic rules. When the result overflows or underflows, it
wraps around within the 32-bit integer range.
Parameters:
self : The minuend (the number being subtracted from).
other : The subtrahend (the number to subtract).
Returns the difference between self and other.
Example:
test "Int::op_sub" {
let a = 42
let b = 10
inspect(a - b, content="32")
let max = 2147483647 // Int maximum value
inspect(max - -1, content="-2147483648") // Overflow case
}
-= 1
480 return ParseContext
ctx.(ctx : ParseContext, start : Int, end : Int) -> Double!ParseError
lex_number_end!(Int
start, ParseContext
ctx.Int
offset)
481 }
482 Char?
None => return ParseContext
ctx.(ctx : ParseContext, start : Int, end : Int) -> Double!ParseError
lex_number_end!(Int
start, ParseContext
ctx.Int
offset)
483 }
484 }
485}
486
487///|
488fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_exponent(
489 ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext,
490 Int
start~ : Int
Int
491) -> Double
Double!type! ParseError String
ParseError {
492 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
493 (Char) -> Char?
Some('+') | (Char) -> Char?
Some('-') => return ParseContext
ctx.(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_exponent_sign!(Int
start~)
494 (Char) -> Char?
Some(Char
c) => {
495 if Char
c (self_ : Char, other : Char) -> Bool
>= '0' (Bool, Bool) -> Bool
&& Char
c (self_ : Char, other : Char) -> Bool
<= '9' {
496 return ParseContext
ctx.(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_exponent_integer!(Int
start~)
497 }
498 ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Double!ParseError
invalid_char!(Char
c, Int
shift=-1)
499 }
500 Char?
None => raise (String) -> ParseError
ParseError("invalid eof")
501 }
502}
503
504///|
505fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_exponent_sign(
506 ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext,
507 Int
start~ : Int
Int
508) -> Double
Double!type! ParseError String
ParseError {
509 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
510 (Char) -> Char?
Some(Char
c) => {
511 if Char
c (self_ : Char, other : Char) -> Bool
>= '0' (Bool, Bool) -> Bool
&& Char
c (self_ : Char, other : Char) -> Bool
<= '9' {
512 return ParseContext
ctx.(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_exponent_integer!(Int
start~)
513 }
514 ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Double!ParseError
invalid_char!(Char
c, Int
shift=-1)
515 }
516 Char?
None => raise (String) -> ParseError
ParseError("invalid eof")
517 }
518}
519
520///|
521fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_exponent_integer(
522 ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext,
523 Int
start~ : Int
Int
524) -> Double
Double!type! ParseError String
ParseError {
525 for {
526 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
527 (Char) -> Char?
Some(Char
c) => {
528 if Char
c (self_ : Char, other : Char) -> Bool
>= '0' (Bool, Bool) -> Bool
&& Char
c (self_ : Char, other : Char) -> Bool
<= '9' {
529 continue
530 }
531 ParseContext
ctx.Int
offset (self : Int, other : Int) -> Int
Performs subtraction between two 32-bit integers, following standard two's
complement arithmetic rules. When the result overflows or underflows, it
wraps around within the 32-bit integer range.
Parameters:
self : The minuend (the number being subtracted from).
other : The subtrahend (the number to subtract).
Returns the difference between self and other.
Example:
test "Int::op_sub" {
let a = 42
let b = 10
inspect(a - b, content="32")
let max = 2147483647 // Int maximum value
inspect(max - -1, content="-2147483648") // Overflow case
}
-= 1
532 return ParseContext
ctx.(ctx : ParseContext, start : Int, end : Int) -> Double!ParseError
lex_number_end!(Int
start, ParseContext
ctx.Int
offset)
533 }
534 Char?
None => return ParseContext
ctx.(ctx : ParseContext, start : Int, end : Int) -> Double!ParseError
lex_number_end!(Int
start, ParseContext
ctx.Int
offset)
535 }
536 }
537}
538
539///|
540fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_zero(
541 ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext,
542 Int
start~ : Int
Int
543) -> Double
Double!type! ParseError String
ParseError {
544 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
545 (Char) -> Char?
Some('.') => ParseContext
ctx.(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_point!(Int
start~)
546 (Char) -> Char?
Some('e' | 'E') => ParseContext
ctx.(ctx : ParseContext, start~ : Int) -> Double!ParseError
lex_decimal_exponent!(Int
start~)
547 (Char) -> Char?
Some(Char
c) => {
548 if Char
c (self_ : Char, other : Char) -> Bool
>= '0' (Bool, Bool) -> Bool
&& Char
c (self_ : Char, other : Char) -> Bool
<= '9' {
549 ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Unit!ParseError
invalid_char!(Char
c, Int
shift=-1)
550 }
551 ParseContext
ctx.Int
offset (self : Int, other : Int) -> Int
Performs subtraction between two 32-bit integers, following standard two's
complement arithmetic rules. When the result overflows or underflows, it
wraps around within the 32-bit integer range.
Parameters:
self : The minuend (the number being subtracted from).
other : The subtrahend (the number to subtract).
Returns the difference between self and other.
Example:
test "Int::op_sub" {
let a = 42
let b = 10
inspect(a - b, content="32")
let max = 2147483647 // Int maximum value
inspect(max - -1, content="-2147483648") // Overflow case
}
-= 1
552 return ParseContext
ctx.(ctx : ParseContext, start : Int, end : Int) -> Double!ParseError
lex_number_end!(Int
start, ParseContext
ctx.Int
offset)
553 }
554 Char?
None => return ParseContext
ctx.(ctx : ParseContext, start : Int, end : Int) -> Double!ParseError
lex_number_end!(Int
start, ParseContext
ctx.Int
offset)
555 }
556}
557
558///|
559fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext, start : Int, end : Int) -> Double!ParseError
lex_number_end(
560 ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext,
561 Int
start : Int
Int,
562 Int
end : Int
Int
563) -> Double
Double!type! ParseError String
ParseError {
564 let String
s = ParseContext
ctx.Buffer
buf.(self : Buffer, start~ : Int, end~ : Int) -> String
substring(Int
start~, Int
end~)
565 try (str : String) -> Double!@strconv.StrConvError
Parse a string into a double precision floating point number. The string
must contain at least one of:
- An integer part (decimal digits)
- A decimal point followed by a fractional part (decimal digits)
- An exponent part ('e' or 'E' followed by an optional sign and decimal digits)
The string may optionally start with a sign ('+' or '-').
For readability, underscores may appear between digits.
Examples:
inspect(parse_double("123"), content="123")
inspect(parse_double("12.34"), content="12.34")
inspect(parse_double(".123"), content="0.123")
inspect(parse_double("1e5"), content="100000")
inspect(parse_double("1.2e-3"), content="0.0012")
inspect(parse_double("1_234.5"), content="1234.5")
An exponent value exp scales the mantissa (significand) by 10^exp.
For example, "1.23e2" represents 1.23 × 10² = 123.
@strconv.parse_double!(String
s) catch {
566 _ => raise (String) -> ParseError
ParseError("invalid number '\{String
s}' at offsets \{Int
start}:\{Int
end}") // InvalidNumber(offset_to_position(ctx.input, start), s)
567 }
568}
569
570///|
571fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext) -> String!ParseError
lex_string(ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext) -> String
String!type! ParseError String
ParseError {
572 let StringBuilder
buf = type StringBuilder
StringBuilder::(size_hint~ : Int = ..) -> StringBuilder
Creates a new string builder with an optional initial capacity hint.
Parameters:
size_hint : An optional initial capacity hint for the internal buffer. If
less than 1, a minimum capacity of 1 is used. Defaults to 0. It is the size of bytes,
not the size of characters. size_hint may be ignored on some platforms, JS for example.
Returns a new StringBuilder instance with the specified initial capacity.
new()
573 let mut Int
start = ParseContext
ctx.Int
offset
574 fn (Int) -> Unit
flush(Int
end : Int
Int) {
575 if Int
start (self_ : Int, other : Int) -> Bool
> 0 (Bool, Bool) -> Bool
&& Int
end (self_ : Int, other : Int) -> Bool
> Int
start {
576 // buf.write_substring(ctx.input, start, end - start)
577 StringBuilder
buf.(self : StringBuilder, str : String) -> Unit
Writes a string to the StringBuilder.
write_string(ParseContext
ctx.Buffer
buf.(self : Buffer, start~ : Int, end~ : Int) -> String
substring(Int
start~, Int
end~))
578 }
579 }
580
581 for {
582 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
583 (Char) -> Char?
Some('"') => {
584 (Int) -> Unit
flush(ParseContext
ctx.Int
offset (self : Int, other : Int) -> Int
Performs subtraction between two 32-bit integers, following standard two's
complement arithmetic rules. When the result overflows or underflows, it
wraps around within the 32-bit integer range.
Parameters:
self : The minuend (the number being subtracted from).
other : The subtrahend (the number to subtract).
Returns the difference between self and other.
Example:
test "Int::op_sub" {
let a = 42
let b = 10
inspect(a - b, content="32")
let max = 2147483647 // Int maximum value
inspect(max - -1, content="-2147483648") // Overflow case
}
- 1)
585 break
586 }
587 (Char) -> Char?
SomeChar?
('\n' | '\r') as c => ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Unit!ParseError
invalid_char!(Char?
c.(self : Char?) -> Char
Extract the value in Some.
If the value is None, it throws a panic.
unwrap(), Int
shift=-1)
588 (Char) -> Char?
Some('\\') => {
589 (Int) -> Unit
flush(ParseContext
ctx.Int
offset (self : Int, other : Int) -> Int
Performs subtraction between two 32-bit integers, following standard two's
complement arithmetic rules. When the result overflows or underflows, it
wraps around within the 32-bit integer range.
Parameters:
self : The minuend (the number being subtracted from).
other : The subtrahend (the number to subtract).
Returns the difference between self and other.
Example:
test "Int::op_sub" {
let a = 42
let b = 10
inspect(a - b, content="32")
let max = 2147483647 // Int maximum value
inspect(max - -1, content="-2147483648") // Overflow case
}
- 1)
590 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
591 (Char) -> Char?
Some('b') => StringBuilder
buf.(self : StringBuilder, ch : Char) -> Unit
Writes a character to the StringBuilder.
write_char('\b')
592 (Char) -> Char?
Some('f') => StringBuilder
buf.(self : StringBuilder, ch : Char) -> Unit
Writes a character to the StringBuilder.
write_char('\u{0C}')
593 (Char) -> Char?
Some('n') => StringBuilder
buf.(self : StringBuilder, ch : Char) -> Unit
Writes a character to the StringBuilder.
write_char('\n')
594 (Char) -> Char?
Some('r') => StringBuilder
buf.(self : StringBuilder, ch : Char) -> Unit
Writes a character to the StringBuilder.
write_char('\r')
595 (Char) -> Char?
Some('t') => StringBuilder
buf.(self : StringBuilder, ch : Char) -> Unit
Writes a character to the StringBuilder.
write_char('\t')
596 (Char) -> Char?
Some('"') => StringBuilder
buf.(self : StringBuilder, ch : Char) -> Unit
Writes a character to the StringBuilder.
write_char('"')
597 (Char) -> Char?
Some('\\') => StringBuilder
buf.(self : StringBuilder, ch : Char) -> Unit
Writes a character to the StringBuilder.
write_char('\\')
598 (Char) -> Char?
Some('/') => StringBuilder
buf.(self : StringBuilder, ch : Char) -> Unit
Writes a character to the StringBuilder.
write_char('/')
599 (Char) -> Char?
Some('u') => {
600 let Int
c = ParseContext
ctx.(ctx : ParseContext, n : Int) -> Int!ParseError
lex_hex_digits!(4)
601 StringBuilder
buf.(self : StringBuilder, ch : Char) -> Unit
Writes a character to the StringBuilder.
write_char((Int) -> Char
Int::(self : Int) -> Char
unsafe_to_char(Int
c))
602 }
603 (Char) -> Char?
Some(Char
c) => ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Unit!ParseError
invalid_char!(Char
c, Int
shift=-1)
604 Char?
None => raise (String) -> ParseError
ParseError("invalid eof")
605 }
606 Int
start = ParseContext
ctx.Int
offset
607 }
608 (Char) -> Char?
Some(Char
ch) =>
609 if Char
ch.(self : Char) -> Int
Converts a character to its Unicode code point value as an integer.
Parameters:
self : The character to be converted.
Returns an integer representing the Unicode code point value of the
character.
Example:
test "Char::to_int" {
inspect('A'.to_int(), content="65") // ASCII value of 'A'
inspect('あ'.to_int(), content="12354") // Unicode code point of 'あ'
}
to_int() (self_ : Int, other : Int) -> Bool
< 32 {
610 ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Unit!ParseError
invalid_char!(Char
ch, Int
shift=-1)
611 } else {
612 continue
613 }
614 Char?
None => raise (String) -> ParseError
ParseError("invalid eof")
615 }
616 }
617 StringBuilder
buf.(self : StringBuilder) -> String
Returns the current content of the StringBuilder as a string.
to_string()
618}
619
620///|
621fn struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext::(ctx : ParseContext, n : Int) -> Int!ParseError
lex_hex_digits(ParseContext
ctx : struct ParseContext {
r: &ByteReader
buf: Buffer
mut offset: Int
}
ParseContext, Int
n : Int
Int) -> Int
Int!type! ParseError String
ParseError {
622 let mut Int
r = 0
623 for Int
i in Int
0..<Int
n {
624 match ParseContext
ctx.(ctx : ParseContext) -> Char?
read_char() {
625 (Char) -> Char?
Some(Char
c) =>
626 if Char
c (self_ : Char, other : Char) -> Bool
>= 'A' {
627 let Int
d = (Char
c.(self : Char) -> Int
Converts a character to its Unicode code point value as an integer.
Parameters:
self : The character to be converted.
Returns an integer representing the Unicode code point value of the
character.
Example:
test "Char::to_int" {
inspect('A'.to_int(), content="65") // ASCII value of 'A'
inspect('あ'.to_int(), content="12354") // Unicode code point of 'あ'
}
to_int() (Int, Int) -> Int
& (32).(self : Int) -> Int
Performs a bitwise NOT operation on a 32-bit integer. Flips each bit in the
integer's binary representation (0 becomes 1 and 1 becomes 0).
Parameters:
value : The 32-bit integer on which to perform the bitwise NOT operation.
Returns a new integer with all bits flipped from the input value.
Example:
test "Int::lnot" {
let a = -1 // All bits are 1
let b = 0 // All bits are 0
inspect(a.lnot(), content="0")
inspect(b.lnot(), content="-1")
}
lnot()) (self : Int, other : Int) -> Int
Performs subtraction between two 32-bit integers, following standard two's
complement arithmetic rules. When the result overflows or underflows, it
wraps around within the 32-bit integer range.
Parameters:
self : The minuend (the number being subtracted from).
other : The subtrahend (the number to subtract).
Returns the difference between self and other.
Example:
test "Int::op_sub" {
let a = 42
let b = 10
inspect(a - b, content="32")
let max = 2147483647 // Int maximum value
inspect(max - -1, content="-2147483648") // Overflow case
}
- 'A'.(self : Char) -> Int
Converts a character to its Unicode code point value as an integer.
Parameters:
self : The character to be converted.
Returns an integer representing the Unicode code point value of the
character.
Example:
test "Char::to_int" {
inspect('A'.to_int(), content="65") // ASCII value of 'A'
inspect('あ'.to_int(), content="12354") // Unicode code point of 'あ'
}
to_int() (self : Int, other : Int) -> Int
Adds two 32-bit signed integers. Performs two's complement arithmetic, which
means the operation will wrap around if the result exceeds the range of a
32-bit integer.
Parameters:
self : The first integer operand.
other : The second integer operand.
Returns a new integer that is the sum of the two operands. If the
mathematical sum exceeds the range of a 32-bit integer (-2,147,483,648 to
2,147,483,647), the result wraps around according to two's complement rules.
Example:
test "Int::op_add" {
inspect(42 + 1, content="43")
inspect(2147483647 + 1, content="-2147483648") // Overflow wraps around to minimum value
}
+ 10
628 if Int
d (self_ : Int, other : Int) -> Bool
> 15 {
629 ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Unit!ParseError
invalid_char!(Char
c, Int
shift=-1)
630 }
631 Int
r = (Int
r (self : Int, other : Int) -> Int
Performs a left shift operation on a 32-bit integer. Shifts each bit in the
integer to the left by the specified number of positions, filling the
rightmost positions with zeros.
Parameters:
self : The integer value to be shifted.
shift : The number of positions to shift. Must be a non-negative value
less than 32. Values outside this range will be masked with & 31.
Returns a new integer with bits shifted left by the specified number of
positions. For each position shifted, the rightmost bit is filled with 0, and
the leftmost bit is discarded.
Example:
test "Int::op_shl" {
let x = 1
inspect(x << 3, content="8") // Binary: 1 -> 1000
let y = -4
inspect(y << 2, content="-16") // Binary: 100 -> 10000
}
<< 4) (Int, Int) -> Int
| Int
d
632 } else if Char
c (self_ : Char, other : Char) -> Bool
>= '0' {
633 let Int
d = Char
c.(self : Char) -> Int
Converts a character to its Unicode code point value as an integer.
Parameters:
self : The character to be converted.
Returns an integer representing the Unicode code point value of the
character.
Example:
test "Char::to_int" {
inspect('A'.to_int(), content="65") // ASCII value of 'A'
inspect('あ'.to_int(), content="12354") // Unicode code point of 'あ'
}
to_int() (self : Int, other : Int) -> Int
Performs subtraction between two 32-bit integers, following standard two's
complement arithmetic rules. When the result overflows or underflows, it
wraps around within the 32-bit integer range.
Parameters:
self : The minuend (the number being subtracted from).
other : The subtrahend (the number to subtract).
Returns the difference between self and other.
Example:
test "Int::op_sub" {
let a = 42
let b = 10
inspect(a - b, content="32")
let max = 2147483647 // Int maximum value
inspect(max - -1, content="-2147483648") // Overflow case
}
- '0'.(self : Char) -> Int
Converts a character to its Unicode code point value as an integer.
Parameters:
self : The character to be converted.
Returns an integer representing the Unicode code point value of the
character.
Example:
test "Char::to_int" {
inspect('A'.to_int(), content="65") // ASCII value of 'A'
inspect('あ'.to_int(), content="12354") // Unicode code point of 'あ'
}
to_int()
634 if Int
d (self_ : Int, other : Int) -> Bool
> 9 {
635 ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Unit!ParseError
invalid_char!(Char
c, Int
shift=-1)
636 }
637 Int
r = (Int
r (self : Int, other : Int) -> Int
Performs a left shift operation on a 32-bit integer. Shifts each bit in the
integer to the left by the specified number of positions, filling the
rightmost positions with zeros.
Parameters:
self : The integer value to be shifted.
shift : The number of positions to shift. Must be a non-negative value
less than 32. Values outside this range will be masked with & 31.
Returns a new integer with bits shifted left by the specified number of
positions. For each position shifted, the rightmost bit is filled with 0, and
the leftmost bit is discarded.
Example:
test "Int::op_shl" {
let x = 1
inspect(x << 3, content="8") // Binary: 1 -> 1000
let y = -4
inspect(y << 2, content="-16") // Binary: 100 -> 10000
}
<< 4) (Int, Int) -> Int
| Int
d
638 } else {
639 ParseContext
ctx.(ctx : ParseContext, c : Char, shift~ : Int) -> Unit!ParseError
invalid_char!(Char
c, Int
shift=-1)
640 }
641 Char?
None => raise (String) -> ParseError
ParseError("invalid eof")
642 }
643 }
644 Int
r
645}
646