The 2024 Wheel Reinvention Jam just concluded. See the results.

The Odin Programming Language

ratchetfreak

1
2
3
4
abs :: overload{ (f : float ) -> float{return ...}, 
                 (f : int ) -> int{return ...}, 
                 ...
               }

As long as abs is treated as a namespace for anonymous functions where you can inject more overloads from somewhere else in the code this is fine. Otherwise this now has the same problems as methods inside structs/classes in c++, where you cannot extend the functionality of a class if you cannot directly edit the sourcefile it resides in.

The whole point of overloading is to extend a function to have multiple signatures. Kind of like one level below generics.
If you can't extend a function from somewhere else, it defeats the purpose.
Cranky:

I understand that problem too. How I handle entities (variables, constants, procedures, type names) is that I search for the first occurrence of the name in the current scope and parent scopes (normal scoping rules). So if an entity with the same name as an entity in a parent scope exists, it overshadows that parent entity. This is kind of how C works and lambda calculus.

1
2
3
4
5
x: int
{
    x: f32
    x = 1 // refers to this scope's x of type `f32`
}



Adding overloading of certain entities would cause a weird edge case in which you would have to check all parent scopes and find the best match. This is certainly not a fast nor efficient method which would definitely slow compilation speed. I did actually implement half of overloading once and then removed it as it was just "ugly" to implement this edge case. I don't really want there to be a "special" namespace (except for file/global scope which is slightly different) either.

ratchetfreak's idea is a good middle ground: allowing for overloading of a particular entity without removing the simple namespacing rule.
Latest demo: Introspection, Modules, and Record Layout

https://www.youtube.com/watch?v=UFq8rhWhx4s


Overview:
  • struct members are reordered by default to minimize alignment padding - can be overridden with either #ordered (c-style) or #packed (no padding at all)
  • Bounds checking - togglealble on a per statement basis - #no_bounds_check #bounds_check
  • Type Information - type_info(Type) and type_info_of_val(val)
  • `any` Type - stores type info and rawptr to data - allows for typesafe printf and much more
  • Files as namespaces (modules), #import and #load
  • #link_name, #stdcall, #fastcall, #dll_import, #dll_export, #shared_global_scope, panic(), assert(), compile_assert()
  • Remove huge dependency on clang and only require MSVC's link.exe as the linker
On structure layout perhaps you could allow explicit layout too...

1
2
3
4
5
6
struct mytype
{
    int data @ 0;
    float x @ 6;
    struct xxx yyy[6] @ 32;
}

Only with your own syntax... Where the numbers indicate byte offset into the structure. Would allow explicit control of layout when you need it without worrying about order or padding etc. As an option of course.


Edited by John Burton on
jb99
On structure layout perhaps you could allow explicit layout too...

1
2
3
4
5
6
struct mytype
{
    int data @ 0;
    float x @ 6;
    struct xxx yyy[6] @ 32;
}

Only with your own syntax... Where the numbers indicate byte offset into the structure. Would allow explicit control of layout when you need it without worrying about order or padding etc. As an option of course.



That should be doable with packed it would require dummy fields when doing explicit padding. But allowing _ to be a member name for it relieves you from having to come up with decent names for them.

1
2
3
4
5
struct #packed{
foo: f32
_: u8[3] /*padding cannot be accessed and will not appear in the struct_info*/
bar: u8
}

Edited by ratchetfreak on
Rachetfreak's approach is how it now works. `_` is a special identifier called the blank identifier. It's kind of a dummy variable that you cannot access. This is useful for ignoring procedure results and other things.
yes. i just thought that was less direct and more error prone was all :)
Latest Demo: push_allocator & Minimal Dependency Building
https://www.youtube.com/watch?v=f_LGVOAMb78

Overview:
  • More core libraries
  • push_allocator & push_context
  • Backend: Minimal Dependency Building (only build what is needed)
  • Fix numerous bugs
Lately with this language, I've been trying to implement compile time execution for use with metaprogramming. This is akin to Jon Blow's #run in JAI.

Having compile time execution is extremely powerful however, it is also extremely delicate. There are a few problems I have found with a system such as this, the main problem being: converting interpreted memory space to compiled memory space. For many types, this is perfectly safe but anything that requires a pointer (except strings) or a binary blob (union and raw_union), will cause problems.

I've done a little write up on GitHub Gist as these forums cannot format tables yet.

https://gist.github.com/gingerBill/98fe5117a7ba94437a0e7132eb25007f

There are other problems such as executing 32-bit code on a 64-bit machine, procedure calling, etc, but this more of an interpreter problem than this metaprogramming problem.

I don't know how (and if) Jon has solved any of these problems or even if it's solvable.

-- Bill
That's an awesome feature - maybe you could start w/ a subset of your language?
I suppose the most frequent use would be to generate look-up tables...
I have most of the interpreter down already, except for the external procedure code and other stuff to do with procedure calls.

One of the problems I have "could" be solved by checking pointers against a range of valid pointers in the memory space, however, that's not going to be fool proof.

Implementing a subset of the language is not going to help as what I'm interpreting is my SSA code and that's only 24 instructions (plus 1 pseudo-instruction). The problem is kind of a fundamental problem with the approach of metaprogramming.

The two options that I can think of at the moment are these: keep the rubbish pointers and blobs; zero the rubbish pointers and blobs.

Unfortunately, I just don't know how to solve this problem at this current time. Maybe I'm thinking about the problem all wrong too.