Updated symbol_table

This commit is contained in:
thomashii 2021-05-18 20:32:54 +08:00
parent 38e38c4a84
commit 082b7876b4
8 changed files with 66 additions and 27 deletions

View file

@ -1,3 +1,6 @@
# 2.0.1
* Resolved static analysis warnings
# 2.0.0 # 2.0.0
* Migrated to work with Dart SDK 2.12.x NNBD * Migrated to work with Dart SDK 2.12.x NNBD

View file

@ -1,5 +1,5 @@
# angel3_symbol_table # angel3_symbol_table
[![version](https://img.shields.io/badge/pub-v2.0.0-brightgreen)](https://pub.dartlang.org/packages/angel3_symbol_table) [![version](https://img.shields.io/badge/pub-v2.0.1-brightgreen)](https://pub.dartlang.org/packages/angel3_symbol_table)
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety) [![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion) [![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion)
@ -52,7 +52,7 @@ doubles.create('one', value: 1.0);
doubles.create('one', value: 1.0, constant: true); doubles.create('one', value: 1.0, constant: true);
// Set a variable within an ancestor, OR create a new variable if none exists. // Set a variable within an ancestor, OR create a new variable if none exists.
doubles.assign('two', value: 2.0); doubles.assign('two', 2.0);
// Completely remove a variable. // Completely remove a variable.
doubles.remove('two'); doubles.remove('two');

View file

@ -0,0 +1,4 @@
include: package:pedantic/analysis_options.yaml
analyzer:
strong-mode:
implicit-casts: false

View file

@ -0,0 +1,26 @@
import 'package:angel3_symbol_table/angel3_symbol_table.dart';
void main(List<String> args) {
var mySymbolTable = SymbolTable<int>();
var doubles =
SymbolTable<double>(values: {'hydrogen': 1.0, 'avogadro': 6.022e23});
// Create a new variable within the scope.
doubles.create('one');
doubles.create('one', value: 1.0);
doubles.create('one', value: 1.0, constant: true);
// Set a variable within an ancestor, OR create a new variable if none exists.
doubles.assign('two', 2.0);
// Completely remove a variable.
doubles.remove('two');
// Find a symbol, either in this symbol table or an ancestor.
var symbol1 = doubles.resolve('one');
// Find OR create a symbol.
var symbol2 = doubles.resolveOrCreate('one');
var symbol3 = doubles.resolveOrCreate('one', value: 1.0);
var symbol4 = doubles.resolveOrCreate('one', value: 1.0, constant: true);
}

View file

@ -17,7 +17,7 @@ class SymbolTable<T> {
/// Initializes an empty symbol table. /// Initializes an empty symbol table.
/// ///
/// You can optionally provide a [Map] of starter [values]. /// You can optionally provide a [Map] of starter [values].
SymbolTable({Map<String, T> values: const {}}) { SymbolTable({Map<String, T> values = const {}}) {
if (values.isNotEmpty == true) { if (values.isNotEmpty == true) {
values.forEach((k, v) { values.forEach((k, v) {
_variables.add(Variable<T>._(k, this, value: v)); _variables.add(Variable<T>._(k, this, value: v));
@ -40,7 +40,7 @@ class SymbolTable<T> {
} }
/// Sets a local context for values within this scope to be resolved against. /// Sets a local context for values within this scope to be resolved against.
void set context(T? value) { set context(T? value) {
_context = value; _context = value;
} }
@ -59,9 +59,11 @@ class SymbolTable<T> {
SymbolTable<T>? get root { SymbolTable<T>? get root {
if (_root != null) return _root; if (_root != null) return _root;
SymbolTable<T> out = this; var out = this;
while (out._parent != null) out = out._parent!; while (out._parent != null) {
out = out._parent!;
}
return _root = out; return _root = out;
} }
@ -73,8 +75,8 @@ class SymbolTable<T> {
/// ///
/// This list is unmodifiable. /// This list is unmodifiable.
List<Variable<T>> get allVariables { List<Variable<T>> get allVariables {
List<String> distinct = []; var distinct = <String>[];
List<Variable<T>> out = []; var out = <Variable<T>>[];
void crawl(SymbolTable<T> table) { void crawl(SymbolTable<T> table) {
for (var v in table._variables) { for (var v in table._variables) {
@ -111,8 +113,8 @@ class SymbolTable<T> {
/// ///
/// This list is unmodifiable. /// This list is unmodifiable.
List<Variable<T>> allVariablesWithVisibility(Visibility visibility) { List<Variable<T>> allVariablesWithVisibility(Visibility visibility) {
List<String> distinct = []; var distinct = <String>[];
List<Variable<T>> out = []; var out = <Variable<T>>[];
void crawl(SymbolTable<T> table) { void crawl(SymbolTable<T> table) {
for (var v in table._variables) { for (var v in table._variables) {
@ -151,12 +153,13 @@ class SymbolTable<T> {
/// You may optionally provide a [value], or mark the variable as [constant]. /// You may optionally provide a [value], or mark the variable as [constant].
Variable<T> create(String name, {T? value, bool? constant}) { Variable<T> create(String name, {T? value, bool? constant}) {
// Check if it exists first. // Check if it exists first.
if (_variables.any((v) => v.name == name)) if (_variables.any((v) => v.name == name)) {
throw StateError( throw StateError(
'A symbol named "$name" already exists within the current context.'); 'A symbol named "$name" already exists within the current context.');
}
_wipeLookupCache(name); _wipeLookupCache(name);
Variable<T> v = Variable._(name, this, value: value); var v = Variable<T>._(name, this, value: value);
if (constant == true) v.lock(); if (constant == true) v.lock();
_variables.add(v); _variables.add(v);
return v; return v;
@ -208,12 +211,13 @@ class SymbolTable<T> {
var v = _lookupCache.putIfAbsent(name, () { var v = _lookupCache.putIfAbsent(name, () {
var variable = _variables.firstWhereOrNull((v) => v.name == name); var variable = _variables.firstWhereOrNull((v) => v.name == name);
if (variable != null) if (variable != null) {
return variable; return variable;
else if (_parent != null) } else if (_parent != null) {
return _parent?.resolve(name); return _parent?.resolve(name);
else } else {
return null; return null;
}
}); });
if (v == null) { if (v == null) {
@ -238,7 +242,7 @@ class SymbolTable<T> {
/// Creates a child scope within this one. /// Creates a child scope within this one.
/// ///
/// You may optionally provide starter [values]. /// You may optionally provide starter [values].
SymbolTable<T> createChild({Map<String, T> values: const {}}) { SymbolTable<T> createChild({Map<String, T> values = const {}}) {
var child = SymbolTable(values: values); var child = SymbolTable(values: values);
child child
.._depth = _depth + 1 .._depth = _depth + 1
@ -273,7 +277,7 @@ class SymbolTable<T> {
/// The forked scope is essentially orphaned and stands alone; although its /// The forked scope is essentially orphaned and stands alone; although its
/// [parent] getter will point to the parent of the original scope, the parent /// [parent] getter will point to the parent of the original scope, the parent
/// will not be aware of the new scope's existence. /// will not be aware of the new scope's existence.
SymbolTable<T> fork({Map<String, T> values: const {}}) { SymbolTable<T> fork({Map<String, T> values = const {}}) {
var table = SymbolTable<T>(); var table = SymbolTable<T>();
table table
@ -282,7 +286,7 @@ class SymbolTable<T> {
.._root = _root; .._root = _root;
table._variables.addAll(_variables.map((Variable v) { table._variables.addAll(_variables.map((Variable v) {
Variable<T> variable = Variable._(v.name, this, value: v.value); var variable = Variable<T>._(v.name, this, value: v.value as T?);
variable.visibility = v.visibility; variable.visibility = v.visibility;
if (v.isImmutable) variable.lock(); if (v.isImmutable) variable.lock();
@ -297,7 +301,7 @@ class SymbolTable<T> {
/// The variation will the input [name], but with a numerical suffix appended. /// The variation will the input [name], but with a numerical suffix appended.
/// Ex. `foo1`, `bar24` /// Ex. `foo1`, `bar24`
String uniqueName(String name) { String uniqueName(String name) {
int count = 0; var count = 0;
SymbolTable? search = this; SymbolTable? search = this;
while (search != null) { while (search != null) {

View file

@ -31,9 +31,10 @@ class Variable<T> {
T? get value => _value; T? get value => _value;
void set value(T? value) { set value(T? value) {
if (_locked) if (_locked) {
throw StateError('The value of constant "$name" cannot be overwritten.'); throw StateError('The value of constant "$name" cannot be overwritten.');
}
_value = value; _value = value;
} }

View file

@ -13,9 +13,9 @@ part of symbol_table;
/// ///
/// In a nutshell: [private] < [protected] < [public]. /// In a nutshell: [private] < [protected] < [public].
class Visibility implements Comparable<Visibility> { class Visibility implements Comparable<Visibility> {
static const Visibility private = const Visibility._(0); static const Visibility private = Visibility._(0);
static const Visibility protected = const Visibility._(1); static const Visibility protected = Visibility._(1);
static const Visibility public = const Visibility._(2); static const Visibility public = Visibility._(2);
final int _n; final int _n;
const Visibility._(this._n); const Visibility._(this._n);
@ -28,4 +28,4 @@ class Visibility implements Comparable<Visibility> {
int compareTo(Visibility other) { int compareTo(Visibility other) {
return _n.compareTo(other._n); return _n.compareTo(other._n);
} }
} }

View file

@ -1,5 +1,5 @@
name: angel3_symbol_table name: angel3_symbol_table
version: 2.0.0 version: 2.0.1
description: A generic symbol table implementation in Dart, with support for scopes and constants. description: A generic symbol table implementation in Dart, with support for scopes and constants.
homepage: https://github.com/dukefirehawk/angel/tree/angel3/packages/symbol_table homepage: https://github.com/dukefirehawk/angel/tree/angel3/packages/symbol_table
environment: environment:
@ -7,4 +7,5 @@ environment:
dependencies: dependencies:
collection: ^1.15.0 collection: ^1.15.0
dev_dependencies: dev_dependencies:
test: ^1.17.4 test: ^1.17.4
pedantic: ^1.11.0