use super::axiom::{AxiomBlock, TheoryBlock};
use super::definition::DefinitionBlock;
use super::logic::LogicExpr;
use super::theorem::TheoremBlock;
use logicaffeine_base::Symbol;
#[derive(Debug, Clone)]
pub enum TypeExpr<'a> {
Primitive(Symbol),
Named(Symbol),
Generic {
base: Symbol,
params: &'a [TypeExpr<'a>],
},
Function {
inputs: &'a [TypeExpr<'a>],
output: &'a TypeExpr<'a>,
},
Refinement {
base: &'a TypeExpr<'a>,
var: Symbol,
predicate: &'a LogicExpr<'a>,
},
Persistent {
inner: &'a TypeExpr<'a>,
},
Mutable {
inner: &'a TypeExpr<'a>,
},
}
#[derive(Debug, Clone, Copy)]
pub enum ReadSource<'a> {
Console,
File(&'a Expr<'a>),
}
#[derive(Debug, Clone)]
pub enum Pattern {
Identifier(Symbol),
Tuple(Vec<Symbol>),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum BinaryOpKind {
Add,
Subtract,
Multiply,
Pow,
Divide,
ExactDivide,
FloorDivide,
Modulo,
Eq,
NotEq,
Lt,
Gt,
LtEq,
GtEq,
And,
Or,
Concat,
SeqConcat,
ApproxEq,
BitXor,
BitAnd,
BitOr,
Shl,
Shr,
}
pub type Block<'a> = &'a [Stmt<'a>];
#[derive(Debug, Clone)]
pub struct MatchArm<'a> {
pub enum_name: Option<Symbol>, pub variant: Option<Symbol>, pub bindings: Vec<(Symbol, Symbol)>, pub body: Block<'a>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CompressionCodec {
Deflate,
Lz4,
Zstd,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SendLayout {
Compact,
Fast,
Packed,
Smallest,
Redundant,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ZoneSource {
Literal(Symbol),
Variable(Symbol),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SecureRole {
Initiator,
Responder,
}
#[derive(Debug, Clone, Copy)]
pub struct SecurePad<'a> {
pub pad: &'a Expr<'a>,
pub role: SecureRole,
}
#[derive(Debug, Clone)]
pub enum Stmt<'a> {
Let {
var: Symbol,
ty: Option<&'a TypeExpr<'a>>,
value: &'a Expr<'a>,
mutable: bool,
},
Set {
target: Symbol,
value: &'a Expr<'a>,
},
Call {
function: Symbol,
args: Vec<&'a Expr<'a>>,
},
If {
cond: &'a Expr<'a>,
then_block: Block<'a>,
else_block: Option<Block<'a>>,
},
While {
cond: &'a Expr<'a>,
body: Block<'a>,
decreasing: Option<&'a Expr<'a>>,
},
Repeat {
pattern: Pattern, iterable: &'a Expr<'a>,
body: Block<'a>,
},
Return {
value: Option<&'a Expr<'a>>,
},
Break,
Assert {
proposition: &'a LogicExpr<'a>,
},
Trust {
proposition: &'a LogicExpr<'a>,
justification: Symbol,
},
RuntimeAssert {
condition: &'a Expr<'a>,
hard: bool,
},
Give {
object: &'a Expr<'a>,
recipient: &'a Expr<'a>,
},
Show {
object: &'a Expr<'a>,
recipient: &'a Expr<'a>,
},
SetField {
object: &'a Expr<'a>,
field: Symbol,
value: &'a Expr<'a>,
},
StructDef {
name: Symbol,
fields: Vec<(Symbol, Symbol, bool)>, is_portable: bool, },
FunctionDef {
name: Symbol,
generics: Vec<Symbol>,
params: Vec<(Symbol, &'a TypeExpr<'a>)>,
body: Block<'a>,
return_type: Option<&'a TypeExpr<'a>>,
is_native: bool,
native_path: Option<Symbol>,
is_exported: bool,
export_target: Option<Symbol>,
opt_flags: crate::optimization::OptimizationConfig,
},
Inspect {
target: &'a Expr<'a>,
arms: Vec<MatchArm<'a>>,
has_otherwise: bool, },
Push {
value: &'a Expr<'a>,
collection: &'a Expr<'a>,
},
Pop {
collection: &'a Expr<'a>,
into: Option<Symbol>,
},
Add {
value: &'a Expr<'a>,
collection: &'a Expr<'a>,
},
Remove {
value: &'a Expr<'a>,
collection: &'a Expr<'a>,
},
SetIndex {
collection: &'a Expr<'a>,
index: &'a Expr<'a>,
value: &'a Expr<'a>,
},
Splice {
body: Block<'a>,
},
Zone {
name: Symbol,
capacity: Option<usize>,
source_file: Option<ZoneSource>,
body: Block<'a>,
},
Concurrent {
tasks: Block<'a>,
},
Parallel {
tasks: Block<'a>,
},
ReadFrom {
var: Symbol,
source: ReadSource<'a>,
},
WriteFile {
content: &'a Expr<'a>,
path: &'a Expr<'a>,
},
Spawn {
agent_type: Symbol,
name: Symbol,
},
SendMessage {
message: &'a Expr<'a>,
destination: &'a Expr<'a>,
compression: Option<CompressionCodec>,
cached: bool,
unchecked: bool,
layout: Option<SendLayout>,
shared: bool,
computed: bool,
indexed: bool,
deduped: bool,
},
AwaitMessage {
source: &'a Expr<'a>,
into: Symbol,
view: bool,
stream: bool,
},
StreamMessage {
values: &'a Expr<'a>,
destination: &'a Expr<'a>,
},
MergeCrdt {
source: &'a Expr<'a>,
target: &'a Expr<'a>,
},
IncreaseCrdt {
object: &'a Expr<'a>,
field: Symbol,
amount: &'a Expr<'a>,
},
DecreaseCrdt {
object: &'a Expr<'a>,
field: Symbol,
amount: &'a Expr<'a>,
},
AppendToSequence {
sequence: &'a Expr<'a>,
value: &'a Expr<'a>,
},
ResolveConflict {
object: &'a Expr<'a>,
field: Symbol,
value: &'a Expr<'a>,
},
Check {
subject: Symbol,
predicate: Symbol,
is_capability: bool,
object: Option<Symbol>,
source_text: String,
span: crate::token::Span,
},
Listen {
address: &'a Expr<'a>,
secure: Option<SecurePad<'a>>,
},
ConnectTo {
address: &'a Expr<'a>,
secure: Option<SecurePad<'a>>,
},
LetPeerAgent {
var: Symbol,
address: &'a Expr<'a>,
},
Sleep {
milliseconds: &'a Expr<'a>,
},
Sync {
var: Symbol,
topic: &'a Expr<'a>,
},
Mount {
var: Symbol,
path: &'a Expr<'a>,
},
LaunchTask {
function: Symbol,
args: Vec<&'a Expr<'a>>,
},
LaunchTaskWithHandle {
handle: Symbol,
function: Symbol,
args: Vec<&'a Expr<'a>>,
},
CreatePipe {
var: Symbol,
element_type: Symbol,
capacity: Option<u32>,
},
SendPipe {
value: &'a Expr<'a>,
pipe: &'a Expr<'a>,
},
ReceivePipe {
var: Symbol,
pipe: &'a Expr<'a>,
},
TrySendPipe {
value: &'a Expr<'a>,
pipe: &'a Expr<'a>,
result: Option<Symbol>,
},
TryReceivePipe {
var: Symbol,
pipe: &'a Expr<'a>,
},
StopTask {
handle: &'a Expr<'a>,
},
Select {
branches: Vec<SelectBranch<'a>>,
},
Theorem(TheoremBlock<'a>),
Definition(DefinitionBlock<'a>),
Axiom(AxiomBlock),
Theory(TheoryBlock),
Escape {
language: Symbol,
code: Symbol,
span: crate::token::Span,
},
Require {
crate_name: Symbol,
version: Symbol,
features: Vec<Symbol>,
span: crate::token::Span,
},
}
#[derive(Debug, Clone)]
pub enum SelectBranch<'a> {
Receive {
var: Symbol,
pipe: &'a Expr<'a>,
body: Block<'a>,
},
Timeout {
milliseconds: &'a Expr<'a>,
body: Block<'a>,
},
}
#[derive(Debug)]
pub enum Expr<'a> {
Literal(Literal),
Identifier(Symbol),
BinaryOp {
op: BinaryOpKind,
left: &'a Expr<'a>,
right: &'a Expr<'a>,
},
Not {
operand: &'a Expr<'a>,
},
Call {
function: Symbol,
args: Vec<&'a Expr<'a>>,
},
Index {
collection: &'a Expr<'a>,
index: &'a Expr<'a>,
},
Slice {
collection: &'a Expr<'a>,
start: &'a Expr<'a>,
end: &'a Expr<'a>,
},
Copy {
expr: &'a Expr<'a>,
},
Give {
value: &'a Expr<'a>,
},
Length {
collection: &'a Expr<'a>,
},
Contains {
collection: &'a Expr<'a>,
value: &'a Expr<'a>,
},
Union {
left: &'a Expr<'a>,
right: &'a Expr<'a>,
},
Intersection {
left: &'a Expr<'a>,
right: &'a Expr<'a>,
},
ManifestOf {
zone: &'a Expr<'a>,
},
ChunkAt {
index: &'a Expr<'a>,
zone: &'a Expr<'a>,
},
List(Vec<&'a Expr<'a>>),
Tuple(Vec<&'a Expr<'a>>),
Range {
start: &'a Expr<'a>,
end: &'a Expr<'a>,
},
FieldAccess {
object: &'a Expr<'a>,
field: Symbol,
},
New {
type_name: Symbol,
type_args: Vec<TypeExpr<'a>>, init_fields: Vec<(Symbol, &'a Expr<'a>)>, },
NewVariant {
enum_name: Symbol, variant: Symbol, fields: Vec<(Symbol, &'a Expr<'a>)>, },
Escape {
language: Symbol,
code: Symbol,
},
OptionSome {
value: &'a Expr<'a>,
},
OptionNone,
WithCapacity {
value: &'a Expr<'a>,
capacity: &'a Expr<'a>,
},
Closure {
params: Vec<(Symbol, &'a TypeExpr<'a>)>,
body: ClosureBody<'a>,
return_type: Option<&'a TypeExpr<'a>>,
},
CallExpr {
callee: &'a Expr<'a>,
args: Vec<&'a Expr<'a>>,
},
InterpolatedString(Vec<StringPart<'a>>),
}
#[derive(Debug, Clone)]
pub enum StringPart<'a> {
Literal(Symbol),
Expr {
value: &'a Expr<'a>,
format_spec: Option<Symbol>,
debug: bool,
},
}
#[derive(Debug, Clone)]
pub enum ClosureBody<'a> {
Expression(&'a Expr<'a>),
Block(Block<'a>),
}
#[derive(Debug, Clone)]
pub enum Literal {
Number(i64),
Float(f64),
Text(Symbol),
Boolean(bool),
Nothing,
Char(char),
Duration(i64),
Date(i32),
Moment(i64),
Span { months: i32, days: i32 },
Time(i64),
}
impl PartialEq for Literal {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Literal::Number(a), Literal::Number(b)) => a == b,
(Literal::Float(a), Literal::Float(b)) => a.to_bits() == b.to_bits(),
(Literal::Text(a), Literal::Text(b)) => a == b,
(Literal::Boolean(a), Literal::Boolean(b)) => a == b,
(Literal::Nothing, Literal::Nothing) => true,
(Literal::Char(a), Literal::Char(b)) => a == b,
(Literal::Duration(a), Literal::Duration(b)) => a == b,
(Literal::Date(a), Literal::Date(b)) => a == b,
(Literal::Moment(a), Literal::Moment(b)) => a == b,
(Literal::Span { months: m1, days: d1 }, Literal::Span { months: m2, days: d2 }) => m1 == m2 && d1 == d2,
(Literal::Time(a), Literal::Time(b)) => a == b,
_ => false,
}
}
}
impl Eq for Literal {}
impl std::hash::Hash for Literal {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
std::mem::discriminant(self).hash(state);
match self {
Literal::Number(n) => n.hash(state),
Literal::Float(f) => f.to_bits().hash(state),
Literal::Text(s) => s.hash(state),
Literal::Boolean(b) => b.hash(state),
Literal::Nothing => {}
Literal::Char(c) => c.hash(state),
Literal::Duration(d) => d.hash(state),
Literal::Date(d) => d.hash(state),
Literal::Moment(m) => m.hash(state),
Literal::Span { months, days } => {
months.hash(state);
days.hash(state);
}
Literal::Time(t) => t.hash(state),
}
}
}