use crate::object_tree::*; use crate::{parser::SyntaxNode, typeregister::Type}; use core::cell::RefCell; use std::rc::Weak; /// The Expression is hold by properties, so it should not hold any strong references to node from the object_tree #[derive(Debug, Clone)] pub enum Expression { /// Something went wrong (and an error will be reported) Invalid, /// We haven't done the lookup yet Uncompiled(SyntaxNode), /// A string literal. The .0 is the content of the string, without the quotes StringLiteral(String), /// Number NumberLiteral(f64), /// Reference to the signal in the within the /// /// Note: if we are to separate expression and statement, we probably do not need to have signal reference within expressions SignalReference { component: Weak, element: Weak>, name: String }, /// Reference to the signal in the within the /// /// Note: if we are to separate expression and statement, we probably do not need to have signal reference within expressions PropertyReference { component: Weak, element: Weak>, name: String }, /// Cast an expression to the given type Cast { from: Box, to: Type }, /// a code block with different expression CodeBlock(Vec), /// A function call FunctionCall { function: Box }, } impl Expression { /// Return the type of this property pub fn ty(&self) -> Type { match self { Expression::Invalid => Type::Invalid, Expression::Uncompiled(_) => Type::Invalid, Expression::StringLiteral(_) => Type::String, Expression::NumberLiteral(_) => Type::Float32, Expression::SignalReference { .. } => Type::Signal, Expression::PropertyReference { element, name, .. } => { element.upgrade().unwrap().borrow().lookup_property(name) } Expression::Cast { to, .. } => to.clone(), Expression::CodeBlock(sub) => sub.last().map_or(Type::Invalid, |e| e.ty()), Expression::FunctionCall { function } => function.ty(), } } /// Call the visitor for each sub-expression. (note: this function does not recurse) pub fn visit(&self, mut visitor: impl FnMut(&Self)) { match self { Expression::Invalid => {} Expression::Uncompiled(_) => {} Expression::StringLiteral(_) => {} Expression::NumberLiteral(_) => {} Expression::SignalReference { .. } => {} Expression::PropertyReference { .. } => {} Expression::Cast { from, .. } => visitor(&**from), Expression::CodeBlock(sub) => { for e in sub { visitor(e) } } Expression::FunctionCall { function } => visitor(&**function), } } pub fn visit_mut(&mut self, mut visitor: impl FnMut(&mut Self)) { match self { Expression::Invalid => {} Expression::Uncompiled(_) => {} Expression::StringLiteral(_) => {} Expression::NumberLiteral(_) => {} Expression::SignalReference { .. } => {} Expression::PropertyReference { .. } => {} Expression::Cast { from, .. } => visitor(&mut **from), Expression::CodeBlock(sub) => { for e in sub { visitor(e) } } Expression::FunctionCall { function } => visitor(&mut **function), } } }