lex_hello worked for a second just now

this is just a backup however
This commit is contained in:
2025-02-02 10:20:03 +01:00
parent 2b79e96dc9
commit 1556d54226
45 changed files with 646 additions and 371 deletions

View File

@@ -4,6 +4,9 @@ version = "0.1.0"
edition = "2021"
[dependencies]
async-once-cell = "0.5.4"
async-std = "1.13.0"
futures = "0.3.31"
itertools = "0.14.0"
never = "0.1.0"
once_cell = "1.20.2"
@@ -13,3 +16,4 @@ orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" }
orchid-base = { version = "0.1.0", path = "../orchid-base" }
orchid-extension = { version = "0.1.0", path = "../orchid-extension" }
ordered-float = "4.6.0"
tokio = { version = "1.43.0", features = ["full"] }

View File

@@ -1,4 +1,16 @@
use orchid_extension::entrypoint::ExtensionData;
use orchid_std::StdSystem;
use std::mem;
use std::rc::Rc;
pub fn main() { ExtensionData::new("orchid-std::main", &[&StdSystem]).main() }
use orchid_extension::entrypoint::{ExtensionData, extension_main_logic};
use orchid_std::StdSystem;
use tokio::task::{LocalSet, spawn_local};
#[tokio::main(flavor = "current_thread")]
pub async fn main() {
LocalSet::new()
.run_until(async {
let data = ExtensionData::new("orchid-std::main", &[&StdSystem]);
extension_main_logic(data, Rc::new(|fut| mem::drop(spawn_local(fut)))).await;
})
.await
}

View File

@@ -1,6 +1,8 @@
use orchid_api_derive::Coding;
use orchid_base::error::OrcRes;
use orchid_extension::atom::{AtomFactory, Atomic, AtomicFeatures, MethodSetBuilder, ToAtom, TypAtom};
use orchid_extension::atom::{
AtomFactory, Atomic, AtomicFeatures, MethodSetBuilder, ToAtom, TypAtom,
};
use orchid_extension::atom_thin::{ThinAtom, ThinVariant};
use orchid_extension::conv::TryFromExpr;
use orchid_extension::expr::Expr;
@@ -15,8 +17,8 @@ impl Atomic for Int {
}
impl ThinAtom for Int {}
impl TryFromExpr for Int {
fn try_from_expr(expr: Expr) -> OrcRes<Self> {
TypAtom::<Int>::try_from_expr(expr).map(|t| t.value)
async fn try_from_expr(expr: Expr) -> OrcRes<Self> {
TypAtom::<Int>::try_from_expr(expr).await.map(|t| t.value)
}
}
@@ -29,8 +31,8 @@ impl Atomic for Float {
}
impl ThinAtom for Float {}
impl TryFromExpr for Float {
fn try_from_expr(expr: Expr) -> OrcRes<Self> {
TypAtom::<Float>::try_from_expr(expr).map(|t| t.value)
async fn try_from_expr(expr: Expr) -> OrcRes<Self> {
TypAtom::<Float>::try_from_expr(expr).await.map(|t| t.value)
}
}
@@ -39,10 +41,11 @@ pub enum Numeric {
Float(NotNan<f64>),
}
impl TryFromExpr for Numeric {
fn try_from_expr(expr: Expr) -> OrcRes<Self> {
Int::try_from_expr(expr.clone())
.map(|t| Numeric::Int(t.0))
.or_else(|e| Float::try_from_expr(expr).map(|t| Numeric::Float(t.0)).map_err(|e2| e + e2))
async fn try_from_expr(expr: Expr) -> OrcRes<Self> {
match Int::try_from_expr(expr.clone()).await {
Ok(t) => Ok(Numeric::Int(t.0)),
Err(e) => Float::try_from_expr(expr).await.map(|t| Numeric::Float(t.0)).map_err(|e2| e + e2),
}
}
}
impl ToAtom for Numeric {

View File

@@ -13,14 +13,14 @@ use super::num_atom::{Float, Int};
pub struct NumLexer;
impl Lexer for NumLexer {
const CHAR_FILTER: &'static [RangeInclusive<char>] = &['0'..='9'];
fn lex<'a>(all: &'a str, ctx: &'a LexContext<'a>) -> OrcRes<(&'a str, GenTokTree<'a>)> {
async fn lex<'a>(all: &'a str, ctx: &'a LexContext<'a>) -> OrcRes<(&'a str, GenTokTree<'a>)> {
let ends_at = all.find(|c: char| !c.is_ascii_hexdigit() && !"xX._pP".contains(c));
let (chars, tail) = all.split_at(ends_at.unwrap_or(all.len()));
let fac = match parse_num(chars) {
Ok(Numeric::Float(f)) => Float(f).factory(),
Ok(Numeric::Uint(uint)) => Int(uint.try_into().unwrap()).factory(),
Ok(Numeric::Decimal(dec)) => Float(NotNan::new(dec.try_into().unwrap()).unwrap()).factory(),
Err(e) => return Err(num_to_err(e, ctx.pos(all)).into()),
Err(e) => return Err(num_to_err(e, ctx.pos(all), ctx.i).await.into()),
};
Ok((tail, GenTok::X(fac).at(ctx.pos(all)..ctx.pos(tail))))
}

View File

@@ -1,7 +1,7 @@
use std::sync::Arc;
use std::rc::Rc;
use never::Never;
use orchid_base::interner::Tok;
use orchid_base::reqnot::Receipt;
use orchid_extension::atom::{AtomDynfo, AtomicFeatures};
use orchid_extension::entrypoint::ExtReq;
use orchid_extension::fs::DeclFs;
@@ -31,15 +31,15 @@ impl SystemCard for StdSystem {
}
}
impl System for StdSystem {
fn request(_: ExtReq, req: Self::Req) -> orchid_base::reqnot::Receipt { match req {} }
async fn request(_: ExtReq<'_>, req: Self::Req) -> Receipt<'_> { match req {} }
fn lexers() -> Vec<orchid_extension::lexer::LexerObj> { vec![&StringLexer] }
fn parsers() -> Vec<orchid_extension::parser::ParserObj> { vec![] }
fn vfs() -> DeclFs { DeclFs::Mod(&[]) }
fn env() -> Vec<(Tok<String>, MemKind)> {
fn env() -> Vec<(String, MemKind)> {
vec![root_mod("std", [], [module(true, "string", [], [comments(
["Concatenate two strings"],
fun(true, "concat", |left: OrcString, right: OrcString| {
StrAtom::new(Arc::new(left.get_string().to_string() + &right.get_string()))
fun(true, "concat", |left: OrcString<'static>, right: OrcString<'static>| async move {
StrAtom::new(Rc::new(left.get_string().await.to_string() + &right.get_string().await))
}),
)])])]
}

View File

@@ -1,43 +1,42 @@
use std::borrow::Cow;
use std::io;
use std::ops::Deref;
use std::sync::Arc;
use std::pin::Pin;
use std::rc::Rc;
use async_std::io::Write;
use orchid_api_derive::Coding;
use orchid_api_traits::{Encode, Request};
use orchid_base::error::{OrcRes, mk_errv};
use orchid_base::intern;
use orchid_base::interner::{Tok, intern};
use orchid_base::interner::Tok;
use orchid_extension::atom::{AtomMethod, Atomic, MethodSetBuilder, Supports, TypAtom};
use orchid_extension::atom_owned::{DeserializeCtx, OwnedAtom, OwnedVariant};
use orchid_extension::conv::TryFromExpr;
use orchid_extension::expr::Expr;
use orchid_extension::system::SysCtx;
#[derive(Copy, Clone, Coding)]
#[derive(Copy, Clone, Debug, Coding)]
pub struct StringGetVal;
impl Request for StringGetVal {
type Response = Arc<String>;
type Response = Rc<String>;
}
impl AtomMethod for StringGetVal {
const NAME: &str = "std::string_get_val";
}
impl Supports<StringGetVal> for StrAtom {
fn handle(&self, _: SysCtx, _: StringGetVal) -> <StringGetVal as Request>::Response {
async fn handle(&self, _: SysCtx, _: StringGetVal) -> <StringGetVal as Request>::Response {
self.0.clone()
}
}
#[derive(Clone)]
pub struct StrAtom(Arc<String>);
pub struct StrAtom(Rc<String>);
impl Atomic for StrAtom {
type Variant = OwnedVariant;
type Data = ();
fn reg_reqs() -> MethodSetBuilder<Self> { MethodSetBuilder::new().handle::<StringGetVal>() }
}
impl StrAtom {
pub fn new(str: Arc<String>) -> Self { Self(str) }
pub fn value(&self) -> Arc<String> { self.0.clone() }
pub fn new(str: Rc<String>) -> Self { Self(str) }
}
impl Deref for StrAtom {
type Target = str;
@@ -45,12 +44,12 @@ impl Deref for StrAtom {
}
impl OwnedAtom for StrAtom {
type Refs = ();
fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
fn serialize(&self, _: SysCtx, sink: &mut (impl io::Write + ?Sized)) -> Self::Refs {
self.deref().encode(sink)
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
async fn serialize(&self, _: SysCtx, sink: Pin<&mut (impl Write + ?Sized)>) -> Self::Refs {
self.deref().encode(sink).await
}
fn deserialize(mut ctx: impl DeserializeCtx, _: Self::Refs) -> Self {
Self::new(Arc::new(ctx.read::<String>()))
async fn deserialize(mut ctx: impl DeserializeCtx, _: Self::Refs) -> Self {
Self::new(Rc::new(ctx.read::<String>().await))
}
}
@@ -66,34 +65,46 @@ impl From<Tok<String>> for IntStrAtom {
}
impl OwnedAtom for IntStrAtom {
type Refs = ();
fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(self.0.to_api()) }
fn print(&self, _ctx: SysCtx) -> String { format!("{:?}i", *self.0) }
fn serialize(&self, _: SysCtx, write: &mut (impl io::Write + ?Sized)) { self.0.encode(write) }
fn deserialize(ctx: impl DeserializeCtx, _: ()) -> Self { Self(intern(&ctx.decode::<String>())) }
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(self.0.to_api()) }
async fn print(&self, _ctx: SysCtx) -> String { format!("{:?}i", *self.0) }
async fn serialize(&self, _: SysCtx, write: Pin<&mut (impl Write + ?Sized)>) {
self.0.encode(write).await
}
async fn deserialize(mut ctx: impl DeserializeCtx, _: ()) -> Self {
let s = ctx.decode::<String>().await;
Self(ctx.sys().i.i(&s).await)
}
}
#[derive(Clone)]
pub enum OrcString<'a> {
pub struct OrcString<'a> {
kind: OrcStringKind<'a>,
ctx: SysCtx,
}
#[derive(Clone)]
pub enum OrcStringKind<'a> {
Val(TypAtom<'a, StrAtom>),
Int(TypAtom<'a, IntStrAtom>),
}
impl OrcString<'_> {
pub fn get_string(&self) -> Arc<String> {
match &self {
Self::Int(tok) => Tok::from_api(tok.value).arc(),
Self::Val(atom) => atom.request(StringGetVal),
pub async fn get_string(&self) -> Rc<String> {
match &self.kind {
OrcStringKind::Int(tok) => self.ctx.i.ex(**tok).await.rc(),
OrcStringKind::Val(atom) => atom.request(StringGetVal).await,
}
}
}
impl TryFromExpr for OrcString<'static> {
fn try_from_expr(expr: Expr) -> OrcRes<OrcString<'static>> {
if let Ok(v) = TypAtom::<StrAtom>::try_from_expr(expr.clone()) {
return Ok(OrcString::Val(v));
async fn try_from_expr(expr: Expr) -> OrcRes<OrcString<'static>> {
if let Ok(v) = TypAtom::<StrAtom>::try_from_expr(expr.clone()).await {
return Ok(OrcString { ctx: expr.ctx(), kind: OrcStringKind::Val(v) });
}
match TypAtom::<IntStrAtom>::try_from_expr(expr) {
Ok(t) => Ok(OrcString::Int(t)),
Err(e) => Err(mk_errv(intern!(str: "A string was expected"), "", e.pos_iter())),
let ctx = expr.ctx();
match TypAtom::<IntStrAtom>::try_from_expr(expr).await {
Ok(t) => Ok(OrcString { ctx: t.data.ctx(), kind: OrcStringKind::Int(t) }),
Err(e) => Err(mk_errv(ctx.i.i("A string was expected").await, "", e.pos_iter())),
}
}
}

View File

@@ -1,9 +1,9 @@
use itertools::Itertools;
use orchid_base::error::{OrcErr, OrcRes, mk_err, mk_errv};
use orchid_base::interner::intern;
use orchid_base::interner::Interner;
use orchid_base::location::Pos;
use orchid_base::tree::{vname_tv, wrap_tokv};
use orchid_base::{intern, vname};
use orchid_base::vname;
use orchid_extension::atom::AtomicFeatures;
use orchid_extension::lexer::{LexContext, Lexer, err_not_applicable};
use orchid_extension::tree::{GenTok, GenTokTree};
@@ -32,10 +32,10 @@ struct StringError {
impl StringError {
/// Convert into project error for reporting
pub fn into_proj(self, pos: u32) -> OrcErr {
pub async fn into_proj(self, pos: u32, i: &Interner) -> OrcErr {
let start = pos + self.pos;
mk_err(
intern!(str: "Failed to parse string"),
i.i("Failed to parse string").await,
match self.kind {
StringErrorKind::NotHex => "Expected a hex digit",
StringErrorKind::BadCodePoint => "The specified number is not a Unicode code point",
@@ -95,29 +95,40 @@ fn parse_string(str: &str) -> Result<String, StringError> {
pub struct StringLexer;
impl Lexer for StringLexer {
const CHAR_FILTER: &'static [std::ops::RangeInclusive<char>] = &['"'..='"'];
fn lex<'a>(all: &'a str, ctx: &'a LexContext<'a>) -> OrcRes<(&'a str, GenTokTree<'a>)> {
let mut tail = all.strip_prefix('"').ok_or_else(err_not_applicable)?;
let mut ret = GenTok::X(IntStrAtom::from(intern!(str: "")).factory()).at(ctx.tok_ran(0, all));
async fn lex<'a>(all: &'a str, ctx: &'a LexContext<'a>) -> OrcRes<(&'a str, GenTokTree<'a>)> {
let Some(mut tail) = all.strip_prefix('"') else {
return Err(err_not_applicable(ctx.i).await.into());
};
let mut ret = GenTok::X(IntStrAtom::from(ctx.i.i("").await).factory()).at(ctx.tok_ran(0, all));
let mut cur = String::new();
let mut errors = vec![];
let str_to_gen = |str: &mut String, tail: &str, err: &mut Vec<OrcErr>| {
let str_val = parse_string(&str.split_off(0))
.inspect_err(|e| err.push(e.clone().into_proj(ctx.pos(tail) - str.len() as u32)))
.unwrap_or_default();
GenTok::X(IntStrAtom::from(intern(&*str_val)).factory())
.at(ctx.tok_ran(str.len() as u32, tail))
};
let add_frag = |prev: GenTokTree<'a>, new: GenTokTree<'a>| {
wrap_tokv(vname_tv(&vname!(std::string::concat), new.range.end).chain([prev, new]))
async fn str_to_gen<'a>(
str: &mut String,
tail: &str,
err: &mut Vec<OrcErr>,
ctx: &'a LexContext<'a>,
) -> GenTokTree<'a> {
let str_val_res = parse_string(&str.split_off(0));
if let Err(e) = &str_val_res {
err.push(e.clone().into_proj(ctx.pos(tail) - str.len() as u32, ctx.i).await);
}
let str_val = str_val_res.unwrap_or_default();
GenTok::X(IntStrAtom::from(ctx.i.i(&*str_val).await).factory())
.at(ctx.tok_ran(str.len() as u32, tail)) as GenTokTree<'a>
}
let add_frag = |prev: GenTokTree<'a>, new: GenTokTree<'a>| async {
wrap_tokv(
vname_tv(&vname!(std::string::concat; ctx.i).await, new.range.end).chain([prev, new]),
)
};
loop {
if let Some(rest) = tail.strip_prefix('"') {
return Ok((rest, add_frag(ret, str_to_gen(&mut cur, tail, &mut errors))));
return Ok((rest, add_frag(ret, str_to_gen(&mut cur, tail, &mut errors, ctx).await).await));
} else if let Some(rest) = tail.strip_prefix('$') {
ret = add_frag(ret, str_to_gen(&mut cur, tail, &mut errors));
let (new_tail, tree) = ctx.recurse(rest)?;
ret = add_frag(ret, str_to_gen(&mut cur, tail, &mut errors, ctx).await).await;
let (new_tail, tree) = ctx.recurse(rest).await?;
tail = new_tail;
ret = add_frag(ret, tree);
ret = add_frag(ret, tree).await;
} else if tail.starts_with('\\') {
// parse_string will deal with it, we just have to skip the next char
tail = &tail[2..];
@@ -128,9 +139,11 @@ impl Lexer for StringLexer {
tail = ch.as_str();
} else {
let range = ctx.pos(all)..ctx.pos("");
return Err(mk_errv(intern!(str: "No string end"), "String never terminated with \"", [
Pos::Range(range.clone()).into(),
]));
return Err(mk_errv(
ctx.i.i("No string end").await,
"String never terminated with \"",
[Pos::Range(range.clone()).into()],
));
}
}
}