Операторы сравнения

This commit is contained in:
rexim 2024-03-27 08:16:40 +07:00
parent 5b46392f99
commit f7f0ee1b1c
14 changed files with 105 additions and 60 deletions

View File

@ -40,24 +40,24 @@
- [x] Многострочные комментарии
- [x] Не забудь избавить от прямого доступа к символам, чтобы случайно не крашнуться.
- [x] «для» должен неявно объявлять переменную
- [ ] Операторы сравнения -\ /- =\ /=
- [x] Операторы сравнения
- [ ] Экранирование «ёлочек»
- [ ] Switch-case-ы в каком-то виде («вилка»)
- [ ] Аналоги операций выхода из циклов (continue, break)
- [ ] Шестнадцатеричные литералы
- [ ] Что дальше?
- То, что не успели в предыдущем месяце
- [ ] Перечисления в каком-нибудь виде
- [ ] Динамическая память в каком-нибудь виде
- [ ] Передача переменных по ссылке
- Примеры
- [x] Rule110
- [ ] Mandelbrot
- Низкий приоритет
- [ ] Переменная «результат» как в Паскале.
- Если есть передача аргументов по-ссылке, то оно особо и не нужно.
- [ ] Провека, что все потоки исполнения возвращают значение.
- [ ] Выравнивание структур как в Си
- [ ] WebAssembly
- [ ] Не прерывай компиляцию из-за одной лишь ошибки.
- [ ] Перечисления в каком-нибудь виде
- [ ] Динамическая память в каком-нибудь виде
- [ ] Передача переменных по ссылке

View File

@ -381,6 +381,30 @@ fn скомпилировать_выражение(пп: &mut ПП, имена:
}
}
}
ВидБинопа::НеРавно => {
let левый_тип = скомпилировать_выражение(пп, имена, текущая_процедура, локальные_имена, &левое, временный_размер)?;
let правый_тип = скомпилировать_выражение(пп, имена, текущая_процедура, локальные_имена, &правое, временный_размер)?;
проверить_типы(правое.лок(), &левый_тип, &правый_тип)?;
match левый_тип {
Тип::Нат64 | Тип::Цел64 | Тип::Нат8 => {
пп.код.push(Инструкция{ вид: ВидИнструкции::НатРавно, лок: ключ.лок.clone() });
пп.код.push(Инструкция{ вид: ВидИнструкции::ЛогОтрицание, лок: ключ.лок.clone() });
Ok(Тип::Лог)
}
_ => {
сделать!(левое.лок(), "Сравнение типа «{тип}»", тип = левый_тип.текст());
Err(())
}
}
}
ВидБинопа::МеньшеРавно => {
сделать!(&ключ.лок, "Реализовать биноп МеньшеРавно");
return Err(());
}
ВидБинопа::БольшеРавно => {
сделать!(&ключ.лок, "Реализовать биноп БольшеРавно");
return Err(());
}
ВидБинопа::Меньше => {
let левый_тип = скомпилировать_выражение(пп, имена, текущая_процедура, локальные_имена, &левое, временный_размер)?;
let правый_тип = скомпилировать_выражение(пп, имена, текущая_процедура, локальные_имена, &правое, временный_размер)?;

View File

@ -12,11 +12,21 @@ pub const ПРИСТАВКИ_ПРЕПИНАНИЙ: &[(&[char], ВидЛексе
(&[':', '='], ВидЛексемы::Присваивание),
(&[':'], ВидЛексемы::Двоеточие),
(&[','], ВидЛексемы::Запятая),
(&['+', '!', '='], ВидЛексемы::МеньшеЛи),
(&['+', '!'], ВидЛексемы::МеньшеРавноЛи),
(&['+', '?', '='], ВидЛексемы::БольшеРавноЛи),
(&['+', '?'], ВидЛексемы::БольшеЛи),
(&['+'], ВидЛексемы::Плюс),
(&['-', '!', '='], ВидЛексемы::БольшеЛи),
(&['-', '!'], ВидЛексемы::БольшеРавноЛи),
(&['-', '?', '='], ВидЛексемы::МеньшеРавноЛи),
(&['-', '?'], ВидЛексемы::МеньшеЛи),
(&['-'], ВидЛексемы::Минус),
(&['*'], ВидЛексемы::Звёздочка),
(&['/'], ВидЛексемы::ПрямаяНаклонная),
(&['=', '='], ВидЛексемы::РавноРавно),
(&['?', '='], ВидЛексемы::РавноЛи),
(&['!', '='], ВидЛексемы::НеРавноЛи),
(&['!'], ВидЛексемы::Не),
(&['='], ВидЛексемы::Равно),
];
@ -30,9 +40,6 @@ pub const КЛЮЧЕВЫЕ_СЛОВА: &[(&str, ВидЛексемы)] = &[
("пока", ВидЛексемы::КлючПока),
("для", ВидЛексемы::КлючДля),
("вернуть", ВидЛексемы::КлючВернуть),
("не", ВидЛексемы::КлючНе),
("мн", ВидЛексемы::КлючМн),
("бл", ВидЛексемы::КлючБл),
("или", ВидЛексемы::КлючИли),
("и", ВидЛексемы::КлючИ),
("нч", ВидЛексемы::КлючНч),
@ -64,9 +71,6 @@ pub enum ВидЛексемы {
КлючПока,
КлючДля,
КлючВернуть,
КлючНе,
КлючМн,
КлючБл,
КлючНч,
КлючИли,
КлючИ,
@ -95,7 +99,13 @@ pub enum ВидЛексемы {
ПрямаяНаклонная,
Присваивание,
Равно,
РавноРавно,
РавноЛи,
МеньшеЛи,
МеньшеРавноЛи,
БольшеЛи,
БольшеРавноЛи,
Не,
НеРавноЛи,
ЦелЧисло,
ВещЧисло,
@ -118,9 +128,6 @@ impl ВидЛексемы {
ВидЛексемы::КлючПока => Сущ{текст: "«пока»", род: Род::Сред},
ВидЛексемы::КлючДля => Сущ{текст: "«для»", род: Род::Сред},
ВидЛексемы::КлючВернуть => Сущ{текст: "«вернуть»", род: Род::Сред},
ВидЛексемы::КлючНе => Сущ{текст: "«не»", род: Род::Сред},
ВидЛексемы::КлючМн => Сущ{текст: "«мн»", род: Род::Сред},
ВидЛексемы::КлючБл => Сущ{текст: "«бл»", род: Род::Сред},
ВидЛексемы::КлючИли => Сущ{текст: "«или»", род: Род::Муж},
ВидЛексемы::КлючИ => Сущ{текст: "«и»", род: Род::Муж},
ВидЛексемы::КлючНч => Сущ{текст: "«нч»", род: Род::Сред},
@ -149,8 +156,14 @@ impl ВидЛексемы {
ВидЛексемы::Звёздочка => Сущ{текст: "звёздочка", род: Род::Жен},
ВидЛексемы::ПрямаяНаклонная => Сущ{текст: "прямая наклонная черта", род: Род::Жен},
ВидЛексемы::Равно => Сущ{текст: "равно", род: Род::Сред},
ВидЛексемы::РавноРавно => Сущ{текст: "двойное равно", род: Род::Сред},
ВидЛексемы::Присваивание => Сущ{текст: "присваивание", род: Род::Сред},
ВидЛексемы::РавноЛи => Сущ{текст: "«равно ли»", род: Род::Сред},
ВидЛексемы::МеньшеЛи => Сущ{текст: "«меньше ли»", род: Род::Сред},
ВидЛексемы::БольшеЛи => Сущ{текст: "«больше ли»", род: Род::Сред},
ВидЛексемы::МеньшеРавноЛи => Сущ{текст: "«меньше либо равно ли»", род: Род::Сред},
ВидЛексемы::БольшеРавноЛи => Сущ{текст: "«больше либо равно ли»", род: Род::Сред},
ВидЛексемы::Не => Сущ{текст: "«не»", род: Род::Сред},
ВидЛексемы::НеРавноЛи => Сущ{текст: "«не равно ли»", род: Род::Сред},
ВидЛексемы::ЦелЧисло => Сущ{текст: "целое число", род: Род::Сред},
ВидЛексемы::ВещЧисло => Сущ{текст: "вещественное число", род: Род::Сред},

View File

@ -23,6 +23,8 @@ impl Переменная {
pub enum ВидБинопа {
Меньше,
Больше,
МеньшеРавно,
БольшеРавно,
Сложение,
Вычитание,
Умножение,
@ -31,6 +33,7 @@ pub enum ВидБинопа {
Или,
И,
Равно,
НеРавно,
Как,
Поле,
ЛевоеБитовоеСмещение,
@ -43,35 +46,38 @@ impl ВидБинопа {
fn приоритет(&self) -> usize {
use self::ВидБинопа::*;
match self {
Или => Self::МАКСРИОРИТЕТ - 7,
И => Self::МАКСРИОРИТЕТ - 6,
Меньше | Больше | Равно => Self::МАКСРИОРИТЕТ - 5,
Сложение | Вычитание => Self::МАКСРИОРИТЕТ - 4,
Умножение | Деление | Остаток => Self::МАКСРИОРИТЕТ - 3,
Или => Self::МАКСРИОРИТЕТ - 7,
И => Self::МАКСРИОРИТЕТ - 6,
Меньше | Больше | МеньшеРавно | БольшеРавно | Равно | НеРавно => Self::МАКСРИОРИТЕТ - 5,
Сложение | Вычитание => Self::МАКСРИОРИТЕТ - 4,
Умножение | Деление | Остаток => Self::МАКСРИОРИТЕТ - 3,
// СДЕЛАТЬ: какой приоритет лучше всего для битовых смещений?
ЛевоеБитовоеСмещение | ПравоеБитовоеСмещение => Self::МАКСРИОРИТЕТ - 2,
Как => Self::МАКСРИОРИТЕТ - 1,
Поле => Self::МАКСРИОРИТЕТ,
ЛевоеБитовоеСмещение | ПравоеБитовоеСмещение => Self::МАКСРИОРИТЕТ - 2,
Как => Self::МАКСРИОРИТЕТ - 1,
Поле => Self::МАКСРИОРИТЕТ,
}
}
fn по_видуексемы(вид: &ВидЛексемы) -> Option<ВидБинопа> {
match вид {
ВидЛексемы::КлючМн => Some(ВидБинопа::Меньше),
ВидЛексемы::КлючБл => Some(ВидБинопа::Больше),
ВидЛексемы::РавноЛи => Some(ВидБинопа::Равно),
ВидЛексемы::МеньшеЛи => Some(ВидБинопа::Меньше),
ВидЛексемы::БольшеЛи => Some(ВидБинопа::Больше),
ВидЛексемы::МеньшеРавноЛи => Some(ВидБинопа::МеньшеРавно),
ВидЛексемы::БольшеРавноЛи => Some(ВидБинопа::БольшеРавно),
ВидЛексемы::НеРавноЛи => Some(ВидБинопа::НеРавно),
ВидЛексемы::Плюс => Some(ВидБинопа::Сложение),
ВидЛексемы::Минус => Some(ВидБинопа::Вычитание),
ВидЛексемы::Звёздочка => Some(ВидБинопа::Умножение),
ВидЛексемы::ПрямаяНаклонная => Some(ВидБинопа::Деление),
ВидЛексемы::КлючОст => Some(ВидБинопа::Остаток),
ВидЛексемы::РавноРавно => Some(ВидБинопа::Равно),
ВидЛексемы::КлючКак => Some(ВидБинопа::Как),
ВидЛексемы::КлючИли => Some(ВидБинопа::Или),
ВидЛексемы::КлючИ => Some(ВидБинопа::И),
ВидЛексемы::Точка => Some(ВидБинопа::Поле),
ВидЛексемы::КлючЛбс => Some(ВидБинопа::ЛевоеБитовоеСмещение),
ВидЛексемы::КлючПбс => Some(ВидБинопа::ПравоеБитовоеСмещение),
_ => None
_ => None
}
}
}
@ -124,7 +130,7 @@ impl Выражение {
ВидЛексемы::Идент,
ВидЛексемы::Строка,
ВидЛексемы::ОткрытаяСкобка,
ВидЛексемы::КлючНе,
ВидЛексемы::Не,
ВидЛексемы::КлючИстина,
ВидЛексемы::КлючЛожь,
ВидЛексемы::Минус,
@ -183,7 +189,7 @@ impl Выражение {
let _ = лекс.вытащитьексему_вида(&[ВидЛексемы::ЗакрытаяСкобка])?;
Ok(выражение)
}
ВидЛексемы::КлючНе => {
ВидЛексемы::Не => {
let ключ = лексема;
let выражение = Box::new(Выражение::разобрать(лекс)?);
Ok(Выражение::Отрицание{ключ, выражение})

View File

@ -4,7 +4,7 @@
// Хотя, мы тогда теряем возможность печатать строки в режиме интерпретации.
про печать_нат(число: нат) нч
если число == 0нат нч
если число ?= 0нат нч
печать(«0»);
вернуть;
кц
@ -13,7 +13,7 @@
пер буфер: массив(ОБЪЁМ, нат8);
пер размер: нат = 0нат;
пока число блат нч
пока число +?ат нч
// СДЕЛАТЬ: размер += 1;
размер := размер + 1нат;
буфер(ОБЪЁМ как нат - размер) := (число ост 10нат + 48нат) как нат8; // СДЕЛАТЬ: буквенные литералы
@ -25,7 +25,7 @@
кц
про печать_цел(число: цел) нч
если число мн 0 как цел нч
если число -? 0 как цел нч
печать(«-»);
число := -число;
кц

View File

@ -11,6 +11,7 @@
пер длинна: нат = ввод(имя);
// СДЕЛАТЬ: Логические операции с коротким замыканиям
// Нужны ли они вообще?
если длинна бл 0нат то если имя(длинна-1нат) == 10нат как нат8 то длинна := длинна - 1нат;
если длинна +? 0нат то если имя(длинна-1нат) ?= 10нат как нат8 то длинна := длинна - 1нат;
// СДЕЛАТЬ: Однобайтовые литералы 10нат8
печать(«Привет, », срез(имя, 0нат, длинна), «!\н»);
кц

View File

@ -4,10 +4,10 @@
// СДЕЛАТЬ: объявление индексной переменной прямо в цикле
// для пер счет := 1..100 нч
для счет := 1..100 нч
если счет ост 15 == 0 то печать(«ФиззБазз\н»);
если счет ост 15 ?= 0 то печать(«ФиззБазз\н»);
// СДЕЛАТЬ: подумать как сократить конструкцию «иначе то если»
иначе то если счет ост 3 == 0 то печать(«Физз\н»);
иначе то если счет ост 5 == 0 то печать(«Базз\н»);
иначе то если счет ост 3 ?= 0 то печать(«Физз\н»);
иначе то если счет ост 5 ?= 0 то печать(«Базз\н»);
иначе то печать(счет, «\н»);
кц
кц

View File

@ -8,7 +8,7 @@
// пер а, б, в: нат;
пер а: цел = 0;
пер б: цел = 1;
пока а мн ЛИМИТ нч
пока а -? ЛИМИТ нч
печать(а, «\н»);
пер в: цел = а + б;
а := б;

View File

@ -2,7 +2,8 @@
// СДЕЛАТЬ: шестнадцатеричные литералы
// ABCDEF
// АБСДЕФ
// АБЦДЕФ
// Походу не первый, кто до этого додумался: http://compiler.su/shestnadtsatirichnye-i-dvoichnye-konstanty.php
конст ЦВЕТОНА = 4279769112нат; // 16%ФФ181818нат
конст ЦВЕТ_КРАСНЫЙ = 4278190335нат; // 16%ФФ0000ФФнат
@ -36,25 +37,25 @@
открыть_окно(800, 600, адрес(«Привет, Raylib!»));
установить_целевую_частотуадров(60);
пер пауза: лог = ложь;
пока не пораакрыть_окно() нч
пока !пораакрыть_окно() нч
пер дельтаремени : вещ = получить_время_кадра();
пер ширина_экрана : вещ = получить_ширину_экрана() как вещ;
пер высота_экрана : вещ = получить_высоту_экрана() как вещ;
если нажата_клавиша(КЛАВИШАРОБЕЛ) то пауза := не пауза;
если нажата_клавиша(КЛАВИШАРОБЕЛ) то пауза := !пауза;
начать_рисовать();
очистить_фон(ЦВЕТОНА);
для индекс := 0..ОБЪЁМ-1 нч
если не пауза нч
если !пауза нч
пер новая_позиция: Вектор2;
новая_позиция.икс := позиции(индекс).икс + дельты(индекс).икс*дельтаремени;
если новая_позиция.икс мн 0.0 или новая_позиция.икс + ШИРИНА как вещ бл ширина_экрана
если новая_позиция.икс -? 0.0 или новая_позиция.икс + ШИРИНА как вещ +? ширина_экрана
то дельты(индекс).икс := -(дельты(индекс).икс); // СДЕЛАТЬ: можно ли как-то распарсить чтобы не нужны были скобки?
иначе то позиции(индекс).икс := новая_позиция.икс;
новая_позиция.игрек := позиции(индекс).игрек + дельты(индекс).игрек*дельтаремени;
если новая_позиция.игрек мн 0.0 или новая_позиция.игрек + ВЫСОТА как вещ бл высота_экрана
если новая_позиция.игрек -? 0.0 или новая_позиция.игрек + ВЫСОТА как вещ +? высота_экрана
то дельты(индекс).игрек := -(дельты(индекс).игрек);
иначе то позиции(индекс).игрек := новая_позиция.игрек;
кц

View File

@ -6,7 +6,7 @@
про отступ(ширина: цел) то для индекс := 1..ширина то печать(« »);
про дерево(глубина: цел) нч
если глубина бл МАКС_ГЛУБИНА то вернуть;
если глубина +? МАКС_ГЛУБИНА то вернуть;
дерево(глубина + 1);
отступ(глубина*2);
счетчик := счетчик + 1;

View File

@ -7,14 +7,14 @@
// СДЕЛАТЬ: передача массива по ссылке
про печать_мира(мир: массив(РАЗМЕР, нат)) нч
для индекс := 1..РАЗМЕР то
если мир(индекс - 1) == 0нат
если мир(индекс - 1) ?= 0нат
то печать(«_»);
иначе то печать(«%»);
печать(«\н»);
кц
про главная() нч
если РАЗМЕР мн 3 то вернуть;
если РАЗМЕР -? 3 то вернуть;
мир0(РАЗМЕР - 2) := 1нат;
печать_мира(мир0);

View File

@ -32,12 +32,12 @@
пер соседи : цел = 0;
для дстр := -1..1 то
для дстл := -1..1 то
если не (дстр == 0 и дстл == 0) нч
если дстр != 0 или дстл != 0 нч
пер строка: цел = строка0 + дстр;
пер столбец: цел = столбец0 + дстл;
// СДЕЛАТЬ: Биноп для «меньше либо равно».
если (0 мн строка или строка == 0) и строка мн ВЫСОТА то
если (0 мн столбец или столбец == 0) и столбец мн ШИРИНА то
если (0 -? строка или строка ?= 0) и строка -? ВЫСОТА то
если (0 -? столбец или столбец ?= 0) и столбец -? ШИРИНА то
если поле(строка)(столбец) то соседи := соседи + 1;
кц
вернуть соседи;
@ -48,8 +48,8 @@
для столбец := 1..ШИРИНА нч
пер соседи: цел = подсчитать_соседей(строка - 1, столбец - 1);
если поле(строка - 1)(столбец - 1)
то скрытое_поле(строка - 1)(столбец - 1) := соседи == 2 или соседи == 3;
иначе то скрытое_поле(строка - 1)(столбец - 1) := соседи == 3;
то скрытое_поле(строка - 1)(столбец - 1) := соседи ?= 2 или соседи ?= 3;
иначе то скрытое_поле(строка - 1)(столбец - 1) := соседи ?= 3;
кц
кц

View File

@ -16,9 +16,9 @@
(eval-and-compile
(defconst ключевые-слова-хуя
'("пер" "про" "конст" "пока" "мн" "бл" "нч" "кц" "для"
'("пер" "про" "конст" "пока" "нч" "кц" "для"
"если" "то" "иначе" "вернуть" "замкнуть" "пропустить"
"структ" "союз" "как" "вкл" "внешняя" "не" "библ" "или"
"структ" "союз" "как" "вкл" "внешняя" "библ" "или"
"и" "истина" "ложь" "лбс" "пбс" "ост")))
(defconst подсветка-хуя

View File

@ -11,8 +11,8 @@
про тест_вещественных_чисел() нч
печать(«Вещественная арифметика: », (17.0*2.0 + 35.0) как нат, «\н»);
печать(«Вещественное отрицание: », -69.0 мн 0.0, «\н»);
печать(«Вещественная логика: », 69.0 мн 420.0, « », 69.0 бл 420.0, «\н»);
печать(«Вещественное отрицание: », -69.0 -? 0.0, «\н»);
печать(«Вещественная сравнение: », 69.0 -? 420.0, « », 69.0 +? 420.0, «\н»);
кц
про баг_при_выделении_локальной_переменной_в_цикле_для() то // некорректно обозначались области видимости
@ -38,7 +38,7 @@
про главная() нч
печать(«Печать чисел: », 0, «, », 69, «, », 1234567890, «\н»);
печать(«Печать логических: », 69 == 69, «, », 69 == 420, «\н»);
печать(«Печать логических: », 69 ?= 69, «, », 69 ?= 420, «\н»);
печать(«Адрес строки: », адрес(«привет»), «\н»);
тест_передачи_аргументов_функции(34нат, 35нат);
тест_порядка_передачи_аргументов_функции(1нат, 2нат, 3нат, 4нат);