mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 23:28:48 +00:00
Merge branch 'odin-lang:master' into fix-4445
This commit is contained in:
@@ -2307,6 +2307,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
|||||||
open := expect_token(p, .Open_Paren)
|
open := expect_token(p, .Open_Paren)
|
||||||
p.expr_level += 1
|
p.expr_level += 1
|
||||||
expr := parse_expr(p, false)
|
expr := parse_expr(p, false)
|
||||||
|
skip_possible_newline(p)
|
||||||
p.expr_level -= 1
|
p.expr_level -= 1
|
||||||
close := expect_token(p, .Close_Paren)
|
close := expect_token(p, .Close_Paren)
|
||||||
|
|
||||||
@@ -3526,6 +3527,7 @@ parse_binary_expr :: proc(p: ^Parser, lhs: bool, prec_in: int) -> ^ast.Expr {
|
|||||||
case .When:
|
case .When:
|
||||||
x := expr
|
x := expr
|
||||||
cond := parse_expr(p, lhs)
|
cond := parse_expr(p, lhs)
|
||||||
|
skip_possible_newline(p)
|
||||||
else_tok := expect_token(p, .Else)
|
else_tok := expect_token(p, .Else)
|
||||||
y := parse_expr(p, lhs)
|
y := parse_expr(p, lhs)
|
||||||
te := ast.new(ast.Ternary_When_Expr, expr.pos, end_pos(p.prev_tok))
|
te := ast.new(ast.Ternary_When_Expr, expr.pos, end_pos(p.prev_tok))
|
||||||
@@ -3780,10 +3782,6 @@ parse_import_decl :: proc(p: ^Parser, kind := Import_Decl_Kind.Standard) -> ^ast
|
|||||||
import_name.pos = p.curr_tok.pos
|
import_name.pos = p.curr_tok.pos
|
||||||
}
|
}
|
||||||
|
|
||||||
if !is_using && is_blank_ident(import_name) {
|
|
||||||
error(p, import_name.pos, "illegal import name: '_'")
|
|
||||||
}
|
|
||||||
|
|
||||||
path := expect_token_after(p, .String, "import")
|
path := expect_token_after(p, .String, "import")
|
||||||
|
|
||||||
decl := ast.new(ast.Import_Decl, tok.pos, end_pos(path))
|
decl := ast.new(ast.Import_Decl, tok.pos, end_pos(path))
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ import "base:intrinsics"
|
|||||||
|
|
||||||
import "core:c"
|
import "core:c"
|
||||||
|
|
||||||
|
IS_SUPPORTED :: _IS_SUPPORTED
|
||||||
|
|
||||||
result :: enum c.int {
|
result :: enum c.int {
|
||||||
// Use `errno` and `strerror` for more information.
|
// Use `errno` and `strerror` for more information.
|
||||||
FAIL = -1,
|
FAIL = -1,
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#+build !linux
|
||||||
|
#+build !darwin
|
||||||
|
#+build !netbsd
|
||||||
|
#+build !openbsd
|
||||||
|
#+build !freebsd
|
||||||
|
#+build !haiku
|
||||||
|
package posix
|
||||||
|
|
||||||
|
_IS_SUPPORTED :: false
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#+build linux, darwin, netbsd, openbsd, freebsd, haiku
|
||||||
|
package posix
|
||||||
|
|
||||||
|
_IS_SUPPORTED :: true
|
||||||
|
|
||||||
+73
-93
@@ -3086,126 +3086,106 @@ gb_internal void check_shift(CheckerContext *c, Operand *x, Operand *y, Ast *nod
|
|||||||
GB_ASSERT(node->kind == Ast_BinaryExpr);
|
GB_ASSERT(node->kind == Ast_BinaryExpr);
|
||||||
ast_node(be, BinaryExpr, node);
|
ast_node(be, BinaryExpr, node);
|
||||||
|
|
||||||
ExactValue x_val = {};
|
bool y_is_untyped = is_type_untyped(y->type);
|
||||||
if (x->mode == Addressing_Constant) {
|
if (y_is_untyped) {
|
||||||
x_val = exact_value_to_integer(x->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool x_is_untyped = is_type_untyped(x->type);
|
|
||||||
if (!(is_type_integer(x->type) || (x_is_untyped && x_val.kind == ExactValue_Integer))) {
|
|
||||||
gbString err_str = expr_to_string(x->expr);
|
|
||||||
error(node, "Shifted operand '%s' must be an integer", err_str);
|
|
||||||
gb_string_free(err_str);
|
|
||||||
x->mode = Addressing_Invalid;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_type_unsigned(y->type)) {
|
|
||||||
|
|
||||||
} else if (is_type_untyped(y->type)) {
|
|
||||||
convert_to_typed(c, y, t_untyped_integer);
|
convert_to_typed(c, y, t_untyped_integer);
|
||||||
if (y->mode == Addressing_Invalid) {
|
if (y->mode == Addressing_Invalid) {
|
||||||
x->mode = Addressing_Invalid;
|
x->mode = Addressing_Invalid;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!is_type_unsigned(y->type)) {
|
||||||
gbString err_str = expr_to_string(y->expr);
|
gbString y_str = expr_to_string(y->expr);
|
||||||
error(node, "Shift amount '%s' must be an unsigned integer", err_str);
|
error(y->expr, "Shift amount '%s' must be an unsigned integer", y_str);
|
||||||
gb_string_free(err_str);
|
gb_string_free(y_str);
|
||||||
x->mode = Addressing_Invalid;
|
x->mode = Addressing_Invalid;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool x_is_untyped = is_type_untyped(x->type);
|
||||||
|
if (!(x_is_untyped || is_type_integer(x->type))) {
|
||||||
|
gbString x_str = expr_to_string(x->expr);
|
||||||
|
error(x->expr, "Shifted operand '%s' must be an integer", x_str);
|
||||||
|
gb_string_free(x_str);
|
||||||
|
x->mode = Addressing_Invalid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y->mode == Addressing_Constant) {
|
||||||
|
if (big_int_is_neg(&y->value.value_integer)) {
|
||||||
|
gbString y_str = expr_to_string(y->expr);
|
||||||
|
error(y->expr, "Shift amount '%s' cannot be negative", y_str);
|
||||||
|
gb_string_free(y_str);
|
||||||
|
x->mode = Addressing_Invalid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BigInt max_shift = {};
|
||||||
|
big_int_from_u64(&max_shift, MAX_BIG_INT_SHIFT);
|
||||||
|
|
||||||
|
if (big_int_cmp(&y->value.value_integer, &max_shift) > 0) {
|
||||||
|
gbString y_str = expr_to_string(y->expr);
|
||||||
|
error(y->expr, "Shift amount '%s' must be <= %u", y_str, MAX_BIG_INT_SHIFT);
|
||||||
|
gb_string_free(y_str);
|
||||||
|
x->mode = Addressing_Invalid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x->mode == Addressing_Constant) {
|
||||||
|
if (x_is_untyped) {
|
||||||
|
convert_to_typed(c, x, t_untyped_integer);
|
||||||
|
if (x->mode == Addressing_Invalid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
x->expr = node;
|
||||||
|
x->value = exact_value_shift(be->op.kind, exact_value_to_integer(x->value), exact_value_to_integer(y->value));
|
||||||
|
|
||||||
if (x->mode == Addressing_Constant) {
|
|
||||||
if (y->mode == Addressing_Constant) {
|
|
||||||
ExactValue y_val = exact_value_to_integer(y->value);
|
|
||||||
if (y_val.kind != ExactValue_Integer) {
|
|
||||||
gbString err_str = expr_to_string(y->expr);
|
|
||||||
error(node, "Shift amount '%s' must be an unsigned integer", err_str);
|
|
||||||
gb_string_free(err_str);
|
|
||||||
x->mode = Addressing_Invalid;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigInt max_shift = {};
|
|
||||||
big_int_from_u64(&max_shift, MAX_BIG_INT_SHIFT);
|
|
||||||
|
|
||||||
if (big_int_cmp(&y_val.value_integer, &max_shift) > 0) {
|
|
||||||
gbString err_str = expr_to_string(y->expr);
|
|
||||||
error(node, "Shift amount too large: '%s'", err_str);
|
|
||||||
gb_string_free(err_str);
|
|
||||||
x->mode = Addressing_Invalid;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_type_integer(x->type)) {
|
|
||||||
// NOTE(bill): It could be an untyped float but still representable
|
|
||||||
// as an integer
|
|
||||||
x->type = t_untyped_integer;
|
|
||||||
}
|
|
||||||
|
|
||||||
x->expr = node;
|
x->expr = node;
|
||||||
x->value = exact_value_shift(be->op.kind, x_val, y_val);
|
x->value = exact_value_shift(be->op.kind, x->value, y->value);
|
||||||
|
|
||||||
|
check_is_expressible(c, x, x->type);
|
||||||
|
|
||||||
if (is_type_typed(x->type)) {
|
|
||||||
check_is_expressible(c, x, x->type);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenPos pos = ast_token(x->expr).pos;
|
if (y_is_untyped) {
|
||||||
if (x_is_untyped) {
|
convert_to_typed(c, y, t_uint);
|
||||||
if (x->expr != nullptr) {
|
|
||||||
x->expr->tav.is_lhs = true;
|
|
||||||
}
|
|
||||||
x->mode = Addressing_Value;
|
|
||||||
if (type_hint) {
|
|
||||||
if (is_type_integer(type_hint)) {
|
|
||||||
convert_to_typed(c, x, type_hint);
|
|
||||||
} else {
|
|
||||||
gbString x_str = expr_to_string(x->expr);
|
|
||||||
gbString to_type = type_to_string(type_hint);
|
|
||||||
error(node, "Conversion of shifted operand '%s' to '%s' is not allowed", x_str, to_type);
|
|
||||||
gb_string_free(x_str);
|
|
||||||
gb_string_free(to_type);
|
|
||||||
x->mode = Addressing_Invalid;
|
|
||||||
}
|
|
||||||
} else if (!is_type_integer(x->type)) {
|
|
||||||
gbString x_str = expr_to_string(x->expr);
|
|
||||||
error(node, "Non-integer shifted operand '%s' is not allowed", x_str);
|
|
||||||
gb_string_free(x_str);
|
|
||||||
x->mode = Addressing_Invalid;
|
|
||||||
}
|
|
||||||
// x->value = x_val;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (y->mode == Addressing_Constant && big_int_is_neg(&y->value.value_integer)) {
|
|
||||||
gbString err_str = expr_to_string(y->expr);
|
|
||||||
error(node, "Shift amount cannot be negative: '%s'", err_str);
|
|
||||||
gb_string_free(err_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_type_integer(x->type)) {
|
|
||||||
gbString err_str = expr_to_string(x->expr);
|
|
||||||
error(node, "Shift operand '%s' must be an integer", err_str);
|
|
||||||
gb_string_free(err_str);
|
|
||||||
x->mode = Addressing_Invalid;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_type_untyped(y->type)) {
|
if (x->mode == Addressing_Constant) {
|
||||||
convert_to_typed(c, y, t_uint);
|
if (x_is_untyped) {
|
||||||
|
if (type_hint) {
|
||||||
|
if (is_type_integer(type_hint)) {
|
||||||
|
convert_to_typed(c, x, type_hint);
|
||||||
|
} else if (is_type_any(type_hint)) {
|
||||||
|
convert_to_typed(c, x, default_type(t_untyped_integer));
|
||||||
|
} else {
|
||||||
|
gbString x_str = expr_to_string(x->expr);
|
||||||
|
gbString type_str = type_to_string(type_hint);
|
||||||
|
error(x->expr, "Shifted operand '%s' cannot convert to non-integer type '%s'", x_str, type_str);
|
||||||
|
gb_string_free(x_str);
|
||||||
|
gb_string_free(type_str);
|
||||||
|
x->mode = Addressing_Invalid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
check_is_expressible(c, x, default_type(t_untyped_integer));
|
||||||
|
}
|
||||||
|
if (x->mode == Addressing_Invalid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
x->mode = Addressing_Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
x->mode = Addressing_Value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) {
|
gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) {
|
||||||
if (check_is_assignable_to(c, operand, y)) {
|
if (check_is_assignable_to(c, operand, y)) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -66,3 +66,31 @@ Foo :: bit_field uint {
|
|||||||
ok := parser.parse_file(&p, &file)
|
ok := parser.parse_file(&p, &file)
|
||||||
testing.expect(t, ok, "bad parse")
|
testing.expect(t, ok, "bad parse")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test
|
||||||
|
test_parse_parser :: proc(t: ^testing.T) {
|
||||||
|
context.allocator = context.temp_allocator
|
||||||
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
|
pkg, ok := parser.parse_package_from_path(ODIN_ROOT + "core/odin/parser")
|
||||||
|
|
||||||
|
testing.expect(t, ok, "parser.parse_package_from_path failed")
|
||||||
|
|
||||||
|
for key, value in pkg.files {
|
||||||
|
testing.expectf(t, value.syntax_error_count == 0, "%v should contain zero errors", key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@test
|
||||||
|
test_parse_stb_image :: proc(t: ^testing.T) {
|
||||||
|
context.allocator = context.temp_allocator
|
||||||
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
|
pkg, ok := parser.parse_package_from_path(ODIN_ROOT + "vendor/stb/image")
|
||||||
|
|
||||||
|
testing.expect(t, ok, "parser.parse_package_from_path failed")
|
||||||
|
|
||||||
|
for key, value in pkg.files {
|
||||||
|
testing.expectf(t, value.syntax_error_count == 0, "%v should contain zero errors", key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+3
-3
@@ -4105,9 +4105,9 @@ AccelerationStructure_size :: #force_inline proc "c" (self: ^AccelerationStructu
|
|||||||
return msgSend(NS.UInteger, self, "size")
|
return msgSend(NS.UInteger, self, "size")
|
||||||
}
|
}
|
||||||
|
|
||||||
@(objc_type=AccelerationStructure, objc_name="getResourceID")
|
@(objc_type=AccelerationStructure, objc_name="gpuResourceID")
|
||||||
AccelerationStructure_getResourceID :: #force_inline proc "c" (self: ^AccelerationStructure) -> ResourceID {
|
AccelerationStructure_gpuResourceID :: #force_inline proc "c" (self: ^AccelerationStructure) -> ResourceID {
|
||||||
return msgSend(ResourceID, self, "getResourceID")
|
return msgSend(ResourceID, self, "gpuResourceID")
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
Reference in New Issue
Block a user