use yog_ids::script_problem;
use yog_script_ids::system::SENDER;
use super::Checker;
use super::model::Type;
use crate::ast::{Decl, DeclKind, Method};
impl Checker<'_, '_, '_> {
pub(super) fn command(&mut self, body: &[Decl]) {
for d in body {
match &d.kind {
DeclKind::Method(m) => {
self.command_method(m);
self.decl(d);
}
_ => self.report.error(
script_problem::TYPE_MISMATCH,
d.span,
"a command holds the methods it's run by",
),
}
}
}
fn command_method(&mut self, m: &Method) {
let mut params = m.params.iter();
let sender = params.next().map(|p| self.type_of(&p.ty));
if sender != Some(Type::own(SENDER.to_string())) {
self.report.error(
script_problem::TYPE_MISMATCH,
m.name.span,
format!("a command's method takes who ran it first: `{SENDER} source`"),
);
}
for p in params {
let t = self.type_of(&p.ty);
if command_arg(&t).is_none() {
self.report.error(
script_problem::TYPE_MISMATCH,
p.ty.span,
format!(
"a command's argument is a number, a `string` or a `Player`, not a `{t}`"
),
);
}
}
}
}
pub fn command_arg(t: &Type) -> Option<&'static str> {
use yog_ids::command_arg::{FLOAT, INT, PLAYER, WORD};
match t {
Type::I32 => Some(INT),
Type::F32 | Type::F64 => Some(FLOAT),
Type::String => Some(WORD),
Type::Yog(name) if name == crate::yog::player() => Some(PLAYER),
_ => None,
}
}