Browse Source

Add new #soa and #vector syntax

gingerBill 5 years ago
parent
commit
d22e5b697d

+ 9 - 3
core/reflect/types.odin

@@ -394,6 +394,13 @@ write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) {
 		write_type(buf, info.value);
 
 	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 ");
 		if info.is_packed    do write_string(buf, "#packed ");
 		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 {
 			write_string(buf, "intrinsics.x86_mmx");
 		} else {
-			write_string(buf, "intrinsics.vector(");
+			write_string(buf, "#vector[");
 			write_i64(buf, i64(info.count));
-			write_string(buf, ", ");
+			write_byte(buf, ']');
 			write_type(buf, info.elem);
-			write_byte(buf, ')');
 		}
 	}
 }

+ 9 - 3
core/runtime/internal.odin

@@ -183,6 +183,13 @@ print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
 		print_type(fd, info.value);
 
 	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 ");
 		if info.is_packed    do os.write_string(fd, "#packed ");
 		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 {
 			os.write_string(fd, "intrinsics.x86_mmx");
 		} else {
-			os.write_string(fd, "intrinsics.vector(");
+			os.write_string(fd, "#vector[");
 			print_u64(fd, u64(info.count));
-			os.write_string(fd, ", ");
+			os.write_byte(fd, ']');
 			print_type(fd, info.elem);
-			os.write_byte(fd, ')');
 		}
 	}
 }

File diff suppressed because it is too large
+ 631 - 294
examples/demo/demo.odin


+ 1 - 1
examples/hms2019/basic.odin

@@ -3,5 +3,5 @@ package basic
 import "core:fmt"
 
 main :: proc() {
-	fmt.println("Hellope!")
+	fmt.println("Hellope!");
 }

+ 48 - 48
examples/hms2019/eca.odin

@@ -6,62 +6,62 @@ import "core:time"
 import "intrinsics"
 
 elementary_cellular_automata :: proc(state: $T, rule: u8, generations: int, pause: time.Duration = 0)
-    where intrinsics.type_is_integer(T),
-          intrinsics.type_is_unsigned(T) {
-    N :: 8*size_of(state);
+	where intrinsics.type_is_integer(T),
+		  intrinsics.type_is_unsigned(T) {
+	N :: 8*size_of(state);
 
-    output :: proc(state: T) {
-        buf: [N]byte;
-        for i in 0..<T(N) {
-            // c := byte('#');
-            c := byte(rand.int_max(26) + 'A' + ('a'-'A')*rand.int_max(2));
-            buf[N-1-i] = state & (1<<i) != 0 ? c : ' ';
-        }
-        fmt.println(string(buf[:]));
-    }
+	output :: proc(state: T) {
+		buf: [N]byte;
+		for i in 0..<T(N) {
+			c := byte('#');
+			// c := byte(rand.int_max(26) + 'A' + ('a'-'A')*rand.int_max(2));
+			buf[N-1-i] = state & (1<<i) != 0 ? c : ' ';
+		}
+		fmt.println(string(buf[:]));
+	}
 
-    bit :: proc(x, i: T) -> T {
-        return (x >> i) & 0x1;
-    }
-    set :: proc(x: ^T, cell, k: T, rule: u8) {
-        x^ &~= 1<<cell;
-        if rule>>k&1 != 0 {
-            x^ |= 1<<cell;
-        }
-    }
+	bit :: proc(x, i: T) -> T {
+		return (x >> i) & 0x1;
+	}
+	set :: proc(x: ^T, cell, k: T, rule: u8) {
+		x^ &~= 1<<cell;
+		if rule>>k&1 != 0 {
+			x^ |= 1<<cell;
+		}
+	}
 
 
-    a := state;
-    a1 := T(0);
+	a := state;
+	a1 := T(0);
 
-    output(a);
+	output(a);
 
-    last := T(N-1);
-    for r in 0..<generations {
-        if pause > 0 do time.sleep(pause);
-    
+	last := T(N-1);
+	for r in 0..<generations {
+		if pause > 0 do time.sleep(pause);
+	
 
-        k := bit(a, last) | bit(a, 0)<<1 | bit(a, 1)<<2;
-        set(&a1, 0, k, rule);
-        a1 |= (1<<0) * T(rule>>k&1);
-        for c in 1..<last {
-            k = k>>1 | bit(a, c+1)<<2;
-            set(&a1, c, k, rule);
-        }
-        set(&a1, last, k>>1|bit(a, 0)<<2, rule);
-        a, a1 = a1, a;
-        output(a);
-        if a == a1 {
-            return;
-        }
-    }
+		k := bit(a, last) | bit(a, 0)<<1 | bit(a, 1)<<2;
+		set(&a1, 0, k, rule);
+		a1 |= (1<<0) * T(rule>>k&1);
+		for c in 1..<last {
+			k = k>>1 | bit(a, c+1)<<2;
+			set(&a1, c, k, rule);
+		}
+		set(&a1, last, k>>1|bit(a, 0)<<2, rule);
+		a, a1 = a1, a;
+		output(a);
+		if a == a1 {
+			return;
+		}
+	}
 }
 
 main :: proc() {
-    elementary_cellular_automata(
-        state=rand.uint128(),
-        rule=30,
-        generations=100,
-        pause=100*time.Millisecond,
-    );
+	elementary_cellular_automata(
+		state=rand.uint128(),
+		rule=30,
+		generations=5000,
+		pause=100*time.Millisecond,
+	);
 }

+ 2 - 2
examples/hms2019/hms2019.odin

@@ -1674,7 +1674,7 @@ soa_struct_layout :: proc() {
 		fmt.println(v_aos[1]);
 		fmt.println(v_aos);
 
-		v_soa: intrinsics.soa_struct(N, Vector3);
+		v_soa: #soa[N]Vector3;
 
 		v_soa[0].x = 1;
 		v_soa[0].y = 4;
@@ -1713,7 +1713,7 @@ soa_struct_layout :: proc() {
 		v_aos[0].y = 4;
 		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].y = 4;

+ 105 - 1
src/check_type.cpp

@@ -2884,11 +2884,115 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
 				count = 0;
 			}
 			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 {
 			Type *elem = check_type(ctx, at->elem);
 			*type = alloc_type_slice(elem);
 		}
+	array_end:
 		set_base_type(named_type, *type);
 		return true;
 	case_end;

+ 11 - 0
src/parser.cpp

@@ -1758,6 +1758,17 @@ Ast *parse_operand(AstFile *f, bool lhs) {
 		} else if (name.string == "defined") {
 			Ast *tag = ast_basic_directive(f, token, name.string);
 			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 {
 			operand = ast_tag_expr(f, token, name, parse_expr(f, false));
 		}

+ 2 - 0
src/parser.hpp

@@ -489,10 +489,12 @@ AST_KIND(_TypeBegin, "", bool) \
 		Token token; \
 		Ast *count; \
 		Ast *elem; \
+		Ast *tag;  \
 	}) \
 	AST_KIND(DynamicArrayType, "dynamic array type", struct { \
 		Token token; \
 		Ast *elem; \
+		Ast *tag;  \
 	}) \
 	AST_KIND(StructType, "struct type", struct { \
 		Token token;                \

Some files were not shown because too many files changed in this diff