mirror of
https://github.com/odin-lang/Odin.git
synced 2026-06-07 02:54:18 +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= ^
|
||||
-we4013 -we4706 -we4002 ^
|
||||
-we4013 -we4706 -we4002 -we4133 ^
|
||||
-wd4100 -wd4101 -wd4127 -wd4189 ^
|
||||
-wd4201 -wd4204 -wd4244 ^
|
||||
-wd4306 ^
|
||||
|
||||
@@ -1,5 +1,34 @@
|
||||
#import "fmt.odin"
|
||||
#import "utf8.odin"
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#import "os.odin"
|
||||
#import "opengl.odin" as gl
|
||||
|
||||
TWO_HEARTS :: #rune "💕"
|
||||
TWO_HEARTS :: '💕'
|
||||
|
||||
win32_perf_count_freq := win32.GetQueryPerformanceFrequency()
|
||||
time_now :: proc() -> f64 {
|
||||
|
||||
@@ -76,8 +76,8 @@ print_rune_to_buffer :: proc(buf: ^[]byte, r: rune) {
|
||||
print_string_to_buffer(buf, b[:n] as string)
|
||||
}
|
||||
|
||||
print_space_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, #rune " ") }
|
||||
print_nl_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, #rune "\n") }
|
||||
print_space_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, ' ') }
|
||||
print_nl_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, '\n') }
|
||||
|
||||
__NUM_TO_CHAR_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$"
|
||||
|
||||
@@ -99,7 +99,7 @@ print_u64_to_buffer :: proc(buffer: ^[]byte, value: u64) {
|
||||
buf: [20]byte
|
||||
len := 0
|
||||
if i == 0 {
|
||||
buf[len] = #rune "0"
|
||||
buf[len] = '0'
|
||||
len++
|
||||
}
|
||||
for i > 0 {
|
||||
@@ -115,7 +115,7 @@ print_i64_to_buffer :: proc(buffer: ^[]byte, value: i64) {
|
||||
neg := i < 0
|
||||
if neg {
|
||||
i = -i
|
||||
print_rune_to_buffer(buffer, #rune "-")
|
||||
print_rune_to_buffer(buffer, '-')
|
||||
}
|
||||
print_u64_to_buffer(buffer, i as u64)
|
||||
}
|
||||
@@ -132,7 +132,7 @@ print_i128_to_buffer :: proc(buffer: ^[]byte, value: i128) {
|
||||
neg := i < 0
|
||||
if neg {
|
||||
i = -i
|
||||
print_rune_to_buffer(buffer, #rune "-")
|
||||
print_rune_to_buffer(buffer, '-')
|
||||
}
|
||||
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) {
|
||||
f := value
|
||||
if f == 0 {
|
||||
print_rune_to_buffer(buffer, #rune "0")
|
||||
print_rune_to_buffer(buffer, '0')
|
||||
return
|
||||
}
|
||||
if f < 0 {
|
||||
print_rune_to_buffer(buffer, #rune "-")
|
||||
print_rune_to_buffer(buffer, '-')
|
||||
f = -f
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ print__f64 :: proc(buffer: ^[]byte, value: f64, decimal_places: int) {
|
||||
print_u64_to_buffer(buffer, i)
|
||||
f -= i as f64
|
||||
|
||||
print_rune_to_buffer(buffer, #rune ".")
|
||||
print_rune_to_buffer(buffer, '.')
|
||||
|
||||
mult: f64 = 10.0
|
||||
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 {
|
||||
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) {
|
||||
@@ -501,7 +501,7 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
|
||||
}
|
||||
|
||||
result *= 10
|
||||
result += (c - #rune "0") as int
|
||||
result += (c - '0') as int
|
||||
}
|
||||
|
||||
return result, offset
|
||||
@@ -514,7 +514,7 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
|
||||
r := fmt[i] as rune
|
||||
index := implicit_index
|
||||
|
||||
if r != #rune "%" {
|
||||
if r != '%' {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -523,7 +523,7 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
|
||||
if i < fmt.count {
|
||||
next := fmt[i] as rune
|
||||
|
||||
if next == #rune "%" {
|
||||
if next == '%' {
|
||||
print_string_to_buffer(buf, "%")
|
||||
i++
|
||||
prev = i
|
||||
@@ -582,7 +582,7 @@ bprint :: proc(buf: ^[]byte, args: ..any) -> int {
|
||||
bprintln :: proc(buf: ^[]byte, args: ..any) -> int {
|
||||
for i := 0; i < args.count; i++ {
|
||||
if i > 0 {
|
||||
append(buf, #rune " ")
|
||||
append(buf, ' ')
|
||||
}
|
||||
print_any_to_buffer(buf, args[i])
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
RUNE_ERROR :: #rune "\ufffd"
|
||||
RUNE_ERROR :: '\ufffd'
|
||||
RUNE_SELF :: 0x80
|
||||
RUNE_BOM :: 0xfeff
|
||||
RUNE_EOF :: ~(0 as rune)
|
||||
MAX_RUNE :: #rune "\U0010ffff"
|
||||
MAX_RUNE :: '\U0010ffff'
|
||||
UTF_MAX :: 4
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#foreign_system_library "user32"
|
||||
#foreign_system_library "gdi32"
|
||||
|
||||
_:= compile_assert(ODIN_OS == "windows")
|
||||
|
||||
HANDLE :: type rawptr
|
||||
HWND :: type HANDLE
|
||||
HDC :: type HANDLE
|
||||
@@ -387,43 +389,43 @@ Key_Code :: enum i32 {
|
||||
DELETE = 0x2E,
|
||||
HELP = 0x2F,
|
||||
|
||||
NUM0 = #rune "0",
|
||||
NUM1 = #rune "1",
|
||||
NUM2 = #rune "2",
|
||||
NUM3 = #rune "3",
|
||||
NUM4 = #rune "4",
|
||||
NUM5 = #rune "5",
|
||||
NUM6 = #rune "6",
|
||||
NUM7 = #rune "7",
|
||||
NUM8 = #rune "8",
|
||||
NUM9 = #rune "9",
|
||||
NUM0 = '0',
|
||||
NUM1 = '1',
|
||||
NUM2 = '2',
|
||||
NUM3 = '3',
|
||||
NUM4 = '4',
|
||||
NUM5 = '5',
|
||||
NUM6 = '6',
|
||||
NUM7 = '7',
|
||||
NUM8 = '8',
|
||||
NUM9 = '9',
|
||||
|
||||
A = #rune "A",
|
||||
B = #rune "B",
|
||||
C = #rune "C",
|
||||
D = #rune "D",
|
||||
E = #rune "E",
|
||||
F = #rune "F",
|
||||
G = #rune "G",
|
||||
H = #rune "H",
|
||||
I = #rune "I",
|
||||
J = #rune "J",
|
||||
K = #rune "K",
|
||||
L = #rune "L",
|
||||
M = #rune "M",
|
||||
N = #rune "N",
|
||||
O = #rune "O",
|
||||
P = #rune "P",
|
||||
Q = #rune "Q",
|
||||
R = #rune "R",
|
||||
S = #rune "S",
|
||||
T = #rune "T",
|
||||
U = #rune "U",
|
||||
V = #rune "V",
|
||||
W = #rune "W",
|
||||
X = #rune "X",
|
||||
Y = #rune "Y",
|
||||
Z = #rune "Z",
|
||||
A = 'A',
|
||||
B = 'B',
|
||||
C = 'C',
|
||||
D = 'D',
|
||||
E = 'E',
|
||||
F = 'F',
|
||||
G = 'G',
|
||||
H = 'H',
|
||||
I = 'I',
|
||||
J = 'J',
|
||||
K = 'K',
|
||||
L = 'L',
|
||||
M = 'M',
|
||||
N = 'N',
|
||||
O = 'O',
|
||||
P = 'P',
|
||||
Q = 'Q',
|
||||
R = 'R',
|
||||
S = 'S',
|
||||
T = 'T',
|
||||
U = 'U',
|
||||
V = 'V',
|
||||
W = 'W',
|
||||
X = 'X',
|
||||
Y = 'Y',
|
||||
Z = 'Z',
|
||||
|
||||
LWIN = 0x5B,
|
||||
RWIN = 0x5C,
|
||||
|
||||
@@ -11,8 +11,8 @@ GB_STATIC_ASSERT(ARRAY_GROW_FORMULA(0) > 0);
|
||||
typedef Array(void) ArrayVoid;
|
||||
|
||||
#define array_init_reserve(x_, allocator_, init_capacity_) do { \
|
||||
GB_ASSERT((x_) != NULL); \
|
||||
void **e = cast(void **)&((x_)->e); \
|
||||
GB_ASSERT((x_) != NULL); \
|
||||
(x_)->allocator = (allocator_); \
|
||||
(x_)->count = 0; \
|
||||
(x_)->capacity = (init_capacity_); \
|
||||
@@ -20,8 +20,8 @@ typedef Array(void) ArrayVoid;
|
||||
} while (0)
|
||||
|
||||
#define array_init_count(x_, allocator_, init_count_) do { \
|
||||
GB_ASSERT((x_) != NULL); \
|
||||
void **e = cast(void **)&((x_)->e); \
|
||||
GB_ASSERT((x_) != NULL); \
|
||||
(x_)->allocator = (allocator_); \
|
||||
(x_)->count = (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) {
|
||||
GB_ASSERT(ptr != NULL);
|
||||
ArrayVoid *x = cast(ArrayVoid *)ptr;
|
||||
GB_ASSERT(ptr != NULL);
|
||||
|
||||
GB_ASSERT(element_size > 0);
|
||||
|
||||
|
||||
@@ -271,8 +271,9 @@ CycleChecker *cycle_checker_add(CycleChecker *cc, Entity *e) {
|
||||
if (cc->path.e == NULL) {
|
||||
array_init(&cc->path, heap_allocator());
|
||||
}
|
||||
GB_ASSERT(e != NULL && e->kind == Entity_TypeName);
|
||||
array_add(&cc->path, e);
|
||||
if (e != NULL && e->kind == Entity_TypeName) {
|
||||
array_add(&cc->path, e);
|
||||
}
|
||||
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) {
|
||||
// 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_constant(a, str_lit("ODIN_OS"), t_untyped_string, make_exact_value_string(str_lit("windows")));
|
||||
add_global_constant(a, str_lit("ODIN_ARCH"), t_untyped_string, make_exact_value_string(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_OS"), str_lit("windows"));
|
||||
add_global_string_constant(a, str_lit("ODIN_ARCH"), str_lit("amd64"));
|
||||
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
|
||||
|
||||
@@ -713,12 +713,10 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
|
||||
if (o.mode != Addressing_Invalid) {
|
||||
iota = o.value;
|
||||
} else {
|
||||
Token add_token = {Token_Add};
|
||||
iota = exact_binary_operator_value(add_token, iota, make_exact_value_integer(1));
|
||||
iota = exact_binary_operator_value(Token_Add, iota, make_exact_value_integer(1));
|
||||
}
|
||||
} else {
|
||||
Token add_token = {Token_Add};
|
||||
iota = exact_binary_operator_value(add_token, iota, make_exact_value_integer(1));
|
||||
iota = exact_binary_operator_value(Token_Add, 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)) {
|
||||
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 (node != NULL) {
|
||||
@@ -1558,7 +1556,7 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
|
||||
} else {
|
||||
if (x->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 {
|
||||
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->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)) {
|
||||
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)) {
|
||||
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 (node != NULL) {
|
||||
x->expr = node;
|
||||
@@ -3166,7 +3164,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
case BuiltinProc_min: {
|
||||
// min :: proc(a, b: comparable) -> comparable
|
||||
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);
|
||||
error(ast_node_token(call),
|
||||
"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) {
|
||||
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);
|
||||
error(ast_node_token(call),
|
||||
"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) {
|
||||
ExactValue x = a.value;
|
||||
ExactValue y = b.value;
|
||||
Token lt = {Token_Lt};
|
||||
|
||||
operand->mode = Addressing_Constant;
|
||||
if (compare_exact_values(lt, x, y)) {
|
||||
if (compare_exact_values(Token_Lt, x, y)) {
|
||||
operand->value = x;
|
||||
operand->type = a.type;
|
||||
} else {
|
||||
@@ -3235,10 +3232,10 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
case BuiltinProc_max: {
|
||||
// min :: proc(a, b: comparable) -> comparable
|
||||
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);
|
||||
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);
|
||||
gb_string_free(type_str);
|
||||
return false;
|
||||
@@ -3251,10 +3248,10 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
if (b.mode == Addressing_Invalid) {
|
||||
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);
|
||||
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);
|
||||
gb_string_free(type_str);
|
||||
return false;
|
||||
@@ -3264,10 +3261,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
b.mode == Addressing_Constant) {
|
||||
ExactValue x = a.value;
|
||||
ExactValue y = b.value;
|
||||
Token gt = {Token_Gt};
|
||||
|
||||
operand->mode = Addressing_Constant;
|
||||
if (compare_exact_values(gt, x, y)) {
|
||||
if (compare_exact_values(Token_Gt, x, y)) {
|
||||
operand->value = x;
|
||||
operand->type = a.type;
|
||||
} else {
|
||||
|
||||
@@ -683,7 +683,8 @@ bool is_type_comparable(Type *t) {
|
||||
return false;
|
||||
} break;
|
||||
case Type_Array:
|
||||
return is_type_comparable(t->Array.elem);
|
||||
return false;
|
||||
// return is_type_comparable(t->Array.elem);
|
||||
case Type_Vector:
|
||||
return is_type_comparable(t->Vector.elem);
|
||||
case Type_Proc:
|
||||
|
||||
20
src/common.c
20
src/common.c
@@ -14,14 +14,19 @@ gb_global bool global_module_path_set = false;
|
||||
|
||||
|
||||
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) {
|
||||
return global_module_path;
|
||||
}
|
||||
|
||||
Array(wchar_t) path_buf;
|
||||
array_init_count(&path_buf, heap_allocator(), 300);
|
||||
|
||||
isize len = 0;
|
||||
len = 0;
|
||||
for (;;) {
|
||||
len = GetModuleFileNameW(NULL, &path_buf.e[0], path_buf.count);
|
||||
if (len == 0) {
|
||||
@@ -33,13 +38,13 @@ String get_module_dir() {
|
||||
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);
|
||||
String path = string16_to_string(heap_allocator(), make_string16(text, len));
|
||||
for (isize i = path.len-1; i >= 0; i--) {
|
||||
path = string16_to_string(heap_allocator(), make_string16(text, len));
|
||||
for (i = path.len-1; i >= 0; i--) {
|
||||
u8 c = path.text[i];
|
||||
if (c == '/' || c == '\\') {
|
||||
break;
|
||||
@@ -141,8 +146,9 @@ i16 f32_to_f16(f32 value) {
|
||||
if (e > 30) {
|
||||
float volatile f = 1e12f;
|
||||
int j;
|
||||
for (j = 0; j < 10; j++)
|
||||
for (j = 0; j < 10; j++) {
|
||||
f *= f; /* NOTE(bill): Cause overflow */
|
||||
}
|
||||
|
||||
return cast(i16)(s | 0x7c00);
|
||||
}
|
||||
|
||||
@@ -148,8 +148,8 @@ ExactValue exact_value_to_float(ExactValue v) {
|
||||
}
|
||||
|
||||
|
||||
ExactValue exact_unary_operator_value(Token op, ExactValue v, i32 precision) {
|
||||
switch (op.kind) {
|
||||
ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision) {
|
||||
switch (op) {
|
||||
case Token_Add: {
|
||||
switch (v.kind) {
|
||||
case ExactValue_Invalid:
|
||||
@@ -207,7 +207,7 @@ ExactValue exact_unary_operator_value(Token op, ExactValue v, i32 precision) {
|
||||
}
|
||||
|
||||
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};
|
||||
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?
|
||||
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);
|
||||
|
||||
switch (x.kind) {
|
||||
@@ -278,7 +278,7 @@ ExactValue exact_binary_operator_value(Token op, ExactValue x, ExactValue y) {
|
||||
return x;
|
||||
|
||||
case ExactValue_Bool:
|
||||
switch (op.kind) {
|
||||
switch (op) {
|
||||
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_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 b = y.value_integer;
|
||||
i64 c = 0;
|
||||
switch (op.kind) {
|
||||
switch (op) {
|
||||
case Token_Add: c = a + b; break;
|
||||
case Token_Sub: 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: {
|
||||
f64 a = x.value_float;
|
||||
f64 b = y.value_float;
|
||||
switch (op.kind) {
|
||||
switch (op) {
|
||||
case Token_Add: 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);
|
||||
@@ -324,22 +324,22 @@ ExactValue exact_binary_operator_value(Token op, ExactValue x, ExactValue y) {
|
||||
|
||||
error:
|
||||
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;
|
||||
}
|
||||
|
||||
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_sub(ExactValue x, ExactValue y) { Token op = {Token_Sub}; return exact_binary_operator_value(op, 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_quo(ExactValue x, ExactValue y) { Token op = {Token_Quo}; return exact_binary_operator_value(op, 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_add(ExactValue x, ExactValue y) { return exact_binary_operator_value(Token_Add, 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) { return exact_binary_operator_value(Token_Mul, 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(TokenKind op, ExactValue x, ExactValue y) { return exact_binary_operator_value(op, x, y); }
|
||||
|
||||
|
||||
i32 cmp_f64(f64 a, f64 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);
|
||||
|
||||
switch (x.kind) {
|
||||
@@ -347,7 +347,7 @@ bool compare_exact_values(Token op, ExactValue x, ExactValue y) {
|
||||
return false;
|
||||
|
||||
case ExactValue_Bool:
|
||||
switch (op.kind) {
|
||||
switch (op) {
|
||||
case Token_CmpEq: 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: {
|
||||
i64 a = x.value_integer;
|
||||
i64 b = y.value_integer;
|
||||
switch (op.kind) {
|
||||
switch (op) {
|
||||
case Token_CmpEq: return a == b;
|
||||
case Token_NotEq: 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: {
|
||||
f64 a = x.value_float;
|
||||
f64 b = y.value_float;
|
||||
switch (op.kind) {
|
||||
switch (op) {
|
||||
case Token_CmpEq: return cmp_f64(a, b) == 0;
|
||||
case Token_NotEq: 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;
|
||||
isize len = gb_min(a.len, b.len);
|
||||
// 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_NotEq: 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) {
|
||||
MapFindResult last;
|
||||
if (fr.entry_prev < 0) {
|
||||
h->hashes.e[fr.hash_index] = h->entries.e[fr.entry_index].next;
|
||||
} else {
|
||||
@@ -253,7 +254,7 @@ void _J2(MAP_PROC,_erase)(MAP_NAME *h, MapFindResult fr) {
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
h->entries.e[last.entry_prev].next = fr.entry_index;
|
||||
} 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) {
|
||||
MapFindResult fr;
|
||||
isize i;
|
||||
if (h->hashes.count == 0) {
|
||||
_J2(MAP_PROC,grow)(h);
|
||||
}
|
||||
MapFindResult fr = _J2(MAP_PROC,_find)(h, key);
|
||||
isize i = _J2(MAP_PROC,_add_entry)(h, key);
|
||||
fr = _J2(MAP_PROC,_find)(h, key);
|
||||
i = _J2(MAP_PROC,_add_entry)(h, key);
|
||||
if (fr.entry_prev < 0) {
|
||||
h->hashes.e[fr.hash_index] = i;
|
||||
} else {
|
||||
|
||||
156
src/parser.c
156
src/parser.c
@@ -32,7 +32,7 @@ typedef struct AstFile {
|
||||
isize expr_level;
|
||||
|
||||
AstNodeArray decls;
|
||||
bool is_global_scope;
|
||||
bool is_global_scope;
|
||||
|
||||
AstNode * curr_proc;
|
||||
isize scope_level;
|
||||
@@ -86,13 +86,6 @@ typedef enum StmtStateFlag {
|
||||
StmtStateFlag_no_bounds_check = GB_BIT(1),
|
||||
} 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 a;
|
||||
array_init(&a, gb_arena_allocator(&f->arena));
|
||||
@@ -134,7 +127,6 @@ AST_NODE_KIND(_ExprBegin, "", i32) \
|
||||
AstNodeArray args; \
|
||||
Token open, close; \
|
||||
Token ellipsis; \
|
||||
CallExprKind kind; \
|
||||
}) \
|
||||
AST_NODE_KIND(SliceExpr, "slice expression", struct { \
|
||||
AstNode *expr; \
|
||||
@@ -256,9 +248,10 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
|
||||
}) \
|
||||
AST_NODE_KIND(ImportDecl, "import declaration", struct { \
|
||||
Token token, relpath; \
|
||||
String os, arch; \
|
||||
String fullpath; \
|
||||
Token import_name; \
|
||||
bool is_load; \
|
||||
bool is_load; \
|
||||
AstNode *note; \
|
||||
}) \
|
||||
AST_NODE_KIND(ForeignLibrary, "foreign library", struct { \
|
||||
@@ -959,11 +952,15 @@ AstNode *make_type_decl(AstFile *f, Token token, AstNode *name, AstNode *type) {
|
||||
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);
|
||||
result->ImportDecl.token = token;
|
||||
result->ImportDecl.relpath = relpath;
|
||||
result->ImportDecl.import_name = import_name;
|
||||
result->ImportDecl.os = os;
|
||||
result->ImportDecl.arch = arch;
|
||||
result->ImportDecl.is_load = is_load;
|
||||
return result;
|
||||
}
|
||||
@@ -1374,19 +1371,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
||||
case Token_Hash: {
|
||||
Token token = expect_token(f, Token_Hash);
|
||||
Token name = expect_token(f, Token_Identifier);
|
||||
if (str_eq(name.string, str_lit("rune"))) {
|
||||
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"))) {
|
||||
if (str_eq(name.string, str_lit("file"))) {
|
||||
Token token = name;
|
||||
token.kind = Token_String;
|
||||
token.string = token.pos.file;
|
||||
@@ -1513,19 +1498,6 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
|
||||
bool loop = true;
|
||||
while (loop) {
|
||||
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: {
|
||||
if (lhs) {
|
||||
// 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_Shr:
|
||||
return 5;
|
||||
case Token_DoublePrime:
|
||||
return 6;
|
||||
case Token_as:
|
||||
case Token_transmute:
|
||||
case Token_down_cast:
|
||||
case Token_union_cast:
|
||||
return 7;
|
||||
return 6;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1708,28 +1678,6 @@ AstNode *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
|
||||
}
|
||||
|
||||
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_transmute:
|
||||
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");
|
||||
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"))) {
|
||||
Token file_path = expect_token(f, Token_String);
|
||||
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");
|
||||
}
|
||||
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
|
||||
|
||||
19
src/ssa.c
19
src/ssa.c
@@ -2447,27 +2447,11 @@ void ssa_emit_slice_bounds_check(ssaProcedure *proc, Token token, ssaValue *low,
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
low = ssa_emit_conv(proc, low, t_int);
|
||||
high = ssa_emit_conv(proc, high, 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));
|
||||
|
||||
// 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;
|
||||
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 *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"));
|
||||
ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
|
||||
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);
|
||||
return ssa_emit_select(proc, cond, x, y);
|
||||
} break;
|
||||
@@ -3040,7 +3022,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
ssa_emit_comment(proc, str_lit("max"));
|
||||
ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
|
||||
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);
|
||||
return ssa_emit_select(proc, cond, x, y);
|
||||
} break;
|
||||
|
||||
181
src/string.c
181
src/string.c
@@ -52,7 +52,8 @@ gb_inline String make_string_c(char *text) {
|
||||
|
||||
gb_inline bool str_eq_ignore_case(String a, String b) {
|
||||
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 y = cast(char)b.text[i];
|
||||
if (gb_char_to_lower(x) != gb_char_to_lower(y))
|
||||
@@ -64,39 +65,40 @@ gb_inline bool str_eq_ignore_case(String a, String b) {
|
||||
}
|
||||
|
||||
int string_compare(String x, String y) {
|
||||
if (x.len == y.len &&
|
||||
x.text == y.text) {
|
||||
return 0;
|
||||
}
|
||||
if (!(x.len == y.len &&
|
||||
x.text == y.text)) {
|
||||
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;
|
||||
isize offset = (fast-1)*gb_size_of(isize);
|
||||
isize curr_block = 0;
|
||||
if (n <= gb_size_of(isize)) {
|
||||
fast = 0;
|
||||
}
|
||||
fast = n/gb_size_of(isize) + 1;
|
||||
offset = (fast-1)*gb_size_of(isize);
|
||||
curr_block = 0;
|
||||
if (n <= gb_size_of(isize)) {
|
||||
fast = 0;
|
||||
}
|
||||
|
||||
isize *la = cast(isize *)x.text;
|
||||
isize *lb = cast(isize *)y.text;
|
||||
la = cast(isize *)x.text;
|
||||
lb = cast(isize *)y.text;
|
||||
|
||||
for (; curr_block < fast; curr_block++) {
|
||||
if (la[curr_block] ^ lb[curr_block]) {
|
||||
for (isize pos = curr_block*gb_size_of(isize); pos < n; pos++) {
|
||||
if (x.text[pos] ^ y.text[pos]) {
|
||||
return cast(int)x.text[pos] - cast(int)y.text[pos];
|
||||
for (; curr_block < fast; curr_block++) {
|
||||
if (la[curr_block] ^ lb[curr_block]) {
|
||||
for (pos = curr_block*gb_size_of(isize); pos < n; pos++) {
|
||||
if (x.text[pos] ^ y.text[pos]) {
|
||||
return cast(int)x.text[pos] - cast(int)y.text[pos];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (; offset < n; offset++) {
|
||||
if (x.text[offset] ^ y.text[offset]) {
|
||||
return cast(int)x.text[offset] - cast(int)y.text[offset];
|
||||
for (; offset < n; offset++) {
|
||||
if (x.text[offset] ^ y.text[offset]) {
|
||||
return cast(int)x.text[offset] - cast(int)y.text[offset];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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_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) {
|
||||
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) {
|
||||
for (isize i = 0; i < s.len; i++) {
|
||||
isize i;
|
||||
for (i = 0; i < s.len; i++) {
|
||||
if (s.text[i] == c)
|
||||
return true;
|
||||
}
|
||||
@@ -166,20 +180,23 @@ bool string_contains_char(String s, u8 c) {
|
||||
|
||||
// TODO(bill): Make this non-windows specific
|
||||
String16 string_to_string16(gbAllocator a, String s) {
|
||||
int len, len1;
|
||||
wchar_t *text;
|
||||
|
||||
if (s.len < 1) {
|
||||
return make_string16(NULL, 0);
|
||||
}
|
||||
|
||||
int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||
cast(char *)s.text, s.len, NULL, 0);
|
||||
len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||
cast(char *)s.text, s.len, NULL, 0);
|
||||
if (len == 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,
|
||||
cast(char *)s.text, s.len, text, len);
|
||||
len1 = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||
cast(char *)s.text, s.len, text, len);
|
||||
if (len1 == 0) {
|
||||
gb_free(a, text);
|
||||
return make_string16(NULL, 0);
|
||||
@@ -190,22 +207,23 @@ String16 string_to_string16(gbAllocator a, String s) {
|
||||
}
|
||||
|
||||
String string16_to_string(gbAllocator a, String16 s) {
|
||||
int len, len1;
|
||||
u8 *text;
|
||||
|
||||
if (s.len < 1) {
|
||||
return make_string(NULL, 0);
|
||||
}
|
||||
|
||||
int len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
|
||||
s.text, s.len, NULL, 0,
|
||||
NULL, NULL);
|
||||
len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
|
||||
s.text, s.len, NULL, 0, NULL, NULL);
|
||||
if (len == 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,
|
||||
s.text, s.len, cast(char *)text, len,
|
||||
NULL, NULL);
|
||||
len1 = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
|
||||
s.text, s.len, cast(char *)text, len, NULL, NULL);
|
||||
if (len1 == 0) {
|
||||
gb_free(a, text);
|
||||
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) {
|
||||
u8 c;
|
||||
|
||||
if (s.text[0] == quote &&
|
||||
(quote == '$' || quote == '"')) {
|
||||
(quote == '\'' || quote == '"')) {
|
||||
return false;
|
||||
} else if (s.text[0] >= 0x80) {
|
||||
Rune r = -1;
|
||||
@@ -252,7 +272,7 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
|
||||
if (s.len <= 1) {
|
||||
return false;
|
||||
}
|
||||
u8 c = s.text[1];
|
||||
c = s.text[1];
|
||||
s = make_string(s.text+2, s.len-2);
|
||||
|
||||
switch (c) {
|
||||
@@ -268,7 +288,7 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
|
||||
case '\\': *rune = '\\'; break;
|
||||
|
||||
|
||||
case '$':
|
||||
case '\'':
|
||||
case '"':
|
||||
if (c != quote) {
|
||||
return false;
|
||||
@@ -284,11 +304,12 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
|
||||
case '5':
|
||||
case '6':
|
||||
case '7': {
|
||||
isize i;
|
||||
i32 r = gb_digit_to_int(c);
|
||||
if (s.len < 2) {
|
||||
return false;
|
||||
}
|
||||
for (isize i = 0; i < 2; i++) {
|
||||
for (i = 0; i < 2; i++) {
|
||||
i32 d = gb_digit_to_int(s.text[i]);
|
||||
if (d < 0 || d > 7) {
|
||||
return false;
|
||||
@@ -305,18 +326,18 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
|
||||
case 'x':
|
||||
case 'u':
|
||||
case 'U': {
|
||||
isize count = 0;
|
||||
Rune r = 0;
|
||||
isize i, count = 0;
|
||||
switch (c) {
|
||||
case 'x': count = 2; break;
|
||||
case 'u': count = 4; break;
|
||||
case 'U': count = 8; break;
|
||||
}
|
||||
|
||||
Rune r = 0;
|
||||
if (s.len < count) {
|
||||
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]);
|
||||
if (d < 0) {
|
||||
return false;
|
||||
@@ -344,14 +365,16 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
|
||||
// 1 == original memory
|
||||
// 2 == new allocation
|
||||
i32 unquote_string(gbAllocator a, String *s_) {
|
||||
GB_ASSERT(s_ != NULL);
|
||||
String s = *s_;
|
||||
isize n = s.len;
|
||||
if (n < 2)
|
||||
u8 quote;
|
||||
if (n < 2) {
|
||||
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;
|
||||
}
|
||||
s.text += 1;
|
||||
s.len -= 2;
|
||||
|
||||
@@ -362,17 +385,19 @@ i32 unquote_string(gbAllocator a, String *s_) {
|
||||
*s_ = s;
|
||||
return 1;
|
||||
}
|
||||
if (quote != '"' && quote != '$')
|
||||
if (quote != '"' && quote != '\'') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (string_contains_char(s, '\n'))
|
||||
if (string_contains_char(s, '\n')) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!string_contains_char(s, '\\') && !string_contains_char(s, quote)) {
|
||||
if (quote == '"') {
|
||||
*s_ = s;
|
||||
return 1;
|
||||
} else if (quote == '$') {
|
||||
} else if (quote == '\'') {
|
||||
Rune r = GB_RUNE_INVALID;
|
||||
isize size = gb_utf8_decode(s.text, s.len, &r);
|
||||
if ((size == s.len) && (r != -1 || size != 1)) {
|
||||
@@ -383,34 +408,36 @@ i32 unquote_string(gbAllocator a, String *s_) {
|
||||
}
|
||||
|
||||
|
||||
u8 rune_temp[4] = {0};
|
||||
isize buf_len = 3*s.len / 2;
|
||||
u8 *buf = gb_alloc_array(a, u8, buf_len);
|
||||
isize offset = 0;
|
||||
while (s.len > 0) {
|
||||
String tail_string = {0};
|
||||
Rune r = 0;
|
||||
bool multiple_bytes = false;
|
||||
bool success = unquote_char(s, quote, &r, &multiple_bytes, &tail_string);
|
||||
if (!success) {
|
||||
gb_free(a, buf);
|
||||
return 0;
|
||||
}
|
||||
s = tail_string;
|
||||
{
|
||||
u8 rune_temp[4] = {0};
|
||||
isize buf_len = 3*s.len / 2;
|
||||
u8 *buf = gb_alloc_array(a, u8, buf_len);
|
||||
isize offset = 0;
|
||||
while (s.len > 0) {
|
||||
String tail_string = {0};
|
||||
Rune r = 0;
|
||||
bool multiple_bytes = false;
|
||||
bool success = unquote_char(s, quote, &r, &multiple_bytes, &tail_string);
|
||||
if (!success) {
|
||||
gb_free(a, buf);
|
||||
return 0;
|
||||
}
|
||||
s = tail_string;
|
||||
|
||||
if (r < 0x80 || !multiple_bytes) {
|
||||
buf[offset++] = cast(u8)r;
|
||||
} else {
|
||||
isize size = gb_utf8_encode_rune(rune_temp, r);
|
||||
gb_memmove(buf+offset, rune_temp, size);
|
||||
offset += size;
|
||||
}
|
||||
if (r < 0x80 || !multiple_bytes) {
|
||||
buf[offset++] = cast(u8)r;
|
||||
} else {
|
||||
isize size = gb_utf8_encode_rune(rune_temp, r);
|
||||
gb_memmove(buf+offset, rune_temp, size);
|
||||
offset += size;
|
||||
}
|
||||
|
||||
if (quote == '$' && s.len != 0) {
|
||||
gb_free(a, buf);
|
||||
return 0;
|
||||
if (quote == '\'' && s.len != 0) {
|
||||
gb_free(a, buf);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*s_ = make_string(buf, offset);
|
||||
}
|
||||
*s_ = make_string(buf, offset);
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -77,12 +77,13 @@ f64 time_stamp_as_ms(TimeStamp ts, u64 freq) {
|
||||
}
|
||||
|
||||
void timings_print_all(Timings *t) {
|
||||
char const SPACES[] = " ";
|
||||
isize max_len, i;
|
||||
|
||||
timings__stop_current_section(t);
|
||||
t->total.finish = time_stamp_time_now();
|
||||
|
||||
char const SPACES[] = " ";
|
||||
|
||||
isize max_len = t->total.label.len;
|
||||
max_len = t->total.label.len;
|
||||
for_array(i, t->sections) {
|
||||
TimeStamp ts = t->sections.e[i];
|
||||
max_len = gb_max(max_len, ts.label.len);
|
||||
|
||||
@@ -34,9 +34,6 @@ TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \
|
||||
TOKEN_KIND(Token_transmute, "transmute"), \
|
||||
TOKEN_KIND(Token_down_cast, "down_cast"), \
|
||||
TOKEN_KIND(Token_union_cast, "union_cast"), \
|
||||
\
|
||||
TOKEN_KIND(Token_Prime, "'"), \
|
||||
TOKEN_KIND(Token_DoublePrime, "''"), \
|
||||
\
|
||||
TOKEN_KIND(Token_CmpAnd, "&&"), \
|
||||
TOKEN_KIND(Token_CmpOr, "||"), \
|
||||
@@ -656,17 +653,50 @@ Token tokenizer_get_token(Tokenizer *t) {
|
||||
token.kind = Token_EOF;
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
token.kind = Token_Prime;
|
||||
if (t->curr_rune == '\'') {
|
||||
case '\'': // Rune Literal
|
||||
{
|
||||
token.kind = Token_Rune;
|
||||
Rune quote = curr_rune;
|
||||
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;
|
||||
}
|
||||
advance_to_next_rune(t);
|
||||
token.kind = Token_DoublePrime;
|
||||
if (r == quote) {
|
||||
break;
|
||||
}
|
||||
n++;
|
||||
if (r == '\\') {
|
||||
if (!scan_escape(t, quote)) {
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// 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 '"': // String Literal
|
||||
{
|
||||
i32 success;
|
||||
Rune quote = curr_rune;
|
||||
token.kind = Token_String;
|
||||
if (curr_rune == '"') {
|
||||
@@ -677,10 +707,12 @@ Token tokenizer_get_token(Tokenizer *t) {
|
||||
break;
|
||||
}
|
||||
advance_to_next_rune(t);
|
||||
if (r == quote)
|
||||
if (r == quote) {
|
||||
break;
|
||||
if (r == '\\')
|
||||
scan_escape(t, '"');
|
||||
}
|
||||
if (r == '\\') {
|
||||
scan_escape(t, quote);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (;;) {
|
||||
@@ -690,12 +722,13 @@ Token tokenizer_get_token(Tokenizer *t) {
|
||||
break;
|
||||
}
|
||||
advance_to_next_rune(t);
|
||||
if (r == quote)
|
||||
if (r == quote) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 == 2) {
|
||||
array_add(&t->allocated_strings, token.string);
|
||||
|
||||
@@ -42,10 +42,10 @@ bool rune_is_whitespace(Rune r) {
|
||||
|
||||
|
||||
bool is_string_an_identifier(String s) {
|
||||
isize offset = 0;
|
||||
if (s.len < 1) {
|
||||
return false;
|
||||
}
|
||||
isize offset = 0;
|
||||
while (offset < s.len) {
|
||||
bool ok = false;
|
||||
Rune r = -1;
|
||||
|
||||
Reference in New Issue
Block a user