Skip to content

Commit

Permalink
v0.1.0
Browse files Browse the repository at this point in the history
Added:
 * Dynamic Arrays `[...]Type`
 * Dynamic Maps   `map[Key]Value`
 * Dynamic array and map literals
 * Custom struct alignemnt `struct #align 8 { bar: i8 }`
 * Allow `_` in numbers
 * Variadic `append`
 * fmt.sprint*
 * Entities prefixes with an underscore do not get exported on imports
 * Overloaded `free` for pointers, slices, strings, dynamic arrays, and dynamic maps
 * enum types have an implict `names` field, a []string of all the names in that enum

Removed:
 * Maybe/option types
 * immutable variables
 * Remove `type` keyword and other "reserved" keywords
 * `compile_assert` and `assert`return the value of the condition for semantic reasons

Changed:
 * thread_local -> #thread_local
 * #include -> #load
 * Files only get checked if they are actually used
 * match x in y {} // For type match statements
 * Version numbering now starts from 0.1.0 and uses the convention:
 	- major.minor.patch

Fixes:
 * Many fmt.* fixes

To come very Soon™:
 * Linux and OS X builds (unofficial ones do exist already)
  • Loading branch information
gingerBill committed Feb 11, 2017
1 parent 4306345 commit e1fdd67
Show file tree
Hide file tree
Showing 12 changed files with 164 additions and 170 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ The Odin programming language is fast, concise, readable, pragmatic and open sou

## Roadmap

Not in any particular order
Not in any particular order and not be implemented

* Compile Time Execution (CTE)
- More metaprogramming madness
Expand All @@ -45,10 +45,8 @@ Not in any particular order
* Replace LLVM backend with my own custom backend
* Improve SSA design to accommodate for lowering to a "bytecode"
* SSA optimizations
* Parametric Polymorphism ("Generics")
* Documentation Generator for "Entities"
* Multiple Architecture support
* Language level atomics and concurrency support
* Debug Information
- pdb format too
* Command Line Tooling
Expand Down
2 changes: 1 addition & 1 deletion build.bat
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
set exe_name=odin.exe

:: Debug = 0, Release = 1
set release_mode=0
set release_mode=1
set compiler_flags= -nologo -Oi -TC -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-

if %release_mode% EQU 0 ( rem Debug
Expand Down
105 changes: 69 additions & 36 deletions code/demo.odin
Original file line number Diff line number Diff line change
@@ -1,26 +1,51 @@
#import . "fmt.odin";
#import "atomic.odin";
#import "hash.odin";
#import "math.odin";
#import "mem.odin";
#import "opengl.odin";
#import "os.odin";
#import "sync.odin";
#import "types.odin";
#import "utf8.odin";
#import "fmt.odin";

main :: proc() {
/*
Version 0.1.0
Added:
* Dynamic Arrays `[...]Type`
* Dynamic Maps `map[Key]Value`
* Dynamic array and map literals
* Custom struct alignemnt `struct #align 8 { bar: i8 }`
* Allow `_` in numbers
* Variadic `append`
* fmt.sprint*
* Entities prefixes with an underscore do not get exported on imports
* Overloaded `free` for pointers, slices, strings, dynamic arrays, and dynamic maps
* enum types have an implict `names` field, a []string of all the names in that enum
Removed:
* Maybe/option types
* immutable variables
* Remove `type` keyword and other "reserved" keywords
* `compile_assert` and `assert`return the value of the condition for semantic reasons
Changed:
* thread_local -> #thread_local
* #include -> #load
* Files only get checked if they are actually used
* match x in y {} // For type match statements
* Version numbering now starts from 0.1.0 and uses the convention:
- major.minor.patch
Fixes:
* Many fmt.* fixes
To come very Soon™:
* Linux and OS X builds (unofficial ones do exist already)
*/

{
Fruit :: enum {
APPLE,
BANANA,
COCONUT,
}
println(x, Fruit.names);
fmt.println(Fruit.names);
}

when false {
{
m: map[f32]int;
reserve(m, 16);
Expand All @@ -33,16 +58,16 @@ when false {
c := m[3.0];
assert(ok && c == 564);

print("map[");
fmt.print("map[");
i := 0;
for val, key in m {
if i > 0 {
print(", ");
fmt.print(", ");
}
printf("%v=%v", key, val);
fmt.printf("%v=%v", key, val);
i += 1;
}
println("]");
fmt.println("]");
}
{
m := map[string]u32{
Expand All @@ -56,39 +81,47 @@ when false {
_, ok := m["c"];
assert(ok && c == 7654);

println(m);
fmt.println(m);
}

{
println("Hellope!");

x: [dynamic]f64;
x: [...]f64;
reserve(x, 16);
defer free(x);
append(x, 2_000_000.500_000, 3, 5, 7);

for p, i in x {
if i > 0 { print(", "); }
print(p);
if i > 0 { fmt.print(", "); }
fmt.print(p);
}
println();
fmt.println();
}

{
x := [...]f64{2_000_000.500_000, 3, 5, 7};
defer free(x);
fmt.println(x);
}


{
Vec3 :: [vector 3]f32;
{
Vec3 :: [vector 3]f32;

x := Vec3{1, 2, 3};
y := Vec3{4, 5, 6};
println(x < y);
println(x + y);
println(x - y);
println(x * y);
println(x / y);
x := Vec3{1, 2, 3};
y := Vec3{4, 5, 6};
fmt.println(x < y);
fmt.println(x + y);
fmt.println(x - y);
fmt.println(x * y);
fmt.println(x / y);

for i in x {
println(i);
}
for i in x {
fmt.println(i);
}

compile_assert(size_of([vector 7]bool) == size_of([7]bool));
compile_assert(size_of([vector 7]i32) == size_of([7]i32));
// align_of([vector 7]i32) != align_of([7]i32) // this may be the case
}
}
}

2 changes: 1 addition & 1 deletion core/_preload.odin
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ Context :: struct #ordered {
user_index: int,
}

thread_local __context: Context;
#thread_local __context: Context;


DEFAULT_ALIGNMENT :: align_of([vector 4]f32);
Expand Down
2 changes: 1 addition & 1 deletion core/opengl.odin
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#foreign_system_library lib "opengl32.lib" when ODIN_OS == "windows";
#import win32 "sys/windows.odin" when ODIN_OS == "windows";
#include "opengl_constants.odin";
#load "opengl_constants.odin";

Clear :: proc(mask: u32) #foreign lib "glClear";
ClearColor :: proc(r, g, b, a: f32) #foreign lib "glClearColor";
Expand Down
4 changes: 2 additions & 2 deletions core/os.odin
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#include "os_windows.odin" when ODIN_OS == "windows";
#include "os_x.odin" when ODIN_OS == "osx";
#load "os_windows.odin" when ODIN_OS == "windows";
#load "os_x.odin" when ODIN_OS == "osx";

20 changes: 0 additions & 20 deletions src/build.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,26 +213,6 @@ String get_fullpath_core(gbAllocator a, String path) {
return res;
}

String get_filepath_extension(String path) {
isize dot = 0;
bool seen_slash = false;
for (isize i = path.len-1; i >= 0; i--) {
u8 c = path.text[i];
if (c == '/' || c == '\\') {
seen_slash = true;
}

if (c == '.') {
if (seen_slash) {
return str_lit("");
}

dot = i;
break;
}
}
return make_string(path.text, dot);
}



Expand Down
28 changes: 8 additions & 20 deletions src/check_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2532,7 +2532,6 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
}

if (op_expr->kind == AstNode_Ident) {
b32 is_not_exported = true;
String name = op_expr->Ident.string;
Entity *e = scope_lookup_entity(c->context.scope, name);

Expand Down Expand Up @@ -2576,14 +2575,19 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
}
}


is_not_exported = !is_entity_name_exported(entity);
bool implicit_is_found = map_bool_get(&e->ImportName.scope->implicit, hash_pointer(entity)) != NULL;
bool is_not_exported = !is_entity_exported(entity);
if (!implicit_is_found) {
is_not_exported = false;
} else if (entity->kind == Entity_ImportName) {
is_not_exported = true;
}

if (is_not_exported) {
gbString sel_str = expr_to_string(selector);
error_node(op_expr, "`%s` is not exported by `%.*s`", sel_str, LIT(name));
gb_string_free(sel_str);
// NOTE(bill): We will have to cause an error his even though it exists
// NOTE(bill): Not really an error so don't goto error
goto error;
}

Expand Down Expand Up @@ -2629,22 +2633,6 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
return procs[0];
}
}

bool *found = map_bool_get(&e->ImportName.scope->implicit, hash_pointer(entity));
if (!found) {
is_not_exported = false;
} else {
if (entity->kind == Entity_ImportName) {
is_not_exported = true;
}
}

if (is_not_exported) {
gbString sel_str = expr_to_string(selector);
error_node(op_expr, "`%s` is not exported by `%.*s`", sel_str, LIT(name));
gb_string_free(sel_str);
// NOTE(bill): Not really an error so don't goto error
}
}
}

Expand Down
31 changes: 13 additions & 18 deletions src/checker.c
Original file line number Diff line number Diff line change
Expand Up @@ -1470,7 +1470,7 @@ void check_collect_entities(Checker *c, AstNodeArray nodes, bool is_file_scope)
if (id->is_import) {
error_node(decl, "#import declarations are only allowed in the file scope");
} else {
error_node(decl, "#include declarations are only allowed in the file scope");
error_node(decl, "#load declarations are only allowed in the file scope");
}
// NOTE(bill): _Should_ be caught by the parser
// TODO(bill): Better error handling if it isn't
Expand Down Expand Up @@ -1686,7 +1686,7 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
if (!previously_added) {
array_add(&parent_scope->imported, scope);
} else {
warning(token, "Multiple #import of the same file within this scope");
warning(token, "Multiple import of the same file within this scope");
}

scope->has_been_imported = true;
Expand All @@ -1698,24 +1698,19 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
if (e->scope == parent_scope) {
continue;
}
switch (e->kind) {
case Entity_ImportName:
case Entity_LibraryName:
break;
default: {

if (id->is_import) {
if (is_entity_name_exported(e)) {
// TODO(bill): Should these entities be imported but cause an error when used?
bool ok = add_entity(c, parent_scope, NULL, e);
if (ok) {
map_bool_set(&parent_scope->implicit, hash_pointer(e), true);
}
if (!is_entity_kind_exported(e->kind)) {
continue;
}
if (id->is_import) {
if (is_entity_exported(e)) {
// TODO(bill): Should these entities be imported but cause an error when used?
bool ok = add_entity(c, parent_scope, NULL, e);
if (ok) {
map_bool_set(&parent_scope->implicit, hash_pointer(e), true);
}
} else {
/* bool ok = */add_entity(c, parent_scope, NULL, e);
}
} break;
} else {
add_entity(c, parent_scope, NULL, e);
}
}
} else {
Expand Down
17 changes: 16 additions & 1 deletion src/entity.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,23 @@ struct Entity {

gb_global Entity *e_context = NULL;

bool is_entity_name_exported(Entity *e) {
bool is_entity_kind_exported(EntityKind kind) {
switch (kind) {
case Entity_Builtin:
case Entity_ImportName:
case Entity_LibraryName:
case Entity_Nil:
return false;
}
return true;
}

bool is_entity_exported(Entity *e) {
GB_ASSERT(e != NULL);
if (!is_entity_kind_exported(e->kind)) {
return false;
}

String name = e->token.string;
if (name.len == 0) {
return false;
Expand Down

0 comments on commit e1fdd67

Please sign in to comment.