Learning Dart

This commit is contained in:
2023-04-06 11:35:43 -05:00
parent fab045379a
commit b16a5813cc
92 changed files with 6437 additions and 21 deletions

View File

@@ -0,0 +1,284 @@
{
"configVersion": 2,
"packages": [
{
"name": "_fe_analyzer_shared",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/_fe_analyzer_shared-58.0.0",
"packageUri": "lib/",
"languageVersion": "2.17"
},
{
"name": "analyzer",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/analyzer-5.10.0",
"packageUri": "lib/",
"languageVersion": "2.19"
},
{
"name": "args",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/args-2.4.0",
"packageUri": "lib/",
"languageVersion": "2.18"
},
{
"name": "async",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/async-2.11.0",
"packageUri": "lib/",
"languageVersion": "2.18"
},
{
"name": "boolean_selector",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1",
"packageUri": "lib/",
"languageVersion": "2.17"
},
{
"name": "collection",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/collection-1.17.1",
"packageUri": "lib/",
"languageVersion": "2.18"
},
{
"name": "convert",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/convert-3.1.1",
"packageUri": "lib/",
"languageVersion": "2.18"
},
{
"name": "coverage",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/coverage-1.6.3",
"packageUri": "lib/",
"languageVersion": "2.18"
},
{
"name": "crypto",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/crypto-3.0.2",
"packageUri": "lib/",
"languageVersion": "2.14"
},
{
"name": "file",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/file-6.1.4",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "frontend_server_client",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/frontend_server_client-3.2.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "glob",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/glob-2.1.1",
"packageUri": "lib/",
"languageVersion": "2.15"
},
{
"name": "http_multi_server",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/http_multi_server-3.2.1",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "http_parser",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/http_parser-4.0.2",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "io",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/io-1.0.4",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "js",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/js-0.6.7",
"packageUri": "lib/",
"languageVersion": "2.19"
},
{
"name": "logging",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/logging-1.1.1",
"packageUri": "lib/",
"languageVersion": "2.18"
},
{
"name": "matcher",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/matcher-0.12.15",
"packageUri": "lib/",
"languageVersion": "2.18"
},
{
"name": "meta",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/meta-1.9.1",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "mime",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/mime-1.0.4",
"packageUri": "lib/",
"languageVersion": "2.18"
},
{
"name": "node_preamble",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/node_preamble-2.0.2",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "package_config",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/package_config-2.1.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "path",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/path-1.8.3",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "pool",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/pool-1.5.1",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "pub_semver",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/pub_semver-2.1.3",
"packageUri": "lib/",
"languageVersion": "2.17"
},
{
"name": "shelf",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/shelf-1.4.0",
"packageUri": "lib/",
"languageVersion": "2.17"
},
{
"name": "shelf_packages_handler",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/shelf_packages_handler-3.0.1",
"packageUri": "lib/",
"languageVersion": "2.14"
},
{
"name": "shelf_static",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/shelf_static-1.1.1",
"packageUri": "lib/",
"languageVersion": "2.14"
},
{
"name": "shelf_web_socket",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/shelf_web_socket-1.0.3",
"packageUri": "lib/",
"languageVersion": "2.17"
},
{
"name": "source_map_stack_trace",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/source_map_stack_trace-2.1.1",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "source_maps",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/source_maps-0.10.12",
"packageUri": "lib/",
"languageVersion": "2.18"
},
{
"name": "source_span",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/source_span-1.10.0",
"packageUri": "lib/",
"languageVersion": "2.18"
},
{
"name": "stack_trace",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/stack_trace-1.11.0",
"packageUri": "lib/",
"languageVersion": "2.18"
},
{
"name": "stream_channel",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/stream_channel-2.1.1",
"packageUri": "lib/",
"languageVersion": "2.14"
},
{
"name": "string_scanner",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/string_scanner-1.2.0",
"packageUri": "lib/",
"languageVersion": "2.18"
},
{
"name": "term_glyph",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/term_glyph-1.2.1",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "test",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/test-1.24.1",
"packageUri": "lib/",
"languageVersion": "2.18"
},
{
"name": "test_api",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/test_api-0.5.1",
"packageUri": "lib/",
"languageVersion": "2.18"
},
{
"name": "test_core",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/test_core-0.5.1",
"packageUri": "lib/",
"languageVersion": "2.18"
},
{
"name": "typed_data",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/typed_data-1.3.1",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "vm_service",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/vm_service-11.3.0",
"packageUri": "lib/",
"languageVersion": "2.19"
},
{
"name": "watcher",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/watcher-1.0.2",
"packageUri": "lib/",
"languageVersion": "2.14"
},
{
"name": "web_socket_channel",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/web_socket_channel-2.3.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "webkit_inspection_protocol",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/webkit_inspection_protocol-1.2.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "yaml",
"rootUri": "file:///home/brbuller/.pub-cache/hosted/pub.dev/yaml-3.1.1",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "forth",
"rootUri": "../",
"packageUri": "lib/",
"languageVersion": "2.18"
}
],
"generated": "2023-04-06T15:26:04.782779Z",
"generator": "pub",
"generatorVersion": "2.19.6"
}

View File

@@ -0,0 +1,21 @@
{
"authors": [
"matthewmorgan"
],
"contributors": [
"AlexeyBukin",
"kytrinyx"
],
"files": {
"solution": [
"lib/forth.dart"
],
"test": [
"test/forth_test.dart"
],
"example": [
".meta/lib/example.dart"
]
},
"blurb": "Implement an evaluator for a very simple subset of Forth."
}

View File

@@ -0,0 +1 @@
{"track":"dart","exercise":"forth","id":"557606834f504c0f83bb01fb309aed02","url":"https://exercism.org/tracks/dart/exercises/forth","handle":"br0xen","is_requester":true,"auto_approve":false}

37
dart/forth/HELP.md Normal file
View File

@@ -0,0 +1,37 @@
# Help
## Running the tests
To run the tests:
```sh
$ dart test
```
## Submitting your solution
You can submit your solution using the `exercism submit lib/forth.dart` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Dart track's documentation](https://exercism.org/docs/tracks/dart)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [Dart API Documentation](https://api.dart.dev/)
- [Dart Gitter Chat](https://gitter.im/dart-lang/home)
- [Community Information](https://www.dart.dev/community)
- [/r/dartlang](https://www.reddit.com/r/dartlang) is the Dart subreddit.
- [StackOverflow](https://stackoverflow.com/questions/tagged/dart) can be used to search for your problem and see if it has been answered already. You can also ask and answer questions.

39
dart/forth/README.md Normal file
View File

@@ -0,0 +1,39 @@
# Forth
Welcome to Forth on Exercism's Dart Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
## Instructions
Implement an evaluator for a very simple subset of Forth.
[Forth][forth]
is a stack-based programming language.
Implement a very basic evaluator for a small subset of Forth.
Your evaluator has to support the following words:
- `+`, `-`, `*`, `/` (integer arithmetic)
- `DUP`, `DROP`, `SWAP`, `OVER` (stack manipulation)
Your evaluator also has to support defining new words using the customary syntax: `: word-name definition ;`.
To keep things simple the only data type you need to support is signed integers of at least 16 bits size.
You should use the following rules for the syntax: a number is a sequence of one or more (ASCII) digits, a word is a sequence of one or more letters, digits, symbols or punctuation that is not a number.
(Forth probably uses slightly different rules, but this is close enough.)
Words are case-insensitive.
[forth]: https://en.wikipedia.org/wiki/Forth_%28programming_language%29
## Source
### Created by
- @matthewmorgan
### Contributed to by
- @AlexeyBukin
- @kytrinyx

View File

@@ -0,0 +1,18 @@
analyzer:
strong-mode:
implicit-casts: false
implicit-dynamic: false
errors:
unused_element: error
unused_import: error
unused_local_variable: error
dead_code: error
linter:
rules:
# Error Rules
- avoid_relative_lib_imports
- avoid_types_as_parameter_names
- literal_only_boolean_expressions
- no_adjacent_strings_in_list
- valid_regexps

103
dart/forth/lib/forth.dart Normal file
View File

@@ -0,0 +1,103 @@
class Forth {
List<int> stack = <int>[];
Map customCmds = Map<String, String>.of({});
List<int> evaluate(String input) {
List<String> pts = input.toLowerCase().split(" ");
for(int i = 0; i < pts.length; i++) {
int? val = int.tryParse(pts[i]);
if(val == null) {
if(customCmds.containsKey(pts[i])) {
return evaluate(customCmds[pts[i]]);
} else {
switch(pts[i]) {
case ':': {
_addCommand(pts.sublist(1));
} break;
case '+': {
_add();
} break;
case '-': {
_sub();
} break;
case '*': {
_mult();
} break;
case '/': {
_div();
} break;
case 'dup': {
_dup();
} break;
case 'drop': {
_drop();
} break;
case 'swap': {
_swap();
} break;
case 'over': {
_over();
} break;
default: {
throw Exception('Unknown command');
} break;
}
}
} else {
_push(val);
}
}
return stack;
}
int _pop() {
if(stack.length > 0) {
int wrk = stack.last;
stack.removeLast();
return wrk;
} else {
throw Exception('Stack empty');
}
}
_push(int v) => stack.add(v);
_add() => _push(_pop() + _pop());
_sub() {
int v2 = _pop();
int v1 = _pop();
_push(v1 - v2);
}
_mult() => _push(_pop() * _pop());
_div() {
int v2 = _pop();
int v1 = _pop();
if(v2 == 0) {
throw Exception('Division by zero');
}
_push((v1 / v2).toInt());
}
_dup() {
int v1 = _pop();
_push(v1);
_push(v1);
}
_drop() => _pop();
_swap() {
int v2 = _pop();
int v1 = _pop();
_push(v2);
_push(v1);
}
_over() {
int v2 = _pop();
int v1 = _pop();
_push(v1);
_push(v2);
_push(v1);
}
_addCommand(List<String> pts) {
String keyword = pts[0];
customCmds[keyword] = pts.sublist(1, pts.length-2).join(" ");
}
}

365
dart/forth/pubspec.lock Normal file
View File

@@ -0,0 +1,365 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: a36ec4843dc30ea6bf652bf25e3448db6c5e8bcf4aa55f063a5d1dad216d8214
url: "https://pub.dev"
source: hosted
version: "58.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: cc4242565347e98424ce9945c819c192ec0838cb9d1f6aa4a97cc96becbc5b27
url: "https://pub.dev"
source: hosted
version: "5.10.0"
args:
dependency: transitive
description:
name: args
sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440"
url: "https://pub.dev"
source: hosted
version: "2.4.0"
async:
dependency: transitive
description:
name: async
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
url: "https://pub.dev"
source: hosted
version: "2.11.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
collection:
dependency: transitive
description:
name: collection
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
url: "https://pub.dev"
source: hosted
version: "1.17.1"
convert:
dependency: transitive
description:
name: convert
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
coverage:
dependency: transitive
description:
name: coverage
sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097"
url: "https://pub.dev"
source: hosted
version: "1.6.3"
crypto:
dependency: transitive
description:
name: crypto
sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67
url: "https://pub.dev"
source: hosted
version: "3.0.2"
file:
dependency: transitive
description:
name: file
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
url: "https://pub.dev"
source: hosted
version: "6.1.4"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
url: "https://pub.dev"
source: hosted
version: "3.2.0"
glob:
dependency: transitive
description:
name: glob
sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
url: "https://pub.dev"
source: hosted
version: "3.2.1"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
url: "https://pub.dev"
source: hosted
version: "4.0.2"
io:
dependency: transitive
description:
name: io
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
logging:
dependency: transitive
description:
name: logging
sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
matcher:
dependency: transitive
description:
name: matcher
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
url: "https://pub.dev"
source: hosted
version: "0.12.15"
meta:
dependency: transitive
description:
name: meta
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
mime:
dependency: transitive
description:
name: mime
sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
url: "https://pub.dev"
source: hosted
version: "1.0.4"
node_preamble:
dependency: transitive
description:
name: node_preamble
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
package_config:
dependency: transitive
description:
name: package_config
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
path:
dependency: transitive
description:
name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
url: "https://pub.dev"
source: hosted
version: "1.8.3"
pool:
dependency: transitive
description:
name: pool
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
url: "https://pub.dev"
source: hosted
version: "1.5.1"
pub_semver:
dependency: transitive
description:
name: pub_semver
sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17"
url: "https://pub.dev"
source: hosted
version: "2.1.3"
shelf:
dependency: transitive
description:
name: shelf
sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c
url: "https://pub.dev"
source: hosted
version: "1.4.0"
shelf_packages_handler:
dependency: transitive
description:
name: shelf_packages_handler
sha256: aef74dc9195746a384843102142ab65b6a4735bb3beea791e63527b88cc83306
url: "https://pub.dev"
source: hosted
version: "3.0.1"
shelf_static:
dependency: transitive
description:
name: shelf_static
sha256: e792b76b96a36d4a41b819da593aff4bdd413576b3ba6150df5d8d9996d2e74c
url: "https://pub.dev"
source: hosted
version: "1.1.1"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8
url: "https://pub.dev"
source: hosted
version: "1.0.3"
source_map_stack_trace:
dependency: transitive
description:
name: source_map_stack_trace
sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
source_maps:
dependency: transitive
description:
name: source_maps
sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
url: "https://pub.dev"
source: hosted
version: "0.10.12"
source_span:
dependency: transitive
description:
name: source_span
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev"
source: hosted
version: "1.10.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
url: "https://pub.dev"
source: hosted
version: "1.11.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
url: "https://pub.dev"
source: hosted
version: "1.2.1"
test:
dependency: "direct dev"
description:
name: test
sha256: "3dac9aecf2c3991d09b9cdde4f98ded7b30804a88a0d7e4e7e1678e78d6b97f4"
url: "https://pub.dev"
source: hosted
version: "1.24.1"
test_api:
dependency: transitive
description:
name: test_api
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
url: "https://pub.dev"
source: hosted
version: "0.5.1"
test_core:
dependency: transitive
description:
name: test_core
sha256: "5138dbffb77b2289ecb12b81c11ba46036590b72a64a7a90d6ffb880f1a29e93"
url: "https://pub.dev"
source: hosted
version: "0.5.1"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5"
url: "https://pub.dev"
source: hosted
version: "1.3.1"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: f6deed8ed625c52864792459709183da231ebf66ff0cf09e69b573227c377efe
url: "https://pub.dev"
source: hosted
version: "11.3.0"
watcher:
dependency: transitive
description:
name: watcher
sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b
url: "https://pub.dev"
source: hosted
version: "2.3.0"
webkit_inspection_protocol:
dependency: transitive
description:
name: webkit_inspection_protocol
sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
yaml:
dependency: transitive
description:
name: yaml
sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
sdks:
dart: ">=2.19.0 <3.0.0"

5
dart/forth/pubspec.yaml Normal file
View File

@@ -0,0 +1,5 @@
name: 'forth'
environment:
sdk: '>=2.18.0 <3.0.0'
dev_dependencies:
test: '<2.0.0'

View File

@@ -0,0 +1,396 @@
import 'package:forth/forth.dart';
import 'package:test/test.dart';
final throwsEmptyStack = throwsA(isA<Exception>().having((e) => e.toString(), 'message', 'Exception: Stack empty'));
final throwsInvalidDefinition =
throwsA(isA<Exception>().having((e) => e.toString(), 'message', 'Exception: Invalid definition'));
void main() {
group('Forth: parsing and numbers - ', parsingAndNumbers);
group('Forth: addition - ', addition);
group('Forth: subtraction - ', subtraction);
group('Forth: multiplication - ', multiplication);
group('Forth: division - ', division);
group('Forth: combined arithmetic - ', combinedArithmetic);
group('Forth: dup - ', dup);
group('Forth: drop - ', drop);
group('Forth: swap - ', swap);
group('Forth: over - ', over);
group('Forth: user-defined words - ', userDefinedWords);
group('Forth: case-insensitivity - ', caseInsensitivity);
}
void parsingAndNumbers() {
test('numbers just get pushed onto the stack', () {
var forth = Forth();
forth.evaluate('1 2 3 4 5');
expect(forth.stack, equals(<int>[1, 2, 3, 4, 5]));
}, skip: false);
test('pushes negative numbers onto the stack', () {
var forth = Forth();
forth.evaluate('-1 -2 -3 -4 -5');
expect(forth.stack, equals(<int>[-1, -2, -3, -4, -5]));
}, skip: false);
}
void addition() {
test('can add two numbers', () {
var forth = Forth();
forth.evaluate('1 2 +');
expect(forth.stack, equals(<int>[3]));
}, skip: false);
test('errors if there is nothing on the stack', () {
var forth = Forth();
expect(
() => forth.evaluate('+'),
throwsEmptyStack,
);
}, skip: false);
test('errors if there is only one value on the stack', () {
var forth = Forth();
expect(
() => forth.evaluate('1 +'),
throwsEmptyStack,
);
}, skip: false);
}
void subtraction() {
test('can subtract two numbers', () {
var forth = Forth();
forth.evaluate('3 4 -');
expect(forth.stack, equals(<int>[-1]));
}, skip: false);
test('errors if there is nothing on the stack', () {
var forth = Forth();
expect(
() => forth.evaluate('-'),
throwsEmptyStack,
);
}, skip: false);
test('errors if there is only one value on the stack', () {
var forth = Forth();
expect(
() => forth.evaluate('1 -'),
throwsEmptyStack,
);
}, skip: false);
}
void multiplication() {
test('can multiply two numbers', () {
var forth = Forth();
forth.evaluate('2 4 *');
expect(forth.stack, equals(<int>[8]));
}, skip: false);
test('errors if there is nothing on the stack', () {
var forth = Forth();
expect(
() => forth.evaluate('*'),
throwsEmptyStack,
);
}, skip: false);
test('errors if there is only one value on the stack', () {
var forth = Forth();
expect(
() => forth.evaluate('1 *'),
throwsEmptyStack,
);
}, skip: false);
}
void division() {
test('can divide two numbers', () {
var forth = Forth();
forth.evaluate('12 3 /');
expect(forth.stack, equals(<int>[4]));
}, skip: false);
test('performs integer division', () {
var forth = Forth();
forth.evaluate('8 3 /');
expect(forth.stack, equals(<int>[2]));
}, skip: false);
test('errors if dividing by zero', () {
var forth = Forth();
expect(
() => forth.evaluate('4 0 /'),
throwsA(isA<Exception>().having((e) => e.toString(), 'message', 'Exception: Division by zero')),
);
}, skip: false);
test('errors if there is nothing on the stack', () {
var forth = Forth();
expect(
() => forth.evaluate('/'),
throwsEmptyStack,
);
}, skip: false);
test('errors if there is only one value on the stack', () {
var forth = Forth();
expect(
() => forth.evaluate('1 /'),
throwsEmptyStack,
);
}, skip: false);
}
void combinedArithmetic() {
test('addition and subtraction', () {
var forth = Forth();
forth.evaluate('1 2 + 4 -');
expect(forth.stack, equals(<int>[-1]));
}, skip: false);
test('multiplication and division', () {
var forth = Forth();
forth.evaluate('2 4 * 3 /');
expect(forth.stack, equals(<int>[2]));
}, skip: false);
}
void dup() {
test('copies a value on the stack', () {
var forth = Forth();
forth.evaluate('1 dup');
expect(forth.stack, equals(<int>[1, 1]));
}, skip: false);
test('copies the top value on the stack', () {
var forth = Forth();
forth.evaluate('1 2 dup');
expect(forth.stack, equals(<int>[1, 2, 2]));
}, skip: false);
test('errors if there is nothing on the stack', () {
var forth = Forth();
expect(
() => forth.evaluate('dup'),
throwsEmptyStack,
);
}, skip: false);
}
void drop() {
test('removes the top value on the stack if it is the only one', () {
var forth = Forth();
forth.evaluate('1 drop');
expect(forth.stack, equals(<int>[]));
}, skip: false);
test('removes the top value on the stack if it is not the only one', () {
var forth = Forth();
forth.evaluate('1 2 drop');
expect(forth.stack, equals(<int>[1]));
}, skip: false);
test('errors if there is nothing on the stack', () {
var forth = Forth();
expect(
() => forth.evaluate('drop'),
throwsEmptyStack,
);
}, skip: false);
}
void swap() {
test('swaps the top two values on the stack if they are the only ones', () {
var forth = Forth();
forth.evaluate('1 2 swap');
expect(forth.stack, equals(<int>[2, 1]));
}, skip: false);
test('swaps the top two values on the stack if they are not the only ones', () {
var forth = Forth();
forth.evaluate('1 2 3 swap');
expect(forth.stack, equals(<int>[1, 3, 2]));
}, skip: false);
test('errors if there is nothing on the stack', () {
var forth = Forth();
expect(
() => forth.evaluate('swap'),
throwsEmptyStack,
);
}, skip: false);
test('errors if there is only one value on the stack', () {
var forth = Forth();
expect(
() => forth.evaluate('1 swap'),
throwsEmptyStack,
);
}, skip: false);
}
void over() {
test('copies the second element if there are only two', () {
var forth = Forth();
forth.evaluate('1 2 over');
expect(forth.stack, equals(<int>[1, 2, 1]));
}, skip: false);
test('copies the second element if there are more than two', () {
var forth = Forth();
forth.evaluate('1 2 3 over');
expect(forth.stack, equals(<int>[1, 2, 3, 2]));
}, skip: false);
test('errors if there is nothing on the stack', () {
var forth = Forth();
expect(
() => forth.evaluate('over'),
throwsEmptyStack,
);
}, skip: false);
test('errors if there is only one value on the stack', () {
var forth = Forth();
expect(
() => forth.evaluate('1 over'),
throwsEmptyStack,
);
}, skip: false);
}
void userDefinedWords() {
test('can consist of built-in words', () {
var forth = Forth();
forth.evaluate(': dup-twice dup dup ;');
forth.evaluate('1 dup-twice');
expect(forth.stack, equals(<int>[1, 1, 1]));
}, skip: false);
test('execute in the right order', () {
var forth = Forth();
forth.evaluate(': countup 1 2 3 ;');
forth.evaluate('countup');
expect(forth.stack, equals(<int>[1, 2, 3]));
}, skip: true);
test('can override other user-defined words', () {
var forth = Forth();
forth.evaluate(': foo dup ;');
forth.evaluate(': foo dup dup ;');
forth.evaluate('1 foo');
expect(forth.stack, equals(<int>[1, 1, 1]));
}, skip: true);
test('can override built-in words', () {
var forth = Forth();
forth.evaluate(': swap dup ;');
forth.evaluate('1 swap');
expect(forth.stack, equals(<int>[1, 1]));
}, skip: true);
test('can override built-in operators', () {
var forth = Forth();
forth.evaluate(': + * ;');
forth.evaluate('3 4 +');
expect(forth.stack, equals(<int>[12]));
}, skip: true);
test('can use different words with the same name', () {
var forth = Forth();
forth.evaluate(': foo 5 ;');
forth.evaluate(': bar foo ;');
forth.evaluate(': foo 6 ;');
forth.evaluate('bar foo');
expect(forth.stack, equals(<int>[5, 6]));
}, skip: true);
test('can define word that uses word with the same name', () {
var forth = Forth();
forth.evaluate(': foo 10 ;');
forth.evaluate(': foo foo 1 + ;');
forth.evaluate('foo');
expect(forth.stack, equals(<int>[11]));
}, skip: true);
test('cannot redefine non-negative numbers', () {
var forth = Forth();
expect(
() => forth.evaluate(': 1 2 ;'),
throwsInvalidDefinition,
);
}, skip: true);
test('cannot redefine negative numbers', () {
var forth = Forth();
expect(
() => forth.evaluate(': -1 2 ;'),
throwsInvalidDefinition,
);
}, skip: true);
test('errors if executing a non-existent word', () {
var forth = Forth();
expect(
() => forth.evaluate('foo'),
throwsA(isA<Exception>().having((e) => e.toString(), 'message', 'Exception: Unknown command')),
);
}, skip: true);
test('only defines locally', () {
var first = Forth();
var second = Forth();
first.evaluate(': + - ;');
first.evaluate('1 1 +');
second.evaluate('1 1 +');
expect(
[first.stack, second.stack],
equals(<List<int>>[
<int>[0],
<int>[2]
]));
}, skip: true);
}
void caseInsensitivity() {
test('DUP is case-insensitive', () {
var forth = Forth();
forth.evaluate('1 DUP Dup dup');
expect(forth.stack, equals(<int>[1, 1, 1, 1]));
}, skip: true);
test('DROP is case-insensitive', () {
var forth = Forth();
forth.evaluate('1 2 3 4 DROP Drop drop');
expect(forth.stack, equals(<int>[1]));
}, skip: true);
test('SWAP is case-insensitive', () {
var forth = Forth();
forth.evaluate('1 2 SWAP 3 Swap 4 swap');
expect(forth.stack, equals(<int>[2, 3, 4, 1]));
}, skip: true);
test('OVER is case-insensitive', () {
var forth = Forth();
forth.evaluate('1 2 OVER Over over');
expect(forth.stack, equals(<int>[1, 2, 1, 2, 1]));
}, skip: true);
test('user-defined words are case-insensitive', () {
var forth = Forth();
forth.evaluate(': foo dup ;');
forth.evaluate('1 FOO Foo foo');
expect(forth.stack, equals(<int>[1, 1, 1, 1]));
}, skip: true);
test('definitions are case-insensitive', () {
var forth = Forth();
forth.evaluate(': SWAP DUP Dup dup ;');
forth.evaluate('1 swap');
expect(forth.stack, equals(<int>[1, 1, 1, 1]));
}, skip: true);
}