mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 07:08:48 +00:00
Complex numbers: complex64 complex128
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
set exe_name=odin.exe
|
set exe_name=odin.exe
|
||||||
|
|
||||||
:: Debug = 0, Release = 1
|
:: Debug = 0, Release = 1
|
||||||
set release_mode=1
|
set release_mode=0
|
||||||
set compiler_flags= -nologo -Oi -TC -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
|
set compiler_flags= -nologo -Oi -TC -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
|
||||||
|
|
||||||
if %release_mode% EQU 0 ( rem Debug
|
if %release_mode% EQU 0 ( rem Debug
|
||||||
|
|||||||
+2
-313
@@ -1,320 +1,9 @@
|
|||||||
#import "atomic.odin";
|
|
||||||
#import "hash.odin";
|
|
||||||
#import "mem.odin";
|
|
||||||
#import "opengl.odin";
|
|
||||||
#import "strconv.odin";
|
|
||||||
#import "sync.odin";
|
|
||||||
#import win32 "sys/windows.odin";
|
|
||||||
|
|
||||||
#import "fmt.odin";
|
#import "fmt.odin";
|
||||||
#import "os.odin";
|
#import "os.odin";
|
||||||
#import "math.odin";
|
#import "math.odin";
|
||||||
|
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
when true {
|
x := 1+2i;
|
||||||
/*
|
fmt.printf("%v\n", x);
|
||||||
Added:
|
|
||||||
* Unexported entities and fields using an underscore prefix
|
|
||||||
- See `sync.odin` and explain
|
|
||||||
|
|
||||||
Removed:
|
|
||||||
* Maybe/option types
|
|
||||||
* Remove `type` keyword and other "reserved" keywords
|
|
||||||
* ..< and ... removed and replace with .. (half-closed range)
|
|
||||||
|
|
||||||
Changed:
|
|
||||||
* `compile_assert` and `assert`return the value of the condition for semantic reasons
|
|
||||||
* thread_local -> #thread_local
|
|
||||||
* #include -> #load
|
|
||||||
* Files only get checked if they are actually used
|
|
||||||
* match x in y {} // For type match statements
|
|
||||||
* Version numbering now starts from 0.1.0 and uses the convention:
|
|
||||||
- major.minor.patch
|
|
||||||
* Core library additions to Windows specific stuff
|
|
||||||
*/
|
|
||||||
|
|
||||||
{
|
|
||||||
Fruit :: enum {
|
|
||||||
APPLE,
|
|
||||||
BANANA,
|
|
||||||
COCONUT,
|
|
||||||
}
|
|
||||||
fmt.println(Fruit.names);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
A :: struct {x, y: f32};
|
|
||||||
B :: struct #align 16 {x, y: f32};
|
|
||||||
fmt.println("align_of(A) =", align_of(A));
|
|
||||||
fmt.println("align_of(B) =", align_of(B));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Removal of ..< and ...
|
|
||||||
for i in 0..16 {
|
|
||||||
}
|
|
||||||
// Is similar to
|
|
||||||
for _i := 0; _i < 16; _i++ { immutable i := _i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
#label thing
|
|
||||||
for i in 0..10 {
|
|
||||||
for j in i+1..10 {
|
|
||||||
if j == 2 {
|
|
||||||
fmt.println(i, j);
|
|
||||||
continue thing;
|
|
||||||
}
|
|
||||||
if j == 3 {
|
|
||||||
break thing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Works with, `for`, `for in`, `match`, `match in`
|
|
||||||
// NOTE(bill): This solves most of the problems I need `goto` for
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
t := type_info(int);
|
|
||||||
using Type_Info;
|
|
||||||
match i in t {
|
|
||||||
case Integer, Float:
|
|
||||||
fmt.println("It's a number");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
x: any = 123;
|
|
||||||
#label foo
|
|
||||||
match i in x {
|
|
||||||
case int, f32:
|
|
||||||
fmt.println("It's an int or f32");
|
|
||||||
break foo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
cond := true;
|
|
||||||
x: int;
|
|
||||||
if cond {
|
|
||||||
x = 3;
|
|
||||||
} else {
|
|
||||||
x = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Ternary operator
|
|
||||||
y := cond ? 3 : 4;
|
|
||||||
|
|
||||||
FOO :: true ? 123 : 432; // Constant ternary expression
|
|
||||||
fmt.println("Ternary values:", y, FOO);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Slices now store a capacity
|
|
||||||
buf: [256]byte;
|
|
||||||
s: []byte;
|
|
||||||
s = buf[..0]; // == buf[0..0];
|
|
||||||
fmt.println("count =", s.count);
|
|
||||||
fmt.println("capacity =", s.capacity);
|
|
||||||
append(s, 1, 2, 3);
|
|
||||||
fmt.println(s);
|
|
||||||
|
|
||||||
s = buf[1..2..3];
|
|
||||||
fmt.println("count =", s.count);
|
|
||||||
fmt.println("capacity =", s.capacity);
|
|
||||||
fmt.println(s);
|
|
||||||
|
|
||||||
clear(s); // Sets count to zero
|
|
||||||
s.count = 0; // Equivalent
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
Foo :: struct {
|
|
||||||
x, y, z: f32,
|
|
||||||
ok: bool,
|
|
||||||
flags: u32,
|
|
||||||
}
|
|
||||||
foo_array: [256]Foo;
|
|
||||||
foo_as_bytes: []byte = slice_to_bytes(foo_array[..]);
|
|
||||||
// Useful for things like
|
|
||||||
// os.write(handle, foo_as_bytes);
|
|
||||||
|
|
||||||
foo_slice := slice_ptr(cast(^Foo)foo_as_bytes.data, foo_as_bytes.count/size_of(Foo), foo_as_bytes.capacity/size_of(Foo));
|
|
||||||
// Question: Should there be a bytes_to_slice procedure or is it clearer to do this even if it is error prone?
|
|
||||||
// And if so what would the syntax be?
|
|
||||||
// slice_transmute([]Foo, foo_as_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
Vec3 :: [vector 3]f32;
|
|
||||||
|
|
||||||
x := Vec3{1, 2, 3};
|
|
||||||
y := Vec3{4, 5, 6};
|
|
||||||
fmt.println(x < y);
|
|
||||||
fmt.println(x + y);
|
|
||||||
fmt.println(x - y);
|
|
||||||
fmt.println(x * y);
|
|
||||||
fmt.println(x / y);
|
|
||||||
|
|
||||||
for i in x {
|
|
||||||
fmt.println(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
compile_assert(size_of([vector 7]bool) == size_of([7]bool));
|
|
||||||
compile_assert(size_of([vector 7]i32) == size_of([7]i32));
|
|
||||||
// align_of([vector 7]i32) != align_of([7]i32) // this may be the case
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// fmt.* changes
|
|
||||||
// bprint* returns `int` (bytes written)
|
|
||||||
// sprint* returns `string` (bytes written as a string)
|
|
||||||
|
|
||||||
data: [256]byte;
|
|
||||||
str := fmt.sprintf(data[..0], "Hellope %d %s %c", 123, "others", '!');
|
|
||||||
fmt.println(str);
|
|
||||||
|
|
||||||
buf := data[..0];
|
|
||||||
count := fmt.bprintf(^buf, "Hellope %d %s %c", 123, "others", '!');
|
|
||||||
fmt.println(cast(string)buf[..count]);
|
|
||||||
|
|
||||||
// NOTE(bill): We may change this but because this is a library feature, I am not that bothered yet
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
x: [dynamic]f64;
|
|
||||||
reserve(x, 16);
|
|
||||||
defer free(x); // `free` is overloaded for numerous types
|
|
||||||
// Number literals can have underscores in them for readability
|
|
||||||
append(x, 2_000_000.500_000, 3, 5, 7); // variadic append
|
|
||||||
|
|
||||||
for p, i in x {
|
|
||||||
if i > 0 { fmt.print(", "); }
|
|
||||||
fmt.print(p);
|
|
||||||
}
|
|
||||||
fmt.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Dynamic array "literals"
|
|
||||||
x := [dynamic]f64{2_000_000.500_000, 3, 5, 7};
|
|
||||||
defer free(x);
|
|
||||||
fmt.println(x); // fmt.print* supports printing of dynamic types
|
|
||||||
clear(x);
|
|
||||||
fmt.println(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
m: map[f32]int;
|
|
||||||
reserve(m, 16);
|
|
||||||
defer free(m);
|
|
||||||
|
|
||||||
m[1.0] = 1278;
|
|
||||||
m[2.0] = 7643;
|
|
||||||
m[3.0] = 564;
|
|
||||||
_, ok := m[3.0];
|
|
||||||
c := m[3.0];
|
|
||||||
assert(ok && c == 564);
|
|
||||||
|
|
||||||
fmt.print("map[");
|
|
||||||
i := 0;
|
|
||||||
for val, key in m {
|
|
||||||
if i > 0 {
|
|
||||||
fmt.print(", ");
|
|
||||||
}
|
|
||||||
fmt.printf("%v=%v", key, val);
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
fmt.println("]");
|
|
||||||
}
|
|
||||||
{
|
|
||||||
m := map[string]u32{
|
|
||||||
"a" = 56,
|
|
||||||
"b" = 13453,
|
|
||||||
"c" = 7654,
|
|
||||||
};
|
|
||||||
defer free(m);
|
|
||||||
|
|
||||||
c := m["c"];
|
|
||||||
_, ok := m["c"];
|
|
||||||
assert(ok && c == 7654);
|
|
||||||
fmt.println(m);
|
|
||||||
|
|
||||||
delete(m, "c"); // deletes entry with key "c"
|
|
||||||
_, found := m["c"];
|
|
||||||
assert(!found);
|
|
||||||
|
|
||||||
fmt.println(m);
|
|
||||||
clear(m);
|
|
||||||
fmt.println(m);
|
|
||||||
|
|
||||||
// NOTE: Fixed size maps are planned but we have not yet implemented
|
|
||||||
// them as we have had no need for them as of yet
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
Vector3 :: struct{x, y, z: f32};
|
|
||||||
Quaternion :: struct{x, y, z, w: f32};
|
|
||||||
|
|
||||||
Entity :: union {
|
|
||||||
// Common Fields
|
|
||||||
id: u64,
|
|
||||||
name: string,
|
|
||||||
using position: Vector3,
|
|
||||||
orientation: Quaternion,
|
|
||||||
flags: u32,
|
|
||||||
|
|
||||||
// Variants
|
|
||||||
Frog{
|
|
||||||
ribbit_volume: f32,
|
|
||||||
jump_height: f32,
|
|
||||||
},
|
|
||||||
Door{
|
|
||||||
openness: f32,
|
|
||||||
},
|
|
||||||
Map{
|
|
||||||
width, height: f32,
|
|
||||||
place_positions: []Vector3,
|
|
||||||
place_names: []string,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
entity: Entity;
|
|
||||||
// implicit conversion from variant to base type
|
|
||||||
entity = Entity.Frog{
|
|
||||||
id = 1337,
|
|
||||||
ribbit_volume = 0.5,
|
|
||||||
jump_height = 2.1,
|
|
||||||
/*other data */
|
|
||||||
};
|
|
||||||
|
|
||||||
entity.name = "Frank";
|
|
||||||
entity.position = Vector3{1, 4, 9};
|
|
||||||
|
|
||||||
using Entity;
|
|
||||||
match e in entity {
|
|
||||||
case Frog:
|
|
||||||
fmt.println("Ribbit");
|
|
||||||
case Door:
|
|
||||||
fmt.println("Creak");
|
|
||||||
case Map:
|
|
||||||
fmt.println("Rustle");
|
|
||||||
default:
|
|
||||||
fmt.println("Just a normal entity");
|
|
||||||
}
|
|
||||||
|
|
||||||
if frog, ok := union_cast(Frog)entity; ok {
|
|
||||||
fmt.printf("The frog jumps %f feet high at %v\n", frog.jump_height, frog.position);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Panics if not the correct type
|
|
||||||
frog: Frog;
|
|
||||||
frog = union_cast(Frog)entity;
|
|
||||||
frog, _ = union_cast(Frog)entity; // ignore error and force cast
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ Type_Info :: union {
|
|||||||
Named{name: string, base: ^Type_Info},
|
Named{name: string, base: ^Type_Info},
|
||||||
Integer{size: int, signed: bool},
|
Integer{size: int, signed: bool},
|
||||||
Float{size: int},
|
Float{size: int},
|
||||||
|
Complex{size: int},
|
||||||
String{},
|
String{},
|
||||||
Boolean{},
|
Boolean{},
|
||||||
Any{},
|
Any{},
|
||||||
|
|||||||
+29
-3
@@ -110,6 +110,11 @@ write_type :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
|||||||
case 4: write_string(buf, "f32");
|
case 4: write_string(buf, "f32");
|
||||||
case 8: write_string(buf, "f64");
|
case 8: write_string(buf, "f64");
|
||||||
}
|
}
|
||||||
|
case Complex:
|
||||||
|
match info.size {
|
||||||
|
case 8: write_string(buf, "complex64");
|
||||||
|
case 16: write_string(buf, "complex128");
|
||||||
|
}
|
||||||
case String: write_string(buf, "string");
|
case String: write_string(buf, "string");
|
||||||
case Boolean: write_string(buf, "bool");
|
case Boolean: write_string(buf, "bool");
|
||||||
case Pointer:
|
case Pointer:
|
||||||
@@ -733,6 +738,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
|
|
||||||
case Boolean: fmt_arg(fi, v, verb);
|
case Boolean: fmt_arg(fi, v, verb);
|
||||||
case Float: fmt_arg(fi, v, verb);
|
case Float: fmt_arg(fi, v, verb);
|
||||||
|
case Complex: fmt_arg(fi, v, verb);
|
||||||
case Integer: fmt_arg(fi, v, verb);
|
case Integer: fmt_arg(fi, v, verb);
|
||||||
case String: fmt_arg(fi, v, verb);
|
case String: fmt_arg(fi, v, verb);
|
||||||
|
|
||||||
@@ -883,6 +889,24 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt_complex :: proc(fi: ^Fmt_Info, c: complex128, bits: int, verb: rune) {
|
||||||
|
match verb {
|
||||||
|
case 'f', 'F', 'v':
|
||||||
|
r := real(c);
|
||||||
|
i := imag(c);
|
||||||
|
fmt_float(fi, r, bits/2, verb);
|
||||||
|
if !fi.plus && i >= 0 {
|
||||||
|
write_rune(fi.buf, '+');
|
||||||
|
}
|
||||||
|
fmt_float(fi, i, bits/2, verb);
|
||||||
|
write_rune(fi.buf, 'i');
|
||||||
|
|
||||||
|
default:
|
||||||
|
fmt_bad_verb(fi, verb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
|
fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
|
||||||
if arg.data == nil || arg.type_info == nil {
|
if arg.data == nil || arg.type_info == nil {
|
||||||
write_string(fi.buf, "<nil>");
|
write_string(fi.buf, "<nil>");
|
||||||
@@ -903,9 +927,11 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
|
|||||||
base_arg := arg;
|
base_arg := arg;
|
||||||
base_arg.type_info = type_info_base(base_arg.type_info);
|
base_arg.type_info = type_info_base(base_arg.type_info);
|
||||||
match a in base_arg {
|
match a in base_arg {
|
||||||
case bool: fmt_bool(fi, a, verb);
|
case bool: fmt_bool(fi, a, verb);
|
||||||
case f32: fmt_float(fi, cast(f64)a, 32, verb);
|
case f32: fmt_float(fi, cast(f64)a, 32, verb);
|
||||||
case f64: fmt_float(fi, a, 64, verb);
|
case f64: fmt_float(fi, a, 64, verb);
|
||||||
|
case complex64: fmt_complex(fi, cast(complex128)a, 64, verb);
|
||||||
|
case complex128: fmt_complex(fi, a, 128, verb);
|
||||||
|
|
||||||
case int: fmt_int(fi, cast(u64)a, true, 8*size_of(int), verb);
|
case int: fmt_int(fi, cast(u64)a, true, 8*size_of(int), verb);
|
||||||
case i8: fmt_int(fi, cast(u64)a, true, 8, verb);
|
case i8: fmt_int(fi, cast(u64)a, true, 8, verb);
|
||||||
|
|||||||
+6
-6
@@ -27,14 +27,14 @@ Mat4 :: [4]Vec4;
|
|||||||
sqrt :: proc(x: f32) -> f32 #foreign __llvm_core "llvm.sqrt.f32";
|
sqrt :: proc(x: f32) -> f32 #foreign __llvm_core "llvm.sqrt.f32";
|
||||||
sqrt :: proc(x: f64) -> f64 #foreign __llvm_core "llvm.sqrt.f64";
|
sqrt :: proc(x: f64) -> f64 #foreign __llvm_core "llvm.sqrt.f64";
|
||||||
|
|
||||||
sin :: proc(x: f32) -> f32 #foreign __llvm_core "llvm.sin.f32";
|
sin :: proc(θ: f32) -> f32 #foreign __llvm_core "llvm.sin.f32";
|
||||||
sin :: proc(x: f64) -> f64 #foreign __llvm_core "llvm.sin.f64";
|
sin :: proc(θ: f64) -> f64 #foreign __llvm_core "llvm.sin.f64";
|
||||||
|
|
||||||
cos :: proc(x: f32) -> f32 #foreign __llvm_core "llvm.cos.f32";
|
cos :: proc(θ: f32) -> f32 #foreign __llvm_core "llvm.cos.f32";
|
||||||
cos :: proc(x: f64) -> f64 #foreign __llvm_core "llvm.cos.f64";
|
cos :: proc(θ: f64) -> f64 #foreign __llvm_core "llvm.cos.f64";
|
||||||
|
|
||||||
tan :: proc(x: f32) -> f32 #inline { return sin(x)/cos(x); }
|
tan :: proc(θ: f32) -> f32 #inline { return sin(θ)/cos(θ); }
|
||||||
tan :: proc(x: f64) -> f64 #inline { return sin(x)/cos(x); }
|
tan :: proc(θ: f64) -> f64 #inline { return sin(θ)/cos(θ); }
|
||||||
|
|
||||||
pow :: proc(x, power: f32) -> f32 #foreign __llvm_core "llvm.pow.f32";
|
pow :: proc(x, power: f32) -> f32 #foreign __llvm_core "llvm.pow.f32";
|
||||||
pow :: proc(x, power: f64) -> f64 #foreign __llvm_core "llvm.pow.f64";
|
pow :: proc(x, power: f64) -> f64 #foreign __llvm_core "llvm.pow.f64";
|
||||||
|
|||||||
+115
-52
@@ -1,6 +1,4 @@
|
|||||||
#import w "sys/windows.odin";
|
#import win32 "sys/windows.odin";
|
||||||
#import "fmt.odin";
|
|
||||||
|
|
||||||
|
|
||||||
Handle :: int;
|
Handle :: int;
|
||||||
File_Time :: u64;
|
File_Time :: u64;
|
||||||
@@ -50,6 +48,8 @@ WSAECONNRESET: Errno : 10054;
|
|||||||
ERROR_FILE_IS_PIPE: Errno : 1<<29 + 0;
|
ERROR_FILE_IS_PIPE: Errno : 1<<29 + 0;
|
||||||
|
|
||||||
|
|
||||||
|
// "Argv" arguments converted to Odin strings
|
||||||
|
args := _alloc_command_line_arguments();
|
||||||
|
|
||||||
|
|
||||||
open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
|
open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
|
||||||
@@ -59,22 +59,22 @@ open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
|
|||||||
|
|
||||||
access: u32;
|
access: u32;
|
||||||
match mode & (O_RDONLY|O_WRONLY|O_RDWR) {
|
match mode & (O_RDONLY|O_WRONLY|O_RDWR) {
|
||||||
case O_RDONLY: access = w.FILE_GENERIC_READ;
|
case O_RDONLY: access = win32.FILE_GENERIC_READ;
|
||||||
case O_WRONLY: access = w.FILE_GENERIC_WRITE;
|
case O_WRONLY: access = win32.FILE_GENERIC_WRITE;
|
||||||
case O_RDWR: access = w.FILE_GENERIC_READ | w.FILE_GENERIC_WRITE;
|
case O_RDWR: access = win32.FILE_GENERIC_READ | win32.FILE_GENERIC_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if mode&O_CREAT != 0 {
|
if mode&O_CREAT != 0 {
|
||||||
access |= w.FILE_GENERIC_WRITE;
|
access |= win32.FILE_GENERIC_WRITE;
|
||||||
}
|
}
|
||||||
if mode&O_APPEND != 0 {
|
if mode&O_APPEND != 0 {
|
||||||
access &~= w.FILE_GENERIC_WRITE;
|
access &~= win32.FILE_GENERIC_WRITE;
|
||||||
access |= w.FILE_APPEND_DATA;
|
access |= win32.FILE_APPEND_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
share_mode := cast(u32)(w.FILE_SHARE_READ|w.FILE_SHARE_WRITE);
|
share_mode := cast(u32)(win32.FILE_SHARE_READ|win32.FILE_SHARE_WRITE);
|
||||||
sa: ^w.Security_Attributes = nil;
|
sa: ^win32.Security_Attributes = nil;
|
||||||
sa_inherit := w.Security_Attributes{length = size_of(w.Security_Attributes), inherit_handle = 1};
|
sa_inherit := win32.Security_Attributes{length = size_of(win32.Security_Attributes), inherit_handle = 1};
|
||||||
if mode&O_CLOEXEC == 0 {
|
if mode&O_CLOEXEC == 0 {
|
||||||
sa = ^sa_inherit;
|
sa = ^sa_inherit;
|
||||||
}
|
}
|
||||||
@@ -82,37 +82,37 @@ open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
|
|||||||
create_mode: u32;
|
create_mode: u32;
|
||||||
match {
|
match {
|
||||||
case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
|
case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
|
||||||
create_mode = w.CREATE_NEW;
|
create_mode = win32.CREATE_NEW;
|
||||||
case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC):
|
case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC):
|
||||||
create_mode = w.CREATE_ALWAYS;
|
create_mode = win32.CREATE_ALWAYS;
|
||||||
case mode&O_CREAT == O_CREAT:
|
case mode&O_CREAT == O_CREAT:
|
||||||
create_mode = w.OPEN_ALWAYS;
|
create_mode = win32.OPEN_ALWAYS;
|
||||||
case mode&O_TRUNC == O_TRUNC:
|
case mode&O_TRUNC == O_TRUNC:
|
||||||
create_mode = w.TRUNCATE_EXISTING;
|
create_mode = win32.TRUNCATE_EXISTING;
|
||||||
default:
|
default:
|
||||||
create_mode = w.OPEN_EXISTING;
|
create_mode = win32.OPEN_EXISTING;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf: [300]byte;
|
buf: [300]byte;
|
||||||
copy(buf[..], cast([]byte)path);
|
copy(buf[..], cast([]byte)path);
|
||||||
|
|
||||||
handle := cast(Handle)w.CreateFileA(^buf[0], access, share_mode, sa, create_mode, w.FILE_ATTRIBUTE_NORMAL, nil);
|
handle := cast(Handle)win32.CreateFileA(^buf[0], access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL, nil);
|
||||||
if handle != INVALID_HANDLE {
|
if handle != INVALID_HANDLE {
|
||||||
return handle, ERROR_NONE;
|
return handle, ERROR_NONE;
|
||||||
}
|
}
|
||||||
err := w.GetLastError();
|
err := win32.GetLastError();
|
||||||
return INVALID_HANDLE, cast(Errno)err;
|
return INVALID_HANDLE, cast(Errno)err;
|
||||||
}
|
}
|
||||||
|
|
||||||
close :: proc(fd: Handle) {
|
close :: proc(fd: Handle) {
|
||||||
w.CloseHandle(cast(w.Handle)fd);
|
win32.CloseHandle(cast(win32.Handle)fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
||||||
bytes_written: i32;
|
bytes_written: i32;
|
||||||
e := w.WriteFile(cast(w.Handle)fd, data.data, cast(i32)data.count, ^bytes_written, nil);
|
e := win32.WriteFile(cast(win32.Handle)fd, data.data, cast(i32)data.count, ^bytes_written, nil);
|
||||||
if e == w.FALSE {
|
if e == win32.FALSE {
|
||||||
err := w.GetLastError();
|
err := win32.GetLastError();
|
||||||
return 0, cast(Errno)err;
|
return 0, cast(Errno)err;
|
||||||
}
|
}
|
||||||
return cast(int)bytes_written, ERROR_NONE;
|
return cast(int)bytes_written, ERROR_NONE;
|
||||||
@@ -120,31 +120,30 @@ write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
|||||||
|
|
||||||
read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
||||||
bytes_read: i32;
|
bytes_read: i32;
|
||||||
e := w.ReadFile(cast(w.Handle)fd, data.data, cast(u32)data.count, ^bytes_read, nil);
|
e := win32.ReadFile(cast(win32.Handle)fd, data.data, cast(u32)data.count, ^bytes_read, nil);
|
||||||
if e == w.FALSE {
|
if e == win32.FALSE {
|
||||||
err := w.GetLastError();
|
err := win32.GetLastError();
|
||||||
return 0, cast(Errno)err;
|
return 0, cast(Errno)err;
|
||||||
}
|
}
|
||||||
return cast(int)bytes_read, ERROR_NONE;
|
return cast(int)bytes_read, ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
||||||
using w;
|
|
||||||
w: u32;
|
w: u32;
|
||||||
match whence {
|
match whence {
|
||||||
case 0: w = FILE_BEGIN;
|
case 0: w = win32.FILE_BEGIN;
|
||||||
case 1: w = FILE_CURRENT;
|
case 1: w = win32.FILE_CURRENT;
|
||||||
case 2: w = FILE_END;
|
case 2: w = win32.FILE_END;
|
||||||
}
|
}
|
||||||
hi := cast(i32)(offset>>32);
|
hi := cast(i32)(offset>>32);
|
||||||
lo := cast(i32)(offset);
|
lo := cast(i32)(offset);
|
||||||
ft := GetFileType(cast(Handle)fd);
|
ft := win32.GetFileType(cast(win32.Handle)fd);
|
||||||
if ft == FILE_TYPE_PIPE {
|
if ft == win32.FILE_TYPE_PIPE {
|
||||||
return 0, ERROR_FILE_IS_PIPE;
|
return 0, ERROR_FILE_IS_PIPE;
|
||||||
}
|
}
|
||||||
dw_ptr := SetFilePointer(cast(Handle)fd, lo, ^hi, w);
|
dw_ptr := win32.SetFilePointer(cast(win32.Handle)fd, lo, ^hi, w);
|
||||||
if dw_ptr == INVALID_SET_FILE_POINTER {
|
if dw_ptr == win32.INVALID_SET_FILE_POINTER {
|
||||||
err := GetLastError();
|
err := win32.GetLastError();
|
||||||
return 0, cast(Errno)err;
|
return 0, cast(Errno)err;
|
||||||
}
|
}
|
||||||
return cast(i64)hi<<32 + cast(i64)dw_ptr, ERROR_NONE;
|
return cast(i64)hi<<32 + cast(i64)dw_ptr, ERROR_NONE;
|
||||||
@@ -152,14 +151,14 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
|||||||
|
|
||||||
|
|
||||||
// NOTE(bill): Uses startup to initialize it
|
// NOTE(bill): Uses startup to initialize it
|
||||||
stdin := get_std_handle(w.STD_INPUT_HANDLE);
|
stdin := get_std_handle(win32.STD_INPUT_HANDLE);
|
||||||
stdout := get_std_handle(w.STD_OUTPUT_HANDLE);
|
stdout := get_std_handle(win32.STD_OUTPUT_HANDLE);
|
||||||
stderr := get_std_handle(w.STD_ERROR_HANDLE);
|
stderr := get_std_handle(win32.STD_ERROR_HANDLE);
|
||||||
|
|
||||||
|
|
||||||
get_std_handle :: proc(h: int) -> Handle {
|
get_std_handle :: proc(h: int) -> Handle {
|
||||||
fd := w.GetStdHandle(cast(i32)h);
|
fd := win32.GetStdHandle(cast(i32)h);
|
||||||
w.SetHandleInformation(fd, w.HANDLE_FLAG_INHERIT, 0);
|
win32.SetHandleInformation(fd, win32.HANDLE_FLAG_INHERIT, 0);
|
||||||
return cast(Handle)fd;
|
return cast(Handle)fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,23 +168,23 @@ get_std_handle :: proc(h: int) -> Handle {
|
|||||||
|
|
||||||
|
|
||||||
last_write_time :: proc(fd: Handle) -> File_Time {
|
last_write_time :: proc(fd: Handle) -> File_Time {
|
||||||
file_info: w.By_Handle_File_Information;
|
file_info: win32.By_Handle_File_Information;
|
||||||
w.GetFileInformationByHandle(cast(w.Handle)fd, ^file_info);
|
win32.GetFileInformationByHandle(cast(win32.Handle)fd, ^file_info);
|
||||||
lo := cast(File_Time)file_info.last_write_time.lo;
|
lo := cast(File_Time)file_info.last_write_time.lo;
|
||||||
hi := cast(File_Time)file_info.last_write_time.hi;
|
hi := cast(File_Time)file_info.last_write_time.hi;
|
||||||
return lo | hi << 32;
|
return lo | hi << 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_write_time_by_name :: proc(name: string) -> File_Time {
|
last_write_time_by_name :: proc(name: string) -> File_Time {
|
||||||
last_write_time: w.Filetime;
|
last_write_time: win32.Filetime;
|
||||||
data: w.File_Attribute_Data;
|
data: win32.File_Attribute_Data;
|
||||||
buf: [1024]byte;
|
buf: [1024]byte;
|
||||||
|
|
||||||
assert(buf.count > name.count);
|
assert(buf.count > name.count);
|
||||||
|
|
||||||
copy(buf[..], cast([]byte)name);
|
copy(buf[..], cast([]byte)name);
|
||||||
|
|
||||||
if w.GetFileAttributesExA(^buf[0], w.GetFileExInfoStandard, ^data) != 0 {
|
if win32.GetFileAttributesExA(^buf[0], win32.GetFileExInfoStandard, ^data) != 0 {
|
||||||
last_write_time = data.last_write_time;
|
last_write_time = data.last_write_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +208,7 @@ read_entire_file :: proc(name: string) -> ([]byte, bool) {
|
|||||||
defer close(fd);
|
defer close(fd);
|
||||||
|
|
||||||
length: i64;
|
length: i64;
|
||||||
file_size_ok := w.GetFileSizeEx(cast(w.Handle)fd, ^length) != 0;
|
file_size_ok := win32.GetFileSizeEx(cast(win32.Handle)fd, ^length) != 0;
|
||||||
if !file_size_ok {
|
if !file_size_ok {
|
||||||
return nil, false;
|
return nil, false;
|
||||||
}
|
}
|
||||||
@@ -232,7 +231,7 @@ read_entire_file :: proc(name: string) -> ([]byte, bool) {
|
|||||||
to_read = MAX;
|
to_read = MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
w.ReadFile(cast(w.Handle)fd, ^data[total_read], to_read, ^single_read_length, nil);
|
win32.ReadFile(cast(win32.Handle)fd, ^data[total_read], to_read, ^single_read_length, nil);
|
||||||
if single_read_length <= 0 {
|
if single_read_length <= 0 {
|
||||||
free(data);
|
free(data);
|
||||||
return nil, false;
|
return nil, false;
|
||||||
@@ -247,7 +246,7 @@ read_entire_file :: proc(name: string) -> ([]byte, bool) {
|
|||||||
|
|
||||||
|
|
||||||
heap_alloc :: proc(size: int) -> rawptr {
|
heap_alloc :: proc(size: int) -> rawptr {
|
||||||
return w.HeapAlloc(w.GetProcessHeap(), w.HEAP_ZERO_MEMORY, size);
|
return win32.HeapAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, size);
|
||||||
}
|
}
|
||||||
heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
|
heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
|
||||||
if new_size == 0 {
|
if new_size == 0 {
|
||||||
@@ -257,25 +256,89 @@ heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
|
|||||||
if ptr == nil {
|
if ptr == nil {
|
||||||
return heap_alloc(new_size);
|
return heap_alloc(new_size);
|
||||||
}
|
}
|
||||||
return w.HeapReAlloc(w.GetProcessHeap(), w.HEAP_ZERO_MEMORY, ptr, new_size);
|
return win32.HeapReAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, ptr, new_size);
|
||||||
}
|
}
|
||||||
heap_free :: proc(ptr: rawptr) {
|
heap_free :: proc(ptr: rawptr) {
|
||||||
if ptr == nil {
|
if ptr == nil {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
w.HeapFree(w.GetProcessHeap(), 0, ptr);
|
win32.HeapFree(win32.GetProcessHeap(), 0, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
exit :: proc(code: int) {
|
exit :: proc(code: int) {
|
||||||
w.ExitProcess(cast(u32)code);
|
win32.ExitProcess(cast(u32)code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
current_thread_id :: proc() -> int {
|
current_thread_id :: proc() -> int {
|
||||||
return cast(int)w.GetCurrentThreadId();
|
return cast(int)win32.GetCurrentThreadId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_alloc_command_line_arguments :: proc() -> []string {
|
||||||
|
alloc_ucs2_to_utf8 :: proc(wstr: ^u16) -> string {
|
||||||
|
wstr_len := 0;
|
||||||
|
for (wstr+wstr_len)^ != 0 {
|
||||||
|
wstr_len++;
|
||||||
|
}
|
||||||
|
len := 2*wstr_len-1;
|
||||||
|
buf := new_slice(byte, len+1);
|
||||||
|
str := slice_ptr(wstr, wstr_len+1);
|
||||||
|
|
||||||
|
|
||||||
|
i, j := 0, 0;
|
||||||
|
for str[j] != 0 {
|
||||||
|
match {
|
||||||
|
case str[j] < 0x80:
|
||||||
|
if i+1 > len {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
buf[i] = cast(byte)str[j]; i++;
|
||||||
|
j++;
|
||||||
|
case str[j] < 0x800:
|
||||||
|
if i+2 > len {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
buf[i] = cast(byte)(0xc0 + (str[j]>>6)); i++;
|
||||||
|
buf[i] = cast(byte)(0x80 + (str[j]&0x3f)); i++;
|
||||||
|
j++;
|
||||||
|
case 0xd800 <= str[j] && str[j] < 0xdc00:
|
||||||
|
if i+4 > len {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
c := cast(rune)((str[j] - 0xd800) << 10) + cast(rune)((str[j+1]) - 0xdc00) + 0x10000;
|
||||||
|
buf[i] = cast(byte)(0xf0 + (c >> 18)); i++;
|
||||||
|
buf[i] = cast(byte)(0x80 + ((c >> 12) & 0x3f)); i++;
|
||||||
|
buf[i] = cast(byte)(0x80 + ((c >> 6) & 0x3f)); i++;
|
||||||
|
buf[i] = cast(byte)(0x80 + ((c ) & 0x3f)); i++;
|
||||||
|
j += 2;
|
||||||
|
case 0xdc00 <= str[j] && str[j] < 0xe000:
|
||||||
|
return "";
|
||||||
|
default:
|
||||||
|
if i+3 > len {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
buf[i] = 0xe0 + cast(byte) (str[j] >> 12); i++;
|
||||||
|
buf[i] = 0x80 + cast(byte)((str[j] >> 6) & 0x3f); i++;
|
||||||
|
buf[i] = 0x80 + cast(byte)((str[j] ) & 0x3f); i++;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cast(string)buf[..i];
|
||||||
|
}
|
||||||
|
|
||||||
|
arg_count: i32;
|
||||||
|
arg_list_ptr := win32.CommandLineToArgvW(win32.GetCommandLineW(), ^arg_count);
|
||||||
|
arg_list := new_slice(string, arg_count);
|
||||||
|
for _, i in arg_list {
|
||||||
|
arg_list[i] = alloc_ucs2_to_utf8((arg_list_ptr+i)^);
|
||||||
|
}
|
||||||
|
return arg_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+7
-20
@@ -313,29 +313,16 @@ append_bits :: proc(buf: []byte, u: u64, base: int, is_signed: bool, bit_size: i
|
|||||||
neg: bool;
|
neg: bool;
|
||||||
u, neg = is_integer_negative(u, is_signed, bit_size);
|
u, neg = is_integer_negative(u, is_signed, bit_size);
|
||||||
|
|
||||||
if is_pow2(cast(i64)base) {
|
for b := cast(u64)base; u >= b; {
|
||||||
b := cast(u64)base;
|
|
||||||
m := cast(uint)b - 1;
|
|
||||||
for u >= b {
|
|
||||||
i--;
|
|
||||||
a[i] = digits[cast(uint)u & m];
|
|
||||||
u >>= b;
|
|
||||||
}
|
|
||||||
i--;
|
i--;
|
||||||
a[i] = digits[cast(uint)u];
|
q := u / b;
|
||||||
} else {
|
a[i] = digits[cast(uint)(u-q*b)];
|
||||||
b := cast(u64)base;
|
u = q;
|
||||||
for u >= b {
|
|
||||||
i--;
|
|
||||||
q := u / b;
|
|
||||||
a[i] = digits[cast(uint)(u-q*b)];
|
|
||||||
u = q;
|
|
||||||
}
|
|
||||||
|
|
||||||
i--;
|
|
||||||
a[i] = digits[cast(uint)u];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i--;
|
||||||
|
a[i] = digits[cast(uint)u];
|
||||||
|
|
||||||
if flags&Int_Flag.PREFIX != 0 {
|
if flags&Int_Flag.PREFIX != 0 {
|
||||||
ok := true;
|
ok := true;
|
||||||
match base {
|
match base {
|
||||||
|
|||||||
+150
-3
@@ -1754,18 +1754,37 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
|
|||||||
if (v.kind != ExactValue_Float) {
|
if (v.kind != ExactValue_Float) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (out_value) *out_value = v;
|
||||||
|
|
||||||
|
|
||||||
switch (type->Basic.kind) {
|
switch (type->Basic.kind) {
|
||||||
// case Basic_f16:
|
|
||||||
case Basic_f32:
|
case Basic_f32:
|
||||||
case Basic_f64:
|
case Basic_f64:
|
||||||
// case Basic_f128:
|
|
||||||
if (out_value) *out_value = v;
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case Basic_UntypedFloat:
|
case Basic_UntypedFloat:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
} else if (is_type_complex(type)) {
|
||||||
|
ExactValue v = exact_value_to_complex(in_value);
|
||||||
|
if (v.kind != ExactValue_Complex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type->Basic.kind) {
|
||||||
|
case Basic_complex64:
|
||||||
|
case Basic_complex128: {
|
||||||
|
ExactValue real = exact_value_real(v);
|
||||||
|
ExactValue imag = exact_value_imag(v);
|
||||||
|
if (real.kind != ExactValue_Invalid &&
|
||||||
|
imag.kind != ExactValue_Invalid) {
|
||||||
|
if (out_value) *out_value = exact_binary_operator_value(Token_Add, real, exact_value_make_imag(imag));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
} else if (is_type_pointer(type)) {
|
} else if (is_type_pointer(type)) {
|
||||||
if (in_value.kind == ExactValue_Pointer) {
|
if (in_value.kind == ExactValue_Pointer) {
|
||||||
return true;
|
return true;
|
||||||
@@ -2190,6 +2209,10 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_type_complex(src) && is_type_complex(dst)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Cast between pointers
|
// Cast between pointers
|
||||||
if (is_type_pointer(src) && is_type_pointer(dst)) {
|
if (is_type_pointer(src) && is_type_pointer(dst)) {
|
||||||
Type *s = base_type(type_deref(src));
|
Type *s = base_type(type_deref(src));
|
||||||
@@ -3568,6 +3591,129 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
operand->mode = Addressing_Value;
|
operand->mode = Addressing_Value;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case BuiltinProc_complex: {
|
||||||
|
// complex :: proc(real, imag: float_type) -> complex_type
|
||||||
|
Operand x = *operand;
|
||||||
|
Operand y = {0};
|
||||||
|
|
||||||
|
// NOTE(bill): Invalid will be the default till fixed
|
||||||
|
operand->type = t_invalid;
|
||||||
|
operand->mode = Addressing_Invalid;
|
||||||
|
|
||||||
|
check_expr(c, &y, ce->args.e[1]);
|
||||||
|
if (y.mode == Addressing_Invalid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 flag = 0;
|
||||||
|
if (is_type_untyped(x.type)) {
|
||||||
|
flag |= 1;
|
||||||
|
}
|
||||||
|
if (is_type_untyped(y.type)) {
|
||||||
|
flag |= 2;
|
||||||
|
}
|
||||||
|
switch (flag) {
|
||||||
|
case 0: break;
|
||||||
|
case 1: convert_to_typed(c, &x, y.type, 0); break;
|
||||||
|
case 2: convert_to_typed(c, &y, x.type, 0); break;
|
||||||
|
case 3: {
|
||||||
|
if (x.mode == Addressing_Constant && y.mode == Addressing_Constant) {
|
||||||
|
if (is_type_numeric(x.type) && exact_value_imag(x.value).value_float == 0) {
|
||||||
|
x.type = t_untyped_float;
|
||||||
|
}
|
||||||
|
if (is_type_numeric(y.type) && exact_value_imag(y.value).value_float == 0) {
|
||||||
|
y.type = t_untyped_float;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
convert_to_typed(c, &x, t_f64, 0);
|
||||||
|
convert_to_typed(c, &y, t_f64, 0);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x.mode == Addressing_Invalid || y.mode == Addressing_Invalid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!are_types_identical(x.type, y.type)) {
|
||||||
|
gbString type_x = type_to_string(x.type);
|
||||||
|
gbString type_y = type_to_string(y.type);
|
||||||
|
error_node(call,
|
||||||
|
"Mismatched types to `complex`, `%s` vs `%s`",
|
||||||
|
type_x, type_y);
|
||||||
|
gb_string_free(type_y);
|
||||||
|
gb_string_free(type_x);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_type_float(x.type)) {
|
||||||
|
gbString s = type_to_string(x.type);
|
||||||
|
error_node(call, "Arguments have type `%s`, expected a floating point", s);
|
||||||
|
gb_string_free(s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x.mode == Addressing_Constant && y.mode == Addressing_Constant) {
|
||||||
|
operand->value = exact_binary_operator_value(Token_Add, x.value, y.value);
|
||||||
|
operand->mode = Addressing_Constant;
|
||||||
|
} else {
|
||||||
|
operand->mode = Addressing_Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicKind kind = core_type(x.type)->Basic.kind;
|
||||||
|
switch (kind) {
|
||||||
|
case Basic_f32: operand->type = t_complex64; break;
|
||||||
|
case Basic_f64: operand->type = t_complex128; break;
|
||||||
|
case Basic_UntypedFloat: operand->type = t_untyped_complex; break;
|
||||||
|
default: GB_PANIC("Invalid type"); break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case BuiltinProc_real:
|
||||||
|
case BuiltinProc_imag: {
|
||||||
|
// real :: proc(c: complex_type) -> float_type
|
||||||
|
// imag :: proc(c: complex_type) -> float_type
|
||||||
|
|
||||||
|
Operand *x = operand;
|
||||||
|
if (is_type_untyped(x->type)) {
|
||||||
|
if (x->mode == Addressing_Constant) {
|
||||||
|
if (is_type_numeric(x->type)) {
|
||||||
|
x->type = t_untyped_complex;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
convert_to_typed(c, x, t_complex128, 0);
|
||||||
|
if (x->mode == Addressing_Invalid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_type_complex(x->type)) {
|
||||||
|
gbString s = type_to_string(x->type);
|
||||||
|
error_node(call, "Argument has type `%s`, expected a complex type", s);
|
||||||
|
gb_string_free(s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x->mode == Addressing_Constant) {
|
||||||
|
if (id == BuiltinProc_real) {
|
||||||
|
x->value = exact_value_real(x->value);
|
||||||
|
} else {
|
||||||
|
x->value = exact_value_imag(x->value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
x->mode = Addressing_Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicKind kind = core_type(x->type)->Basic.kind;
|
||||||
|
switch (kind) {
|
||||||
|
case Basic_complex64: x->type = t_f32; break;
|
||||||
|
case Basic_complex128: x->type = t_f64; break;
|
||||||
|
case Basic_UntypedComplex: x->type = t_untyped_float; break;
|
||||||
|
default: GB_PANIC("Invalid type"); break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_slice_ptr: {
|
case BuiltinProc_slice_ptr: {
|
||||||
// slice_ptr :: proc(a: ^T, len: int) -> []T
|
// slice_ptr :: proc(a: ^T, len: int) -> []T
|
||||||
// slice_ptr :: proc(a: ^T, len, cap: int) -> []T
|
// slice_ptr :: proc(a: ^T, len, cap: int) -> []T
|
||||||
@@ -4405,6 +4551,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
|||||||
switch (bl->kind) {
|
switch (bl->kind) {
|
||||||
case Token_Integer: t = t_untyped_integer; break;
|
case Token_Integer: t = t_untyped_integer; break;
|
||||||
case Token_Float: t = t_untyped_float; break;
|
case Token_Float: t = t_untyped_float; break;
|
||||||
|
case Token_Imag: t = t_untyped_complex; break;
|
||||||
case Token_String: t = t_untyped_string; break;
|
case Token_String: t = t_untyped_string; break;
|
||||||
case Token_Rune: t = t_untyped_rune; break;
|
case Token_Rune: t = t_untyped_rune; break;
|
||||||
default: GB_PANIC("Unknown literal"); break;
|
default: GB_PANIC("Unknown literal"); break;
|
||||||
|
|||||||
+37
-18
@@ -52,6 +52,10 @@ typedef enum BuiltinProcId {
|
|||||||
|
|
||||||
BuiltinProc_swizzle,
|
BuiltinProc_swizzle,
|
||||||
|
|
||||||
|
BuiltinProc_complex,
|
||||||
|
BuiltinProc_real,
|
||||||
|
BuiltinProc_imag,
|
||||||
|
|
||||||
// BuiltinProc_ptr_offset,
|
// BuiltinProc_ptr_offset,
|
||||||
// BuiltinProc_ptr_sub,
|
// BuiltinProc_ptr_sub,
|
||||||
BuiltinProc_slice_ptr,
|
BuiltinProc_slice_ptr,
|
||||||
@@ -87,8 +91,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
|
|||||||
{STR_LIT("type_info"), 1, false, Expr_Expr},
|
{STR_LIT("type_info"), 1, false, Expr_Expr},
|
||||||
{STR_LIT("type_info_of_val"), 1, false, Expr_Expr},
|
{STR_LIT("type_info_of_val"), 1, false, Expr_Expr},
|
||||||
|
|
||||||
{STR_LIT("compile_assert"), 1, false, Expr_Stmt},
|
{STR_LIT("compile_assert"), 1, false, Expr_Expr},
|
||||||
{STR_LIT("assert"), 1, false, Expr_Stmt},
|
{STR_LIT("assert"), 1, false, Expr_Expr},
|
||||||
{STR_LIT("panic"), 1, false, Expr_Stmt},
|
{STR_LIT("panic"), 1, false, Expr_Stmt},
|
||||||
|
|
||||||
{STR_LIT("copy"), 2, false, Expr_Expr},
|
{STR_LIT("copy"), 2, false, Expr_Expr},
|
||||||
@@ -96,6 +100,10 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
|
|||||||
|
|
||||||
{STR_LIT("swizzle"), 1, true, Expr_Expr},
|
{STR_LIT("swizzle"), 1, true, Expr_Expr},
|
||||||
|
|
||||||
|
{STR_LIT("complex"), 2, false, Expr_Expr},
|
||||||
|
{STR_LIT("real"), 1, false, Expr_Expr},
|
||||||
|
{STR_LIT("imag"), 1, false, Expr_Expr},
|
||||||
|
|
||||||
// {STR_LIT("ptr_offset"), 2, false, Expr_Expr},
|
// {STR_LIT("ptr_offset"), 2, false, Expr_Expr},
|
||||||
// {STR_LIT("ptr_sub"), 2, false, Expr_Expr},
|
// {STR_LIT("ptr_sub"), 2, false, Expr_Expr},
|
||||||
{STR_LIT("slice_ptr"), 2, true, Expr_Expr},
|
{STR_LIT("slice_ptr"), 2, true, Expr_Expr},
|
||||||
@@ -940,6 +948,15 @@ void add_type_info_type(Checker *c, Type *t) {
|
|||||||
add_type_info_type(c, t_type_info_ptr);
|
add_type_info_type(c, t_type_info_ptr);
|
||||||
add_type_info_type(c, t_rawptr);
|
add_type_info_type(c, t_rawptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Basic_complex64:
|
||||||
|
add_type_info_type(c, t_type_info_float);
|
||||||
|
add_type_info_type(c, t_f32);
|
||||||
|
break;
|
||||||
|
case Basic_complex128:
|
||||||
|
add_type_info_type(c, t_type_info_float);
|
||||||
|
add_type_info_type(c, t_f64);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -1128,31 +1145,33 @@ void init_preload(Checker *c) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (record->variant_count != 19) {
|
if (record->variant_count != 20) {
|
||||||
compiler_error("Invalid `Type_Info` layout");
|
compiler_error("Invalid `Type_Info` layout");
|
||||||
}
|
}
|
||||||
t_type_info_named = record->variants[ 1]->type;
|
t_type_info_named = record->variants[ 1]->type;
|
||||||
t_type_info_integer = record->variants[ 2]->type;
|
t_type_info_integer = record->variants[ 2]->type;
|
||||||
t_type_info_float = record->variants[ 3]->type;
|
t_type_info_float = record->variants[ 3]->type;
|
||||||
t_type_info_string = record->variants[ 4]->type;
|
t_type_info_complex = record->variants[ 4]->type;
|
||||||
t_type_info_boolean = record->variants[ 5]->type;
|
t_type_info_string = record->variants[ 5]->type;
|
||||||
t_type_info_any = record->variants[ 6]->type;
|
t_type_info_boolean = record->variants[ 6]->type;
|
||||||
t_type_info_pointer = record->variants[ 7]->type;
|
t_type_info_any = record->variants[ 7]->type;
|
||||||
t_type_info_procedure = record->variants[ 8]->type;
|
t_type_info_pointer = record->variants[ 8]->type;
|
||||||
t_type_info_array = record->variants[ 9]->type;
|
t_type_info_procedure = record->variants[ 9]->type;
|
||||||
t_type_info_dynamic_array = record->variants[10]->type;
|
t_type_info_array = record->variants[10]->type;
|
||||||
t_type_info_slice = record->variants[11]->type;
|
t_type_info_dynamic_array = record->variants[11]->type;
|
||||||
t_type_info_vector = record->variants[12]->type;
|
t_type_info_slice = record->variants[12]->type;
|
||||||
t_type_info_tuple = record->variants[13]->type;
|
t_type_info_vector = record->variants[13]->type;
|
||||||
t_type_info_struct = record->variants[14]->type;
|
t_type_info_tuple = record->variants[14]->type;
|
||||||
t_type_info_raw_union = record->variants[15]->type;
|
t_type_info_struct = record->variants[15]->type;
|
||||||
t_type_info_union = record->variants[16]->type;
|
t_type_info_raw_union = record->variants[16]->type;
|
||||||
t_type_info_enum = record->variants[17]->type;
|
t_type_info_union = record->variants[17]->type;
|
||||||
t_type_info_map = record->variants[18]->type;
|
t_type_info_enum = record->variants[18]->type;
|
||||||
|
t_type_info_map = record->variants[19]->type;
|
||||||
|
|
||||||
t_type_info_named_ptr = make_type_pointer(c->allocator, t_type_info_named);
|
t_type_info_named_ptr = make_type_pointer(c->allocator, t_type_info_named);
|
||||||
t_type_info_integer_ptr = make_type_pointer(c->allocator, t_type_info_integer);
|
t_type_info_integer_ptr = make_type_pointer(c->allocator, t_type_info_integer);
|
||||||
t_type_info_float_ptr = make_type_pointer(c->allocator, t_type_info_float);
|
t_type_info_float_ptr = make_type_pointer(c->allocator, t_type_info_float);
|
||||||
|
t_type_info_complex_ptr = make_type_pointer(c->allocator, t_type_info_complex);
|
||||||
t_type_info_string_ptr = make_type_pointer(c->allocator, t_type_info_string);
|
t_type_info_string_ptr = make_type_pointer(c->allocator, t_type_info_string);
|
||||||
t_type_info_boolean_ptr = make_type_pointer(c->allocator, t_type_info_boolean);
|
t_type_info_boolean_ptr = make_type_pointer(c->allocator, t_type_info_boolean);
|
||||||
t_type_info_any_ptr = make_type_pointer(c->allocator, t_type_info_any);
|
t_type_info_any_ptr = make_type_pointer(c->allocator, t_type_info_any);
|
||||||
|
|||||||
+143
-14
@@ -12,21 +12,27 @@ typedef enum ExactValueKind {
|
|||||||
ExactValue_String,
|
ExactValue_String,
|
||||||
ExactValue_Integer,
|
ExactValue_Integer,
|
||||||
ExactValue_Float,
|
ExactValue_Float,
|
||||||
|
ExactValue_Complex,
|
||||||
ExactValue_Pointer,
|
ExactValue_Pointer,
|
||||||
ExactValue_Compound, // TODO(bill): Is this good enough?
|
ExactValue_Compound, // TODO(bill): Is this good enough?
|
||||||
|
|
||||||
ExactValue_Count,
|
ExactValue_Count,
|
||||||
} ExactValueKind;
|
} ExactValueKind;
|
||||||
|
|
||||||
|
typedef struct Complex128 {
|
||||||
|
f64 real, imag;
|
||||||
|
} Complex128;
|
||||||
|
|
||||||
typedef struct ExactValue {
|
typedef struct ExactValue {
|
||||||
ExactValueKind kind;
|
ExactValueKind kind;
|
||||||
union {
|
union {
|
||||||
bool value_bool;
|
bool value_bool;
|
||||||
String value_string;
|
String value_string;
|
||||||
i64 value_integer; // NOTE(bill): This must be an integer and not a pointer
|
i64 value_integer; // NOTE(bill): This must be an integer and not a pointer
|
||||||
f64 value_float;
|
f64 value_float;
|
||||||
i64 value_pointer;
|
i64 value_pointer;
|
||||||
AstNode *value_compound;
|
Complex128 value_complex;
|
||||||
|
AstNode * value_compound;
|
||||||
};
|
};
|
||||||
} ExactValue;
|
} ExactValue;
|
||||||
|
|
||||||
@@ -66,6 +72,13 @@ ExactValue exact_value_float(f64 f) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExactValue exact_value_complex(f64 real, f64 imag) {
|
||||||
|
ExactValue result = {ExactValue_Complex};
|
||||||
|
result.value_complex.real = real;
|
||||||
|
result.value_complex.imag = imag;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ExactValue exact_value_pointer(i64 ptr) {
|
ExactValue exact_value_pointer(i64 ptr) {
|
||||||
ExactValue result = {ExactValue_Pointer};
|
ExactValue result = {ExactValue_Pointer};
|
||||||
result.value_pointer = ptr;
|
result.value_pointer = ptr;
|
||||||
@@ -113,9 +126,7 @@ ExactValue exact_value_integer_from_string(String string) {
|
|||||||
return exact_value_integer(result);
|
return exact_value_integer(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f64 float_from_string(String string) {
|
||||||
|
|
||||||
ExactValue exact_value_float_from_string(String string) {
|
|
||||||
isize i = 0;
|
isize i = 0;
|
||||||
u8 *str = string.text;
|
u8 *str = string.text;
|
||||||
isize len = string.len;
|
isize len = string.len;
|
||||||
@@ -190,8 +201,11 @@ ExactValue exact_value_float_from_string(String string) {
|
|||||||
while (exp > 0) { scale *= 10.0; exp -= 1; }
|
while (exp > 0) { scale *= 10.0; exp -= 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
f64 result = sign * (frac ? (value / scale) : (value * scale));
|
return sign * (frac ? (value / scale) : (value * scale));
|
||||||
return exact_value_float(result);
|
}
|
||||||
|
|
||||||
|
ExactValue exact_value_float_from_string(String string) {
|
||||||
|
return exact_value_float(float_from_string(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -200,6 +214,12 @@ ExactValue exact_value_from_basic_literal(Token token) {
|
|||||||
case Token_String: return exact_value_string(token.string);
|
case Token_String: return exact_value_string(token.string);
|
||||||
case Token_Integer: return exact_value_integer_from_string(token.string);
|
case Token_Integer: return exact_value_integer_from_string(token.string);
|
||||||
case Token_Float: return exact_value_float_from_string(token.string);
|
case Token_Float: return exact_value_float_from_string(token.string);
|
||||||
|
case Token_Imag: {
|
||||||
|
String str = token.string;
|
||||||
|
str.len--; // Ignore the `i`
|
||||||
|
f64 imag = float_from_string(str);
|
||||||
|
return exact_value_complex(0, imag);
|
||||||
|
}
|
||||||
case Token_Rune: {
|
case Token_Rune: {
|
||||||
Rune r = GB_RUNE_INVALID;
|
Rune r = GB_RUNE_INVALID;
|
||||||
gb_utf8_decode(token.string.text, token.string.len, &r);
|
gb_utf8_decode(token.string.text, token.string.len, &r);
|
||||||
@@ -245,6 +265,57 @@ ExactValue exact_value_to_float(ExactValue v) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExactValue exact_value_to_complex(ExactValue v) {
|
||||||
|
switch (v.kind) {
|
||||||
|
case ExactValue_Integer:
|
||||||
|
return exact_value_complex(cast(i64)v.value_integer, 0);
|
||||||
|
case ExactValue_Float:
|
||||||
|
return exact_value_complex(v.value_float, 0);
|
||||||
|
case ExactValue_Complex:
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
ExactValue r = {ExactValue_Invalid};
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExactValue exact_value_real(ExactValue v) {
|
||||||
|
switch (v.kind) {
|
||||||
|
case ExactValue_Integer:
|
||||||
|
case ExactValue_Float:
|
||||||
|
return v;
|
||||||
|
case ExactValue_Complex:
|
||||||
|
return exact_value_float(v.value_complex.real);
|
||||||
|
}
|
||||||
|
ExactValue r = {ExactValue_Invalid};
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExactValue exact_value_imag(ExactValue v) {
|
||||||
|
switch (v.kind) {
|
||||||
|
case ExactValue_Integer:
|
||||||
|
case ExactValue_Float:
|
||||||
|
return exact_value_integer(0);
|
||||||
|
case ExactValue_Complex:
|
||||||
|
return exact_value_float(v.value_complex.imag);
|
||||||
|
}
|
||||||
|
ExactValue r = {ExactValue_Invalid};
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExactValue exact_value_make_imag(ExactValue v) {
|
||||||
|
switch (v.kind) {
|
||||||
|
case ExactValue_Integer:
|
||||||
|
return exact_value_complex(0, exact_value_to_float(v).value_float);
|
||||||
|
case ExactValue_Float:
|
||||||
|
return exact_value_complex(0, v.value_float);
|
||||||
|
default:
|
||||||
|
GB_PANIC("Expected an integer or float type for `exact_value_make_imag`");
|
||||||
|
}
|
||||||
|
ExactValue r = {ExactValue_Invalid};
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision) {
|
ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision) {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@@ -253,6 +324,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
|
|||||||
case ExactValue_Invalid:
|
case ExactValue_Invalid:
|
||||||
case ExactValue_Integer:
|
case ExactValue_Integer:
|
||||||
case ExactValue_Float:
|
case ExactValue_Float:
|
||||||
|
case ExactValue_Complex:
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -271,6 +343,11 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
|
|||||||
i.value_float = -i.value_float;
|
i.value_float = -i.value_float;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
case ExactValue_Complex: {
|
||||||
|
f64 real = v.value_complex.real;
|
||||||
|
f64 imag = v.value_complex.imag;
|
||||||
|
return exact_value_complex(-real, -imag);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -324,8 +401,10 @@ i32 exact_value_order(ExactValue v) {
|
|||||||
return 2;
|
return 2;
|
||||||
case ExactValue_Float:
|
case ExactValue_Float:
|
||||||
return 3;
|
return 3;
|
||||||
case ExactValue_Pointer:
|
case ExactValue_Complex:
|
||||||
return 4;
|
return 4;
|
||||||
|
case ExactValue_Pointer:
|
||||||
|
return 5;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
GB_PANIC("How'd you get here? Invalid Value.kind");
|
GB_PANIC("How'd you get here? Invalid Value.kind");
|
||||||
@@ -346,6 +425,7 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
|
|||||||
|
|
||||||
case ExactValue_Bool:
|
case ExactValue_Bool:
|
||||||
case ExactValue_String:
|
case ExactValue_String:
|
||||||
|
case ExactValue_Complex:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case ExactValue_Integer:
|
case ExactValue_Integer:
|
||||||
@@ -356,16 +436,23 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
|
|||||||
// TODO(bill): Is this good enough?
|
// TODO(bill): Is this good enough?
|
||||||
*x = exact_value_float(cast(f64)x->value_integer);
|
*x = exact_value_float(cast(f64)x->value_integer);
|
||||||
return;
|
return;
|
||||||
|
case ExactValue_Complex:
|
||||||
|
*x = exact_value_complex(cast(f64)x->value_integer, 0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ExactValue_Float:
|
case ExactValue_Float:
|
||||||
if (y->kind == ExactValue_Float)
|
if (y->kind == ExactValue_Float) {
|
||||||
return;
|
return;
|
||||||
|
} else if (y->kind == ExactValue_Complex) {
|
||||||
|
*x = exact_value_to_complex(*x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
compiler_error("How'd you get here? Invalid ExactValueKind");
|
compiler_error("match_exact_values: How'd you get here? Invalid ExactValueKind %d", x->kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bill): Allow for pointer arithmetic? Or are pointer slices good enough?
|
// TODO(bill): Allow for pointer arithmetic? Or are pointer slices good enough?
|
||||||
@@ -420,6 +507,37 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
|
|||||||
default: goto error;
|
default: goto error;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case ExactValue_Complex: {
|
||||||
|
y = exact_value_to_complex(y);
|
||||||
|
f64 a = x.value_complex.real;
|
||||||
|
f64 b = x.value_complex.imag;
|
||||||
|
f64 c = y.value_complex.real;
|
||||||
|
f64 d = y.value_complex.imag;
|
||||||
|
f64 real = 0;
|
||||||
|
f64 imag = 0;
|
||||||
|
switch (op) {
|
||||||
|
case Token_Add:
|
||||||
|
real = a + c;
|
||||||
|
imag = b + d;
|
||||||
|
break;
|
||||||
|
case Token_Sub:
|
||||||
|
real = a - c;
|
||||||
|
imag = b - d;
|
||||||
|
break;
|
||||||
|
case Token_Mul:
|
||||||
|
real = (a*c - b*d);
|
||||||
|
imag = (b*c + a*d);
|
||||||
|
break;
|
||||||
|
case Token_Quo: {
|
||||||
|
f64 s = c*c + d*d;
|
||||||
|
real = (a*c + b*d)/s;
|
||||||
|
imag = (b*c - a*d)/s;
|
||||||
|
} break;
|
||||||
|
default: goto error;
|
||||||
|
}
|
||||||
|
return exact_value_complex(real, imag);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@@ -480,6 +598,17 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case ExactValue_Complex: {
|
||||||
|
f64 a = x.value_complex.real;
|
||||||
|
f64 b = x.value_complex.imag;
|
||||||
|
f64 c = y.value_complex.real;
|
||||||
|
f64 d = y.value_complex.imag;
|
||||||
|
switch (op) {
|
||||||
|
case Token_CmpEq: return cmp_f64(a, c) == 0 && cmp_f64(b, d) == 0;
|
||||||
|
case Token_NotEq: return cmp_f64(a, c) != 0 || cmp_f64(b, d) != 0;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
case ExactValue_String: {
|
case ExactValue_String: {
|
||||||
String a = x.value_string;
|
String a = x.value_string;
|
||||||
String b = y.value_string;
|
String b = y.value_string;
|
||||||
|
|||||||
@@ -1653,6 +1653,7 @@ irValue *ir_addr_load(irProcedure *proc, irAddr addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_emit_array_epi(irProcedure *proc, irValue *s, i32 index);
|
irValue *ir_emit_array_epi(irProcedure *proc, irValue *s, i32 index);
|
||||||
|
irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index);
|
||||||
|
|
||||||
irValue *ir_emit_ptr_offset(irProcedure *proc, irValue *ptr, irValue *offset) {
|
irValue *ir_emit_ptr_offset(irProcedure *proc, irValue *ptr, irValue *offset) {
|
||||||
offset = ir_emit_conv(proc, offset, t_int);
|
offset = ir_emit_conv(proc, offset, t_int);
|
||||||
@@ -1716,6 +1717,64 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
|
|||||||
return ir_emit_load(proc, res);
|
return ir_emit_load(proc, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_type_complex(t_left)) {
|
||||||
|
ir_emit_comment(proc, str_lit("complex.arith.begin"));
|
||||||
|
Type *tl = core_type(t_left);
|
||||||
|
Type *ft = t_f32;
|
||||||
|
if (tl->Basic.kind == Basic_complex128) {
|
||||||
|
ft = t_f64;
|
||||||
|
}
|
||||||
|
|
||||||
|
irValue *res = ir_add_local_generated(proc, type);
|
||||||
|
irValue *a = ir_emit_struct_ev(proc, left, 0);
|
||||||
|
irValue *b = ir_emit_struct_ev(proc, left, 1);
|
||||||
|
irValue *c = ir_emit_struct_ev(proc, right, 0);
|
||||||
|
irValue *d = ir_emit_struct_ev(proc, right, 1);
|
||||||
|
|
||||||
|
irValue *real = NULL;
|
||||||
|
irValue *imag = NULL;
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case Token_Add:
|
||||||
|
real = ir_emit_arith(proc, Token_Add, a, c, ft);
|
||||||
|
imag = ir_emit_arith(proc, Token_Add, b, d, ft);
|
||||||
|
break;
|
||||||
|
case Token_Sub:
|
||||||
|
real = ir_emit_arith(proc, Token_Sub, a, c, ft);
|
||||||
|
imag = ir_emit_arith(proc, Token_Sub, b, d, ft);
|
||||||
|
break;
|
||||||
|
case Token_Mul: {
|
||||||
|
irValue *x = ir_emit_arith(proc, Token_Mul, a, c, ft);
|
||||||
|
irValue *y = ir_emit_arith(proc, Token_Mul, b, d, ft);
|
||||||
|
real = ir_emit_arith(proc, Token_Sub, x, y, ft);
|
||||||
|
irValue *z = ir_emit_arith(proc, Token_Mul, b, c, ft);
|
||||||
|
irValue *w = ir_emit_arith(proc, Token_Mul, a, d, ft);
|
||||||
|
imag = ir_emit_arith(proc, Token_Add, z, w, ft);
|
||||||
|
} break;
|
||||||
|
case Token_Quo: {
|
||||||
|
irValue *s1 = ir_emit_arith(proc, Token_Mul, c, c, ft);
|
||||||
|
irValue *s2 = ir_emit_arith(proc, Token_Mul, d, d, ft);
|
||||||
|
irValue *s = ir_emit_arith(proc, Token_Add, s1, s2, ft);
|
||||||
|
|
||||||
|
irValue *x = ir_emit_arith(proc, Token_Mul, a, c, ft);
|
||||||
|
irValue *y = ir_emit_arith(proc, Token_Mul, b, d, ft);
|
||||||
|
real = ir_emit_arith(proc, Token_Add, x, y, ft);
|
||||||
|
real = ir_emit_arith(proc, Token_Quo, real, s, ft);
|
||||||
|
|
||||||
|
irValue *z = ir_emit_arith(proc, Token_Mul, b, c, ft);
|
||||||
|
irValue *w = ir_emit_arith(proc, Token_Mul, a, d, ft);
|
||||||
|
imag = ir_emit_arith(proc, Token_Sub, z, w, ft);
|
||||||
|
imag = ir_emit_arith(proc, Token_Quo, imag, s, ft);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 0), real);
|
||||||
|
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 1), imag);
|
||||||
|
|
||||||
|
ir_emit_comment(proc, str_lit("complex.end.begin"));
|
||||||
|
return ir_emit_load(proc, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (op == Token_Add) {
|
if (op == Token_Add) {
|
||||||
if (is_type_pointer(t_left)) {
|
if (is_type_pointer(t_left)) {
|
||||||
@@ -1890,6 +1949,15 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
|
|||||||
GB_ASSERT(t->Tuple.variable_count > 0);
|
GB_ASSERT(t->Tuple.variable_count > 0);
|
||||||
GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1));
|
GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1));
|
||||||
result_type = make_type_pointer(a, t->Tuple.variables[index]->type);
|
result_type = make_type_pointer(a, t->Tuple.variables[index]->type);
|
||||||
|
} else if (is_type_complex(t)) {
|
||||||
|
Type *ft = t_f32;
|
||||||
|
if (core_type(t)->Basic.kind == Basic_complex128) {
|
||||||
|
ft = t_f64;
|
||||||
|
}
|
||||||
|
switch (index) {
|
||||||
|
case 0: result_type = make_type_pointer(a, ft); break;
|
||||||
|
case 1: result_type = make_type_pointer(a, ft); break;
|
||||||
|
}
|
||||||
} else if (is_type_slice(t)) {
|
} else if (is_type_slice(t)) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0: result_type = make_type_pointer(a, make_type_pointer(a, t->Slice.elem)); break;
|
case 0: result_type = make_type_pointer(a, make_type_pointer(a, t->Slice.elem)); break;
|
||||||
@@ -1956,6 +2024,15 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
|
|||||||
GB_ASSERT(t->Tuple.variable_count > 0);
|
GB_ASSERT(t->Tuple.variable_count > 0);
|
||||||
GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1));
|
GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1));
|
||||||
result_type = t->Tuple.variables[index]->type;
|
result_type = t->Tuple.variables[index]->type;
|
||||||
|
} else if (is_type_complex(t)) {
|
||||||
|
Type *ft = t_f32;
|
||||||
|
if (core_type(t)->Basic.kind == Basic_complex128) {
|
||||||
|
ft = t_f64;
|
||||||
|
}
|
||||||
|
switch (index) {
|
||||||
|
case 0: result_type = ft; break;
|
||||||
|
case 1: result_type = ft; break;
|
||||||
|
}
|
||||||
} else if (is_type_slice(t)) {
|
} else if (is_type_slice(t)) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0: result_type = make_type_pointer(a, t->Slice.elem); break;
|
case 0: result_type = make_type_pointer(a, t->Slice.elem); break;
|
||||||
@@ -2285,6 +2362,8 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
|||||||
ExactValue ev = value->Constant.value;
|
ExactValue ev = value->Constant.value;
|
||||||
if (is_type_float(dst)) {
|
if (is_type_float(dst)) {
|
||||||
ev = exact_value_to_float(ev);
|
ev = exact_value_to_float(ev);
|
||||||
|
} else if (is_type_complex(dst)) {
|
||||||
|
ev = exact_value_to_complex(ev);
|
||||||
} else if (is_type_string(dst)) {
|
} else if (is_type_string(dst)) {
|
||||||
// Handled elsewhere
|
// Handled elsewhere
|
||||||
GB_ASSERT(ev.kind == ExactValue_String);
|
GB_ASSERT(ev.kind == ExactValue_String);
|
||||||
@@ -2350,6 +2429,16 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
|||||||
return ir_emit(proc, ir_instr_conv(proc, kind, value, src, dst));
|
return ir_emit(proc, ir_instr_conv(proc, kind, value, src, dst));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_type_complex(src) && is_type_complex(dst)) {
|
||||||
|
Type *ft = base_complex_elem_type(dst);
|
||||||
|
irValue *gen = ir_add_local_generated(proc, dst);
|
||||||
|
irValue *real = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 0), ft);
|
||||||
|
irValue *imag = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 1), ft);
|
||||||
|
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 0), real);
|
||||||
|
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 1), imag);
|
||||||
|
return ir_emit_load(proc, gen);
|
||||||
|
}
|
||||||
|
|
||||||
// float <-> integer
|
// float <-> integer
|
||||||
if (is_type_float(src) && is_type_integer(dst)) {
|
if (is_type_float(src) && is_type_integer(dst)) {
|
||||||
irConvKind kind = irConv_fptosi;
|
irConvKind kind = irConv_fptosi;
|
||||||
@@ -3704,6 +3793,37 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
|||||||
// return ir_emit(proc, ir_instr_vector_shuffle(proc, vector, indices, index_count));
|
// return ir_emit(proc, ir_instr_vector_shuffle(proc, vector, indices, index_count));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case BuiltinProc_complex: {
|
||||||
|
ir_emit_comment(proc, str_lit("complex"));
|
||||||
|
irValue *real = ir_build_expr(proc, ce->args.e[0]);
|
||||||
|
irValue *imag = ir_build_expr(proc, ce->args.e[1]);
|
||||||
|
irValue *dst = ir_add_local_generated(proc, tv->type);
|
||||||
|
|
||||||
|
Type *ft = base_complex_elem_type(tv->type);
|
||||||
|
irValue *rp = ir_emit_struct_ep(proc, dst, 0);
|
||||||
|
irValue *ip = ir_emit_struct_ep(proc, dst, 1);
|
||||||
|
|
||||||
|
real = ir_emit_conv(proc, real, ft);
|
||||||
|
imag = ir_emit_conv(proc, imag, ft);
|
||||||
|
ir_emit_store(proc, rp, real);
|
||||||
|
ir_emit_store(proc, ip, imag);
|
||||||
|
|
||||||
|
return ir_emit_load(proc, dst);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case BuiltinProc_real: {
|
||||||
|
ir_emit_comment(proc, str_lit("real"));
|
||||||
|
irValue *complex = ir_build_expr(proc, ce->args.e[0]);
|
||||||
|
irValue *real = ir_emit_struct_ev(proc, complex, 0);
|
||||||
|
return ir_emit_conv(proc, real, tv->type);
|
||||||
|
} break;
|
||||||
|
case BuiltinProc_imag: {
|
||||||
|
ir_emit_comment(proc, str_lit("imag"));
|
||||||
|
irValue *complex = ir_build_expr(proc, ce->args.e[0]);
|
||||||
|
irValue *imag = ir_emit_struct_ev(proc, complex, 1);
|
||||||
|
return ir_emit_conv(proc, imag, tv->type);
|
||||||
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_slice_ptr: {
|
case BuiltinProc_slice_ptr: {
|
||||||
ir_emit_comment(proc, str_lit("slice_ptr"));
|
ir_emit_comment(proc, str_lit("slice_ptr"));
|
||||||
irValue *ptr = ir_build_expr(proc, ce->args.e[0]);
|
irValue *ptr = ir_build_expr(proc, ce->args.e[0]);
|
||||||
@@ -6528,8 +6648,6 @@ void ir_gen_tree(irGen *s) {
|
|||||||
case Basic_u32:
|
case Basic_u32:
|
||||||
case Basic_i64:
|
case Basic_i64:
|
||||||
case Basic_u64:
|
case Basic_u64:
|
||||||
// case Basic_i128:
|
|
||||||
// case Basic_u128:
|
|
||||||
case Basic_int:
|
case Basic_int:
|
||||||
case Basic_uint: {
|
case Basic_uint: {
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_integer_ptr);
|
tag = ir_emit_conv(proc, ti_ptr, t_type_info_integer_ptr);
|
||||||
@@ -6540,16 +6658,23 @@ void ir_gen_tree(irGen *s) {
|
|||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 1), is_signed);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 1), is_signed);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
// case Basic_f16:
|
|
||||||
case Basic_f32:
|
case Basic_f32:
|
||||||
case Basic_f64:
|
case Basic_f64:
|
||||||
// case Basic_f128:
|
|
||||||
{
|
{
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_float_ptr);
|
tag = ir_emit_conv(proc, ti_ptr, t_type_info_float_ptr);
|
||||||
irValue *bits = ir_const_int(a, type_size_of(a, t));
|
irValue *bits = ir_const_int(a, type_size_of(a, t));
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), bits);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), bits);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case Basic_complex64:
|
||||||
|
case Basic_complex128:
|
||||||
|
{
|
||||||
|
tag = ir_emit_conv(proc, ti_ptr, t_type_info_complex_ptr);
|
||||||
|
irValue *bits = ir_const_int(a, type_size_of(a, t));
|
||||||
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), bits);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
|
||||||
case Basic_rawptr:
|
case Basic_rawptr:
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_pointer_ptr);
|
tag = ir_emit_conv(proc, ti_ptr, t_type_info_pointer_ptr);
|
||||||
break;
|
break;
|
||||||
|
|||||||
+29
-22
@@ -154,12 +154,14 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
|||||||
case Basic_u32: ir_fprintf(f, "i32"); return;
|
case Basic_u32: ir_fprintf(f, "i32"); return;
|
||||||
case Basic_i64: ir_fprintf(f, "i64"); return;
|
case Basic_i64: ir_fprintf(f, "i64"); return;
|
||||||
case Basic_u64: ir_fprintf(f, "i64"); return;
|
case Basic_u64: ir_fprintf(f, "i64"); return;
|
||||||
// case Basic_i128: ir_fprintf(f, "i128"); return;
|
|
||||||
// case Basic_u128: ir_fprintf(f, "i128"); return;
|
|
||||||
// case Basic_f16: ir_fprintf(f, "half"); return;
|
|
||||||
case Basic_f32: ir_fprintf(f, "float"); return;
|
case Basic_f32: ir_fprintf(f, "float"); return;
|
||||||
case Basic_f64: ir_fprintf(f, "double"); return;
|
case Basic_f64: ir_fprintf(f, "double"); return;
|
||||||
// case Basic_f128: ir_fprintf(f, "fp128"); return;
|
|
||||||
|
case Basic_complex64: ir_fprintf(f, "%%..complex64"); return;
|
||||||
|
case Basic_complex128: ir_fprintf(f, "%%..complex128"); return;
|
||||||
|
|
||||||
|
|
||||||
case Basic_rawptr: ir_fprintf(f, "%%..rawptr"); return;
|
case Basic_rawptr: ir_fprintf(f, "%%..rawptr"); return;
|
||||||
case Basic_string: ir_fprintf(f, "%%..string"); return;
|
case Basic_string: ir_fprintf(f, "%%..string"); return;
|
||||||
case Basic_uint: ir_fprintf(f, "i%lld", word_bits); return;
|
case Basic_uint: ir_fprintf(f, "i%lld", word_bits); return;
|
||||||
@@ -365,7 +367,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
|
|||||||
} break;
|
} break;
|
||||||
case ExactValue_Float: {
|
case ExactValue_Float: {
|
||||||
GB_ASSERT_MSG(is_type_float(type), "%s", type_to_string(type));
|
GB_ASSERT_MSG(is_type_float(type), "%s", type_to_string(type));
|
||||||
type = base_type(type);
|
type = core_type(type);
|
||||||
u64 u = *cast(u64*)&value.value_float;
|
u64 u = *cast(u64*)&value.value_float;
|
||||||
switch (type->Basic.kind) {
|
switch (type->Basic.kind) {
|
||||||
case Basic_f32:
|
case Basic_f32:
|
||||||
@@ -382,28 +384,27 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
|
|||||||
|
|
||||||
switch (type->Basic.kind) {
|
switch (type->Basic.kind) {
|
||||||
case 0: break;
|
case 0: break;
|
||||||
#if 0
|
|
||||||
case Basic_f16:
|
|
||||||
ir_fprintf(f, "bitcast (");
|
|
||||||
ir_print_type(f, m, t_u16);
|
|
||||||
ir_fprintf(f, " %u to ", cast(u16)f32_to_f16(cast(f32)value.value_float));
|
|
||||||
ir_print_type(f, m, t_f16);
|
|
||||||
ir_fprintf(f, ")");
|
|
||||||
break;
|
|
||||||
case Basic_f128:
|
|
||||||
ir_fprintf(f, "bitcast (");
|
|
||||||
ir_fprintf(f, "i128");
|
|
||||||
// TODO(bill): Actually support f128
|
|
||||||
ir_fprintf(f, " %llu to ", u);
|
|
||||||
ir_print_type(f, m, t_f128);
|
|
||||||
ir_fprintf(f, ")");
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
ir_fprintf(f, "0x%016llx", u);
|
ir_fprintf(f, "0x%016llx", u);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case ExactValue_Complex: {
|
||||||
|
GB_ASSERT_MSG(is_type_complex(type), "%s", type_to_string(type));
|
||||||
|
type = core_type(type);
|
||||||
|
Type *ft = base_complex_elem_type(type);
|
||||||
|
ir_fprintf(f, " {");
|
||||||
|
ir_print_type(f, m, ft);
|
||||||
|
ir_fprintf(f, " ");
|
||||||
|
ir_print_exact_value(f, m, exact_value_float(value.value_complex.real), ft);
|
||||||
|
ir_fprintf(f, ", ");
|
||||||
|
ir_print_type(f, m, ft);
|
||||||
|
ir_fprintf(f, " ");
|
||||||
|
ir_print_exact_value(f, m, exact_value_float(value.value_complex.imag), ft);
|
||||||
|
ir_fprintf(f, "}");
|
||||||
|
} break;
|
||||||
|
|
||||||
case ExactValue_Pointer:
|
case ExactValue_Pointer:
|
||||||
if (value.value_pointer == 0) {
|
if (value.value_pointer == 0) {
|
||||||
ir_fprintf(f, "null");
|
ir_fprintf(f, "null");
|
||||||
@@ -1415,6 +1416,12 @@ void print_llvm_ir(irGen *ir) {
|
|||||||
ir_print_encoded_local(f, str_lit("..rawptr"));
|
ir_print_encoded_local(f, str_lit("..rawptr"));
|
||||||
ir_fprintf(f, " = type i8* ; Basic_rawptr\n");
|
ir_fprintf(f, " = type i8* ; Basic_rawptr\n");
|
||||||
|
|
||||||
|
ir_print_encoded_local(f, str_lit("..complex64"));
|
||||||
|
ir_fprintf(f, " = type {float, float} ; Basic_complex64\n");
|
||||||
|
ir_print_encoded_local(f, str_lit("..complex128"));
|
||||||
|
ir_fprintf(f, " = type {double, double} ; Basic_complex128\n");
|
||||||
|
|
||||||
|
|
||||||
ir_print_encoded_local(f, str_lit("..any"));
|
ir_print_encoded_local(f, str_lit("..any"));
|
||||||
ir_fprintf(f, " = type {");
|
ir_fprintf(f, " = type {");
|
||||||
ir_print_type(f, m, t_type_info_ptr);
|
ir_print_type(f, m, t_type_info_ptr);
|
||||||
|
|||||||
+1
-1
@@ -252,7 +252,7 @@ int main(int argc, char **argv) {
|
|||||||
i32 exit_code = 0;
|
i32 exit_code = 0;
|
||||||
// For more passes arguments: http://llvm.org/docs/Passes.html
|
// For more passes arguments: http://llvm.org/docs/Passes.html
|
||||||
exit_code = system_exec_command_line_app("llvm-opt", false,
|
exit_code = system_exec_command_line_app("llvm-opt", false,
|
||||||
"\"%.*sbin/opt\" \"%s\" -o \"%.*s\".bc "
|
"\"%.*sbin/opt\" \"%s\" -o \"%.*s.bc\" "
|
||||||
"-mem2reg "
|
"-mem2reg "
|
||||||
"-memcpyopt "
|
"-memcpyopt "
|
||||||
"-die "
|
"-die "
|
||||||
|
|||||||
@@ -1735,6 +1735,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|||||||
|
|
||||||
case Token_Integer:
|
case Token_Integer:
|
||||||
case Token_Float:
|
case Token_Float:
|
||||||
|
case Token_Imag:
|
||||||
case Token_Rune:
|
case Token_Rune:
|
||||||
operand = ast_basic_lit(f, f->curr_token);
|
operand = ast_basic_lit(f, f->curr_token);
|
||||||
next_token(f);
|
next_token(f);
|
||||||
@@ -3238,6 +3239,7 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
case Token_Ident:
|
case Token_Ident:
|
||||||
case Token_Integer:
|
case Token_Integer:
|
||||||
case Token_Float:
|
case Token_Float:
|
||||||
|
case Token_Imag:
|
||||||
case Token_Rune:
|
case Token_Rune:
|
||||||
case Token_String:
|
case Token_String:
|
||||||
case Token_OpenParen:
|
case Token_OpenParen:
|
||||||
|
|||||||
+9
-3
@@ -7,6 +7,7 @@ TOKEN_KIND(Token__LiteralBegin, "_LiteralBegin"), \
|
|||||||
TOKEN_KIND(Token_Ident, "identifier"), \
|
TOKEN_KIND(Token_Ident, "identifier"), \
|
||||||
TOKEN_KIND(Token_Integer, "integer"), \
|
TOKEN_KIND(Token_Integer, "integer"), \
|
||||||
TOKEN_KIND(Token_Float, "float"), \
|
TOKEN_KIND(Token_Float, "float"), \
|
||||||
|
TOKEN_KIND(Token_Imag, "imaginary"), \
|
||||||
TOKEN_KIND(Token_Rune, "rune"), \
|
TOKEN_KIND(Token_Rune, "rune"), \
|
||||||
TOKEN_KIND(Token_String, "string"), \
|
TOKEN_KIND(Token_String, "string"), \
|
||||||
TOKEN_KIND(Token__LiteralEnd, "_LiteralEnd"), \
|
TOKEN_KIND(Token__LiteralEnd, "_LiteralEnd"), \
|
||||||
@@ -547,18 +548,18 @@ Token scan_number_to_token(Tokenizer *t, bool seen_decimal_point) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
token.string.len = t->curr - token.string.text;
|
goto end;
|
||||||
return token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scan_mantissa(t, 10);
|
scan_mantissa(t, 10);
|
||||||
|
|
||||||
|
|
||||||
fraction:
|
fraction:
|
||||||
if (t->curr_rune == '.') {
|
if (t->curr_rune == '.') {
|
||||||
// HACK(bill): This may be inefficient
|
// HACK(bill): This may be inefficient
|
||||||
TokenizerState state = save_tokenizer_state(t);
|
TokenizerState state = save_tokenizer_state(t);
|
||||||
advance_to_next_rune(t);
|
advance_to_next_rune(t);
|
||||||
if (digit_value(t->curr_rune) >= 10) {
|
if (t->curr_rune == '.') {
|
||||||
// TODO(bill): Clean up this shit
|
// TODO(bill): Clean up this shit
|
||||||
restore_tokenizer_state(t, &state);
|
restore_tokenizer_state(t, &state);
|
||||||
goto end;
|
goto end;
|
||||||
@@ -577,6 +578,11 @@ exponent:
|
|||||||
scan_mantissa(t, 10);
|
scan_mantissa(t, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (t->curr_rune == 'i') {
|
||||||
|
token.kind = Token_Imag;
|
||||||
|
advance_to_next_rune(t);
|
||||||
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
token.string.len = t->curr - token.string.text;
|
token.string.len = t->curr - token.string.text;
|
||||||
return token;
|
return token;
|
||||||
|
|||||||
+56
-30
@@ -12,25 +12,12 @@ typedef enum BasicKind {
|
|||||||
Basic_i64,
|
Basic_i64,
|
||||||
Basic_u64,
|
Basic_u64,
|
||||||
|
|
||||||
/* Basic_i16le,
|
|
||||||
Basic_i16be,
|
|
||||||
Basic_u16le,
|
|
||||||
Basic_u16be,
|
|
||||||
Basic_i32le,
|
|
||||||
Basic_i32be,
|
|
||||||
Basic_u32le,
|
|
||||||
Basic_u32be,
|
|
||||||
Basic_i64le,
|
|
||||||
Basic_i64be,
|
|
||||||
Basic_u64le,
|
|
||||||
Basic_u64be, */
|
|
||||||
|
|
||||||
// Basic_i128,
|
|
||||||
// Basic_u128,
|
|
||||||
// Basic_f16,
|
|
||||||
Basic_f32,
|
Basic_f32,
|
||||||
Basic_f64,
|
Basic_f64,
|
||||||
// Basic_f128,
|
|
||||||
|
Basic_complex64,
|
||||||
|
Basic_complex128,
|
||||||
|
|
||||||
Basic_int,
|
Basic_int,
|
||||||
Basic_uint,
|
Basic_uint,
|
||||||
Basic_rawptr,
|
Basic_rawptr,
|
||||||
@@ -40,6 +27,7 @@ typedef enum BasicKind {
|
|||||||
Basic_UntypedBool,
|
Basic_UntypedBool,
|
||||||
Basic_UntypedInteger,
|
Basic_UntypedInteger,
|
||||||
Basic_UntypedFloat,
|
Basic_UntypedFloat,
|
||||||
|
Basic_UntypedComplex,
|
||||||
Basic_UntypedString,
|
Basic_UntypedString,
|
||||||
Basic_UntypedRune,
|
Basic_UntypedRune,
|
||||||
Basic_UntypedNil,
|
Basic_UntypedNil,
|
||||||
@@ -55,12 +43,13 @@ typedef enum BasicFlag {
|
|||||||
BasicFlag_Integer = GB_BIT(1),
|
BasicFlag_Integer = GB_BIT(1),
|
||||||
BasicFlag_Unsigned = GB_BIT(2),
|
BasicFlag_Unsigned = GB_BIT(2),
|
||||||
BasicFlag_Float = GB_BIT(3),
|
BasicFlag_Float = GB_BIT(3),
|
||||||
BasicFlag_Pointer = GB_BIT(4),
|
BasicFlag_Complex = GB_BIT(4),
|
||||||
BasicFlag_String = GB_BIT(5),
|
BasicFlag_Pointer = GB_BIT(5),
|
||||||
BasicFlag_Rune = GB_BIT(6),
|
BasicFlag_String = GB_BIT(6),
|
||||||
BasicFlag_Untyped = GB_BIT(7),
|
BasicFlag_Rune = GB_BIT(7),
|
||||||
|
BasicFlag_Untyped = GB_BIT(8),
|
||||||
|
|
||||||
BasicFlag_Numeric = BasicFlag_Integer | BasicFlag_Float,
|
BasicFlag_Numeric = BasicFlag_Integer | BasicFlag_Float | BasicFlag_Complex,
|
||||||
BasicFlag_Ordered = BasicFlag_Numeric | BasicFlag_String | BasicFlag_Pointer,
|
BasicFlag_Ordered = BasicFlag_Numeric | BasicFlag_String | BasicFlag_Pointer,
|
||||||
BasicFlag_ConstantType = BasicFlag_Boolean | BasicFlag_Numeric | BasicFlag_Pointer | BasicFlag_String | BasicFlag_Rune,
|
BasicFlag_ConstantType = BasicFlag_Boolean | BasicFlag_Numeric | BasicFlag_Pointer | BasicFlag_String | BasicFlag_Rune,
|
||||||
} BasicFlag;
|
} BasicFlag;
|
||||||
@@ -210,7 +199,9 @@ void selection_add_index(Selection *s, isize index) {
|
|||||||
|
|
||||||
gb_global Type basic_types[] = {
|
gb_global Type basic_types[] = {
|
||||||
{Type_Basic, {Basic_Invalid, 0, 0, STR_LIT("invalid type")}},
|
{Type_Basic, {Basic_Invalid, 0, 0, STR_LIT("invalid type")}},
|
||||||
|
|
||||||
{Type_Basic, {Basic_bool, BasicFlag_Boolean, 1, STR_LIT("bool")}},
|
{Type_Basic, {Basic_bool, BasicFlag_Boolean, 1, STR_LIT("bool")}},
|
||||||
|
|
||||||
{Type_Basic, {Basic_i8, BasicFlag_Integer, 1, STR_LIT("i8")}},
|
{Type_Basic, {Basic_i8, BasicFlag_Integer, 1, STR_LIT("i8")}},
|
||||||
{Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, 1, STR_LIT("u8")}},
|
{Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, 1, STR_LIT("u8")}},
|
||||||
{Type_Basic, {Basic_i16, BasicFlag_Integer, 2, STR_LIT("i16")}},
|
{Type_Basic, {Basic_i16, BasicFlag_Integer, 2, STR_LIT("i16")}},
|
||||||
@@ -219,20 +210,24 @@ gb_global Type basic_types[] = {
|
|||||||
{Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, 4, STR_LIT("u32")}},
|
{Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, 4, STR_LIT("u32")}},
|
||||||
{Type_Basic, {Basic_i64, BasicFlag_Integer, 8, STR_LIT("i64")}},
|
{Type_Basic, {Basic_i64, BasicFlag_Integer, 8, STR_LIT("i64")}},
|
||||||
{Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, 8, STR_LIT("u64")}},
|
{Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, 8, STR_LIT("u64")}},
|
||||||
// {Type_Basic, {Basic_i128, BasicFlag_Integer, 16, STR_LIT("i128")}},
|
|
||||||
// {Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, 16, STR_LIT("u128")}},
|
|
||||||
// {Type_Basic, {Basic_f16, BasicFlag_Float, 2, STR_LIT("f16")}},
|
|
||||||
{Type_Basic, {Basic_f32, BasicFlag_Float, 4, STR_LIT("f32")}},
|
{Type_Basic, {Basic_f32, BasicFlag_Float, 4, STR_LIT("f32")}},
|
||||||
{Type_Basic, {Basic_f64, BasicFlag_Float, 8, STR_LIT("f64")}},
|
{Type_Basic, {Basic_f64, BasicFlag_Float, 8, STR_LIT("f64")}},
|
||||||
// {Type_Basic, {Basic_f128, BasicFlag_Float, 16, STR_LIT("f128")}},
|
|
||||||
|
{Type_Basic, {Basic_complex64, BasicFlag_Complex, 8, STR_LIT("complex64")}},
|
||||||
|
{Type_Basic, {Basic_complex128, BasicFlag_Complex, 16, STR_LIT("complex128")}},
|
||||||
|
|
||||||
{Type_Basic, {Basic_int, BasicFlag_Integer, -1, STR_LIT("int")}},
|
{Type_Basic, {Basic_int, BasicFlag_Integer, -1, STR_LIT("int")}},
|
||||||
{Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, -1, STR_LIT("uint")}},
|
{Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, -1, STR_LIT("uint")}},
|
||||||
|
|
||||||
{Type_Basic, {Basic_rawptr, BasicFlag_Pointer, -1, STR_LIT("rawptr")}},
|
{Type_Basic, {Basic_rawptr, BasicFlag_Pointer, -1, STR_LIT("rawptr")}},
|
||||||
{Type_Basic, {Basic_string, BasicFlag_String, -1, STR_LIT("string")}},
|
{Type_Basic, {Basic_string, BasicFlag_String, -1, STR_LIT("string")}},
|
||||||
{Type_Basic, {Basic_any, 0, -1, STR_LIT("any")}},
|
{Type_Basic, {Basic_any, 0, -1, STR_LIT("any")}},
|
||||||
|
|
||||||
{Type_Basic, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, 0, STR_LIT("untyped bool")}},
|
{Type_Basic, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, 0, STR_LIT("untyped bool")}},
|
||||||
{Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, 0, STR_LIT("untyped integer")}},
|
{Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, 0, STR_LIT("untyped integer")}},
|
||||||
{Type_Basic, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, 0, STR_LIT("untyped float")}},
|
{Type_Basic, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, 0, STR_LIT("untyped float")}},
|
||||||
|
{Type_Basic, {Basic_UntypedComplex, BasicFlag_Complex | BasicFlag_Untyped, 0, STR_LIT("untyped complex")}},
|
||||||
{Type_Basic, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, 0, STR_LIT("untyped string")}},
|
{Type_Basic, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, 0, STR_LIT("untyped string")}},
|
||||||
{Type_Basic, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, 0, STR_LIT("untyped rune")}},
|
{Type_Basic, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, 0, STR_LIT("untyped rune")}},
|
||||||
{Type_Basic, {Basic_UntypedNil, BasicFlag_Untyped, 0, STR_LIT("untyped nil")}},
|
{Type_Basic, {Basic_UntypedNil, BasicFlag_Untyped, 0, STR_LIT("untyped nil")}},
|
||||||
@@ -253,20 +248,24 @@ gb_global Type *t_i32 = &basic_types[Basic_i32];
|
|||||||
gb_global Type *t_u32 = &basic_types[Basic_u32];
|
gb_global Type *t_u32 = &basic_types[Basic_u32];
|
||||||
gb_global Type *t_i64 = &basic_types[Basic_i64];
|
gb_global Type *t_i64 = &basic_types[Basic_i64];
|
||||||
gb_global Type *t_u64 = &basic_types[Basic_u64];
|
gb_global Type *t_u64 = &basic_types[Basic_u64];
|
||||||
// gb_global Type *t_i128 = &basic_types[Basic_i128];
|
|
||||||
// gb_global Type *t_u128 = &basic_types[Basic_u128];
|
|
||||||
// gb_global Type *t_f16 = &basic_types[Basic_f16];
|
|
||||||
gb_global Type *t_f32 = &basic_types[Basic_f32];
|
gb_global Type *t_f32 = &basic_types[Basic_f32];
|
||||||
gb_global Type *t_f64 = &basic_types[Basic_f64];
|
gb_global Type *t_f64 = &basic_types[Basic_f64];
|
||||||
// gb_global Type *t_f128 = &basic_types[Basic_f128];
|
|
||||||
|
gb_global Type *t_complex64 = &basic_types[Basic_complex64];
|
||||||
|
gb_global Type *t_complex128 = &basic_types[Basic_complex128];
|
||||||
|
|
||||||
gb_global Type *t_int = &basic_types[Basic_int];
|
gb_global Type *t_int = &basic_types[Basic_int];
|
||||||
gb_global Type *t_uint = &basic_types[Basic_uint];
|
gb_global Type *t_uint = &basic_types[Basic_uint];
|
||||||
|
|
||||||
gb_global Type *t_rawptr = &basic_types[Basic_rawptr];
|
gb_global Type *t_rawptr = &basic_types[Basic_rawptr];
|
||||||
gb_global Type *t_string = &basic_types[Basic_string];
|
gb_global Type *t_string = &basic_types[Basic_string];
|
||||||
gb_global Type *t_any = &basic_types[Basic_any];
|
gb_global Type *t_any = &basic_types[Basic_any];
|
||||||
|
|
||||||
gb_global Type *t_untyped_bool = &basic_types[Basic_UntypedBool];
|
gb_global Type *t_untyped_bool = &basic_types[Basic_UntypedBool];
|
||||||
gb_global Type *t_untyped_integer = &basic_types[Basic_UntypedInteger];
|
gb_global Type *t_untyped_integer = &basic_types[Basic_UntypedInteger];
|
||||||
gb_global Type *t_untyped_float = &basic_types[Basic_UntypedFloat];
|
gb_global Type *t_untyped_float = &basic_types[Basic_UntypedFloat];
|
||||||
|
gb_global Type *t_untyped_complex = &basic_types[Basic_UntypedComplex];
|
||||||
gb_global Type *t_untyped_string = &basic_types[Basic_UntypedString];
|
gb_global Type *t_untyped_string = &basic_types[Basic_UntypedString];
|
||||||
gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune];
|
gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune];
|
||||||
gb_global Type *t_untyped_nil = &basic_types[Basic_UntypedNil];
|
gb_global Type *t_untyped_nil = &basic_types[Basic_UntypedNil];
|
||||||
@@ -293,6 +292,7 @@ gb_global Type *t_type_info_enum_value_ptr = NULL;
|
|||||||
gb_global Type *t_type_info_named = NULL;
|
gb_global Type *t_type_info_named = NULL;
|
||||||
gb_global Type *t_type_info_integer = NULL;
|
gb_global Type *t_type_info_integer = NULL;
|
||||||
gb_global Type *t_type_info_float = NULL;
|
gb_global Type *t_type_info_float = NULL;
|
||||||
|
gb_global Type *t_type_info_complex = NULL;
|
||||||
gb_global Type *t_type_info_any = NULL;
|
gb_global Type *t_type_info_any = NULL;
|
||||||
gb_global Type *t_type_info_string = NULL;
|
gb_global Type *t_type_info_string = NULL;
|
||||||
gb_global Type *t_type_info_boolean = NULL;
|
gb_global Type *t_type_info_boolean = NULL;
|
||||||
@@ -312,6 +312,7 @@ gb_global Type *t_type_info_map = NULL;
|
|||||||
gb_global Type *t_type_info_named_ptr = NULL;
|
gb_global Type *t_type_info_named_ptr = NULL;
|
||||||
gb_global Type *t_type_info_integer_ptr = NULL;
|
gb_global Type *t_type_info_integer_ptr = NULL;
|
||||||
gb_global Type *t_type_info_float_ptr = NULL;
|
gb_global Type *t_type_info_float_ptr = NULL;
|
||||||
|
gb_global Type *t_type_info_complex_ptr = NULL;
|
||||||
gb_global Type *t_type_info_any_ptr = NULL;
|
gb_global Type *t_type_info_any_ptr = NULL;
|
||||||
gb_global Type *t_type_info_string_ptr = NULL;
|
gb_global Type *t_type_info_string_ptr = NULL;
|
||||||
gb_global Type *t_type_info_boolean_ptr = NULL;
|
gb_global Type *t_type_info_boolean_ptr = NULL;
|
||||||
@@ -615,6 +616,13 @@ bool is_type_float(Type *t) {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool is_type_complex(Type *t) {
|
||||||
|
t = core_type(t);
|
||||||
|
if (t->kind == Type_Basic) {
|
||||||
|
return (t->Basic.flags & BasicFlag_Complex) != 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
bool is_type_f32(Type *t) {
|
bool is_type_f32(Type *t) {
|
||||||
t = core_type(t);
|
t = core_type(t);
|
||||||
if (t->kind == Type_Basic) {
|
if (t->kind == Type_Basic) {
|
||||||
@@ -695,6 +703,19 @@ Type *base_vector_type(Type *t) {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type *base_complex_elem_type(Type *t) {
|
||||||
|
t = core_type(t);
|
||||||
|
if (is_type_complex(t)) {
|
||||||
|
switch (t->Basic.kind) {
|
||||||
|
case Basic_complex64: return t_f32;
|
||||||
|
case Basic_complex128: return t_f64;
|
||||||
|
case Basic_UntypedComplex: return t_untyped_float;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GB_PANIC("Invalid complex type");
|
||||||
|
return t_invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool is_type_struct(Type *t) {
|
bool is_type_struct(Type *t) {
|
||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
@@ -953,6 +974,7 @@ Type *default_type(Type *type) {
|
|||||||
case Basic_UntypedBool: return t_bool;
|
case Basic_UntypedBool: return t_bool;
|
||||||
case Basic_UntypedInteger: return t_int;
|
case Basic_UntypedInteger: return t_int;
|
||||||
case Basic_UntypedFloat: return t_f64;
|
case Basic_UntypedFloat: return t_f64;
|
||||||
|
case Basic_UntypedComplex: return t_complex128;
|
||||||
case Basic_UntypedString: return t_string;
|
case Basic_UntypedString: return t_string;
|
||||||
case Basic_UntypedRune: return t_rune;
|
case Basic_UntypedRune: return t_rune;
|
||||||
}
|
}
|
||||||
@@ -1543,6 +1565,10 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
|||||||
|
|
||||||
case Basic_int: case Basic_uint: case Basic_rawptr:
|
case Basic_int: case Basic_uint: case Basic_rawptr:
|
||||||
return build_context.word_size;
|
return build_context.word_size;
|
||||||
|
|
||||||
|
case Basic_complex64: case Basic_complex128:
|
||||||
|
// complex{64,128} align as [2]f{32,64}
|
||||||
|
return type_size_of_internal(allocator, t, path) / 2;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user