diff --git a/исходники/компилятор.rs b/исходники/компилятор.rs index cc766a2..62091cf 100644 --- a/исходники/компилятор.rs +++ b/исходники/компилятор.rs @@ -454,6 +454,27 @@ fn скомпилировать_выражение(пп: &mut ПП, имена: } } +fn достать_и_проверить_процедуру_печати<'ы>(имена: &'ы Имена, имя_принтера: &str, тип: &Тип, лок: &Лок) -> Результат<&'ы СкомпПроцедура> { + if let Some(процедура) = имена.процедуры.get(имя_принтера) { + let арность = 1; + let [параметр] = процедура.параметры.as_slice() else { + диагностика!(лок, "ОШИБКА", "Процедура «{имя_принтера}» ответственная за печать данного аргумента типа «{тип}» имеет некорректную сигнатуру. Она должна принимать {арность} {параметров} типа «{тип}»", тип = тип.текст(), параметров = ЧИСУЩ_ПАРАМЕТР.текст(арность)); + диагностика!(&процедура.имя.лок, "ИНФО", "Но по факту, она принимает {число_параметров}", число_параметров = процедура.параметры.len()); + return Err(()); + }; + if параметр.тип != *тип { + диагностика!(лок, "ОШИБКА", "Процедура «{имя_принтера}» ответственная за печать данного аргумента типа «{тип}» имеет некорректную сигнатуру. Она должна принимать {арность} {параметров} типа «{тип}»", тип = тип.текст(), параметров = ЧИСУЩ_ПАРАМЕТР.текст(арность)); + диагностика!(&процедура.имя.лок, "ИНФО", "Но по факту, она принимает тип «{тип}»", тип = параметр.тип.текст()); + return Err(()); + } + + Ok(процедура) + } else { + диагностика!(лок, "ОШИБКА", "Чтобы печатать значения тип «{тип}», нужно чтобы где-нибудь была определена процедура с именем «{имя_принтера}», которая принимает один аргумент типа «{тип}» и печатает его. Мы не смогли найти определение такой процедуры. Обычно все нужные процедуры печати определены в модуле «прелюдия». Возможно мы не смогли его загрузить.", тип = тип.текст()); + Err(()) + } +} + fn скомпилировать_утвержление(пп: &mut ПП, имена: &Имена, параметры: &Vec<СкомпПараметр>, утверждение: &Утверждение) -> Результат<()> { match утверждение { Утверждение::Присваивание{ключ, имя, значение} => { @@ -530,18 +551,22 @@ fn скомпилировать_утвержление(пп: &mut ПП, имен for арг in аргументы { let тип = скомпилировать_выражение(пп, имена, параметры, &арг)?; match тип { - Тип::Строка => пп.код.push(Инструкция{ вид: ВидИнструкции::ПечатьСтроки, лок: имя.лок.clone() }), + Тип::Строка => { + пп.код.push(Инструкция{ вид: ВидИнструкции::ПечатьСтроки, лок: арг.лок().clone() }) + } Тип::Цел64 => { - сделать!(арг.лок(), "печать цел(8)"); - return Err(()) + let процедура = достать_и_проверить_процедуру_печати(имена, "печать_цел", &тип, &арг.лок())?; + пп.код.push(Инструкция { вид: ВидИнструкции::ВызватьПроцедуру(процедура.точка_входа), лок: арг.лок().clone() }); + пп.код.push(Инструкция { вид: ВидИнструкции::Вытолкнуть(процедура.параметры.len()), лок: арг.лок().clone() }); } Тип::Цел8 => { сделать!(арг.лок(), "печать цел(1)"); return Err(()) } Тип::Лог => { - сделать!(арг.лок(), "печать логического типа"); - return Err(()) + let процедура = достать_и_проверить_процедуру_печати(имена, "печать_лог", &тип, &арг.лок())?; + пп.код.push(Инструкция { вид: ВидИнструкции::ВызватьПроцедуру(процедура.точка_входа), лок: арг.лок().clone() }); + пп.код.push(Инструкция { вид: ВидИнструкции::Вытолкнуть(процедура.параметры.len()), лок: арг.лок().clone() }); } Тип::Массив{..} => { сделать!(арг.лок(), "печать массивов"); diff --git a/прелюдия.хуя b/прелюдия.хуя index acdb151..d9dcf8e 100644 --- a/прелюдия.хуя +++ b/прелюдия.хуя @@ -2,6 +2,9 @@ пер буфер: массив(ОБЪЁМ, цел8); пер размер: цел; +// СДЕЛАТЬ: загрузка модуля «прелюдия» (я пока не знаю как) +// СДЕЛАТЬ: ввести функцию печать_строки, которая делает системный вызов SYS_write + про печать_цел(число: цел) нч если число == 0 нч печать(«0»); @@ -32,17 +35,12 @@ кц про тест(а: цел, б: цел) нч - печать_цел(а + б); - печать(«\н»); + печать(а + б, «\н»); кц про главная() нч - печать_цел(0); печать(«\н»); - печать_цел(69); печать(«\н»); - печать_цел(1234567890); печать(«\н»); - печать(«----------\н»); - печать_лог(69 == 69); печать(«\н»); - печать_лог(69 == 420); печать(«\н»); + печать(«Печать чисел: », 0, «, », 69, «, », 1234567890, «\н»); + печать(«Печать логических: », 69 == 69, «, », 69 == 420, «\н»); печать(«----------\н»); тест(34, 35); кц