Flutter符号表管理插件belatuk_symbol_table的使用
Flutter符号表管理插件belatuk_symbol_table的使用
包含重大更改以支持NNBD的package:symbol_table
的替代品。
这是一个在Dart中实现的通用符号表库,支持作用域和常量。生成的符号表是分层的(在这种情况下,树形),并利用基本的缓存来加速重复查找。
变量
要表示一个符号,可以使用Variable
。我选择使用名称Variable
是为了避免与Dart的原始类型Symbol
冲突。
var foo = Variable<String>('foo');
var bar = Variable<String>('bar', value: 'baz');
// 调用`lock`将符号标记为不可变。
var shelley = Variable<String>('foo', value: 'bar')..lock();
foo.value = 'bar';
shelley.value = 'Mary'; // 抛出一个StateError - 常量不能被覆盖。
foo.lock();
foo.value = 'baz'; // 同样抛出一个StateError - 一旦变量被锁定,就不能被覆盖。
可见性
变量默认是公开的,但也可以标记为私有或受保护。这在你尝试确定哪些符号应该从库或类中导出时非常有用。
myVariable.visibility = Visibility.protected;
myVariable.visibility = Visibility.private;
符号表
创建一个基本的符号表很容易:
var mySymbolTable = SymbolTable<int>();
var doubles = 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', 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);
导出符号
由于符号表的树结构,提取一个线性的唯一变量列表变得非常简单,层次较低的变量会覆盖其父级变量(有效地实现了变量遮蔽)。
var allSymbols = mySymbolTable.allVariables;
我们还可以提取非私有的符号。这有助于我们从库或类中导出符号。
var exportedSymbols = mySymbolTable.allPublicVariables;
提取具有特定可见性的符号也很容易:
var exportedSymbols = mySymbolTable.allVariablesWithVisibility(Visibility.protected);
子作用域
有三种方式可以创建一个新的符号表:
普通子作用域
大多数解释器需要这种方式;它只是创建一个以当前符号表作为父级的新符号表。新作用域可以定义自己的符号,这些符号只会在其正确的范围内遮蔽祖先。
var child = mySymbolTable.createChild();
var child = mySymbolTable.createChild(values: {...});
深度
每个符号表都有一个关联的depth
值,根的深度为0
。当调用createChild
时,生成的子作用域的depth
会递增。
克隆
这会在当前级别创建一个具有所有相同变量的作用域。
var clone = mySymbolTable.clone();
分叉作用域
如果你正在实现一个带有闭包函数的语言,可以考虑这种方法。分叉作用域与当前作用域完全相同,但不是仅仅复制变量的引用,而是将变量的值复制到新的变量中。
新的作用域基本上是一个“冻结”的当前作用域。
它也是有效地孤立的——尽管它意识到它的parent
,但父作用域并不知道分叉作用域是一个子作用域。因此,如果父级调用了remove
,resolve
可能返回旧的变量。
var forked = mySymbolTable.fork();
var forked = mySymbolTable.fork(values: {...});
创建名称
在具有块作用域的语言中,标识符通常会在全局作用域中发生冲突。为了避免这种情况,符号表暴露了一个uniqueName()
方法,该方法只是给输入名称附加一个数字后缀。名称保证在一个特定的作用域内不会重复。
var name0 = mySymbolTable.uniqueName('foo'); // foo0
var name1 = mySymbolTable.uniqueName('foo'); // foo1
var name2 = mySymbolTable.uniqueName('foo'); // foo2
this上下文
许多语言处理一种this
上下文,其中作用域内的值可以选择性地解析。符号表可以轻松设置其上下文如下:
void foo() {
mySymbolTable.context = thisContext;
}
对context
的解析就像解析一个符号一样工作;如果本地没有设置,则它将引用父级。
void bar() {
mySymbolTable.context = thisContext;
expect(mySymbolTable.createChild().createChild().context, thisContext);
}
示例代码
import 'package:belatuk_symbol_table/belatuk_symbol_table.dart';
void main(List<String> args) {
//var mySymbolTable = SymbolTable<int>();
var doubles =
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', 2.0);
// 完全移除一个变量。
doubles.remove('two');
// 查找一个符号,要么在这个符号表中,要么在祖先中。
// var symbol1 = doubles.resolve('one');
// 查找或创建一个符号。
// var symbol2 = doubles.resolveOrCreate('one');
// var symbol3 = doubles.resolveOrCreate('one', value: 1.0);
// var symbol4 = doubles.resolveOrCreate('one', value: 1.0, constant: true);
}
更多关于Flutter符号表管理插件belatuk_symbol_table的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter符号表管理插件belatuk_symbol_table的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中使用belatuk_symbol_table
插件的示例代码案例。belatuk_symbol_table
插件用于管理符号表,这在处理动态符号解析、变量存储等场景时非常有用。
首先,确保你已经在pubspec.yaml
文件中添加了belatuk_symbol_table
依赖:
dependencies:
flutter:
sdk: flutter
belatuk_symbol_table: ^最新版本号 # 请替换为实际的最新版本号
然后运行flutter pub get
来获取依赖。
接下来,你可以在Flutter项目中创建一个简单的示例来演示如何使用belatuk_symbol_table
。
import 'package:flutter/material.dart';
import 'package:belatuk_symbol_table/belatuk_symbol_table.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Symbol Table Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SymbolTableDemo(),
);
}
}
class SymbolTableDemo extends StatefulWidget {
@override
_SymbolTableDemoState createState() => _SymbolTableDemoState();
}
class _SymbolTableDemoState extends State<SymbolTableDemo> {
final SymbolTable _symbolTable = SymbolTable();
void _addToSymbolTable(String key, dynamic value) {
_symbolTable.defineSymbol(key, value);
setState(() {});
}
dynamic _getFromSymbolTable(String key) {
return _symbolTable.resolveSymbol(key);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Symbol Table Demo'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextField(
decoration: InputDecoration(
labelText: 'Key',
),
onChanged: (key) {
// Handle key input
},
),
SizedBox(height: 16),
TextField(
decoration: InputDecoration(
labelText: 'Value',
),
onChanged: (value) {
// Handle value input
},
),
SizedBox(height: 16),
ElevatedButton(
onPressed: () {
// Example: Adding a string value
String key = 'exampleKey';
String value = 'exampleValue';
_addToSymbolTable(key, value);
// Display the value to verify
String resolvedValue = _getFromSymbolTable(key) as String;
print('Resolved Value: $resolvedValue');
},
child: Text('Add to Symbol Table'),
),
SizedBox(height: 16),
Text('Symbol Table Contents:'),
SizedBox(height: 8),
Expanded(
child: ListView.builder(
itemCount: _symbolTable.symbols.length,
itemBuilder: (context, index) {
final symbol = _symbolTable.symbols.keys.elementAt(index);
final value = _symbolTable.resolveSymbol(symbol);
return ListTile(
title: Text('$symbol: $value'),
);
},
),
),
],
),
),
);
}
}
在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个SymbolTable
实例。你可以通过点击按钮将键值对添加到符号表中,并在ListView中显示符号表的内容。
注意:
SymbolTable
的defineSymbol
方法用于定义符号。resolveSymbol
方法用于解析符号并获取其值。
实际应用中,你可能需要更复杂的逻辑来处理输入和输出,但这个示例提供了一个基本的框架,展示了如何在Flutter项目中使用belatuk_symbol_table
插件。