Skip to content

Commit 63b1751

Browse files
committed
Support builtin int addition operator
1 parent c898389 commit 63b1751

7 files changed

Lines changed: 70 additions & 21 deletions

File tree

core/prototype/builtins.rssi

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ pub fn Csv.read_into(
1515

1616
pub fn Csv.parse_row(buffer: read RowBuffer) -> Result<fresh Row, CsvError>
1717

18-
pub fn Int.add(left: Int, right: Int) -> Int
19-
2018
pub fn List.consume(list: take List) -> Unit
2119

2220
pub fn Buffer.consume(buffer: take Buffer) -> Unit

examples/int_add.rss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fn main() -> Unit {
2+
let _ = 20 + 22
3+
Log.write(message: read "int add ran")
4+
return Unit
5+
}

src/rust_lower.rs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -666,14 +666,11 @@ impl<'a> RustLowerer<'a> {
666666
op, left, right, ..
667667
} => {
668668
let op = match op {
669+
BinaryOp::Add => "+",
669670
BinaryOp::LogicalAnd => "&&",
670671
BinaryOp::LogicalOr => "||",
671672
};
672-
format!(
673-
"({} {op} {})",
674-
self.lower_expr(left),
675-
self.lower_expr(right)
676-
)
673+
format!("{} {op} {}", self.lower_expr(left), self.lower_expr(right))
677674
}
678675
Expr::Field { base, name, .. } => {
679676
format!("{}.{}", self.lower_expr(base), rust_ident(name))
@@ -1044,21 +1041,25 @@ fn is_string_concat_callee(callee: &Callee) -> bool {
10441041
}
10451042

10461043
fn lower_string_concat_call(lowerer: &mut RustLowerer<'_>, args: &[CallArg]) -> String {
1047-
let left = args
1048-
.iter()
1049-
.find(|arg| arg.name.as_deref() == Some("left"))
1050-
.or_else(|| args.first())
1051-
.map(|arg| lowerer.lower_expr(&arg.value))
1052-
.unwrap_or_else(|| "\"\".to_string()".to_string());
1053-
let right = args
1054-
.iter()
1055-
.find(|arg| arg.name.as_deref() == Some("right"))
1056-
.or_else(|| args.get(1))
1057-
.map(|arg| lowerer.lower_expr(&arg.value))
1058-
.unwrap_or_else(|| "\"\".to_string()".to_string());
1044+
let left = lower_call_arg(lowerer, args, "left", 0, "\"\".to_string()");
1045+
let right = lower_call_arg(lowerer, args, "right", 1, "\"\".to_string()");
10591046
format!("format!(\"{{}}{{}}\", {left}, {right})")
10601047
}
10611048

1049+
fn lower_call_arg(
1050+
lowerer: &mut RustLowerer<'_>,
1051+
args: &[CallArg],
1052+
name: &str,
1053+
index: usize,
1054+
default: &str,
1055+
) -> String {
1056+
args.iter()
1057+
.find(|arg| arg.name.as_deref() == Some(name))
1058+
.or_else(|| args.get(index))
1059+
.map(|arg| lowerer.lower_expr(&arg.value))
1060+
.unwrap_or_else(|| default.to_string())
1061+
}
1062+
10621063
fn is_resource_pool_borrow_callee(callee: &Callee) -> bool {
10631064
matches!(callee, Callee::Qualified { namespace, name } if type_root_name(namespace) == "ResourcePool" && name == "borrow")
10641065
}

src/syntax/ast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ pub enum Expr {
223223

224224
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
225225
pub enum BinaryOp {
226+
Add,
226227
LogicalAnd,
227228
LogicalOr,
228229
}

src/syntax/parser.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,9 +738,15 @@ fn parse_expr(tokens: &[Token], start: usize, end: usize) -> Option<Expr> {
738738
fn parse_binary_expr(tokens: &[Token], start: usize, end: usize) -> Option<Expr> {
739739
find_top_level_binary_operator(tokens, start, end, "|", "|")
740740
.or_else(|| find_top_level_binary_operator(tokens, start, end, "&", "&"))
741+
.or_else(|| find_top_level_single_binary_operator(tokens, start, end, "+", BinaryOp::Add))
741742
.and_then(|(operator, op)| {
742743
let left = parse_expr(tokens, start, operator)?;
743-
let right = parse_expr(tokens, operator + 2, end)?;
744+
let right_start = if matches!(op, BinaryOp::Add) {
745+
operator + 1
746+
} else {
747+
operator + 2
748+
};
749+
let right = parse_expr(tokens, right_start, end)?;
744750
Some(Expr::Binary {
745751
op,
746752
left: Box::new(left),
@@ -750,6 +756,31 @@ fn parse_binary_expr(tokens: &[Token], start: usize, end: usize) -> Option<Expr>
750756
})
751757
}
752758

759+
fn find_top_level_single_binary_operator(
760+
tokens: &[Token],
761+
start: usize,
762+
end: usize,
763+
symbol: &str,
764+
op: BinaryOp,
765+
) -> Option<(usize, BinaryOp)> {
766+
let mut depth = 0usize;
767+
let mut found = None;
768+
for (index, token) in tokens.iter().enumerate().take(end).skip(start) {
769+
if token.symbol("(") || token.symbol("{") || token.symbol("[") || token.symbol("<") {
770+
depth += 1;
771+
continue;
772+
}
773+
if token.symbol(")") || token.symbol("}") || token.symbol("]") || token.symbol(">") {
774+
depth = depth.saturating_sub(1);
775+
continue;
776+
}
777+
if depth == 0 && token.symbol(symbol) {
778+
found = Some((index, op));
779+
}
780+
}
781+
found
782+
}
783+
753784
fn find_trailing_top_level_question(tokens: &[Token], start: usize, end: usize) -> Option<usize> {
754785
if end <= start || !tokens.get(end - 1).is_some_and(|token| token.symbol("?")) {
755786
return None;

tests/checker.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,19 @@ fn main() -> Unit {
312312
assert!(rust.contains("rsscript_runtime::log_write(&message);"));
313313
}
314314

315+
#[test]
316+
fn rust_lowering_maps_int_add_to_rust_std_expression() {
317+
let source = r#"
318+
fn main() -> Unit {
319+
let value = 20 + 22
320+
return Unit
321+
}
322+
"#;
323+
let rust = lower_source_to_rust("int.rss", source).expect("source should lower");
324+
325+
assert!(rust.contains("let value = 20 + 22;"));
326+
}
327+
315328
#[test]
316329
fn rust_lowering_maps_try_operator_to_rust_result_propagation() {
317330
let source = r#"

tests/fixtures/pass/csv-stream-local-buffer.rss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn sum_csv(path: read Path) -> Result<Int, CsvError> {
1111
with File.open_read(path: read path) as file {
1212
Csv.read_into(file: mut file, buffer: mut buffer)?
1313
let row = Csv.parse_row(buffer: read buffer)?
14-
Int.add(left: total, right: row.amount)
14+
total + row.amount
1515
}
1616

1717
return Ok(total)

0 commit comments

Comments
 (0)