iowo/src/typed.rs

134 lines
4.6 KiB
Rust
Raw Normal View History

use core::panic;
use crate::{
builtins::{TYPE_FLOAT, TYPE_INTEGER, TYPE_STRING},
error::Errors,
namespace::{command::Command, r#type::Type, GlobalNamespace},
syntax::{CommandPart, CommandPartKind, PipelineElement, PipelineElementKind},
Span,
};
#[allow(dead_code, reason = "will be used later")]
#[derive(Debug)]
pub struct Expr<'a> {
kind: ExprKind<'a>,
span: Span,
}
#[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"
)]
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(),
}
}
}
pub fn into_typed_repr(
ns: &GlobalNamespace,
syntax: Vec<PipelineElement>,
) -> Result<Vec<Expr>, Errors> {
let mut res = Vec::new();
let mut errs = Vec::new();
for item in syntax {
let PipelineElement { kind, span } = item;
match kind {
PipelineElementKind::Command(c) => {
if c.len() == 1 {
let CommandPart { kind, .. } = &c[0];
res.push(Expr {
kind: match kind {
CommandPartKind::Word(val) => ExprKind::Command {
command: {
let Some(c) = ns.get_command_by_name(val) else {
errs.push(span);
continue;
};
c
},
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
});
} 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 {
command: {
let Some(c) = ns.get_command_by_name(name) else {
errs.push(span.clone());
continue;
};
c
},
args: c
.iter()
.skip(1)
.map(|CommandPart { kind, span }| Expr {
kind: ExprKind::Literal(match kind {
CommandPartKind::String(val)
| CommandPartKind::Word(val) => {
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
});
}
}
PipelineElementKind::Pipe => {}
}
}
if errs.is_empty() {
Ok(res)
} else {
Err(Errors::new(crate::error::ErrorKind::CommandNotFound, errs))
}
}