Skip to content

Commit 018d94e

Browse files
committed
Add runnable take consume hooks
1 parent 908a207 commit 018d94e

10 files changed

Lines changed: 108 additions & 7 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ If a lowered package contains `fn main() -> Unit` or `fn main() -> Result<Unit,
418418

419419
`rss verify-rust <file.rss> --out-dir <directory>` keeps the generated package used for backend checking, including `rsscript-source-map.json`, so unmappable rustc diagnostics can be inspected against the generated Rust.
420420

421-
The first observable runtime boundaries are `Log.write(message: read String)`, `Assert.equal(left: read String, right: read String)`, and the core `File`, `Json`, `Csv`, `Image`, `ImageCache`, HTTP handler, DB resource-pool, config reload, interpreter object-cycle, and `Counter` APIs, which lower to explicit runtime hooks. `ImageCache` is the first small retained managed-container hook: it stores managed image handles and enforces a capacity limit. The interpreter hooks model `Environment` and `FunctionObject` as managed handles, including an environment/function closure cycle. Simple core operations such as `String.concat(left: read String, right: read String)` keep RSScript `.rssi` signatures for checking and review, but lower directly to Rust standard-library expressions. Built-in boolean literals, numeric operators, comparison operators, `Option<T>` constructors, and core surface types such as `Bytes`, `Buffer`, `Path`, `List<T>`, `Map<K,V>`, and `Set<T>` lower to the corresponding Rust literals, operators, enum constructors, and standard-library types; user-defined operator overloading remains forbidden.
421+
The first observable runtime boundaries are `Log.write(message: read String)`, `Assert.equal(left: read String, right: read String)`, `OS.close(fd: Fd)`, `List.consume(list: take List<T>)`, `Buffer.consume(buffer: take Buffer)`, and the core `File`, `Json`, `Csv`, `Image`, `ImageCache`, HTTP handler, DB resource-pool, config reload, interpreter object-cycle, and `Counter` APIs, which lower to explicit runtime hooks. `ImageCache` is the first small retained managed-container hook: it stores managed image handles and enforces a capacity limit. The interpreter hooks model `Environment` and `FunctionObject` as managed handles, including an environment/function closure cycle. Simple core operations such as `String.concat(left: read String, right: read String)` keep RSScript `.rssi` signatures for checking and review, but lower directly to Rust standard-library expressions. Built-in boolean literals, numeric operators, comparison operators, `Option<T>` constructors, and core surface types such as `Bytes`, `Buffer`, `Path`, `List<T>`, `Map<K,V>`, and `Set<T>` lower to the corresponding Rust literals, operators, enum constructors, and standard-library types; user-defined operator overloading remains forbidden.
422422

423423
Smallest runnable example:
424424

core/collections/buffer.rssi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub fn Buffer.consume(buffer: take Buffer) -> Unit

core/collections/list.rssi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub fn List.consume<T>(list: take List<T>) -> Unit

core/os/os.rssi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub fn OS.close(fd: Fd) -> Unit

core/prototype/builtins.rssi

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
pub fn OS.close(fd: Fd) -> Unit
2-
3-
pub fn List.consume(list: take List) -> Unit
4-
5-
pub fn Buffer.consume(buffer: take Buffer) -> Unit
6-
71
pub fn RuleLoader.load_rules(path: read Path) -> Result<fresh List<Rule>, ConfigError>
82

93
pub fn GlobalConfig.replace(

examples/buffer_consume.rss

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
features: local
2+
3+
fn main() -> Result<Unit, FileError> {
4+
let path = "rsscript-buffer-consume.txt"
5+
6+
with File.open_write(path: read path) as file {
7+
File.write(file: mut file, data: read "consume buffer")?
8+
}
9+
10+
with File.open_read(path: read path) as file {
11+
local bytes = File.read_all(file: mut file)?
12+
Buffer.consume(buffer: take bytes)
13+
}
14+
15+
OS.close(fd: 0)
16+
Log.write(message: read "buffer consumed")
17+
return Ok(Unit)
18+
}

runtime/src/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,18 @@ pub fn file_write<B: RuntimeBytes + ?Sized>(file: &mut File, data: &B) -> std::i
355355
file.inner.write_all(data.as_bytes_slice())
356356
}
357357

358+
pub fn os_close(fd: i64) {
359+
let _ = fd;
360+
}
361+
362+
pub fn list_consume<T>(list: Vec<T>) {
363+
drop(list);
364+
}
365+
366+
pub fn buffer_consume(buffer: Vec<u8>) {
367+
drop(buffer);
368+
}
369+
358370
pub fn request_new(path: &str) -> Request {
359371
Request {
360372
path: path.to_string(),
@@ -1049,6 +1061,13 @@ mod tests {
10491061
assert_eq!(super::counter_value(&counter), 3);
10501062
}
10511063

1064+
#[test]
1065+
fn consume_runtime_hooks_take_collections() {
1066+
super::list_consume(vec![1_i64, 2, 3]);
1067+
super::buffer_consume(b"bytes".to_vec());
1068+
super::os_close(0);
1069+
}
1070+
10521071
#[test]
10531072
fn interpreter_runtime_hooks_link_environment_function_cycle() {
10541073
let root = super::manage(super::environment_root());

src/interfaces.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ pub(crate) const CORE_INTERFACES: &[(&str, &str)] = &[
33
"core/cache/image_cache.rssi",
44
include_str!("../core/cache/image_cache.rssi"),
55
),
6+
(
7+
"core/collections/buffer.rssi",
8+
include_str!("../core/collections/buffer.rssi"),
9+
),
10+
(
11+
"core/collections/list.rssi",
12+
include_str!("../core/collections/list.rssi"),
13+
),
614
(
715
"core/collections/map.rssi",
816
include_str!("../core/collections/map.rssi"),
@@ -35,6 +43,7 @@ pub(crate) const CORE_INTERFACES: &[(&str, &str)] = &[
3543
include_str!("../core/json/json.rssi"),
3644
),
3745
("core/log/log.rssi", include_str!("../core/log/log.rssi")),
46+
("core/os/os.rssi", include_str!("../core/os/os.rssi")),
3847
(
3948
"core/resource/resource_pool.rssi",
4049
include_str!("../core/resource/resource_pool.rssi"),

src/rust_lower.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,11 @@ fn lower_callee(callee: &Callee) -> String {
11851185
match callee {
11861186
callee if is_log_write_callee(callee) => "rsscript_runtime::log_write".to_string(),
11871187
callee if is_assert_equal_callee(callee) => "rsscript_runtime::assert_equal".to_string(),
1188+
callee if is_os_close_callee(callee) => "rsscript_runtime::os_close".to_string(),
1189+
callee if is_list_consume_callee(callee) => "rsscript_runtime::list_consume".to_string(),
1190+
callee if is_buffer_consume_callee(callee) => {
1191+
"rsscript_runtime::buffer_consume".to_string()
1192+
}
11881193
callee if is_file_open_callee(callee) => "rsscript_runtime::file_open".to_string(),
11891194
callee if is_file_open_read_callee(callee) => {
11901195
"rsscript_runtime::file_open_read".to_string()
@@ -1291,6 +1296,18 @@ fn is_assert_equal_callee(callee: &Callee) -> bool {
12911296
matches!(callee, Callee::Qualified { namespace, name } if type_root_name(namespace) == "Assert" && name == "equal")
12921297
}
12931298

1299+
fn is_os_close_callee(callee: &Callee) -> bool {
1300+
matches!(callee, Callee::Qualified { namespace, name } if type_root_name(namespace) == "OS" && name == "close")
1301+
}
1302+
1303+
fn is_list_consume_callee(callee: &Callee) -> bool {
1304+
matches!(callee, Callee::Qualified { namespace, name } if type_root_name(namespace) == "List" && name == "consume")
1305+
}
1306+
1307+
fn is_buffer_consume_callee(callee: &Callee) -> bool {
1308+
matches!(callee, Callee::Qualified { namespace, name } if type_root_name(namespace) == "Buffer" && name == "consume")
1309+
}
1310+
12941311
fn is_string_concat_callee(callee: &Callee) -> bool {
12951312
matches!(callee, Callee::Qualified { namespace, name } if type_root_name(namespace) == "String" && name == "concat")
12961313
}

tests/checker.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,21 @@ fn bundled_core_interfaces_are_available_to_checker() {
8787
.iter()
8888
.any(|(path, _)| *path == "core/log/log.rssi")
8989
);
90+
assert!(
91+
core_interfaces()
92+
.iter()
93+
.any(|(path, _)| *path == "core/collections/buffer.rssi")
94+
);
95+
assert!(
96+
core_interfaces()
97+
.iter()
98+
.any(|(path, _)| *path == "core/collections/list.rssi")
99+
);
100+
assert!(
101+
core_interfaces()
102+
.iter()
103+
.any(|(path, _)| *path == "core/os/os.rssi")
104+
);
90105
assert!(
91106
core_interfaces()
92107
.iter()
@@ -326,6 +341,32 @@ pub fn inspect_core(
326341
assert!(rust.contains("-> Result<Vec<u8>, CoreError>"));
327342
}
328343

344+
#[test]
345+
fn rust_lowering_maps_take_consume_core_calls_to_runtime_hooks() {
346+
let source = r#"
347+
features: local
348+
349+
fn close_fd() -> Unit {
350+
OS.close(fd: 0)
351+
}
352+
353+
fn consume_list(list: take List<Int>) -> Unit {
354+
List.consume(list: take list)
355+
}
356+
357+
fn consume_buffer(buffer: take Buffer) -> Unit {
358+
Buffer.consume(buffer: take buffer)
359+
}
360+
"#;
361+
let rust = lower_source_to_rust("consume.rss", source).expect("source should lower");
362+
363+
assert!(rust.contains("rsscript_runtime::os_close(0);"));
364+
assert!(rust.contains("fn consume_list(list: Vec<i64>)"));
365+
assert!(rust.contains("rsscript_runtime::list_consume(list);"));
366+
assert!(rust.contains("fn consume_buffer(buffer: Vec<u8>)"));
367+
assert!(rust.contains("rsscript_runtime::buffer_consume(buffer);"));
368+
}
369+
329370
#[test]
330371
fn rust_lowering_maps_file_core_calls_to_runtime_hooks() {
331372
let source = r#"

0 commit comments

Comments
 (0)