青语言开发文档

语境

创建于 2023-04-27 / 最近更新于 2023-04-27 / 1426
字体: [默认] [大] [更大]

语境是青语言中十分重要的概念,所有的代码执行均依赖于语境,所以再进一步了解青语言的执行过程前,我们先来了解一下语境。

语境类似于其他语言中的符号表或作用域的概念,用于在程序执行期间,记录变量名和变量值的绑定关系,因此其本质上是一个映射表,但添加了层级关系。语境类的定义:

public class Ctx {
        public Dictionary<string, Expr> Map { get; set; } //存储变量的表
        public Ctx? Father; //上级语境
        public CtxTp Tp = CtxTp.Default; //语境类型,主要是为了标记程序自动创建的临时语境,如循环、函数
        ……
}

这里的层级关系,对应的JS中的作用域链,因此在在语境中对变量进行查找、设值等操作时,除了本级语境外,还需考虑当前的语境链。因此,语境的相关操作基本包括两套逻辑。

public void PutNow(string k, Expr v) {
            Map[k] = v;
}

 public Expr GetNow(string k) {
            Expr v = Map.GetValueOrDefault(k, new Expr(TP.None, 0));
            return v;
 }

public Expr RemoveNow(string k) {
            if (Map.ContainsKey(k)) {
                Map.Remove(k);
                return new Expr(TP.Bool, true);
            } else {
                return new Expr(TP.Bool, false);
            }
}

这3个方法分别对应向语境中添加变量绑定、获取变量值、删除绑定的操作,并且只在当前语境中完成。

public void Put(string k, Expr v) {
            Ctx curr = this;
            /*逐级向上查找*/
            while (!curr.Map.ContainsKey(k) && curr.Father != null) {
                /*
                 * 不能修改LibCtx中的绑定关系
                 * 如果发现上级已经是LibCtx
                 * 那么直接再本级绑定
                 * 相当于是全局变量
                 */
                if (curr.Father.Father == null) {
                    curr.Map[k] = v;
                    return;
                }
                curr = curr.Father;
            }
            curr.Map[k] = v;
            return;
}

public Expr Get(string k) {
            Ctx curr = this;
            while (!curr.Map.ContainsKey(k) && curr.Father != null) {
                curr = curr.Father;
            }
            Expr v = curr.Map.GetValueOrDefault(k, new Expr(TP.None, 0));
            return v;
}

public Expr Remove(string k) {
            Ctx? ctx = this;
            while (ctx != null) {
                if (ctx.Map.ContainsKey(k)) {
                    if (ctx.Father == null) {
                        return new Expr(TP.Bool, false);
                    }
                    Map.Remove(k);
                    return new Expr(TP.Bool, true);
                }

                ctx = ctx.Father;

            }
            return new Expr(TP.Bool, false);
}

这里的3个方法同样对应添加变量绑定、获取变量值、删除绑定的操作,与前面不同的是,这些操作会沿着语境链逐层向上查找。
对于获取变量操作,向上查找的过程中一旦发现了某个语境中存在对应的记录,那么会立即返回该语境中记录的值。
对于添加和删除变量绑定操作,同样向上查找的过程中如果发现存在记录,那么就在该语境中执行对应的操作。但是这个逐级向上的操作最多可到达用户语境,而不会继续向上到达库语境,这么做是为了保护库语境中的记录,库语境是只读的。


语境的操作方式对应到语法中会出现2种设值方式,使用等号=进行赋值,那么会逐层向上查找,而如果使用冒号进行赋值,那么只会在当前语境进行操作。


青语言的对象本质上也是语境:

public class Obj : Ctx {
        /*
         * 这里定义了一个raw,用来存放原生的对象
         * 如果需要封装C#原生的功能
         * 可以继承Obj类,把原始的对象放到raw里
         * 再添加对原始对象的操作方法
         * 相应的例子在Proto命名空间里
         */
        public object Raw { get; set; }
        ……
}

对象的封装类型继承了语境类型,但添加了一个Raw用于保存原生的对象。

0 人点赞过