mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Fix parsing for block/if expression within if/for/etc. statements
This commit is contained in:
@@ -46,7 +46,7 @@ cl %compiler_settings% "src\main.c" ^
|
|||||||
/link %linker_settings% -OUT:%exe_name% ^
|
/link %linker_settings% -OUT:%exe_name% ^
|
||||||
&& odin run code/demo.odin
|
&& odin run code/demo.odin
|
||||||
rem && odin build_dll code/example.odin ^
|
rem && odin build_dll code/example.odin ^
|
||||||
rem && odin run code/demo.odin
|
rem odin run code/punity.odin
|
||||||
|
|
||||||
rem pushd src\asm
|
rem pushd src\asm
|
||||||
rem nasm hellope.asm -fwin64 -o hellope.obj ^
|
rem nasm hellope.asm -fwin64 -o hellope.obj ^
|
||||||
|
|||||||
+16
-13
@@ -1,12 +1,13 @@
|
|||||||
#import "fmt.odin";
|
#import "fmt.odin";
|
||||||
#import "utf8.odin";
|
#import "utf8.odin";
|
||||||
#import "atomic.odin";
|
// #import "atomic.odin";
|
||||||
#import "hash.odin";
|
// #import "hash.odin";
|
||||||
#import "math.odin";
|
// #import "math.odin";
|
||||||
#import "mem.odin";
|
// #import "mem.odin";
|
||||||
#import "opengl.odin";
|
// #import "opengl.odin";
|
||||||
#import "os.odin";
|
// #import "os.odin";
|
||||||
#import "sync.odin";
|
// #import "sync.odin";
|
||||||
|
// #import win32 "sys/windows.odin";
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
syntax();
|
syntax();
|
||||||
@@ -15,8 +16,8 @@ main :: proc() {
|
|||||||
syntax :: proc() {
|
syntax :: proc() {
|
||||||
// Cyclic type checking
|
// Cyclic type checking
|
||||||
// Uncomment to see the error
|
// Uncomment to see the error
|
||||||
// A :: struct { b: B };
|
// A :: struct {b: B};
|
||||||
// B :: struct { a: A };
|
// B :: struct {a: A};
|
||||||
|
|
||||||
x: int;
|
x: int;
|
||||||
y := cast(f32)x;
|
y := cast(f32)x;
|
||||||
@@ -40,10 +41,10 @@ syntax :: proc() {
|
|||||||
};
|
};
|
||||||
Thing2 :: struct {x: f32, y: int, z: ^[]int};
|
Thing2 :: struct {x: f32, y: int, z: ^[]int};
|
||||||
|
|
||||||
// Slice interals are not just a `ptr+count`
|
// Slice interals are now just a `ptr+count`
|
||||||
slice: []int; compile_assert(size_of_val(slice) == 2*size_of(int));
|
slice: []int; compile_assert(size_of_val(slice) == 2*size_of(int));
|
||||||
|
|
||||||
// Helper type - Help the reader understand that it is quicker
|
// Helper type - Help the reader understand what it is quicker
|
||||||
My_Int :: type int;
|
My_Int :: type int;
|
||||||
My_Proc :: type proc(int) -> f32;
|
My_Proc :: type proc(int) -> f32;
|
||||||
|
|
||||||
@@ -62,6 +63,9 @@ syntax :: proc() {
|
|||||||
// ++ and -- have been removed
|
// ++ and -- have been removed
|
||||||
// x++;
|
// x++;
|
||||||
// x--;
|
// x--;
|
||||||
|
// Question: Should they be added again?
|
||||||
|
// They were removed as they are redundant and statements, not expressions
|
||||||
|
// like in C/C++
|
||||||
|
|
||||||
|
|
||||||
// You can now build files as a `.dll`
|
// You can now build files as a `.dll`
|
||||||
@@ -167,7 +171,6 @@ special_expressions :: proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loops :: proc() {
|
loops :: proc() {
|
||||||
|
|
||||||
// The C-style for loop
|
// The C-style for loop
|
||||||
for i := 0; i < 123; i += 1 {
|
for i := 0; i < 123; i += 1 {
|
||||||
break;
|
break;
|
||||||
@@ -259,7 +262,7 @@ procedure_overloading :: proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
a: i32 = #line;
|
a: i32 = 123;
|
||||||
b: f32;
|
b: f32;
|
||||||
c: rawptr;
|
c: rawptr;
|
||||||
fmt.println(foo(^a));
|
fmt.println(foo(^a));
|
||||||
|
|||||||
+86
-86
@@ -1,9 +1,9 @@
|
|||||||
#import "fmt.odin"
|
#import "fmt.odin";
|
||||||
#import "os.odin"
|
#import "os.odin";
|
||||||
#import "mem.odin"
|
#import "mem.odin";
|
||||||
// #import "http_test.odin" as ht
|
// #import "http_test.odin" as ht;
|
||||||
// #import "game.odin" as game
|
// #import "game.odin" as game;
|
||||||
// #import "punity.odin" as pn
|
// #import "punity.odin" as pn;
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
// struct_padding()
|
// struct_padding()
|
||||||
@@ -26,58 +26,58 @@ main :: proc() {
|
|||||||
struct_padding :: proc() {
|
struct_padding :: proc() {
|
||||||
{
|
{
|
||||||
A :: struct {
|
A :: struct {
|
||||||
a: u8
|
a: u8,
|
||||||
b: u32
|
b: u32,
|
||||||
c: u16
|
c: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
B :: struct {
|
B :: struct {
|
||||||
a: [7]u8
|
a: [7]u8,
|
||||||
b: [3]u16
|
b: [3]u16,
|
||||||
c: u8
|
c: u8,
|
||||||
d: u16
|
d: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.println("size_of(A):", size_of(A))
|
fmt.println("size_of(A):", size_of(A));
|
||||||
fmt.println("size_of(B):", size_of(B))
|
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
|
// n.b. http://cbloomrants.blogspot.co.uk/2012/07/07-23-12-structs-are-not-what-you-want.html
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
A :: struct #ordered {
|
A :: struct #ordered {
|
||||||
a: u8
|
a: u8,
|
||||||
b: u32
|
b: u32,
|
||||||
c: u16
|
c: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
B :: struct #ordered {
|
B :: struct #ordered {
|
||||||
a: [7]u8
|
a: [7]u8,
|
||||||
b: [3]u16
|
b: [3]u16,
|
||||||
c: u8
|
c: u8,
|
||||||
d: u16
|
d: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.println("size_of(A):", size_of(A))
|
fmt.println("size_of(A):", size_of(A));
|
||||||
fmt.println("size_of(B):", size_of(B))
|
fmt.println("size_of(B):", size_of(B));
|
||||||
|
|
||||||
// C-style structure layout
|
// C-style structure layout
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
A :: struct #packed {
|
A :: struct #packed {
|
||||||
a: u8
|
a: u8,
|
||||||
b: u32
|
b: u32,
|
||||||
c: u16
|
c: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
B :: struct #packed {
|
B :: struct #packed {
|
||||||
a: [7]u8
|
a: [7]u8,
|
||||||
b: [3]u16
|
b: [3]u16,
|
||||||
c: u8
|
c: u8,
|
||||||
d: u16
|
d: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.println("size_of(A):", size_of(A))
|
fmt.println("size_of(A):", size_of(A));
|
||||||
fmt.println("size_of(B):", size_of(B))
|
fmt.println("size_of(B):", size_of(B));
|
||||||
|
|
||||||
// Useful for explicit layout
|
// Useful for explicit layout
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ struct_padding :: proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bounds_checking :: proc() {
|
bounds_checking :: proc() {
|
||||||
x: [4]int
|
x: [4]int;
|
||||||
// x[-1] = 0; // Compile Time
|
// x[-1] = 0; // Compile Time
|
||||||
// x[4] = 0; // Compile Time
|
// x[4] = 0; // Compile Time
|
||||||
|
|
||||||
@@ -132,9 +132,9 @@ bounds_checking :: proc() {
|
|||||||
// Works for arrays, strings, slices, and related procedures & operations
|
// Works for arrays, strings, slices, and related procedures & operations
|
||||||
|
|
||||||
{
|
{
|
||||||
base: [10]int
|
base: [10]int;
|
||||||
s := base[2:6]
|
s := base[2:6];
|
||||||
a, b := -1, 6
|
a, b := -1, 6;
|
||||||
|
|
||||||
#no_bounds_check {
|
#no_bounds_check {
|
||||||
s[a] = 0;
|
s[a] = 0;
|
||||||
@@ -154,69 +154,69 @@ bounds_checking :: proc() {
|
|||||||
|
|
||||||
type_introspection :: proc() {
|
type_introspection :: proc() {
|
||||||
{
|
{
|
||||||
info: ^Type_Info
|
info: ^Type_Info;
|
||||||
x: int
|
x: int;
|
||||||
|
|
||||||
info = type_info(int) // by type
|
info = type_info(int); // by type
|
||||||
info = type_info_of_val(x) // by value
|
info = type_info_of_val(x); // by value
|
||||||
// See: runtime.odin
|
// See: runtime.odin
|
||||||
|
|
||||||
match type i : info {
|
match type i in info {
|
||||||
case Type_Info.Integer:
|
case Type_Info.Integer:
|
||||||
fmt.println("integer!")
|
fmt.println("integer!");
|
||||||
case Type_Info.Float:
|
case Type_Info.Float:
|
||||||
fmt.println("float!")
|
fmt.println("float!");
|
||||||
default:
|
default:
|
||||||
fmt.println("potato!")
|
fmt.println("potato!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsafe cast
|
// Unsafe cast
|
||||||
integer_info := info as ^Type_Info.Integer
|
integer_info := cast(^Type_Info.Integer)info;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Vector2 :: struct { x, y: f32 }
|
Vector2 :: struct { x, y: f32 }
|
||||||
Vector3 :: struct { x, y, z: f32 }
|
Vector3 :: struct { x, y, z: f32 }
|
||||||
|
|
||||||
v1: Vector2
|
v1: Vector2;
|
||||||
v2: Vector3
|
v2: Vector3;
|
||||||
v3: Vector3
|
v3: Vector3;
|
||||||
|
|
||||||
t1 := type_info_of_val(v1)
|
t1 := type_info_of_val(v1);
|
||||||
t2 := type_info_of_val(v2)
|
t2 := type_info_of_val(v2);
|
||||||
t3 := type_info_of_val(v3)
|
t3 := type_info_of_val(v3);
|
||||||
|
|
||||||
fmt.println()
|
fmt.println();
|
||||||
fmt.print("Type of v1 is:\n\t", t1)
|
fmt.print("Type of v1 is:\n\t", t1);
|
||||||
|
|
||||||
fmt.println()
|
fmt.println();
|
||||||
fmt.print("Type of v2 is:\n\t", t2)
|
fmt.print("Type of v2 is:\n\t", t2);
|
||||||
|
|
||||||
fmt.println("\n")
|
fmt.println("\n");
|
||||||
fmt.println("t1 == t2:", t1 == t2)
|
fmt.println("t1 == t2:", t1 == t2);
|
||||||
fmt.println("t2 == t3:", t2 == t3)
|
fmt.println("t2 == t3:", t2 == t3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
any_type :: proc() {
|
any_type :: proc() {
|
||||||
a: any
|
a: any;
|
||||||
|
|
||||||
x: int = 123
|
x: int = 123;
|
||||||
y: f64 = 6.28
|
y: f64 = 6.28;
|
||||||
z: string = "Yo-Yo Ma"
|
z: string = "Yo-Yo Ma";
|
||||||
// All types can be implicit cast to `any`
|
// All types can be implicit cast to `any`
|
||||||
a = x
|
a = x;
|
||||||
a = y
|
a = y;
|
||||||
a = z
|
a = z;
|
||||||
a = a // This the "identity" type, it doesn't get converted
|
a = a; // This the "identity" type, it doesn't get converted
|
||||||
|
|
||||||
a = 123 // Literals are copied onto the stack first
|
a = 123; // Literals are copied onto the stack first
|
||||||
|
|
||||||
// any has two members
|
// any has two members
|
||||||
// data - rawptr to the data
|
// data - rawptr to the data
|
||||||
// type_info - pointer to the type info
|
// type_info - pointer to the type info
|
||||||
|
|
||||||
fmt.println(x, y, z)
|
fmt.println(x, y, z);
|
||||||
// See: fmt.odin
|
// See: fmt.odin
|
||||||
// For variadic any procedures in action
|
// For variadic any procedures in action
|
||||||
}
|
}
|
||||||
@@ -232,15 +232,15 @@ crazy_introspection :: proc() {
|
|||||||
TOMATO,
|
TOMATO,
|
||||||
}
|
}
|
||||||
|
|
||||||
s: string
|
s: string;
|
||||||
s = enum_to_string(Fruit.PEACH)
|
// s = enum_to_string(Fruit.PEACH);
|
||||||
fmt.println(s)
|
fmt.println(s);
|
||||||
|
|
||||||
f := Fruit.GRAPE
|
f := Fruit.GRAPE;
|
||||||
s = enum_to_string(f)
|
// s = enum_to_string(f);
|
||||||
fmt.println(s)
|
fmt.println(s);
|
||||||
|
|
||||||
fmt.println(f)
|
fmt.println(f);
|
||||||
// See: runtime.odin
|
// See: runtime.odin
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,15 +259,15 @@ crazy_introspection :: proc() {
|
|||||||
TOMATO,
|
TOMATO,
|
||||||
}
|
}
|
||||||
|
|
||||||
fruit_ti := type_info(Fruit)
|
fruit_ti := type_info(Fruit);
|
||||||
name := (fruit_ti as ^Type_Info.Named).name // Unsafe casts
|
name := (cast(^Type_Info.Named)fruit_ti).name; // Unsafe casts
|
||||||
info := type_info_base(fruit_ti) as ^Type_Info.Enum // Unsafe casts
|
info := cast(^Type_Info.Enum)type_info_base(fruit_ti); // Unsafe casts
|
||||||
|
|
||||||
fmt.printf("% :: enum % {\n", name, info.base);
|
fmt.printf("% :: enum % {\n", name, info.base);
|
||||||
for i := 0; i < info.values.count; i++ {
|
for i := 0; i < info.values.count; i += 1 {
|
||||||
fmt.printf("\t%\t= %,\n", info.names[i], info.values[i])
|
fmt.printf("\t%\t= %,\n", info.names[i], info.values[i]);
|
||||||
}
|
}
|
||||||
fmt.printf("}\n")
|
fmt.printf("}\n");
|
||||||
|
|
||||||
// NOTE(bill): look at that type-safe printf!
|
// NOTE(bill): look at that type-safe printf!
|
||||||
}
|
}
|
||||||
@@ -275,10 +275,10 @@ crazy_introspection :: proc() {
|
|||||||
{
|
{
|
||||||
Vector3 :: struct {x, y, z: f32}
|
Vector3 :: struct {x, y, z: f32}
|
||||||
|
|
||||||
a := Vector3{x = 1, y = 4, z = 9}
|
a := Vector3{x = 1, y = 4, z = 9};
|
||||||
fmt.println(a)
|
fmt.println(a);
|
||||||
b := Vector3{x = 9, y = 3, z = 1}
|
b := Vector3{x = 9, y = 3, z = 1};
|
||||||
fmt.println(b)
|
fmt.println(b);
|
||||||
|
|
||||||
// NOTE(bill): See fmt.odin
|
// NOTE(bill): See fmt.odin
|
||||||
}
|
}
|
||||||
|
|||||||
+168
-160
@@ -1,34 +1,35 @@
|
|||||||
#import "win32.odin"
|
#import win32 "sys/windows.odin";
|
||||||
#import "fmt.odin"
|
#import "fmt.odin";
|
||||||
#import "os.odin"
|
#import "os.odin";
|
||||||
|
#import "mem.odin";
|
||||||
|
|
||||||
CANVAS_WIDTH :: 128
|
CANVAS_WIDTH :: 128;
|
||||||
CANVAS_HEIGHT :: 128
|
CANVAS_HEIGHT :: 128;
|
||||||
CANVAS_SCALE :: 3
|
CANVAS_SCALE :: 3;
|
||||||
FRAME_TIME :: 1.0/30.0
|
FRAME_TIME :: 1.0/30.0;
|
||||||
WINDOW_TITLE :: "Punity\x00"
|
WINDOW_TITLE :: "Punity\x00";
|
||||||
|
|
||||||
_ := compile_assert(CANVAS_WIDTH % 16 == 0)
|
_ := compile_assert(CANVAS_WIDTH % 16 == 0);
|
||||||
|
|
||||||
WINDOW_WIDTH :: CANVAS_WIDTH * CANVAS_SCALE
|
WINDOW_WIDTH :: CANVAS_WIDTH * CANVAS_SCALE;
|
||||||
WINDOW_HEIGHT :: CANVAS_HEIGHT * CANVAS_SCALE
|
WINDOW_HEIGHT :: CANVAS_HEIGHT * CANVAS_SCALE;
|
||||||
|
|
||||||
|
|
||||||
STACK_CAPACITY :: 1<<20
|
STACK_CAPACITY :: 1<<20;
|
||||||
STORAGE_CAPACITY :: 1<<20
|
STORAGE_CAPACITY :: 1<<20;
|
||||||
|
|
||||||
DRAW_LIST_RESERVE :: 128
|
DRAW_LIST_RESERVE :: 128;
|
||||||
|
|
||||||
MAX_KEYS :: 256
|
MAX_KEYS :: 256;
|
||||||
|
|
||||||
Core :: struct {
|
Core :: struct {
|
||||||
stack: ^Bank
|
stack: ^Bank,
|
||||||
storage: ^Bank
|
storage: ^Bank,
|
||||||
|
|
||||||
running: bool
|
running: bool,
|
||||||
key_modifiers: u32
|
key_modifiers: u32,
|
||||||
key_states: [MAX_KEYS]byte
|
key_states: [MAX_KEYS]byte,
|
||||||
key_deltas: [MAX_KEYS]byte
|
key_deltas: [MAX_KEYS]byte,
|
||||||
|
|
||||||
perf_frame,
|
perf_frame,
|
||||||
perf_frame_inner,
|
perf_frame_inner,
|
||||||
@@ -36,70 +37,66 @@ Core :: struct {
|
|||||||
perf_audio,
|
perf_audio,
|
||||||
perf_blit,
|
perf_blit,
|
||||||
perf_blit_cvt,
|
perf_blit_cvt,
|
||||||
perf_blit_gdi: Perf_Span
|
perf_blit_gdi: Perf_Span,
|
||||||
|
|
||||||
frame: i64
|
frame: i64,
|
||||||
|
|
||||||
canvas: Canvas
|
canvas: Canvas,
|
||||||
draw_list: ^Draw_List
|
draw_list: ^Draw_List,
|
||||||
}
|
}
|
||||||
|
|
||||||
Perf_Span :: struct {
|
Perf_Span :: struct {
|
||||||
stamp: f64
|
stamp: f64,
|
||||||
delta: f32
|
delta: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
Bank :: struct {
|
Bank :: struct {
|
||||||
memory: []byte
|
memory: []byte,
|
||||||
cursor: int
|
cursor: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
Bank_State :: struct {
|
Bank_State :: struct {
|
||||||
state: Bank
|
state: Bank,
|
||||||
bank: ^Bank
|
bank: ^Bank,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Color :: raw_union {
|
Color :: raw_union {
|
||||||
using channels: struct{ a, b, g, r: byte; }
|
using channels: struct{a, b, g, r: byte},
|
||||||
rgba: u32
|
rgba: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
Palette :: struct {
|
Palette :: struct {
|
||||||
colors: [256]Color
|
colors: [256]Color,
|
||||||
colors_count: byte
|
colors_count: byte,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rect :: raw_union {
|
Rect :: raw_union {
|
||||||
using minmax: struct {
|
using minmax: struct {min_x, min_y, max_x, max_y: int},
|
||||||
min_x, min_y, max_x, max_y: int
|
using pos: struct {left, top, right, bottom: int},
|
||||||
}
|
e: [4]int,
|
||||||
using pos: struct {
|
|
||||||
left, top, right, bottom: int
|
|
||||||
}
|
|
||||||
e: [4]int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap :: struct {
|
Bitmap :: struct {
|
||||||
pixels: []byte
|
pixels: []byte,
|
||||||
width: int
|
width: int,
|
||||||
height: int
|
height: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
Font :: struct {
|
Font :: struct {
|
||||||
using bitmap: Bitmap
|
using bitmap: Bitmap,
|
||||||
char_width: int
|
char_width: int,
|
||||||
char_height: int
|
char_height: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas :: struct {
|
Canvas :: struct {
|
||||||
using bitmap: ^Bitmap
|
using bitmap: ^Bitmap,
|
||||||
palette: Palette
|
palette: Palette,
|
||||||
translate_x: int
|
translate_x: int,
|
||||||
translate_y: int
|
translate_y: int,
|
||||||
clip: Rect
|
clip: Rect,
|
||||||
font: ^Font
|
font: ^Font,
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawFlag :: enum {
|
DrawFlag :: enum {
|
||||||
@@ -109,12 +106,9 @@ DrawFlag :: enum {
|
|||||||
MASK = 1<<2,
|
MASK = 1<<2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Draw_Item :: struct {}
|
||||||
Draw_List :: struct {
|
Draw_List :: struct {
|
||||||
Item :: struct {
|
items: []Draw_Item,
|
||||||
|
|
||||||
}
|
|
||||||
items: []Item
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Key :: enum {
|
Key :: enum {
|
||||||
@@ -268,112 +262,112 @@ Key :: enum {
|
|||||||
BACKSLASH = 92, /* \ */
|
BACKSLASH = 92, /* \ */
|
||||||
RIGHT_BRACKET = 93, /* ] */
|
RIGHT_BRACKET = 93, /* ] */
|
||||||
GRAVE_ACCENT = 96, /* ` */
|
GRAVE_ACCENT = 96, /* ` */
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
key_down :: proc(k: Key) -> bool {
|
key_down :: proc(k: Key) -> bool {
|
||||||
return _core.key_states[k] != 0
|
return _core.key_states[k] != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
key_pressed :: proc(k: Key) -> bool {
|
key_pressed :: proc(k: Key) -> bool {
|
||||||
return (_core.key_deltas[k] != 0) && key_down(k)
|
return (_core.key_deltas[k] != 0) && key_down(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
win32_perf_count_freq := win32.GetQueryPerformanceFrequency()
|
win32_perf_count_freq := win32.GetQueryPerformanceFrequency();
|
||||||
time_now :: proc() -> f64 {
|
time_now :: proc() -> f64 {
|
||||||
assert(win32_perf_count_freq != 0)
|
assert(win32_perf_count_freq != 0);
|
||||||
|
|
||||||
counter: i64
|
counter: i64;
|
||||||
win32.QueryPerformanceCounter(^counter)
|
win32.QueryPerformanceCounter(^counter);
|
||||||
result := counter as f64 / win32_perf_count_freq as f64
|
result := cast(f64)counter / cast(f64)win32_perf_count_freq;
|
||||||
return result
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
_core: Core
|
_core: Core;
|
||||||
|
|
||||||
run :: proc(user_init, user_step: proc(c: ^Core)) {
|
run :: proc(user_init, user_step: proc(c: ^Core)) {
|
||||||
using win32
|
using win32;
|
||||||
|
|
||||||
_core.running = true
|
_core.running = true;
|
||||||
|
|
||||||
win32_proc :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #no_inline #stdcall {
|
win32_proc :: proc(hwnd: win32.HWND, msg: u32, wparam: win32.WPARAM, lparam: win32.LPARAM) -> win32.LRESULT #no_inline #cc_c {
|
||||||
win32_app_key_mods :: proc() -> u32 {
|
win32_app_key_mods :: proc() -> u32 {
|
||||||
mods: u32 = 0
|
mods: u32 = 0;
|
||||||
|
|
||||||
if is_key_down(Key_Code.SHIFT) {
|
if is_key_down(Key_Code.SHIFT) {
|
||||||
mods |= Key.MOD_SHIFT as u32
|
mods |= cast(u32)Key.MOD_SHIFT;
|
||||||
}
|
}
|
||||||
if is_key_down(Key_Code.CONTROL) {
|
if is_key_down(Key_Code.CONTROL) {
|
||||||
mods |= Key.MOD_CONTROL as u32
|
mods |= cast(u32)Key.MOD_CONTROL;
|
||||||
}
|
}
|
||||||
if is_key_down(Key_Code.MENU) {
|
if is_key_down(Key_Code.MENU) {
|
||||||
mods |= Key.MOD_ALT as u32
|
mods |= cast(u32)Key.MOD_ALT;
|
||||||
}
|
}
|
||||||
if is_key_down(Key_Code.LWIN) || is_key_down(Key_Code.RWIN) {
|
if is_key_down(Key_Code.LWIN) || is_key_down(Key_Code.RWIN) {
|
||||||
mods |= Key.MOD_SUPER as u32
|
mods |= cast(u32)Key.MOD_SUPER;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mods
|
return mods;
|
||||||
}
|
}
|
||||||
|
|
||||||
match msg {
|
match msg {
|
||||||
case WM_KEYDOWN:
|
case WM_KEYDOWN:
|
||||||
_core.key_modifiers = win32_app_key_mods()
|
_core.key_modifiers = win32_app_key_mods();
|
||||||
if wparam < MAX_KEYS {
|
if wparam < MAX_KEYS {
|
||||||
_core.key_states[wparam] = 1
|
_core.key_states[wparam] = 1;
|
||||||
_core.key_deltas[wparam] = 1
|
_core.key_deltas[wparam] = 1;
|
||||||
}
|
}
|
||||||
return 0
|
return 0;
|
||||||
|
|
||||||
case WM_KEYUP:
|
case WM_KEYUP:
|
||||||
_core.key_modifiers = win32_app_key_mods()
|
_core.key_modifiers = win32_app_key_mods();
|
||||||
if wparam < MAX_KEYS {
|
if wparam < MAX_KEYS {
|
||||||
_core.key_states[wparam] = 0
|
_core.key_states[wparam] = 0;
|
||||||
_core.key_deltas[wparam] = 1
|
_core.key_deltas[wparam] = 1;
|
||||||
}
|
}
|
||||||
return 0
|
return 0;
|
||||||
|
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
PostQuitMessage(0)
|
PostQuitMessage(0);
|
||||||
_core.running = false
|
_core.running = false;
|
||||||
return 0
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DefWindowProcA(hwnd, msg, wparam, lparam)
|
return DefWindowProcA(hwnd, msg, wparam, lparam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
window_class := WNDCLASSEXA{
|
window_class := WNDCLASSEXA{
|
||||||
class_name = ("Punity\x00" as string).data, // C-style string
|
class_name = (cast(string)"Punity\x00").data, // C-style string
|
||||||
size = size_of(WNDCLASSEXA) as u32,
|
size = size_of(WNDCLASSEXA),
|
||||||
style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
|
style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
|
||||||
instance = GetModuleHandleA(nil) as HINSTANCE,
|
instance = cast(HINSTANCE)GetModuleHandleA(nil),
|
||||||
wnd_proc = win32_proc,
|
wnd_proc = win32_proc,
|
||||||
// wnd_proc = DefWindowProcA,
|
// wnd_proc = DefWindowProcA,
|
||||||
background = GetStockObject(BLACK_BRUSH) as HBRUSH,
|
background = cast(HBRUSH)GetStockObject(BLACK_BRUSH),
|
||||||
}
|
};
|
||||||
|
|
||||||
if RegisterClassExA(^window_class) == 0 {
|
if RegisterClassExA(^window_class) == 0 {
|
||||||
fmt.fprintln(os.stderr, "RegisterClassExA failed")
|
fmt.fprintln(os.stderr, "RegisterClassExA failed");
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
screen_width := GetSystemMetrics(SM_CXSCREEN)
|
screen_width := GetSystemMetrics(SM_CXSCREEN);
|
||||||
screen_height := GetSystemMetrics(SM_CYSCREEN)
|
screen_height := GetSystemMetrics(SM_CYSCREEN);
|
||||||
|
|
||||||
rc: RECT
|
rc: RECT;
|
||||||
rc.left = (screen_width - WINDOW_WIDTH) / 2
|
rc.left = (screen_width - WINDOW_WIDTH) / 2;
|
||||||
rc.top = (screen_height - WINDOW_HEIGHT) / 2
|
rc.top = (screen_height - WINDOW_HEIGHT) / 2;
|
||||||
rc.right = rc.left + WINDOW_WIDTH
|
rc.right = rc.left + WINDOW_WIDTH;
|
||||||
rc.bottom = rc.top + WINDOW_HEIGHT
|
rc.bottom = rc.top + WINDOW_HEIGHT;
|
||||||
|
|
||||||
style: u32 = WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
|
style: u32 = WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
|
||||||
assert(AdjustWindowRect(^rc, style, 0) != 0)
|
assert(AdjustWindowRect(^rc, style, 0) != 0);
|
||||||
|
|
||||||
wt := WINDOW_TITLE
|
wt := WINDOW_TITLE;
|
||||||
|
|
||||||
win32_window := CreateWindowExA(0,
|
win32_window := CreateWindowExA(0,
|
||||||
window_class.class_name,
|
window_class.class_name,
|
||||||
@@ -382,101 +376,115 @@ run :: proc(user_init, user_step: proc(c: ^Core)) {
|
|||||||
rc.left, rc.top,
|
rc.left, rc.top,
|
||||||
rc.right-rc.left, rc.bottom-rc.top,
|
rc.right-rc.left, rc.bottom-rc.top,
|
||||||
nil, nil, window_class.instance,
|
nil, nil, window_class.instance,
|
||||||
nil)
|
nil);
|
||||||
|
|
||||||
if win32_window == nil {
|
if win32_window == nil {
|
||||||
fmt.fprintln(os.stderr, "CreateWindowExA failed")
|
fmt.fprintln(os.stderr, "CreateWindowExA failed");
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
window_bmi: BITMAPINFO
|
window_bmi: BITMAPINFO;
|
||||||
window_bmi.size = size_of(BITMAPINFO.HEADER) as u32
|
window_bmi.size = size_of(BITMAPINFOHEADER);
|
||||||
window_bmi.width = CANVAS_WIDTH
|
window_bmi.width = CANVAS_WIDTH;
|
||||||
window_bmi.height = CANVAS_HEIGHT
|
window_bmi.height = CANVAS_HEIGHT;
|
||||||
window_bmi.planes = 1
|
window_bmi.planes = 1;
|
||||||
window_bmi.bit_count = 32
|
window_bmi.bit_count = 32;
|
||||||
window_bmi.compression = BI_RGB
|
window_bmi.compression = BI_RGB;
|
||||||
|
|
||||||
|
|
||||||
user_init(^_core)
|
user_init(^_core);
|
||||||
|
|
||||||
|
ShowWindow(win32_window, SW_SHOW);
|
||||||
|
|
||||||
|
window_buffer := new_slice(u32, CANVAS_WIDTH * CANVAS_HEIGHT);
|
||||||
|
assert(window_buffer.data != nil);
|
||||||
|
defer free(window_buffer.data);
|
||||||
|
|
||||||
|
|
||||||
ShowWindow(win32_window, SW_SHOW)
|
for i := 0; i < window_buffer.count; i += 1 {
|
||||||
|
window_buffer[i] = 0xff00ff;
|
||||||
window_buffer := new_slice(u32, CANVAS_WIDTH * CANVAS_HEIGHT)
|
|
||||||
assert(window_buffer.data != nil)
|
|
||||||
defer free(window_buffer.data)
|
|
||||||
|
|
||||||
for i := 0; i < window_buffer.count; i++ {
|
|
||||||
window_buffer[i] = 0xff00ff
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
prev_time, curr_time,dt: f64
|
dt: f64;
|
||||||
prev_time = time_now()
|
prev_time := time_now();
|
||||||
curr_time = time_now()
|
curr_time := time_now();
|
||||||
total_time : f64 = 0
|
total_time : f64 = 0;
|
||||||
offset_x := 0
|
offset_x := 0;
|
||||||
offset_y := 0
|
offset_y := 0;
|
||||||
|
|
||||||
message: MSG
|
message: MSG;
|
||||||
for _core.running {
|
for _core.running {
|
||||||
curr_time = time_now()
|
curr_time = time_now();
|
||||||
dt = curr_time - prev_time
|
dt = curr_time - prev_time;
|
||||||
prev_time = curr_time
|
prev_time = curr_time;
|
||||||
total_time += dt
|
total_time += dt;
|
||||||
|
|
||||||
offset_x += 1
|
offset_x += 1;
|
||||||
offset_y += 2
|
offset_y += 2;
|
||||||
|
|
||||||
{
|
{
|
||||||
data: [128]byte
|
data: [128]byte;
|
||||||
buf := data[:0]
|
buf: fmt.Buffer;
|
||||||
fmt.bprintf(^buf, "Punity: % ms\x00", dt*1000)
|
buf.data = data[:];
|
||||||
win32.SetWindowTextA(win32_window, buf.data)
|
fmt.bprintf(^buf, "Punity: %.4f ms\x00", dt*1000);
|
||||||
|
win32.SetWindowTextA(win32_window, ^buf[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for y := 0; y < CANVAS_HEIGHT; y++ {
|
for y := 0; y < CANVAS_HEIGHT; y += 1 {
|
||||||
for x := 0; x < CANVAS_WIDTH; x++ {
|
for x := 0; x < CANVAS_WIDTH; x += 1 {
|
||||||
g := (x % 32) * 8
|
g := (x % 32) * 8;
|
||||||
b := (y % 32) * 8
|
b := (y % 32) * 8;
|
||||||
window_buffer[x + y*CANVAS_WIDTH] = (g << 8 | b) as u32
|
window_buffer[x + y*CANVAS_WIDTH] = cast(u32)(g << 8 | b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_core.key_deltas = nil
|
mem.zero(^_core.key_deltas[0], size_of_val(_core.key_deltas));
|
||||||
|
|
||||||
for PeekMessageA(^message, nil, 0, 0, PM_REMOVE) != 0 {
|
for PeekMessageA(^message, nil, 0, 0, PM_REMOVE) != 0 {
|
||||||
if message.message == WM_QUIT {
|
if message.message == WM_QUIT {
|
||||||
_core.running = false
|
_core.running = false;
|
||||||
}
|
}
|
||||||
TranslateMessage(^message)
|
TranslateMessage(^message);
|
||||||
DispatchMessageA(^message)
|
DispatchMessageA(^message);
|
||||||
}
|
}
|
||||||
|
|
||||||
user_step(^_core)
|
user_step(^_core);
|
||||||
|
|
||||||
dc := GetDC(win32_window)
|
dc := GetDC(win32_window);
|
||||||
StretchDIBits(dc,
|
StretchDIBits(dc,
|
||||||
0, 0, CANVAS_WIDTH * CANVAS_SCALE, CANVAS_HEIGHT * CANVAS_SCALE,
|
0, 0, CANVAS_WIDTH * CANVAS_SCALE, CANVAS_HEIGHT * CANVAS_SCALE,
|
||||||
0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
|
0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
|
||||||
window_buffer.data,
|
window_buffer.data,
|
||||||
^window_bmi,
|
^window_bmi,
|
||||||
DIB_RGB_COLORS,
|
DIB_RGB_COLORS,
|
||||||
SRCCOPY)
|
SRCCOPY);
|
||||||
ReleaseDC(win32_window, dc)
|
ReleaseDC(win32_window, dc);
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
delta := time_now() - prev_time
|
delta := time_now() - prev_time;
|
||||||
ms := ((FRAME_TIME - delta) * 1000) as i32
|
ms := cast(i32)((FRAME_TIME - delta) * 1000);
|
||||||
if ms > 0 {
|
if ms > 0 {
|
||||||
win32.Sleep(ms)
|
win32.Sleep(ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_core.frame++
|
_core.frame += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
main :: proc() {
|
||||||
|
user_init :: proc(c: ^Core) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
user_step :: proc(c: ^Core) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
run(user_init, user_step);
|
||||||
|
}
|
||||||
|
|||||||
+20
-12
@@ -421,9 +421,7 @@ fmt_write_padding :: proc(fi: ^Fmt_Info, width: int) {
|
|||||||
|
|
||||||
fmt_integer :: proc(fi: ^Fmt_Info, u: u64, base: int, signed: bool, digits: string) {
|
fmt_integer :: proc(fi: ^Fmt_Info, u: u64, base: int, signed: bool, digits: string) {
|
||||||
negative := signed && cast(i64)u < 0;
|
negative := signed && cast(i64)u < 0;
|
||||||
if negative {
|
u = abs(u);
|
||||||
u = -u;
|
|
||||||
}
|
|
||||||
buf: [256]byte;
|
buf: [256]byte;
|
||||||
if fi.width_set || fi.prec_set {
|
if fi.width_set || fi.prec_set {
|
||||||
width := fi.width + fi.prec + 3;
|
width := fi.width + fi.prec + 3;
|
||||||
@@ -504,14 +502,16 @@ fmt_integer :: proc(fi: ^Fmt_Info, u: u64, base: int, signed: bool, digits: stri
|
|||||||
buffer_write(fi.buf, buf[i:]);
|
buffer_write(fi.buf, buf[i:]);
|
||||||
} else {
|
} else {
|
||||||
width := fi.width - utf8.rune_count(cast(string)buf[i:]);
|
width := fi.width - utf8.rune_count(cast(string)buf[i:]);
|
||||||
if fi.minus {
|
if width > 0 {
|
||||||
// Right pad
|
if fi.minus {
|
||||||
buffer_write(fi.buf, buf[i:]);
|
// Right pad
|
||||||
fmt_write_padding(fi, width);
|
buffer_write(fi.buf, buf[i:]);
|
||||||
} else {
|
fmt_write_padding(fi, width);
|
||||||
// Left pad
|
} else {
|
||||||
fmt_write_padding(fi, width);
|
// Left pad
|
||||||
buffer_write(fi.buf, buf[i:]);
|
fmt_write_padding(fi, width);
|
||||||
|
buffer_write(fi.buf, buf[i:]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,8 +574,16 @@ fmt_float :: proc(fi: ^Fmt_Info, v: f64, bit_size: int, verb: rune) {
|
|||||||
signed := v < 0;
|
signed := v < 0;
|
||||||
v = abs(v);
|
v = abs(v);
|
||||||
|
|
||||||
|
if signed {
|
||||||
|
buffer_write_byte(fi.buf, '-');
|
||||||
|
}
|
||||||
|
|
||||||
val := cast(u64)v;
|
val := cast(u64)v;
|
||||||
fmt_integer(fi, val, 10, signed, __DIGITS_LOWER);
|
fi.minus = false;
|
||||||
|
fi.width = 0;
|
||||||
|
fi.prec = 0;
|
||||||
|
// TODO(bill): Write integer to buffer than use this crap
|
||||||
|
fmt_integer(fi, val, 10, false, __DIGITS_LOWER);
|
||||||
|
|
||||||
if fi.hash || prec > 0 {
|
if fi.hash || prec > 0 {
|
||||||
arg := v - cast(f64)val;
|
arg := v - cast(f64)val;
|
||||||
|
|||||||
+5
-4
@@ -302,10 +302,11 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
|
|||||||
error_node(pd->body, "A procedure tagged as `#foreign` cannot have a body");
|
error_node(pd->body, "A procedure tagged as `#foreign` cannot have a body");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proc_type->Proc.calling_convention != ProcCC_Odin) {
|
// TODO(bill): Is this the best option? What about passing to external shit?!
|
||||||
error_node(d->proc_lit, "An internal procedure may only have the Odin calling convention");
|
// if (proc_type->Proc.calling_convention != ProcCC_Odin) {
|
||||||
proc_type->Proc.calling_convention = ProcCC_Odin;
|
// error_node(d->proc_lit, "An internal procedure may only have the Odin calling convention");
|
||||||
}
|
// proc_type->Proc.calling_convention = ProcCC_Odin;
|
||||||
|
// }
|
||||||
|
|
||||||
d->scope = c->context.scope;
|
d->scope = c->context.scope;
|
||||||
|
|
||||||
|
|||||||
@@ -203,6 +203,11 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (is_type_proc(dst)) {
|
||||||
|
// if (are_types_identical(src, dst)) {
|
||||||
|
// return 1;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
if (is_type_any(dst)) {
|
if (is_type_any(dst)) {
|
||||||
// NOTE(bill): Anything can cast to `Any`
|
// NOTE(bill): Anything can cast to `Any`
|
||||||
|
|||||||
+1
-1
@@ -240,7 +240,7 @@ int main(int argc, char **argv) {
|
|||||||
char lib_str_buf[1024] = {0};
|
char lib_str_buf[1024] = {0};
|
||||||
for_array(i, ir_gen.module.foreign_library_paths) {
|
for_array(i, ir_gen.module.foreign_library_paths) {
|
||||||
String lib = ir_gen.module.foreign_library_paths.e[i];
|
String lib = ir_gen.module.foreign_library_paths.e[i];
|
||||||
gb_printf_err("Linking lib: %.*s\n", LIT(lib));
|
// gb_printf_err("Linking lib: %.*s\n", LIT(lib));
|
||||||
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
|
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
|
||||||
" \"%.*s\"", LIT(lib));
|
" \"%.*s\"", LIT(lib));
|
||||||
lib_str = gb_string_appendc(lib_str, lib_str_buf);
|
lib_str = gb_string_appendc(lib_str, lib_str_buf);
|
||||||
|
|||||||
+8
-5
@@ -1827,11 +1827,15 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case Token_if:
|
case Token_if:
|
||||||
if (lhs) goto error;
|
if (!lhs && f->expr_level >= 0) {
|
||||||
return parse_if_expr(f);
|
return parse_if_expr(f);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Token_OpenBrace:
|
case Token_OpenBrace:
|
||||||
if (lhs) goto error;
|
if (!lhs && f->expr_level >= 0) {
|
||||||
return parse_block_expr(f);
|
return parse_block_expr(f);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
AstNode *type = parse_identifier_or_type(f);
|
AstNode *type = parse_identifier_or_type(f);
|
||||||
@@ -1846,7 +1850,6 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error:
|
|
||||||
Token begin = f->curr_token;
|
Token begin = f->curr_token;
|
||||||
syntax_error(begin, "Expected an operand");
|
syntax_error(begin, "Expected an operand");
|
||||||
fix_advance_to_next_stmt(f);
|
fix_advance_to_next_stmt(f);
|
||||||
|
|||||||
+3
-1
@@ -1194,7 +1194,9 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
|||||||
} else if (!is_type_union(type)) {
|
} else if (!is_type_union(type)) {
|
||||||
for (isize i = 0; i < type->Record.field_count; i++) {
|
for (isize i = 0; i < type->Record.field_count; i++) {
|
||||||
Entity *f = type->Record.fields[i];
|
Entity *f = type->Record.fields[i];
|
||||||
GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
|
if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
String str = f->token.string;
|
String str = f->token.string;
|
||||||
if (str_eq(field_name, str)) {
|
if (str_eq(field_name, str)) {
|
||||||
selection_add_index(&sel, i); // HACK(bill): Leaky memory
|
selection_add_index(&sel, i); // HACK(bill): Leaky memory
|
||||||
|
|||||||
Reference in New Issue
Block a user