Skip to content

Commit 47649ec

Browse files
authored
Merge pull request #144 from chr1st0scli/ceiling-floor-primitives
Ceiling floor primitives
2 parents c6d6fbd + 00105d7 commit 47649ec

File tree

11 files changed

+111
-3
lines changed

11 files changed

+111
-3
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,17 @@ Semantic versioning is followed.
1616

1717
### Removed
1818

19+
## [1.1.0] - 2024-01-28
20+
21+
### Added
22+
- Ceiling and floor primitive procedures.
23+
24+
### Fixed
25+
26+
### Changed
27+
28+
### Removed
29+
1930
## [1.0.0] - 2023-07-20
2031

2132
Initial release.

RainLisp/Docs/primitives.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
- [add-years](primitives/add-years.md)
1919
- [car](primitives/car.md)
2020
- [cdr](primitives/cdr.md)
21+
- [ceiling](primitives/ceiling.md)
2122
- [cons](primitives/cons.md)
2223
- [datetime-to-string](primitives/datetime-to-string.md)
2324
- [day](primitives/day.md)
@@ -26,6 +27,7 @@
2627
- [display](primitives/display.md)
2728
- [error](primitives/error.md)
2829
- [eval](primitives/eval.md)
30+
- [floor](primitives/floor.md)
2931
- [hour](primitives/hour.md)
3032
- [hours-diff](primitives/hours-diff.md)
3133
- [index-of-string](primitives/index-of-string.md)

RainLisp/Docs/primitives/ceiling.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# ceiling
2+
```scheme
3+
(ceiling num)
4+
```
5+
Rounds a numeric value to the smallest integral that is greater than or equal to it.
6+
7+
> *num* is a numeric value to round.
8+
9+
## Examples
10+
```scheme
11+
(ceiling 231.23456)
12+
```
13+
-> *232*
14+
15+
```scheme
16+
(ceiling 231.56789)
17+
```
18+
-> *232*

RainLisp/Docs/primitives/floor.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# floor
2+
```scheme
3+
(floor num)
4+
```
5+
Rounds a numeric value to the largest integral that is less than or equal to it.
6+
7+
> *num* is a numeric value to round.
8+
9+
## Examples
10+
```scheme
11+
(floor 231.23456)
12+
```
13+
-> *231*
14+
15+
```scheme
16+
(floor 231.56789)
17+
```
18+
-> *231*

RainLisp/Docs/quick-start/numbers.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ The operations that relate to numbers are:
5252
- [=](../primitives/equal.md)
5353
- [>](../primitives/greater.md)
5454
- [>=](../primitives/greater-or-equal.md)
55+
- [ceiling](../primitives/ceiling.md)
56+
- [floor](../primitives/floor.md)
5557
- [number-to-string](../primitives/number-to-string.md)
5658
- [parse-number](../primitives/parse-number.md)
5759
- [round](../primitives/round.md)

RainLisp/Evaluation/PrimitiveOperation.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,26 @@ public static EvaluationResult ParseNumber(EvaluationResult[]? values)
731731
public static EvaluationResult Round(EvaluationResult[]? values)
732732
=> ApplyBinaryOperator(AsDouble, (val, decimals) => ValueOrThrowInvalid(() => new NumberDatum((double)Math.Round((decimal)val, (int)decimals, MidpointRounding.AwayFromZero))), values);
733733

734+
/// <summary>
735+
/// Rounds a numeric value to the smallest integral that is greater than or equal to it.
736+
/// </summary>
737+
/// <param name="values">A numeric value to round.</param>
738+
/// <returns>The integral numeric value that is greater than or equal to the specified one.</returns>
739+
/// <exception cref="WrongNumberOfArgumentsException">The given arguments are not one.</exception>
740+
/// <exception cref="WrongTypeOfArgumentException">The argument is not a numeric value.</exception>
741+
public static EvaluationResult Ceiling(EvaluationResult[]? values)
742+
=> ApplyUnaryOperator(AsDouble, val => new NumberDatum(Math.Ceiling(val)), values);
743+
744+
/// <summary>
745+
/// Rounds a numeric value to the largest integral that is less than or equal to it.
746+
/// </summary>
747+
/// <param name="values">A numeric value to round.</param>
748+
/// <returns>The integral numeric value that is less than or equal to the specified one.</returns>
749+
/// <exception cref="WrongNumberOfArgumentsException">The given arguments are not one.</exception>
750+
/// <exception cref="WrongTypeOfArgumentException">The argument is not a numeric value.</exception>
751+
public static EvaluationResult Floor(EvaluationResult[]? values)
752+
=> ApplyUnaryOperator(AsDouble, val => new NumberDatum(Math.Floor(val)), values);
753+
734754
/// <summary>
735755
/// Returns a result by evaluating a quote symbol or a non-empty list of quote symbols as user code.
736756
/// </summary>

RainLisp/Grammar/Primitives.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,16 @@ public static class Primitives
320320
/// </summary>
321321
public const string ROUND = "round";
322322

323+
/// <summary>
324+
/// Rounds a numeric value to the smallest integral that is greater than or equal to it.
325+
/// </summary>
326+
public const string CEILING = "ceiling";
327+
328+
/// <summary>
329+
/// Rounds a numeric value to the largest integral that is less than or equal to it.
330+
/// </summary>
331+
public const string FLOOR = "floor";
332+
323333
/// <summary>
324334
/// Returns a result by evaluating a quote symbol or a non-empty list of quote symbols as user code.
325335
/// </summary>

RainLisp/Interpreter.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,8 @@ void Install(string procedureName, Func<EvaluationResult[]?, EvaluationResult> i
336336
Install(NUMBER_TO_STRING, PrimitiveOperation.NumberToString);
337337
Install(PARSE_NUMBER, PrimitiveOperation.ParseNumber);
338338
Install(ROUND, PrimitiveOperation.Round);
339+
Install(CEILING, PrimitiveOperation.Ceiling);
340+
Install(FLOOR, PrimitiveOperation.Floor);
339341

340342
_mostRecentGlobalEnvironment.DefineIdentifier(EVAL, new PrimitiveProcedure(EVAL, values => PrimitiveOperation.Eval(values, EvalPrimitiveCallback)));
341343
_mostRecentGlobalEnvironment.DefineIdentifier(NIL, Nil.GetNil());

RainLisp/RainLisp.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<Nullable>enable</Nullable>
77
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
88
<Title>RainLisp a .NET LISP implementation</Title>
9-
<Version>1.0.0</Version>
9+
<Version>1.1.0</Version>
1010
<Description>RainLisp a .NET LISP implementation.</Description>
1111
<Copyright>2023</Copyright>
1212
<PackageProjectUrl>https://github.com/chr1st0scli/RainLisp</PackageProjectUrl>
@@ -18,7 +18,7 @@
1818
<Authors>Christos Giamouridis</Authors>
1919
<Company>Rainsoft</Company>
2020
<GenerateDocumentationFile>True</GenerateDocumentationFile>
21-
<PackageReleaseNotes>Initial release.</PackageReleaseNotes>
21+
<PackageReleaseNotes>Add ceiling and floor primitive procedures.</PackageReleaseNotes>
2222
</PropertyGroup>
2323

2424
<ItemGroup>

RainLispTests/EvaluatorErrorTests.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public void Evaluate_CallExpectingOneWithWrongNumberOfArguments_Throws(string ex
8585
{
8686
"not", "car", "cdr", "null?", "display", "debug", "trace", "error", "string-length", "to-lower", "to-upper",
8787
"year", "month", "day", "hour", "minute", "second", "millisecond", "utc?", "to-local", "to-utc", "parse-number",
88-
"eval", "pair?"
88+
"eval", "pair?", "ceiling", "floor"
8989
}, expression, expected, false, actual);
9090
}
9191

@@ -218,6 +218,21 @@ public void Evaluate_CallExpectingNumbersOrStringsWithWrongTypeOfArgument_Throws
218218
Evaluate_CallsWithWrongExpression_Throws(new[] { "+" }, expression, actual, expected);
219219
}
220220

221+
[Theory]
222+
[InlineData("({0} \"hi\")", typeof(StringDatum))]
223+
[InlineData("({0} false)", typeof(BoolDatum))]
224+
[InlineData("({0} true)", typeof(BoolDatum))]
225+
[InlineData("({0} nil)", typeof(Nil))]
226+
[InlineData("({0} (cons 1 2))", typeof(Pair))]
227+
[InlineData("({0} (lambda(x) x))", typeof(UserProcedure))]
228+
[InlineData("({0} -)", typeof(PrimitiveProcedure))]
229+
[InlineData("({0} (now))", typeof(DateTimeDatum))]
230+
[InlineData("({0} (newline))", typeof(Unspecified))]
231+
public void Evaluate_CallExpectingNumberWithWrongTypeOfArgument_Throws(string expression, Type actual)
232+
{
233+
Evaluate_CallsWithWrongExpression_Throws(new[] { "ceiling", "floor" }, expression, actual, typeof(NumberDatum));
234+
}
235+
221236
[Theory]
222237
[InlineData("({0} \"hi\" 1)", typeof(StringDatum))]
223238
[InlineData("({0} 1 \"hi\")", typeof(StringDatum))]

RainLispTests/EvaluatorTests.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@ public void Evaluate_StringLiteral_Correctly(string expression, string expectedR
104104
[InlineData("(round 2.4 0)", 2d)]
105105
[InlineData("(round 21.423 2)", 21.42d)]
106106
[InlineData("(round 21.425 2)", 21.43d)]
107+
[InlineData("(ceiling 2)", 2d)]
108+
[InlineData("(ceiling 2.5)", 3d)]
109+
[InlineData("(ceiling 2.4)", 3d)]
110+
[InlineData("(ceiling 21.423)", 22d)]
111+
[InlineData("(ceiling 21.825)", 22d)]
112+
[InlineData("(floor 2)", 2d)]
113+
[InlineData("(floor 2.5)", 2d)]
114+
[InlineData("(floor 2.4)", 2d)]
115+
[InlineData("(floor 21.423)", 21d)]
116+
[InlineData("(floor 21.825)", 21d)]
107117
public void Evaluate_NumericExpression_Correctly(string expression, double expectedResult)
108118
{
109119
// Arrange

0 commit comments

Comments
 (0)