diff --git a/samples/helloworld.ks b/samples/helloworld.ks index 3a5d9f4..563ecc5 100644 --- a/samples/helloworld.ks +++ b/samples/helloworld.ks @@ -1,5 +1,6 @@ mod D:\code\rs\key-native\target\debug\key_native.dll> m -let 😂😂 = 20 -log(😂😂) +let o = [2,"s",99] +o[1] = 111 +log(o) diff --git a/spec/ops.md b/spec/ops.md index a3fe93c..1f7fb4c 100644 --- a/spec/ops.md +++ b/spec/ops.md @@ -46,4 +46,14 @@ Str, Instance, List, Obj也依照以上算法比较。 使用连等: 为了减少无意义的数据复制,目前赋值语句只返回uninit,所以连等并不可用。 -一元运算符优先级比二元运算符高 \ No newline at end of file +一元运算符优先级比二元运算符高 + +index[] +以下类型可以使用索引 +Buffer 返回Uint,在下标无效时返回uninit +List 返回对应槽位的值 +Inst 类实例传入下标可以无视可见性读取第n个属性 +Str 获取第i个unicode字符(性能较差,请用迭代器替代) +Uint 传入小于64的数字,返回Bool,代表从右到左的二进制第i位是否为1 + +index不会报错,在遇到问题时会直接返回uninit \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 18b7dc2..ae1147b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,7 @@ fn main()-> ExitCode { // })); // index + // 迭代器 loop // 基本类型的方法,也就是所有litr的prop // 析构函数..? diff --git a/src/runtime/calc.rs b/src/runtime/calc.rs index 528b466..0774514 100644 --- a/src/runtime/calc.rs +++ b/src/runtime/calc.rs @@ -17,6 +17,9 @@ impl CalcRef { CalcRef::Own(v)=> v } } + pub fn uninit()-> Self { + CalcRef::Own(Litr::Uninit) + } } impl std::ops::Deref for CalcRef { type Target = Litr; @@ -41,10 +44,11 @@ impl Scope { /// /// 该函数必定发生复制 pub fn calc(&mut self,e:&Expr)-> Litr { - use Litr::*; match e { Expr::Call { args, targ }=> self.call(args, targ), + Expr::Index { left, i }=> calc_index(self, left, i).own(), + Expr::Literal(litr)=> litr.clone(), Expr::Variant(id)=> self.var(*id).clone(), @@ -60,6 +64,7 @@ impl Scope { // 一元运算符 Expr::Unary{right, op}=> { + use Litr::*; let right = self.calc_ref(right); match op { b'-'=> { @@ -237,6 +242,7 @@ impl Scope { let mut from = self.calc_ref(&e); get_prop(self, &mut *from, *find) } + Expr::Index { left, i }=> calc_index(self, left, i), Expr::Variant(id)=> CalcRef::Ref(self.var(*id)), // todo: Expr::Index _=> { @@ -275,7 +281,10 @@ fn expr_set(this:&mut Scope, left:&Expr, right:Litr) { let (rf, scope) = this.var_with_scope(*id); (CalcRef::Ref(rf), scope) } - // todo: Expr::Index + Expr::Index{left, i}=> { + let (mut from, scope) = calc_ref_with_scope(this, &left); + (calc_index(this, left, i), scope) + } _=> { let v = this.calc(e); // 如果是需要计算的量,就代表其作用域就在this @@ -301,7 +310,20 @@ fn expr_set(this:&mut Scope, left:&Expr, right:Litr) { _=> *get_prop(this, &mut left, *find) = right } } - // todo Expr::Index + Expr::Index{left,i}=> { + let (mut left, scope) = calc_ref_with_scope(this, &left); + let i = match this.calc(i) { + Litr::Int(n)=> n as usize, + Litr::Uint(n)=> n, + _=> err!("Index必须是整数") + }; + may_add_ref(&right, scope); + if let Litr::Ninst(inst) = &mut *left { + (unsafe{&*inst.cls}.isetter)(inst, i, right) + }else { + *index(left, i) = right; + } + } _=>{ let (mut left, scope) = calc_ref_with_scope(this, left); may_add_ref(&right, scope); @@ -373,6 +395,45 @@ fn get_prop(this:&Scope, from:&mut Litr, find:Interned)-> CalcRef { } } +fn calc_index(this:&mut Scope, left:&Box, i:&Box)-> CalcRef { + let mut left = this.calc_ref(left); + let i = match this.calc(i) { + Litr::Int(n)=> n as usize, + Litr::Uint(n)=> n, + _=> err!("Index必须是整数") + }; + index(left, i) +} +fn index(mut left:CalcRef, i:usize)-> CalcRef { + match &mut *left { + Litr::Buffer(v)=> { + if i>=v.len() {return CalcRef::uninit()} + CalcRef::Own(Litr::Uint(v[i] as usize)) + } + Litr::List(v)=> { + if i>=v.len() {return CalcRef::uninit()} + CalcRef::Ref(&mut v[i]) + } + Litr::Inst(v)=> { + if i>=v.v.len() {return CalcRef::uninit()} + CalcRef::Ref(&mut v.v[i]) + } + Litr::Ninst(v)=> { + CalcRef::Own((unsafe{&*v.cls}.igetter)(v, i)) + } + Litr::Str(n)=> { + match n.chars().nth(i) { + Some(c)=> CalcRef::Own(Litr::Str(c.to_string())), + None=> CalcRef::uninit() + } + } + Litr::Uint(n)=> { + if i>=64 {return CalcRef::Own(Litr::Bool(false));} + CalcRef::Own(Litr::Bool((*n & (1< CalcRef::uninit() + } +} fn binary(this:&mut Scope, left:&Box, right:&Box, op:&Box<[u8]>)-> Litr { use Litr::*; diff --git a/src/runtime/outlive.rs b/src/runtime/outlive.rs index 516c29b..0f1205d 100644 --- a/src/runtime/outlive.rs +++ b/src/runtime/outlive.rs @@ -116,6 +116,6 @@ pub fn may_add_ref(v:&crate::scan::literal::Litr, target_scope: Scope) { Litr::Inst(inst)=> inst.v.iter().for_each(|item|may_add_ref(item, target_scope)), Litr::Obj(map)=> map.values().for_each(|item|may_add_ref(item, target_scope)), - _=> {} + _=> () } } diff --git a/src/scan/expr.rs b/src/scan/expr.rs index 63cb524..e2da92f 100644 --- a/src/scan/expr.rs +++ b/src/scan/expr.rs @@ -31,6 +31,10 @@ pub enum Expr { args: Vec, targ: Box }, + Index{ + left: Box, + i: Box + }, // 创建实例 NewInst{ cls: Interned, @@ -139,9 +143,9 @@ impl Scanner<'_> { // 如果此运算符是括号就代表call if op == b"(" { - let targ = Box::new(expr_stack.pop().unwrap()); self.next(); self.spaces(); + let targ = Box::new(expr_stack.pop().unwrap()); let mut args = Vec::new(); loop { let e = self.expr(); @@ -163,7 +167,23 @@ impl Scanner<'_> { args, targ }); continue; - }; + } + + // 如果此运算符是方括号就代表index + if op == b"[" { + self.next(); + self.spaces(); + let left = Box::new(expr_stack.pop().unwrap()); + let i = Box::new(self.expr()); + if self.i() >= self.src.len() || self.cur() != b']' { + self.err("未闭合的右括号']'。"); + } + self.next(); + expr_stack.push(Expr::Index{ + left, i + }); + continue; + } // 将新运算符和它右边的值推进栈 self.spaces();