mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-14 23:33:15 +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.
|
||||
|
||||
## Requirements
|
||||
|
||||
* x86-64
|
||||
* Windows
|
||||
* MSVC installed
|
||||
* call `vcvarsall.bat` to setup the path
|
||||
|
||||
## Warnings
|
||||
|
||||
* This is still highly in development and the language's design is quite volatile.
|
||||
|
||||
308
code/demo.odin
308
code/demo.odin
@@ -2,33 +2,293 @@
|
||||
#import "os.odin"
|
||||
|
||||
|
||||
|
||||
main :: proc() {
|
||||
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}
|
||||
v := Vector3{x = 1, y = 4, z = 9}
|
||||
fmt.println(v)
|
||||
// struct_padding()
|
||||
// bounds_checking()
|
||||
// type_introspection()
|
||||
// any_type()
|
||||
crazy_introspection()
|
||||
// namespaces_and_files()
|
||||
// miscellany()
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -206,7 +206,7 @@ run :: proc() {
|
||||
display_window(^window)
|
||||
ms_to_sleep := (16 - 1000*dt) as i32
|
||||
if ms_to_sleep > 0 {
|
||||
sleep_ms(ms_to_sleep)
|
||||
win32.Sleep(ms_to_sleep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ remainder :: proc(x, y: f32) -> f32 {
|
||||
fmod :: proc(x, y: f32) -> f32 {
|
||||
y = abs(y)
|
||||
result := remainder(abs(x), y)
|
||||
if fsign(result) < 0 {
|
||||
if sign32(result) < 0 {
|
||||
result += y
|
||||
}
|
||||
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)) }
|
||||
vec3_mag :: proc(v: Vec3) -> f32 { return fsqrt(dot3(v, v)) }
|
||||
vec4_mag :: proc(v: Vec4) -> f32 { return fsqrt(dot4(v, v)) }
|
||||
vec2_mag :: proc(v: Vec2) -> f32 { return sqrt32(dot2(v, v)) }
|
||||
vec3_mag :: proc(v: Vec3) -> f32 { return sqrt32(dot3(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)} }
|
||||
vec3_norm :: proc(v: Vec3) -> Vec3 { return v / Vec3{vec3_mag(v)} }
|
||||
|
||||
@@ -1,5 +1,38 @@
|
||||
#import "fmt.odin"
|
||||
|
||||
thing :: proc() #link_name "frankerooney" {
|
||||
thing :: proc() {
|
||||
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!")
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -22,7 +22,7 @@ INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE
|
||||
CS_VREDRAW :: 0x0001
|
||||
CS_HREDRAW :: 0x0002
|
||||
CS_OWNDC :: 0x0020
|
||||
CW_USEDEFAULT :: 0x80000000
|
||||
CW_USEDEFAULT :: -0x80000000
|
||||
|
||||
WS_OVERLAPPED :: 0
|
||||
WS_MAXIMIZEBOX :: 0x00010000
|
||||
|
||||
@@ -418,7 +418,7 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
|
||||
|
||||
void check_scope_usage(Checker *c, Scope *scope) {
|
||||
// TODO(bill): Use this?
|
||||
#if 1
|
||||
#if 0
|
||||
gb_for_array(i, scope->elements.entries) {
|
||||
auto *entry = scope->elements.entries + i;
|
||||
Entity *e = entry->value;
|
||||
|
||||
@@ -599,12 +599,8 @@ b32 are_types_identical(Type *x, Type *y) {
|
||||
break;
|
||||
|
||||
case TypeRecord_Enum:
|
||||
if (are_types_identical(x->Record.enum_base, y->Record.enum_base)) {
|
||||
if (x->Record.field_count == y->Record.field_count) {
|
||||
return x->Record.fields == y->Record.fields;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
// NOTE(bill): Each enum is unique
|
||||
return x == y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1348,9 +1348,8 @@ isize ssa_type_info_index(CheckerInfo *info, Type *type) {
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ i32 win32_exec_command_line_app(char *fmt, ...) {
|
||||
va_end(va);
|
||||
|
||||
if (CreateProcessA(NULL, cmd_line,
|
||||
NULL, NULL, true, 0, NULL, NULL,
|
||||
NULL, NULL, true, 0, NULL, NULL,
|
||||
&start_info, &pi)) {
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
|
||||
|
||||
@@ -1499,7 +1499,14 @@ AstNode *parse_atom_expr(AstFile *f, b32 lhs) {
|
||||
|
||||
case Token_OpenBrace: {
|
||||
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 {
|
||||
loop = false;
|
||||
}
|
||||
@@ -1553,13 +1560,24 @@ AstNode *parse_binary_expr(AstFile *f, b32 lhs, i32 prec_in) {
|
||||
|
||||
switch (op.kind) {
|
||||
case Token_DoublePrime: {
|
||||
// TODO(bill): Properly define semantic for in-fix and post-fix calls
|
||||
AstNode *proc = parse_identifier(f);
|
||||
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);
|
||||
/* if (f->cursor[0].kind == Token_OpenParen) {
|
||||
AstNode *call = parse_call_expr(f, proc);
|
||||
gb_array_append(call->CallExpr.args, expression);
|
||||
for (isize i = gb_array_count(call->CallExpr.args)-1; i > 0; i--) {
|
||||
gb_swap(AstNode *, call->CallExpr.args[i], call->CallExpr.args[i-1]);
|
||||
}
|
||||
|
||||
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;
|
||||
} break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user