Closed rempas closed 2 years ago
I don't know much about linux signals yet, but it may be the case that you need to register signal handlers for this to work.
Oh ok! I just wanted to let you know at least and you can see it when you want
I checked and it worked actually
void main() {
while(true){}
}
user@PC:~/vox/test_work_dir$ ./vox test2.vx && ./test2
^Z
[1]+ Stopped ./test2
user@PC:~/vox/test_work_dir$ fg
./test2
^C
user@PC:~/vox/test_work_dir$
Interesting. It worked for me too with this example. Then something else is the problem with the specific code that I'm having. And it seems that the problem is when compiling code and not in the runtime so nothing with the way that vox generates code. Ok so here is the full code:
void print[T...](u8[] prompt, T... args) {
u64 psize = 0;
u64 carg = 0;
u8 c;
// TODO: Find if we can for prompt to be known at compile time and use "#foreach" here
// TODO: After I'm done with this, make a version with "else" labels removed
while (psize < prompt.length) {
c = prompt[psize++];
if (c != '{') {
// TODO: Make a macro called "add_char" when macros are implemented
if (stdout_index < STDOUT_BUF_LEN) {
stdout_buffer[stdout_index++] = c;
continue;
} else {
sys_write(1, stdout_buffer.ptr, stdout_index + 1); // TODO: Remove '+ 1' and see what happens
stdout_index = 0;
stdout_buffer[stdout_index++] = c;
continue;
}
} else {
// TODO: When the #debug is released, make this check only in the #debug version
if (psize >= prompt.length) // FIXME: psize can never be bigger than prompt.length so maybe only check for equality makes more sense?
sys_write(2, "Error: Expected the matching '}'\n", 22); // TODO: find how to get the current line number
// Get the closing '}'
c = prompt[psize++];
if (c == '}') { // Format it as its type
// TODO: When the #debug is released, make this check only in the #debug version
if (carg >= args.length) { // FIXME: carg can never be bigger than args.length so maybe only check for equality makes more sense?
sys_write(2, "There are no more argruments to print\n", 27); // TODO: find how to get the current line number
}
// TODO FIXME: Change ALL these methods to put the character directly to stdout rather than returning a "u8*"
#if (T == u8 || T == i8 || T == u16 || T == i16 || T == u32 || T == i32 || T == u64 || T == i64) {
u8* val = to_str(args[carg++]);
u64 len = strlen(val);
for (u64 i = 0; i < len; i++) {
if (stdout_index < STDOUT_BUF_LEN) {
stdout_buffer[stdout_index++] = val[i];
continue;
} else {
sys_write(1, stdout_buffer.ptr, stdout_index + 1); // TODO: Remove '+ 1' and see what happens
stdout_index = 0;
stdout_buffer[stdout_index++] = val[i];
continue;
}
}
}
}
}
}
}
void main() {
print("Hello world!!!");
exit(0);
}
It's a big code snippet unfortunately. Please ignore any logical errors and comments. So when trying to compile this, it will run for about 2-3 seconds and then I will get the infamous "illegal hardware instruction" error. It seems that #if
is causing the error because there are two cases without it.
If you remove the the #if
but NOT the code inside it, you will get the following error message:
fe.passes.eval:56: ICE: Cannot evaluate static expression decl_var
- token main.vox:15:3
Stack:
> main.vox:46:30: node.14065 name_resolve expr_index expr_index
main.vox:46:25: node.14075 name_resolve expr_call to_str
main.vox:46:9: node.14089 name_resolve decl_var val
main.vox:39:7: node.14489 name_resolve stmt_if stmt_if
main.vox:21:5: node.14501 name_resolve stmt_if stmt_if
main.vox:19:3: node.14513 name_resolve stmt_while stmt_while
main.vox:13:42: node.14521 name_resolve stmt_block stmt_block
main.vox:13:1: node.13330 name_resolve decl_function print[]
main.vox:65:8: node.11161 type_check expr_call print
main.vox:64:13: node.11201 type_check stmt_block stmt_block
main.vox:64:1: node.11118 type_check decl_function main
main.vox:1:1: node.572 type_check decl_module main
context.CompilationException@fe.passes.eval(56)
If you remove the the #if
AND the code inside it, you will get the following error message:
fe.ast.expr.member_access:471: ICE: Unexpected node type expr_member
- token main.vox:41:25
- module `main`
- function `print[]`
- defined at main.vox:13:1
context.CompilationException@fe.ast.expr.member_access(471)
So, aside from bugs in the code, the T
here refers to a $alias[]
, so you cannot compare it to anything. You also try to index it with runtime variable carg
, which is not possible. You can only index it with compile-time variable. Variadic arguments are barely implemented atm, basically you can only do #foreach and indexing on them.
Efficient implementation of prinf is a tricky problem. Ideally it requires compile-time knowledge of the format string, and minimal compile-time cost. In D std lib they workaround the indexing of runtime arguments with the switch (but we don't have the ability to generate cases programmatically in Vox yet)
Also, you allocate memory in to_str
, while instead you could write the formatted argument directly into stdout_buffer
.
So, aside from bugs in the code, the T here refers to a $alias[], so you cannot compare it to anything.
Whaaaaaaaaa? But you said it yourself here. Wasn't this what you meant or did something changed between then and now? Or did I got it wrong? Can you please show me a small simple example of how to choose types (if it is even available at the moment of course)?
Efficient implementation of prinf is a tricky problem. Ideally it requires compile-time knowledge of the format string, and minimal compile-time cost. In D std lib they workaround the indexing of runtime arguments with the switch (but we don't have the ability to generate cases programmatically in Vox yet)
You know, when I wanted to create a transpiler, I though about having a keyword for variables that will only accept values that can be known at compile time. It wouldn't be a "real" variable just a place to hold a value when compiling. This would be used as a function parameter and I would be able to used with #foreach
. What are your thoughts on this idea?
Also, you allocate memory in to_str, while instead you could write the formatted argument directly into stdout_buffer.
Buuuuut I told you to not worry about any logical error :). Just kidding! Thanks for the info, I was planning to do this anyway because it is more efficient and makes more sense but I just wanted to test the function first and then create a different function that does that.
Whaaaaaaaaa? But you said it yourself here. Wasn't this what you meant or did something changed between then and now? Or did I got it wrong? Can you please show me a small simple example of how to choose types (if it is even available at the moment of course)?
Note the that they are different. Singular T
is just a type alias, while T...
is type array.
Here is an example https://github.com/MrSmith33/voxelman2/blob/master/plugins/core/src/core/utils.vx#L287-L314
You know, when I wanted to create a transpiler, I though about having a keyword for variables that will only accept values that can be known at compile time. It wouldn't be a "real" variable just a place to hold a value when compiling. This would be used as a function parameter and I would be able to used with #foreach. What are your thoughts on this idea?
I thought about this too. It is basically a template parameter. But making it a template parameter is unergonomic, but possible (value template parameters are not yet implemented). The other option is to have something like comptime
in Zig. It is exactly what we want, but having 2 ways of defining template parameters doesn't feel good. Third option is macro. Since every macro invocation has direct access to the arguments it can check if the value is a constant. Macros are not easy to implement, and I haven't worked on them yet.
Thanks for the example.
having 2 ways of defining template parameters doesn't feel good
Yeah, that's how I see things two. I like to have one thing to do something (when it comes to features and not problem solving of course) to not blot the language.
Third option is macro
Yeah, that's what I was thinking too! It also makes sense cause the types of functions that are going to use it will probably be variadic and need to get reconstructed anyway so it make sense.
Macros are not easy to implement, and I haven't worked on them yet.
Yes of course they are! There are a lot of decisions you have to make when it comes to design them. Rushing thing is never good. The good things take time as we say here in Greece ;)
Normally when I run a program, I expect
Ctrl+c
to stop its execution andCtrl+z
to suspend it (put it in the background). There are probably other signals that you can send but these two are the ones I mostly care about and from what I noticed (don't ask me why I found out about this now, lol) they don't work with Vox