Skip to content

Commit

Permalink
feat: 解构赋值
Browse files Browse the repository at this point in the history
  • Loading branch information
Bylx666 committed Apr 15, 2024
1 parent ab263fd commit a922c8a
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 37 deletions.
11 changes: 10 additions & 1 deletion samples/helloworld.ks
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,13 @@
//mod D:\code\rs\tst\target\debug\tstlib.dll> m;


log([2,4,6,5,3].map(|n|:n/2)); // [1,2,3,2,1]
// 定义一个有a和b两个属性的本地类型A
class A {
a b
}

// 创建一个A的实例
let inst = A::{a:9, b:20};
// 解构A实例得到a和b
let {a b} = inst;
log(a,b); // 9 20
13 changes: 2 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,11 @@ static VERSION:usize = 100005;
static DISTRIBUTION:&str = "Subkey";

fn main()-> ExitCode {
// clone版本的方法
// 更实用的宏
// let [] = x
// let a=0,b=0
// prelude mod 让模块本身帮你初始化上下文

// pub use
// 传进Native的struct怎么处理?
// Native outlive api
// key intern
// 更实用的宏
// 可变参数([args])
// ..[参数展开]
// extern to_raw_args
// throw catch
// catch
// 同名省略struct属性
// 科学计数法0x 0b
// linux macos支持
Expand Down
2 changes: 1 addition & 1 deletion src/primitive/kstr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub fn method(s:&mut String, scope:Scope, name:Interned, args:Vec<CalcRef>)-> Li
b"repeat"=> Litr::Str(s.repeat(get_arg0!(usize))),
b"replace"=> Litr::Str(_replace(s, args)),
b"splice"=> splice(s, args),
b"trim"=> void!(*s = s.trim().to_string()),
b"trim"=> Litr::Str(s.trim().to_string()),

// transmute
b"to_buf"=> Litr::Buf(s.as_bytes().to_vec()),
Expand Down
76 changes: 66 additions & 10 deletions src/runtime/evil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,9 @@ impl Scope {
}

// let语句
Stmt::Let(a)=> {
let mut v = self.calc(&a.val);
// 不检查变量是否存在是因为寻找变量的行为是反向的
self.vars.push(Variant {name:a.id, v, locked:false});
}
Stmt::Let(asn)=> assign(*self, asn, false),
// const语句
Stmt::Const(a)=> {
let mut v = self.calc(&a.val);
// 和let区别就是自动锁上
self.vars.push(Variant {name:a.id, v, locked:true});
}
Stmt::Const(asn)=> assign(*self, asn, true),
/// 锁定语句
Stmt::Lock(id)=> self.lock(*id),

Expand Down Expand Up @@ -178,6 +170,70 @@ impl Scope {
}
}

/// let和const
fn assign(mut s:Scope, asn:&AssignDef, locked: bool) {
// 如果用的是<而不是=, 则直接夺取右侧值所有权
let mut v = if asn.take {
std::mem::take(&mut *s.calc_ref(&asn.val))
} else {
s.calc(&asn.val)
};
// 不检查变量是否存在是因为寻找变量的行为是反向的
match &asn.id {
AssignTo::One(id)=> {
s.vars.push(Variant {name:*id, v, locked});
}
AssignTo::Destr(ids)=> match v {
// 属性解构
Litr::Inst(mut inst)=> {
let cls = unsafe{&*inst.cls};
for id in ids {
let i = cls.props.iter()
.position(|prop|*id==prop.name)
.expect(&format!("本地类'{}'实例没有'{}'属性", cls.name, id));
let v = std::mem::take(&mut inst.v[i]);
s.vars.push(Variant {name:*id, v, locked});
}
}
Litr::Ninst(v)=> {
let cls = unsafe{&*v.cls};
for id in ids {
let v = (cls.getter)(&v, *id);
s.vars.push(Variant {name:*id, v, locked});
}
}
Litr::Obj(mut map)=> for id in ids {
let v = map.remove(id).expect(&format!("哈希表中没有'{id}'属性"));
s.vars.push(Variant {name:*id, v, locked});
}

// 线性解构
Litr::Buf(v)=> {
let mut v = v.into_iter();
for id in ids {
let v = v.next().map_or(Litr::Uninit, |n|Litr::Uint(n as _));
s.vars.push(Variant {name:*id, v, locked});
}
}
Litr::Str(str)=> {
let mut itr = str.chars();
for id in ids {
let v = itr.next().map_or(Litr::Uninit, |s|Litr::Str(s.to_string()));
s.vars.push(Variant {name:*id, v, locked});
}
}
Litr::List(v)=> {
let mut v = v.into_iter();
for id in ids {
let v = v.next().unwrap_or(Litr::Uninit);
s.vars.push(Variant {name:*id, v, locked});
}
}
_=> panic!("{v:?}无法被解构赋值")
}
}
}

/// 判断if后的条件
fn cond(v:Litr)-> bool {
match v {
Expand Down
76 changes: 62 additions & 14 deletions src/scan/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ pub enum Stmt {
ExportFn (Interned, LocalFuncRaw),
ExportCls (*const ClassDefRaw),

Match, // 模式匹配
Match,

// 块系列
Block (Statements), // 一个普通块
Block (Statements),
If {
condition: Expr,
exec: Box<Stmt>,
Expand All @@ -59,8 +59,8 @@ pub enum Stmt {

// 流程控制
Break,
Continue, // 立刻进入下一次循环
Return (Expr), // 函数返回
Continue,
Return (Expr),

// 表达式作为语句
Expression(Expr),
Expand All @@ -69,8 +69,20 @@ pub enum Stmt {
/// 赋值语句
#[derive(Debug, Clone)]
pub struct AssignDef {
pub id: Interned,
pub val: Expr
/// =左侧
pub id: AssignTo,
/// =右侧
pub val: Expr,
/// 是否使用<代替=
pub take: bool
}

#[derive(Debug, Clone)]
pub enum AssignTo {
/// 单体赋值
One(Interned),
/// 解构赋值
Destr(Vec<Interned>)
}


Expand Down Expand Up @@ -175,7 +187,7 @@ impl Scanner<'_> {
}
// 修复开头遇到没定义的符号时死循环
127..=u8::MAX|b')'|b'}'|b']'|b'?'|b','|b'\\'|b'$'|b'#'=> panic!("需要一个语句或表达式,但你写了'{}'",String::from_utf8_lossy(&[first])),
_=>{}
_=> ()
}

let ident = self.literal();
Expand All @@ -202,6 +214,7 @@ impl Scanner<'_> {
b"break"=> Stmt::Break,
b"continue"=> Stmt::Continue,
b"async"|b"await"=> panic!("异步关键词暂时保留无法使用"),
b"match"=> panic!("match暂未实现"),
_=> {
let expr = self.expr_with_left(ident, vec![]);
Stmt::Expression(expr)
Expand All @@ -227,8 +240,28 @@ impl Scanner<'_> {
/// 解析let关键词
fn letting(&self)-> AssignDef {
self.spaces();
let id = self.ident().unwrap_or_else(||panic!("let后需要标识符"));
let id = intern(id);

let id = match self.cur() {
n@b'['|n@b'{'=> {
self.next();
let mut vec = Vec::new();
self.spaces();
while let Some(id) = self.ident() {
vec.push(intern(id));
self.spaces();
if self.cur() == b',' {
self.next();
self.spaces();
}
}
if n + 2 != self.cur() {
panic!("let解构错误:未闭合的括号'{}'", String::from_utf8_lossy(&[n]))
}
self.next();
AssignTo::Destr(vec)
}
_=> AssignTo::One(intern(self.ident().unwrap_or_else(||panic!("let后需要标识符"))))
};

// 检查标识符后的符号
self.spaces();
Expand All @@ -241,7 +274,18 @@ impl Scanner<'_> {
panic!("无法为空气赋值")
}
AssignDef {
id, val
id, val, take:false
}
}
// take语法
b'<'=> {
self.next();
let val = self.expr();
if let Expr::Empty = val {
panic!("无法为空气赋值")
}
AssignDef {
id, val, take:true
}
}
b'(' => {
Expand All @@ -264,12 +308,12 @@ impl Scanner<'_> {
// 其生命周期应当和Statements相同,绑定作用域时将被复制
// 绑定作用域行为发生在runtime::Scope::calc
AssignDef {
id,
id, take:false,
val: Expr::LocalDecl(LocalFuncRaw { argdecl: args, stmts })
}
}
_ => AssignDef {
id, val:Expr::Literal(Litr::Uninit)
id, take:false, val:Expr::Literal(Litr::Uninit)
}
}
}
Expand Down Expand Up @@ -328,7 +372,8 @@ impl Scanner<'_> {
String::from_utf8_lossy(path),
String::from_utf8_lossy(sym)));
self.push(Stmt::Let(AssignDef {
id:intern($id),
id: AssignTo::One(intern($id)),
take: false,
val: Expr::Literal(Litr::Func(Function::Extern(ExternFunc {
argdecl,
ptr
Expand Down Expand Up @@ -455,8 +500,11 @@ impl Scanner<'_> {
self.next();
// 套用let声明模板
let asn = self.letting();
let id = if let AssignTo::One(n) = asn.id {n}else {
panic!("mod.语句一次只能导出一个函数");
};
if let Expr::LocalDecl(f) = asn.val {
return Stmt::ExportFn(asn.id, f.clone());
return Stmt::ExportFn(id, f.clone());
}
panic!("模块只能导出本地函数。\n 若导出外界函数请用本地函数包裹。")
},
Expand Down

0 comments on commit a922c8a

Please sign in to comment.