Skip to content

Commit 402e6a0

Browse files
Add forth exercise
1 parent b5d5b5a commit 402e6a0

File tree

8 files changed

+377
-0
lines changed

8 files changed

+377
-0
lines changed

config.json

+8
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,14 @@
538538
"prerequisites": [],
539539
"difficulty": 5
540540
},
541+
{
542+
"slug": "forth",
543+
"name": "Forth",
544+
"uuid": "eab77e91-52bf-497b-88a5-0404e11a64e4",
545+
"practices": [],
546+
"prerequisites": [],
547+
"difficulty": 5
548+
},
541549
{
542550
"slug": "strain",
543551
"name": "Strain",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Instructions append
2+
3+
```exercism/note
4+
As Uiua does _not_ support putting functions on the stack, you won't be implementing user-defined words.
5+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Instructions
2+
3+
Implement an evaluator for a very simple subset of Forth.
4+
5+
[Forth][forth]
6+
is a stack-based programming language.
7+
Implement a very basic evaluator for a small subset of Forth.
8+
9+
Your evaluator has to support the following words:
10+
11+
- `+`, `-`, `*`, `/` (integer arithmetic)
12+
- `DUP`, `DROP`, `SWAP`, `OVER` (stack manipulation)
13+
14+
Your evaluator also has to support defining new words using the customary syntax: `: word-name definition ;`.
15+
16+
To keep things simple the only data type you need to support is signed integers of at least 16 bits size.
17+
18+
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.
19+
(Forth probably uses slightly different rules, but this is close enough.)
20+
21+
Words are case-insensitive.
22+
23+
[forth]: https://en.wikipedia.org/wiki/Forth_%28programming_language%29
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"authors": [
3+
"erikschierboom"
4+
],
5+
"files": {
6+
"solution": [
7+
"forth.ua"
8+
],
9+
"test": [
10+
"tests.ua"
11+
],
12+
"example": [
13+
".meta/example.ua"
14+
]
15+
},
16+
"blurb": "Implement an evaluator for a very simple subset of Forth."
17+
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Words ← {"+" "-" "*" "/" "dup" "swap" "over" "drop"}
2+
Parse ← ⊜□≠@\s.
3+
Number ← ⊂◇⋕
4+
UnaryOp! ← |2 ⨬(
5+
⍤"empty stack"
6+
| ⍜(↙1|^0)
7+
) ↧1⧻.
8+
BinaryOp! ← |2 ⨬(
9+
⍤"empty stack"
10+
| ⍤ "only one value on the stack"
11+
| ⍜(↙2|^0°⊟)
12+
) ↧2⧻.
13+
Op ← ⨬(
14+
BinaryOp!+◌
15+
| BinaryOp!-◌
16+
| BinaryOp!×◌
17+
| BinaryOp!(⨬(⌊÷|⍤"divide by zero") =0.)◌
18+
| UnaryOp!(⊂.)◌
19+
| BinaryOp!(⊂:)◌
20+
| BinaryOp!(⊂⊂,)◌
21+
| UnaryOp!([]◌)◌
22+
| Number
23+
) ⊸(⊗⊙Words)
24+
Evaluate ← ⇌ ∧Op ⊙[] Parse ¯⌵
+188
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[9962203f-f00a-4a85-b404-8a8ecbcec09d]
13+
description = "parsing and numbers -> numbers just get pushed onto the stack"
14+
15+
[fd7a8da2-6818-4203-a866-fed0714e7aa0]
16+
description = "parsing and numbers -> pushes negative numbers onto the stack"
17+
18+
[9e69588e-a3d8-41a3-a371-ea02206c1e6e]
19+
description = "addition -> can add two numbers"
20+
21+
[52336dd3-30da-4e5c-8523-bdf9a3427657]
22+
description = "addition -> errors if there is nothing on the stack"
23+
24+
[06efb9a4-817a-435e-b509-06166993c1b8]
25+
description = "addition -> errors if there is only one value on the stack"
26+
27+
[1e07a098-c5fa-4c66-97b2-3c81205dbc2f]
28+
description = "addition -> more than two values on the stack"
29+
30+
[09687c99-7bbc-44af-8526-e402f997ccbf]
31+
description = "subtraction -> can subtract two numbers"
32+
33+
[5d63eee2-1f7d-4538-b475-e27682ab8032]
34+
description = "subtraction -> errors if there is nothing on the stack"
35+
36+
[b3cee1b2-9159-418a-b00d-a1bb3765c23b]
37+
description = "subtraction -> errors if there is only one value on the stack"
38+
39+
[2c8cc5ed-da97-4cb1-8b98-fa7b526644f4]
40+
description = "subtraction -> more than two values on the stack"
41+
42+
[5df0ceb5-922e-401f-974d-8287427dbf21]
43+
description = "multiplication -> can multiply two numbers"
44+
45+
[9e004339-15ac-4063-8ec1-5720f4e75046]
46+
description = "multiplication -> errors if there is nothing on the stack"
47+
48+
[8ba4b432-9f94-41e0-8fae-3b3712bd51b3]
49+
description = "multiplication -> errors if there is only one value on the stack"
50+
51+
[5cd085b5-deb1-43cc-9c17-6b1c38bc9970]
52+
description = "multiplication -> more than two values on the stack"
53+
54+
[e74c2204-b057-4cff-9aa9-31c7c97a93f5]
55+
description = "division -> can divide two numbers"
56+
57+
[54f6711c-4b14-4bb0-98ad-d974a22c4620]
58+
description = "division -> performs integer division"
59+
60+
[a5df3219-29b4-4d2f-b427-81f82f42a3f1]
61+
description = "division -> errors if dividing by zero"
62+
63+
[1d5bb6b3-6749-4e02-8a79-b5d4d334cb8a]
64+
description = "division -> errors if there is nothing on the stack"
65+
66+
[d5547f43-c2ff-4d5c-9cb0-2a4f6684c20d]
67+
description = "division -> errors if there is only one value on the stack"
68+
69+
[f224f3e0-b6b6-4864-81de-9769ecefa03f]
70+
description = "division -> more than two values on the stack"
71+
72+
[ee28d729-6692-4a30-b9be-0d830c52a68c]
73+
description = "combined arithmetic -> addition and subtraction"
74+
75+
[40b197da-fa4b-4aca-a50b-f000d19422c1]
76+
description = "combined arithmetic -> multiplication and division"
77+
78+
[f749b540-53aa-458e-87ec-a70797eddbcb]
79+
description = "combined arithmetic -> multiplication and addition"
80+
81+
[c8e5a4c2-f9bf-4805-9a35-3c3314e4989a]
82+
description = "combined arithmetic -> addition and multiplication"
83+
84+
[c5758235-6eef-4bf6-ab62-c878e50b9957]
85+
description = "dup -> copies a value on the stack"
86+
87+
[f6889006-5a40-41e7-beb3-43b09e5a22f4]
88+
description = "dup -> copies the top value on the stack"
89+
90+
[40b7569c-8401-4bd4-a30d-9adf70d11bc4]
91+
description = "dup -> errors if there is nothing on the stack"
92+
93+
[1971da68-1df2-4569-927a-72bf5bb7263c]
94+
description = "drop -> removes the top value on the stack if it is the only one"
95+
96+
[8929d9f2-4a78-4e0f-90ad-be1a0f313fd9]
97+
description = "drop -> removes the top value on the stack if it is not the only one"
98+
99+
[6dd31873-6dd7-4cb8-9e90-7daa33ba045c]
100+
description = "drop -> errors if there is nothing on the stack"
101+
102+
[3ee68e62-f98a-4cce-9e6c-8aae6c65a4e3]
103+
description = "swap -> swaps the top two values on the stack if they are the only ones"
104+
105+
[8ce869d5-a503-44e4-ab55-1da36816ff1c]
106+
description = "swap -> swaps the top two values on the stack if they are not the only ones"
107+
108+
[74ba5b2a-b028-4759-9176-c5c0e7b2b154]
109+
description = "swap -> errors if there is nothing on the stack"
110+
111+
[dd52e154-5d0d-4a5c-9e5d-73eb36052bc8]
112+
description = "swap -> errors if there is only one value on the stack"
113+
114+
[a2654074-ba68-4f93-b014-6b12693a8b50]
115+
description = "over -> copies the second element if there are only two"
116+
117+
[c5b51097-741a-4da7-8736-5c93fa856339]
118+
description = "over -> copies the second element if there are more than two"
119+
120+
[6e1703a6-5963-4a03-abba-02e77e3181fd]
121+
description = "over -> errors if there is nothing on the stack"
122+
123+
[ee574dc4-ef71-46f6-8c6a-b4af3a10c45f]
124+
description = "over -> errors if there is only one value on the stack"
125+
126+
[ed45cbbf-4dbf-4901-825b-54b20dbee53b]
127+
description = "user-defined words -> can consist of built-in words"
128+
include = false
129+
130+
[2726ea44-73e4-436b-bc2b-5ff0c6aa014b]
131+
description = "user-defined words -> execute in the right order"
132+
include = false
133+
134+
[9e53c2d0-b8ef-4ad8-b2c9-a559b421eb33]
135+
description = "user-defined words -> can override other user-defined words"
136+
include = false
137+
138+
[669db3f3-5bd6-4be0-83d1-618cd6e4984b]
139+
description = "user-defined words -> can override built-in words"
140+
include = false
141+
142+
[588de2f0-c56e-4c68-be0b-0bb1e603c500]
143+
description = "user-defined words -> can override built-in operators"
144+
include = false
145+
146+
[ac12aaaf-26c6-4a10-8b3c-1c958fa2914c]
147+
description = "user-defined words -> can use different words with the same name"
148+
include = false
149+
150+
[53f82ef0-2750-4ccb-ac04-5d8c1aefabb1]
151+
description = "user-defined words -> can define word that uses word with the same name"
152+
include = false
153+
154+
[35958cee-a976-4a0f-9378-f678518fa322]
155+
description = "user-defined words -> cannot redefine non-negative numbers"
156+
include = false
157+
158+
[df5b2815-3843-4f55-b16c-c3ed507292a7]
159+
description = "user-defined words -> cannot redefine negative numbers"
160+
include = false
161+
162+
[5180f261-89dd-491e-b230-62737e09806f]
163+
description = "user-defined words -> errors if executing a non-existent word"
164+
include = false
165+
166+
[3c8bfef3-edbb-49c1-9993-21d4030043cb]
167+
description = "user-defined words -> only defines locally"
168+
include = false
169+
170+
[7b83bb2e-b0e8-461f-ad3b-96ee2e111ed6]
171+
description = "case-insensitivity -> DUP is case-insensitive"
172+
173+
[339ed30b-f5b4-47ff-ab1c-67591a9cd336]
174+
description = "case-insensitivity -> DROP is case-insensitive"
175+
176+
[ee1af31e-1355-4b1b-bb95-f9d0b2961b87]
177+
description = "case-insensitivity -> SWAP is case-insensitive"
178+
179+
[acdc3a49-14c8-4cc2-945d-11edee6408fa]
180+
description = "case-insensitivity -> OVER is case-insensitive"
181+
182+
[5934454f-a24f-4efc-9fdd-5794e5f0c23c]
183+
description = "case-insensitivity -> user-defined words are case-insensitive"
184+
include = false
185+
186+
[037d4299-195f-4be7-a46d-f07ca6280a06]
187+
description = "case-insensitivity -> definitions are case-insensitive"
188+
include = false

exercises/practice/forth/forth.ua

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Evaluate Forth code
2+
# Stack ? Instructions
3+
Evaluate ← |1 ⊙(⍤"Please implement Evaluate" 0)

exercises/practice/forth/tests.ua

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
~ "forth.ua" ~ Evaluate
2+
3+
# Parsing and numbers - numbers just get pushed onto the stack
4+
⍤⤙≍ [1 2 3 4 5] Evaluate "1 2 3 4 5"
5+
6+
# Parsing and numbers - pushes negative numbers onto the stack
7+
⍤⤙≍ [¯1 ¯2 ¯3 ¯4 ¯5] Evaluate "-1 -2 -3 -4 -5"
8+
9+
# Addition - can add two numbers
10+
⍤⤙≍ [3] Evaluate "1 2 +"
11+
12+
# Addition - errors if there is nothing on the stack
13+
⍤⤙≍ "empty stack" ⍣(Evaluate "+")
14+
15+
# Addition - errors if there is only one value on the stack
16+
⍤⤙≍ "only one value on the stack" ⍣(Evaluate "1 +")
17+
18+
# Subtraction - can subtract two numbers
19+
⍤⤙≍ [¯1] Evaluate "3 4 -"
20+
21+
# Subtraction - errors if there is nothing on the stack
22+
⍤⤙≍ "empty stack" ⍣(Evaluate "-")
23+
24+
# Subtraction - errors if there is only one value on the stack
25+
⍤⤙≍ "only one value on the stack" ⍣(Evaluate "1 -")
26+
27+
# Multiplication - can multiply two numbers
28+
⍤⤙≍ [8] Evaluate "2 4 *"
29+
30+
# Multiplication - errors if there is nothing on the stack
31+
⍤⤙≍ "empty stack" ⍣(Evaluate "*")
32+
33+
# Multiplication - errors if there is only one value on the stack
34+
⍤⤙≍ "only one value on the stack" ⍣(Evaluate "1 *")
35+
36+
# Division - can divide two numbers
37+
⍤⤙≍ [4] Evaluate "12 3 /"
38+
39+
# Division - performs integer division
40+
⍤⤙≍ [2] Evaluate "8 3 /"
41+
42+
# Division - errors if dividing by zero
43+
⍤⤙≍ "divide by zero" ⍣(Evaluate "4 0 /")
44+
45+
# Division - errors if there is nothing on the stack
46+
⍤⤙≍ "empty stack" ⍣(Evaluate "/")
47+
48+
# Division - errors if there is only one value on the stack
49+
⍤⤙≍ "only one value on the stack" ⍣(Evaluate "1 /")
50+
51+
# Combined arithmetic - addition and subtraction
52+
⍤⤙≍ [¯1] Evaluate "1 2 + 4 -"
53+
54+
# Combined arithmetic - multiplication and division
55+
⍤⤙≍ [2] Evaluate "2 4 * 3 /"
56+
57+
# Dup - copies a value on the stack
58+
⍤⤙≍ [1 1] Evaluate "1 dup"
59+
60+
# Dup - copies the top value on the stack
61+
⍤⤙≍ [1 2 2] Evaluate "1 2 dup"
62+
63+
# Dup - errors if there is nothing on the stack
64+
⍤⤙≍ "empty stack" ⍣(Evaluate "dup")
65+
66+
# Drop - removes the top value on the stack if it is the only one
67+
⍤⤙≍ [] Evaluate "1 drop"
68+
69+
# Drop - removes the top value on the stack if it is not the only one
70+
⍤⤙≍ [1] Evaluate "1 2 drop"
71+
72+
# Drop - errors if there is nothing on the stack
73+
⍤⤙≍ "empty stack" ⍣(Evaluate "drop")
74+
75+
# Swap - swaps the top two values on the stack if they are the only ones
76+
⍤⤙≍ [2 1] Evaluate "1 2 swap"
77+
78+
# Swap - swaps the top two values on the stack if they are not the only ones
79+
⍤⤙≍ [1 3 2] Evaluate "1 2 3 swap"
80+
81+
# Swap - errors if there is nothing on the stack
82+
⍤⤙≍ "empty stack" ⍣(Evaluate "swap")
83+
84+
# Swap - errors if there is only one value on the stack
85+
⍤⤙≍ "only one value on the stack" ⍣(Evaluate "1 swap")
86+
87+
# Over - copies the second element if there are only two
88+
⍤⤙≍ [1 2 1] Evaluate "1 2 over"
89+
90+
# Over - copies the second element if there are more than two
91+
⍤⤙≍ [1 2 3 2] Evaluate "1 2 3 over"
92+
93+
# Over - errors if there is nothing on the stack
94+
⍤⤙≍ "empty stack" ⍣(Evaluate "over")
95+
96+
# Over - errors if there is only one value on the stack
97+
⍤⤙≍ "only one value on the stack" ⍣(Evaluate "1 over")
98+
99+
# Case-insensitivity - DUP is case-insensitive
100+
⍤⤙≍ [1 1 1 1] Evaluate "1 DUP Dup dup"
101+
102+
# Case-insensitivity - DROP is case-insensitive
103+
⍤⤙≍ [1] Evaluate "1 2 3 4 DROP Drop drop"
104+
105+
# Case-insensitivity - SWAP is case-insensitive
106+
⍤⤙≍ [2 3 4 1] Evaluate "1 2 SWAP 3 Swap 4 swap"
107+
108+
# Case-insensitivity - OVER is case-insensitive
109+
⍤⤙≍ [1 2 1 2 1] Evaluate "1 2 OVER Over over"

0 commit comments

Comments
 (0)