-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement simple i8 arithmetic. (#660)
- Loading branch information
Showing
3 changed files
with
125 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,26 @@ | ||
/** | ||
* The Alan root scope. The functions and types it binds from Rust are either part of the standard | ||
* library, or are defined in the sibling root.rs file | ||
**/ | ||
|
||
// Integer-related bindings | ||
export fn toI8(i: i64): i8 binds i64toi8; | ||
export fn add(a: i8, b: i8): Result<i8> binds addi8; | ||
export fn sub(a: i8, b: i8): Result<i8> binds subi8; | ||
export fn mul(a: i8, b: i8): Result<i8> binds muli8; | ||
export fn div(a: i8, b: i8): Result<i8> binds divi8; | ||
export fn mod(a: i8, b: i8): Result<i8> binds modi8; | ||
export fn pow(a: i8, b: i8): Result<i8> binds powi8; | ||
export fn min(a: i8, b: i8): i8 binds mini8; | ||
export fn max(a: i8, b: i8): i8 binds maxi8; | ||
|
||
// Process exit-related bindings | ||
export type ExitCode binds std::process::ExitCode; | ||
export fn toExitCode(e: i64): ExitCode binds to_exit_code; | ||
export fn print(str: String) binds println!; | ||
export fn toExitCode(e: i64): ExitCode binds to_exit_code_i64; | ||
export fn toExitCode(e: i8): ExitCode binds to_exit_code_i8; | ||
export fn getOrExit(a: Result<i8>): i8 binds get_or_exit; // TODO: Support real generics | ||
|
||
// Stdout/stderr-related bindings | ||
export fn print(str: String) binds println!; | ||
export fn print(i: i8) binds print; | ||
export fn print(i: i64) binds print; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,87 @@ | ||
fn to_exit_code(i: i64) -> std::process::ExitCode { | ||
/// Rust functions that the root scope binds. | ||
/// `to_exit_code_i64` converts a 64-bit integer into an exit code, for convenience since `i64` is the | ||
/// default integer type in Alan. | ||
fn to_exit_code_i64(i: i64) -> std::process::ExitCode { | ||
(i as u8).into() | ||
} | ||
|
||
/// `to_exit_code_i8` converts a 64-bit integer into an exit code, for convenience since `i64` is the | ||
/// default integer type in Alan. | ||
fn to_exit_code_i8(i: i8) -> std::process::ExitCode { | ||
(i as u8).into() | ||
} | ||
|
||
/// `i64toi8` casts an i64 to an i8. | ||
fn i64toi8(i: i64) -> i8 { | ||
i as i8 | ||
} | ||
|
||
/// `addi8` safely adds two i8s together, returning a Result-wrapped i8 (or an error on overflow) | ||
fn addi8(a: i8, b: i8) -> Result<i8, Box<dyn std::error::Error>> { | ||
match a.checked_add(b) { | ||
Some(c) => Ok(c), | ||
None => Err("Overflow".into()), | ||
} | ||
} | ||
|
||
/// `subi8` safely subtracts two i8s, returning a Result-wrapped i8 (or an error on underflow) | ||
fn subi8(a: i8, b: i8) -> Result<i8, Box<dyn std::error::Error>> { | ||
match a.checked_sub(b) { | ||
Some(c) => Ok(c), | ||
None => Err("Underflow".into()), | ||
} | ||
} | ||
|
||
/// `muli8` safely multiplies two i8s, returning a Result-wrapped i8 (or an error on under/overflow) | ||
fn muli8(a: i8, b: i8) -> Result<i8, Box<dyn std::error::Error>> { | ||
match a.checked_mul(b) { | ||
Some(c) => Ok(c), | ||
None => Err("Underflow or Overflow".into()), | ||
} | ||
} | ||
|
||
/// `divi8` safely divides two i8s, returning a Result-wrapped i8 (or an error on divide-by-zero) | ||
fn divi8(a: i8, b: i8) -> Result<i8, Box<dyn std::error::Error>> { | ||
match a.checked_div(b) { | ||
Some(c) => Ok(c), | ||
None => Err("Divide-by-zero".into()), | ||
} | ||
} | ||
|
||
/// `modi8` safely divides two i8s, returning a Result-wrapped remainder in i8 (or an error on divide-by-zero) | ||
fn modi8(a: i8, b: i8) -> Result<i8, Box<dyn std::error::Error>> { | ||
match a.checked_rem(b) { | ||
Some(c) => Ok(c), | ||
None => Err("Divide-by-zero".into()), | ||
} | ||
} | ||
|
||
/// `powi8` safely raises the first i8 to the second i8, returning a Result-wrapped i8 (or an error on under/overflow) | ||
fn powi8(a: i8, b: i8) -> Result<i8, Box<dyn std::error::Error>> { | ||
// TODO: Support b being negative correctly | ||
match a.checked_pow(b as u32) { | ||
Some(c) => Ok(c), | ||
None => Err("Underflow or Overflow".into()), | ||
} | ||
} | ||
|
||
/// `mini8` returns the smaller of the two i8 values | ||
fn mini8(a: i8, b: i8) -> i8 { | ||
if a < b { a } else { b } | ||
} | ||
|
||
/// `maxi8` returns the larger of the two i8 values | ||
fn maxi8(a: i8, b: i8) -> i8 { | ||
if a > b { a } else { b } | ||
} | ||
|
||
/// `get_or_exit` is basically an alias to `unwrap`, but as a function instead of a method | ||
fn get_or_exit<A>(a: Result<A, Box<dyn std::error::Error>>) -> A { | ||
a.unwrap() | ||
} | ||
|
||
/// `print` is a simple function that prints basically anything other than String | ||
fn print<A: std::fmt::Display>(a: A) { | ||
println!("{}", a); | ||
} |