什么语言适合写游戏脚本_用Rust写脚本语言(十八):对象的新身份

Cowsay:用Rust写脚本语言(零):目录​zhuanlan.zhihu.com
1c165ea69b5547da420eb132506f4658.png
whoiscc/shattuck​github.com
b5afd2a40bd6dcb0e4bb4baa7059c6e0.png

From this article I will continue writing in English. The following articles could be uncomfortable to read at first. But I will try my best to improve my English-writing skill.

The titles of the following articles remain in Chinese, because Zhihu limits English title unacceptable shortly.


The re-designed Memory and Runtime structs are agnostic to the concrete type of objects. Pratically the type will keep the original Box<dyn Object> structure. This structure assures constant size known at compile time, while permits flexiable implementation of Object by various custom types. However, I will try my best to ignore this fact when dealing with Memory and Runtime, because it makes me confused about the funtionality of them quite much. As a vivid example, I will introduce Method and AsMethod traits, which are deeply affected by this new-styled Runtime.

The two traits Method and AsMethod lives besides the definition of Object previously. However, the reason why they exist is Runtime, who is responsible to invoking methods. To resolve the conflict above, I defined "could be executed as a method (possibly)" as one of two basic features of objects. It works well, just a little annoying when I question myself why a submodule in core has to use a submodule not in core .

At the same time, MethodObject in objects submodule also has a strong connection on the conception of Runtime (and RuntimeError). And Object, desipte no direct relationship with Runtime, relies on MethodObject through its as_method interface which is required to exist by AsMethod super trait. It is more annoying that Runtime appears in the conception of Object, which should be as "pure" as possible in my thoughts.

After eliminating Object trait objects from Runtime, the very first thing I did is removing core::object and objects submodules in a whole. This doesn't mean I think they are not an essential part of Shattuck. They just need a full rewriting.

When I was doing this, I realized that Runtime cannot execute any object as method any more. It knows nothing about its type arguments L and S, except their relationship to each other. They may implement Object, and they may not. Actually, these is not a Object for them to implement at that time (and currently).


The Runtime be hardly useful without the missing function. To find a way to re-add it, I need to think of a central problem first:

Who requires AsMethod, Object or Runtime?

Suddenly I found benefit that I previously ignored. With the action of extracting object type into type arguments from Runtime, I got a chance to design a "slimmer" version of Object. It is not required to have any feature by default. It is just required to exist. Anyone who wants to filter out objects with specific functionality defines its own As* trait. For Runtime, it needs to determine the objects which could be treated as methods, so it introduces AsMethod. It does not need to access any properties of any objects (for now), so AsProp could be safely excluded from all the conception currently.

And what's more (which looks like an overdesign), the AsMethod trait is only required to be implemented by objects when we need Runtime to have ability to call method objects indeed. So the "common" methods, like share and insert, could live in an impl block which doesn't bound AsMethod to any of L, S and O.

Speaking of this, AsMethod is only required for S after some thinking. Like my explaination in the 4th article, method objects need to be copied before executed, and it would be too limited to require L to be Cloneable. S is stored in Arc<RwLock<...>> in Runtime, which implements Clone inherently. Thus, a method object will be shared before executed. In this way, the only limitation to the native code inside is that it cannot borrow the method object itself mutably (aka, cannot call write on it). This is absolutely reasonable for a method object.

The part of code looks like this:

impl<O, L, S> Runtime<L, S>
where
    O: ?Sized,
    S: From<L> + DerefMut<Target = O> + AsMethod<L, S>,
    L: DerefMut<Target = O>,
{
    pub fn call(&mut self, method: usize) -> Result<(), RuntimeError> {
        let share_object = Arc::clone(&self.share(method)?.0);
        let read_method = share_object
            .read()
            .map_err(|_| RuntimeError::AccessConflict)?;
        read_method.as_method()?.run(self)
    }
}

Notice the redundant part after where. It seems there's no way to abstract them into a trait or something. What a pity.

Cowsay:用Rust写脚本语言(零):目录​zhuanlan.zhihu.com
1c165ea69b5547da420eb132506f4658.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值