Добавить биноп «либо»

This commit is contained in:
rexim 2024-04-01 15:35:21 +07:00
parent bcf5cec08e
commit 47052e2d79
7 changed files with 56 additions and 6 deletions

View File

@ -49,8 +49,8 @@
- [x] Массивы в полях структур
- [ ] Все бинопы для всех релевантных типов в правой части
- [x] НеРавно/Равно
- [ ] Меньше/Больше/МеньшеРавно/БольшеРавно
- [ ] и/или, добавить «либо» (исключающее или)
- [x] Меньше/Больше/МеньшеРавно/БольшеРавно
- [x] и/или, добавить «либо» (исключающее или)
- [ ] сложение/вычитание/умножение/деление/остаток
- [ ] конвертация между типами («как»)
- [ ] битовые смещения

View File

@ -645,6 +645,12 @@ impl<'ы> Машина<'ы> {
self.протолкнуть_значениеат((а && б) as usize)?;
self.индекс_инструкции += 1;
}
ВидИнструкции::ЛогЛибо => {
let а = self.вытолкнуть_значениеат()? != 0;
let б = self.вытолкнуть_значениеат()? != 0;
self.протолкнуть_значениеат((а != б) as usize)?;
self.индекс_инструкции += 1;
}
ВидИнструкции::БитИли => {
let а = self.вытолкнуть_значениеат()?;
let б = self.вытолкнуть_значениеат()?;
@ -657,6 +663,12 @@ impl<'ы> Машина<'ы> {
self.протолкнуть_значениеат(а & б)?;
self.индекс_инструкции += 1;
}
ВидИнструкции::БитЛибо => {
let а = self.вытолкнуть_значениеат()?;
let б = self.вытолкнуть_значениеат()?;
self.протолкнуть_значениеат(а ^ б)?;
self.индекс_инструкции += 1;
}
ВидИнструкции::БитСмещениеВлево => {
let сдвиг = self.вытолкнуть_значениеат()?;
let значение = self.вытолкнуть_значениеат()?;

View File

@ -82,8 +82,10 @@ pub enum ВидИнструкции {
Вещ32Отриц,
ЛогОтрицание,
ЛогИ,
ЛогЛибо,
БитИли,
БитИ,
БитЛибо,
БитСмещениеВлево,
БитСмещениеВправо,
ПечатьСтроки,
@ -924,7 +926,7 @@ fn скомпилировать_выражение(пп: &mut ПП, имена:
let правый_тип = скомпилировать_выражение(пп, имена, текущая_процедура, локальные_имена, &правое, временный_размер)?;
проверить_типы(правое.лок(), &левый_тип, &правый_тип)?;
match левый_тип {
Тип::Лог | Тип::Нат64 => {
Тип::Лог | Тип::Нат64 | Тип::Нат8 | Тип::Цел64 => {
пп.код.push(Инструкция{ вид: ВидИнструкции::БитИли, лок: ключ.лок.clone() });
}
_ => {
@ -939,7 +941,7 @@ fn скомпилировать_выражение(пп: &mut ПП, имена:
let правый_тип = скомпилировать_выражение(пп, имена, текущая_процедура, локальные_имена, &правое, временный_размер)?;
проверить_типы(правое.лок(), &левый_тип, &правый_тип)?;
match левый_тип {
Тип::Нат64 => {
Тип::Нат64 | Тип::Нат8 | Тип::Цел64 => {
пп.код.push(Инструкция{ вид: ВидИнструкции::БитИ, лок: ключ.лок.clone() });
}
Тип::Лог => {
@ -952,6 +954,24 @@ fn скомпилировать_выражение(пп: &mut ПП, имена:
}
Ok(левый_тип.clone())
}
ВидБинопа::Либо => {
let левый_тип = скомпилировать_выражение(пп, имена, текущая_процедура, локальные_имена, &левое, временный_размер)?;
let правый_тип = скомпилировать_выражение(пп, имена, текущая_процедура, локальные_имена, &правое, временный_размер)?;
проверить_типы(правое.лок(), &левый_тип, &правый_тип)?;
match левый_тип {
Тип::Нат64 | Тип::Нат8 | Тип::Цел64 => {
пп.код.push(Инструкция{ вид: ВидИнструкции::БитЛибо, лок: ключ.лок.clone() });
}
Тип::Лог => {
пп.код.push(Инструкция{ вид: ВидИнструкции::ЛогЛибо, лок: ключ.лок.clone() });
}
_ => {
диагностика!(&левое.лок(), "ОШИБКА", "Операция «либо» не поддерживается для типов «{тип}»", тип = левый_тип.текст());
return Err(())
}
}
Ok(левый_тип.clone())
}
ВидБинопа::Сложение => {
let левый_тип = скомпилировать_выражение(пп, имена, текущая_процедура, локальные_имена, &левое, временный_размер)?;
let правый_тип = скомпилировать_выражение(пп, имена, текущая_процедура, локальные_имена, &правое, временный_размер)?;
@ -1061,6 +1081,8 @@ fn скомпилировать_выражение(пп: &mut ПП, имена:
return Ok(типели);
}
// СДЕЛАТЬ: конвертация из численных типов в логические должна преобразовывать все что != 0 в 1
// Иначе равенство не будет работать правильно.
match (&тип_значения, &типели) {
(Тип::Нат64, Тип::Нат8) => Ok(типели),
(Тип::Цел64, Тип::Нат8) => Ok(типели),

View File

@ -37,6 +37,7 @@ pub const КЛЮЧЕВЫЕ_СЛОВА: &[(&str, ВидЛексемы)] = &[
("вернуть", ВидЛексемы::КлючВернуть),
("или", ВидЛексемы::КлючИли),
("и", ВидЛексемы::КлючИ),
("либо", ВидЛексемы::КлючЛибо),
("нч", ВидЛексемы::КлючНч),
("кц", ВидЛексемы::КлючКц),
("как", ВидЛексемы::КлючКак),
@ -72,6 +73,7 @@ pub enum ВидЛексемы {
КлючНч,
КлючИли,
КлючИ,
КлючЛибо,
КлючКц,
КлючКак,
КлючВкл,
@ -129,6 +131,7 @@ impl ВидЛексемы {
ВидЛексемы::КлючПока => Сущ{текст: "«пока»", род: Род::Сред},
ВидЛексемы::КлючДля => Сущ{текст: "«для»", род: Род::Сред},
ВидЛексемы::КлючВернуть => Сущ{текст: "«вернуть»", род: Род::Сред},
ВидЛексемы::КлючЛибо => Сущ{текст: "«либо»", род: Род::Сред},
ВидЛексемы::КлючИли => Сущ{текст: "«или»", род: Род::Муж},
ВидЛексемы::КлючИ => Сущ{текст: "«и»", род: Род::Муж},
ВидЛексемы::КлючНч => Сущ{текст: "«нч»", род: Род::Сред},

View File

@ -32,6 +32,7 @@ pub enum ВидБинопа {
Остаток,
Или,
И,
Либо,
Равно,
НеРавно,
Как,
@ -46,7 +47,7 @@ impl ВидБинопа {
fn приоритет(&self) -> usize {
use self::ВидБинопа::*;
match self {
Или => Self::МАКСРИОРИТЕТ - 7,
Или | Либо => Self::МАКСРИОРИТЕТ - 7,
И => Self::МАКСРИОРИТЕТ - 6,
Меньше | Больше | МеньшеРавно | БольшеРавно | Равно | НеРавно => Self::МАКСРИОРИТЕТ - 5,
Сложение | Вычитание => Self::МАКСРИОРИТЕТ - 4,
@ -74,6 +75,7 @@ impl ВидБинопа {
ВидЛексемы::КлючКак => Some(ВидБинопа::Как),
ВидЛексемы::КлючИли => Some(ВидБинопа::Или),
ВидЛексемы::КлючИ => Some(ВидБинопа::И),
ВидЛексемы::КлючЛибо => Some(ВидБинопа::Либо),
ВидЛексемы::Точка => Some(ВидБинопа::Поле),
ВидЛексемы::КлючЛбс => Some(ВидБинопа::ЛевоеБитовоеСмещение),
ВидЛексемы::КлючПбс => Some(ВидБинопа::ПравоеБитовоеСмещение),

View File

@ -389,6 +389,10 @@ fn сгенерировать_инструкции(файл: &mut impl Write, п
let _ = writeln!(файл, " and rbx, rcx");
let _ = writeln!(файл, " push rbx");
}
ВидИнструкции::ЛогЛибо => {
сделать!(&инструкция.лок, "Кодогенерация инструкции «{вид:?}»", вид = инструкция.вид);
return Err(())
}
ВидИнструкции::БитИли => {
let _ = writeln!(файл, " pop rax");
let _ = writeln!(файл, " pop rbx");
@ -401,6 +405,12 @@ fn сгенерировать_инструкции(файл: &mut impl Write, п
let _ = writeln!(файл, " and rax, rbx");
let _ = writeln!(файл, " push rax");
}
ВидИнструкции::БитЛибо => {
let _ = writeln!(файл, " pop rax");
let _ = writeln!(файл, " pop rbx");
let _ = writeln!(файл, " xor rax, rbx");
let _ = writeln!(файл, " push rax");
}
ВидИнструкции::БитСмещениеВлево => {
let _ = writeln!(файл, " pop rcx");
let _ = writeln!(файл, " pop rax");

View File

@ -19,7 +19,8 @@
'("пер" "про" "конст" "пока" "нч" "кц" "для"
"если" "то" "иначе" "вернуть" "замкнуть" "пропустить"
"структ" "союз" "как" "вкл" "внешняя" "библ" "или"
"и" "истина" "ложь" "лбс" "пбс" "ост" "вилка" "когда" "любое")))
"и" "истина" "ложь" "лбс" "пбс" "ост" "вилка" "когда" "любое"
"либо")))
(defun строковый-литерал-хуя (придел)
(while (and (< (point) придел)