add serialization of values

This commit is contained in:
Matthieu Jolimaitre 2024-10-24 06:03:40 +02:00
parent da82c775db
commit 6350e4a40f
5 changed files with 87 additions and 26 deletions

View file

@ -20,3 +20,7 @@ backtrace-on-stack-overflow = "0.3.0"
[[bin]] [[bin]]
name = "repl" name = "repl"
path = "example/repl.rs" path = "example/repl.rs"
[[bin]]
name = "run"
path = "example/run.rs"

View file

@ -1,4 +1,4 @@
use std::io::stdin; use std::io::{stdin, stdout, Write};
use microlang::Context; use microlang::Context;
@ -6,9 +6,14 @@ pub fn main() {
unsafe { backtrace_on_stack_overflow::enable() }; unsafe { backtrace_on_stack_overflow::enable() };
let mut context = Context::empty(); let mut context = Context::empty();
loop { loop {
print!("> ");
stdout().flush().ok();
let mut line = String::new(); let mut line = String::new();
stdin().read_line(&mut line).unwrap(); stdin().read_line(&mut line).unwrap();
let res = context.eval(line); let res = context.eval(line);
dbg!(res).ok(); match res {
Ok((_, value)) => println!("{}", value.serialize()),
Err(e) => println!("Error : {e:?}"),
}
} }
} }

15
example/run.rs Normal file
View file

@ -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()),
}
}
}

View file

@ -86,8 +86,8 @@ pub struct FunDef {
impl FunDef { impl FunDef {
pub fn parser_def(instr: impl Parse<Instr>, expr: impl Parse<Expr>) -> impl Parse<(String, Self)> { pub fn parser_def(instr: impl Parse<Instr>, expr: impl Parse<Expr>) -> impl Parse<(String, Self)> {
let arguments = id().separated_by(lx(",")); let arguments = id().padded().separated_by(lx(","));
(lx("fn").ignore_then(id())) (lx("fn").ignore_then(id().padded()))
.then(lx("(").ignore_then(arguments).then_ignore(lx(")"))) .then(lx("(").ignore_then(arguments).then_ignore(lx(")")))
.then(lx("{").ignore_then(Block::parser(instr, expr)).then_ignore(lx("}"))) .then(lx("{").ignore_then(Block::parser(instr, expr)).then_ignore(lx("}")))
.map(|((id, args), body)| (id, Self { args, body })) .map(|((id, args), body)| (id, Self { args, body }))
@ -95,7 +95,7 @@ impl FunDef {
} }
pub fn parser_lamb(instr: impl Parse<Instr>, expr: impl Parse<Expr>) -> impl Parse<Self> { pub fn parser_lamb(instr: impl Parse<Instr>, expr: impl Parse<Expr>) -> impl Parse<Self> {
let arguments = id().separated_by(lx(",")); let arguments = id().padded().separated_by(lx(","));
(lx("(").ignore_then(arguments).then_ignore(lx(")"))) (lx("(").ignore_then(arguments).then_ignore(lx(")")))
.then(lx("{").ignore_then(Block::parser(instr, expr)).then_ignore(lx("}"))) .then(lx("{").ignore_then(Block::parser(instr, expr)).then_ignore(lx("}")))
.map(|(args, body)| Self { args, body }) .map(|(args, body)| Self { args, body })
@ -258,7 +258,7 @@ impl Expr {
.map(|(f, o)| Self::BinOps(f.to_box(), o)) .map(|(f, o)| Self::BinOps(f.to_box(), o))
.or((left.clone()) .or((left.clone())
.then_ignore(lx(".")) .then_ignore(lx("."))
.then(id()) .then(id().padded())
.map(|(e, a)| Self::Access(e.to_box(), a))) .map(|(e, a)| Self::Access(e.to_box(), a)))
.or((left.clone()) .or((left.clone())
.then_ignore(lx("(")) .then_ignore(lx("("))

View file

@ -4,7 +4,11 @@ mod util;
use core::{cell::RefCell, fmt::Debug, iter::repeat}; 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 ast::{Block, FunDef, Short};
use chumsky::{error::Simple, Parser}; use chumsky::{error::Simple, Parser};
@ -121,6 +125,54 @@ pub enum Value {
Function(Rc<RefCell<Function>>), Function(Rc<RefCell<Function>>),
} }
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) => "<function>".to_string(),
}
}
}
pub enum InstrOutput { pub enum InstrOutput {
Short(Short), Short(Short),
Value(Value), Value(Value),
@ -135,9 +187,12 @@ pub struct Function {
#[derive(Clone)] #[derive(Clone)]
pub enum FunImpl { pub enum FunImpl {
Def(FunDef), Def(FunDef),
Built(Rc<dyn Fn(Vec<Value>, &mut Context) -> Result<Value, EvalError>>), Built(Rc<BuiltFun>),
} }
pub type FunRes = Result<Value, EvalError>;
pub type BuiltFun = dyn Fn(Vec<Value>, &mut Context) -> FunRes;
impl Debug for FunImpl { impl Debug for FunImpl {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self { match self {
@ -168,21 +223,3 @@ impl Function {
} }
pub mod ast; pub mod ast;
/*
let a = 3;
fn f1() {
let a = 5;
fn f2() {
a = 3;
}
f2
}
let f2 = f1();
f2();
a = 3
*/