LINUX.ORG.RU

Zig 0.11

 , ,


1

3

Спустя 8 месяцев и 4457 коммитов от 269 различных участников вышла новая версия Zig.

Zig — это (кросс-)компилятор языков программирования Zig, С++, С, Objective-C, Objective-C++, а также сборочная система и менеджер пакетов для них. Проект разрабатывается под лицензией MIT. Недавно в Zig Core Team вошёл ещё один разработчик на зарплате: Jacob Young.

В новой версии:

  • Появился пакетный менеджер.
  • Улучшена поддержка powerpc, powerpc64le и Plan9.
  • Архитектура i386 переименована в x86.
  • Множественные улучшения и исправления для WebAssembly и появление специфичного для него аллокатора wasm_allocator.
  • Реализация компилятора Zig на Zig (self-hosted) полностью готова, а старый компилятор на C++ «выкинут на орбиту» (требования к ОЗУ для сборки снижены с 11 до 4 ГБ).
  • Обновлены сторонние компоненты:
    • LLVM 16.0.6;
    • musl 1.2.4;
    • wasi-libc 3189cd1ceec8771e8f27faab58ad05d4d6c369ef;
  • Множество изменений в стандартной библиотеке (подробнее).

>>> Подробности

anonymous

Проверено: cetjs2 ()
Последнее исправление: cetjs2 (всего исправлений: 3)

с одной стороны вроде все правильно делают, вот и llvm хотят выкинуть и запилить полностью свой компилятор, с другой - какие-то у них загоны. Вместо того чтобы признать что таки да, указатель может быть нулем и ничего ты с этим не сделаешь, они фигачат какой-то наркоманский синтаксис вроде вот этого ?*Node.

Или обработка ошибок - ну нельзя сделать ничего нормального на кодах возврата. Да и не на кодах тоже, это целиком ответственность разработчика а не компилятора. В zig опять же отказываются это признать и фигачат какие-то orelse, которые только мешают…

Lrrr ★★★★★
()
Ответ на: комментарий от BratishkaErik

ну я и говорю, какие-то мусорные специальные ключевые слова и касты, в которых потом весь код будет. Если юзерам так нужны ненулевые указатели (спойлер, они им нафиг не нужны), они могут сделать нужные структуры на уровне своих юзерских библиотек, зачем этим язык-то замусоривать?

Lrrr ★★★★★
()
Ответ на: комментарий от Lrrr

чёт сообщение не редактируется, ну ладно.

спойлер, они им нафиг не нужны

Нужны, и в Сишке нужны, оттого и пользуется народ всякими

__attribute__((notnull(blablabla)))

Здесь им просто уделили больше внимания и ээ любви.

на уровне своих юзерских библиотек

Помянем экосистему, эргономичность и возможности для оптимизации компилятором… :свечка: Вообще если кто-то хочет сравнить (офк приблизительно) код на Зиге и Си, у меня тут маленькая обвязка над libgccjit есть, туториалы плюс-минус строка в строку портировал (я не мастер Zig, так шо код может где-то страшно выглядеть):

https://git.sr.ht/~bratishkaerik/zig-libgccjit/tree/3c21e0bf8d9f4462f79059da1320679e012eafd0/item/examples/official_tutorial_part_1/src/main.zig

fn create_code(ctxt: *GccJit.Context) void {
    // Let's try to inject the equivalent of following function:

    // C form:
    // void
    // greet (const char *name)
    // {
    //    printf ("hello %s\n", name);
    // }

    // C-in-Zig form:
    // fn greet(name: [*:0]const u8) callconv(.C) void {
    //    printf("hello %s\n", name);
    // }

    const void_type: *GccJit.Type = ctxt.getType(.void);
    const const_char_ptr_type: *GccJit.Type = ctxt.getType(.const_char_ptr);
    const param_name: *GccJit.Param = ctxt.newParam(.no_location, const_char_ptr_type, "name");
    const func: *GccJit.Function = ctxt.newFunction(.no_location, .exported, void_type, "greet", @constCast(&[_]*GccJit.Param{param_name}), .not_variadic);

    const param_format: *GccJit.Param = ctxt.newParam(.no_location, const_char_ptr_type, "format");
    const printf_func: *GccJit.Function = ctxt.newFunction(.no_location, .imported, ctxt.getType(.int), "printf", @constCast(&[_]*GccJit.Param{param_format}), .variadic);
    var args: [2]*GccJit.Rvalue = undefined;
    args[0] = ctxt.newStringLiteral("hello %s\n");
    args[1] = param_name.asRvalue();

    const block: *GccJit.Block = func.newBlock(.no_name);

    block.addEval(.no_location, ctxt.newCall(.no_location, printf_func, &args));
    block.endWithVoidReturn(.no_location);
}

https://gcc.gnu.org/onlinedocs/gcc-12.2.0/jit/intro/tutorial01.html

  /* Let's try to inject the equivalent of:
     void
     greet (const char *name)
     {
        printf ("hello %s\n", name);
     }
  */
  gcc_jit_type *void_type =
    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
  gcc_jit_type *const_char_ptr_type =
    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CONST_CHAR_PTR);
  gcc_jit_param *param_name =
    gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "name");
  gcc_jit_function *func =
    gcc_jit_context_new_function (ctxt, NULL,
                                  GCC_JIT_FUNCTION_EXPORTED,
                                  void_type,
                                  "greet",
                                  1, &param_name,
                                  0);

  gcc_jit_param *param_format =
    gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "format");
  gcc_jit_function *printf_func =
    gcc_jit_context_new_function (ctxt, NULL,
				  GCC_JIT_FUNCTION_IMPORTED,
				  gcc_jit_context_get_type (
				     ctxt, GCC_JIT_TYPE_INT),
				  "printf",
				  1, &param_format,
				  1);
  gcc_jit_rvalue *args[2];
  args[0] = gcc_jit_context_new_string_literal (ctxt, "hello %s\n");
  args[1] = gcc_jit_param_as_rvalue (param_name);

  gcc_jit_block *block = gcc_jit_function_new_block (func, NULL);

  gcc_jit_block_add_eval (
    block, NULL,
    gcc_jit_context_new_call (ctxt,
                              NULL,
                              printf_func,
                              2, args));
  gcc_jit_block_end_with_void_return (block, NULL);
BratishkaErik
()
Ответ на: комментарий от BratishkaErik

чёт сообщение не редактируется, ну ладно.

На этом сайте какое-то странное правило, что малозвездочным савсем вапще низзя комменты редактировать.

Ладно, теперь по делу. Ты этот язык знаешь более-менее? У меня вопросы.

1. Как там с типизацией постфактум, что обычно известно как имплементация интерфейсов или трейтов? Т.е. скажем Вася Пупкин написал класс, или даже разрабы этого зига написали свою std (как она у них там). А я хочу написать свой интерфейс (или класс, мне пофиг), и сказать: ваш класс выполняет мой интерфейс, вот смотрите: код-код-код ... . При этом править Васин класс и класс из std нельзя.

2. Как там с обработкой ошибок? Можно превращать воду в вино исключения в Optional (как он в зиге называется?) и обратно?

www_linux_org_ru ★★★★★
()
Последнее исправление: www_linux_org_ru (всего исправлений: 2)
Ответ на: комментарий от www_linux_org_ru
  1. Как там с типизацией постфактум, что обычно известно как имплементация интерфейсов или трейтов? Т.е. скажем Вася Пупкин написал класс, или даже разрабы этого зига написали свою std (как она у них там). А я хочу написать свой интерфейс (или класс, пофиг), и сказать: ваш класс выполняет мой интерфейс, вот смотрите: … .

На уровне языка никак, предварительный вердикт. Ещё предлагают добавить std.interface, но его пока тоже нет (есть кусочки в std.meta.trait по типу hasFn и прочих), и сторонние библиотеки по типу https://github.com/mov-rax/zig-validate.

  1. Как там с обработкой ошибок? Можно превращать воду в вино исключения в Optional (как он в зиге называется?) и обратно?
pub fn mayFall(smth: bool) error{Fall}!u32 {
    return if (smth) 0 else error.Fall;
}

pub fn theBestU64() ?u64 {
    const optional_u32 = mayFall(false) catch null; // ошибку в опциональный тип
    const errored_u32 = optional_u32 orelse error.WhyNull; // и обратно
    const optional_u64: ?u64 = errored_u32 catch null; // и обратно
    return optional_u64;
}

const std = @import("std");

pub fn main() void {
    @compileLog(comptime theBestU64()); // вызвать во время компиляции
    @compileLog(theBestU64()); // простой вызов во время выполнения
}

Вывод:

test.zig:15:5: error: found compile log statement
    @compileLog(comptime theBestU64()); // вызвать во время компиляции
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Compile Log Output:
@as(?u32, null)
@as(?u32, [runtime value])
BratishkaErik
()
Ответ на: комментарий от BratishkaErik

да блин, не ту версию скинул, ну ладно, вот выхлоп от него:

test.zig:15:5: error: found compile log statement
    @compileLog(comptime theBestU64()); // вызвать во время компиляции
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Compile Log Output:
@as(?u64, null)
@as(?u64, [runtime value])
BratishkaErik
()
Ответ на: комментарий от BratishkaErik

Для указателя на нулевой адрес есть *allowzero Node (они друг в друга кастаются ЕМНИП).

Т.е. ?*Node и *allowzero Node бинарно (т.е. в битах реальной памяти) реализованы по-разному?

www_linux_org_ru ★★★★★
()
Последнее исправление: www_linux_org_ru (всего исправлений: 1)
Ответ на: комментарий от www_linux_org_ru

Т.е. ?*Node и *allowzero Node бинарно (т.е. в битах реальной памяти) реализованы по-разному?

Нет, они реализованы одинаково (на нулевой адрес), просто:

_ = optional_node.?; // Здесь будет всунута проверка во время выполнения, что это не null, как Rust'овый unwrap при None.
// так как мы считаем указатель на нулевой адрес ошибкой и assert'аем, что её не произойдет.
_ = allowzero_node; // Здесь мы не считаем нулевой адрес ошибкой, а валидным значением, к примеру когда мы работаем над ядром ОС.

Они оба занимают нулевой адрес и по размерам в машине не отличаются от обычных указателей. Вот если вы совмещаете оба (не знаю зачем), нужно как-то разделить эти два случая, поэтому добавится дополнительный бит. Во всех остальных опциональных типах (не-указателей) дополнительный бит добавляется всегда:

comptime {
    @compileLog(@sizeOf(u64));
    @compileLog(@sizeOf(?u64));
}

Выхлоп:
```zig
test.zig:2:5: error: found compile log statement
    @compileLog(@sizeOf(u64));
    ^~~~~~~~~~~~~~~~~~~~~~~~~

Compile Log Output:
@as(comptime_int, 8)
@as(comptime_int, 16)
BratishkaErik
()
Ответ на: комментарий от BratishkaErik
comptime {
    @compileLog(@sizeOf(*u64));
    @compileLog(@sizeOf(?*u64));
    @compileLog(@sizeOf(*allowzero u64));
    @compileLog(@sizeOf(?*allowzero u64));
}

Выхлоп для 64-битной машины:

test.zig:2:5: error: found compile log statement
    @compileLog(@sizeOf(*u64));
    ^~~~~~~~~~~~~~~~~~~~~~~~~~

Compile Log Output:
@as(comptime_int, 8)
@as(comptime_int, 8)
@as(comptime_int, 8)
@as(comptime_int, 16)

Для 32-битной:

test.zig:2:5: error: found compile log statement
    @compileLog(@sizeOf(*u64));
    ^~~~~~~~~~~~~~~~~~~~~~~~~~

Compile Log Output:
@as(comptime_int, 4)
@as(comptime_int, 4)
@as(comptime_int, 4)
@as(comptime_int, 8)
BratishkaErik
()
Ответ на: комментарий от Lrrr

Что-то вспомнилась древняя телега времен моего программистского детства (да и просто детства, судя по дате написания) :)

http://hosting.vspu.ac.ru/~chul/humor/babbage/babbage.htm

gns ★★★★★
()
Последнее исправление: gns (всего исправлений: 1)
Ответ на: комментарий от gns

Это, во-первых, надо читать в оригинале, поскольку «строгая печать» (гы-гы) это strong typing, т.е. строгая типизация.

А во-вторых их попытки постебаться довольно глупые, т.к. там либо полный бред написан, либо полезные конструкции (к примеру, OR ELSE вполне себе полезная вещь, даже так, как она там на русском описана).

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Да, кривость перевода мне тоже бросилась в глаза, когда я еще и не понимал, что такое строгая типизация :)

gns ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.