mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Fix enum type comparison; Start demo 003 code
This commit is contained in:
@@ -2,6 +2,13 @@
|
|||||||
|
|
||||||
Odin in an open source programming language that is simple to read, comprehend and reason with.
|
Odin in an open source programming language that is simple to read, comprehend and reason with.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
* x86-64
|
||||||
|
* Windows
|
||||||
|
* MSVC installed
|
||||||
|
* call `vcvarsall.bat` to setup the path
|
||||||
|
|
||||||
## Warnings
|
## Warnings
|
||||||
|
|
||||||
* This is still highly in development and the language's design is quite volatile.
|
* This is still highly in development and the language's design is quite volatile.
|
||||||
|
|||||||
+284
-24
@@ -2,33 +2,293 @@
|
|||||||
#import "os.odin"
|
#import "os.odin"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
Fruit :: enum {
|
// struct_padding()
|
||||||
APPLE,
|
// bounds_checking()
|
||||||
BANANA,
|
// type_introspection()
|
||||||
GRAPE,
|
// any_type()
|
||||||
MELON,
|
crazy_introspection()
|
||||||
PEACH,
|
// namespaces_and_files()
|
||||||
TOMATO,
|
// miscellany()
|
||||||
}
|
|
||||||
|
|
||||||
fruit_ti := type_info(Fruit)
|
|
||||||
name := (fruit_ti as ^Type_Info.Named).name // Unsafe casts
|
|
||||||
info := type_info_base(fruit_ti) as ^Type_Info.Enum // Unsafe casts
|
|
||||||
|
|
||||||
fmt.printf("% :: enum ", name);
|
|
||||||
fmt.fprint_type(os.stdout, info.base)
|
|
||||||
fmt.printf(" {\n")
|
|
||||||
for i := 0; i < info.values.count; i++ {
|
|
||||||
fmt.printf("\t%\t= %,\n", info.names[i], info.values[i])
|
|
||||||
}
|
|
||||||
fmt.printf("}\n")
|
|
||||||
|
|
||||||
Vector3 :: struct {x, y, z: f32}
|
|
||||||
v := Vector3{x = 1, y = 4, z = 9}
|
|
||||||
fmt.println(v)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct_padding :: proc() {
|
||||||
|
{
|
||||||
|
A :: struct {
|
||||||
|
a: u8
|
||||||
|
b: u32
|
||||||
|
c: u16
|
||||||
|
}
|
||||||
|
|
||||||
|
B :: struct {
|
||||||
|
a: [7]u8
|
||||||
|
b: [3]u16
|
||||||
|
c: u8
|
||||||
|
d: u16
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.println("size_of(A):", size_of(A))
|
||||||
|
fmt.println("size_of(B):", size_of(B))
|
||||||
|
|
||||||
|
// n.b. http://cbloomrants.blogspot.co.uk/2012/07/07-23-12-structs-are-not-what-you-want.html
|
||||||
|
}
|
||||||
|
{
|
||||||
|
A :: struct #ordered {
|
||||||
|
a: u8
|
||||||
|
b: u32
|
||||||
|
c: u16
|
||||||
|
}
|
||||||
|
|
||||||
|
B :: struct #ordered {
|
||||||
|
a: [7]u8
|
||||||
|
b: [3]u16
|
||||||
|
c: u8
|
||||||
|
d: u16
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.println("size_of(A):", size_of(A))
|
||||||
|
fmt.println("size_of(B):", size_of(B))
|
||||||
|
|
||||||
|
// C-style structure layout
|
||||||
|
}
|
||||||
|
{
|
||||||
|
A :: struct #packed {
|
||||||
|
a: u8
|
||||||
|
b: u32
|
||||||
|
c: u16
|
||||||
|
}
|
||||||
|
|
||||||
|
B :: struct #packed {
|
||||||
|
a: [7]u8
|
||||||
|
b: [3]u16
|
||||||
|
c: u8
|
||||||
|
d: u16
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.println("size_of(A):", size_of(A))
|
||||||
|
fmt.println("size_of(B):", size_of(B))
|
||||||
|
|
||||||
|
// Useful for explicit layout
|
||||||
|
}
|
||||||
|
|
||||||
|
// Member sorting by priority
|
||||||
|
// Alignment desc.
|
||||||
|
// Size desc.
|
||||||
|
// source order asc.
|
||||||
|
|
||||||
|
/*
|
||||||
|
A :: struct {
|
||||||
|
a: u8
|
||||||
|
b: u32
|
||||||
|
c: u16
|
||||||
|
}
|
||||||
|
|
||||||
|
B :: struct {
|
||||||
|
a: [7]u8
|
||||||
|
b: [3]u16
|
||||||
|
c: u8
|
||||||
|
d: u16
|
||||||
|
}
|
||||||
|
|
||||||
|
Equivalent too
|
||||||
|
|
||||||
|
A :: struct #ordered {
|
||||||
|
b: u32
|
||||||
|
c: u16
|
||||||
|
a: u8
|
||||||
|
}
|
||||||
|
|
||||||
|
B :: struct #ordered {
|
||||||
|
b: [3]u16
|
||||||
|
d: u16
|
||||||
|
a: [7]u8
|
||||||
|
c: u8
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
bounds_checking :: proc() {
|
||||||
|
x: [4]int
|
||||||
|
// x[-1] = 0; // Compile Time
|
||||||
|
// x[4] = 0; // Compile Time
|
||||||
|
|
||||||
|
/*{
|
||||||
|
a, b := -1, 4;
|
||||||
|
x[a] = 0; // Runtime Time
|
||||||
|
x[b] = 0; // Runtime Time
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// Works for arrays, strings, slices, and related procedures & operations
|
||||||
|
|
||||||
|
{
|
||||||
|
base: [10]int
|
||||||
|
s := base[2:6]
|
||||||
|
a, b := -1, 6
|
||||||
|
|
||||||
|
#no_bounds_check {
|
||||||
|
s[a] = 0;
|
||||||
|
// #bounds_check s[b] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#no_bounds_check
|
||||||
|
if s[a] == 0 {
|
||||||
|
// Do whatever
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bounds checking can be toggled explicit
|
||||||
|
// on a per statement basis.
|
||||||
|
// _any statement_
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type_introspection :: proc() {
|
||||||
|
|
||||||
|
info: ^Type_Info
|
||||||
|
x: int
|
||||||
|
|
||||||
|
info = type_info(int) // by type
|
||||||
|
info = type_info(x) // by value
|
||||||
|
// See: runtime.odin
|
||||||
|
|
||||||
|
match type i : info {
|
||||||
|
case Type_Info.Integer:
|
||||||
|
fmt.println("integer!")
|
||||||
|
case Type_Info.Float:
|
||||||
|
fmt.println("float!")
|
||||||
|
default:
|
||||||
|
fmt.println("potato!")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unsafe cast
|
||||||
|
integer_info := info as ^Type_Info.Integer
|
||||||
|
}
|
||||||
|
|
||||||
|
any_type :: proc() {
|
||||||
|
a: any
|
||||||
|
|
||||||
|
x := 123
|
||||||
|
y := 6.28
|
||||||
|
z := "Yo-Yo Ma"
|
||||||
|
// All types can be implicit cast to `any`
|
||||||
|
a = x
|
||||||
|
a = y
|
||||||
|
a = z
|
||||||
|
a = a
|
||||||
|
|
||||||
|
// any has two members
|
||||||
|
// data - rawptr to the data
|
||||||
|
// type_info - pointer to the type info
|
||||||
|
|
||||||
|
fmt.println(x, y, z)
|
||||||
|
// See: Implementation
|
||||||
|
}
|
||||||
|
|
||||||
|
crazy_introspection :: proc() {
|
||||||
|
{
|
||||||
|
Fruit :: enum {
|
||||||
|
APPLE,
|
||||||
|
BANANA,
|
||||||
|
GRAPE,
|
||||||
|
MELON,
|
||||||
|
PEACH,
|
||||||
|
TOMATO,
|
||||||
|
}
|
||||||
|
|
||||||
|
s: string
|
||||||
|
s = enum_to_string(Fruit.PEACH)
|
||||||
|
fmt.println(s)
|
||||||
|
|
||||||
|
f := Fruit.GRAPE
|
||||||
|
s = enum_to_string(f)
|
||||||
|
fmt.println(s)
|
||||||
|
|
||||||
|
fmt.println(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
// NOTE(bill): This is not safe code and I would not recommend this at all
|
||||||
|
// I'd recommend you use `match type` to get the subtype rather than
|
||||||
|
// casting pointers
|
||||||
|
|
||||||
|
Fruit :: enum {
|
||||||
|
APPLE,
|
||||||
|
BANANA,
|
||||||
|
GRAPE,
|
||||||
|
MELON,
|
||||||
|
PEACH,
|
||||||
|
TOMATO,
|
||||||
|
}
|
||||||
|
|
||||||
|
fruit_ti := type_info(Fruit)
|
||||||
|
name := (fruit_ti as ^Type_Info.Named).name // Unsafe casts
|
||||||
|
info := type_info_base(fruit_ti) as ^Type_Info.Enum // Unsafe casts
|
||||||
|
|
||||||
|
fmt.printf("% :: enum ", name);
|
||||||
|
fmt.fprint_type(os.stdout, info.base)
|
||||||
|
fmt.printf(" {\n")
|
||||||
|
for i := 0; i < info.values.count; i++ {
|
||||||
|
fmt.printf("\t%\t= %,\n", info.names[i], info.values[i])
|
||||||
|
}
|
||||||
|
fmt.printf("}\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Vector3 :: struct {x, y, z: f32}
|
||||||
|
|
||||||
|
a := Vector3{x = 1, y = 4, z = 9}
|
||||||
|
fmt.println(a)
|
||||||
|
b := Vector3{x = 9, y = 3, z = 1}
|
||||||
|
fmt.println(b)
|
||||||
|
|
||||||
|
// NOTE(bill): See fmt.odin
|
||||||
|
}
|
||||||
|
|
||||||
|
// n.b. This pretty much "solves" serialization (to strings)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespaces_and_files :: proc() {
|
||||||
|
/*
|
||||||
|
// Non-exporting import
|
||||||
|
#import "file.odin"
|
||||||
|
#import "file.odin" as file
|
||||||
|
#import "file.odin" as .
|
||||||
|
#import "file.odin" as _
|
||||||
|
|
||||||
|
// Exporting import
|
||||||
|
#load "file.odin"
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Talk about scope rules and diagram
|
||||||
|
}
|
||||||
|
|
||||||
|
miscellany :: proc() {
|
||||||
|
/*
|
||||||
|
win32 `__imp__` prefix
|
||||||
|
#dll_import
|
||||||
|
#dll_export
|
||||||
|
|
||||||
|
Change exported name/symbol for linking
|
||||||
|
#link_name
|
||||||
|
|
||||||
|
Custom calling conventions
|
||||||
|
#stdcall
|
||||||
|
#fastcall
|
||||||
|
|
||||||
|
Runtime stuff
|
||||||
|
#shared_global_scope
|
||||||
|
*/
|
||||||
|
|
||||||
|
// assert(false)
|
||||||
|
// compile_assert(false)
|
||||||
|
// panic("Panic message goes here")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// #import "fmt.odin" as fmt
|
// #import "fmt.odin" as fmt
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -206,7 +206,7 @@ run :: proc() {
|
|||||||
display_window(^window)
|
display_window(^window)
|
||||||
ms_to_sleep := (16 - 1000*dt) as i32
|
ms_to_sleep := (16 - 1000*dt) as i32
|
||||||
if ms_to_sleep > 0 {
|
if ms_to_sleep > 0 {
|
||||||
sleep_ms(ms_to_sleep)
|
win32.Sleep(ms_to_sleep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -96,7 +96,7 @@ remainder :: proc(x, y: f32) -> f32 {
|
|||||||
fmod :: proc(x, y: f32) -> f32 {
|
fmod :: proc(x, y: f32) -> f32 {
|
||||||
y = abs(y)
|
y = abs(y)
|
||||||
result := remainder(abs(x), y)
|
result := remainder(abs(x), y)
|
||||||
if fsign(result) < 0 {
|
if sign32(result) < 0 {
|
||||||
result += y
|
result += y
|
||||||
}
|
}
|
||||||
return copy_sign(result, x)
|
return copy_sign(result, x)
|
||||||
@@ -120,9 +120,9 @@ cross :: proc(x, y: Vec3) -> Vec3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
vec2_mag :: proc(v: Vec2) -> f32 { return fsqrt(dot2(v, v)) }
|
vec2_mag :: proc(v: Vec2) -> f32 { return sqrt32(dot2(v, v)) }
|
||||||
vec3_mag :: proc(v: Vec3) -> f32 { return fsqrt(dot3(v, v)) }
|
vec3_mag :: proc(v: Vec3) -> f32 { return sqrt32(dot3(v, v)) }
|
||||||
vec4_mag :: proc(v: Vec4) -> f32 { return fsqrt(dot4(v, v)) }
|
vec4_mag :: proc(v: Vec4) -> f32 { return sqrt32(dot4(v, v)) }
|
||||||
|
|
||||||
vec2_norm :: proc(v: Vec2) -> Vec2 { return v / Vec2{vec2_mag(v)} }
|
vec2_norm :: proc(v: Vec2) -> Vec2 { return v / Vec2{vec2_mag(v)} }
|
||||||
vec3_norm :: proc(v: Vec3) -> Vec3 { return v / Vec3{vec3_mag(v)} }
|
vec3_norm :: proc(v: Vec3) -> Vec3 { return v / Vec3{vec3_mag(v)} }
|
||||||
|
|||||||
+34
-1
@@ -1,5 +1,38 @@
|
|||||||
#import "fmt.odin"
|
#import "fmt.odin"
|
||||||
|
|
||||||
thing :: proc() #link_name "frankerooney" {
|
thing :: proc() {
|
||||||
fmt.println("Hello!")
|
fmt.println("Hello!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#import "fmt.odin" as fmt
|
||||||
|
|
||||||
|
thing :: proc() {
|
||||||
|
fmt.println("Hello!")
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
#import "fmt.odin" as .
|
||||||
|
|
||||||
|
thing :: proc() {
|
||||||
|
println("Hello!")
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
#import "fmt.odin" as _
|
||||||
|
|
||||||
|
thing :: proc() {
|
||||||
|
// println("Hello!")
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
#load "fmt.odin"
|
||||||
|
|
||||||
|
thing :: proc() {
|
||||||
|
println("Hello!")
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE
|
|||||||
CS_VREDRAW :: 0x0001
|
CS_VREDRAW :: 0x0001
|
||||||
CS_HREDRAW :: 0x0002
|
CS_HREDRAW :: 0x0002
|
||||||
CS_OWNDC :: 0x0020
|
CS_OWNDC :: 0x0020
|
||||||
CW_USEDEFAULT :: 0x80000000
|
CW_USEDEFAULT :: -0x80000000
|
||||||
|
|
||||||
WS_OVERLAPPED :: 0
|
WS_OVERLAPPED :: 0
|
||||||
WS_MAXIMIZEBOX :: 0x00010000
|
WS_MAXIMIZEBOX :: 0x00010000
|
||||||
|
|||||||
@@ -418,7 +418,7 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
|
|||||||
|
|
||||||
void check_scope_usage(Checker *c, Scope *scope) {
|
void check_scope_usage(Checker *c, Scope *scope) {
|
||||||
// TODO(bill): Use this?
|
// TODO(bill): Use this?
|
||||||
#if 1
|
#if 0
|
||||||
gb_for_array(i, scope->elements.entries) {
|
gb_for_array(i, scope->elements.entries) {
|
||||||
auto *entry = scope->elements.entries + i;
|
auto *entry = scope->elements.entries + i;
|
||||||
Entity *e = entry->value;
|
Entity *e = entry->value;
|
||||||
|
|||||||
@@ -599,12 +599,8 @@ b32 are_types_identical(Type *x, Type *y) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TypeRecord_Enum:
|
case TypeRecord_Enum:
|
||||||
if (are_types_identical(x->Record.enum_base, y->Record.enum_base)) {
|
// NOTE(bill): Each enum is unique
|
||||||
if (x->Record.field_count == y->Record.field_count) {
|
return x == y;
|
||||||
return x->Record.fields == y->Record.fields;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -1348,9 +1348,8 @@ isize ssa_type_info_index(CheckerInfo *info, Type *type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (entry_index < 0) {
|
if (entry_index < 0) {
|
||||||
gb_printf_err("%s\n", type_to_string(type));
|
compiler_error("Type_Info for `%s` could not be found", type_to_string(type));
|
||||||
}
|
}
|
||||||
GB_ASSERT(entry_index >= 0);
|
|
||||||
return entry_index;
|
return entry_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ i32 win32_exec_command_line_app(char *fmt, ...) {
|
|||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
||||||
if (CreateProcessA(NULL, cmd_line,
|
if (CreateProcessA(NULL, cmd_line,
|
||||||
NULL, NULL, true, 0, NULL, NULL,
|
NULL, NULL, true, 0, NULL, NULL,
|
||||||
&start_info, &pi)) {
|
&start_info, &pi)) {
|
||||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||||
|
|
||||||
|
|||||||
+25
-7
@@ -1499,7 +1499,14 @@ AstNode *parse_atom_expr(AstFile *f, b32 lhs) {
|
|||||||
|
|
||||||
case Token_OpenBrace: {
|
case Token_OpenBrace: {
|
||||||
if (!lhs && is_literal_type(operand) && f->expr_level >= 0) {
|
if (!lhs && is_literal_type(operand) && f->expr_level >= 0) {
|
||||||
operand = parse_literal_value(f, operand);
|
if (f->cursor[0].pos.line == f->cursor[-1].pos.line) {
|
||||||
|
// TODO(bill): This is a hack due to optional semicolons
|
||||||
|
// TODO(bill): It's probably much better to solve this by changing
|
||||||
|
// the syntax for struct literals and array literals
|
||||||
|
operand = parse_literal_value(f, operand);
|
||||||
|
} else {
|
||||||
|
loop = false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
loop = false;
|
loop = false;
|
||||||
}
|
}
|
||||||
@@ -1553,13 +1560,24 @@ AstNode *parse_binary_expr(AstFile *f, b32 lhs, i32 prec_in) {
|
|||||||
|
|
||||||
switch (op.kind) {
|
switch (op.kind) {
|
||||||
case Token_DoublePrime: {
|
case Token_DoublePrime: {
|
||||||
|
// TODO(bill): Properly define semantic for in-fix and post-fix calls
|
||||||
AstNode *proc = parse_identifier(f);
|
AstNode *proc = parse_identifier(f);
|
||||||
AstNode *right = parse_binary_expr(f, false, prec+1);
|
/* if (f->cursor[0].kind == Token_OpenParen) {
|
||||||
gbArray(AstNode *) args;
|
AstNode *call = parse_call_expr(f, proc);
|
||||||
gb_array_init_reserve(args, gb_arena_allocator(&f->arena), 2);
|
gb_array_append(call->CallExpr.args, expression);
|
||||||
gb_array_append(args, expression);
|
for (isize i = gb_array_count(call->CallExpr.args)-1; i > 0; i--) {
|
||||||
gb_array_append(args, right);
|
gb_swap(AstNode *, call->CallExpr.args[i], call->CallExpr.args[i-1]);
|
||||||
expression = make_call_expr(f, proc, args, op, ast_node_token(right), empty_token);
|
}
|
||||||
|
|
||||||
|
expression = call;
|
||||||
|
} else */{
|
||||||
|
AstNode *right = parse_binary_expr(f, false, prec+1);
|
||||||
|
gbArray(AstNode *) args;
|
||||||
|
gb_array_init_reserve(args, gb_arena_allocator(&f->arena), 2);
|
||||||
|
gb_array_append(args, expression);
|
||||||
|
gb_array_append(args, right);
|
||||||
|
expression = make_call_expr(f, proc, args, op, ast_node_token(right), empty_token);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user