@@ -4,35 +4,47 @@ AIScript provides a robust and elegant error handling system inspired by modern
44
55## Error Types
66
7- In AIScript, errors are represented using enums with a special ` ! ` suffix:
7+ In AIScript, errors are represented using enum or class with a special ` ! ` suffix:
88
99``` js
1010enum FileError! {
1111 NotFound,
1212 PermissionDenied,
13- InvalidFormat (str),
13+ InvalidFormat,
14+ }
15+
16+ class SyntaxError ! {
17+ message: str,
18+ line: int,
1419}
1520```
1621
17- This syntax clearly communicates that an enum is meant to represent error cases.
22+ This syntax clearly communicates that an enum or class is meant to represent error cases.
1823
1924## Declaring Functions with Error Types
2025
2126Functions that can fail should declare their potential error types in the return signature using the pipe (` | ` ) operator:
2227
23- ``` js
28+ ``` rust
2429fn read_file (path : str ) -> str | FileError! {
2530 // Implementation that might fail...
2631}
2732```
2833
2934This return type specifies that the function returns either a string or a ` FileError! ` .
3035
36+ ``` rust
37+ fn read_file (path : str ) -> str | FileError! | IoError! {
38+ }
39+ ```
40+
41+ For multiple error types, use the` | ` to seperate them.
42+
3143## Raising Errors
3244
3345Use the ` raise ` keyword to signal an error from a function:
3446
35- ``` js
47+ ``` rust
3648fn read_file (path : str ) -> str | FileError! {
3749 if ! file_exists (path ) {
3850 raise FileError! :: NotFound ;
@@ -44,7 +56,7 @@ fn read_file(path: str) -> str | FileError! {
4456
4557 let content = read_file_contents (path );
4658 if ! is_valid_format (content ) {
47- raise FileError! :: InvalidFormat ( " Invalid file format " ) ;
59+ raise FileError! :: InvalidFormat ;
4860 }
4961
5062 return content ;
@@ -55,40 +67,40 @@ fn read_file(path: str) -> str | FileError! {
5567
5668AIScript provides three main ways to handle errors:
5769
58- ### 1. Using the Error Handler Syntax
70+ ### Error Handler
5971
60- The error handler syntax uses the pipe (` | ` ) operator followed by a code block:
72+ The error handler syntax uses the pipe (` |err| ` ) syntax followed by a code block:
6173
62- ``` js
74+ ``` rust
6375let content = read_file (" config.json" ) | err | {
6476 match err {
6577 FileError! :: NotFound => {
6678 print (" File not found, using default config" );
67- return " {}" ; // Default empty config
79+ " {}" // Default empty config
6880 },
6981 FileError! :: PermissionDenied => {
7082 print (" Permission denied, please check file permissions" );
71- return " {}" ;
83+ " {}"
7284 },
73- FileError! :: InvalidFormat (msg) => {
74- print (" Invalid file format: {msg} " );
75- return " {}" ;
85+ FileError! :: InvalidFormat => {
86+ print (" Invalid file format" );
87+ " {}"
7688 }
7789 }
7890};
7991
8092// content is guaranteed to be a string here
81- print (" Config loaded: { content} " );
93+ print (" Config loaded:" , content " );
8294```
8395
8496The error handler receives the error as a parameter and must return a value of the same type as the success case.
8597
86- ### 2. Using the Propagation Operator ( ` ? ` )
98+ ### Error Propagation
8799
88100For functions that might fail with similar error types, you can use the `?` operator to immediately return errors to the caller:
89101
90- ``` js
91- fn load_configuration () - > object | FileError! {
102+ ```rust
103+ fn load_configuration() -> str | FileError! {
92104 let file_content = read_file(" config . json" )?; // Propagate error
93105 let config = parse_json(file_content)?; // Propagate error
94106 return config;
@@ -97,192 +109,12 @@ fn load_configuration() -> object | FileError! {
97109// Usage
98110let config = load_configuration() |err| {
99111 print(" Error loading configuration : {err }" );
100- return {}; // Default empty config
112+ {} // Default empty config
101113};
102114```
103115
104116When a function call with `?` returns an error, the current function immediately returns with that error.
105117
106- ### 3. Match on Result Types
107-
108- For more complex error handling logic, you can match on result types explicitly:
109-
110- ` ` ` js
111- fn process_file () - > str | FileError! {
112- let result = read_file (" data.txt" );
113-
114- match result {
115- str content => {
116- // Process the content
117- return " Processed: {content}" ;
118- },
119- FileError! :: NotFound => {
120- // Handle specific error
121- raise FileError! :: NotFound;
122- },
123- FileError! err => {
124- // Handle any other error from FileError
125- print (" Error: {err}" );
126- raise err;
127- }
128- }
129- }
130- ` ` `
131-
132- ## Creating Custom Error Types
133-
134- Create custom error types to represent domain-specific failures:
135-
136- ` ` ` js
137- enum ValidationError! {
138- InvalidEmail (str),
139- InvalidPassword {
140- reason: str,
141- score: int,
142- },
143- MissingField (str),
144- }
145-
146- fn validate_user (user: object) - > bool | ValidationError! {
147- if ! user .email {
148- raise ValidationError! :: MissingField (" email" );
149- }
150-
151- if ! is_valid_email (user .email ) {
152- raise ValidationError! :: InvalidEmail (user .email );
153- }
154-
155- if ! user .password {
156- raise ValidationError! :: MissingField (" password" );
157- }
158-
159- let password_score = calculate_password_strength (user .password );
160- if password_score < 50 {
161- raise ValidationError! :: InvalidPassword {
162- reason: " Password too weak" ,
163- score: password_score,
164- };
165- }
166-
167- return true ;
168- }
169- ` ` `
170-
171- ## Combining Multiple Error Types
172-
173- Functions can declare multiple potential error types:
174-
175- ` ` ` js
176- enum DatabaseError! {
177- ConnectionFailed,
178- QueryFailed (str),
179- }
180-
181- fn save_user (user: object) - > bool | ValidationError! | DatabaseError! {
182- // First validate the user
183- validate_user (user)? ;
184-
185- // Then attempt to save to database
186- if ! db_connected () {
187- raise DatabaseError! :: ConnectionFailed;
188- }
189-
190- let result = db_insert (" users" , user);
191- if ! result .success {
192- raise DatabaseError! :: QueryFailed (result .message );
193- }
194-
195- return true ;
196- }
197- ` ` `
198-
199- ## Converting Between Error Types
200-
201- You can convert between error types to provide more context:
202-
203- ` ` ` js
204- fn register_user (user_data: object) - > object | ValidationError! | DatabaseError! {
205- let validated = validate_user (user_data)? ;
206-
207- try {
208- return db_create_user (validated);
209- } catch (db_error) {
210- // Convert database error to a more user-friendly error
211- if db_error is DatabaseError! :: ConnectionFailed {
212- print (" Database connection issue, please try again later" );
213- raise DatabaseError! :: ConnectionFailed;
214- }
215-
216- // Add context to the error
217- raise DatabaseError! :: QueryFailed (" User registration failed: {db_error}" );
218- }
219- }
220- ` ` `
221-
222- ## Error Handling in Web APIs
223-
224- AIScript's error handling is particularly useful for web APIs:
225-
226- ` ` ` js
227- enum ApiError! {
228- NotFound (str),
229- Unauthorized,
230- BadRequest (str),
231- InternalError ,
232- }
233-
234- get / users/ : id {
235- // Path parameters
236- let user_id = params .id ;
237-
238- // Try to get user from database
239- let user = db .get_user (user_id) | err| {
240- match err {
241- DatabaseError! :: ConnectionFailed => {
242- return response (500 , { error: " Database connection failed" });
243- },
244- _ => {
245- return response (404 , { error: " User not found" });
246- }
247- }
248- };
249-
250- // Return user data
251- return response (200 , { user });
252- }
253- ` ` `
254-
255- ## Error Context and Debugging
256-
257- Add context to errors to make debugging easier:
258-
259- ` ` ` js
260- enum AppError! {
261- OperationFailed {
262- operation: str,
263- cause: str,
264- context: object,
265- }
266- }
267-
268- fn process_data (data: array) - > array | AppError! {
269- try {
270- return transform_data (data);
271- } catch (error) {
272- // Add context to the error
273- raise AppError! :: OperationFailed {
274- operation: " transform_data" ,
275- cause: " {error}" ,
276- context: {
277- data_length: len (data),
278- data_sample: data .slice (0 , 5 ),
279- timestamp: now (),
280- }
281- };
282- }
283- }
284- ` ` `
285-
286118## Best Practices
287119
2881201. **Be specific with error types**: Create domain-specific error types for different categories of errors
0 commit comments