use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct Span {
pub start_line: usize,
pub start_col: usize,
pub end_line: usize,
pub end_col: usize,
}
impl Span {
pub fn new(start_line: usize, start_col: usize, end_line: usize, end_col: usize) -> Self {
Self {
start_line,
start_col,
end_line,
end_col,
}
}
}
impl fmt::Display for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}:{}-{}:{}",
self.start_line, self.start_col, self.end_line, self.end_col
)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Type {
I8,
I16,
I32,
I64,
U8,
U16,
U32,
U64,
F32,
F64,
Bool,
String,
Void,
Pin, Bus, Duration, Custom(String),
Array(Box<Type>, usize),
}
impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Type::I8 => write!(f, "i8"),
Type::I16 => write!(f, "i16"),
Type::I32 => write!(f, "i32"),
Type::I64 => write!(f, "i64"),
Type::U8 => write!(f, "u8"),
Type::U16 => write!(f, "u16"),
Type::U32 => write!(f, "u32"),
Type::U64 => write!(f, "u64"),
Type::F32 => write!(f, "f32"),
Type::F64 => write!(f, "f64"),
Type::Bool => write!(f, "bool"),
Type::String => write!(f, "string"),
Type::Void => write!(f, "void"),
Type::Pin => write!(f, "pin"),
Type::Bus => write!(f, "bus"),
Type::Duration => write!(f, "duration"),
Type::Custom(name) => write!(f, "{}", name),
Type::Array(inner, size) => write!(f, "[{}; {}]", inner, size),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PinMode {
In,
Out,
Alt,
Pwm,
Analog,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PinPull {
None,
Up,
Down,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum TaskPriority {
Low,
Normal,
High,
Critical,
Realtime,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum BusType {
I2C,
SPI,
UART,
CAN,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Program {
pub imports: Vec<ImportDecl>,
pub items: Vec<Item>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ImportDecl {
pub path: Vec<String>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Item {
Pin(PinDecl),
Bus(BusDecl),
Robot(RobotDecl),
Task(TaskDecl),
Function(FnDecl),
Struct(StructDecl),
Enum(EnumDecl),
StateMachine(StateMachineDecl),
TopicHandler(TopicHandlerDecl),
EventHandler(EventHandlerDecl),
InterruptHandler(InterruptHandlerDecl),
ServiceHandler(ServiceHandlerDecl),
ActionHandler(ActionHandlerDecl),
Watchdog(WatchdogDecl),
SensorPipeline(SensorPipelineDecl),
SafetyInvariant(SafetyInvariantDecl),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct WatchdogDecl {
pub name: String,
pub timeout_ms: u32,
pub priority: TaskPriority,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SensorPipelineDecl {
pub name: String,
pub source: String,
pub filter: String,
pub output_type: Type,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SafetyInvariantDecl {
pub condition: Expr,
pub panic_msg: String,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct StateMachineDecl {
pub name: String,
pub initial_state: String,
pub states: Vec<StateBlock>,
pub transitions: Vec<StateTransition>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct StateBlock {
pub name: String,
pub on_enter: Block,
pub on_update: Block,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct StateTransition {
pub from_state: String,
pub to_state: String,
pub condition: String,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct InterruptHandlerDecl {
pub pin_num: u32,
pub edge: String,
pub handler_name: String,
pub body: Block,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ServiceHandlerDecl {
pub service: String,
pub req_name: String,
pub req_type: Type,
pub ret_type: Type,
pub body: Block,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ActionHandlerDecl {
pub action: String,
pub goal_name: String,
pub goal_type: Type,
pub body: Block,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PinDecl {
pub name: String,
pub pin_num: u32,
pub mode: PinMode,
pub pull: PinPull,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BusDecl {
pub name: String,
pub bus_type: BusType,
pub bus_id: u32,
pub pins: Vec<String>,
pub baudrate: u32,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RobotDecl {
pub name: String,
pub pins: Vec<PinDecl>,
pub buses: Vec<BusDecl>,
pub fields: Vec<StructField>,
pub methods: Vec<FnDecl>,
pub tasks: Vec<TaskDecl>,
pub topic_handlers: Vec<TopicHandlerDecl>,
pub event_handlers: Vec<EventHandlerDecl>,
pub state_machines: Vec<StateMachineDecl>,
pub interrupt_handlers: Vec<InterruptHandlerDecl>,
pub service_handlers: Vec<ServiceHandlerDecl>,
pub action_handlers: Vec<ActionHandlerDecl>,
pub watchdogs: Vec<WatchdogDecl>,
pub sensor_pipelines: Vec<SensorPipelineDecl>,
pub safety_invariants: Vec<SafetyInvariantDecl>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TaskDecl {
pub name: String,
pub deadline_ms: u32,
pub priority: TaskPriority,
pub body: Block,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TopicHandlerDecl {
pub topic: String,
pub param_name: String,
pub param_type: Type,
pub body: Block,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct EventHandlerDecl {
pub event_type: String,
pub target_id: u32,
pub condition: String,
pub body: Block,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FnDecl {
pub name: String,
pub params: Vec<Param>,
pub ret_type: Type,
pub body: Block,
pub is_test: bool,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Param {
pub name: String,
pub ty: Type,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct StructDecl {
pub name: String,
pub fields: Vec<StructField>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct StructField {
pub name: String,
pub ty: Type,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EnumDecl {
pub name: String,
pub variants: Vec<String>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Block {
pub statements: Vec<Stmt>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Stmt {
Let {
name: String,
mutability: bool,
ty: Option<Type>,
init: Expr,
span: Span,
},
Assign {
target: Expr,
value: Expr,
span: Span,
},
If {
cond: Expr,
then_block: Block,
else_block: Option<Block>,
span: Span,
},
While {
cond: Expr,
body: Block,
span: Span,
},
For {
var: String,
start: Expr,
end: Expr,
body: Block,
span: Span,
},
Loop {
body: Block,
span: Span,
},
Match {
target: Expr,
arms: Vec<MatchArm>,
span: Span,
},
Return {
value: Option<Expr>,
span: Span,
},
Emit {
topic: String,
payload: Expr,
span: Span,
},
Break(Span),
Continue(Span),
Expr(Expr),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MatchArm {
pub pattern: Pattern,
pub body: Block,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Pattern {
Literal(Literal),
EnumVariant { enum_name: String, variant: String },
Wildcard,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Expr {
Literal(Literal, Span),
Variable(String, Span),
FieldAccess(Box<Expr>, String, Span),
Index(Box<Expr>, Box<Expr>, Span),
Binary {
op: BinaryOp,
left: Box<Expr>,
right: Box<Expr>,
span: Span,
},
Unary {
op: UnaryOp,
operand: Box<Expr>,
span: Span,
},
Call {
func: String,
args: Vec<Expr>,
span: Span,
},
MethodCall {
receiver: Box<Expr>,
method: String,
args: Vec<Expr>,
span: Span,
},
StructInit {
name: String,
fields: Vec<(String, Expr)>,
span: Span,
},
ArrayInit(Vec<Expr>, Span),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Literal {
Int(i64),
Float(f64),
Bool(bool),
String(String),
DurationMs(u32),
HardwareConstant(String), }
impl Eq for Literal {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum BinaryOp {
Add,
Sub,
Mul,
Div,
Mod,
Eq,
NotEq,
Lt,
LtEq,
Gt,
GtEq,
And,
Or,
BitAnd,
BitOr,
BitXor,
Shl,
Shr,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum UnaryOp {
Neg,
Not,
BitNot,
}