mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-07 08:08:50 +00:00
#rune "" to ''; Remove infix and postfix call notation
This commit is contained in:
@@ -16,7 +16,7 @@ if %release_mode% EQU 0 ( rem Debug
|
|||||||
)
|
)
|
||||||
|
|
||||||
set compiler_warnings= ^
|
set compiler_warnings= ^
|
||||||
-we4013 -we4706 -we4002 ^
|
-we4013 -we4706 -we4002 -we4133 ^
|
||||||
-wd4100 -wd4101 -wd4127 -wd4189 ^
|
-wd4100 -wd4101 -wd4127 -wd4189 ^
|
||||||
-wd4201 -wd4204 -wd4244 ^
|
-wd4201 -wd4204 -wd4244 ^
|
||||||
-wd4306 ^
|
-wd4306 ^
|
||||||
|
|||||||
+30
-1
@@ -1,5 +1,34 @@
|
|||||||
#import "fmt.odin"
|
#import "fmt.odin"
|
||||||
|
#import "utf8.odin"
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
fmt.println("Hellope, World!")
|
MAX :: 64
|
||||||
|
buf: [MAX]rune
|
||||||
|
backing: [MAX]byte
|
||||||
|
offset: int
|
||||||
|
|
||||||
|
msg := "Hello"
|
||||||
|
count := utf8.rune_count(msg)
|
||||||
|
assert(count <= MAX)
|
||||||
|
runes := buf[:count]
|
||||||
|
|
||||||
|
offset = 0
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
s := msg[offset:]
|
||||||
|
r, len := utf8.decode_rune(s)
|
||||||
|
runes[count-i-1] = r
|
||||||
|
offset += len
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = 0
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
data, len := utf8.encode_rune(runes[i])
|
||||||
|
for j := 0; j < len; j++ {
|
||||||
|
backing[offset+j] = data[j]
|
||||||
|
}
|
||||||
|
offset += len
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse := backing[:count] as string
|
||||||
|
fmt.println(reverse)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
#import "os.odin"
|
#import "os.odin"
|
||||||
#import "opengl.odin" as gl
|
#import "opengl.odin" as gl
|
||||||
|
|
||||||
TWO_HEARTS :: #rune "💕"
|
TWO_HEARTS :: '💕'
|
||||||
|
|
||||||
win32_perf_count_freq := win32.GetQueryPerformanceFrequency()
|
win32_perf_count_freq := win32.GetQueryPerformanceFrequency()
|
||||||
time_now :: proc() -> f64 {
|
time_now :: proc() -> f64 {
|
||||||
|
|||||||
+13
-13
@@ -76,8 +76,8 @@ print_rune_to_buffer :: proc(buf: ^[]byte, r: rune) {
|
|||||||
print_string_to_buffer(buf, b[:n] as string)
|
print_string_to_buffer(buf, b[:n] as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
print_space_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, #rune " ") }
|
print_space_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, ' ') }
|
||||||
print_nl_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, #rune "\n") }
|
print_nl_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, '\n') }
|
||||||
|
|
||||||
__NUM_TO_CHAR_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$"
|
__NUM_TO_CHAR_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$"
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ print_u64_to_buffer :: proc(buffer: ^[]byte, value: u64) {
|
|||||||
buf: [20]byte
|
buf: [20]byte
|
||||||
len := 0
|
len := 0
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
buf[len] = #rune "0"
|
buf[len] = '0'
|
||||||
len++
|
len++
|
||||||
}
|
}
|
||||||
for i > 0 {
|
for i > 0 {
|
||||||
@@ -115,7 +115,7 @@ print_i64_to_buffer :: proc(buffer: ^[]byte, value: i64) {
|
|||||||
neg := i < 0
|
neg := i < 0
|
||||||
if neg {
|
if neg {
|
||||||
i = -i
|
i = -i
|
||||||
print_rune_to_buffer(buffer, #rune "-")
|
print_rune_to_buffer(buffer, '-')
|
||||||
}
|
}
|
||||||
print_u64_to_buffer(buffer, i as u64)
|
print_u64_to_buffer(buffer, i as u64)
|
||||||
}
|
}
|
||||||
@@ -132,7 +132,7 @@ print_i128_to_buffer :: proc(buffer: ^[]byte, value: i128) {
|
|||||||
neg := i < 0
|
neg := i < 0
|
||||||
if neg {
|
if neg {
|
||||||
i = -i
|
i = -i
|
||||||
print_rune_to_buffer(buffer, #rune "-")
|
print_rune_to_buffer(buffer, '-')
|
||||||
}
|
}
|
||||||
print_u128_to_buffer(buffer, i as u128)
|
print_u128_to_buffer(buffer, i as u128)
|
||||||
}
|
}
|
||||||
@@ -142,11 +142,11 @@ print_i128_to_buffer :: proc(buffer: ^[]byte, value: i128) {
|
|||||||
print__f64 :: proc(buffer: ^[]byte, value: f64, decimal_places: int) {
|
print__f64 :: proc(buffer: ^[]byte, value: f64, decimal_places: int) {
|
||||||
f := value
|
f := value
|
||||||
if f == 0 {
|
if f == 0 {
|
||||||
print_rune_to_buffer(buffer, #rune "0")
|
print_rune_to_buffer(buffer, '0')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if f < 0 {
|
if f < 0 {
|
||||||
print_rune_to_buffer(buffer, #rune "-")
|
print_rune_to_buffer(buffer, '-')
|
||||||
f = -f
|
f = -f
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ print__f64 :: proc(buffer: ^[]byte, value: f64, decimal_places: int) {
|
|||||||
print_u64_to_buffer(buffer, i)
|
print_u64_to_buffer(buffer, i)
|
||||||
f -= i as f64
|
f -= i as f64
|
||||||
|
|
||||||
print_rune_to_buffer(buffer, #rune ".")
|
print_rune_to_buffer(buffer, '.')
|
||||||
|
|
||||||
mult: f64 = 10.0
|
mult: f64 = 10.0
|
||||||
for ; decimal_places >= 0; decimal_places-- {
|
for ; decimal_places >= 0; decimal_places-- {
|
||||||
@@ -488,7 +488,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
|||||||
|
|
||||||
bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
|
bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
|
||||||
is_digit :: proc(r: rune) -> bool #inline {
|
is_digit :: proc(r: rune) -> bool #inline {
|
||||||
return r >= #rune "0" && r <= #rune "9"
|
return '0' <= r && r <= '9'
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_int :: proc(s: string, offset: int) -> (int, int) {
|
parse_int :: proc(s: string, offset: int) -> (int, int) {
|
||||||
@@ -501,7 +501,7 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result *= 10
|
result *= 10
|
||||||
result += (c - #rune "0") as int
|
result += (c - '0') as int
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, offset
|
return result, offset
|
||||||
@@ -514,7 +514,7 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
|
|||||||
r := fmt[i] as rune
|
r := fmt[i] as rune
|
||||||
index := implicit_index
|
index := implicit_index
|
||||||
|
|
||||||
if r != #rune "%" {
|
if r != '%' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,7 +523,7 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
|
|||||||
if i < fmt.count {
|
if i < fmt.count {
|
||||||
next := fmt[i] as rune
|
next := fmt[i] as rune
|
||||||
|
|
||||||
if next == #rune "%" {
|
if next == '%' {
|
||||||
print_string_to_buffer(buf, "%")
|
print_string_to_buffer(buf, "%")
|
||||||
i++
|
i++
|
||||||
prev = i
|
prev = i
|
||||||
@@ -582,7 +582,7 @@ bprint :: proc(buf: ^[]byte, args: ..any) -> int {
|
|||||||
bprintln :: proc(buf: ^[]byte, args: ..any) -> int {
|
bprintln :: proc(buf: ^[]byte, args: ..any) -> int {
|
||||||
for i := 0; i < args.count; i++ {
|
for i := 0; i < args.count; i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
append(buf, #rune " ")
|
append(buf, ' ')
|
||||||
}
|
}
|
||||||
print_any_to_buffer(buf, args[i])
|
print_any_to_buffer(buf, args[i])
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
RUNE_ERROR :: #rune "\ufffd"
|
RUNE_ERROR :: '\ufffd'
|
||||||
RUNE_SELF :: 0x80
|
RUNE_SELF :: 0x80
|
||||||
RUNE_BOM :: 0xfeff
|
RUNE_BOM :: 0xfeff
|
||||||
RUNE_EOF :: ~(0 as rune)
|
RUNE_EOF :: ~(0 as rune)
|
||||||
MAX_RUNE :: #rune "\U0010ffff"
|
MAX_RUNE :: '\U0010ffff'
|
||||||
UTF_MAX :: 4
|
UTF_MAX :: 4
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+38
-36
@@ -1,6 +1,8 @@
|
|||||||
#foreign_system_library "user32"
|
#foreign_system_library "user32"
|
||||||
#foreign_system_library "gdi32"
|
#foreign_system_library "gdi32"
|
||||||
|
|
||||||
|
_:= compile_assert(ODIN_OS == "windows")
|
||||||
|
|
||||||
HANDLE :: type rawptr
|
HANDLE :: type rawptr
|
||||||
HWND :: type HANDLE
|
HWND :: type HANDLE
|
||||||
HDC :: type HANDLE
|
HDC :: type HANDLE
|
||||||
@@ -387,43 +389,43 @@ Key_Code :: enum i32 {
|
|||||||
DELETE = 0x2E,
|
DELETE = 0x2E,
|
||||||
HELP = 0x2F,
|
HELP = 0x2F,
|
||||||
|
|
||||||
NUM0 = #rune "0",
|
NUM0 = '0',
|
||||||
NUM1 = #rune "1",
|
NUM1 = '1',
|
||||||
NUM2 = #rune "2",
|
NUM2 = '2',
|
||||||
NUM3 = #rune "3",
|
NUM3 = '3',
|
||||||
NUM4 = #rune "4",
|
NUM4 = '4',
|
||||||
NUM5 = #rune "5",
|
NUM5 = '5',
|
||||||
NUM6 = #rune "6",
|
NUM6 = '6',
|
||||||
NUM7 = #rune "7",
|
NUM7 = '7',
|
||||||
NUM8 = #rune "8",
|
NUM8 = '8',
|
||||||
NUM9 = #rune "9",
|
NUM9 = '9',
|
||||||
|
|
||||||
A = #rune "A",
|
A = 'A',
|
||||||
B = #rune "B",
|
B = 'B',
|
||||||
C = #rune "C",
|
C = 'C',
|
||||||
D = #rune "D",
|
D = 'D',
|
||||||
E = #rune "E",
|
E = 'E',
|
||||||
F = #rune "F",
|
F = 'F',
|
||||||
G = #rune "G",
|
G = 'G',
|
||||||
H = #rune "H",
|
H = 'H',
|
||||||
I = #rune "I",
|
I = 'I',
|
||||||
J = #rune "J",
|
J = 'J',
|
||||||
K = #rune "K",
|
K = 'K',
|
||||||
L = #rune "L",
|
L = 'L',
|
||||||
M = #rune "M",
|
M = 'M',
|
||||||
N = #rune "N",
|
N = 'N',
|
||||||
O = #rune "O",
|
O = 'O',
|
||||||
P = #rune "P",
|
P = 'P',
|
||||||
Q = #rune "Q",
|
Q = 'Q',
|
||||||
R = #rune "R",
|
R = 'R',
|
||||||
S = #rune "S",
|
S = 'S',
|
||||||
T = #rune "T",
|
T = 'T',
|
||||||
U = #rune "U",
|
U = 'U',
|
||||||
V = #rune "V",
|
V = 'V',
|
||||||
W = #rune "W",
|
W = 'W',
|
||||||
X = #rune "X",
|
X = 'X',
|
||||||
Y = #rune "Y",
|
Y = 'Y',
|
||||||
Z = #rune "Z",
|
Z = 'Z',
|
||||||
|
|
||||||
LWIN = 0x5B,
|
LWIN = 0x5B,
|
||||||
RWIN = 0x5C,
|
RWIN = 0x5C,
|
||||||
|
|||||||
+3
-3
@@ -11,8 +11,8 @@ GB_STATIC_ASSERT(ARRAY_GROW_FORMULA(0) > 0);
|
|||||||
typedef Array(void) ArrayVoid;
|
typedef Array(void) ArrayVoid;
|
||||||
|
|
||||||
#define array_init_reserve(x_, allocator_, init_capacity_) do { \
|
#define array_init_reserve(x_, allocator_, init_capacity_) do { \
|
||||||
GB_ASSERT((x_) != NULL); \
|
|
||||||
void **e = cast(void **)&((x_)->e); \
|
void **e = cast(void **)&((x_)->e); \
|
||||||
|
GB_ASSERT((x_) != NULL); \
|
||||||
(x_)->allocator = (allocator_); \
|
(x_)->allocator = (allocator_); \
|
||||||
(x_)->count = 0; \
|
(x_)->count = 0; \
|
||||||
(x_)->capacity = (init_capacity_); \
|
(x_)->capacity = (init_capacity_); \
|
||||||
@@ -20,8 +20,8 @@ typedef Array(void) ArrayVoid;
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define array_init_count(x_, allocator_, init_count_) do { \
|
#define array_init_count(x_, allocator_, init_count_) do { \
|
||||||
GB_ASSERT((x_) != NULL); \
|
|
||||||
void **e = cast(void **)&((x_)->e); \
|
void **e = cast(void **)&((x_)->e); \
|
||||||
|
GB_ASSERT((x_) != NULL); \
|
||||||
(x_)->allocator = (allocator_); \
|
(x_)->allocator = (allocator_); \
|
||||||
(x_)->count = (init_count_); \
|
(x_)->count = (init_count_); \
|
||||||
(x_)->capacity = (init_count_); \
|
(x_)->capacity = (init_count_); \
|
||||||
@@ -67,8 +67,8 @@ typedef Array(void) ArrayVoid;
|
|||||||
|
|
||||||
|
|
||||||
void array__set_capacity(void *ptr, isize capacity, isize element_size) {
|
void array__set_capacity(void *ptr, isize capacity, isize element_size) {
|
||||||
GB_ASSERT(ptr != NULL);
|
|
||||||
ArrayVoid *x = cast(ArrayVoid *)ptr;
|
ArrayVoid *x = cast(ArrayVoid *)ptr;
|
||||||
|
GB_ASSERT(ptr != NULL);
|
||||||
|
|
||||||
GB_ASSERT(element_size > 0);
|
GB_ASSERT(element_size > 0);
|
||||||
|
|
||||||
|
|||||||
+12
-4
@@ -271,8 +271,9 @@ CycleChecker *cycle_checker_add(CycleChecker *cc, Entity *e) {
|
|||||||
if (cc->path.e == NULL) {
|
if (cc->path.e == NULL) {
|
||||||
array_init(&cc->path, heap_allocator());
|
array_init(&cc->path, heap_allocator());
|
||||||
}
|
}
|
||||||
GB_ASSERT(e != NULL && e->kind == Entity_TypeName);
|
if (e != NULL && e->kind == Entity_TypeName) {
|
||||||
array_add(&cc->path, e);
|
array_add(&cc->path, e);
|
||||||
|
}
|
||||||
return cc;
|
return cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,6 +509,11 @@ void add_global_constant(gbAllocator a, String name, Type *type, ExactValue valu
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void add_global_string_constant(gbAllocator a, String name, String value) {
|
||||||
|
add_global_constant(a, name, t_untyped_string, make_exact_value_string(value));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void init_universal_scope(void) {
|
void init_universal_scope(void) {
|
||||||
// NOTE(bill): No need to free these
|
// NOTE(bill): No need to free these
|
||||||
@@ -528,9 +534,11 @@ void init_universal_scope(void) {
|
|||||||
|
|
||||||
add_global_entity(make_entity_nil(a, str_lit("nil"), t_untyped_nil));
|
add_global_entity(make_entity_nil(a, str_lit("nil"), t_untyped_nil));
|
||||||
|
|
||||||
add_global_constant(a, str_lit("ODIN_OS"), t_untyped_string, make_exact_value_string(str_lit("windows")));
|
add_global_string_constant(a, str_lit("ODIN_OS"), str_lit("windows"));
|
||||||
add_global_constant(a, str_lit("ODIN_ARCH"), t_untyped_string, make_exact_value_string(str_lit("amd64")));
|
add_global_string_constant(a, str_lit("ODIN_ARCH"), str_lit("amd64"));
|
||||||
add_global_constant(a, str_lit("ODIN_VERSION"), t_untyped_string, make_exact_value_string(str_lit(VERSION_STRING)));
|
add_global_string_constant(a, str_lit("ODIN_VENDOR"), str_lit("odin"));
|
||||||
|
add_global_string_constant(a, str_lit("ODIN_VERSION"), str_lit(VERSION_STRING));
|
||||||
|
add_global_string_constant(a, str_lit("ODIN_ENDIAN"), str_lit("little"));
|
||||||
|
|
||||||
|
|
||||||
// Builtin Procedures
|
// Builtin Procedures
|
||||||
|
|||||||
+14
-18
@@ -713,12 +713,10 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
|
|||||||
if (o.mode != Addressing_Invalid) {
|
if (o.mode != Addressing_Invalid) {
|
||||||
iota = o.value;
|
iota = o.value;
|
||||||
} else {
|
} else {
|
||||||
Token add_token = {Token_Add};
|
iota = exact_binary_operator_value(Token_Add, iota, make_exact_value_integer(1));
|
||||||
iota = exact_binary_operator_value(add_token, iota, make_exact_value_integer(1));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Token add_token = {Token_Add};
|
iota = exact_binary_operator_value(Token_Add, iota, make_exact_value_integer(1));
|
||||||
iota = exact_binary_operator_value(add_token, iota, make_exact_value_integer(1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1492,7 +1490,7 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
|
|||||||
if (is_type_unsigned(type)) {
|
if (is_type_unsigned(type)) {
|
||||||
precision = cast(i32)(8 * type_size_of(c->sizes, c->allocator, type));
|
precision = cast(i32)(8 * type_size_of(c->sizes, c->allocator, type));
|
||||||
}
|
}
|
||||||
o->value = exact_unary_operator_value(op, o->value, precision);
|
o->value = exact_unary_operator_value(op.kind, o->value, precision);
|
||||||
|
|
||||||
if (is_type_typed(type)) {
|
if (is_type_typed(type)) {
|
||||||
if (node != NULL) {
|
if (node != NULL) {
|
||||||
@@ -1558,7 +1556,7 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
|
|||||||
} else {
|
} else {
|
||||||
if (x->mode == Addressing_Constant &&
|
if (x->mode == Addressing_Constant &&
|
||||||
y->mode == Addressing_Constant) {
|
y->mode == Addressing_Constant) {
|
||||||
x->value = make_exact_value_bool(compare_exact_values(op, x->value, y->value));
|
x->value = make_exact_value_bool(compare_exact_values(op.kind, x->value, y->value));
|
||||||
} else {
|
} else {
|
||||||
x->mode = Addressing_Value;
|
x->mode = Addressing_Value;
|
||||||
|
|
||||||
@@ -1645,7 +1643,7 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) {
|
|||||||
x->type = t_untyped_integer;
|
x->type = t_untyped_integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
x->value = exact_value_shift(be->op, x_val, make_exact_value_integer(amount));
|
x->value = exact_value_shift(be->op.kind, x_val, make_exact_value_integer(amount));
|
||||||
|
|
||||||
if (is_type_typed(x->type)) {
|
if (is_type_typed(x->type)) {
|
||||||
check_is_expressible(c, x, base_type(x->type));
|
check_is_expressible(c, x, base_type(x->type));
|
||||||
@@ -2168,7 +2166,7 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
|||||||
if (op.kind == Token_Quo && is_type_integer(type)) {
|
if (op.kind == Token_Quo && is_type_integer(type)) {
|
||||||
op.kind = Token_QuoEq; // NOTE(bill): Hack to get division of integers
|
op.kind = Token_QuoEq; // NOTE(bill): Hack to get division of integers
|
||||||
}
|
}
|
||||||
x->value = exact_binary_operator_value(op, a, b);
|
x->value = exact_binary_operator_value(op.kind, a, b);
|
||||||
if (is_type_typed(type)) {
|
if (is_type_typed(type)) {
|
||||||
if (node != NULL) {
|
if (node != NULL) {
|
||||||
x->expr = node;
|
x->expr = node;
|
||||||
@@ -3166,7 +3164,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
case BuiltinProc_min: {
|
case BuiltinProc_min: {
|
||||||
// min :: proc(a, b: comparable) -> comparable
|
// min :: proc(a, b: comparable) -> comparable
|
||||||
Type *type = base_type(operand->type);
|
Type *type = base_type(operand->type);
|
||||||
if (!is_type_comparable(type) || !is_type_numeric(type)) {
|
if (!is_type_comparable(type) || !(is_type_numeric(type) || is_type_string(type))) {
|
||||||
gbString type_str = type_to_string(operand->type);
|
gbString type_str = type_to_string(operand->type);
|
||||||
error(ast_node_token(call),
|
error(ast_node_token(call),
|
||||||
"Expected a comparable numeric type to `min`, got `%s`",
|
"Expected a comparable numeric type to `min`, got `%s`",
|
||||||
@@ -3182,7 +3180,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
if (b.mode == Addressing_Invalid) {
|
if (b.mode == Addressing_Invalid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!is_type_comparable(b.type) || !is_type_numeric(type)) {
|
if (!is_type_comparable(b.type) || !(is_type_numeric(b.type) || is_type_string(b.type))) {
|
||||||
gbString type_str = type_to_string(b.type);
|
gbString type_str = type_to_string(b.type);
|
||||||
error(ast_node_token(call),
|
error(ast_node_token(call),
|
||||||
"Expected a comparable numeric type to `min`, got `%s`",
|
"Expected a comparable numeric type to `min`, got `%s`",
|
||||||
@@ -3195,10 +3193,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
b.mode == Addressing_Constant) {
|
b.mode == Addressing_Constant) {
|
||||||
ExactValue x = a.value;
|
ExactValue x = a.value;
|
||||||
ExactValue y = b.value;
|
ExactValue y = b.value;
|
||||||
Token lt = {Token_Lt};
|
|
||||||
|
|
||||||
operand->mode = Addressing_Constant;
|
operand->mode = Addressing_Constant;
|
||||||
if (compare_exact_values(lt, x, y)) {
|
if (compare_exact_values(Token_Lt, x, y)) {
|
||||||
operand->value = x;
|
operand->value = x;
|
||||||
operand->type = a.type;
|
operand->type = a.type;
|
||||||
} else {
|
} else {
|
||||||
@@ -3235,10 +3232,10 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
case BuiltinProc_max: {
|
case BuiltinProc_max: {
|
||||||
// min :: proc(a, b: comparable) -> comparable
|
// min :: proc(a, b: comparable) -> comparable
|
||||||
Type *type = base_type(operand->type);
|
Type *type = base_type(operand->type);
|
||||||
if (!is_type_comparable(type) || !is_type_numeric(type)) {
|
if (!is_type_comparable(type) || !(is_type_numeric(type) || is_type_string(type))) {
|
||||||
gbString type_str = type_to_string(operand->type);
|
gbString type_str = type_to_string(operand->type);
|
||||||
error(ast_node_token(call),
|
error(ast_node_token(call),
|
||||||
"Expected a comparable numeric type to `max`, got `%s`",
|
"Expected a comparable numeric or string type to `max`, got `%s`",
|
||||||
type_str);
|
type_str);
|
||||||
gb_string_free(type_str);
|
gb_string_free(type_str);
|
||||||
return false;
|
return false;
|
||||||
@@ -3251,10 +3248,10 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
if (b.mode == Addressing_Invalid) {
|
if (b.mode == Addressing_Invalid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!is_type_comparable(b.type) || !is_type_numeric(type)) {
|
if (!is_type_comparable(b.type) || !(is_type_numeric(type) || is_type_string(type))) {
|
||||||
gbString type_str = type_to_string(b.type);
|
gbString type_str = type_to_string(b.type);
|
||||||
error(ast_node_token(call),
|
error(ast_node_token(call),
|
||||||
"Expected a comparable numeric type to `max`, got `%s`",
|
"Expected a comparable numeric or string type to `max`, got `%s`",
|
||||||
type_str);
|
type_str);
|
||||||
gb_string_free(type_str);
|
gb_string_free(type_str);
|
||||||
return false;
|
return false;
|
||||||
@@ -3264,10 +3261,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
b.mode == Addressing_Constant) {
|
b.mode == Addressing_Constant) {
|
||||||
ExactValue x = a.value;
|
ExactValue x = a.value;
|
||||||
ExactValue y = b.value;
|
ExactValue y = b.value;
|
||||||
Token gt = {Token_Gt};
|
|
||||||
|
|
||||||
operand->mode = Addressing_Constant;
|
operand->mode = Addressing_Constant;
|
||||||
if (compare_exact_values(gt, x, y)) {
|
if (compare_exact_values(Token_Gt, x, y)) {
|
||||||
operand->value = x;
|
operand->value = x;
|
||||||
operand->type = a.type;
|
operand->type = a.type;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+2
-1
@@ -683,7 +683,8 @@ bool is_type_comparable(Type *t) {
|
|||||||
return false;
|
return false;
|
||||||
} break;
|
} break;
|
||||||
case Type_Array:
|
case Type_Array:
|
||||||
return is_type_comparable(t->Array.elem);
|
return false;
|
||||||
|
// return is_type_comparable(t->Array.elem);
|
||||||
case Type_Vector:
|
case Type_Vector:
|
||||||
return is_type_comparable(t->Vector.elem);
|
return is_type_comparable(t->Vector.elem);
|
||||||
case Type_Proc:
|
case Type_Proc:
|
||||||
|
|||||||
+13
-7
@@ -14,14 +14,19 @@ gb_global bool global_module_path_set = false;
|
|||||||
|
|
||||||
|
|
||||||
String get_module_dir() {
|
String get_module_dir() {
|
||||||
|
String path = global_module_path;
|
||||||
|
Array(wchar_t) path_buf;
|
||||||
|
isize len, i;
|
||||||
|
gbTempArenaMemory tmp;
|
||||||
|
wchar_t *text;
|
||||||
|
|
||||||
if (global_module_path_set) {
|
if (global_module_path_set) {
|
||||||
return global_module_path;
|
return global_module_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array(wchar_t) path_buf;
|
|
||||||
array_init_count(&path_buf, heap_allocator(), 300);
|
array_init_count(&path_buf, heap_allocator(), 300);
|
||||||
|
|
||||||
isize len = 0;
|
len = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
len = GetModuleFileNameW(NULL, &path_buf.e[0], path_buf.count);
|
len = GetModuleFileNameW(NULL, &path_buf.e[0], path_buf.count);
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
@@ -33,13 +38,13 @@ String get_module_dir() {
|
|||||||
array_resize(&path_buf, 2*path_buf.count + 300);
|
array_resize(&path_buf, 2*path_buf.count + 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
|
tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
|
||||||
|
|
||||||
wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
|
text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
|
||||||
|
|
||||||
GetModuleFileNameW(NULL, text, len);
|
GetModuleFileNameW(NULL, text, len);
|
||||||
String path = string16_to_string(heap_allocator(), make_string16(text, len));
|
path = string16_to_string(heap_allocator(), make_string16(text, len));
|
||||||
for (isize i = path.len-1; i >= 0; i--) {
|
for (i = path.len-1; i >= 0; i--) {
|
||||||
u8 c = path.text[i];
|
u8 c = path.text[i];
|
||||||
if (c == '/' || c == '\\') {
|
if (c == '/' || c == '\\') {
|
||||||
break;
|
break;
|
||||||
@@ -141,8 +146,9 @@ i16 f32_to_f16(f32 value) {
|
|||||||
if (e > 30) {
|
if (e > 30) {
|
||||||
float volatile f = 1e12f;
|
float volatile f = 1e12f;
|
||||||
int j;
|
int j;
|
||||||
for (j = 0; j < 10; j++)
|
for (j = 0; j < 10; j++) {
|
||||||
f *= f; /* NOTE(bill): Cause overflow */
|
f *= f; /* NOTE(bill): Cause overflow */
|
||||||
|
}
|
||||||
|
|
||||||
return cast(i16)(s | 0x7c00);
|
return cast(i16)(s | 0x7c00);
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-18
@@ -148,8 +148,8 @@ ExactValue exact_value_to_float(ExactValue v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ExactValue exact_unary_operator_value(Token op, ExactValue v, i32 precision) {
|
ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision) {
|
||||||
switch (op.kind) {
|
switch (op) {
|
||||||
case Token_Add: {
|
case Token_Add: {
|
||||||
switch (v.kind) {
|
switch (v.kind) {
|
||||||
case ExactValue_Invalid:
|
case ExactValue_Invalid:
|
||||||
@@ -207,7 +207,7 @@ ExactValue exact_unary_operator_value(Token op, ExactValue v, i32 precision) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
failure:
|
failure:
|
||||||
GB_PANIC("Invalid unary operation, %.*s", LIT(token_strings[op.kind]));
|
GB_PANIC("Invalid unary operation, %.*s", LIT(token_strings[op]));
|
||||||
|
|
||||||
ExactValue error_value = {0};
|
ExactValue error_value = {0};
|
||||||
return error_value;
|
return error_value;
|
||||||
@@ -270,7 +270,7 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bill): Allow for pointer arithmetic? Or are pointer slices good enough?
|
// TODO(bill): Allow for pointer arithmetic? Or are pointer slices good enough?
|
||||||
ExactValue exact_binary_operator_value(Token op, ExactValue x, ExactValue y) {
|
ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y) {
|
||||||
match_exact_values(&x, &y);
|
match_exact_values(&x, &y);
|
||||||
|
|
||||||
switch (x.kind) {
|
switch (x.kind) {
|
||||||
@@ -278,7 +278,7 @@ ExactValue exact_binary_operator_value(Token op, ExactValue x, ExactValue y) {
|
|||||||
return x;
|
return x;
|
||||||
|
|
||||||
case ExactValue_Bool:
|
case ExactValue_Bool:
|
||||||
switch (op.kind) {
|
switch (op) {
|
||||||
case Token_CmpAnd: return make_exact_value_bool(x.value_bool && y.value_bool);
|
case Token_CmpAnd: return make_exact_value_bool(x.value_bool && y.value_bool);
|
||||||
case Token_CmpOr: return make_exact_value_bool(x.value_bool || y.value_bool);
|
case Token_CmpOr: return make_exact_value_bool(x.value_bool || y.value_bool);
|
||||||
case Token_And: return make_exact_value_bool(x.value_bool & y.value_bool);
|
case Token_And: return make_exact_value_bool(x.value_bool & y.value_bool);
|
||||||
@@ -291,7 +291,7 @@ ExactValue exact_binary_operator_value(Token op, ExactValue x, ExactValue y) {
|
|||||||
i64 a = x.value_integer;
|
i64 a = x.value_integer;
|
||||||
i64 b = y.value_integer;
|
i64 b = y.value_integer;
|
||||||
i64 c = 0;
|
i64 c = 0;
|
||||||
switch (op.kind) {
|
switch (op) {
|
||||||
case Token_Add: c = a + b; break;
|
case Token_Add: c = a + b; break;
|
||||||
case Token_Sub: c = a - b; break;
|
case Token_Sub: c = a - b; break;
|
||||||
case Token_Mul: c = a * b; break;
|
case Token_Mul: c = a * b; break;
|
||||||
@@ -312,7 +312,7 @@ ExactValue exact_binary_operator_value(Token op, ExactValue x, ExactValue y) {
|
|||||||
case ExactValue_Float: {
|
case ExactValue_Float: {
|
||||||
f64 a = x.value_float;
|
f64 a = x.value_float;
|
||||||
f64 b = y.value_float;
|
f64 b = y.value_float;
|
||||||
switch (op.kind) {
|
switch (op) {
|
||||||
case Token_Add: return make_exact_value_float(a + b);
|
case Token_Add: return make_exact_value_float(a + b);
|
||||||
case Token_Sub: return make_exact_value_float(a - b);
|
case Token_Sub: return make_exact_value_float(a - b);
|
||||||
case Token_Mul: return make_exact_value_float(a * b);
|
case Token_Mul: return make_exact_value_float(a * b);
|
||||||
@@ -324,22 +324,22 @@ ExactValue exact_binary_operator_value(Token op, ExactValue x, ExactValue y) {
|
|||||||
|
|
||||||
error:
|
error:
|
||||||
ExactValue error_value = {0};
|
ExactValue error_value = {0};
|
||||||
// gb_printf_err("Invalid binary operation: %s\n", token_kind_to_string(op.kind));
|
// gb_printf_err("Invalid binary operation: %s\n", token_kind_to_string(op));
|
||||||
return error_value;
|
return error_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline ExactValue exact_value_add(ExactValue x, ExactValue y) { Token op = {Token_Add}; return exact_binary_operator_value(op, x, y); }
|
gb_inline ExactValue exact_value_add(ExactValue x, ExactValue y) { return exact_binary_operator_value(Token_Add, x, y); }
|
||||||
gb_inline ExactValue exact_value_sub(ExactValue x, ExactValue y) { Token op = {Token_Sub}; return exact_binary_operator_value(op, x, y); }
|
gb_inline ExactValue exact_value_sub(ExactValue x, ExactValue y) { return exact_binary_operator_value(Token_Sub, x, y); }
|
||||||
gb_inline ExactValue exact_value_mul(ExactValue x, ExactValue y) { Token op = {Token_Mul}; return exact_binary_operator_value(op, x, y); }
|
gb_inline ExactValue exact_value_mul(ExactValue x, ExactValue y) { return exact_binary_operator_value(Token_Mul, x, y); }
|
||||||
gb_inline ExactValue exact_value_quo(ExactValue x, ExactValue y) { Token op = {Token_Quo}; return exact_binary_operator_value(op, x, y); }
|
gb_inline ExactValue exact_value_quo(ExactValue x, ExactValue y) { return exact_binary_operator_value(Token_Quo, x, y); }
|
||||||
gb_inline ExactValue exact_value_shift(Token op, ExactValue x, ExactValue y) { return exact_binary_operator_value(op, x, y); }
|
gb_inline ExactValue exact_value_shift(TokenKind op, ExactValue x, ExactValue y) { return exact_binary_operator_value(op, x, y); }
|
||||||
|
|
||||||
|
|
||||||
i32 cmp_f64(f64 a, f64 b) {
|
i32 cmp_f64(f64 a, f64 b) {
|
||||||
return (a > b) - (a < b);
|
return (a > b) - (a < b);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool compare_exact_values(Token op, ExactValue x, ExactValue y) {
|
bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
|
||||||
match_exact_values(&x, &y);
|
match_exact_values(&x, &y);
|
||||||
|
|
||||||
switch (x.kind) {
|
switch (x.kind) {
|
||||||
@@ -347,7 +347,7 @@ bool compare_exact_values(Token op, ExactValue x, ExactValue y) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
case ExactValue_Bool:
|
case ExactValue_Bool:
|
||||||
switch (op.kind) {
|
switch (op) {
|
||||||
case Token_CmpEq: return x.value_bool == y.value_bool;
|
case Token_CmpEq: return x.value_bool == y.value_bool;
|
||||||
case Token_NotEq: return x.value_bool != y.value_bool;
|
case Token_NotEq: return x.value_bool != y.value_bool;
|
||||||
}
|
}
|
||||||
@@ -356,7 +356,7 @@ bool compare_exact_values(Token op, ExactValue x, ExactValue y) {
|
|||||||
case ExactValue_Integer: {
|
case ExactValue_Integer: {
|
||||||
i64 a = x.value_integer;
|
i64 a = x.value_integer;
|
||||||
i64 b = y.value_integer;
|
i64 b = y.value_integer;
|
||||||
switch (op.kind) {
|
switch (op) {
|
||||||
case Token_CmpEq: return a == b;
|
case Token_CmpEq: return a == b;
|
||||||
case Token_NotEq: return a != b;
|
case Token_NotEq: return a != b;
|
||||||
case Token_Lt: return a < b;
|
case Token_Lt: return a < b;
|
||||||
@@ -369,7 +369,7 @@ bool compare_exact_values(Token op, ExactValue x, ExactValue y) {
|
|||||||
case ExactValue_Float: {
|
case ExactValue_Float: {
|
||||||
f64 a = x.value_float;
|
f64 a = x.value_float;
|
||||||
f64 b = y.value_float;
|
f64 b = y.value_float;
|
||||||
switch (op.kind) {
|
switch (op) {
|
||||||
case Token_CmpEq: return cmp_f64(a, b) == 0;
|
case Token_CmpEq: return cmp_f64(a, b) == 0;
|
||||||
case Token_NotEq: return cmp_f64(a, b) != 0;
|
case Token_NotEq: return cmp_f64(a, b) != 0;
|
||||||
case Token_Lt: return cmp_f64(a, b) < 0;
|
case Token_Lt: return cmp_f64(a, b) < 0;
|
||||||
@@ -384,7 +384,7 @@ bool compare_exact_values(Token op, ExactValue x, ExactValue y) {
|
|||||||
String b = y.value_string;
|
String b = y.value_string;
|
||||||
isize len = gb_min(a.len, b.len);
|
isize len = gb_min(a.len, b.len);
|
||||||
// TODO(bill): gb_memcompare is used because the strings are UTF-8
|
// TODO(bill): gb_memcompare is used because the strings are UTF-8
|
||||||
switch (op.kind) {
|
switch (op) {
|
||||||
case Token_CmpEq: return gb_memcompare(a.text, b.text, len) == 0;
|
case Token_CmpEq: return gb_memcompare(a.text, b.text, len) == 0;
|
||||||
case Token_NotEq: return gb_memcompare(a.text, b.text, len) != 0;
|
case Token_NotEq: return gb_memcompare(a.text, b.text, len) != 0;
|
||||||
case Token_Lt: return gb_memcompare(a.text, b.text, len) < 0;
|
case Token_Lt: return gb_memcompare(a.text, b.text, len) < 0;
|
||||||
|
|||||||
@@ -243,6 +243,7 @@ void _J2(MAP_PROC,set)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
|
|||||||
|
|
||||||
|
|
||||||
void _J2(MAP_PROC,_erase)(MAP_NAME *h, MapFindResult fr) {
|
void _J2(MAP_PROC,_erase)(MAP_NAME *h, MapFindResult fr) {
|
||||||
|
MapFindResult last;
|
||||||
if (fr.entry_prev < 0) {
|
if (fr.entry_prev < 0) {
|
||||||
h->hashes.e[fr.hash_index] = h->entries.e[fr.entry_index].next;
|
h->hashes.e[fr.hash_index] = h->entries.e[fr.entry_index].next;
|
||||||
} else {
|
} else {
|
||||||
@@ -253,7 +254,7 @@ void _J2(MAP_PROC,_erase)(MAP_NAME *h, MapFindResult fr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
h->entries.e[fr.entry_index] = h->entries.e[h->entries.count-1];
|
h->entries.e[fr.entry_index] = h->entries.e[h->entries.count-1];
|
||||||
MapFindResult last = _J2(MAP_PROC,_find)(h, h->entries.e[fr.entry_index].key);
|
last = _J2(MAP_PROC,_find)(h, h->entries.e[fr.entry_index].key);
|
||||||
if (last.entry_prev >= 0) {
|
if (last.entry_prev >= 0) {
|
||||||
h->entries.e[last.entry_prev].next = fr.entry_index;
|
h->entries.e[last.entry_prev].next = fr.entry_index;
|
||||||
} else {
|
} else {
|
||||||
@@ -314,11 +315,13 @@ void _J2(MAP_PROC,multi_get_all)(MAP_NAME *h, HashKey key, MAP_TYPE *items) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _J2(MAP_PROC,multi_insert)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
|
void _J2(MAP_PROC,multi_insert)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
|
||||||
|
MapFindResult fr;
|
||||||
|
isize i;
|
||||||
if (h->hashes.count == 0) {
|
if (h->hashes.count == 0) {
|
||||||
_J2(MAP_PROC,grow)(h);
|
_J2(MAP_PROC,grow)(h);
|
||||||
}
|
}
|
||||||
MapFindResult fr = _J2(MAP_PROC,_find)(h, key);
|
fr = _J2(MAP_PROC,_find)(h, key);
|
||||||
isize i = _J2(MAP_PROC,_add_entry)(h, key);
|
i = _J2(MAP_PROC,_add_entry)(h, key);
|
||||||
if (fr.entry_prev < 0) {
|
if (fr.entry_prev < 0) {
|
||||||
h->hashes.e[fr.hash_index] = i;
|
h->hashes.e[fr.hash_index] = i;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+56
-96
@@ -86,13 +86,6 @@ typedef enum StmtStateFlag {
|
|||||||
StmtStateFlag_no_bounds_check = GB_BIT(1),
|
StmtStateFlag_no_bounds_check = GB_BIT(1),
|
||||||
} StmtStateFlag;
|
} StmtStateFlag;
|
||||||
|
|
||||||
|
|
||||||
typedef enum CallExprKind {
|
|
||||||
CallExpr_Prefix, // call(...)
|
|
||||||
CallExpr_Postfix, // a'call
|
|
||||||
CallExpr_Infix, // a ''call b
|
|
||||||
} CallExprKind;
|
|
||||||
|
|
||||||
AstNodeArray make_ast_node_array(AstFile *f) {
|
AstNodeArray make_ast_node_array(AstFile *f) {
|
||||||
AstNodeArray a;
|
AstNodeArray a;
|
||||||
array_init(&a, gb_arena_allocator(&f->arena));
|
array_init(&a, gb_arena_allocator(&f->arena));
|
||||||
@@ -134,7 +127,6 @@ AST_NODE_KIND(_ExprBegin, "", i32) \
|
|||||||
AstNodeArray args; \
|
AstNodeArray args; \
|
||||||
Token open, close; \
|
Token open, close; \
|
||||||
Token ellipsis; \
|
Token ellipsis; \
|
||||||
CallExprKind kind; \
|
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(SliceExpr, "slice expression", struct { \
|
AST_NODE_KIND(SliceExpr, "slice expression", struct { \
|
||||||
AstNode *expr; \
|
AstNode *expr; \
|
||||||
@@ -256,6 +248,7 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
|
|||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(ImportDecl, "import declaration", struct { \
|
AST_NODE_KIND(ImportDecl, "import declaration", struct { \
|
||||||
Token token, relpath; \
|
Token token, relpath; \
|
||||||
|
String os, arch; \
|
||||||
String fullpath; \
|
String fullpath; \
|
||||||
Token import_name; \
|
Token import_name; \
|
||||||
bool is_load; \
|
bool is_load; \
|
||||||
@@ -959,11 +952,15 @@ AstNode *make_type_decl(AstFile *f, Token token, AstNode *name, AstNode *type) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *make_import_decl(AstFile *f, Token token, Token relpath, Token import_name, bool is_load) {
|
AstNode *make_import_decl(AstFile *f, Token token, Token relpath, Token import_name,
|
||||||
|
String os, String arch,
|
||||||
|
bool is_load) {
|
||||||
AstNode *result = make_node(f, AstNode_ImportDecl);
|
AstNode *result = make_node(f, AstNode_ImportDecl);
|
||||||
result->ImportDecl.token = token;
|
result->ImportDecl.token = token;
|
||||||
result->ImportDecl.relpath = relpath;
|
result->ImportDecl.relpath = relpath;
|
||||||
result->ImportDecl.import_name = import_name;
|
result->ImportDecl.import_name = import_name;
|
||||||
|
result->ImportDecl.os = os;
|
||||||
|
result->ImportDecl.arch = arch;
|
||||||
result->ImportDecl.is_load = is_load;
|
result->ImportDecl.is_load = is_load;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1374,19 +1371,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|||||||
case Token_Hash: {
|
case Token_Hash: {
|
||||||
Token token = expect_token(f, Token_Hash);
|
Token token = expect_token(f, Token_Hash);
|
||||||
Token name = expect_token(f, Token_Identifier);
|
Token name = expect_token(f, Token_Identifier);
|
||||||
if (str_eq(name.string, str_lit("rune"))) {
|
if (str_eq(name.string, str_lit("file"))) {
|
||||||
if (f->curr_token.kind == Token_String) {
|
|
||||||
Token *s = &f->curr_token;
|
|
||||||
|
|
||||||
if (gb_utf8_strnlen(s->string.text, s->string.len) != 1) {
|
|
||||||
syntax_error(*s, "Invalid rune literal %.*s", LIT(s->string));
|
|
||||||
}
|
|
||||||
s->kind = Token_Rune; // NOTE(bill): Change it
|
|
||||||
} else {
|
|
||||||
expect_token(f, Token_String);
|
|
||||||
}
|
|
||||||
operand = parse_operand(f, lhs);
|
|
||||||
} else if (str_eq(name.string, str_lit("file"))) {
|
|
||||||
Token token = name;
|
Token token = name;
|
||||||
token.kind = Token_String;
|
token.kind = Token_String;
|
||||||
token.string = token.pos.file;
|
token.string = token.pos.file;
|
||||||
@@ -1513,19 +1498,6 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
|
|||||||
bool loop = true;
|
bool loop = true;
|
||||||
while (loop) {
|
while (loop) {
|
||||||
switch (f->curr_token.kind) {
|
switch (f->curr_token.kind) {
|
||||||
|
|
||||||
case Token_Prime: {
|
|
||||||
Token op = expect_token(f, Token_Prime);
|
|
||||||
if (lhs) {
|
|
||||||
// TODO(bill): Handle this
|
|
||||||
}
|
|
||||||
AstNode *proc = parse_identifier(f);
|
|
||||||
AstNodeArray args;
|
|
||||||
array_init_reserve(&args, gb_arena_allocator(&f->arena), 1);
|
|
||||||
array_add(&args, operand);
|
|
||||||
operand = make_call_expr(f, proc, args, ast_node_token(operand), op, empty_token);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case Token_OpenParen: {
|
case Token_OpenParen: {
|
||||||
if (lhs) {
|
if (lhs) {
|
||||||
// TODO(bill): Handle this shit! Is this even allowed in this language?!
|
// TODO(bill): Handle this shit! Is this even allowed in this language?!
|
||||||
@@ -1680,13 +1652,11 @@ i32 token_precedence(Token t) {
|
|||||||
case Token_Shl:
|
case Token_Shl:
|
||||||
case Token_Shr:
|
case Token_Shr:
|
||||||
return 5;
|
return 5;
|
||||||
case Token_DoublePrime:
|
|
||||||
return 6;
|
|
||||||
case Token_as:
|
case Token_as:
|
||||||
case Token_transmute:
|
case Token_transmute:
|
||||||
case Token_down_cast:
|
case Token_down_cast:
|
||||||
case Token_union_cast:
|
case Token_union_cast:
|
||||||
return 7;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1708,28 +1678,6 @@ AstNode *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (op.kind) {
|
switch (op.kind) {
|
||||||
case Token_DoublePrime: {
|
|
||||||
// TODO(bill): Properly define semantic for in-fix and post-fix calls
|
|
||||||
AstNode *proc = parse_identifier(f);
|
|
||||||
/* if (f->curr_token.kind == Token_OpenParen) {
|
|
||||||
AstNode *call = parse_call_expr(f, proc);
|
|
||||||
array_add(&call->CallExpr.args, expression);
|
|
||||||
for (isize i = gb_array_count(call->CallExpr.args)-1; i > 0; i--) {
|
|
||||||
gb_swap(AstNode *, call->CallExpr.args[i], call->CallExpr.args[i-1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
expression = call;
|
|
||||||
} else */{
|
|
||||||
right = parse_binary_expr(f, false, prec+1);
|
|
||||||
AstNodeArray args = {0};
|
|
||||||
array_init_reserve(&args, gb_arena_allocator(&f->arena), 2);
|
|
||||||
array_add(&args, expression);
|
|
||||||
array_add(&args, right);
|
|
||||||
expression = make_call_expr(f, proc, args, op, ast_node_token(right), empty_token);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case Token_as:
|
case Token_as:
|
||||||
case Token_transmute:
|
case Token_transmute:
|
||||||
case Token_down_cast:
|
case Token_down_cast:
|
||||||
@@ -2755,42 +2703,6 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
}
|
}
|
||||||
syntax_error(token, "You cannot use #shared_global_scope within a procedure. This must be done at the file scope");
|
syntax_error(token, "You cannot use #shared_global_scope within a procedure. This must be done at the file scope");
|
||||||
return make_bad_decl(f, token, f->curr_token);
|
return make_bad_decl(f, token, f->curr_token);
|
||||||
} else if (str_eq(tag, str_lit("import"))) {
|
|
||||||
// TODO(bill): better error messages
|
|
||||||
Token import_name = {0};
|
|
||||||
Token file_path = expect_token_after(f, Token_String, "#import");
|
|
||||||
if (allow_token(f, Token_as)) {
|
|
||||||
// NOTE(bill): Custom import name
|
|
||||||
if (f->curr_token.kind == Token_Period) {
|
|
||||||
import_name = f->curr_token;
|
|
||||||
import_name.kind = Token_Identifier;
|
|
||||||
next_token(f);
|
|
||||||
} else {
|
|
||||||
import_name = expect_token_after(f, Token_Identifier, "`as` for import declaration");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str_eq(import_name.string, str_lit("_"))) {
|
|
||||||
syntax_error(token, "Illegal import name: `_`");
|
|
||||||
return make_bad_decl(f, token, f->curr_token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f->curr_proc == NULL) {
|
|
||||||
return make_import_decl(f, s->TagStmt.token, file_path, import_name, false);
|
|
||||||
}
|
|
||||||
syntax_error(token, "You cannot use #import within a procedure. This must be done at the file scope");
|
|
||||||
return make_bad_decl(f, token, file_path);
|
|
||||||
} else if (str_eq(tag, str_lit("load"))) {
|
|
||||||
// TODO(bill): better error messages
|
|
||||||
Token file_path = expect_token(f, Token_String);
|
|
||||||
Token import_name = file_path;
|
|
||||||
import_name.string = str_lit(".");
|
|
||||||
|
|
||||||
if (f->curr_proc == NULL) {
|
|
||||||
return make_import_decl(f, s->TagStmt.token, file_path, import_name, true);
|
|
||||||
}
|
|
||||||
syntax_error(token, "You cannot use #load within a procedure. This must be done at the file scope");
|
|
||||||
return make_bad_decl(f, token, file_path);
|
|
||||||
} else if (str_eq(tag, str_lit("foreign_system_library"))) {
|
} else if (str_eq(tag, str_lit("foreign_system_library"))) {
|
||||||
Token file_path = expect_token(f, Token_String);
|
Token file_path = expect_token(f, Token_String);
|
||||||
if (f->curr_proc == NULL) {
|
if (f->curr_proc == NULL) {
|
||||||
@@ -2831,6 +2743,54 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together");
|
syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together");
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
} else if (str_eq(tag, str_lit("import"))) {
|
||||||
|
String os = {0};
|
||||||
|
String arch = {0};
|
||||||
|
|
||||||
|
// if (tag.len > 6) {
|
||||||
|
// String sub = make_string(tag.text+6, tag.len-6);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TODO(bill): better error messages
|
||||||
|
Token import_name = {0};
|
||||||
|
Token file_path = expect_token_after(f, Token_String, "#import");
|
||||||
|
if (allow_token(f, Token_as)) {
|
||||||
|
// NOTE(bill): Custom import name
|
||||||
|
if (f->curr_token.kind == Token_Period) {
|
||||||
|
import_name = f->curr_token;
|
||||||
|
import_name.kind = Token_Identifier;
|
||||||
|
next_token(f);
|
||||||
|
} else {
|
||||||
|
import_name = expect_token_after(f, Token_Identifier, "`as` for import declaration");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str_eq(import_name.string, str_lit("_"))) {
|
||||||
|
syntax_error(token, "Illegal import name: `_`");
|
||||||
|
return make_bad_decl(f, token, f->curr_token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f->curr_proc != NULL) {
|
||||||
|
syntax_error(token, "You cannot use #import within a procedure. This must be done at the file scope");
|
||||||
|
return make_bad_decl(f, token, file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return make_import_decl(f, s->TagStmt.token, file_path, import_name, os, arch, false);
|
||||||
|
} else if (str_eq(tag, str_lit("load"))) {
|
||||||
|
String os = {0};
|
||||||
|
String arch = {0};
|
||||||
|
// TODO(bill): better error messages
|
||||||
|
Token file_path = expect_token(f, Token_String);
|
||||||
|
Token import_name = file_path;
|
||||||
|
import_name.string = str_lit(".");
|
||||||
|
|
||||||
|
if (f->curr_proc == NULL) {
|
||||||
|
return make_import_decl(f, s->TagStmt.token, file_path, import_name, os, arch, true);
|
||||||
|
}
|
||||||
|
syntax_error(token, "You cannot use #load within a procedure. This must be done at the file scope");
|
||||||
|
return make_bad_decl(f, token, file_path);
|
||||||
|
} else {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s->TagStmt.stmt = parse_stmt(f); // TODO(bill): Find out why this doesn't work as an argument
|
s->TagStmt.stmt = parse_stmt(f); // TODO(bill): Find out why this doesn't work as an argument
|
||||||
|
|||||||
@@ -2447,27 +2447,11 @@ void ssa_emit_slice_bounds_check(ssaProcedure *proc, Token token, ssaValue *low,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
low = ssa_emit_conv(proc, low, t_int);
|
low = ssa_emit_conv(proc, low, t_int);
|
||||||
high = ssa_emit_conv(proc, high, t_int);
|
high = ssa_emit_conv(proc, high, t_int);
|
||||||
max = ssa_emit_conv(proc, max, t_int);
|
max = ssa_emit_conv(proc, max, t_int);
|
||||||
|
|
||||||
ssa_emit(proc, ssa_make_instr_slice_bounds_check(proc, token.pos, low, high, max, is_substring));
|
ssa_emit(proc, ssa_make_instr_slice_bounds_check(proc, token.pos, low, high, max, is_substring));
|
||||||
|
|
||||||
// gbAllocator a = proc->module->allocator;
|
|
||||||
// ssaValue **args = gb_alloc_array(a, ssaValue *, 6);
|
|
||||||
// args[0] = ssa_emit_global_string(proc, token.pos.file);
|
|
||||||
// args[1] = ssa_make_const_int(a, token.pos.line);
|
|
||||||
// args[2] = ssa_make_const_int(a, token.pos.column);
|
|
||||||
// args[3] = ssa_emit_conv(proc, low, t_int);
|
|
||||||
// args[4] = ssa_emit_conv(proc, high, t_int);
|
|
||||||
// args[5] = ssa_emit_conv(proc, max, t_int);
|
|
||||||
|
|
||||||
// if (!is_substring) {
|
|
||||||
// ssa_emit_global_call(proc, "__slice_expr_error", args, 6);
|
|
||||||
// } else {
|
|
||||||
// ssa_emit_global_call(proc, "__substring_expr_error", args, 5);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2878,7 +2862,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
Type *elem_type = slice_type->Slice.elem;
|
Type *elem_type = slice_type->Slice.elem;
|
||||||
i64 size_of_elem = type_size_of(proc->module->sizes, proc->module->allocator, elem_type);
|
i64 size_of_elem = type_size_of(proc->module->sizes, proc->module->allocator, elem_type);
|
||||||
|
|
||||||
|
|
||||||
ssaValue *dst = ssa_emit_conv(proc, ssa_slice_elem(proc, dst_slice), t_rawptr);
|
ssaValue *dst = ssa_emit_conv(proc, ssa_slice_elem(proc, dst_slice), t_rawptr);
|
||||||
ssaValue *src = ssa_emit_conv(proc, ssa_slice_elem(proc, src_slice), t_rawptr);
|
ssaValue *src = ssa_emit_conv(proc, ssa_slice_elem(proc, src_slice), t_rawptr);
|
||||||
|
|
||||||
@@ -3031,7 +3014,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
ssa_emit_comment(proc, str_lit("min"));
|
ssa_emit_comment(proc, str_lit("min"));
|
||||||
ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
|
ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
|
||||||
ssaValue *y = ssa_build_expr(proc, ce->args.e[1]);
|
ssaValue *y = ssa_build_expr(proc, ce->args.e[1]);
|
||||||
Type *t = base_type(ssa_type(x));
|
|
||||||
ssaValue *cond = ssa_emit_comp(proc, Token_Lt, x, y);
|
ssaValue *cond = ssa_emit_comp(proc, Token_Lt, x, y);
|
||||||
return ssa_emit_select(proc, cond, x, y);
|
return ssa_emit_select(proc, cond, x, y);
|
||||||
} break;
|
} break;
|
||||||
@@ -3040,7 +3022,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
ssa_emit_comment(proc, str_lit("max"));
|
ssa_emit_comment(proc, str_lit("max"));
|
||||||
ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
|
ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
|
||||||
ssaValue *y = ssa_build_expr(proc, ce->args.e[1]);
|
ssaValue *y = ssa_build_expr(proc, ce->args.e[1]);
|
||||||
Type *t = base_type(ssa_type(x));
|
|
||||||
ssaValue *cond = ssa_emit_comp(proc, Token_Gt, x, y);
|
ssaValue *cond = ssa_emit_comp(proc, Token_Gt, x, y);
|
||||||
return ssa_emit_select(proc, cond, x, y);
|
return ssa_emit_select(proc, cond, x, y);
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
+67
-40
@@ -52,7 +52,8 @@ gb_inline String make_string_c(char *text) {
|
|||||||
|
|
||||||
gb_inline bool str_eq_ignore_case(String a, String b) {
|
gb_inline bool str_eq_ignore_case(String a, String b) {
|
||||||
if (a.len == b.len) {
|
if (a.len == b.len) {
|
||||||
for (isize i = 0; i < a.len; i++) {
|
isize i;
|
||||||
|
for (i = 0; i < a.len; i++) {
|
||||||
char x = cast(char)a.text[i];
|
char x = cast(char)a.text[i];
|
||||||
char y = cast(char)b.text[i];
|
char y = cast(char)b.text[i];
|
||||||
if (gb_char_to_lower(x) != gb_char_to_lower(y))
|
if (gb_char_to_lower(x) != gb_char_to_lower(y))
|
||||||
@@ -64,26 +65,27 @@ gb_inline bool str_eq_ignore_case(String a, String b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int string_compare(String x, String y) {
|
int string_compare(String x, String y) {
|
||||||
if (x.len == y.len &&
|
if (!(x.len == y.len &&
|
||||||
x.text == y.text) {
|
x.text == y.text)) {
|
||||||
return 0;
|
isize n, fast, offset, curr_block;
|
||||||
}
|
isize *la, *lb;
|
||||||
|
isize pos;
|
||||||
|
|
||||||
isize n = gb_min(x.len, y.len);
|
n = gb_min(x.len, y.len);
|
||||||
|
|
||||||
isize fast = n/gb_size_of(isize) + 1;
|
fast = n/gb_size_of(isize) + 1;
|
||||||
isize offset = (fast-1)*gb_size_of(isize);
|
offset = (fast-1)*gb_size_of(isize);
|
||||||
isize curr_block = 0;
|
curr_block = 0;
|
||||||
if (n <= gb_size_of(isize)) {
|
if (n <= gb_size_of(isize)) {
|
||||||
fast = 0;
|
fast = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
isize *la = cast(isize *)x.text;
|
la = cast(isize *)x.text;
|
||||||
isize *lb = cast(isize *)y.text;
|
lb = cast(isize *)y.text;
|
||||||
|
|
||||||
for (; curr_block < fast; curr_block++) {
|
for (; curr_block < fast; curr_block++) {
|
||||||
if (la[curr_block] ^ lb[curr_block]) {
|
if (la[curr_block] ^ lb[curr_block]) {
|
||||||
for (isize pos = curr_block*gb_size_of(isize); pos < n; pos++) {
|
for (pos = curr_block*gb_size_of(isize); pos < n; pos++) {
|
||||||
if (x.text[pos] ^ y.text[pos]) {
|
if (x.text[pos] ^ y.text[pos]) {
|
||||||
return cast(int)x.text[pos] - cast(int)y.text[pos];
|
return cast(int)x.text[pos] - cast(int)y.text[pos];
|
||||||
}
|
}
|
||||||
@@ -96,7 +98,7 @@ int string_compare(String x, String y) {
|
|||||||
return cast(int)x.text[offset] - cast(int)y.text[offset];
|
return cast(int)x.text[offset] - cast(int)y.text[offset];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +128,18 @@ gb_inline bool str_gt(String a, String b) { return string_compare(a, b) > 0;
|
|||||||
gb_inline bool str_le(String a, String b) { return string_compare(a, b) <= 0; }
|
gb_inline bool str_le(String a, String b) { return string_compare(a, b) <= 0; }
|
||||||
gb_inline bool str_ge(String a, String b) { return string_compare(a, b) >= 0; }
|
gb_inline bool str_ge(String a, String b) { return string_compare(a, b) >= 0; }
|
||||||
|
|
||||||
|
gb_inline bool str_has_prefix(String s, String prefix) {
|
||||||
|
isize i;
|
||||||
|
if (prefix.len < s.len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (i = 0; i < prefix.len; i++) {
|
||||||
|
if (s.text[i] != prefix.text[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
gb_inline isize string_extension_position(String str) {
|
gb_inline isize string_extension_position(String str) {
|
||||||
isize dot_pos = -1;
|
isize dot_pos = -1;
|
||||||
@@ -157,7 +170,8 @@ gb_inline bool string_has_extension(String str, String ext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool string_contains_char(String s, u8 c) {
|
bool string_contains_char(String s, u8 c) {
|
||||||
for (isize i = 0; i < s.len; i++) {
|
isize i;
|
||||||
|
for (i = 0; i < s.len; i++) {
|
||||||
if (s.text[i] == c)
|
if (s.text[i] == c)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -166,19 +180,22 @@ bool string_contains_char(String s, u8 c) {
|
|||||||
|
|
||||||
// TODO(bill): Make this non-windows specific
|
// TODO(bill): Make this non-windows specific
|
||||||
String16 string_to_string16(gbAllocator a, String s) {
|
String16 string_to_string16(gbAllocator a, String s) {
|
||||||
|
int len, len1;
|
||||||
|
wchar_t *text;
|
||||||
|
|
||||||
if (s.len < 1) {
|
if (s.len < 1) {
|
||||||
return make_string16(NULL, 0);
|
return make_string16(NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
|
len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||||
cast(char *)s.text, s.len, NULL, 0);
|
cast(char *)s.text, s.len, NULL, 0);
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
return make_string16(NULL, 0);
|
return make_string16(NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t *text = gb_alloc_array(a, wchar_t, len+1);
|
text = gb_alloc_array(a, wchar_t, len+1);
|
||||||
|
|
||||||
int len1 = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
|
len1 = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||||
cast(char *)s.text, s.len, text, len);
|
cast(char *)s.text, s.len, text, len);
|
||||||
if (len1 == 0) {
|
if (len1 == 0) {
|
||||||
gb_free(a, text);
|
gb_free(a, text);
|
||||||
@@ -190,22 +207,23 @@ String16 string_to_string16(gbAllocator a, String s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String string16_to_string(gbAllocator a, String16 s) {
|
String string16_to_string(gbAllocator a, String16 s) {
|
||||||
|
int len, len1;
|
||||||
|
u8 *text;
|
||||||
|
|
||||||
if (s.len < 1) {
|
if (s.len < 1) {
|
||||||
return make_string(NULL, 0);
|
return make_string(NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
|
len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
|
||||||
s.text, s.len, NULL, 0,
|
s.text, s.len, NULL, 0, NULL, NULL);
|
||||||
NULL, NULL);
|
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
return make_string(NULL, 0);
|
return make_string(NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 *text = gb_alloc_array(a, u8, len+1);
|
text = gb_alloc_array(a, u8, len+1);
|
||||||
|
|
||||||
int len1 = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
|
len1 = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
|
||||||
s.text, s.len, cast(char *)text, len,
|
s.text, s.len, cast(char *)text, len, NULL, NULL);
|
||||||
NULL, NULL);
|
|
||||||
if (len1 == 0) {
|
if (len1 == 0) {
|
||||||
gb_free(a, text);
|
gb_free(a, text);
|
||||||
return make_string(NULL, 0);
|
return make_string(NULL, 0);
|
||||||
@@ -233,8 +251,10 @@ String string16_to_string(gbAllocator a, String16 s) {
|
|||||||
|
|
||||||
|
|
||||||
bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *tail_string) {
|
bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *tail_string) {
|
||||||
|
u8 c;
|
||||||
|
|
||||||
if (s.text[0] == quote &&
|
if (s.text[0] == quote &&
|
||||||
(quote == '$' || quote == '"')) {
|
(quote == '\'' || quote == '"')) {
|
||||||
return false;
|
return false;
|
||||||
} else if (s.text[0] >= 0x80) {
|
} else if (s.text[0] >= 0x80) {
|
||||||
Rune r = -1;
|
Rune r = -1;
|
||||||
@@ -252,7 +272,7 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
|
|||||||
if (s.len <= 1) {
|
if (s.len <= 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
u8 c = s.text[1];
|
c = s.text[1];
|
||||||
s = make_string(s.text+2, s.len-2);
|
s = make_string(s.text+2, s.len-2);
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@@ -268,7 +288,7 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
|
|||||||
case '\\': *rune = '\\'; break;
|
case '\\': *rune = '\\'; break;
|
||||||
|
|
||||||
|
|
||||||
case '$':
|
case '\'':
|
||||||
case '"':
|
case '"':
|
||||||
if (c != quote) {
|
if (c != quote) {
|
||||||
return false;
|
return false;
|
||||||
@@ -284,11 +304,12 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
|
|||||||
case '5':
|
case '5':
|
||||||
case '6':
|
case '6':
|
||||||
case '7': {
|
case '7': {
|
||||||
|
isize i;
|
||||||
i32 r = gb_digit_to_int(c);
|
i32 r = gb_digit_to_int(c);
|
||||||
if (s.len < 2) {
|
if (s.len < 2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (isize i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
i32 d = gb_digit_to_int(s.text[i]);
|
i32 d = gb_digit_to_int(s.text[i]);
|
||||||
if (d < 0 || d > 7) {
|
if (d < 0 || d > 7) {
|
||||||
return false;
|
return false;
|
||||||
@@ -305,18 +326,18 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
|
|||||||
case 'x':
|
case 'x':
|
||||||
case 'u':
|
case 'u':
|
||||||
case 'U': {
|
case 'U': {
|
||||||
isize count = 0;
|
Rune r = 0;
|
||||||
|
isize i, count = 0;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'x': count = 2; break;
|
case 'x': count = 2; break;
|
||||||
case 'u': count = 4; break;
|
case 'u': count = 4; break;
|
||||||
case 'U': count = 8; break;
|
case 'U': count = 8; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rune r = 0;
|
|
||||||
if (s.len < count) {
|
if (s.len < count) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (isize i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
i32 d = gb_hex_digit_to_int(s.text[i]);
|
i32 d = gb_hex_digit_to_int(s.text[i]);
|
||||||
if (d < 0) {
|
if (d < 0) {
|
||||||
return false;
|
return false;
|
||||||
@@ -344,14 +365,16 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
|
|||||||
// 1 == original memory
|
// 1 == original memory
|
||||||
// 2 == new allocation
|
// 2 == new allocation
|
||||||
i32 unquote_string(gbAllocator a, String *s_) {
|
i32 unquote_string(gbAllocator a, String *s_) {
|
||||||
GB_ASSERT(s_ != NULL);
|
|
||||||
String s = *s_;
|
String s = *s_;
|
||||||
isize n = s.len;
|
isize n = s.len;
|
||||||
if (n < 2)
|
u8 quote;
|
||||||
|
if (n < 2) {
|
||||||
return 0;
|
return 0;
|
||||||
u8 quote = s.text[0];
|
}
|
||||||
if (quote != s.text[n-1])
|
quote = s.text[0];
|
||||||
|
if (quote != s.text[n-1]) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
s.text += 1;
|
s.text += 1;
|
||||||
s.len -= 2;
|
s.len -= 2;
|
||||||
|
|
||||||
@@ -362,17 +385,19 @@ i32 unquote_string(gbAllocator a, String *s_) {
|
|||||||
*s_ = s;
|
*s_ = s;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (quote != '"' && quote != '$')
|
if (quote != '"' && quote != '\'') {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (string_contains_char(s, '\n'))
|
if (string_contains_char(s, '\n')) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!string_contains_char(s, '\\') && !string_contains_char(s, quote)) {
|
if (!string_contains_char(s, '\\') && !string_contains_char(s, quote)) {
|
||||||
if (quote == '"') {
|
if (quote == '"') {
|
||||||
*s_ = s;
|
*s_ = s;
|
||||||
return 1;
|
return 1;
|
||||||
} else if (quote == '$') {
|
} else if (quote == '\'') {
|
||||||
Rune r = GB_RUNE_INVALID;
|
Rune r = GB_RUNE_INVALID;
|
||||||
isize size = gb_utf8_decode(s.text, s.len, &r);
|
isize size = gb_utf8_decode(s.text, s.len, &r);
|
||||||
if ((size == s.len) && (r != -1 || size != 1)) {
|
if ((size == s.len) && (r != -1 || size != 1)) {
|
||||||
@@ -383,6 +408,7 @@ i32 unquote_string(gbAllocator a, String *s_) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
u8 rune_temp[4] = {0};
|
u8 rune_temp[4] = {0};
|
||||||
isize buf_len = 3*s.len / 2;
|
isize buf_len = 3*s.len / 2;
|
||||||
u8 *buf = gb_alloc_array(a, u8, buf_len);
|
u8 *buf = gb_alloc_array(a, u8, buf_len);
|
||||||
@@ -406,11 +432,12 @@ i32 unquote_string(gbAllocator a, String *s_) {
|
|||||||
offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (quote == '$' && s.len != 0) {
|
if (quote == '\'' && s.len != 0) {
|
||||||
gb_free(a, buf);
|
gb_free(a, buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*s_ = make_string(buf, offset);
|
*s_ = make_string(buf, offset);
|
||||||
|
}
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -77,12 +77,13 @@ f64 time_stamp_as_ms(TimeStamp ts, u64 freq) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void timings_print_all(Timings *t) {
|
void timings_print_all(Timings *t) {
|
||||||
|
char const SPACES[] = " ";
|
||||||
|
isize max_len, i;
|
||||||
|
|
||||||
timings__stop_current_section(t);
|
timings__stop_current_section(t);
|
||||||
t->total.finish = time_stamp_time_now();
|
t->total.finish = time_stamp_time_now();
|
||||||
|
|
||||||
char const SPACES[] = " ";
|
max_len = t->total.label.len;
|
||||||
|
|
||||||
isize max_len = t->total.label.len;
|
|
||||||
for_array(i, t->sections) {
|
for_array(i, t->sections) {
|
||||||
TimeStamp ts = t->sections.e[i];
|
TimeStamp ts = t->sections.e[i];
|
||||||
max_len = gb_max(max_len, ts.label.len);
|
max_len = gb_max(max_len, ts.label.len);
|
||||||
|
|||||||
+47
-14
@@ -34,9 +34,6 @@ TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \
|
|||||||
TOKEN_KIND(Token_transmute, "transmute"), \
|
TOKEN_KIND(Token_transmute, "transmute"), \
|
||||||
TOKEN_KIND(Token_down_cast, "down_cast"), \
|
TOKEN_KIND(Token_down_cast, "down_cast"), \
|
||||||
TOKEN_KIND(Token_union_cast, "union_cast"), \
|
TOKEN_KIND(Token_union_cast, "union_cast"), \
|
||||||
\
|
|
||||||
TOKEN_KIND(Token_Prime, "'"), \
|
|
||||||
TOKEN_KIND(Token_DoublePrime, "''"), \
|
|
||||||
\
|
\
|
||||||
TOKEN_KIND(Token_CmpAnd, "&&"), \
|
TOKEN_KIND(Token_CmpAnd, "&&"), \
|
||||||
TOKEN_KIND(Token_CmpOr, "||"), \
|
TOKEN_KIND(Token_CmpOr, "||"), \
|
||||||
@@ -656,17 +653,50 @@ Token tokenizer_get_token(Tokenizer *t) {
|
|||||||
token.kind = Token_EOF;
|
token.kind = Token_EOF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\'':
|
case '\'': // Rune Literal
|
||||||
token.kind = Token_Prime;
|
{
|
||||||
if (t->curr_rune == '\'') {
|
token.kind = Token_Rune;
|
||||||
advance_to_next_rune(t);
|
Rune quote = curr_rune;
|
||||||
token.kind = Token_DoublePrime;
|
bool valid = true;
|
||||||
}
|
i32 n = 0, success;
|
||||||
|
for (;;) {
|
||||||
|
Rune r = t->curr_rune;
|
||||||
|
if (r == '\n' || r < 0) {
|
||||||
|
tokenizer_err(t, "Rune literal not terminated");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
advance_to_next_rune(t);
|
||||||
|
if (r == quote) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
if (r == '\\') {
|
||||||
|
if (!scan_escape(t, quote)) {
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(bill): Better Error Handling
|
||||||
|
if (valid && n != 1) {
|
||||||
|
tokenizer_err(t, "Invalid rune literal");
|
||||||
|
}
|
||||||
|
token.string.len = t->curr - token.string.text;
|
||||||
|
success = unquote_string(heap_allocator(), &token.string);
|
||||||
|
if (success > 0) {
|
||||||
|
if (success == 2) {
|
||||||
|
array_add(&t->allocated_strings, token.string);
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
} else {
|
||||||
|
tokenizer_err(t, "Invalid rune literal");
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
case '`': // Raw String Literal
|
case '`': // Raw String Literal
|
||||||
case '"': // String Literal
|
case '"': // String Literal
|
||||||
{
|
{
|
||||||
|
i32 success;
|
||||||
Rune quote = curr_rune;
|
Rune quote = curr_rune;
|
||||||
token.kind = Token_String;
|
token.kind = Token_String;
|
||||||
if (curr_rune == '"') {
|
if (curr_rune == '"') {
|
||||||
@@ -677,10 +707,12 @@ Token tokenizer_get_token(Tokenizer *t) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
advance_to_next_rune(t);
|
advance_to_next_rune(t);
|
||||||
if (r == quote)
|
if (r == quote) {
|
||||||
break;
|
break;
|
||||||
if (r == '\\')
|
}
|
||||||
scan_escape(t, '"');
|
if (r == '\\') {
|
||||||
|
scan_escape(t, quote);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -690,12 +722,13 @@ Token tokenizer_get_token(Tokenizer *t) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
advance_to_next_rune(t);
|
advance_to_next_rune(t);
|
||||||
if (r == quote)
|
if (r == quote) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
token.string.len = t->curr - token.string.text;
|
token.string.len = t->curr - token.string.text;
|
||||||
i32 success = unquote_string(heap_allocator(), &token.string);
|
success = unquote_string(heap_allocator(), &token.string);
|
||||||
if (success > 0) {
|
if (success > 0) {
|
||||||
if (success == 2) {
|
if (success == 2) {
|
||||||
array_add(&t->allocated_strings, token.string);
|
array_add(&t->allocated_strings, token.string);
|
||||||
|
|||||||
+1
-1
@@ -42,10 +42,10 @@ bool rune_is_whitespace(Rune r) {
|
|||||||
|
|
||||||
|
|
||||||
bool is_string_an_identifier(String s) {
|
bool is_string_an_identifier(String s) {
|
||||||
|
isize offset = 0;
|
||||||
if (s.len < 1) {
|
if (s.len < 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
isize offset = 0;
|
|
||||||
while (offset < s.len) {
|
while (offset < s.len) {
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
Rune r = -1;
|
Rune r = -1;
|
||||||
|
|||||||
Reference in New Issue
Block a user