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]]
|
[[bin]]
|
||||||
name = "repl"
|
name = "repl"
|
||||||
path = "example/repl.rs"
|
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;
|
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
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 {
|
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("("))
|
||||||
|
|
77
src/lib.rs
77
src/lib.rs
|
@ -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
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue