192 lines
5.1 KiB
Rust
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!(),
|
|
}
|
|
}
|
|
}
|