mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 23:28:48 +00:00
Add new #soa and #vector syntax
This commit is contained in:
@@ -394,6 +394,13 @@ write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) {
|
|||||||
write_type(buf, info.value);
|
write_type(buf, info.value);
|
||||||
|
|
||||||
case rt.Type_Info_Struct:
|
case rt.Type_Info_Struct:
|
||||||
|
if info.soa_base_type != nil {
|
||||||
|
write_string(buf, "#soa[");
|
||||||
|
write_i64(buf, i64(info.soa_len));
|
||||||
|
write_byte(buf, ']');
|
||||||
|
write_type(buf, info.soa_base_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
write_string(buf, "struct ");
|
write_string(buf, "struct ");
|
||||||
if info.is_packed do write_string(buf, "#packed ");
|
if info.is_packed do write_string(buf, "#packed ");
|
||||||
if info.is_raw_union do write_string(buf, "#raw_union ");
|
if info.is_raw_union do write_string(buf, "#raw_union ");
|
||||||
@@ -479,11 +486,10 @@ write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) {
|
|||||||
if info.is_x86_mmx {
|
if info.is_x86_mmx {
|
||||||
write_string(buf, "intrinsics.x86_mmx");
|
write_string(buf, "intrinsics.x86_mmx");
|
||||||
} else {
|
} else {
|
||||||
write_string(buf, "intrinsics.vector(");
|
write_string(buf, "#vector[");
|
||||||
write_i64(buf, i64(info.count));
|
write_i64(buf, i64(info.count));
|
||||||
write_string(buf, ", ");
|
write_byte(buf, ']');
|
||||||
write_type(buf, info.elem);
|
write_type(buf, info.elem);
|
||||||
write_byte(buf, ')');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,6 +183,13 @@ print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
|
|||||||
print_type(fd, info.value);
|
print_type(fd, info.value);
|
||||||
|
|
||||||
case Type_Info_Struct:
|
case Type_Info_Struct:
|
||||||
|
if info.soa_base_type != nil {
|
||||||
|
os.write_string(fd, "#soa[");
|
||||||
|
print_u64(fd, u64(info.soa_len));
|
||||||
|
os.write_byte(fd, ']');
|
||||||
|
print_type(fd, info.soa_base_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
os.write_string(fd, "struct ");
|
os.write_string(fd, "struct ");
|
||||||
if info.is_packed do os.write_string(fd, "#packed ");
|
if info.is_packed do os.write_string(fd, "#packed ");
|
||||||
if info.is_raw_union do os.write_string(fd, "#raw_union ");
|
if info.is_raw_union do os.write_string(fd, "#raw_union ");
|
||||||
@@ -263,11 +270,10 @@ print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
|
|||||||
if info.is_x86_mmx {
|
if info.is_x86_mmx {
|
||||||
os.write_string(fd, "intrinsics.x86_mmx");
|
os.write_string(fd, "intrinsics.x86_mmx");
|
||||||
} else {
|
} else {
|
||||||
os.write_string(fd, "intrinsics.vector(");
|
os.write_string(fd, "#vector[");
|
||||||
print_u64(fd, u64(info.count));
|
print_u64(fd, u64(info.count));
|
||||||
os.write_string(fd, ", ");
|
os.write_byte(fd, ']');
|
||||||
print_type(fd, info.elem);
|
print_type(fd, info.elem);
|
||||||
os.write_byte(fd, ')');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+708
-334
File diff suppressed because it is too large
Load Diff
@@ -3,5 +3,5 @@ package basic
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
fmt.println("Hellope!")
|
fmt.println("Hellope!");
|
||||||
}
|
}
|
||||||
+48
-48
@@ -6,62 +6,62 @@ import "core:time"
|
|||||||
import "intrinsics"
|
import "intrinsics"
|
||||||
|
|
||||||
elementary_cellular_automata :: proc(state: $T, rule: u8, generations: int, pause: time.Duration = 0)
|
elementary_cellular_automata :: proc(state: $T, rule: u8, generations: int, pause: time.Duration = 0)
|
||||||
where intrinsics.type_is_integer(T),
|
where intrinsics.type_is_integer(T),
|
||||||
intrinsics.type_is_unsigned(T) {
|
intrinsics.type_is_unsigned(T) {
|
||||||
N :: 8*size_of(state);
|
N :: 8*size_of(state);
|
||||||
|
|
||||||
output :: proc(state: T) {
|
output :: proc(state: T) {
|
||||||
buf: [N]byte;
|
buf: [N]byte;
|
||||||
for i in 0..<T(N) {
|
for i in 0..<T(N) {
|
||||||
// c := byte('#');
|
c := byte('#');
|
||||||
c := byte(rand.int_max(26) + 'A' + ('a'-'A')*rand.int_max(2));
|
// c := byte(rand.int_max(26) + 'A' + ('a'-'A')*rand.int_max(2));
|
||||||
buf[N-1-i] = state & (1<<i) != 0 ? c : ' ';
|
buf[N-1-i] = state & (1<<i) != 0 ? c : ' ';
|
||||||
}
|
}
|
||||||
fmt.println(string(buf[:]));
|
fmt.println(string(buf[:]));
|
||||||
}
|
}
|
||||||
|
|
||||||
bit :: proc(x, i: T) -> T {
|
bit :: proc(x, i: T) -> T {
|
||||||
return (x >> i) & 0x1;
|
return (x >> i) & 0x1;
|
||||||
}
|
}
|
||||||
set :: proc(x: ^T, cell, k: T, rule: u8) {
|
set :: proc(x: ^T, cell, k: T, rule: u8) {
|
||||||
x^ &~= 1<<cell;
|
x^ &~= 1<<cell;
|
||||||
if rule>>k&1 != 0 {
|
if rule>>k&1 != 0 {
|
||||||
x^ |= 1<<cell;
|
x^ |= 1<<cell;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
a := state;
|
a := state;
|
||||||
a1 := T(0);
|
a1 := T(0);
|
||||||
|
|
||||||
output(a);
|
output(a);
|
||||||
|
|
||||||
last := T(N-1);
|
last := T(N-1);
|
||||||
for r in 0..<generations {
|
for r in 0..<generations {
|
||||||
if pause > 0 do time.sleep(pause);
|
if pause > 0 do time.sleep(pause);
|
||||||
|
|
||||||
|
|
||||||
k := bit(a, last) | bit(a, 0)<<1 | bit(a, 1)<<2;
|
k := bit(a, last) | bit(a, 0)<<1 | bit(a, 1)<<2;
|
||||||
set(&a1, 0, k, rule);
|
set(&a1, 0, k, rule);
|
||||||
a1 |= (1<<0) * T(rule>>k&1);
|
a1 |= (1<<0) * T(rule>>k&1);
|
||||||
for c in 1..<last {
|
for c in 1..<last {
|
||||||
k = k>>1 | bit(a, c+1)<<2;
|
k = k>>1 | bit(a, c+1)<<2;
|
||||||
set(&a1, c, k, rule);
|
set(&a1, c, k, rule);
|
||||||
}
|
}
|
||||||
set(&a1, last, k>>1|bit(a, 0)<<2, rule);
|
set(&a1, last, k>>1|bit(a, 0)<<2, rule);
|
||||||
a, a1 = a1, a;
|
a, a1 = a1, a;
|
||||||
output(a);
|
output(a);
|
||||||
if a == a1 {
|
if a == a1 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
elementary_cellular_automata(
|
elementary_cellular_automata(
|
||||||
state=rand.uint128(),
|
state=rand.uint128(),
|
||||||
rule=30,
|
rule=30,
|
||||||
generations=100,
|
generations=5000,
|
||||||
pause=100*time.Millisecond,
|
pause=100*time.Millisecond,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1674,7 +1674,7 @@ soa_struct_layout :: proc() {
|
|||||||
fmt.println(v_aos[1]);
|
fmt.println(v_aos[1]);
|
||||||
fmt.println(v_aos);
|
fmt.println(v_aos);
|
||||||
|
|
||||||
v_soa: intrinsics.soa_struct(N, Vector3);
|
v_soa: #soa[N]Vector3;
|
||||||
|
|
||||||
v_soa[0].x = 1;
|
v_soa[0].x = 1;
|
||||||
v_soa[0].y = 4;
|
v_soa[0].y = 4;
|
||||||
@@ -1713,7 +1713,7 @@ soa_struct_layout :: proc() {
|
|||||||
v_aos[0].y = 4;
|
v_aos[0].y = 4;
|
||||||
v_aos[0].z = 9;
|
v_aos[0].z = 9;
|
||||||
|
|
||||||
v_soa: intrinsics.soa_struct(N, Vector3);
|
v_soa: #soa[N]Vector3;
|
||||||
|
|
||||||
v_soa[0].x = 1;
|
v_soa[0].x = 1;
|
||||||
v_soa[0].y = 4;
|
v_soa[0].y = 4;
|
||||||
|
|||||||
+105
-1
@@ -2884,11 +2884,115 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
|
|||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
Type *elem = check_type_expr(ctx, at->elem, nullptr);
|
Type *elem = check_type_expr(ctx, at->elem, nullptr);
|
||||||
*type = alloc_type_array(elem, count, generic_type);
|
|
||||||
|
if (at->tag != nullptr) {
|
||||||
|
GB_ASSERT(at->tag->kind == Ast_BasicDirective);
|
||||||
|
String name = at->tag->BasicDirective.name;
|
||||||
|
if (name == "soa") {
|
||||||
|
Type *bt_elem = base_type(elem);
|
||||||
|
if (!is_type_struct(elem) && !is_type_raw_union(elem) && !(is_type_array(elem) && bt_elem->Array.count <= 4)) {
|
||||||
|
gbString str = type_to_string(elem);
|
||||||
|
error(at->elem, "Invalid type for an #soa array, expected a struct or array of length 4 or below, got '%s'", str);
|
||||||
|
gb_string_free(str);
|
||||||
|
*type = alloc_type_array(elem, count, generic_type);
|
||||||
|
goto array_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type *soa_struct = nullptr;
|
||||||
|
Scope *scope = nullptr;
|
||||||
|
|
||||||
|
if (is_type_array(elem)) {
|
||||||
|
Type *old_array = base_type(elem);
|
||||||
|
soa_struct = alloc_type_struct();
|
||||||
|
soa_struct->Struct.fields = array_make<Entity *>(heap_allocator(), old_array->Array.count);
|
||||||
|
soa_struct->Struct.tags = array_make<String>(heap_allocator(), old_array->Array.count);
|
||||||
|
soa_struct->Struct.node = e;
|
||||||
|
soa_struct->Struct.is_soa = true;
|
||||||
|
soa_struct->Struct.soa_elem = elem;
|
||||||
|
soa_struct->Struct.soa_count = count;
|
||||||
|
|
||||||
|
scope = create_scope(ctx->scope, ctx->allocator);
|
||||||
|
soa_struct->Struct.scope = scope;
|
||||||
|
|
||||||
|
String params_xyzw[4] = {
|
||||||
|
str_lit("x"),
|
||||||
|
str_lit("y"),
|
||||||
|
str_lit("z"),
|
||||||
|
str_lit("w")
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i64 i = 0; i < old_array->Array.count; i++) {
|
||||||
|
Type *array_type = alloc_type_array(old_array->Array.elem, count);
|
||||||
|
Token token = {};
|
||||||
|
token.string = params_xyzw[i];
|
||||||
|
|
||||||
|
Entity *new_field = alloc_entity_field(scope, token, array_type, false, cast(i32)i);
|
||||||
|
soa_struct->Struct.fields[i] = new_field;
|
||||||
|
add_entity(ctx->checker, scope, nullptr, new_field);
|
||||||
|
add_entity_use(ctx, nullptr, new_field);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
GB_ASSERT(is_type_struct(elem));
|
||||||
|
|
||||||
|
Type *old_struct = base_type(elem);
|
||||||
|
soa_struct = alloc_type_struct();
|
||||||
|
soa_struct->Struct.fields = array_make<Entity *>(heap_allocator(), old_struct->Struct.fields.count);
|
||||||
|
soa_struct->Struct.tags = array_make<String>(heap_allocator(), old_struct->Struct.tags.count);
|
||||||
|
soa_struct->Struct.node = e;
|
||||||
|
soa_struct->Struct.is_soa = true;
|
||||||
|
soa_struct->Struct.soa_elem = elem;
|
||||||
|
soa_struct->Struct.soa_count = count;
|
||||||
|
|
||||||
|
scope = create_scope(old_struct->Struct.scope->parent, ctx->allocator);
|
||||||
|
soa_struct->Struct.scope = scope;
|
||||||
|
|
||||||
|
for_array(i, old_struct->Struct.fields) {
|
||||||
|
Entity *old_field = old_struct->Struct.fields[i];
|
||||||
|
if (old_field->kind == Entity_Variable) {
|
||||||
|
Type *array_type = alloc_type_array(old_field->type, count);
|
||||||
|
Entity *new_field = alloc_entity_field(scope, old_field->token, array_type, false, old_field->Variable.field_src_index);
|
||||||
|
soa_struct->Struct.fields[i] = new_field;
|
||||||
|
add_entity(ctx->checker, scope, nullptr, new_field);
|
||||||
|
} else {
|
||||||
|
soa_struct->Struct.fields[i] = old_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
soa_struct->Struct.tags[i] = old_struct->Struct.tags[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Token token = {};
|
||||||
|
token.string = str_lit("Base_Type");
|
||||||
|
Entity *base_type_entity = alloc_entity_type_name(scope, token, elem, EntityState_Resolved);
|
||||||
|
add_entity(ctx->checker, scope, nullptr, base_type_entity);
|
||||||
|
|
||||||
|
add_type_info_type(ctx, soa_struct);
|
||||||
|
|
||||||
|
*type = soa_struct;
|
||||||
|
|
||||||
|
|
||||||
|
} else if (name == "vector") {
|
||||||
|
if (!is_type_valid_vector_elem(elem)) {
|
||||||
|
gbString str = type_to_string(elem);
|
||||||
|
error(at->elem, "Invalid element type for 'intrinsics.vector', expected an integer or float with no specific endianness, got '%s'", str);
|
||||||
|
gb_string_free(str);
|
||||||
|
*type = alloc_type_array(elem, count, generic_type);
|
||||||
|
goto array_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
*type = alloc_type_simd_vector(count, elem);
|
||||||
|
} else {
|
||||||
|
GB_PANIC("Unhandled array type tag %.*s", LIT(name));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*type = alloc_type_array(elem, count, generic_type);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Type *elem = check_type(ctx, at->elem);
|
Type *elem = check_type(ctx, at->elem);
|
||||||
*type = alloc_type_slice(elem);
|
*type = alloc_type_slice(elem);
|
||||||
}
|
}
|
||||||
|
array_end:
|
||||||
set_base_type(named_type, *type);
|
set_base_type(named_type, *type);
|
||||||
return true;
|
return true;
|
||||||
case_end;
|
case_end;
|
||||||
|
|||||||
@@ -1758,6 +1758,17 @@ Ast *parse_operand(AstFile *f, bool lhs) {
|
|||||||
} else if (name.string == "defined") {
|
} else if (name.string == "defined") {
|
||||||
Ast *tag = ast_basic_directive(f, token, name.string);
|
Ast *tag = ast_basic_directive(f, token, name.string);
|
||||||
return parse_call_expr(f, tag);
|
return parse_call_expr(f, tag);
|
||||||
|
} else if (name.string == "soa" || name.string == "vector") {
|
||||||
|
Ast *tag = ast_basic_directive(f, token, name.string);
|
||||||
|
Ast *type = parse_type(f);
|
||||||
|
switch (type->kind) {
|
||||||
|
case Ast_ArrayType: type->ArrayType.tag = tag; break;
|
||||||
|
case Ast_DynamicArrayType: type->DynamicArrayType.tag = tag; break;
|
||||||
|
default:
|
||||||
|
syntax_error(type, "Expected an array type after #%.*s, got %.*s", LIT(name.string), LIT(ast_strings[type->kind]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return type;
|
||||||
} else {
|
} else {
|
||||||
operand = ast_tag_expr(f, token, name, parse_expr(f, false));
|
operand = ast_tag_expr(f, token, name, parse_expr(f, false));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -489,10 +489,12 @@ AST_KIND(_TypeBegin, "", bool) \
|
|||||||
Token token; \
|
Token token; \
|
||||||
Ast *count; \
|
Ast *count; \
|
||||||
Ast *elem; \
|
Ast *elem; \
|
||||||
|
Ast *tag; \
|
||||||
}) \
|
}) \
|
||||||
AST_KIND(DynamicArrayType, "dynamic array type", struct { \
|
AST_KIND(DynamicArrayType, "dynamic array type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Ast *elem; \
|
Ast *elem; \
|
||||||
|
Ast *tag; \
|
||||||
}) \
|
}) \
|
||||||
AST_KIND(StructType, "struct type", struct { \
|
AST_KIND(StructType, "struct type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
|
|||||||
Reference in New Issue
Block a user