use std::fmt::{self, Debug, Formatter}; use lexpar::lexer::Span; pub trait Ast: Debug {} pub struct AstNode { pub span: Span, expr: Box } impl AstNode { pub fn new(span: Span, expr: A) -> Self where A: Ast + 'static { Self { span, expr: Box::new(expr) } } } impl Debug for AstNode { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.write_fmt(format_args!("{:?}", self.expr)) } } #[derive(Debug)] pub enum BinOp { Assign, Or, And, Eq, NotEq, Range, Add, Sub, Mul, Div, } macro_rules! ast_nodes { { $(struct $name: ident { $( $field: ident : $type: ty ),* $(,)* })+ } => { $( #[derive(Debug)] pub struct $name { $( pub $field: $type ),* } impl Ast for $name {} )+ } } ast_nodes! { struct NumberExpr { num: f64 } struct StringExpr { string: String } struct VariableExpr { name: String } struct FunctionProtoExpr { name: Option, params: Vec } struct FunctionExpr { proto: AstNode, body: AstNode } struct ClosureExpr { proto: AstNode, body: AstNode } struct CallExpr { name: String, args: Vec } struct BlockExpr { exprs: Vec } struct BinExpr { op: BinOp, lhs: AstNode, rhs: AstNode } struct IfExpr { cond: AstNode, then: AstNode, el: Option } struct ForExpr { var: AstNode, iter: AstNode, body: AstNode } struct VariableDef { name: String, value: AstNode } }