Fix enum type comparison; Start demo 003 code

This commit is contained in:
Ginger Bill
2016-09-21 23:26:31 +01:00
parent 33bd3f635f
commit 664c2cd7a5
11 changed files with 361 additions and 48 deletions
+7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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;
+2 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;