Skip to content

Commit

Permalink
feat: float的所有方法
Browse files Browse the repository at this point in the history
  • Loading branch information
Bylx666 committed Mar 27, 2024
1 parent aed1263 commit aebe518
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 25 deletions.
6 changes: 1 addition & 5 deletions samples/helloworld.ks
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,4 @@
//mod D:\code\rs\key-native\target\debug\key_native.dll> m
//mod D:\code\rs\key-lang\samples\testmod.ks> m;

log('{//start
8A03D5af 90
/ ok
3223 423 2
}')
log(2.76543.to_fixed(3))
133 changes: 133 additions & 0 deletions src/primitive/float.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
use crate::{
intern::{Interned,intern},
runtime::calc::CalcRef,
native::NativeFn
};
use super::litr::Litr;

fn to_f(v:&Litr)-> f64 {
match v {
Litr::Uint(n)=> *n as _,
Litr::Int(n)=> *n as _,
Litr::Float(n)=> *n,
_=> 0.0
}
}
pub fn method(n:f64, name:Interned, args:Vec<CalcRef>)-> Litr {
macro_rules! get_arg0 {($deal:ident)=> {
args.get(0).map_or(0.0, |n|$deal(n))
}}
match name.vec() {
// exponential 指数
b"log"=> Litr::Float(n.log(get_arg0!(to_f))),
b"log2"=> Litr::Float(n.log2()),
b"log10"=> Litr::Float(n.log10()),
b"ln"=> Litr::Float(n.ln()),
b"log1p"=> Litr::Float(n.ln_1p()),
b"exp"=> Litr::Float(n.exp()),
b"exp2"=> Litr::Float(n.exp2()),
b"expm1"=> Litr::Float(n.exp_m1()),
b"hypot"=> Litr::Float(n.hypot(get_arg0!(to_f))),

// triangles 三角函数
b"acos"=> Litr::Float(n.acos()),
b"acosh"=> Litr::Float(n.acosh()),
b"asin"=> Litr::Float(n.asin()),
b"asinh"=> Litr::Float(n.asinh()),
b"atan"=> Litr::Float(n.atan()),
b"atan2"=> Litr::Float(n.atan2(get_arg0!(to_f))),
b"atanh"=> Litr::Float(n.atanh()),
b"cos"=> Litr::Float(n.cos()),
b"cosh"=> Litr::Float(n.cosh()),
b"sin"=> Litr::Float(n.sin()),
b"sinh"=> Litr::Float(n.sinh()),
b"tan"=> Litr::Float(n.tan()),
b"tanh"=> Litr::Float(n.tanh()),
b"sincos"=> Litr::List(vec![Litr::Float(n.sin()), Litr::Float(n.cos())]),

// rounding 四舍五入
b"ceil"=> Litr::Int(n.ceil() as _),
b"floor"=> Litr::Float(n.floor()),
b"round"=> Litr::Float(n.round()),
b"trunc"=> Litr::Int(n.trunc() as _),
b"fract"=> Litr::Float(n.fract()),

// power 次幂
b"pow"=> Litr::Float(
args.get(0).map_or(0.0, |val|match &**val {
Litr::Uint(r)=> n.powi(*r as _),
Litr::Int(r)=> n.powi(*r as _),
Litr::Float(r)=> n.powf(*r),
_=> 1.0
})),
b"sqrt"=> Litr::Float(n.sqrt()),
b"cbrt"=> Litr::Float(n.cbrt()),
b"recip"=> Litr::Float(n.recip()),

// compare 比较
b"max"=> Litr::Float(n.max(get_arg0!(to_f))),
b"min"=> Litr::Float(n.min(get_arg0!(to_f))),
b"clamp"=> Litr::Float({
assert!(args.len()>=2, "float.clamp需要2个Float作为参数");
let [mut min,mut max] = [to_f(args.get(0).unwrap()), to_f(args.get(1).unwrap())];
if min > max {
std::mem::swap(&mut min, &mut max);
}
n.clamp(min,max)
}),

// sign 符号 注意0和-0的符号不一样
b"abs"=> Litr::Float(n.abs()),
b"copy_sign"=> Litr::Float(n.copysign(get_arg0!(to_f))),
b"is_pos"=> Litr::Bool(n.is_sign_positive()),

// Pi 圆周
b"deg"=> Litr::Float(n.to_degrees()),
b"rad"=> Litr::Float(n.to_radians()),

// memory 内存
b"as_buf"=> Litr::Buf(n.to_ne_bytes().to_vec()),
b"rev"=> Litr::Float({
let mut b = n.to_ne_bytes();
b.reverse();
// SAFETY: 这十分unsafe, 不过在考虑字节序时这会很便利
unsafe{std::mem::transmute(b)}
}),
b"is_nan"=> Litr::Bool(n.is_nan()),
b"is_infinite"=> Litr::Bool(n.is_infinite()),

// string 字符
b"to_str"=> Litr::Str(n.to_string()),
b"to_fixed"=> Litr::Str({
match args.get(0) {
Some(fix_to)=> {
let mut s = n.to_string();

let fix_to = 2 + match &**fix_to {
Litr::Int(n)=> *n as _,
Litr::Uint(n)=> *n as _,
_=> 0
};
let trunc_len = n.trunc().to_string().len();
let len = trunc_len - 1 + fix_to;

if len>=s.len() {
s.push_str(&"0".repeat(len - s.len()));
}else {
s.truncate(len);
}
s
}
None=> n.to_string()
}
}),

_=> panic!("{}上没有{}方法","Float",name)
}
}

// - statics -
pub fn statics()-> Vec<(Interned, NativeFn)> {
vec![
]
}
26 changes: 24 additions & 2 deletions src/primitive/int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub fn method_int(n:isize, name:Interned, args:Vec<CalcRef>)-> Litr {
b"to_hex"=> Litr::Str(format!("{:X}", n)),
b"min"=> Litr::Int(n.min(get_arg0!(to_isize))),
b"max"=> Litr::Int(n.max(get_arg0!(to_isize))),
_=> panic!("{}上没有{}方法","int",name)
_=> panic!("{}上没有{}方法","Int",name)
}
}

Expand All @@ -71,7 +71,7 @@ pub fn method_uint(n:usize, name:Interned, args:Vec<CalcRef>)-> Litr {
b"to_hex"=> Litr::Str(format!("{:X}", n)),
b"min"=> Litr::Uint(n.min(get_arg0!(to_usize))),
b"max"=> Litr::Uint(n.max(get_arg0!(to_usize))),
_=> panic!("{}上没有{}方法","int",name)
_=> panic!("{}上没有{}方法","Uint",name)
}
}

Expand All @@ -96,3 +96,25 @@ fn s_parse_int(args:Vec<CalcRef>, _cx:Scope)-> Litr {
}
Litr::Int(0)
}

// - statics uint -
pub fn statics_uint()-> Vec<(Interned, NativeFn)> {
vec![
(intern(b"parse"), s_parse_uint),
(intern(b"max"), |_,_|Litr::Uint(usize::MAX)),
(intern(b"min"), |_,_|Litr::Uint(usize::MIN))
]
}

/// 根据传入的进制解析字符串
fn s_parse_uint(args:Vec<CalcRef>, _cx:Scope)-> Litr {
let radix = args.get(1).map_or(10, |n|to_u32(&**n));
if let Some(s) = args.get(0) {
return match &**s {
Litr::Str(s)=> Litr::Uint(usize::from_str_radix(s, radix)
.unwrap_or_else(|_|panic!("Uint::parse: 数字'{}'解析失败",s))),
n=> Litr::Uint(to_usize(n))
}
}
Litr::Uint(0)
}
17 changes: 10 additions & 7 deletions src/primitive/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub mod kstd;
pub mod buf;
pub mod list;
pub mod int;
pub mod float;
pub mod sym;
pub mod obj;
pub mod iter;
Expand Down Expand Up @@ -68,13 +69,15 @@ pub fn classes()-> Vec<(Interned, Class)> {unsafe {
if let Some(cls) = &mut CLASSES {
cls.iter_mut().map(|(name, f)|(*name, Class::Native(f))).collect()
}else {
let buf_c = new_static_class(b"Buf", buf::statics());
let list_c = new_static_class(b"List", list::statics());
let obj_c = new_static_class(b"Obj", obj::statics());
let int_c = new_static_class(b"Int", int::statics_int());
let sym_c = new_static_class(b"Sym", sym::statics());
let func_c = new_static_class(b"Func", func::statics());
CLASSES = Some(vec![buf_c, list_c, obj_c, int_c, sym_c, func_c]);
CLASSES = Some(vec![
new_static_class(b"Buf", buf::statics()),
new_static_class(b"List", list::statics()),
new_static_class(b"Obj", obj::statics()),
new_static_class(b"Int", int::statics_int()),
new_static_class(b"Uint", int::statics_uint()),
new_static_class(b"Sym", sym::statics()),
new_static_class(b"Func", func::statics()),
]);
classes()
}
}}
Expand Down
14 changes: 3 additions & 11 deletions src/runtime/calc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -490,15 +490,6 @@ fn binary(mut this: Scope, left:&Box<Expr>, right:&Box<Expr>, op:&Box<[u8]>)-> L
_=> panic!($pan)
}
}};
($pan:literal $op:tt $n:tt)=> {{
if match &*right {
Int(r) => *r == 0,
Uint(r) => *r == 0,
Float(r) => *r == 0.0,
_=> false
} {panic!("除数必须非0")}
impl_num!($pan $op)
}};
}

/// 二元运算中无符号数的戏份
Expand Down Expand Up @@ -571,8 +562,9 @@ fn binary(mut this: Scope, left:&Box<Expr>, right:&Box<Expr>, op:&Box<[u8]>)-> L
},
b"-" => impl_num!("相减类型不同" -),
b"*" => impl_num!("相乘类型不同" *),
b"%" => impl_num!("求余类型不同" % 0),
b"/" => impl_num!("相除类型不同" / 0),
// 本应该判断非0的,还是让rust帮我报错吧
b"%" => impl_num!("求余类型不同" %),
b"/" => impl_num!("相除类型不同" /),

// unsigned
b"<<" => impl_unsigned!("左移需要左值无符号" <<),
Expand Down
1 change: 1 addition & 0 deletions src/runtime/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ impl Scope {
Litr::List(v)=> primitive::list::method(v, self, name, args),
Litr::Obj(o)=> primitive::obj::method(o, self, name, args),
Litr::Int(n)=> primitive::int::method_int(*n, name, args),
Litr::Float(n)=> primitive::float::method(*n, name, args),
Litr::Inst(inst)=> {
let cannot_access_private = unsafe {(*inst.cls).module} != self.exports;
let cls = unsafe {&*inst.cls};
Expand Down

0 comments on commit aebe518

Please sign in to comment.