mirror of
https://github.com/odin-lang/Odin.git
synced 2026-03-01 06:08:19 +00:00
Initial Demo001 code for tour of language
This commit is contained in:
@@ -45,7 +45,7 @@ pushd %build_dir%
|
||||
|
||||
cl %compiler_settings% "..\src\main.cpp" ^
|
||||
/link %linker_settings% -OUT:%exe_name% ^
|
||||
&& odin run ..\examples/main.odin
|
||||
&& odin run ..\examples/demo001.odin
|
||||
|
||||
|
||||
:do_not_compile_exe
|
||||
|
||||
525
examples/demo001.odin
Normal file
525
examples/demo001.odin
Normal file
@@ -0,0 +1,525 @@
|
||||
#load "basic.odin"
|
||||
#load "math.odin"
|
||||
// #load "game.odin"
|
||||
|
||||
main :: proc() {
|
||||
_ = hellope();
|
||||
procedures();
|
||||
variables();
|
||||
constants();
|
||||
types();
|
||||
data_control();
|
||||
// run_game();
|
||||
}
|
||||
|
||||
hellope :: proc() -> int {
|
||||
print_string("Hellope, 世界\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
apple, banana, carrot: bool;
|
||||
box, carboard: bool = true, false;
|
||||
hellope_value := hellope();
|
||||
|
||||
variables :: proc() {
|
||||
i: int; // initialized with zero value
|
||||
j: int = 1;
|
||||
x, y: int = 1, 2;
|
||||
|
||||
// Type inference
|
||||
apple, banana, carrot := true, 123, "carrot";
|
||||
|
||||
|
||||
// Basic Types of the Language
|
||||
//
|
||||
// bool
|
||||
//
|
||||
// i8 i16 i32 i64 i128
|
||||
// u8 u16 u32 u64 u128
|
||||
//
|
||||
// f32 f64
|
||||
//
|
||||
// int uint (size_of(int) = size_of(rawptr))
|
||||
//
|
||||
// rawptr
|
||||
//
|
||||
// string
|
||||
//
|
||||
// byte - alias for u8
|
||||
// rune - alias for i32 // Unicode Codepoint
|
||||
//
|
||||
// untyped bool - "untyped" types can implicitly convert to any of the "typed" types
|
||||
// untyped integer
|
||||
// untyped float
|
||||
// untyped pointer
|
||||
// untyped string
|
||||
// untyped rune
|
||||
|
||||
|
||||
// // Zero values
|
||||
zero_numeric := 0;
|
||||
zero_boolean := false;
|
||||
zero_pointer := null;
|
||||
zero_string1 := ""; // Escaped string
|
||||
zero_string2 := ``; // Raw string
|
||||
|
||||
// Unary operators
|
||||
// +a
|
||||
// -a
|
||||
// ~a
|
||||
// !a
|
||||
|
||||
// Binary operators
|
||||
// a + b
|
||||
// a - b
|
||||
// a ~ b
|
||||
// a | b
|
||||
|
||||
// a * b
|
||||
// a / b
|
||||
// a % b
|
||||
// a & b
|
||||
// a &~ b == a & (~b)
|
||||
// a << b
|
||||
// a >> b
|
||||
|
||||
// a as Type
|
||||
// a transmute Type
|
||||
|
||||
// a == b
|
||||
// a != b
|
||||
// a < b
|
||||
// a > b
|
||||
// a <= b
|
||||
// a >= b
|
||||
|
||||
}
|
||||
|
||||
procedures :: proc() {
|
||||
add :: proc(x: int, y: int) -> int {
|
||||
return x + y;
|
||||
}
|
||||
print_int(add(3, 4)); // 7
|
||||
print_rune('\n');
|
||||
|
||||
add_v2 :: proc(x, y: int) -> int {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
|
||||
swap_strings :: proc(x, y: string) -> (string, string) {
|
||||
return y, x;
|
||||
}
|
||||
a, b := swap_strings("Hellope\n", "World\n");
|
||||
print_string(a);
|
||||
print_string(b);
|
||||
|
||||
a, b = b, a; // Quirk of grammar the of multiple assignments
|
||||
print_string(a);
|
||||
print_string(b);
|
||||
|
||||
// Not hints, it's mandatory
|
||||
proc1 :: proc(a, b: int) #inline {
|
||||
print_int(a + b);
|
||||
}
|
||||
proc2 :: proc(a, b: int) #no_inline {
|
||||
print_int(a + b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TAU :: 6.28318530718;
|
||||
|
||||
constants :: proc() {
|
||||
TAU :: 6.28318530718; // untyped float
|
||||
WORLD_JAPANESE :: "世界"; // untyped string
|
||||
|
||||
TAU_32 : f32 : 6.28318530718;
|
||||
TAU_AS_32 :: 6.28318530718 as f32;
|
||||
}
|
||||
|
||||
nl :: proc() { print_rune('\n'); }
|
||||
|
||||
types :: proc() {
|
||||
|
||||
x: int = 123;
|
||||
y := x; // y: int = x;
|
||||
// z: f32 = x; // invalid
|
||||
z: f32 = x as f32;
|
||||
|
||||
ptr_z := ^z; // Pascal notation
|
||||
ptr_z^ = 123; // Derefence Notation
|
||||
print_f32(z); nl();
|
||||
|
||||
// ^z - pointer to z
|
||||
// z^ - z from pointer
|
||||
|
||||
f32_array: [12]f32; // Array of 12 f32
|
||||
f32_array[0] = 2;
|
||||
f32_array[1] = 3;
|
||||
// f32_array[-1] = 2; // Error - compile time check
|
||||
// f32_array[13] = 2; // Error - compile time check
|
||||
f32_array_len := len(f32_array); // builtin procedure
|
||||
f32_array_cap := cap(f32_array); // == len(f32_array)
|
||||
|
||||
api: [2]^f32;
|
||||
papi: ^[2]^f32;
|
||||
|
||||
f32_slice: []f32; // Array reference
|
||||
f32_slice = f32_array[0:5];
|
||||
f32_slice = f32_array[:5];
|
||||
f32_slice = f32_array[:]; // f32_array[0:len(f32_array)-1];
|
||||
|
||||
f32_slice = f32_array[1:5:7]; // low:1, high:5, capacity:7
|
||||
|
||||
append_success := append(^f32_slice, 1);
|
||||
_ = append(^f32_slice, 2);
|
||||
|
||||
_ = copy(f32_array[0:2], f32_array[2:4]); // You can use memcpy/memmove if you want
|
||||
|
||||
|
||||
s := "Hellope World";
|
||||
sub_string := s[5:10];
|
||||
|
||||
v0: {4}f32; // Vector of 4 f32
|
||||
v0[0] = 1;
|
||||
v0[1] = 3;
|
||||
v0[2] = 6;
|
||||
v0[3] = 10;
|
||||
|
||||
v1 := v0 + v0; // Simd Arithmetic
|
||||
v1 = v1 - v0;
|
||||
v1 *= v0; // i.e. hadamard product
|
||||
v1 /= v0;
|
||||
|
||||
// builtin procedure
|
||||
v2 := swizzle(v0, 3, 2, 1, 0); // {10, 6, 3, 1}
|
||||
|
||||
v3: {4}bool = v0 == v2;
|
||||
// LLVM rant?
|
||||
|
||||
|
||||
type Vec4: {4}f32;
|
||||
type Array3Int: [3]int;
|
||||
|
||||
type Vec3: struct {
|
||||
x, y, z: f32
|
||||
}
|
||||
|
||||
type BinaryNode: struct {
|
||||
left, right: ^BinaryNode, // same format as procedure argument
|
||||
data: rawptr,
|
||||
}
|
||||
|
||||
type AddProc: proc(a, b: int) -> int
|
||||
|
||||
type Packed: struct #packed {
|
||||
a: u8,
|
||||
b: u16,
|
||||
c: u32,
|
||||
}
|
||||
static_assert(size_of(Packed) == 7);
|
||||
|
||||
|
||||
{
|
||||
type MyInt: int
|
||||
x: int = 1;
|
||||
y: MyInt = 2;
|
||||
// z := x + y; // Failure - types cannot implicit convert*
|
||||
z := x as MyInt + y; // Type cast using `as`
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
// From: Quake III Arena
|
||||
Q_rsqrt :: proc(number: f32) -> f32 {
|
||||
i: i32;
|
||||
x2, y: f32;
|
||||
THREE_HALFS :: 1.5;
|
||||
|
||||
x2 = number * 0.5;
|
||||
y = number;
|
||||
i = (^y as ^i32)^; // evil floating point bit level hacking
|
||||
i = 0x5f3759df - i>>1; // what the fuck?
|
||||
y = (^i as ^f32)^;
|
||||
y = y * (THREE_HALFS - (x2 * y *y)); // 1st iteration
|
||||
// y = y * (THREE_HALFS - (x2 * y *y)); // 2nd iteration, this can be removed
|
||||
return y;
|
||||
}
|
||||
|
||||
Q_rsqrt_v2 :: proc(number: f32) -> f32 {
|
||||
THREE_HALFS :: 1.5;
|
||||
|
||||
x2 := number * 0.5;
|
||||
y := number;
|
||||
i := y transmute i32; // evil floating point bit level hacking
|
||||
i = 0x5f3759df - i>>1; // what the fuck?
|
||||
y = i transmute f32;
|
||||
y = y * (THREE_HALFS - (x2 * y *y)); // 1st iteration
|
||||
// y = y * (THREE_HALFS - (x2 * y *y)); // 2nd iteration, this can be removed
|
||||
return y;
|
||||
}
|
||||
|
||||
// transmute only works if the size of the types are equal
|
||||
/{
|
||||
// in C
|
||||
union {
|
||||
i32 i;
|
||||
f32 y;
|
||||
};
|
||||
}/
|
||||
}
|
||||
|
||||
{ // Compound Literals
|
||||
a := [3]int{1, 2, 3};
|
||||
b := [3]int{};
|
||||
c := [..]int{1, 2, 3};
|
||||
|
||||
d := []int{1, 2, 3}; // slice
|
||||
|
||||
e := {4}f32{1, 2, 3, 4};
|
||||
f := {4}f32{1}; // broadcasts to all
|
||||
// g := {4}f32{1, 2}; // require either 1 or 4 elements
|
||||
|
||||
type Vec2: {2}f32;
|
||||
|
||||
h := Vec2{1, 2};
|
||||
|
||||
i := Vec2{5} * h; // For strong type safety
|
||||
// FORENOTE: 5 * h was originally allowed but it was an edge case in the
|
||||
// compiler I didn't think it was enough to justify have it it.
|
||||
|
||||
print_f32(i[0]); print_rune(',');
|
||||
print_f32(i[1]); print_rune('\n');
|
||||
}
|
||||
|
||||
{
|
||||
do_thing :: proc(p: proc(a, b: int) -> int) {
|
||||
print_int(p(3, 4)); nl();
|
||||
}
|
||||
|
||||
add :: proc(a, b: int) -> int {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
|
||||
add_lambda := proc(a, b: int) -> int {
|
||||
return a - b;
|
||||
}; // note semicolon
|
||||
|
||||
do_thing(add);
|
||||
do_thing(add_lambda);
|
||||
do_thing(proc(a, b: int) -> int {
|
||||
return a * b;
|
||||
});
|
||||
}
|
||||
|
||||
{ // strings and runes
|
||||
escaped := "Hellope World\n";
|
||||
raw := `Hellope World\n`;
|
||||
print_string(escaped);
|
||||
print_string(raw); nl();
|
||||
|
||||
// Crap shader example
|
||||
shader_string :=
|
||||
`#version 410
|
||||
|
||||
layout (location = 0) in vec3 a_position;
|
||||
layout (location = 1) in vec3 a_normal;
|
||||
layout (location = 2) in vec2 a_tex_coord;
|
||||
|
||||
out vec3 v_position;
|
||||
out vec3 v_normal;
|
||||
out vec2 v_tex_coord;
|
||||
|
||||
uniform mat4 u_model_view;
|
||||
uniform mat3 u_normal;
|
||||
uniform mat4 u_proj;
|
||||
uniform mat4 u_mvp;
|
||||
|
||||
void main() {
|
||||
v_tex_coord = a_tex_coord;
|
||||
v_normal = normalize(u_normal * a_normal);
|
||||
v_position = vec3(u_model_view * vec4(a_position, 1.0));
|
||||
|
||||
gl_Position = u_mvp * vec4(a_position, 1.0);
|
||||
}`;
|
||||
|
||||
|
||||
knot1 := '⌘';
|
||||
knot2 := '\u2318'; // 16 bit
|
||||
knot3 := '\U00002318'; // 32 bit
|
||||
knot4 := "\xe2\x8c\x98"; // Note it's a string, should I allow untyped string -> untyped rune casts?
|
||||
|
||||
// String ideas "nicked" from Go, so far. I think I might change how some of it works later.
|
||||
}
|
||||
|
||||
|
||||
{ // size, align, offset
|
||||
type Thing: struct {
|
||||
a: u8,
|
||||
b: u16,
|
||||
c, d, e: u32,
|
||||
}
|
||||
|
||||
s := size_of(Thing);
|
||||
a := align_of(Thing);
|
||||
o := offset_of(Thing, b);
|
||||
|
||||
t: Thing;
|
||||
|
||||
sv := size_of_val(t);
|
||||
av := align_of_val(t);
|
||||
ov := offset_of_val(t.b);
|
||||
}
|
||||
}
|
||||
|
||||
data_control :: proc() {
|
||||
sum := 0;
|
||||
for i := 0; i < 12; i++ {
|
||||
sum += 1;
|
||||
}
|
||||
print_string("sum = "); print_int(sum); nl();
|
||||
|
||||
sum = 1;
|
||||
for ; sum < 1000000; {
|
||||
sum += sum;
|
||||
}
|
||||
print_string("sum = "); print_int(sum); nl();
|
||||
|
||||
sum = 1;
|
||||
for sum < 1000000 {
|
||||
sum += sum;
|
||||
}
|
||||
print_string("sum = "); print_int(sum); nl();
|
||||
|
||||
// loop
|
||||
// for { } == for true {}
|
||||
|
||||
// Question: Should I separate all these concepts and rename it?
|
||||
//
|
||||
// range - iterable
|
||||
// for - c style
|
||||
// while
|
||||
// loop - while true
|
||||
|
||||
// Notes:
|
||||
// conditions _must_ a boolean expression
|
||||
// i++ and i-- are statements, not expressions
|
||||
|
||||
|
||||
x := 2;
|
||||
if x < 3 {
|
||||
print_string("x < 2\n");
|
||||
}
|
||||
|
||||
// Unified initializer syntax - same as for statements
|
||||
if x := 2; x < 3 {
|
||||
print_string("x < 2\n");
|
||||
}
|
||||
|
||||
if x := 4; x < 3 {
|
||||
print_string("Never called\n");
|
||||
} else {
|
||||
print_string("This is called\n");
|
||||
}
|
||||
|
||||
{ // String comparison
|
||||
a := "Hellope";
|
||||
b := "World";
|
||||
if a < b {
|
||||
print_string("a < b\n");
|
||||
}
|
||||
if a != b {
|
||||
print_string("a != b\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
defer print_string("日本語\n");
|
||||
print_string("Japanese\n");
|
||||
}
|
||||
|
||||
{
|
||||
defer print_string("1\n");
|
||||
defer print_string("2\n");
|
||||
defer print_string("3\n");
|
||||
}
|
||||
|
||||
{
|
||||
// C strings, yuk!
|
||||
to_c_string :: proc(s: string) -> ^u8 {
|
||||
c := heap_alloc(len(s)+1) as ^u8;
|
||||
mem_copy(c, ^s[0], len(s));
|
||||
c[len(s)] = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
fopen :: proc(filename, mode: ^u8) -> rawptr #foreign
|
||||
fclose :: proc(f: rawptr) -> i32 #foreign
|
||||
|
||||
filename := to_c_string("../examples/base.odin");
|
||||
mode := to_c_string("rb");
|
||||
defer heap_free(filename);
|
||||
defer heap_free(mode);
|
||||
|
||||
f := fopen(filename, mode);
|
||||
if f == null {
|
||||
// handle error
|
||||
}
|
||||
defer if f != null {
|
||||
_ = fclose(f);
|
||||
}
|
||||
|
||||
// rest of code
|
||||
|
||||
// Better version
|
||||
/{
|
||||
type File: struct { filename: string }
|
||||
type FileError: int
|
||||
open_file :: proc(filename: string) -> (File, FileError) { ... }
|
||||
close_file :: proc(f: ^File) { ... }
|
||||
f, err := open_file("Test");
|
||||
if err != 0 {
|
||||
// handle error
|
||||
}
|
||||
defer close_file(^f);
|
||||
|
||||
}/
|
||||
|
||||
|
||||
}
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
blah := heap_alloc(100 * size_of(int)) as ^int;
|
||||
defer {
|
||||
defer print_string("!");
|
||||
defer print_string("heap_free");
|
||||
heap_free(blah);
|
||||
}
|
||||
|
||||
if i == 3 {
|
||||
// defers called
|
||||
continue;
|
||||
}
|
||||
|
||||
if i == 5 {
|
||||
// defers called
|
||||
return;
|
||||
}
|
||||
|
||||
if i == 8 {
|
||||
// defers called
|
||||
break; // never happens
|
||||
}
|
||||
}
|
||||
|
||||
defer print_string("It'll never happen, mate 1");
|
||||
print_string("It'll never happen, mate 2");
|
||||
print_string("It'll never happen, mate 3");
|
||||
}
|
||||
|
||||
@@ -125,8 +125,7 @@ display_window :: proc(w: ^Window) {
|
||||
|
||||
|
||||
|
||||
|
||||
main :: proc() {
|
||||
run_game :: proc() {
|
||||
win32_proc :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #no_inline {
|
||||
if msg == WM_DESTROY || msg == WM_CLOSE || msg == WM_QUIT {
|
||||
ExitProcess(0);
|
||||
@@ -134,9 +133,7 @@ main :: proc() {
|
||||
}
|
||||
return DefWindowProcA(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
print_f64(13.37);
|
||||
print_rune('\n');
|
||||
/*
|
||||
|
||||
window, window_success := make_window("Odin Language Demo", 854, 480, win32_proc);
|
||||
if !window_success {
|
||||
return;
|
||||
@@ -189,5 +186,4 @@ main :: proc() {
|
||||
sleep_ms(ms_to_sleep);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -196,10 +196,13 @@ void ssa_print_type(gbFile *f, BaseTypeSizes s, Type *t) {
|
||||
}
|
||||
|
||||
void ssa_print_exact_value(gbFile *f, ssaModule *m, ExactValue value, Type *type) {
|
||||
type = get_base_type(type);
|
||||
if (is_type_float(type)) {
|
||||
value = exact_value_to_float(value);
|
||||
} else if (is_type_integer(type)) {
|
||||
value = exact_value_to_integer(value);
|
||||
} else if (is_type_pointer(type)) {
|
||||
value = exact_value_to_integer(value);
|
||||
}
|
||||
|
||||
switch (value.kind) {
|
||||
@@ -212,7 +215,7 @@ void ssa_print_exact_value(gbFile *f, ssaModule *m, ExactValue value, Type *type
|
||||
ssa_fprintf(f, "\"");
|
||||
} break;
|
||||
case ExactValue_Integer: {
|
||||
if (is_type_pointer(get_base_type(type))) {
|
||||
if (is_type_pointer(type)) {
|
||||
if (value.value_integer == 0) {
|
||||
ssa_fprintf(f, "null");
|
||||
} else {
|
||||
@@ -235,14 +238,14 @@ void ssa_print_exact_value(gbFile *f, ssaModule *m, ExactValue value, Type *type
|
||||
ssa_fprintf(f, "0x%016llx", u);
|
||||
} break;
|
||||
case ExactValue_Pointer:
|
||||
if (value.value_float == NULL) {
|
||||
if (value.value_pointer == NULL) {
|
||||
ssa_fprintf(f, "null");
|
||||
} else {
|
||||
GB_PANIC("TODO(bill): ExactValue_Pointer");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GB_PANIC("Invalid ExactValue");
|
||||
GB_PANIC("Invalid ExactValue: %d", value.kind);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -908,7 +908,9 @@ ssaValue *ssa_lvalue_store(ssaProcedure *proc, ssaLvalue lval, ssaValue *value)
|
||||
if (lval.is_vector) {
|
||||
// HACK(bill): Fix how lvalues for vectors work
|
||||
ssaValue *v = ssa_emit_load(proc, lval.address);
|
||||
ssaValue *out = ssa_emit(proc, ssa_make_instr_insert_element(proc, v, value, lval.index));
|
||||
Type *elem_type = get_base_type(ssa_value_type(v))->vector.elem;
|
||||
ssaValue *elem = ssa_emit_conv(proc, value, elem_type);
|
||||
ssaValue *out = ssa_emit(proc, ssa_make_instr_insert_element(proc, v, elem, lval.index));
|
||||
return ssa_emit_store(proc, lval.address, out);
|
||||
}
|
||||
return ssa_emit_store(proc, lval.address, value);
|
||||
@@ -1401,22 +1403,22 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
|
||||
return ssa_emit_load(proc, slice);
|
||||
}
|
||||
|
||||
if (is_type_vector(dst)) {
|
||||
Type *dst_elem = dst->vector.elem;
|
||||
value = ssa_emit_conv(proc, value, dst_elem);
|
||||
ssaValue *v = ssa_add_local_generated(proc, t);
|
||||
v = ssa_emit_load(proc, v);
|
||||
v = ssa_emit(proc, ssa_make_instr_insert_element(proc, v, value, v_zero32));
|
||||
// NOTE(bill): Broadcast lowest value to all values
|
||||
isize index_count = dst->vector.count;
|
||||
i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count);
|
||||
for (isize i = 0; i < index_count; i++) {
|
||||
indices[i] = 0;
|
||||
}
|
||||
// if (is_type_vector(dst)) {
|
||||
// Type *dst_elem = dst->vector.elem;
|
||||
// value = ssa_emit_conv(proc, value, dst_elem);
|
||||
// ssaValue *v = ssa_add_local_generated(proc, t);
|
||||
// v = ssa_emit_load(proc, v);
|
||||
// v = ssa_emit(proc, ssa_make_instr_insert_element(proc, v, value, v_zero32));
|
||||
// // NOTE(bill): Broadcast lowest value to all values
|
||||
// isize index_count = dst->vector.count;
|
||||
// i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count);
|
||||
// for (isize i = 0; i < index_count; i++) {
|
||||
// indices[i] = 0;
|
||||
// }
|
||||
|
||||
v = ssa_emit(proc, ssa_make_instr_shuffle_vector(proc, v, indices, index_count));
|
||||
return v;
|
||||
}
|
||||
// v = ssa_emit(proc, ssa_make_instr_shuffle_vector(proc, v, indices, index_count));
|
||||
// return v;
|
||||
// }
|
||||
|
||||
|
||||
gb_printf_err("Not Identical %s != %s\n", type_to_string(src_type), type_to_string(t));
|
||||
@@ -1606,10 +1608,10 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
for (AstNode *elem = cl->elem_list;
|
||||
elem != NULL;
|
||||
elem = elem->next, index++) {
|
||||
ssaValue *field_expr = ssa_build_expr(proc, elem);
|
||||
Type *t = ssa_value_type(field_expr);
|
||||
ssaValue *field_elem = ssa_build_expr(proc, elem);
|
||||
Type *t = ssa_value_type(field_elem);
|
||||
GB_ASSERT(t->kind != Type_Tuple);
|
||||
ssaValue *ev = ssa_emit_conv(proc, field_expr, et);
|
||||
ssaValue *ev = ssa_emit_conv(proc, field_elem, et);
|
||||
ssaValue *i = ssa_make_value_constant(proc->module->allocator, t_int, make_exact_value_integer(index));
|
||||
result = ssa_emit(proc, ssa_make_instr_insert_element(proc, result, ev, i));
|
||||
}
|
||||
@@ -1619,7 +1621,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
for (isize i = 0; i < index_count; i++) {
|
||||
indices[i] = 0;
|
||||
}
|
||||
return ssa_emit(proc, ssa_make_instr_shuffle_vector(proc, result, indices, index_count));
|
||||
ssaValue *sv = ssa_emit(proc, ssa_make_instr_shuffle_vector(proc, result, indices, index_count));
|
||||
ssa_emit_store(proc, v, sv);
|
||||
return ssa_emit_load(proc, v);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -1761,15 +1765,20 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
AstNode *sptr_node = ce->arg_list;
|
||||
AstNode *item_node = ce->arg_list->next;
|
||||
ssaValue *slice = ssa_build_addr(proc, sptr_node).address;
|
||||
ssaValue *item_value = ssa_build_expr(proc, item_node);
|
||||
Type *item_type = ssa_value_type(item_value);
|
||||
ssaValue *item = ssa_add_local_generated(proc, item_type);
|
||||
ssa_emit_store(proc, item, item_value);
|
||||
|
||||
ssaValue *elem = ssa_slice_elem(proc, slice);
|
||||
ssaValue *len = ssa_slice_len(proc, slice);
|
||||
ssaValue *cap = ssa_slice_cap(proc, slice);
|
||||
|
||||
Type *elem_type = type_deref(get_base_type(ssa_value_type(elem)));
|
||||
|
||||
ssaValue *item_value = ssa_build_expr(proc, item_node);
|
||||
item_value = ssa_emit_conv(proc, item_value, elem_type);
|
||||
|
||||
ssaValue *item = ssa_add_local_generated(proc, elem_type);
|
||||
ssa_emit_store(proc, item, item_value);
|
||||
|
||||
|
||||
// NOTE(bill): Check if can append is possible
|
||||
Token lt = {Token_Lt};
|
||||
ssaValue *cond = ssa_emit_comp(proc, lt, len, cap);
|
||||
@@ -1781,9 +1790,13 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
|
||||
// Add new slice item
|
||||
ssaValue *offset = ssa_emit_ptr_offset(proc, elem, len);
|
||||
i64 item_size = type_size_of(proc->module->sizes, proc->module->allocator, item_type);
|
||||
i64 item_size = type_size_of(proc->module->sizes, proc->module->allocator, elem_type);
|
||||
ssaValue *byte_count = ssa_make_value_constant(proc->module->allocator, t_int,
|
||||
make_exact_value_integer(item_size));
|
||||
offset = ssa_emit_conv(proc, offset, t_rawptr);
|
||||
item = ssa_emit_ptr_offset(proc, item, v_zero);
|
||||
ssa_value_set_type(item, make_type_pointer(proc->module->allocator, ssa_value_type(item)));
|
||||
item = ssa_emit_conv(proc, item, t_rawptr);
|
||||
ssa_emit(proc, ssa_make_instr_copy_memory(proc, offset, item, byte_count, 1, false));
|
||||
|
||||
// Increment slice length
|
||||
@@ -1847,6 +1860,11 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
}
|
||||
}
|
||||
|
||||
auto *pt = &proc_type_->proc.params->tuple;
|
||||
for (isize i = 0; i < arg_count; i++) {
|
||||
args[i] = ssa_emit_conv(proc, args[i], pt->variables[i]->type);
|
||||
}
|
||||
|
||||
ssaValue *call = ssa_make_instr_call(proc, value, args, arg_count, type->results);
|
||||
return ssa_emit(proc, call);
|
||||
case_end;
|
||||
|
||||
@@ -108,6 +108,8 @@ ExactValue exact_value_to_integer(ExactValue v) {
|
||||
return v;
|
||||
case ExactValue_Float:
|
||||
return make_exact_value_integer(cast(i64)v.value_float);
|
||||
case ExactValue_Pointer:
|
||||
return make_exact_value_integer(cast(i64)cast(intptr)v.value_pointer);
|
||||
}
|
||||
ExactValue r = {ExactValue_Invalid};
|
||||
return r;
|
||||
|
||||
@@ -371,18 +371,18 @@ void tokenizer_skip_whitespace(Tokenizer *t) {
|
||||
if (t->read_curr[0] == '/') { // Line comment //
|
||||
while (t->curr_rune != '\n')
|
||||
advance_to_next_rune(t);
|
||||
} else if (t->read_curr[0] == '*') { // (Nested) Block comment /**/
|
||||
} else if (t->read_curr[0] == '{') { // (Nested) Block comment /{}/
|
||||
isize comment_scope = 1;
|
||||
for (;;) {
|
||||
advance_to_next_rune(t);
|
||||
if (t->curr_rune == '/') {
|
||||
advance_to_next_rune(t);
|
||||
if (t->curr_rune == '*') {
|
||||
if (t->curr_rune == '{') {
|
||||
advance_to_next_rune(t);
|
||||
comment_scope++;
|
||||
}
|
||||
}
|
||||
if (t->curr_rune == '*') {
|
||||
if (t->curr_rune == '}') {
|
||||
advance_to_next_rune(t);
|
||||
if (t->curr_rune == '/') {
|
||||
advance_to_next_rune(t);
|
||||
|
||||
Reference in New Issue
Block a user