add serialization of values
This commit is contained in:
parent
da82c775db
commit
6350e4a40f
5 changed files with 87 additions and 26 deletions
|
@ -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"
|
||||
|
|
|
@ -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:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
15
example/run.rs
Normal file
15
example/run.rs
Normal 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()),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -86,8 +86,8 @@ pub struct FunDef {
|
|||
|
||||
impl FunDef {
|
||||
pub fn parser_def(instr: impl Parse<Instr>, expr: impl Parse<Expr>) -> 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<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(")")))
|
||||
.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("("))
|
||||
|
|
77
src/lib.rs
77
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<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 {
|
||||
Short(Short),
|
||||
Value(Value),
|
||||
|
@ -135,9 +187,12 @@ pub struct Function {
|
|||
#[derive(Clone)]
|
||||
pub enum FunImpl {
|
||||
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 {
|
||||
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
|
||||
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue