use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct GlyphModule {
pub program: ProgramDecorator,
pub imports: Vec<Import>,
pub statements: Vec<Statement>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ProgramDecorator {
pub name: String,
pub version: String,
pub requires: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Import {
Module { name: String },
FromImport { module: String, items: Vec<String> },
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Statement {
FunctionDef(Function),
Expression(Expression),
If(IfStatement),
Match(MatchStatement),
Return(Option<Expression>),
Let {
name: String,
value: Expression,
type_hint: Option<Type>,
},
Assignment { target: String, value: Expression },
While {
condition: Expression,
body: Vec<Statement>,
},
For {
variable: String,
iterable: Expression,
body: Vec<Statement>,
},
Break,
Continue,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Function {
pub name: String,
pub params: Vec<Parameter>,
pub return_type: Option<Type>,
pub body: Vec<Statement>,
pub is_async: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Parameter {
pub name: String,
pub type_hint: Option<Type>,
pub default: Option<Expression>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct IfStatement {
pub condition: Expression,
pub then_body: Vec<Statement>,
pub elif_clauses: Vec<ElifClause>,
pub else_body: Option<Vec<Statement>>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ElifClause {
pub condition: Expression,
pub body: Vec<Statement>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MatchStatement {
pub subject: Expression,
pub cases: Vec<CaseClause>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CaseClause {
pub pattern: Pattern,
pub body: Vec<Statement>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Pattern {
Literal(Literal),
Variable(String),
Constructor { name: String, args: Vec<Pattern> },
Wildcard,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Expression {
Literal(Literal),
Identifier(String),
BinaryOp {
left: Box<Expression>,
op: BinaryOperator,
right: Box<Expression>,
},
UnaryOp {
op: UnaryOperator,
operand: Box<Expression>,
},
Call {
func: Box<Expression>,
args: Vec<Expression>,
kwargs: Vec<(String, Expression)>,
},
Await(Box<Expression>),
FString(Vec<FStringPart>),
List(Vec<Expression>),
Dict(Vec<(Expression, Expression)>),
Attribute {
value: Box<Expression>,
attr: String,
},
IfExpr {
test: Box<Expression>,
if_true: Box<Expression>,
if_false: Box<Expression>,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum FStringPart {
Text(String),
Expression(Expression),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Literal {
Int(i64),
Float(f64),
String(String),
Bool(bool),
Unit,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum BinaryOperator {
Add,
Subtract,
Multiply,
Divide,
Modulo,
Power,
Equal,
NotEqual,
Less,
Greater,
LessEqual,
GreaterEqual,
And,
Or,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum UnaryOperator {
Negate,
Not,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Type {
Named(String),
List(Box<Type>),
Dict { key: Box<Type>, value: Box<Type> },
Optional(Box<Type>),
Promise(Box<Type>),
Result { ok: Box<Type>, err: Box<Type> },
}
pub type GlyphAst = GlyphModule;
impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Type::Named(name) => write!(f, "{name}"),
Type::List(inner) => write!(f, "list[{inner}]"),
Type::Dict { key, value } => write!(f, "dict[{key}, {value}]"),
Type::Optional(inner) => write!(f, "optional[{inner}]"),
Type::Promise(inner) => write!(f, "promise[{inner}]"),
Type::Result { ok, err } => write!(f, "result[{ok}, {err}]"),
}
}
}
impl fmt::Display for BinaryOperator {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use BinaryOperator::*;
match self {
Add => write!(f, "+"),
Subtract => write!(f, "-"),
Multiply => write!(f, "*"),
Divide => write!(f, "/"),
Modulo => write!(f, "%"),
Power => write!(f, "**"),
Equal => write!(f, "=="),
NotEqual => write!(f, "!="),
Less => write!(f, "<"),
Greater => write!(f, ">"),
LessEqual => write!(f, "<="),
GreaterEqual => write!(f, ">="),
And => write!(f, "and"),
Or => write!(f, "or"),
}
}
}