From 6350e4a40ffaf5ed56544bf0c8c03fb0596dc049 Mon Sep 17 00:00:00 2001 From: Matthieu Jolimaitre Date: Thu, 24 Oct 2024 06:03:40 +0200 Subject: [PATCH] add serialization of values --- Cargo.toml | 4 +++ example/repl.rs | 9 ++++-- example/run.rs | 15 ++++++++++ src/ast.rs | 8 ++--- src/lib.rs | 77 ++++++++++++++++++++++++++++++++++++------------- 5 files changed, 87 insertions(+), 26 deletions(-) create mode 100644 example/run.rs diff --git a/Cargo.toml b/Cargo.toml index 33fb838..e2d8091 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,3 +20,7 @@ backtrace-on-stack-overflow = "0.3.0" [[bin]] name = "repl" path = "example/repl.rs" + +[[bin]] +name = "run" +path = "example/run.rs" diff --git a/example/repl.rs b/example/repl.rs index 36ca92d..ab45356 100644 --- a/example/repl.rs +++ b/example/repl.rs @@ -1,4 +1,4 @@ -use std::io::stdin; +use std::io::{stdin, stdout, Write}; use microlang::Context; @@ -6,9 +6,14 @@ pub fn main() { unsafe { backtrace_on_stack_overflow::enable() }; let mut context = Context::empty(); loop { + print!("> "); + stdout().flush().ok(); let mut line = String::new(); stdin().read_line(&mut line).unwrap(); let res = context.eval(line); - dbg!(res).ok(); + match res { + Ok((_, value)) => println!("{}", value.serialize()), + Err(e) => println!("Error : {e:?}"), + } } } diff --git a/example/run.rs b/example/run.rs new file mode 100644 index 0000000..02e2eb8 --- /dev/null +++ b/example/run.rs @@ -0,0 +1,15 @@ +use std::{env::args, fs}; + +use microlang::Context; + +pub fn main() { + unsafe { backtrace_on_stack_overflow::enable() }; + let mut context = Context::empty(); + let lines = fs::read_to_string(args().nth(1).expect("Pass a file as arg 1.")).expect("File could not be read."); + for line in lines.lines() { + match context.eval(line.into()) { + Err(err) => panic!("Failed : {err:?}"), + Ok((_, value)) => println!("{}", value.serialize()), + } + } +} diff --git a/src/ast.rs b/src/ast.rs index 0593400..0fa4fab 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -86,8 +86,8 @@ pub struct FunDef { impl FunDef { pub fn parser_def(instr: impl Parse, expr: impl Parse) -> impl Parse<(String, Self)> { - let arguments = id().separated_by(lx(",")); - (lx("fn").ignore_then(id())) + let arguments = id().padded().separated_by(lx(",")); + (lx("fn").ignore_then(id().padded())) .then(lx("(").ignore_then(arguments).then_ignore(lx(")"))) .then(lx("{").ignore_then(Block::parser(instr, expr)).then_ignore(lx("}"))) .map(|((id, args), body)| (id, Self { args, body })) @@ -95,7 +95,7 @@ impl FunDef { } pub fn parser_lamb(instr: impl Parse, expr: impl Parse) -> impl Parse { - let arguments = id().separated_by(lx(",")); + let arguments = id().padded().separated_by(lx(",")); (lx("(").ignore_then(arguments).then_ignore(lx(")"))) .then(lx("{").ignore_then(Block::parser(instr, expr)).then_ignore(lx("}"))) .map(|(args, body)| Self { args, body }) @@ -258,7 +258,7 @@ impl Expr { .map(|(f, o)| Self::BinOps(f.to_box(), o)) .or((left.clone()) .then_ignore(lx(".")) - .then(id()) + .then(id().padded()) .map(|(e, a)| Self::Access(e.to_box(), a))) .or((left.clone()) .then_ignore(lx("(")) diff --git a/src/lib.rs b/src/lib.rs index f134069..d762348 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,11 @@ mod util; use core::{cell::RefCell, fmt::Debug, iter::repeat}; -use alloc::{rc::Rc, string::String, vec::Vec}; +use alloc::{ + rc::Rc, + string::{String, ToString}, + vec::Vec, +}; use ast::{Block, FunDef, Short}; use chumsky::{error::Simple, Parser}; @@ -121,6 +125,54 @@ pub enum Value { Function(Rc>), } +impl Value { + pub fn serialize(&self) -> String { + match self { + Self::None => "none".to_string(), + Self::Bool(b) => b.to_string(), + Self::Num(n) => n.to_string(), + Self::Str(s) => s.to_string(), + Self::Object(o) => { + let mut res = "{".to_string(); + let mut first = true; + for (name, value) in o.borrow().iter() { + if first { + res += " "; + res += name; + res += ": "; + res += &value.serialize(); + first = false; + } else { + res += ", "; + res += name; + res += ": "; + res += &value.serialize(); + } + } + res += " }"; + res + } + Self::Array(a) => { + let mut res = "[".to_string(); + let mut first = true; + for value in a.borrow().iter() { + if first { + res += " "; + res += &value.serialize(); + first = false; + } else { + res += ", "; + res += &value.serialize(); + } + } + res += " ]"; + res + } + Self::Function(_f) => "".to_string(), + } + } +} + pub enum InstrOutput { Short(Short), Value(Value), @@ -135,9 +187,12 @@ pub struct Function { #[derive(Clone)] pub enum FunImpl { Def(FunDef), - Built(Rc, &mut Context) -> Result>), + Built(Rc), } +pub type FunRes = Result; +pub type BuiltFun = dyn Fn(Vec, &mut Context) -> FunRes; + impl Debug for FunImpl { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { @@ -168,21 +223,3 @@ impl Function { } pub mod ast; - -/* - -let a = 3; - -fn f1() { - let a = 5; - fn f2() { - a = 3; - } - f2 -} - -let f2 = f1(); -f2(); -a = 3 - -*/