Skip to content

Commit

Permalink
Finish all awk examples, add multiplication and division
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchpaulus committed Dec 9, 2024
1 parent ddbd490 commit 86d0d25
Show file tree
Hide file tree
Showing 17 changed files with 131 additions and 174 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ jobs:

- name: Test mshell-go
run: cd tests && ./test.sh

- name: Run awk example tests
run: cd examples/awk && ./test.sh
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,11 @@ wt ((toFloat) map sum str wl) each
# 19. Add up all fields in all lines and print the sum
# { for (i = 1; i <= NF; i = i + 1) sum = sum + $i }
# END { print sum }
wt ((toFloat) map sum) sum wl
wt ((toFloat) map sum) sum str wl
# 20. Print every line after replacing each field by its absolute value
# { for (i = 1; i <= NF; i = i + 1) $i = ($i < 0) ? -$i : $i; print }
wt ((toFloat abs) map wjoin wl) each
wt ((toFloat abs str) map wjoin wl) each
```
Expand All @@ -139,10 +139,11 @@ wt ((toFloat abs) map wjoin wl) each
| Objective | `sh` | `mshell` |
|-----------|-----|----------|
| Print the number of files in the current directory | `ls \| wc -l` | `* glob len wl` |
| Print the number of files in the current directory | `ls \| wc -l` | `"*" glob len wl` |
| `find`/`xargs` | `find . -t x -name '*.sh' -print0 \| xargs -0 mycommand` | `[mycommand [find . -t x -name "*.sh"]]o;` |
# TODO
- Floating point numbers
- Type checking
- Improved error messages
- Dictionaries
23 changes: 0 additions & 23 deletions examples/1.msh

This file was deleted.

38 changes: 0 additions & 38 deletions examples/1.sh

This file was deleted.

101 changes: 0 additions & 101 deletions examples/awk.msh

This file was deleted.

2 changes: 2 additions & 0 deletions examples/awk/19.awk
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{ for (i = 1; i <= NF; i = i + 1) sum = sum + $i }
END { print sum }
3 changes: 3 additions & 0 deletions examples/awk/19.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
1 2 3
4 5 6
7 8 9
1 change: 1 addition & 0 deletions examples/awk/19.msh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
wt ((toFloat) map sum) map sum str wl
20 changes: 20 additions & 0 deletions examples/awk/2.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1 change: 1 addition & 0 deletions examples/awk/20.awk
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ for (i = 1; i <= NF; i = i + 1) $i = ($i < 0) ? -$i : $i; print }
3 changes: 3 additions & 0 deletions examples/awk/20.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
1 -2 3
-4 5 -6
7 -8 9
1 change: 1 addition & 0 deletions examples/awk/20.msh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
wt ((toFloat abs str) map wjoin wl) each
11 changes: 3 additions & 8 deletions examples/awk/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,7 @@ data_test() {
FAIL=0

emp_test 1

if diff <(seq 1 20 | awk -f '2.awk' ) <(seq 1 20 | mshell 2.msh); then
printf "2. pass\n"
else
printf "2. fail\n"
FAIL=1
fi

data_test 2
emp_test 3
emp_test 4
data_test 5
Expand All @@ -45,5 +38,7 @@ emp_test 15
emp_test 16
emp_test 17
data_test 18
data_test 19
data_test 20

exit "$FAIL"
5 changes: 5 additions & 0 deletions lib/std.msh
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,8 @@ def reverse
) loop
nip # Drop original list
end

# abs (int|float -- int|float)
def abs
[(dup 0 <) (-1 *)] if
end
69 changes: 69 additions & 0 deletions mshell/Evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,75 @@ MainLoop:
}

stack.Push(&MShellBool{strings.Contains(totalStringText, substringText)})
} else if t.Lexeme == "/" {
obj1, err := stack.Pop()
if err != nil {
return FailWithMessage(fmt.Sprintf("%d:%d: Cannot do '/' operation on an empty stack.\n", t.Line, t.Column))
}

obj2, err := stack.Pop()
if err != nil {
return FailWithMessage(fmt.Sprintf("%d:%d: Cannot do '/' operation on a stack with only one item.\n", t.Line, t.Column))
}

if !obj1.IsNumeric() || !obj2.IsNumeric() {
return FailWithMessage(fmt.Sprintf("%d:%d: Cannot divide a %s and a %s.\n", t.Line, t.Column, obj2.TypeName(), obj1.TypeName()))
}

switch obj1.(type) {
case *MShellInt:
if obj1.(*MShellInt).Value == 0 {
return FailWithMessage(fmt.Sprintf("%d:%d: Cannot divide by zero.\n", t.Line, t.Column))
}
switch obj2.(type) {
case *MShellInt:
stack.Push(&MShellInt{obj2.(*MShellInt).Value / obj1.(*MShellInt).Value})
case *MShellFloat:
stack.Push(&MShellFloat{float64(obj2.(*MShellFloat).Value) / float64(obj1.(*MShellInt).Value)})
}
case *MShellFloat:
if obj1.(*MShellFloat).Value == 0 {
return FailWithMessage(fmt.Sprintf("%d:%d: Cannot divide by zero.\n", t.Line, t.Column))
}

switch obj2.(type) {
case *MShellInt:
stack.Push(&MShellFloat{float64(obj2.(*MShellInt).Value) / obj1.(*MShellFloat).Value})
case *MShellFloat:
stack.Push(&MShellFloat{obj2.(*MShellFloat).Value / obj1.(*MShellFloat).Value})
}
}
} else if t.Lexeme == "*" {
obj1, err := stack.Pop()
if err != nil {
return FailWithMessage(fmt.Sprintf("%d:%d: Cannot do '*' operation on an empty stack.\n", t.Line, t.Column))
}

obj2, err := stack.Pop()
if err != nil {
return FailWithMessage(fmt.Sprintf("%d:%d: Cannot do '*' operation on a stack with only one item.\n", t.Line, t.Column))
}

if !obj1.IsNumeric() || !obj2.IsNumeric() {
return FailWithMessage(fmt.Sprintf("%d:%d: Cannot multiply a %s and a %s. If you are looking for wildcard glob, you want `\"*\" glob`.\n", t.Line, t.Column, obj2.TypeName(), obj1.TypeName()))
}

switch obj1.(type) {
case *MShellInt:
switch obj2.(type) {
case *MShellInt:
stack.Push(&MShellInt{obj2.(*MShellInt).Value * obj1.(*MShellInt).Value})
case *MShellFloat:
stack.Push(&MShellFloat{obj2.(*MShellFloat).Value * float64(obj1.(*MShellInt).Value)})
}
case *MShellFloat:
switch obj2.(type) {
case *MShellInt:
stack.Push(&MShellFloat{float64(obj2.(*MShellInt).Value) * float64(obj1.(*MShellFloat).Value)})
case *MShellFloat:
stack.Push(&MShellFloat{obj2.(*MShellFloat).Value * obj1.(*MShellFloat).Value})
}
}
} else if t.Lexeme == "toFloat" {
obj, err := stack.Pop()
if err != nil {
Expand Down
8 changes: 8 additions & 0 deletions tests/arithmetic.msh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
2 3 * str wl
1.5 2.5 * str wl
5 2 / str wl
5.0 2.0 / str wl
5 2.0 / str wl
5.0 2 / str wl

-3 abs str wl
7 changes: 7 additions & 0 deletions tests/arithmetic.msh.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
6
3.75
2
2.5
2.5
2.5
3

0 comments on commit 86d0d25

Please sign in to comment.