From 47052e2d796ebf3113fa60458212200ab2db57eb Mon Sep 17 00:00:00 2001 From: rexim Date: Mon, 1 Apr 2024 15:35:21 +0700 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20=D0=B1=D0=B8=D0=BD=D0=BE=D0=BF=20=C2=AB=D0=BB=D0=B8?= =?UTF-8?q?=D0=B1=D0=BE=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ПЛАН.txt | 4 ++-- исходники/интерпретатор.rs | 12 ++++++++++++ исходники/компилятор.rs | 26 ++++++++++++++++++++++++-- исходники/лексика.rs | 3 +++ исходники/синтаксис.rs | 4 +++- исходники/фазм.rs | 10 ++++++++++ редакторы/режим-хуя.el | 3 ++- 7 files changed, 56 insertions(+), 6 deletions(-) diff --git a/ПЛАН.txt b/ПЛАН.txt index 51b24cc..01c2a81 100644 --- a/ПЛАН.txt +++ b/ПЛАН.txt @@ -49,8 +49,8 @@ - [x] Массивы в полях структур - [ ] Все бинопы для всех релевантных типов в правой части - [x] НеРавно/Равно - - [ ] Меньше/Больше/МеньшеРавно/БольшеРавно - - [ ] и/или, добавить «либо» (исключающее или) + - [x] Меньше/Больше/МеньшеРавно/БольшеРавно + - [x] и/или, добавить «либо» (исключающее или) - [ ] сложение/вычитание/умножение/деление/остаток - [ ] конвертация между типами («как») - [ ] битовые смещения diff --git a/исходники/интерпретатор.rs b/исходники/интерпретатор.rs index bd6b50a..1c3d5e6 100644 --- a/исходники/интерпретатор.rs +++ b/исходники/интерпретатор.rs @@ -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.вытолкнуть_значение_нат()?; diff --git a/исходники/компилятор.rs b/исходники/компилятор.rs index 011bd16..14783a4 100644 --- a/исходники/компилятор.rs +++ b/исходники/компилятор.rs @@ -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(тип_цели), diff --git a/исходники/лексика.rs b/исходники/лексика.rs index 3dd6078..ade8987 100644 --- a/исходники/лексика.rs +++ b/исходники/лексика.rs @@ -37,6 +37,7 @@ pub const КЛЮЧЕВЫЕ_СЛОВА: &[(&str, ВидЛексемы)] = &[ ("вернуть", ВидЛексемы::КлючВернуть), ("или", ВидЛексемы::КлючИли), ("и", ВидЛексемы::КлючИ), + ("либо", ВидЛексемы::КлючЛибо), ("нч", ВидЛексемы::КлючНч), ("кц", ВидЛексемы::КлючКц), ("как", ВидЛексемы::КлючКак), @@ -72,6 +73,7 @@ pub enum ВидЛексемы { КлючНч, КлючИли, КлючИ, + КлючЛибо, КлючКц, КлючКак, КлючВкл, @@ -129,6 +131,7 @@ impl ВидЛексемы { ВидЛексемы::КлючПока => Сущ{текст: "«пока»", род: Род::Сред}, ВидЛексемы::КлючДля => Сущ{текст: "«для»", род: Род::Сред}, ВидЛексемы::КлючВернуть => Сущ{текст: "«вернуть»", род: Род::Сред}, + ВидЛексемы::КлючЛибо => Сущ{текст: "«либо»", род: Род::Сред}, ВидЛексемы::КлючИли => Сущ{текст: "«или»", род: Род::Муж}, ВидЛексемы::КлючИ => Сущ{текст: "«и»", род: Род::Муж}, ВидЛексемы::КлючНч => Сущ{текст: "«нч»", род: Род::Сред}, diff --git a/исходники/синтаксис.rs b/исходники/синтаксис.rs index 1d627ac..3cb217c 100644 --- a/исходники/синтаксис.rs +++ b/исходники/синтаксис.rs @@ -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(ВидБинопа::ПравоеБитовоеСмещение), diff --git a/исходники/фазм.rs b/исходники/фазм.rs index 9999466..b608b1b 100644 --- a/исходники/фазм.rs +++ b/исходники/фазм.rs @@ -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"); diff --git a/редакторы/режим-хуя.el b/редакторы/режим-хуя.el index d26af75..4ea6b7e 100644 --- a/редакторы/режим-хуя.el +++ b/редакторы/режим-хуя.el @@ -19,7 +19,8 @@ '("пер" "про" "конст" "пока" "нч" "кц" "для" "если" "то" "иначе" "вернуть" "замкнуть" "пропустить" "структ" "союз" "как" "вкл" "внешняя" "библ" "или" - "и" "истина" "ложь" "лбс" "пбс" "ост" "вилка" "когда" "любое"))) + "и" "истина" "ложь" "лбс" "пбс" "ост" "вилка" "когда" "любое" + "либо"))) (defun строковый-литерал-хуя (придел) (while (and (< (point) придел)