mirror of
https://github.com/tsoding/good_training_language.git
synced 2026-09-12 19:50:53 +05:00
Добавить биноп «либо»
This commit is contained in:
parent
bcf5cec08e
commit
47052e2d79
4
ПЛАН.txt
4
ПЛАН.txt
@ -49,8 +49,8 @@
|
||||
- [x] Массивы в полях структур
|
||||
- [ ] Все бинопы для всех релевантных типов в правой части
|
||||
- [x] НеРавно/Равно
|
||||
- [ ] Меньше/Больше/МеньшеРавно/БольшеРавно
|
||||
- [ ] и/или, добавить «либо» (исключающее или)
|
||||
- [x] Меньше/Больше/МеньшеРавно/БольшеРавно
|
||||
- [x] и/или, добавить «либо» (исключающее или)
|
||||
- [ ] сложение/вычитание/умножение/деление/остаток
|
||||
- [ ] конвертация между типами («как»)
|
||||
- [ ] битовые смещения
|
||||
|
||||
@ -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.вытолкнуть_значение_нат()?;
|
||||
|
||||
@ -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(тип_цели),
|
||||
|
||||
@ -37,6 +37,7 @@ pub const КЛЮЧЕВЫЕ_СЛОВА: &[(&str, ВидЛексемы)] = &[
|
||||
("вернуть", ВидЛексемы::КлючВернуть),
|
||||
("или", ВидЛексемы::КлючИли),
|
||||
("и", ВидЛексемы::КлючИ),
|
||||
("либо", ВидЛексемы::КлючЛибо),
|
||||
("нч", ВидЛексемы::КлючНч),
|
||||
("кц", ВидЛексемы::КлючКц),
|
||||
("как", ВидЛексемы::КлючКак),
|
||||
@ -72,6 +73,7 @@ pub enum ВидЛексемы {
|
||||
КлючНч,
|
||||
КлючИли,
|
||||
КлючИ,
|
||||
КлючЛибо,
|
||||
КлючКц,
|
||||
КлючКак,
|
||||
КлючВкл,
|
||||
@ -129,6 +131,7 @@ impl ВидЛексемы {
|
||||
ВидЛексемы::КлючПока => Сущ{текст: "«пока»", род: Род::Сред},
|
||||
ВидЛексемы::КлючДля => Сущ{текст: "«для»", род: Род::Сред},
|
||||
ВидЛексемы::КлючВернуть => Сущ{текст: "«вернуть»", род: Род::Сред},
|
||||
ВидЛексемы::КлючЛибо => Сущ{текст: "«либо»", род: Род::Сред},
|
||||
ВидЛексемы::КлючИли => Сущ{текст: "«или»", род: Род::Муж},
|
||||
ВидЛексемы::КлючИ => Сущ{текст: "«и»", род: Род::Муж},
|
||||
ВидЛексемы::КлючНч => Сущ{текст: "«нч»", род: Род::Сред},
|
||||
|
||||
@ -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(ВидБинопа::ПравоеБитовоеСмещение),
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -19,7 +19,8 @@
|
||||
'("пер" "про" "конст" "пока" "нч" "кц" "для"
|
||||
"если" "то" "иначе" "вернуть" "замкнуть" "пропустить"
|
||||
"структ" "союз" "как" "вкл" "внешняя" "библ" "или"
|
||||
"и" "истина" "ложь" "лбс" "пбс" "ост" "вилка" "когда" "любое")))
|
||||
"и" "истина" "ложь" "лбс" "пбс" "ост" "вилка" "когда" "любое"
|
||||
"либо")))
|
||||
|
||||
(defun строковый-литерал-хуя (придел)
|
||||
(while (and (< (point) придел)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user