From 1ad2a510cd2950c7b90ef4ad3447cf6dc9d18010 Mon Sep 17 00:00:00 2001 From: LLLL Colonq Date: Wed, 6 May 2026 21:47:23 -0400 Subject: Update scripting API --- Cargo.lock | 1 + crates/teleia/src/script.rs | 155 +++++++++++++++++++++++++++++++++++++++++++- flake.lock | 6 +- 3 files changed, 158 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9bb1f16..a5725b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2369,6 +2369,7 @@ dependencies = [ name = "teleia" version = "0.1.0" dependencies = [ + "ahash", "base64 0.22.1", "bimap", "bincode", diff --git a/crates/teleia/src/script.rs b/crates/teleia/src/script.rs index 0282f65..8e27f31 100644 --- a/crates/teleia/src/script.rs +++ b/crates/teleia/src/script.rs @@ -1,5 +1,158 @@ -use std::ffi::c_int; +use std::{ffi::c_int, mem::MaybeUninit}; + +use crate::utils; + +const NIL: Value = Value { val: PitValue { data: 0xfff4000000000000 } }; + +#[derive(Debug)] +pub struct Error { + pub msg: String +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "teleia script error: {}", self.msg) + } +} +impl std::error::Error for Error {} + +#[repr(C)] +#[derive(Debug, Clone, Copy)] +struct PitValue { data: u64 } + +#[repr(C)] +struct PitRuntime { _data: () } + +#[repr(C)] +struct PitLexer { + input: *const u8, + len: i64, + start: i64, end: i64, + line: i64, column: i64, + start_line: i64, start_column: i64, + error: *const u8, +} + +#[repr(C)] +struct PitParserTokenInfo { + token: c_int, + start: i64, end: i64, + line: i64, column: i64, +} + +#[repr(C)] +struct PitParser { + lexer: *mut PitLexer, + cur: PitParserTokenInfo, next: PitParserTokenInfo, +} unsafe extern "C" { pub fn pit_runtime_test(out: *mut u8, out_len: i64, buf: *mut u8, len: i64) -> c_int; + fn pit_runtime_new(buf: *mut MaybeUninit, len: i64) -> *mut PitRuntime; + fn pit_get_error(buf: *mut PitRuntime) -> PitValue; + fn pit_install_library_essential(buf: *mut PitRuntime); + fn pit_install_library_plist(buf: *mut PitRuntime); + fn pit_install_library_alist(buf: *mut PitRuntime); + fn pit_lex_bytes(ret: *mut PitLexer, buf: *const u8, len: i64); + fn pit_parser_from_lexer(ret: *mut PitParser, lex: *mut PitLexer); + fn pit_parse(rt: *mut PitRuntime, parser: *mut PitParser, eof: *mut bool) -> PitValue; + fn pit_eval(rt: *mut PitRuntime, v: PitValue) -> PitValue; + fn pit_dump(rt: *mut PitRuntime, buf: *mut u8, len: i64, v: PitValue, readable: bool) -> i64; + fn pit_eq(rt: *mut PitRuntime, x: PitValue, y: PitValue) -> bool; +} + +pub struct Runtime { + _buf: Box<[MaybeUninit]>, + rt: *mut PitRuntime, +} +impl Runtime { + pub fn new(sz: usize) -> Self { + let mut buf = Box::new_uninit_slice(sz); + let rt = unsafe { + pit_runtime_new((*buf).as_mut_ptr(), buf.len() as i64) + }; + unsafe { + pit_install_library_essential(rt); + pit_install_library_plist(rt); + pit_install_library_alist(rt); + } + Self { + _buf: buf, + rt, + } + } + pub fn error(&mut self) -> utils::Erm<()> { + let e = unsafe { pit_get_error(self.rt) }; + let ve = Value { val: e }; + if self.eq(ve, NIL) { return Ok(()) }; + Err(Error { msg: self.dump(ve).unwrap_or("".to_owned()) }.into()) + } + pub fn parse(&mut self, s: &str) -> utils::Erm { + let mut rt = Runtime::new(1024 * 1024 * 1024); + let lexer = Lexer::from_bytes(s.as_bytes()); + let mut parser = Parser::from_lexer(lexer); + let expr = parser.parse(&mut rt)?.ok_or(Error { msg: "end of file".to_string() })?; + let res = rt.eval(expr)?; + Ok(res) + } + pub fn eval(&mut self, v: Value) -> utils::Erm { + unsafe { + let ret = pit_eval(self.rt, v.val); + self.error()?; + Ok(Value { val: ret }) + } + } + pub fn dump(&mut self, v: Value) -> utils::Erm { + let mut buf = vec![0; 1024]; + unsafe { + let len = pit_dump(self.rt, buf.as_mut_ptr(), buf.len() as i64, v.val, false) as usize; + Ok(str::from_utf8(&buf[0..len]).map(|s| s.to_owned())?) + } + } + pub fn eq(&mut self, x: Value, y: Value) -> bool { + unsafe { pit_eq(self.rt, x.val, y.val) } + } +} + +pub struct Lexer { + lexer: Box, +} +impl Lexer { + pub fn from_bytes(bs: &[u8]) -> Self { + let mut lexer = Box::new_uninit(); + unsafe { + pit_lex_bytes(lexer.as_mut_ptr(), bs.as_ptr(), bs.len() as i64); + } + Self { lexer: unsafe { lexer.assume_init() } } + } +} + +pub struct Parser { + _lexer: Lexer, + parser: Box, +} +impl Parser { + pub fn from_lexer(mut lexer: Lexer) -> Self { + let mut parser = Box::new_uninit(); + unsafe { + pit_parser_from_lexer(parser.as_mut_ptr(), lexer.lexer.as_mut() as *mut _); + } + Self { + _lexer: lexer, + parser: unsafe { parser.assume_init() } + } + } + pub fn parse(&mut self, rt: &mut Runtime) -> utils::Erm> { + unsafe { + let mut eof = false; + let val = pit_parse(rt.rt, self.parser.as_mut() as *mut _, &mut eof); + rt.error()?; + if eof { return Ok(None) } + Ok(Some(Value { val })) + } + } +} + +#[derive(Debug, Clone, Copy)] +pub struct Value { + val: PitValue, } diff --git a/flake.lock b/flake.lock index 4bcf437..054ccf9 100644 --- a/flake.lock +++ b/flake.lock @@ -75,11 +75,11 @@ ] }, "locked": { - "lastModified": 1777329908, - "narHash": "sha256-UhRpKmDNj7chpHjaO+EpGBTyBnCpgntYp1fMyikbVyU=", + "lastModified": 1778114622, + "narHash": "sha256-bRTfd6+rs54j0LX4GIPUDo/liyVqZ75gNdM0A7+fQfI=", "owner": "lcolonq", "repo": "pit", - "rev": "7748d30575151af59844f43a0e9149b18c40f2f1", + "rev": "cbe112aa52a7ff84935163c442714e49057b2da6", "type": "github" }, "original": { -- cgit v1.2.3