aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--base/runtime/core.odin5
-rw-r--r--core/odin/ast/ast.odin22
-rw-r--r--core/odin/ast/clone.odin7
-rw-r--r--core/odin/ast/walk.odin10
-rw-r--r--core/odin/parser/parser.odin47
-rw-r--r--core/odin/printer/visit.odin52
-rw-r--r--core/sys/windows/types.odin8
-rw-r--r--core/time/datetime/validation.odin8
-rw-r--r--src/check_type.cpp2
-rw-r--r--src/linker.cpp2
-rw-r--r--tests/core/odin/test_parser.odin50
-rw-r--r--vendor/OpenGL/wrappers.odin8
12 files changed, 200 insertions, 21 deletions
diff --git a/base/runtime/core.odin b/base/runtime/core.odin
index 7ad3ef1d6..c62301c34 100644
--- a/base/runtime/core.odin
+++ b/base/runtime/core.odin
@@ -597,8 +597,9 @@ type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
base := info
loop: for {
#partial switch i in base.variant {
- case Type_Info_Named: base = i.base
- case Type_Info_Enum: base = i.base
+ case Type_Info_Named: base = i.base
+ case Type_Info_Enum: base = i.base
+ case Type_Info_Bit_Field: base = i.backing_type
case: break loop
}
}
diff --git a/core/odin/ast/ast.odin b/core/odin/ast/ast.odin
index 3e215e0f2..be541befa 100644
--- a/core/odin/ast/ast.odin
+++ b/core/odin/ast/ast.odin
@@ -617,7 +617,7 @@ field_flag_strings := [Field_Flag]string{
.Any_Int = "#any_int",
.Subtype = "#subtype",
.By_Ptr = "#by_ptr",
- .No_Broadcast ="#no_broadcast",
+ .No_Broadcast = "#no_broadcast",
.Results = "results",
.Tags = "field tag",
@@ -842,6 +842,23 @@ Matrix_Type :: struct {
elem: ^Expr,
}
+Bit_Field_Type :: struct {
+ using node: Expr,
+ tok_pos: tokenizer.Pos,
+ backing_type: ^Expr,
+ open: tokenizer.Pos,
+ fields: []^Bit_Field_Field,
+ close: tokenizer.Pos,
+}
+
+Bit_Field_Field :: struct {
+ using node: Node,
+ docs: ^Comment_Group,
+ name: ^Expr,
+ type: ^Expr,
+ bit_size: ^Expr,
+ comments: ^Comment_Group,
+}
Any_Node :: union {
^Package,
@@ -898,6 +915,7 @@ Any_Node :: union {
^Map_Type,
^Relative_Type,
^Matrix_Type,
+ ^Bit_Field_Type,
^Bad_Stmt,
^Empty_Stmt,
@@ -928,6 +946,7 @@ Any_Node :: union {
^Attribute,
^Field,
^Field_List,
+ ^Bit_Field_Field,
}
@@ -982,6 +1001,7 @@ Any_Expr :: union {
^Map_Type,
^Relative_Type,
^Matrix_Type,
+ ^Bit_Field_Type,
}
diff --git a/core/odin/ast/clone.odin b/core/odin/ast/clone.odin
index d105f6035..bca740dd4 100644
--- a/core/odin/ast/clone.odin
+++ b/core/odin/ast/clone.odin
@@ -336,6 +336,13 @@ clone_node :: proc(node: ^Node) -> ^Node {
case ^Relative_Type:
r.tag = clone(r.tag)
r.type = clone(r.type)
+ case ^Bit_Field_Type:
+ r.backing_type = clone(r.backing_type)
+ r.fields = auto_cast clone(r.fields)
+ case ^Bit_Field_Field:
+ r.name = clone(r.name)
+ r.type = clone(r.type)
+ r.bit_size = clone(r.bit_size)
case:
fmt.panicf("Unhandled node kind: %v", r)
}
diff --git a/core/odin/ast/walk.odin b/core/odin/ast/walk.odin
index 966a8137e..63107a2e2 100644
--- a/core/odin/ast/walk.odin
+++ b/core/odin/ast/walk.odin
@@ -414,7 +414,15 @@ walk :: proc(v: ^Visitor, node: ^Node) {
walk(v, n.row_count)
walk(v, n.column_count)
walk(v, n.elem)
-
+ case ^Bit_Field_Type:
+ walk(v, n.backing_type)
+ for f in n.fields {
+ walk(v, f)
+ }
+ case ^Bit_Field_Field:
+ walk(v, n.name)
+ walk(v, n.type)
+ walk(v, n.bit_size)
case:
fmt.panicf("ast.walk: unexpected node type %T", n)
}
diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin
index ab723e145..9eaef4655 100644
--- a/core/odin/parser/parser.odin
+++ b/core/odin/parser/parser.odin
@@ -531,7 +531,7 @@ is_semicolon_optional_for_node :: proc(p: ^Parser, node: ^ast.Node) -> bool {
return is_semicolon_optional_for_node(p, n.type)
case ^ast.Pointer_Type:
return is_semicolon_optional_for_node(p, n.elem)
- case ^ast.Struct_Type, ^ast.Union_Type, ^ast.Enum_Type:
+ case ^ast.Struct_Type, ^ast.Union_Type, ^ast.Enum_Type, ^ast.Bit_Set_Type, ^ast.Bit_Field_Type:
// Require semicolon within a procedure body
return p.curr_proc == nil
case ^ast.Proc_Lit:
@@ -2790,6 +2790,48 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
mt.column_count = column_count
mt.elem = elem
return mt
+
+ case .Bit_Field:
+ tok := expect_token(p, .Bit_Field)
+
+ backing_type := parse_type_or_ident(p)
+ if backing_type == nil {
+ token := advance_token(p)
+ error(p, token.pos, "Expected a backing type for a 'bit_field'")
+ }
+
+ skip_possible_newline_for_literal(p)
+ open := expect_token_after(p, .Open_Brace, "bit_field")
+
+ fields: [dynamic]^ast.Bit_Field_Field
+ for p.curr_tok.kind != .Close_Brace && p.curr_tok.kind != .EOF {
+ name := parse_ident(p)
+ expect_token(p, .Colon)
+ type := parse_type(p)
+ expect_token(p, .Or)
+ bit_size := parse_expr(p, true)
+
+ field := ast.new(ast.Bit_Field_Field, name.pos, bit_size)
+
+ field.name = name
+ field.type = type
+ field.bit_size = bit_size
+
+ append(&fields, field)
+
+ allow_token(p, .Comma) or_break
+ }
+
+ close := expect_closing_brace_of_field_list(p)
+
+ bf := ast.new(ast.Bit_Field_Type, tok.pos, close.pos)
+
+ bf.tok_pos = tok.pos
+ bf.backing_type = backing_type
+ bf.open = open.pos
+ bf.fields = fields[:]
+ bf.close = close.pos
+ return bf
case .Asm:
tok := expect_token(p, .Asm)
@@ -2897,7 +2939,8 @@ is_literal_type :: proc(expr: ^ast.Expr) -> bool {
^ast.Map_Type,
^ast.Bit_Set_Type,
^ast.Matrix_Type,
- ^ast.Call_Expr:
+ ^ast.Call_Expr,
+ ^ast.Bit_Field_Type:
return true
}
return false
diff --git a/core/odin/printer/visit.odin b/core/odin/printer/visit.odin
index 7dd208a49..571e4001d 100644
--- a/core/odin/printer/visit.odin
+++ b/core/odin/printer/visit.odin
@@ -445,7 +445,7 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) {
for value in v.values {
#partial switch a in value.derived {
- case ^ast.Union_Type, ^ast.Enum_Type, ^ast.Struct_Type:
+ case ^ast.Union_Type, ^ast.Enum_Type, ^ast.Struct_Type, ^ast.Bit_Field_Type:
add_semicolon = false || called_in_stmt
case ^ast.Proc_Lit:
add_semicolon = false
@@ -489,6 +489,37 @@ visit_exprs :: proc(p: ^Printer, list: []^ast.Expr, options := List_Options{}) {
}
@(private)
+visit_bit_field_fields :: proc(p: ^Printer, list: []^ast.Bit_Field_Field, options := List_Options{}) {
+ if len(list) == 0 {
+ return
+ }
+
+ // we have to newline the expressions to respect the source
+ for v, i in list {
+ // Don't move the first expression, it looks bad
+ if i != 0 && .Enforce_Newline in options {
+ newline_position(p, 1)
+ } else if i != 0 {
+ move_line_limit(p, v.pos, 1)
+ }
+
+ visit_expr(p, v.name, options)
+ push_generic_token(p, .Colon, 0)
+ visit_expr(p, v.type, options)
+ push_generic_token(p, .Or, 1)
+ visit_expr(p, v.bit_size, options)
+
+ if (i != len(list) - 1 || .Trailing in options) && .Add_Comma in options {
+ push_generic_token(p, .Comma, 0)
+ }
+ }
+
+ if len(list) > 1 && .Enforce_Newline in options {
+ newline_position(p, 1)
+ }
+}
+
+@(private)
visit_attributes :: proc(p: ^Printer, attributes: [dynamic]^ast.Attribute) {
if len(attributes) == 0 {
return
@@ -1293,6 +1324,25 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, options := List_Options{}) {
visit_expr(p, v.column_count)
push_generic_token(p, .Close_Bracket, 0)
visit_expr(p, v.elem)
+ case ^ast.Bit_Field_Type:
+ push_generic_token(p, .Bit_Field, 1)
+
+ visit_expr(p, v.backing_type)
+
+ if len(v.fields) == 0 || v.pos.line == v.close.line {
+ push_generic_token(p, .Open_Brace, 1)
+ visit_bit_field_fields(p, v.fields, {.Add_Comma})
+ push_generic_token(p, .Close_Brace, 0)
+ } else {
+ visit_begin_brace(p, v.pos, .Generic, len(v.fields))
+ newline_position(p, 1)
+ set_source_position(p, v.fields[0].pos)
+ visit_bit_field_fields(p, v.fields, {.Add_Comma, .Trailing, .Enforce_Newline})
+ set_source_position(p, v.close)
+ visit_end_brace(p, v.close)
+ }
+
+ set_source_position(p, v.close)
case:
panic(fmt.aprint(expr.derived))
}
diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin
index 37f953c58..4b54f0ed1 100644
--- a/core/sys/windows/types.odin
+++ b/core/sys/windows/types.odin
@@ -2074,7 +2074,13 @@ SRWLOCK_INIT :: SRWLOCK{}
STARTF_USESTDHANDLES: DWORD : 0x00000100
VOLUME_NAME_DOS: DWORD : 0x0
-MOVEFILE_REPLACE_EXISTING: DWORD : 1
+
+MOVEFILE_COPY_ALLOWED: DWORD: 0x2
+MOVEFILE_CREATE_HARDLINK: DWORD: 0x10
+MOVEFILE_DELAY_UNTIL_REBOOT: DWORD: 0x4
+MOVEFILE_FAIL_IF_NOT_TRACKABLE: DWORD: 0x20
+MOVEFILE_REPLACE_EXISTING: DWORD : 0x1
+MOVEFILE_WRITE_THROUGH: DWORD: 0x8
FILE_BEGIN: DWORD : 0
FILE_CURRENT: DWORD : 1
diff --git a/core/time/datetime/validation.odin b/core/time/datetime/validation.odin
index 110a7e78e..87d5aa1cd 100644
--- a/core/time/datetime/validation.odin
+++ b/core/time/datetime/validation.odin
@@ -56,9 +56,9 @@ validate_hour_minute_second :: proc "contextless" (#any_int hour, #any_int minut
return .None
}
-validate_datetime :: proc "contextless" (using datetime: DateTime) -> (err: Error) {
- validate(date) or_return
- validate(time) or_return
+validate_datetime :: proc "contextless" (datetime: DateTime) -> (err: Error) {
+ validate(datetime.date) or_return
+ validate(datetime.time) or_return
return .None
}
@@ -69,4 +69,4 @@ validate :: proc{
validate_hour_minute_second,
validate_time,
validate_datetime,
-} \ No newline at end of file
+}
diff --git a/src/check_type.cpp b/src/check_type.cpp
index 81e67f261..f1d991acb 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -1689,7 +1689,7 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para
bool is_using = (p->flags&FieldFlag_using) != 0;
if ((check_vet_flags(param) & VetFlag_UsingParam) && is_using) {
ERROR_BLOCK();
- error(param, "'using' on a procedure parameter is now allowed when '-vet' or '-vet-using-param' is applied");
+ error(param, "'using' on a procedure parameter is not allowed when '-vet' or '-vet-using-param' is applied");
error_line("\t'using' is considered bad practice to use as a statement/procedure parameter outside of immediate refactoring\n");
}
diff --git a/src/linker.cpp b/src/linker.cpp
index aa36b3278..498a96c5f 100644
--- a/src/linker.cpp
+++ b/src/linker.cpp
@@ -384,7 +384,7 @@ gb_internal i32 linker_stage(LinkerData *gen) {
LIT(obj_file),
LIT(build_context.extra_assembler_flags)
);
- if (!result) {
+ if (result) {
gb_printf_err("executing `nasm` to assemble foreing import of %.*s failed.\n\tSuggestion: `nasm` does not ship with the compiler and should be installed with your system's package manager.\n", LIT(asm_file));
return result;
}
diff --git a/tests/core/odin/test_parser.odin b/tests/core/odin/test_parser.odin
index 3837436bc..08f73a732 100644
--- a/tests/core/odin/test_parser.odin
+++ b/tests/core/odin/test_parser.odin
@@ -1,9 +1,12 @@
package test_core_odin_parser
-import "core:testing"
import "core:fmt"
-import "core:os"
+import "core:odin/ast"
import "core:odin/parser"
+import "core:odin/printer"
+import "core:os"
+import "core:strings"
+import "core:testing"
TEST_count := 0
@@ -30,6 +33,7 @@ when ODIN_TEST {
main :: proc() {
t := testing.T{}
test_parse_demo(&t)
+ test_parse_bitfield(&t)
fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
if TEST_fail > 0 {
@@ -47,4 +51,44 @@ test_parse_demo :: proc(t: ^testing.T) {
for key, value in pkg.files {
expect(t, value.syntax_error_count == 0, fmt.tprintf("%v should contain zero errors", key))
}
-} \ No newline at end of file
+}
+
+@test
+test_parse_bitfield :: proc(t: ^testing.T) {
+ file := ast.File{
+ fullpath = "test.odin",
+ src = `
+package main
+
+Foo :: bit_field uint {}
+
+Foo :: bit_field uint {hello: bool | 1}
+
+Foo :: bit_field uint {
+ hello: bool | 1,
+ hello: bool | 5,
+}
+
+// Hellope 1.
+Foo :: bit_field uint {
+ // Hellope 2.
+ hello: bool | 1,
+ hello: bool | 5, // Hellope 3.
+}
+ `,
+ }
+
+ p := parser.default_parser()
+ ok := parser.parse_file(&p, &file)
+ expect(t, ok == true, "bad parse")
+
+ cfg := printer.default_style
+ cfg.newline_style = .LF
+ print := printer.make_printer(cfg)
+ out := printer.print(&print, &file)
+
+ tsrc := strings.trim_space(file.src)
+ tout := strings.trim_space(out)
+
+ expect(t, tsrc == tout, fmt.tprintf("\n%s\n!=\n%s", tsrc, tout))
+}
diff --git a/vendor/OpenGL/wrappers.odin b/vendor/OpenGL/wrappers.odin
index 550ba3cfa..a04df6987 100644
--- a/vendor/OpenGL/wrappers.odin
+++ b/vendor/OpenGL/wrappers.odin
@@ -787,8 +787,8 @@ when !GL_DEBUG {
fmt.printf(" call: gl%s(", loc.procedure)
{
// add input arguments
- for arg, i in args[num_ret:] {
- if i > 0 { fmt.printf(", ") }
+ for arg, arg_index in args[num_ret:] {
+ if arg_index > 0 { fmt.printf(", ") }
if v, ok := arg.(u32); ok { // TODO: Assumes all u32 are GLenum (they're not, GLbitfield and GLuint are also mapped to u32), fix later by better typing
if err == .INVALID_ENUM {
@@ -806,8 +806,8 @@ when !GL_DEBUG {
fmt.printf(") -> %v \n", args[0])
} else if num_ret > 1 {
fmt.printf(") -> (")
- for arg, i in args[1:num_ret] {
- if i > 0 { fmt.printf(", ") }
+ for arg, arg_index in args[1:num_ret] {
+ if arg_index > 0 { fmt.printf(", ") }
fmt.printf("%v", arg)
}
fmt.printf(")\n")