// Structs can be passed by value to procedures.
print_person :: (person: Person) {
- printf("Person(%s, %i, %i)\n", person.name, person.age, person.height);
+ printf("Person({}, {}, {})\n", person.name, person.age, person.height);
+
+ // Structs can also be printed using a single '{}' in printf.
+ printf("{}\n", person);
}
// This is the verbose way to declare a local variable with a struct
}
print_vector2f :: (vec: Vector2f) {
- printf("Vector2f(%f, %f)", vec.x, vec.y);
+ printf("{}", vec);
}
// This does initialize the members to their defaults.
fiu : FloatIntUnion;
fiu.f = 0.5f;
- printf("Integer representation of 0.5: %p\n", fiu.i);
+ printf("Integer representation of 0.5: {}\n", fiu.i);
another_data_member = 1234,
};
- printf("%s, (%f, %f)\n", thing.name, thing.velocity.x, thing.velocity.y);
+ printf("{}, ({}, {})\n", thing.name, thing.velocity.x, thing.velocity.y);
// This is very useful in many different situtations. Another useful feature is an implicit
// pointer conversion between two structs, A and B, if A is the first member of B, and is used.
// For example, we can pass `thing` to this procedure, even though it is not a ComponentOne.
// The first member is a ComponentOne and is used, so a implicit pointer conversion is always safe.
do_something_with_component_one :: (c: ^ComponentOne) {
- printf("ComponentOne's name is %s.\n", c.name);
+ printf("ComponentOne's name is {}.\n", c.name);
}
do_something_with_component_one(^thing);
println("param_struct_instance values:");
println(param_struct_instance.t_member);
- for elem: param_struct_instance.array_of_T do printf("%f ", elem);
+ for elem: param_struct_instance.array_of_T do printf("{} ", elem);
print("\n");
use package core
main :: (args: [] cstr) {
- // Currently, for loops can iterate over four kinds of data structures in Onyx:
+ // Currently, for loops can iterate over five kinds of data structures in Onyx:
// * Ranges
// * Fixed arrays
// * Slices
// * Dynamic arrays
+ // * Custom iterators
// The syntax of for loops is very simple:
// for ^? <iteration variable>: <iterator> <block>
print("Doubled primes: ");
print_array(primes);
- // Currently, there is not support for defining custom iterators for for-loops.
- // At the moment, this pattern is the best for that purpose:
+ // There is also support for custom iterators using the built-in Iterator type.
+ // You have to specify a next, close, and data member. The semantics are roughly
+ // as follows:
//
- // while it := iterator_create(...); !iterator_done(^it) {
- // defer iterator_next(^it);
- // ...
- // }
+ // 1. next is called to get two values: the next iteration value, and a
+ // continuation flag. If the continuation flag is true, then the iteration
+ // will continue for another iteration. If the continuation flag is false
+ // the iteration immediately terminates and the iteration value will be
+ // ignored.
+ //
+ // 2. close is called whenever the for-loop exits in any manner (finished,
+ // break, return).
+
+ {
+ value: i32 = 10;
+
+ // This is pointer provided to the iterator structure.
+ next :: (v: ^i32) -> (i32, bool) {
+ defer *v -= 1;
+ return *v, *v >= 0;
+ }
+
+ close :: (v: ^i32) {
+ println("Closing the iterator.");
+ }
+
+ iterator: Iterator(i32) = .{ data = ^value, next = next, close = close };
+
+ // Simply use the iterator.
+ for v: iterator {
+ println(v);
+ }
+ }
}
static bh_imap type_dynarr_map;
static bh_imap type_vararg_map;
+static Type* type_create(TypeKind kind, bh_allocator a, u32 extra_type_pointer_count) {
+ Type* type = bh_alloc(a, sizeof(Type) + sizeof(Type *) * extra_type_pointer_count);
+ type->kind = kind;
+ type->ast_type = NULL;
+ return type;
+}
+
static void type_register(Type* type) {
static u32 next_unique_id = 1;
type->id = next_unique_id++;
Type* return_type = type_build_from_ast(alloc, ftype_node->return_type);
if (return_type == NULL) return NULL;
- Type* func_type = bh_alloc(alloc, sizeof(Type) + sizeof(Type *) * param_count);
-
- func_type->kind = Type_Kind_Function;
+ Type* func_type = type_create(Type_Kind_Function, alloc, param_count);
func_type->ast_type = type_node;
func_type->Function.param_count = param_count;
func_type->Function.needed_param_count = param_count;
case Ast_Kind_Array_Type: {
AstArrayType* a_node = (AstArrayType *) type_node;
- Type* a_type = bh_alloc(alloc, sizeof(Type));
- a_type->kind = Type_Kind_Array;
- a_type->ast_type = type_node;
+ Type* a_type = type_create(Type_Kind_Array, alloc, 0);
a_type->Array.elem = type_build_from_ast(alloc, a_node->elem);
u32 count = 0;
Type* s_type;
if (s_node->stcache == NULL) {
- s_type = bh_alloc(alloc, sizeof(Type));
+ s_type = type_create(Type_Kind_Struct, alloc, 0);
s_node->stcache = s_type;
- s_type->kind = Type_Kind_Struct;
s_type->ast_type = type_node;
s_type->Struct.name = s_node->name;
s_type->Struct.mem_count = bh_arr_length(s_node->members);
if (enum_node->etcache) return enum_node->etcache;
if (enum_node->backing_type == NULL) return NULL;
- Type* enum_type = bh_alloc(alloc, sizeof(Type));
+ Type* enum_type = type_create(Type_Kind_Enum, alloc, 0);
enum_node->etcache = enum_type;
- enum_type->kind = Type_Kind_Enum;
enum_type->ast_type = type_node;
enum_type->Enum.backing = enum_node->backing_type;
enum_type->Enum.name = enum_node->name;
i64 type_count = bh_arr_length(ctype->types);
- Type* comp_type = bh_alloc(alloc, sizeof(Type) + sizeof(Type *) * type_count);
- comp_type->kind = Type_Kind_Compound;
+ Type* comp_type = type_create(Type_Kind_Compound, alloc, type_count);
comp_type->Compound.size = 0;
comp_type->Compound.count = type_count;
Type* return_type = type_build_from_ast(alloc, func->return_type);
if (return_type == NULL) return NULL;
- Type* func_type = bh_alloc(alloc, sizeof(Type) + sizeof(Type *) * param_count);
-
- func_type->kind = Type_Kind_Function;
+ Type* func_type = type_create(Type_Kind_Function, alloc, param_count);
func_type->Function.param_count = param_count;
func_type->Function.needed_param_count = 0;
func_type->Function.vararg_arg_pos = -1;
if (compound->exprs[i]->type == NULL) return NULL;
}
- Type* comp_type = bh_alloc(alloc, sizeof(Type) + sizeof(Type *) * expr_count);
- comp_type->kind = Type_Kind_Compound;
+ Type* comp_type = type_create(Type_Kind_Compound, alloc, expr_count);
comp_type->Compound.size = 0;
comp_type->Compound.count = expr_count;
return ptr_type;
} else {
- Type* ptr_type = bh_alloc_item(alloc, Type);
-
- ptr_type->kind = Type_Kind_Pointer;
+ Type* ptr_type = type_create(Type_Kind_Pointer, alloc, 0);
ptr_type->Pointer.base.flags |= Basic_Flag_Pointer;
ptr_type->Pointer.base.size = 8;
ptr_type->Pointer.elem = to;
Type* type_make_array(bh_allocator alloc, Type* to, u32 count) {
if (to == NULL) return NULL;
- Type* arr_type = bh_alloc_item(alloc, Type);
-
- arr_type->kind = Type_Kind_Array;
+ Type* arr_type = type_create(Type_Kind_Array, alloc, 0);
arr_type->Array.count = count;
arr_type->Array.elem = to;
arr_type->Array.size = count * type_size_of(to);
return slice_type;
} else {
- Type* slice_type = bh_alloc(alloc, sizeof(Type));
- slice_type->kind = Type_Kind_Slice;
+ Type* slice_type = type_create(Type_Kind_Slice, alloc, 0);
type_register(slice_type);
bh_imap_put(&type_slice_map, of->id, slice_type->id);
return dynarr;
} else {
- Type* dynarr = bh_alloc(alloc, sizeof(Type));
- dynarr->kind = Type_Kind_DynArray;
+ Type* dynarr = type_create(Type_Kind_DynArray, alloc, 0);
type_register(dynarr);
bh_imap_put(&type_dynarr_map, of->id, dynarr->id);
return va_type;
} else {
- Type* va_type = bh_alloc(alloc, sizeof(Type));
- va_type->kind = Type_Kind_VarArgs;
+ Type* va_type = type_create(Type_Kind_VarArgs, alloc, 0);
type_register(va_type);
bh_imap_put(&type_vararg_map, of->id, va_type->id);