Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Lepuroid
    @Lepuroid
    А, и выше, где упоминалось сложение по модулю 32, на самом деле по модулю 2^32, т.е. u32::staturating_add().
    Denis Lisov
    @tanriol
    Окей, возможно, это у меня в терминологии что-то странное.
    @Lepuroid Всё-таки wrapping_add, вероятно, а не saturating?
    Lepuroid
    @Lepuroid
    Да, wrapping_add.
    Aleksey Melnikov
    @aleksmelnikov
    Добрый день. Может ли кто помочь с кодом:
    use walrus::*;
    use walrus::InitExpr;
    use walrus::ir::Value;
    use wasmprinter::*;
    fn main() -> Result<()> {
        let config = ModuleConfig::new();
        let mut module = Module::with_config(config);
        module.name = Some("AAA".into());
        // globals
        module.globals.add_local(ValType::I32, true, InitExpr::Value(Value::I32(5)));
        module.globals.add_local(ValType::I32, true, InitExpr::Value(Value::I32(55)));
        // emit
        module.emit_wasm_file("/at/rust/workspace/target/test_walrus_2.wasm")?;
        // print
        let f = print_file("/at/rust/workspace/target/test_walrus_2.wasm")?;
        println!("{}",f);
        // load and parse
        let mut module = Module::from_file("/at/rust/workspace/target/test_walrus_2.wasm")?;
        println!("{:?}",&module.name.unwrap());
        println!("{:?}",&module.globals);
        // iter
        for x in module.globals.iter() {
            println!("{:?} {:?} {:?}", x, x.kind, x.id());
        }
        println!("{:?}",&module.globals.get(0));  // <<--------- ПРОБЛЕМА: Как взять по индексу?
        Ok(())
    }
    error[E0308]: mismatched types
      --> test_walrus_2/src/main.rs:36:41
       |
    36 |     println!("{:?}",&module.globals.get(0));
       |                                         ^ expected struct `id_arena::Id`, found integer
       |
       = note: expected struct `id_arena::Id<walrus::Global>`
                    found type `{integer}`
    Lepuroid
    @Lepuroid
    Извиняюсь, если не в тему, ибо не ведаю я, что творю :) , но судя по этому, у структуры Global есть метод .id(), который возвращает как раз id_arena::Id<walrus::Global>.
    Aleksey Melnikov
    @aleksmelnikov
    Этот метод я использую как раз в цикле итерации: println!("{:?} {:?} {:?}", x, x.kind, x.id());
    Вопрос в том как получить этот x просто по индексу.
    https://docs.rs/walrus/0.18.0/walrus/struct.ModuleGlobals.html
    iter() - работает
    get() - как с ним работать? как сконструировать GlobalId ?
    Lepuroid
    @Lepuroid
    Судя по сигнатуре, pub fn add_local(&mut self, ty: ValType, mutable: bool, init: InitExpr) -> GlobalId его возвращает.
    Aleksey Melnikov
    @aleksmelnikov

    Да, я попробовал такой вариант:

    use walrus::*;
    use walrus::InitExpr;
    use walrus::ir::Value;
    use wasmprinter::*;
    use id_arena::Id;
    
    fn main() -> Result<()> {
    
        let config = ModuleConfig::new();
        let mut module = Module::with_config(config);
        module.name = Some("AAA".into());
    
        // globals
        let a = module.globals.add_local(ValType::I32, true, InitExpr::Value(Value::I32(5)));
        let b = module.globals.add_local(ValType::I32, true, InitExpr::Value(Value::I32(55)));
    
        println!("{:?}",&module.globals.get(a)); // WORKS
        println!("{:?}",&module.globals.get(b)); // WORKS
    
        // emit
        module.emit_wasm_file("/at/rust/workspace/target/test_walrus_2.wasm")?;
    
        // print
        let f = print_file("/at/rust/workspace/target/test_walrus_2.wasm")?;
        println!("{}",f);
    
        // load and parse
        let mut module = Module::from_file("/at/rust/workspace/target/test_walrus_2.wasm")?;
        println!("{:?}",&module.name.unwrap());
        println!("{:?}",&module.globals);
    
        // iter
        for x in module.globals.iter() {
            println!("{:?} {:?} {:?}", x, x.kind, x.id());
            println!("{:?}",&module.globals.get(x.id()));
        }
    
        println!("{:?}",&module.globals.get(a)); // <<---- PROBLEM: how to get by index?
    
        Ok(())
    }

    Но после загрузке wasm из файла, функция падает. До этого она работает.

    Lepuroid
    @Lepuroid

    Module::from_file() вызывает Module::from_buffer(), в котором, в свою очередь, есть вызов ModuleConfig::new().parse(), а уже там есть

    let mut indices = IndicesToIds::default();

    У IndicesToIDs есть метод

    pub fn get_global(&self, index: u32) -> Result<GlobalId>

    Может быть - оно? :)

    Aleksey Melnikov
    @aleksmelnikov
    Т.е. взять от туда кусок кода (по сути парсер) ?
    Пока не понимаю как можно простым способом из модуля взять indices
    Denis Lisov
    @tanriol
    А по какому индексу, собственно, ты его хочешь достать?
    Aleksey Melnikov
    @aleksmelnikov
    0 или 1
    Denis Lisov
    @tanriol
    То есть по индексу в самом wasm-файле?
    Aleksey Melnikov
    @aleksmelnikov
    думаю да
    либо понять что для этого нужно
    пока пробую вот что: создать по 1 элементу каждого типа, записать все в файл. прочитать файл, прочитать элементы каждого типа.
    типы wasm имеются в виду
    Lepuroid
    @Lepuroid

    Пока не понимаю как можно простым способом из модуля взять indices

    Видимо, эта структура существует только во время парсинга, судя по описанию ModuleConfig.on_parse().

    Lepuroid
    @Lepuroid

    Как можно и можно ли вообще сделать следующее:

    1. Использовать type Block = [u8; 4]; или use [u8; 4] as Block; или что-то подобное вместо struct Block([u8; 4])? В лоб ничего не выходит, но, если что-то подобное можно реализовать, это уберёт необходимость в реализациях методов, состоящих из перенаправления на Block.0 (я не жалуюсь, всё что надо сделал, но эстет во мне негодует немного). Иными словами, как сказать компилятору, что Block - это [u8; 4] со своими методами?
    2. Перегружать реализации операторов и методы для того, что описано в [1], т.е.:
      let x: u8 = 255;
      let y: sometype = 255; 
      let xx = x + 1;  // overflow
      let yy = y + 1;  // wrapping add
      Опять же, в лоб не вышло, но, если есть правильный способ реализовать [1], наверное, должен быть и правильный способ реализовать это.

    Спасибо.

    P.S. Где можно прочитать, что компилятор оптимизирует, а что лежит на программисте? Пока нашёл только то, что он старается инлайнить всё, что можно и вручную инлайны прописывать незачем, но, например, меняет ли он 5 * 8 на 5 << 3?

    Denis Lisov
    @tanriol
    1+2 нормально не делается. Или это тот же тип, и тогда все реализации остаются те же, или другой, и тогда все нужны новые. Для реализаций по ссылке есть ещё Deref / DerefMut, но это тоже не совсем то - они не обернут обратно в этот тип.
    Denis Lisov
    @tanriol
    Что до оптимизаций - в основном их реализует LLVM, так что круглым счётом можно рассчитывать примерно на то же, на что и в случае Clang (то есть примерно то же, что и в случае GCC)
    Да, отдельный комментарий - большая часть оптимизаций не срабатывает в отладочном режиме.
    Lepuroid
    @Lepuroid
    Эх, иногда даже ООП вынуждает поскучать по себе :) Про --release знаю. Вот, к слову, можно ли как-то узнать, как rustc дешугарит всё написанное, но не так низко, как выдаёт cargo rustc -- --emit mir?
    Denis Lisov
    @tanriol
    Я такого способа не знаю.
    Denis Lisov
    @tanriol
    Мне казалось, что вопрос не про макросы...
    Lepuroid
    @Lepuroid
    Да, не совсем то, но, всё равно, благодарю. Макросы можно и с помощью IDE посмотреть перейдя к определению, а вот с [derive] - интересно.
    sobaka_v_kepke
    @chabapok_twitter
    так, стоп
    а чем #[cfg(feature="foo")] отличается от #[feature("foo")]?
    Denis Lisov
    @tanriol
    Тем, что #[cfg(feature=...)] - это про фичи крейта, а #[feature(...)] - про нестабильные возможности языка?
    sobaka_v_kepke
    @chabapok_twitter
    спасибо.
    Lepuroid
    @Lepuroid

    Почему циклы не могут явно возвращать не () в конце своей работы?

        fn permut(&self) -> Block {
            let mask = 0b_11110000_u8;
            let mut block: Block = Default::default();
            for i in 0..BLOCK_LEN {
                let mut l4: u8 = (&self[i] & mask) >> 4;
                let mut r4: u8 = &self[i] & !mask;
                l4 = TABLE[i << 1][l4 as usize];
                r4 = TABLE[(i << 1) + 1][r4 as usize];
                block[i] = (l4 << 4) + r4;
            }
            block
        }

    Например, вот в таком методе, если убрать ; в последней строке цикла, то получится вполне валидный expression вместо statement (кстати, какими словами по-русски принято эти два понятия называть?) и весь цикл тогда будет таким же валидным expression и добавлять block после цикла не надо будет. Или я что-то не понял/не знаю?

    Denis Lisov
    @tanriol
    @Lepuroid Потому что в общем случае компилятор не может знать заранее, выполнится ли цикл хотя бы один раз?
    Кроме того, конкретно в данном примере я напоминаю, что присваивание в Расте возвращает (), а не то, что присваивалось.
    Lepuroid
    @Lepuroid
    Спасибо, а разве не для таких случаев есть Option? По второму моменту - да, вылетело из головы, извиняюсь.
    Lepuroid
    @Lepuroid
    Я не говорю, что это правильно, но оно работает... Это надруганный мною for из документации.
    fn main() {
        let yyy = {
            let mut xxx = None;
            match IntoIterator::into_iter(0..5) {
                mut iter => 'label: loop {
                    let mut next;
                    match Iterator::next(&mut iter) {
                        Option::Some(val) => next = val,
                        Option::None => break,
                    };
                    let PATTERN = next;
                    xxx = Some({ println!("{}", next); "чтоугодно"});
                }
            }
            xxx
        };
        println!("{:?}", yyy.unwrap())
    }
    Psilon
    @Pzixel
    Мне не оч понятно что должно возвращаться в примере выше
    а так есть циклы loop которые возвращают значение
    Lepuroid
    @Lepuroid

    @Pzixel Последний expression блока.

    Я покопался, подумал и, да, так незачем делать. Если сделать красиво снаружи, то внутри получается адский кошмар.

    Gexon
    @Gexon
    привет
    Вопрос такой: допустим я обьявлю массив [u8]
    длинной, например 100
    он в памяти сложится в непрерывный набор данных
    он памяти будет занимать как u8100
    или как u32
    100?
    Denis Lisov
    @tanriol
    Массив [u8; 100] в памяти занимает сто байт.
    С чего бы ему вдруг быть как u32?
    Gexon
    @Gexon
    да, меня спросили
    я переспросил, так как не уверен)
    Lepuroid
    @Lepuroid
    Тут только одно исключение: bool. Он не бит занимает, а байт.
    Denis Lisov
    @tanriol
    @Lepuroid Если лезть в детали, то тогда можно и про padding / alignment вспомнить для структур, но это вроде уже другой вопрос.