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)

Ответ на: комментарий от 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
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.