sunflower/src/main.rs

192 lines
5.1 KiB
Rust

use std::{any::Any, fs::read_to_string};
use env::Env;
use expression::Expression;
use function::FunctionMap;
use lwb_parser::{codegen_prelude::AstInfo, language::Language, sources::source_file::SourceFile};
use statement::Statement;
use value::{custom::CustomValue, Value};
mod env;
mod expression;
mod function;
mod macros;
mod statement;
mod value;
// mod lexer;
// mod parser;
mod pest_parser;
#[rustfmt::skip]
mod sunflower;
lwb_parser::language!(SFL at mod sunflower);
fn run(functions: &FunctionMap, statement: &Statement) {
let env = Env::new();
statement.eval(&env, functions);
}
#[derive(Clone, Debug, PartialEq, Eq)]
struct Foo {
x: i32,
}
impl Foo {
fn edit(&self) -> Self {
let mut f = self.clone();
f.x += 1;
f
}
}
impl CustomValue for Foo {
fn as_any(&self) -> &dyn Any {
self
}
fn format(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Foo({})", self.x)
}
fn eq(&self, other: &Value) -> bool {
if let Some(v) = other.as_t() {
self == v
} else {
false
}
}
fn functions(&self) -> Option<FunctionMap> {
let mut map = FunctionMap::new();
map.insert_native("edit_foo", Foo::edit);
Some(map)
}
fn add(&self, other: &Value) -> Value {
if let Some(v) = other.as_t::<Foo>() {
Foo { x: self.x + v.x }.into()
} else {
Value::default()
}
}
}
fn main() {
// let f = read_to_string("./test.foo").unwrap();
// let (res, funcs) = pest_parser::parse(&f);
let mut m = FunctionMap::new();
// m.insert_holder(funcs);
// m.insert_native("print", |a: &Value| {
// println!("{}", a);
// });
// m.insert_native("waluigi", || "Waluigi");
// m.insert_native("native_test", || Foo { x: 41 });
// m.insert_native("other_foo", || Foo { x: 1 });
// run(&m, &res);
let res = SFL::try_parse(&SourceFile::new(
"
10 / 2 + 3 * 4;
",
"based.sfl",
))
.unwrap();
// println!("{:?}", res);
for r in res.1 {
if let sunflower::Statement::Expression(_, e) = r {
println!("{}", e.eval())
}
}
// for r in res.1 {
// r.eval(&Env::new(), &m)
// }
}
impl<M: AstInfo> sunflower::Expression<M> {
fn eval(&self) -> Value {
self.1.eval()
}
}
impl<M: AstInfo> sunflower::Equality<M> {
fn eval(&self) -> Value {
match self {
sunflower::Equality::Equal(_, lhs, rhs) => (lhs.eval() == rhs.eval()).into(),
sunflower::Equality::NotEqual(_, rhs, lhs) => (lhs.eval() != rhs.eval()).into(),
sunflower::Equality::Inequality(_, all) => all.eval(),
}
}
}
impl<M: AstInfo> sunflower::Inequality<M> {
fn eval(&self) -> Value {
match self {
sunflower::Inequality::LessThan(_, lhs, rhs) => (lhs.eval() < rhs.eval()).into(),
sunflower::Inequality::LessThanOrEqual(_, lhs, rhs) => {
(lhs.eval() <= rhs.eval()).into()
}
sunflower::Inequality::GreaterThan(_, lhs, rhs) => (lhs.eval() > rhs.eval()).into(),
sunflower::Inequality::GreaterThanOrEqual(_, lhs, rhs) => {
(lhs.eval() >= rhs.eval()).into()
}
sunflower::Inequality::Plus(_, all) => all.eval(),
}
}
}
impl<M: AstInfo> sunflower::Plus<M> {
fn eval(&self) -> Value {
match self {
sunflower::Plus::Plus(_, lhs, rhs) => {
println!("doing plus");
(lhs.eval() + rhs.eval()).into()
}
sunflower::Plus::Minus(_, lhs, rhs) => (lhs.eval() - rhs.eval()).into(),
sunflower::Plus::Times(_, all) => all.eval(),
}
}
}
impl<M: AstInfo> sunflower::Times<M> {
fn eval(&self) -> Value {
match self {
sunflower::Times::Times(_, lhs, rhs) => {
println!("doing times");
(lhs.eval() * rhs.eval()).into()
}
sunflower::Times::Divide(_, lhs, rhs) => {
println!("doing divide");
(lhs.eval() / rhs.eval()).into()
}
sunflower::Times::Value(_, all) => all.eval(),
}
}
}
impl<M: AstInfo> sunflower::Value<M> {
fn eval(&self) -> Value {
match self {
sunflower::Value::Const(_, c) => {
println!("doing const");
c.eval()
}
sunflower::Value::Call(_, _) => todo!(),
sunflower::Value::Identifier(_, _) => todo!(),
sunflower::Value::Parens(_, inner) => inner.eval(),
}
}
}
impl<M: AstInfo> sunflower::ConstValue<M> {
fn eval(&self) -> Value {
match self {
sunflower::ConstValue::Int(_, i) => i.1.parse::<i32>().unwrap().into(),
sunflower::ConstValue::Bool(_, b) => match b {
sunflower::Bool::True(_) => true.into(),
sunflower::Bool::False(_) => false.into(),
},
sunflower::ConstValue::String(_, _) => todo!(),
sunflower::ConstValue::Char(_, _) => todo!(),
}
}
}