r/o

0ff46104c25d0d43393c0d54294453f150350264 parent 6d011b62

authored by Asherah Connor <ashe@kivikakk.ee> 3 weeks ago
committed by Asherah Connor <ashe@kivikakk.ee> 3 weeks ago

hm!

1.chr | 15 ++++----
com/src/codegen.rs | 36 +++++--------------
com/src/parser.rs | 104 +++++++++++++++++++++++++++++++-----------------------
run/src/lib.rs | 31 +++++++++-------
6 files changed, 101 insertions(+), 88 deletions(-)
diff --git a/1.chr b/1.chr
index 02d73bb..813c454 100644
--- a/1.chr
+++ b/1.chr
@@ -1,16 +1,19 @@
-to Cat with dog
+to Cat with dog and dog2
say "Meow"
+ say "telling dog ronronarr!"
tell dog "ronronarrrrrr"
+ say "telling dog2 yippee!"
+ tell dog2 "yippee"
end
-to Dog
- say "Woof"
- say listen
+to Dog with name
+ say "Woof from ", name, ": ", listen
end
to main
- dog: start Dog
- start Cat w/ dog
+ dog: start Dog with "dog"
+ dogga: start Dog with "dogga"
+ start Cat w/ dog and dogga
end
diff --git a/com/src/ast.rs b/com/src/ast.rs
index d9e9d04..a1a0699 100644
--- a/com/src/ast.rs
+++ b/com/src/ast.rs
@@ -11,7 +11,7 @@ pub enum Top {
#[derive(Debug)]
pub enum Stmt {
- Say(Expr),
+ Say(Vec<Expr>),
Assign(LocalName, Expr),
Tell(LocalName, Expr),
Expr(Expr),
diff --git a/com/src/codegen.rs b/com/src/codegen.rs
index 550ba10..25a7381 100644
--- a/com/src/codegen.rs
+++ b/com/src/codegen.rs
@@ -3,27 +3,12 @@ use qbe::*;
use crate::ast;
pub fn gene(tops: &[ast::Top]) -> Module<'_> {
- let mut module = Module::new();
-
- module.add_data(DataDef::new(
- Linkage::private(),
- "idk".to_string(),
- None,
- vec![
- (Type::Byte, DataItem::Str("idk".to_string())),
- (Type::Byte, DataItem::Const(0)),
- ],
- ));
-
- let mut g = Gene::new(module);
+ let mut g = Gene::new(Module::new());
for top in tops {
g.top(top);
}
- let module = g.module();
- eprintln!("{:?}", module);
-
- module
+ g.module()
}
struct Gene<'a> {
@@ -86,14 +71,15 @@ impl<'a> Gene<'a> {
fn stmt(&mut self, func: &mut Function<'a>, stmt: &ast::Stmt) {
match stmt {
- ast::Stmt::Say(expr) => {
- let value = self.expr(func, expr);
- func.assign_instr(Value::Temporary("_v".into()), Type::Long, value);
- func.add_instr(Instr::Call(
- "char_puts".into(),
- vec![(Type::Long, Value::Temporary("_v".into()))],
- None,
- ));
+ ast::Stmt::Say(exprs) => {
+ let mut ax = vec![(Type::Word, Value::Const(exprs.len() as u64))];
+ for (ix, a) in exprs.iter().enumerate() {
+ let n = format!("_s{ix}");
+ let instr = self.expr(func, a);
+ func.assign_instr(Value::Temporary(n.clone()), Type::Long, instr);
+ ax.push((Type::Long, Value::Temporary(n)));
+ }
+ func.add_instr(Instr::Call("char_puts".into(), ax, Some(1)));
}
ast::Stmt::Assign(ast::LocalName(name), expr) => {
let value = self.expr(func, expr);
diff --git a/com/src/main.rs b/com/src/main.rs
index fe82958..88878c8 100644
--- a/com/src/main.rs
+++ b/com/src/main.rs
@@ -15,7 +15,6 @@ fn main() -> Result<()> {
let Ok(tops) = parser::parse(&input) else {
std::process::exit(1);
};
- eprintln!("{tops:?}");
let module = codegen::gene(&tops);
if let Some(output_filename) = output_filename {
diff --git a/com/src/parser.rs b/com/src/parser.rs
index 62d9179..64d5c5e 100644
--- a/com/src/parser.rs
+++ b/com/src/parser.rs
@@ -13,6 +13,8 @@ use nom_language::error::{VerboseError, convert_error};
use crate::ast;
+type IR<'i, O, E> = IResult<&'i str, O, E>;
+
pub fn parse(input: &str) -> Result<Vec<ast::Top>> {
match many0(top::<VerboseError<&str>>).parse(input) {
Ok((leftover_input, tops)) => {
@@ -25,7 +27,7 @@ pub fn parse(input: &str) -> Result<Vec<ast::Top>> {
Ok(tops)
}
Err(Err::Error(e)) | Err(Err::Failure(e)) => {
- eprintln!("ERR: {e:?}");
+ eprintln!("Parse error!");
eprintln!("{}", convert_error(input, e));
Err(anyhow!("oh no"))
}
@@ -33,11 +35,11 @@ pub fn parse(input: &str) -> Result<Vec<ast::Top>> {
}
}
-fn top<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, ast::Top, E> {
+fn top<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, ast::Top, E> {
top_to(i)
}
-fn top_to<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, ast::Top, E> {
+fn top_to<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, ast::Top, E> {
let (i, (name, args)) = preceded(
top_to_start,
cut(terminated(
@@ -55,7 +57,7 @@ fn top_to<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, ast::Top,
Ok((i, ast::Top::To(name, args.unwrap_or_default(), stmts)))
}
-fn top_to_start<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, (), E> {
+fn top_to_start<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, (), E> {
let (i, _) = ws(i)?;
let (i, _) = tag("to")(i)?;
let (i, _) = space1(i)?;
@@ -63,29 +65,31 @@ fn top_to_start<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, (),
Ok((i, ()))
}
-fn arg_separator<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, (), E> {
- let (i, _) = space1(i)?;
- let (i, _) = tag("and")(i)?;
- let (i, _) = space1(i)?;
+fn arg_separator<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, (), E> {
+ let (i, _) = alt((
+ delimited(space1, tag("and"), space1),
+ delimited(space0, tag(","), space0),
+ ))
+ .parse(i)?;
Ok((i, ()))
}
-fn stmt<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, ast::Stmt, E> {
+fn stmt<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, ast::Stmt, E> {
alt((stmt_say, stmt_assign, stmt_tell, stmt_expr)).parse(i)
}
-fn stmt_say<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, ast::Stmt, E> {
+fn stmt_say<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, ast::Stmt, E> {
let (i, _) = ws(i)?;
let (i, _) = tag("say")(i)?;
let (i, _) = space1(i)?;
- let (i, expr) = expr(i)?;
+ let (i, params) = params(i)?;
let (i, _) = eol(i)?;
- Ok((i, ast::Stmt::Say(expr)))
+ Ok((i, ast::Stmt::Say(params)))
}
-fn stmt_assign<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, ast::Stmt, E> {
+fn stmt_assign<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, ast::Stmt, E> {
let (i, name) = delimited(ws, alphanumeric1, char(':')).parse(i)?;
let (i, _) = space0(i)?;
let (i, expr) = cut(terminated(expr, eol)).parse(i)?;
@@ -93,7 +97,7 @@ fn stmt_assign<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, ast::
Ok((i, ast::Stmt::Assign(ast::LocalName(name.to_string()), expr)))
}
-fn stmt_tell<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, ast::Stmt, E> {
+fn stmt_tell<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, ast::Stmt, E> {
let (i, _) = ws(i)?;
let (i, _) = tag("tell")(i)?;
let (i, _) = space1(i)?;
@@ -105,7 +109,7 @@ fn stmt_tell<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, ast::St
Ok((i, ast::Stmt::Tell(ast::LocalName(name.to_string()), expr)))
}
-fn stmt_expr<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, ast::Stmt, E> {
+fn stmt_expr<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, ast::Stmt, E> {
let (i, _) = ws(i)?;
let (i, expr) = expr(i)?;
let (i, _) = eol(i)?;
@@ -113,53 +117,67 @@ fn stmt_expr<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, ast::St
Ok((i, ast::Stmt::Expr(expr)))
}
-fn expr<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, ast::Expr, E> {
- alt((expr_imm_string, expr_start, expr_listen)).parse(i)
+fn expr<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, ast::Expr, E> {
+ alt((expr_imm_string, expr_start, expr_listen, expr_local)).parse(i)
}
-fn expr_imm_string<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, ast::Expr, E> {
+fn expr_imm_string<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, ast::Expr, E> {
let (i, chars) = delimited(char('"'), take_till(|b| b == '"'), char('"')).parse(i)?;
Ok((i, ast::Expr::ImmString(chars.to_string())))
}
-fn expr_start<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, ast::Expr, E> {
+fn expr_start<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, ast::Expr, E> {
let (i, _) = tag("start")(i)?;
let (i, _) = space1(i)?;
let (i, to_name) = map(alphanumeric1, |n: &str| ast::ToName(n.to_string())).parse(i)?;
- let (i, args) = cut(opt(map(args, |a| {
- a.into_iter().map(ast::Expr::Local).collect::<Vec<_>>()
- })))
- .parse(i)?;
+ let (i, params) = cut(opt(with(params))).parse(i)?;
- Ok((i, ast::Expr::Start(to_name, args.unwrap_or_default())))
+ Ok((i, ast::Expr::Start(to_name, params.unwrap_or_default())))
}
-fn expr_listen<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, ast::Expr, E> {
+fn expr_listen<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, ast::Expr, E> {
let (i, _) = tag("listen")(i)?;
Ok((i, ast::Expr::Listen))
}
+fn expr_local<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, ast::Expr, E> {
+ map(alphanumeric1, |n: &str| {
+ ast::Expr::Local(ast::LocalName(n.to_string()))
+ })
+ .parse(i)
+}
+
// misc
-fn args<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, Vec<ast::LocalName>, E> {
- preceded(
- space1,
- preceded(
- alt((tag("with"), tag("w/"))),
- preceded(
- space1,
- cut(map(separated_list1(arg_separator, alphanumeric1), |sx| {
- sx.into_iter()
- .map(|s| ast::LocalName(s.to_string()))
- .collect()
- })),
- ),
- ),
- )
+fn with<'i, O, E: ParseError<&'i str>, F>(f: F) -> impl Parser<&'i str, Output = O, Error = E>
+where
+ F: Parser<&'i str, Output = O, Error = E>,
+{
+ preceded(with_prefix, cut(f))
+}
+
+fn with_prefix<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, (), E> {
+ let (i, _) = preceded(space1, preceded(alt((tag("with"), tag("w/"))), space1)).parse(i)?;
+ Ok((i, ()))
+}
+
+fn args<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, Vec<ast::LocalName>, E> {
+ with(cut(map(
+ separated_list1(arg_separator, alphanumeric1),
+ |sx| {
+ sx.into_iter()
+ .map(|s| ast::LocalName(s.to_string()))
+ .collect()
+ },
+ )))
.parse(i)
}
-fn end<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, (), E> {
+fn params<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, Vec<ast::Expr>, E> {
+ separated_list1(arg_separator, expr).parse(i)
+}
+
+fn end<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, (), E> {
let (i, _) = ws(i)?;
let (i, _) = tag("end")(i)?;
let (i, _) = eol(i)?;
@@ -167,12 +185,12 @@ fn end<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, (), E> {
Ok((i, ()))
}
-fn ws<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, (), E> {
+fn ws<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, (), E> {
let (i, _) = multispace0(i)?;
Ok((i, ()))
}
-fn eol<'i, E: ParseError<&'i str>>(i: &'i str) -> IResult<&'i str, (), E> {
+fn eol<'i, E: ParseError<&'i str>>(i: &'i str) -> IR<'i, (), E> {
let (i, _) = space0(i)?;
let (i, _) = alt((line_ending, eof)).parse(i)?;
diff --git a/run/src/lib.rs b/run/src/lib.rs
index 315c527..747d8f9 100644
--- a/run/src/lib.rs
+++ b/run/src/lib.rs
@@ -29,6 +29,9 @@ pub extern "C" fn char_terminate() {
pub struct Message(u64);
+/// # Safety
+///
+/// I wouldn't count on it
#[unsafe(no_mangle)]
pub unsafe extern "C" fn char_start(
entry: u64,
@@ -40,10 +43,6 @@ pub unsafe extern "C" fn char_start(
for _ in 0..argc {
args.push(unsafe { va_args.arg() });
}
- eprintln!("char start calling {entry:x} with {argc} args");
- for a in &args {
- eprintln!("- {a:x}");
- }
let jh = thread::spawn(move || {
let receiver = Box::into_raw(Box::new(receiver));
@@ -58,15 +57,18 @@ pub unsafe extern "C" fn char_start(
unsafe { mem::transmute(entry as usize) };
target(receiver, args[0]);
}
+ 2 => {
+ let target: extern "C" fn(*mut mpsc::Receiver<Message>, arg0: u64, arg1: u64) =
+ unsafe { mem::transmute(entry as usize) };
+ target(receiver, args[0], args[1]);
+ }
_ => panic!("argc unhandled"),
}
});
let mut jhs = THREADS_MUTEX.lock().unwrap();
jhs.push(jh);
- let sender = Box::into_raw(Box::new(sender));
- eprintln!("returning sender {:x}", sender as usize);
- sender
+ Box::into_raw(Box::new(sender))
}
#[unsafe(no_mangle)]
@@ -83,20 +85,25 @@ pub extern "C" fn char_receive(receiver: u64) -> u64 {
#[unsafe(no_mangle)]
pub extern "C" fn char_send(sender: u64, value: u64) {
- eprintln!("sending {value:x} with sender {sender:x}");
let sender = unsafe {
Box::from_raw(std::ptr::with_exposed_provenance_mut::<
std::sync::mpsc::Sender<Message>,
>(sender as usize))
};
sender.send(Message(value)).unwrap();
- eprintln!("sent");
_ = Box::into_raw(sender);
}
+/// # Safety
+///
+/// Doubtful
#[unsafe(no_mangle)]
-pub extern "C" fn char_puts(s: *const i8) {
+pub unsafe extern "C" fn char_puts(argc: u32, mut va_args: ...) {
let _guard = PUTS_MUTEX.lock().unwrap();
- let s = unsafe { CStr::from_ptr(s) };
- println!("{}", s.to_str().unwrap());
+ for _ in 0..argc {
+ let s: *const i8 = unsafe { va_args.arg() };
+ let s = unsafe { CStr::from_ptr(s) };
+ print!("{}", s.to_str().unwrap());
+ }
+ println!();
}