mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 23:28:48 +00:00
Write demo for v0.5.0
This commit is contained in:
+408
@@ -1,5 +1,411 @@
|
|||||||
import "fmt.odin";
|
import "fmt.odin";
|
||||||
|
|
||||||
|
proc general_stuff() {
|
||||||
|
// Complex numbers
|
||||||
|
var a = 3 + 4i;
|
||||||
|
var b: complex64 = 3 + 4i;
|
||||||
|
var c: complex128 = 3 + 4i;
|
||||||
|
var d = complex(2, 3);
|
||||||
|
|
||||||
|
var e = a / conj(a);
|
||||||
|
fmt.println("(3+4i)/(3-4i) =", e);
|
||||||
|
fmt.println(real(e), "+", imag(e), "i");
|
||||||
|
|
||||||
|
|
||||||
|
// C-style variadic procedures
|
||||||
|
foreign __llvm_core {
|
||||||
|
// The variadic part allows for extra type checking too which C does not provide
|
||||||
|
proc c_printf(fmt: ^u8, #c_vararg args: ..any) -> i32 #link_name "printf";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Foo struct {
|
||||||
|
x: int,
|
||||||
|
y: f32,
|
||||||
|
z: string,
|
||||||
|
}
|
||||||
|
var foo = Foo{123, 0.513, "A string"};
|
||||||
|
var x, y, z = expand_to_tuple(foo);
|
||||||
|
fmt.println(x, y, z);
|
||||||
|
|
||||||
|
|
||||||
|
// By default, all variables are zeroed
|
||||||
|
// This can be overridden with the "uninitialized value"
|
||||||
|
var undef_int: int = ---;
|
||||||
|
|
||||||
|
|
||||||
|
// Context system is now implemented using Implicit Parameter Passing (IPP)
|
||||||
|
// The previous implementation was Thread Local Storage (TLS)
|
||||||
|
// IPP has the advantage that it works on systems without TLS and that you can
|
||||||
|
// link the context to the stack frame and thus look at previous contexts
|
||||||
|
//
|
||||||
|
// It does mean that a pointer is implicitly passed procedures with the default
|
||||||
|
// Odin calling convention (#cc_odin)
|
||||||
|
// This can be overridden with something like #cc_contextless or #cc_c
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
proc foreign_blocks() {
|
||||||
|
// See sys/windows.odin
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
proc default_arguments() {
|
||||||
|
proc hello(a: int = 9, b: int = 9) {
|
||||||
|
fmt.printf("a is %d; b is %d\n", a, b);
|
||||||
|
}
|
||||||
|
fmt.println("\nTesting default arguments:");
|
||||||
|
hello(1, 2);
|
||||||
|
hello(1);
|
||||||
|
hello();
|
||||||
|
}
|
||||||
|
|
||||||
|
proc named_arguments() {
|
||||||
|
type Colour enum {
|
||||||
|
Red,
|
||||||
|
Orange,
|
||||||
|
Yellow,
|
||||||
|
Green,
|
||||||
|
Blue,
|
||||||
|
Octarine,
|
||||||
|
};
|
||||||
|
using Colour;
|
||||||
|
|
||||||
|
proc make_character(name, catch_phrase: string, favorite_color, least_favorite_color: Colour) {
|
||||||
|
fmt.println();
|
||||||
|
fmt.printf("My name is %v and I like %v. %v\n", name, favorite_color, catch_phrase);
|
||||||
|
}
|
||||||
|
|
||||||
|
make_character("Frank", "¡Ay, caramba!", Blue, Green);
|
||||||
|
|
||||||
|
|
||||||
|
// As the procedures have more and more parameters, it is very easy
|
||||||
|
// to get many of the arguments in the wrong order
|
||||||
|
make_character("¡Ay, caramba!", "Frank", Green, Blue);
|
||||||
|
|
||||||
|
// Named arguments help to disambiguate this problem
|
||||||
|
make_character(catch_phrase = "¡Ay, caramba!", name = "Frank",
|
||||||
|
least_favorite_color = Green, favorite_color = Blue);
|
||||||
|
|
||||||
|
|
||||||
|
// The named arguments can be specifed in any order.
|
||||||
|
make_character(favorite_color = Octarine, catch_phrase = "U wot m8!",
|
||||||
|
least_favorite_color = Green, name = "Dennis");
|
||||||
|
|
||||||
|
|
||||||
|
// NOTE: You cannot mix named arguments with normal values
|
||||||
|
/*
|
||||||
|
make_character("Dennis",
|
||||||
|
favorite_color = Octarine, catch_phrase = "U wot m8!",
|
||||||
|
least_favorite_color = Green);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Named arguments can also aid with default arguments
|
||||||
|
proc numerous_things(s : string, a = 1, b = 2, c = 3.14, d = "The Best String!", e = false, f = 10.3/3.1, g = false) {
|
||||||
|
var g_str = g ? "true" : "false";
|
||||||
|
fmt.printf("How many?! %s: %v\n", s, g_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
numerous_things("First");
|
||||||
|
numerous_things(s = "Second", g = true);
|
||||||
|
|
||||||
|
|
||||||
|
// Default values can be placed anywhere, not just at the end like in other languages
|
||||||
|
proc weird(pre: string, mid: int = 0, post: string) {
|
||||||
|
fmt.println(pre, mid, post);
|
||||||
|
}
|
||||||
|
|
||||||
|
weird("How many things", 42, "huh?");
|
||||||
|
weird(pre = "Prefix", post = "Pat");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
proc default_return_values() {
|
||||||
|
proc foo(x: int) -> (first: string = "Hellope", second = "world!") {
|
||||||
|
match x {
|
||||||
|
case 0: return;
|
||||||
|
case 1: return "Goodbye";
|
||||||
|
case 2: return "Goodbye", "cruel world...";
|
||||||
|
case 3: return second = "cruel world...", first = "Goodbye";
|
||||||
|
}
|
||||||
|
|
||||||
|
return second = "my old friend.";
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.printf("%s %s\n", foo(0));
|
||||||
|
fmt.printf("%s %s\n", foo(1));
|
||||||
|
fmt.printf("%s %s\n", foo(2));
|
||||||
|
fmt.printf("%s %s\n", foo(3));
|
||||||
|
fmt.printf("%s %s\n", foo(4));
|
||||||
|
fmt.println();
|
||||||
|
|
||||||
|
|
||||||
|
// A more "real" example
|
||||||
|
type Error enum {
|
||||||
|
None,
|
||||||
|
WhyTheNumberThree,
|
||||||
|
TenIsTooBig,
|
||||||
|
};
|
||||||
|
|
||||||
|
type Entity struct {
|
||||||
|
name: string,
|
||||||
|
id: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
proc some_thing(input: int) -> (result: ^Entity = nil, err = Error.None) {
|
||||||
|
match {
|
||||||
|
case input == 3: return err = Error.WhyTheNumberThree;
|
||||||
|
case input >= 10: return err = Error.TenIsTooBig;
|
||||||
|
}
|
||||||
|
|
||||||
|
var e = new(Entity);
|
||||||
|
e.id = u32(input);
|
||||||
|
|
||||||
|
return result = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proc call_location() {
|
||||||
|
proc amazing(n: int, using loc = #caller_location) {
|
||||||
|
fmt.printf("%s(%d:%d) just asked to do something amazing to %d.\n",
|
||||||
|
fully_pathed_filename, line, column);
|
||||||
|
fmt.printf("Amazing -> %d\n", n+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var loc = #location(main);
|
||||||
|
fmt.println("`main` is located at", loc);
|
||||||
|
|
||||||
|
fmt.println("This line is located at", #location());
|
||||||
|
fmt.println();
|
||||||
|
|
||||||
|
amazing(3);
|
||||||
|
amazing(4, #location(call_location));
|
||||||
|
|
||||||
|
// See _preload.odin for the implementations of `assert` and `panic`
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
proc explicit_parametric_polymorphic_procedures() {
|
||||||
|
// This is how `new` is actually implemented, see _preload.odin
|
||||||
|
proc alloc_type(T: type) -> ^T {
|
||||||
|
return ^T(alloc(size_of(T), align_of(T)));
|
||||||
|
}
|
||||||
|
|
||||||
|
var int_ptr = alloc_type(int);
|
||||||
|
defer free(int_ptr);
|
||||||
|
int_ptr^ = 137;
|
||||||
|
fmt.println(int_ptr, int_ptr^);
|
||||||
|
|
||||||
|
// Named arguments work too!
|
||||||
|
var another_ptr = alloc_type(T = f32);
|
||||||
|
defer free(another_ptr);
|
||||||
|
|
||||||
|
|
||||||
|
proc add(T: type, args: ..T) -> T {
|
||||||
|
var res: T;
|
||||||
|
for arg in args {
|
||||||
|
res += arg;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.println("add =", add(int, 1, 2, 3, 4, 5, 6));
|
||||||
|
|
||||||
|
proc swap(T: type, a, b: ^T) {
|
||||||
|
var tmp = a^;
|
||||||
|
a^ = b^;
|
||||||
|
b^ = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
var a, b: int = 3, 4;
|
||||||
|
fmt.println("Pre-swap:", a, b);
|
||||||
|
swap(int, &a, &b);
|
||||||
|
fmt.println("Post-swap:", a, b);
|
||||||
|
a, b = b, a; // Or use this syntax for this silly example case
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// A more complicated example using subtyping
|
||||||
|
// Something like this could be used a game
|
||||||
|
type Vector2 struct {x, y: f32};
|
||||||
|
|
||||||
|
type Entity struct {
|
||||||
|
using position: Vector2,
|
||||||
|
flags: u64,
|
||||||
|
id: u64,
|
||||||
|
batch_index: u32,
|
||||||
|
slot_index: u32,
|
||||||
|
portable_id: u32,
|
||||||
|
derived: any,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Rock struct {
|
||||||
|
using entity: ^Entity,
|
||||||
|
heavy: bool,
|
||||||
|
}
|
||||||
|
type Door struct {
|
||||||
|
using entity: ^Entity,
|
||||||
|
open: bool,
|
||||||
|
}
|
||||||
|
type Monster struct {
|
||||||
|
using entity: ^Entity,
|
||||||
|
is_robot: bool,
|
||||||
|
is_zombie: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
type EntityManager struct {
|
||||||
|
batches: [dynamic]^EntityBatch,
|
||||||
|
next_portable_id: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
const ENTITIES_PER_BATCH = 16;
|
||||||
|
type EntityBatch struct {
|
||||||
|
data: [ENTITIES_PER_BATCH]Entity,
|
||||||
|
occupied: [ENTITIES_PER_BATCH]bool,
|
||||||
|
batch_index: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
proc use_empty_slot(manager: ^EntityManager, batch: ^EntityBatch) -> ^Entity {
|
||||||
|
for ok, i in batch.occupied {
|
||||||
|
if ok -> continue;
|
||||||
|
batch.occupied[i] = true;
|
||||||
|
|
||||||
|
var e = &batch.data[i];
|
||||||
|
e.batch_index = u32(batch.batch_index);
|
||||||
|
e.slot_index = u32(i);
|
||||||
|
e.portable_id = manager.next_portable_id;
|
||||||
|
manager.next_portable_id++;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc gen_new_entity(manager: ^EntityManager) -> ^Entity {
|
||||||
|
for b in manager.batches {
|
||||||
|
var e = use_empty_slot(manager, b);
|
||||||
|
if e != nil -> return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
var new_batch = new(EntityBatch);
|
||||||
|
append(manager.batches, new_batch);
|
||||||
|
new_batch.batch_index = u32(len(manager.batches)-1);
|
||||||
|
|
||||||
|
return use_empty_slot(manager, new_batch);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
proc new_entity(manager: ^EntityManager, Type: type, x, y: int) -> ^Type {
|
||||||
|
var result = new(Type);
|
||||||
|
result.entity = gen_new_entity(manager);
|
||||||
|
result.derived.data = result;
|
||||||
|
result.derived.type_info = type_info(Type);
|
||||||
|
|
||||||
|
result.position.x = f32(x);
|
||||||
|
result.position.y = f32(y);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
var manager: EntityManager;
|
||||||
|
var entities: [dynamic]^Entity;
|
||||||
|
|
||||||
|
var rock = new_entity(&manager, Rock, 3, 5);
|
||||||
|
|
||||||
|
// Named arguments work too!
|
||||||
|
var door = new_entity(manager = &manager, Type = Door, x = 3, y = 6);
|
||||||
|
|
||||||
|
// And named arguments can be any order
|
||||||
|
var monster = new_entity(
|
||||||
|
y = 1,
|
||||||
|
x = 2,
|
||||||
|
manager = &manager,
|
||||||
|
Type = Monster,
|
||||||
|
);
|
||||||
|
|
||||||
|
append(entities, rock, door, monster);
|
||||||
|
|
||||||
|
// An alternative to `union`s
|
||||||
|
for entity in entities {
|
||||||
|
match e in entity.derived {
|
||||||
|
case Rock: fmt.println("Rock", e.portable_id);
|
||||||
|
case Door: fmt.println("Door", e.portable_id);
|
||||||
|
case Monster: fmt.println("Monster", e.portable_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proc main() {
|
||||||
|
general_stuff();
|
||||||
|
foreign_blocks();
|
||||||
|
default_arguments();
|
||||||
|
named_arguments();
|
||||||
|
default_return_values();
|
||||||
|
call_location();
|
||||||
|
explicit_parametric_polymorphic_procedures();
|
||||||
|
|
||||||
|
// Command line argument(s)!
|
||||||
|
// -opt=0,1,2,3
|
||||||
|
|
||||||
|
|
||||||
|
/*************/
|
||||||
|
/* Questions */
|
||||||
|
/*************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
I'm questioning if I should change the declaration syntax back to Jai-like
|
||||||
|
as I've found solutions to the problems I had with it before.
|
||||||
|
|
||||||
|
Should I change back to Jai-like declarations or keep with the Pascal-like?
|
||||||
|
|
||||||
|
Jai-like
|
||||||
|
|
||||||
|
x: int;
|
||||||
|
x: int = 123;
|
||||||
|
x := 123;
|
||||||
|
|
||||||
|
foo : int : 123;
|
||||||
|
foo :: 123;
|
||||||
|
|
||||||
|
MyInt :: int;
|
||||||
|
BarType :: proc();
|
||||||
|
|
||||||
|
bar :: proc() {
|
||||||
|
}
|
||||||
|
|
||||||
|
foreign lib {
|
||||||
|
foreign_bar :: proc() ---;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pascal-like
|
||||||
|
|
||||||
|
var x: int;
|
||||||
|
var x: int = 123;
|
||||||
|
var x = 123;
|
||||||
|
|
||||||
|
const foo: int = 123;
|
||||||
|
const foo = 123;
|
||||||
|
|
||||||
|
type MyInt int;
|
||||||
|
type BarType proc();
|
||||||
|
|
||||||
|
proc bar() {
|
||||||
|
}
|
||||||
|
|
||||||
|
foreign lib {
|
||||||
|
proc foreign_bar();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
proc main() {
|
proc main() {
|
||||||
var program = "+ + * - /";
|
var program = "+ + * - /";
|
||||||
var accumulator = 0;
|
var accumulator = 0;
|
||||||
@@ -17,3 +423,5 @@ proc main() {
|
|||||||
fmt.printf("The program \"%s\" calculates the value %d\n",
|
fmt.printf("The program \"%s\" calculates the value %d\n",
|
||||||
program, accumulator);
|
program, accumulator);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|||||||
+13
-1
@@ -45,6 +45,11 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
|
|||||||
}
|
}
|
||||||
t = default_type(t);
|
t = default_type(t);
|
||||||
}
|
}
|
||||||
|
if (is_type_gen_proc(t)) {
|
||||||
|
error(e->token, "Invalid use of a generic procedure in %.*s", LIT(context_name));
|
||||||
|
e->type = t_invalid;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (is_type_bit_field_value(t)) {
|
if (is_type_bit_field_value(t)) {
|
||||||
t = default_bit_field_value_type(t);
|
t = default_bit_field_value_type(t);
|
||||||
}
|
}
|
||||||
@@ -361,7 +366,12 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
|||||||
|
|
||||||
if (pt->is_generic) {
|
if (pt->is_generic) {
|
||||||
if (pd->body == NULL) {
|
if (pd->body == NULL) {
|
||||||
error(e->token, "Generic procedures must have a body");
|
error(e->token, "Polymorphic procedures must have a body");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_foreign) {
|
||||||
|
error(e->token, "A foreign procedures cannot be a polymorphic");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,6 +397,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
|||||||
pt->require_results = is_require_results;
|
pt->require_results = is_require_results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (is_foreign) {
|
if (is_foreign) {
|
||||||
String name = e->token.string;
|
String name = e->token.string;
|
||||||
if (pd->link_name.len > 0) {
|
if (pd->link_name.len > 0) {
|
||||||
|
|||||||
+20
-16
@@ -12,7 +12,6 @@ enum CallArgumentError {
|
|||||||
CallArgumentError_ParameterNotFound,
|
CallArgumentError_ParameterNotFound,
|
||||||
CallArgumentError_ParameterMissing,
|
CallArgumentError_ParameterMissing,
|
||||||
CallArgumentError_DuplicateParameter,
|
CallArgumentError_DuplicateParameter,
|
||||||
CallArgumentError_GenericProcedureNotSupported,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CallArgumentErrorMode {
|
enum CallArgumentErrorMode {
|
||||||
@@ -285,9 +284,11 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
|
|||||||
|
|
||||||
|
|
||||||
if (is_type_any(dst)) {
|
if (is_type_any(dst)) {
|
||||||
// NOTE(bill): Anything can cast to `Any`
|
if (!is_type_gen_proc(src)) {
|
||||||
add_type_info_type(c, s);
|
// NOTE(bill): Anything can cast to `Any`
|
||||||
return 10;
|
add_type_info_type(c, s);
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4241,13 +4242,17 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
|
|
||||||
|
|
||||||
case BuiltinProc_type_of:
|
case BuiltinProc_type_of:
|
||||||
// proc type_of_val(val: Type) -> type(Type)
|
// proc type_of(val: Type) -> type(Type)
|
||||||
check_assignment(c, operand, NULL, str_lit("argument of `type_of_val`"));
|
check_assignment(c, operand, NULL, str_lit("argument of `type_of`"));
|
||||||
if (operand->mode == Addressing_Invalid || operand->mode == Addressing_Builtin) {
|
if (operand->mode == Addressing_Invalid || operand->mode == Addressing_Builtin) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (operand->type == NULL || operand->type == t_invalid || is_type_gen_proc(operand->type)) {
|
if (operand->type == NULL || operand->type == t_invalid) {
|
||||||
error(operand->expr, "Invalid argument to `type_of_val`");
|
error(operand->expr, "Invalid argument to `type_of`");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (is_type_gen_proc(operand->type)) {
|
||||||
|
error(operand->expr, "`type_of` of generic procedure cannot be determined");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
operand->mode = Addressing_Type;
|
operand->mode = Addressing_Type;
|
||||||
@@ -4999,10 +5004,10 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity,
|
|||||||
Type *final_proc_type = make_type_proc(c->allocator, c->context.scope, NULL, 0, NULL, 0, false, pt->calling_convention);
|
Type *final_proc_type = make_type_proc(c->allocator, c->context.scope, NULL, 0, NULL, 0, false, pt->calling_convention);
|
||||||
check_procedure_type(c, final_proc_type, pt->node, operands);
|
check_procedure_type(c, final_proc_type, pt->node, operands);
|
||||||
|
|
||||||
auto *found = map_get(&c->info.gen_procs, hash_pointer(base_entity->identifier));
|
auto *found_gen_procs = map_get(&c->info.gen_procs, hash_pointer(base_entity->identifier));
|
||||||
if (found) {
|
if (found_gen_procs) {
|
||||||
for_array(i, *found) {
|
for_array(i, *found_gen_procs) {
|
||||||
Entity *other = (*found)[i];
|
Entity *other = (*found_gen_procs)[i];
|
||||||
if (are_types_identical(other->type, final_proc_type)) {
|
if (are_types_identical(other->type, final_proc_type)) {
|
||||||
// NOTE(bill): This scope is not needed any more, destroy it
|
// NOTE(bill): This scope is not needed any more, destroy it
|
||||||
destroy_scope(scope);
|
destroy_scope(scope);
|
||||||
@@ -5041,13 +5046,13 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity,
|
|||||||
proc_info.body = pd->body;
|
proc_info.body = pd->body;
|
||||||
proc_info.tags = tags;
|
proc_info.tags = tags;
|
||||||
|
|
||||||
if (found) {
|
if (found_gen_procs) {
|
||||||
array_add(found, entity);
|
array_add(found_gen_procs, entity);
|
||||||
} else {
|
} else {
|
||||||
Array<Entity *> array = {};
|
Array<Entity *> array = {};
|
||||||
array_init(&array, heap_allocator());
|
array_init(&array, heap_allocator());
|
||||||
array_add(&array, entity);
|
array_add(&array, entity);
|
||||||
map_set(&c->info.gen_procs, hash_pointer(entity->identifier), array);
|
map_set(&c->info.gen_procs, hash_pointer(base_entity->identifier), array);
|
||||||
}
|
}
|
||||||
|
|
||||||
GB_ASSERT(entity != NULL);
|
GB_ASSERT(entity != NULL);
|
||||||
@@ -5373,7 +5378,6 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
|||||||
|
|
||||||
Entity *gen_entity = NULL;
|
Entity *gen_entity = NULL;
|
||||||
if (pt->is_generic && err == CallArgumentError_None) {
|
if (pt->is_generic && err == CallArgumentError_None) {
|
||||||
// err = CallArgumentError_GenericProcedureNotSupported;
|
|
||||||
ProcedureInfo proc_info = {};
|
ProcedureInfo proc_info = {};
|
||||||
gen_entity = find_or_generate_polymorphic_procedure(c, entity, &ordered_operands, &proc_info);
|
gen_entity = find_or_generate_polymorphic_procedure(c, entity, &ordered_operands, &proc_info);
|
||||||
if (gen_entity != NULL) {
|
if (gen_entity != NULL) {
|
||||||
|
|||||||
+2
-3
@@ -87,7 +87,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
|||||||
{STR_LIT("size_of"), 1, false, Expr_Expr},
|
{STR_LIT("size_of"), 1, false, Expr_Expr},
|
||||||
{STR_LIT("align_of"), 1, false, Expr_Expr},
|
{STR_LIT("align_of"), 1, false, Expr_Expr},
|
||||||
{STR_LIT("offset_of"), 2, false, Expr_Expr},
|
{STR_LIT("offset_of"), 2, false, Expr_Expr},
|
||||||
{STR_LIT("type_of_val"), 1, false, Expr_Expr},
|
{STR_LIT("type_of"), 1, false, Expr_Expr},
|
||||||
{STR_LIT("type_info"), 1, false, Expr_Expr},
|
{STR_LIT("type_info"), 1, false, Expr_Expr},
|
||||||
|
|
||||||
{STR_LIT("compile_assert"), 1, false, Expr_Expr},
|
{STR_LIT("compile_assert"), 1, false, Expr_Expr},
|
||||||
@@ -1456,7 +1456,7 @@ void check_procedure_overloading(Checker *c, Entity *e) {
|
|||||||
TypeProc *ptq = &base_type(q->type)->Proc;
|
TypeProc *ptq = &base_type(q->type)->Proc;
|
||||||
if (ptq->is_generic) {
|
if (ptq->is_generic) {
|
||||||
q->type = t_invalid;
|
q->type = t_invalid;
|
||||||
error(q->token, "Generic procedure `%.*s` cannot be overloaded", LIT(name));
|
error(q->token, "Polymorphic procedure `%.*s` cannot be overloaded", LIT(name));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2269,7 +2269,6 @@ void check_parsed_files(Checker *c) {
|
|||||||
if (pi->decl->gen_proc_type == NULL) {
|
if (pi->decl->gen_proc_type == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// gb_printf_err("Generic procedure `%.*s` -> %s\n", LIT(pi->token.string), type_to_string(pi->decl->gen_proc_type));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
add_curr_ast_file(c, pi->file);
|
add_curr_ast_file(c, pi->file);
|
||||||
|
|||||||
Reference in New Issue
Block a user