2023-11-19 01:44:53 +01:00
|
|
|
use core::panic;
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
builtins::{TYPE_FLOAT, TYPE_INTEGER, TYPE_STRING},
|
2023-11-19 16:52:38 +01:00
|
|
|
error::Errors,
|
2023-11-19 01:44:53 +01:00
|
|
|
namespace::{command::Command, r#type::Type, GlobalNamespace},
|
|
|
|
syntax::{CommandPart, CommandPartKind, PipelineElement, PipelineElementKind},
|
2023-11-19 16:52:38 +01:00
|
|
|
Span,
|
2023-11-19 01:44:53 +01:00
|
|
|
};
|
|
|
|
|
2023-11-20 11:05:55 +01:00
|
|
|
#[allow(dead_code, reason = "will be used later")]
|
2023-11-19 01:44:53 +01:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Expr<'a> {
|
|
|
|
kind: ExprKind<'a>,
|
2023-11-19 16:52:38 +01:00
|
|
|
span: Span,
|
2023-11-19 01:44:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum ExprKind<'a> {
|
|
|
|
Command {
|
|
|
|
command: Command<'a>,
|
|
|
|
args: Vec<Expr<'a>>,
|
|
|
|
},
|
|
|
|
Literal(LiteralKind),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum LiteralKind {
|
|
|
|
Int(i64),
|
|
|
|
Float(f64),
|
|
|
|
String(String),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl LiteralKind {
|
2023-11-20 10:27:47 +01:00
|
|
|
#[allow(
|
|
|
|
clippy::unwrap_used,
|
|
|
|
reason = "these are fetched by type name constants used for keeping names consistent in codebase, which cannot be None"
|
|
|
|
)]
|
2023-11-19 01:44:53 +01:00
|
|
|
pub fn get_type<'a>(&self, ns: &'a GlobalNamespace) -> Type<'a> {
|
|
|
|
match self {
|
|
|
|
LiteralKind::Int(_) => ns.get_type_by_name(TYPE_INTEGER).unwrap(),
|
|
|
|
LiteralKind::Float(_) => ns.get_type_by_name(TYPE_FLOAT).unwrap(),
|
|
|
|
LiteralKind::String(_) => ns.get_type_by_name(TYPE_STRING).unwrap(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-19 16:52:38 +01:00
|
|
|
pub fn into_typed_repr(
|
|
|
|
ns: &GlobalNamespace,
|
|
|
|
syntax: Vec<PipelineElement>,
|
|
|
|
) -> Result<Vec<Expr>, Errors> {
|
2023-11-19 01:44:53 +01:00
|
|
|
let mut res = Vec::new();
|
2023-11-19 16:52:38 +01:00
|
|
|
let mut errs = Vec::new();
|
2023-11-19 01:44:53 +01:00
|
|
|
|
|
|
|
for item in syntax {
|
|
|
|
let PipelineElement { kind, span } = item;
|
|
|
|
match kind {
|
|
|
|
PipelineElementKind::Command(c) => {
|
|
|
|
if c.len() == 1 {
|
2023-11-20 11:05:55 +01:00
|
|
|
let CommandPart { kind, .. } = &c[0];
|
2023-11-19 01:44:53 +01:00
|
|
|
|
|
|
|
res.push(Expr {
|
|
|
|
kind: match kind {
|
|
|
|
CommandPartKind::Word(val) => ExprKind::Command {
|
2023-11-19 16:52:38 +01:00
|
|
|
command: {
|
|
|
|
let Some(c) = ns.get_command_by_name(val) else {
|
|
|
|
errs.push(span);
|
|
|
|
continue;
|
|
|
|
};
|
|
|
|
c
|
|
|
|
},
|
2023-11-19 01:44:53 +01:00
|
|
|
args: Vec::new(),
|
|
|
|
},
|
|
|
|
CommandPartKind::Integer(val) => {
|
|
|
|
ExprKind::Literal(LiteralKind::Int(*val))
|
|
|
|
}
|
|
|
|
CommandPartKind::Float(val) => {
|
|
|
|
ExprKind::Literal(LiteralKind::Float(*val))
|
|
|
|
}
|
|
|
|
CommandPartKind::String(val) => {
|
|
|
|
ExprKind::Literal(LiteralKind::String(val.clone()))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
span,
|
2023-11-20 10:29:08 +01:00
|
|
|
});
|
2023-11-19 01:44:53 +01:00
|
|
|
} else {
|
|
|
|
let Some(CommandPart {
|
|
|
|
kind: CommandPartKind::Word(name),
|
|
|
|
span,
|
|
|
|
}) = c.first()
|
|
|
|
else {
|
|
|
|
panic!("tried conversion to typed representation with invalid syntax")
|
|
|
|
};
|
|
|
|
|
|
|
|
res.push(Expr {
|
|
|
|
kind: ExprKind::Command {
|
2023-11-19 16:52:38 +01:00
|
|
|
command: {
|
|
|
|
let Some(c) = ns.get_command_by_name(name) else {
|
|
|
|
errs.push(span.clone());
|
|
|
|
continue;
|
|
|
|
};
|
|
|
|
c
|
|
|
|
},
|
2023-11-19 01:44:53 +01:00
|
|
|
args: c
|
|
|
|
.iter()
|
|
|
|
.skip(1)
|
|
|
|
.map(|CommandPart { kind, span }| Expr {
|
|
|
|
kind: ExprKind::Literal(match kind {
|
2023-11-20 11:05:55 +01:00
|
|
|
CommandPartKind::String(val)
|
|
|
|
| CommandPartKind::Word(val) => {
|
2023-11-19 01:44:53 +01:00
|
|
|
LiteralKind::String(val.to_string())
|
|
|
|
}
|
|
|
|
CommandPartKind::Integer(val) => LiteralKind::Int(*val),
|
|
|
|
CommandPartKind::Float(val) => LiteralKind::Float(*val),
|
|
|
|
}),
|
|
|
|
span: span.clone(),
|
|
|
|
})
|
|
|
|
.collect(),
|
|
|
|
},
|
|
|
|
span: span.clone(),
|
2023-11-20 10:29:08 +01:00
|
|
|
});
|
2023-11-19 01:44:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
PipelineElementKind::Pipe => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-19 16:52:38 +01:00
|
|
|
if errs.is_empty() {
|
|
|
|
Ok(res)
|
|
|
|
} else {
|
|
|
|
Err(Errors::new(crate::error::ErrorKind::CommandNotFound, errs))
|
|
|
|
}
|
2023-11-19 01:44:53 +01:00
|
|
|
}
|