Flutter符号表管理插件essential_symbol_table的使用
Flutter符号表管理插件essential_symbol_table的使用
简介
在本教程中,我们将详细介绍如何在Flutter中使用名为essential_symbol_table
的符号表管理插件。该插件提供了强大的功能来管理和操作符号表,包括变量创建、删除、查找等。
变量(Variables)
要表示一个符号,可以使用Variable
类。选择Variable
这个名字是为了避免与Dart的基本类型Symbol
冲突。
var foo = new Variable<String>('foo');
var bar = new Variable<String>('bar', value: 'baz');
// 使用`lock`方法将符号标记为不可变。
var shelley = new Variable<String>('foo', value: 'bar')..lock();
foo.value = 'bar';
shelley.value = 'Mary'; // 抛出StateError - 常量不能被覆盖。
foo.lock();
foo.value = 'baz'; // 同样抛出StateError - 一旦变量被锁定,就不能被覆盖。
可见性(Visibility)
变量默认是公开的(public),但也可以标记为私有(private)或受保护的(protected)。这有助于确定哪些符号应该从库或类中导出。
myVariable.visibility = Visibility.protected;
myVariable.visibility = Visibility.private;
符号表(Symbol Tables)
创建一个基本的符号表非常简单:
var mySymbolTable = new SymbolTable<int>();
var doubles = new SymbolTable<double>(values: {
'hydrogen': 1.0,
'avogadro': 6.022e23
});
// 在当前作用域内创建一个新的变量。
doubles.create('one');
doubles.create('one', value: 1.0);
doubles.create('one', value: 1.0, constant: true);
// 设置一个变量,如果不存在则创建新的变量。
doubles.assign('two', value: 2.0);
// 完全移除一个变量。
doubles.remove('two');
// 查找一个符号,可以在当前符号表或祖先表中找到。
var symbol = doubles.resolve('one');
// 查找或创建一个符号。
var symbol = doubles.resolveOrCreate('one');
var symbol = doubles.resolveOrCreate('one', value: 1.0);
var symbol = doubles.resolveOrCreate('one', value: 1.0, constant: true);
导出符号(Exporting Symbols)
由于符号表的树形结构,很容易提取出一个线性的变量列表,并且低层次的变量会覆盖其父级变量(有效地实现了变量屏蔽)。
var allSymbols = mySymbolTable.allVariables;
我们还可以提取非私有的符号。这有助于从库或类中导出符号。
var exportedSymbols = mySymbolTable.allPublicVariables;
提取具有特定可见性的符号也很容易:
var exportedSymbols = mySymbolTable.allVariablesWithVisibility(Visibility.protected);
子作用域(Child Scopes)
有三种方式可以创建新的符号表:
普通子作用域(Regular Children)
这是大多数解释器所需要的;它只是创建一个以当前符号表为父级的新符号表。新作用域可以定义自己的符号,这些符号只会屏蔽祖先作用域内的符号。
var child = mySymbolTable.createChild();
var child = mySymbolTable.createChild(values: {...});
深度(Depth)
每个符号表都有一个关联的depth
值,根的depth
为0
。当调用createChild
时,生成的子作用域的depth
会增加。
克隆(Clones)
这会在当前作用域的同一级别创建一个新的作用域,并且具有相同的变量。
var clone = mySymbolTable.clone();
分叉作用域(Forked Scopes)
如果你正在实现带有闭包函数的语言,你可能需要考虑这种方法。分叉作用域是一个与当前作用域相同的作用域,但它不是简单地复制变量的引用,而是将变量的值复制到新的变量中。
新作用域本质上是当前作用域的一个“冻结”版本。它也是孤立的——虽然它知道它的parent
,但父作用域不知道分叉作用域是它的子级。因此,调用resolve
时可能会返回旧的变量,如果父级已经调用remove
移除了某个符号。
var forked = mySymbolTable.fork();
var forked = mySymbolTable.fork(values: {...});
创建名称(Creating Names)
在具有块作用域的语言中,标识符常常会在全局作用域内发生冲突。为了避免这种情况,符号表暴露了一个uniqueName()
方法,该方法只是给输入名称附加一个数字后缀。该名称保证在一个特定的作用域内不会重复。
var name0 = mySymbolTable.uniqueName('foo'); // foo0
var name1 = mySymbolTable.uniqueName('foo'); // foo1
var name2 = mySymbolTable.uniqueName('foo'); // foo2
当前上下文(This Context)
许多语言处理一种类似于this
的上下文,该上下文允许范围内的值可选地解析。符号表可以通过以下方式设置其上下文:
void foo() {
mySymbolTable.context = thisContext;
}
// 解析`context`就像解析一个符号一样;如果没有本地设置,则会引用父级。
void bar() {
mySymbolTable.context = thisContext;
expect(mySymbolTable.createChild().createChild().context, thisContext);
}
更多关于Flutter符号表管理插件essential_symbol_table的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html