Skip to content

Commit 3f38684

Browse files
committed
fix math fns logic
1 parent 5261617 commit 3f38684

3 files changed

Lines changed: 90 additions & 17 deletions

File tree

src/glisp.gleam

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import gleam/io
21
import repl
32

43
pub fn main() -> Nil {

src/repl.gleam

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import ast.{type Expr}
2-
import environment.{type Env}
1+
import ast
2+
import environment
33
import eval
44
import gleam/io
55
import gleam/result

src/stdlib.gleam

Lines changed: 88 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ pub fn standard_env() -> Env {
2020
|> environment.set("list", Builtin(make_list))
2121
|> environment.set("car", Builtin(car))
2222
|> environment.set("cdr", Builtin(cdr))
23+
// More functions
24+
|> environment.set("cons", Builtin(cons))
25+
|> environment.set("length", Builtin(length))
26+
|> environment.set("null?", Builtin(null))
27+
|> environment.set("not", Builtin(not))
2328
env
2429
}
2530

@@ -35,14 +40,27 @@ fn add(args: List(Expr)) -> Result(Expr, String) {
3540
}
3641

3742
fn subtract(args: List(Expr)) -> Result(Expr, String) {
38-
args
39-
|> list.try_map(fn(arg) {
40-
case arg {
41-
Number(n) -> Ok(n)
42-
_ -> Error("Expected number in subtraction")
43+
case args {
44+
[] -> Error("- requires at least one argument")
45+
[Number(first), ..rest] -> {
46+
rest
47+
|> list.try_map(fn(arg) {
48+
case arg {
49+
Number(n) -> Ok(n)
50+
_ -> Error("Expected number in subtraction")
51+
}
52+
})
53+
|> result.map(fn(nums) {
54+
case list.length(nums) {
55+
// Unary minus (negate)
56+
0 -> Number(0 - first)
57+
// Subtraction from first argument
58+
_ -> Number(list.fold(nums, first, fn(acc, n) { acc - n }))
59+
}
60+
})
4361
}
44-
})
45-
|> result.map(fn(nums) { Number(list.fold(nums, 0, fn(acc, n) { acc - n })) })
62+
_ -> Error("Expected number as first argument to -")
63+
}
4664
}
4765

4866
fn multiply(args: List(Expr)) -> Result(Expr, String) {
@@ -57,14 +75,31 @@ fn multiply(args: List(Expr)) -> Result(Expr, String) {
5775
}
5876

5977
fn divide(args: List(Expr)) -> Result(Expr, String) {
60-
args
61-
|> list.try_map(fn(arg) {
62-
case arg {
63-
Number(n) -> Ok(n)
64-
_ -> Error("Expected number in division")
78+
case args {
79+
[] -> Error("/ requires at least one argument")
80+
[Number(first), ..rest] -> {
81+
rest
82+
|> list.try_map(fn(arg) {
83+
case arg {
84+
Number(n) ->
85+
case n {
86+
0 -> Error("Division by zero")
87+
_ -> Ok(n)
88+
}
89+
_ -> Error("Expected number in division")
90+
}
91+
})
92+
|> result.map(fn(nums) {
93+
case list.length(nums) {
94+
// Unary division (reciprocal)
95+
0 -> Number(1 / first)
96+
// Division
97+
_ -> Number(list.fold(nums, first, fn(acc, n) { acc / n }))
98+
}
99+
})
65100
}
66-
})
67-
|> result.map(fn(nums) { Number(list.fold(nums, 0, fn(acc, n) { acc / n })) })
101+
_ -> Error("Expected number as first argument to /")
102+
}
68103
}
69104

70105
fn equals(args: List(Expr)) -> Result(Expr, String) {
@@ -131,3 +166,42 @@ fn cdr(args: List(Expr)) -> Result(Expr, String) {
131166
_ -> Error("cdr: expected exactly one argument")
132167
}
133168
}
169+
170+
fn cons(args: List(Expr)) -> Result(Expr, String) {
171+
case args {
172+
[head, List(tail)] -> {
173+
Ok(List([head, ..tail]))
174+
}
175+
[_, _] -> Error("cons: second argument must be a list")
176+
_ -> Error("cons: expected exactly two arguments")
177+
}
178+
}
179+
180+
fn length(args: List(Expr)) -> Result(Expr, String) {
181+
case args {
182+
[List(elements)] -> {
183+
Ok(Number(list.length(elements)))
184+
}
185+
[_] -> Error("length: argunment must be a list")
186+
_ -> Error("length: expected exactly one argument")
187+
}
188+
}
189+
190+
fn null(args: List(Expr)) -> Result(Expr, String) {
191+
case args {
192+
[List([])] -> Ok(Number(1))
193+
// True if empty
194+
[List(_)] -> Ok(Number(0))
195+
// False if has elements
196+
[_] -> Error("null?: argument must be a list")
197+
_ -> Error("null?: expected exactly one argument")
198+
}
199+
}
200+
201+
fn not(args: List(Expr)) -> Result(Expr, String) {
202+
case args {
203+
[Number(0)] -> Ok(Number(1))
204+
[_] -> Ok(Number(0))
205+
_ -> Error("not: expected exactly one argument")
206+
}
207+
}

0 commit comments

Comments
 (0)