Skip to content

get rid of zeroes #222

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
andrewrk opened this issue Jan 16, 2017 · 5 comments
Closed

get rid of zeroes #222

andrewrk opened this issue Jan 16, 2017 · 5 comments

Comments

@andrewrk
Copy link
Member

No description provided.

@andrewrk
Copy link
Member Author

if anyone has examples of use cases for zeroes literal, please post them here and I'll make sure there is a suggested alternative way to solve that use case.

@ofelas
Copy link

ofelas commented Jan 18, 2017

Not sure its a correct, good or valid use case, but I had this...(diff)

-    var column: [(if (s1len > s2len) s1len else s2len) + 1]usize = zeroes;
+    const maxlen: usize = (if (s1len > s2len) s1len else s2len) + usize(1);
+    var column: [maxlen]usize = []usize{usize(0)} ** maxlen;

Which now gives this error message.

zig build --static --export exe --name test_stringalgo_dbg test_stringalgo.zig
./levenshtein.zig:24:18: error: unable to evaluate constant expression
    var column: [maxlen]usize = []usize{usize(0)} ** maxlen;
                 ^
./levenshtein.zig:24:54: error: unable to evaluate constant expression
    var column: [maxlen]usize = []usize{usize(0)} ** maxlen;
                                                     ^

@andrewrk
Copy link
Member Author

ah ok there was another change here.

it used to be that the variable declaration syntax would do alloca (increase the stack size by an amount known only at runtime) if the array length was not compile-time known. I decided that this a way to accidentally shoot yourself in the foot, so now you have to explicitly use const column = @alloca(usize, maxlen). Docs for @alloca:

@alloca(inline T: type, count: usize) -> []T

Allocates memory in the stack frame of the caller. This temporary space is
automatically freed when the function that called alloca returns to its caller,
just like other stack variables.

When using this function to allocate memory, you should know the upper bound
of count. Consider putting a constant array on the stack with the upper bound
instead of using alloca. If you do use alloca it is to save a few bytes off
the memory size given that you didn't actually hit your upper bound.

The allocated memory contents are undefined.

The ** operator operates on compile-time known values only, so if maxlen is not compile-time known then you can't use the ** operator. You can do this though:

const mem = @import("std").mem;
mem.set(usize, column, 0);

Is the compiler correct that maxlen is a runtime-known value?

@ofelas
Copy link

ofelas commented Jan 18, 2017

Aye, maxlen is indeed a runtime-known value. I had no particular reason for using zeroes other than convenience I guess (and trying out stuff in langref).
So a const column = @alloca(...) is writeable!? (seems to work with both const and var)

The @alloca thing works fine, so does using a global like below (and possibly allocation of some other sort) obviously one could be a bit more careful.

var globalarray : [512]usize = undefined;
:
: 8< snip 8< and in the fn
    const column = if (maxlen <= 16) @alloca(usize, maxlen) else ([]usize)(globalarray);
    for (column) |*b| {
            *b = 0;
    }

@andrewrk
Copy link
Member Author

andrewrk commented Jan 18, 2017

So a const column = @alloca(...) is writeable!? (seems to work with both const and var)

Yeah, seems kind of weird that you can write through const doesn't it?

What's going on is that the concept of "const" is referring to memory range. When you have a const variable, the memory range that contains the variable cannot be changed through that variable.

When you have a pointer, the pointer address itself exists in memory too, and that can be const or not, and then the memory range the pointer points to can be const or not. That's why we have & vs &const and [] vs []const.

So in this example @alloca is returning a []usize which is a mutable slice. However the slice itself is a pointer and a size - 16 bytes on x86_64 - and those 16 bytes are constant. Meaning you cannot re-assign the column variable to a different slice.

It works with var but in the future I will add an error for using var when you could have used const instead. #224

So it makes sense, but it's still confusing that you can write through a const. So I think this is an argument in favor of using let instead of const (See #181)

Be careful with that globalarray code because that causes problems with thread safety and re-entrancy safety. var array: [512]usize = undefined is allowed inside a function, because 512 is a compile-time known value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants