diff --git a/src/julec/compile.jule b/src/julec/compile.jule index 0b4301856..14d51e4b4 100644 --- a/src/julec/compile.jule +++ b/src/julec/compile.jule @@ -21,7 +21,7 @@ use std::jule::sema::{ SemaFlag, analyze_package, } -use std::jule::build::{ +use build for std::jule::build::{ self, LogMsg, Log, @@ -34,6 +34,7 @@ use std::jule::build::{ logf, is_valid_cpp_ext, } +use types for std::jule::types use std::process::{ProcessError, Cmd} use strings for std::strings @@ -271,13 +272,13 @@ fn check_target_flag(&target: str) { if os != "native" { check_target_os(os) - env::OS = os + build::OS = os } - if arch != "native" { check_target_arch(arch) - env::ARCH = arch + build::ARCH = arch } + types::update_target() } fn check_opt_flag(&opt: str) { diff --git a/src/julec/env/platform.jule b/src/julec/env/platform.jule deleted file mode 100644 index 09987586b..000000000 --- a/src/julec/env/platform.jule +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2023-2024 The Jule Programming Language. -// Use of this source code is governed by a BSD 3-Clause -// license that can be found in the LICENSE file. - -use std::env - -// Target operating system. -// Setted to current operating system by default. -pub static mut OS = std::env::OS - -// Target architecture. -// Setted to current architecture by default. -pub static mut ARCH = std::env::ARCH diff --git a/src/julec/importer/annotation.jule b/src/julec/importer/annotation.jule index 89b0397dd..3d8236efb 100644 --- a/src/julec/importer/annotation.jule +++ b/src/julec/importer/annotation.jule @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD 3-Clause // license that can be found in the LICENSE file. -use env - use path for std::fs::path use build for std::jule::build use strings for std::strings @@ -13,10 +11,14 @@ fn check_os(arg: str): (ok: bool, exist: bool) { exist = true match arg { - | build::Os.Windows: ok = build::is_windows(env::OS) - | build::Os.Darwin: ok = build::is_darwin(env::OS) - | build::Os.Linux: ok = build::is_linux(env::OS) - | build::Os.Unix: ok = build::is_unix(env::OS) + | build::Os.Windows: + ok = build::is_windows(build::OS) + | build::Os.Darwin: + ok = build::is_darwin(build::OS) + | build::Os.Linux: + ok = build::is_linux(build::OS) + | build::Os.Unix: + ok = build::is_unix(build::OS) |: ok = true exist = false @@ -30,11 +32,16 @@ fn check_arch(arg: str): (ok: bool, exist: bool) { exist = true match arg { - | build::Arch.I386: ok = build::is_i386(env::ARCH) - | build::Arch.Amd64: ok = build::is_amd64(env::ARCH) - | build::Arch.Arm64: ok = build::is_arm64(env::ARCH) - | build::Arch.X64: ok = build::is_64bit(env::ARCH) - | build::Arch.X32: ok = build::is_32bit(env::ARCH) + | build::Arch.I386: + ok = build::is_i386(build::ARCH) + | build::Arch.Amd64: + ok = build::is_amd64(build::ARCH) + | build::Arch.Arm64: + ok = build::is_arm64(build::ARCH) + | build::Arch.X64: + ok = build::is_64bit(build::ARCH) + | build::Arch.X32: + ok = build::is_32bit(build::ARCH) |: ok = true exist = false diff --git a/src/julec/importer/var.jule b/src/julec/importer/var.jule index facb75dae..073af6d89 100644 --- a/src/julec/importer/var.jule +++ b/src/julec/importer/var.jule @@ -4,35 +4,25 @@ use env -use std::jule::build::{Os, Arch, is_unix, is_32bit, is_64bit} +use build for std::jule::build pub static mut VARS: []str = nil // Set operating system variables by native operating system. fn set_os_vars() { - match env::OS { - | Os.Windows: VARS = append(VARS, "windows") - | Os.Linux: VARS = append(VARS, "linux") - | Os.Darwin: VARS = append(VARS, "darwin") - } - - if is_unix(env::OS) { + VARS = append(VARS, build::OS) + if build::is_unix(build::OS) { VARS = append(VARS, "unix") } } // Set architecture variables by native architecture. fn set_arch_vars() { - match env::ARCH { - | Arch.I386: VARS = append(VARS, "i386") - | Arch.Amd64: VARS = append(VARS, "amd64") - | Arch.Arm64: VARS = append(VARS, "arm64") - } - - if is_64bit(env::ARCH) { + VARS = append(VARS, build::ARCH) + if build::is_64bit(build::ARCH) { VARS = append(VARS, "x64") } - if is_32bit(env::ARCH) { + if build::is_32bit(build::ARCH) { VARS = append(VARS, "x32") } } @@ -51,13 +41,18 @@ pub fn init_vars() { } match env::COMPILER { - | "clang": VARS = append(VARS, "clang") - | "gcc": VARS = append(VARS, "gcc") + | "clang": + VARS = append(VARS, "clang") + | "gcc": + VARS = append(VARS, "gcc") } match env::CPP_STD { - | "cpp14": VARS = append(VARS, "cpp14") - | "cpp17": VARS = append(VARS, "cpp17") - | "cpp20": VARS = append(VARS, "cpp20") + | "cpp14": + VARS = append(VARS, "cpp14") + | "cpp17": + VARS = append(VARS, "cpp17") + | "cpp20": + VARS = append(VARS, "cpp20") } } diff --git a/std/jule/build/env.jule b/std/jule/build/env.jule index 64ad5b7cc..177e43b6c 100644 --- a/std/jule/build/env.jule +++ b/std/jule/build/env.jule @@ -13,6 +13,14 @@ pub static PATH_EXEC = "" // Path of executable file's directory. pub static PATH_WD = "" // Path of working directory. pub static PATH_API = "" // Path of main API header file. +// Target operating system. +// Setted to runtime operating system by default. +pub static mut OS = env::OS + +// Target architecture. +// Setted to runtime architecture by default. +pub static mut ARCH = env::ARCH + fn init() { let mut path = process::executable() if path == "" { diff --git a/std/jule/sema/eval.jule b/std/jule/sema/eval.jule index e13ffede0..d5e171cc6 100644 --- a/std/jule/sema/eval.jule +++ b/std/jule/sema/eval.jule @@ -145,8 +145,10 @@ fn is_ptr_arithmetic_compatible_int(mut &d: &Data): bool { ret int_assignable(types::TypeKind.Int, d) } let mut tcc = TypeCompatibilityChecker{ - dest: &TypeKind{kind: build_prim_type(types::TypeKind.Int)}, - src: d.kind, + dest: &TypeKind{ + kind: build_prim_type(types::TypeKind.Int), + }, + src: d.kind, } ret tcc.check() } @@ -155,29 +157,10 @@ fn normalize_type(mut &d: &Data) { match { | int_assignable(PrimKind.Int, d): d.kind.kind = build_prim_type(PrimKind.Int) - d.constant.set_i64(i64(d.constant.as_f64())) + d.constant.set_i64(d.constant.as_i64()) | int_assignable(PrimKind.Uint, d): d.kind.kind = build_prim_type(PrimKind.Uint) - d.constant.set_u64(u64(d.constant.as_f64())) - } -} - -// Fit constant value to type. -fn fit_type(mut &d: &Data) { - if !d.is_const() { - ret - } - - let p = d.kind.prim() - if p == nil { - ret - } - - let k = p.kind - match { - | types::is_float(k): d.constant.set_f64(d.constant.as_f64()) - | types::is_sig_int(k): d.constant.set_i64(d.constant.as_i64()) - | types::is_unsig_int(k): d.constant.set_u64(d.constant.as_u64()) + d.constant.set_u64(d.constant.as_u64()) } } @@ -210,25 +193,6 @@ fn build_void_data(): &Data { } } -fn kind_by_bitsize(expr: any): str { - match type expr { - | f64: - let x = f64(expr) - ret types::float_from_bits(types::bitsize_of_float(x)) - - | i64: - let x = i64(expr) - ret types::int_from_bits(types::bitsize_of_int(x)) - - | u64: - let x = u64(expr) - ret types::uint_from_bits(types::bitsize_of_uint(x)) - - |: - ret "" - } -} - fn check_data_for_integer_indexing(mut &d: &Data): (err_fmt: LogMsg) { if d == nil { ret LogMsg.Empty @@ -237,15 +201,12 @@ fn check_data_for_integer_indexing(mut &d: &Data): (err_fmt: LogMsg) { match { | d.kind.prim() == nil: ret LogMsg.InvalidTypeForIndexing - | !types::is_int(d.kind.prim().to_str()): ret LogMsg.InvalidTypeForIndexing - | d.is_const(): if d.constant.as_f64() < 0 { ret LogMsg.OverflowLimits } - | d.kind.prim() == nil | d.is_const() | types::real_kind_of(d.kind.prim().to_str()) != types::real_kind_of(PrimKind.Int): @@ -294,13 +255,19 @@ pub struct Data { impl Data { // Reports whether Data is nil literal. - pub fn is_nil(self): bool { ret self.kind.is_nil() } + pub fn is_nil(self): bool { + ret self.kind.is_nil() + } // Reports whether Data is void. - pub fn is_void(self): bool { ret self.kind.void() } + pub fn is_void(self): bool { + ret self.kind.void() + } // Reports whether Data is constant expression. - pub fn is_const(self): bool { ret self.constant != nil } + pub fn is_const(self): bool { + ret self.constant != nil + } // Reports left and right operand is good order. // If reports false, left and right operand should be swapped. @@ -355,12 +322,12 @@ impl Eval { } } - fn apply_numeric_prefix(mut self, mut &d: &Data) { + fn apply_numeric_prefix(mut self, mut &d: &Data): bool { if d == nil || d.cast_kind != nil || !d.is_const() || d.kind.prim() == nil { - ret + ret false } if self.prefix == nil || self.prefix.prim() == nil { - ret + ret false } let pk = self.prefix.prim().kind @@ -370,17 +337,18 @@ impl Eval { d.constant.set_f64(d.constant.as_f64()) | types::is_sig_int(pk): if !int_assignable(pk, d) { - break + ret false } d.kind = new(TypeKind, *self.prefix) d.constant.set_i64(d.constant.as_i64()) | types::is_unsig_int(pk): if !int_assignable(pk, d) { - break + ret false } d.kind = new(TypeKind, *self.prefix) d.constant.set_u64(d.constant.as_u64()) } + ret true } fn lit_nil(self): &Data { @@ -481,7 +449,7 @@ impl Eval { } fn lit_int(mut self, &l: &LitExpr): &Data { - const BIT_SIZE = 0b01000000 + const BIT_SIZE = 1 << 6 let mut lit = l.value let mut base = 0 @@ -517,7 +485,7 @@ impl Eval { if ok { d.constant = Const.new_i64(sig) d.kind = &TypeKind{ - kind: build_prim_type(PrimKind.Int), + kind: build_prim_type(PrimKind.I64), } } else { let unsig = parse_uint(lit, base, BIT_SIZE) else { @@ -527,15 +495,14 @@ impl Eval { } d.constant = Const.new_u64(unsig) d.kind = &TypeKind{ - kind: build_prim_type(PrimKind.Uint), + kind: build_prim_type(PrimKind.U64), } } d.model = d.constant - - // Apply prefix. - self.apply_numeric_prefix(d) - + if !self.apply_numeric_prefix(d) { + normalize_type(d) + } ret d } @@ -4315,6 +4282,29 @@ impl BinaryEval { d.model = d.constant apply_cast_model_by_enum(d, d.kind.enm()) + + let mut prim = d.kind.prim() + if prim == nil || !types::is_num(prim.to_str()) { + ret + } + if self.e.apply_numeric_prefix(d) { + ret + } + // If prefix is not implemented, check constant bitsize. + // Current data kind might be insufficient to store constant data. + // If this concern is true, set kind to minimum type that has enough bitsize. + let mut k = "" + match { + | d.constant.is_i64(): + k = types::int_from_bits(types::bitsize_of_int(d.constant.read_i64())) + | d.constant.is_u64(): + k = types::uint_from_bits(types::bitsize_of_uint(d.constant.read_u64())) + | d.constant.is_f64(): + k = types::float_from_bits(types::bitsize_of_float(d.constant.read_f64())) + } + if types::is_greater(k, types::real_kind_of(prim.kind)) { + prim.kind = k + } } fn check_data(mut self, mut &d: &Data) { @@ -4355,8 +4345,6 @@ impl BinaryEval { fn post_eval(mut self, mut &d: &Data) { d.lvalue = false self.set_model(d) - - self.e.apply_numeric_prefix(d) } fn solve_explicit(mut self, mut &l: &Data, mut &r: &Data): &Data { diff --git a/std/jule/types/bits.jule b/std/jule/types/bits.jule index 2897ab79b..80a7ae201 100644 --- a/std/jule/types/bits.jule +++ b/std/jule/types/bits.jule @@ -4,18 +4,38 @@ use conv for std::conv use strings for std::strings +use build for std::jule::build type BitChecker: fn(v: str, base: int, bit: int): bool +// Bit-size of target architecture. +// Possible values are: 32, and 64. +pub static BIT_SIZE = 0 + +// Signed integer kind of target architecture. +// Is equavalent to "int", but specific bit-sized integer kind. +pub static SYS_INT = "" + +// Unsigned integer kind of target architecture. +// Is equavalent to "uint" and "uintptr", but specific bit-sized integer kind. +pub static SYS_UINT = "" + fn check_bit(v: str, bit: int, checker: BitChecker): bool { match { - | v == "": ret false - | v.len == 1: ret true - | strings::has_prefix(v, "0x"): ret checker(v[2:], 0b00010000, bit) // Hexadecimal - | strings::has_prefix(v, "0b"): ret checker(v[2:], 0b10, bit) // Binary - | strings::has_prefix(v, "0o"): ret checker(v[2:], 0b1000, bit) // Octal - | v[0] == '0': ret checker(v[1:], 0b1000, bit) // Octal - |: ret checker(v, 0b1010, bit) // Decimal + | v == "": + ret false + | v.len == 1: + ret true + | strings::has_prefix(v, "0x"): + ret checker(v[2:], 1 << 4, bit) // Hexadecimal + | strings::has_prefix(v, "0b"): + ret checker(v[2:], 1 << 1, bit) // Binary + | strings::has_prefix(v, "0o"): + ret checker(v[2:], 1 << 3, bit) // Octal + | v[0] == '0': + ret checker(v[1:], 1 << 3, bit) // Octal + |: + ret checker(v, 1 << 3 + 2, bit) // Decimal } } @@ -40,18 +60,18 @@ pub fn bitsize_of(k: str): int { match k { | TypeKind.I8 | TypeKind.U8: - ret 0b1000 + ret 1 << 3 | TypeKind.I16 | TypeKind.U16: - ret 0b00010000 + ret 1 << 4 | TypeKind.I32 | TypeKind.U32 | TypeKind.F32: - ret 0b00100000 + ret 1 << 5 | TypeKind.I64 | TypeKind.U64 | TypeKind.F64: - ret 0b01000000 + ret 1 << 6 | TypeKind.Uint | TypeKind.Int: ret BIT_SIZE @@ -65,11 +85,16 @@ pub fn bitsize_of(k: str): int { // Returns empty string if bits is invalid. pub fn int_from_bits(bits: u64): str { match bits { - | 0b1000: ret TypeKind.I8 - | 0b00010000: ret TypeKind.I16 - | 0b00100000: ret TypeKind.I32 - | 0b01000000: ret TypeKind.I64 - |: ret "" + | 1 << 3: + ret TypeKind.I8 + | 1 << 4: + ret TypeKind.I16 + | 1 << 5: + ret TypeKind.I32 + | 1 << 6: + ret TypeKind.I64 + |: + ret "" } } @@ -78,11 +103,16 @@ pub fn int_from_bits(bits: u64): str { // Returns empty string if bits is invalid. pub fn uint_from_bits(bits: u64): str { match bits { - | 0b1000: ret TypeKind.U8 - | 0b00010000: ret TypeKind.U16 - | 0b00100000: ret TypeKind.U32 - | 0b01000000: ret TypeKind.U64 - |: ret "" + | 1 << 3: + ret TypeKind.U8 + | 1 << 4: + ret TypeKind.U16 + | 1 << 5: + ret TypeKind.U32 + | 1 << 6: + ret TypeKind.U64 + |: + ret "" } } @@ -91,9 +121,12 @@ pub fn uint_from_bits(bits: u64): str { // Returns empty string if bits is invalid. pub fn float_from_bits(bits: u64): str { match bits { - | 0b00100000: ret TypeKind.F32 - | 0b01000000: ret TypeKind.F64 - |: ret "" + | 1 << 5: + ret TypeKind.F32 + | 1 << 6: + ret TypeKind.F64 + |: + ret "" } } @@ -126,8 +159,10 @@ pub fn check_bit_float(val: str, bit: int): bool { // - 64 for 64-bit pub fn bitsize_of_float(x: f64): u64 { match { - | MIN_F32 <= x && x <= MAX_F32: ret 0b00100000 - |: ret 0b01000000 + | MIN_F32 <= x && x <= MAX_F32: + ret 1 << 5 + |: + ret 1 << 6 } } @@ -140,10 +175,14 @@ pub fn bitsize_of_float(x: f64): u64 { // - 64 for 64-bit pub fn bitsize_of_int(x: i64): u64 { match { - | MIN_I8 <= x && x <= MAX_I8: ret 0b1000 - | MIN_I16 <= x && x <= MAX_I16: ret 0b00010000 - | MIN_I32 <= x && x <= MAX_I32: ret 0b00100000 - |: ret 0b01000000 + | MIN_I8 <= x && x <= MAX_I8: + ret 1 << 3 + | MIN_I16 <= x && x <= MAX_I16: + ret 1 << 4 + | MIN_I32 <= x && x <= MAX_I32: + ret 1 << 5 + |: + ret 1 << 6 } } @@ -156,9 +195,35 @@ pub fn bitsize_of_int(x: i64): u64 { // - 64 for 64-bit pub fn bitsize_of_uint(x: u64): u64 { match { - | x <= MAX_U8: ret 0b1000 - | x <= MAX_U16: ret 0b00010000 - | x <= MAX_U32: ret 0b00100000 - |: ret 0b01000000 + | x <= MAX_U8: + ret 1 << 3 + | x <= MAX_U16: + ret 1 << 4 + | x <= MAX_U32: + ret 1 << 5 + |: + ret 1 << 6 + } +} + +// Updates platform-specific informations by target. +// If you will update target configuration, you should call this function. +// In other words, new configurations is not applied for types. +pub fn update_target() { + unsafe { + match build::ARCH { + | "arm64" | "amd64": + *(&BIT_SIZE) = 1 << 6 + *(&SYS_INT) = TypeKind.I64 + *(&SYS_UINT) = TypeKind.U64 + | "i386": + *(&BIT_SIZE) = 1 << 5 + *(&SYS_INT) = TypeKind.I32 + *(&SYS_UINT) = TypeKind.U32 + } } } + +fn init() { + update_target() +} diff --git a/std/jule/types/bits_x32.jule b/std/jule/types/bits_x32.jule deleted file mode 100644 index d68cd9977..000000000 --- a/std/jule/types/bits_x32.jule +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2023-2024 The Jule Programming Language. -// Use of this source code is governed by a BSD 3-Clause -// license that can be found in the LICENSE file. - -// Bit-size of runtime architecture. -// Possible values are: 32, and 64. -pub const BIT_SIZE = 0b00100000 - -// Signed integer kind of runtime architecture. -// Is equavalent to "int", but specific bit-sized integer kind. -pub const SYS_INT = "i32" - -// Unsigned integer kind of runtime architecture. -// Is equavalent to "uint" and "uintptr", but specific bit-sized integer kind. -pub const SYS_UINT = "u32" diff --git a/std/jule/types/bits_x64.jule b/std/jule/types/bits_x64.jule deleted file mode 100644 index 850dc44e9..000000000 --- a/std/jule/types/bits_x64.jule +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2023-2024 The Jule Programming Language. -// Use of this source code is governed by a BSD 3-Clause -// license that can be found in the LICENSE file. - -// Bit-size of runtime architecture. -// Possible values are: 32, and 64. -pub const BIT_SIZE = 0b01000000 - -// Signed integer kind of runtime architecture. -// Is equavalent to "int", but specific bit-sized integer kind. -pub const SYS_INT = "i64" - -// Unsigned integer kind of runtime architecture. -// Is equavalent to "uint" and "uintptr", but specific bit-sized integer kind. -pub const SYS_UINT = "u64" diff --git a/std/jule/types/limits.jule b/std/jule/types/limits.jule index 3a57b312f..30e8e075b 100644 --- a/std/jule/types/limits.jule +++ b/std/jule/types/limits.jule @@ -47,13 +47,20 @@ pub const MAX_U64 = 18446744073709551615 pub fn min(mut k: str): f64 { k = real_kind_of(k) match k { - | TypeKind.I8: ret MIN_I8 - | TypeKind.I16: ret MIN_I16 - | TypeKind.I32: ret MIN_I32 - | TypeKind.I64: ret MIN_I64 - | TypeKind.F32: ret MIN_F32 - | TypeKind.F64: ret MIN_F64 - |: ret 0 + | TypeKind.I8: + ret MIN_I8 + | TypeKind.I16: + ret MIN_I16 + | TypeKind.I32: + ret MIN_I32 + | TypeKind.I64: + ret MIN_I64 + | TypeKind.F32: + ret MIN_F32 + | TypeKind.F64: + ret MIN_F64 + |: + ret 0 } } @@ -62,16 +69,27 @@ pub fn min(mut k: str): f64 { pub fn max(mut k: str): f64 { k = real_kind_of(k) match k { - | TypeKind.I8: ret MAX_I8 - | TypeKind.I16: ret MAX_I16 - | TypeKind.I32: ret MAX_I32 - | TypeKind.I64: ret MAX_I64 - | TypeKind.U8: ret MAX_U8 - | TypeKind.U16: ret MAX_U16 - | TypeKind.U32: ret MAX_U32 - | TypeKind.U64: ret MAX_U64 - | TypeKind.F32: ret MAX_F32 - | TypeKind.F64: ret MAX_F64 - |: ret 0 + | TypeKind.I8: + ret MAX_I8 + | TypeKind.I16: + ret MAX_I16 + | TypeKind.I32: + ret MAX_I32 + | TypeKind.I64: + ret MAX_I64 + | TypeKind.U8: + ret MAX_U8 + | TypeKind.U16: + ret MAX_U16 + | TypeKind.U32: + ret MAX_U32 + | TypeKind.U64: + ret MAX_U64 + | TypeKind.F32: + ret MAX_F32 + | TypeKind.F64: + ret MAX_F64 + |: + ret 0 } }