Skip to content

Commit 8b74ede

Browse files
committed
Move number functions to own compile unit
1 parent c07f4a3 commit 8b74ede

File tree

7 files changed

+271
-28
lines changed

7 files changed

+271
-28
lines changed

Makefile.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ SOURCES = \
1111
context.cpp \
1212
constants.cpp \
1313
fn_utils.cpp \
14+
fn_numbers.cpp \
1415
functions.cpp \
1516
color_maps.cpp \
1617
environment.cpp \

src/fn_numbers.cpp

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
#include <cstdint>
2+
#include <cstdlib>
3+
#include <cmath>
4+
#include <cctype>
5+
#include <random>
6+
#include <sstream>
7+
#include <iomanip>
8+
#include <algorithm>
9+
10+
#include "ast.hpp"
11+
#include "sass.hpp"
12+
#include "units.hpp"
13+
#include "fn_utils.hpp"
14+
#include "fn_numbers.hpp"
15+
16+
#ifdef __MINGW32__
17+
#include "windows.h"
18+
#include "wincrypt.h"
19+
#endif
20+
21+
namespace Sass {
22+
23+
namespace Functions {
24+
25+
#ifdef __MINGW32__
26+
uint64_t GetSeed()
27+
{
28+
HCRYPTPROV hp = 0;
29+
BYTE rb[8];
30+
CryptAcquireContext(&hp, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
31+
CryptGenRandom(hp, sizeof(rb), rb);
32+
CryptReleaseContext(hp, 0);
33+
34+
uint64_t seed;
35+
memcpy(&seed, &rb[0], sizeof(seed));
36+
37+
return seed;
38+
}
39+
#else
40+
uint64_t GetSeed()
41+
{
42+
std::random_device rd;
43+
return rd();
44+
}
45+
#endif
46+
47+
// note: the performance of many implementations of
48+
// random_device degrades sharply once the entropy pool
49+
// is exhausted. For practical use, random_device is
50+
// generally only used to seed a PRNG such as mt19937.
51+
static std::mt19937 rand(static_cast<unsigned int>(GetSeed()));
52+
53+
///////////////////
54+
// NUMBER FUNCTIONS
55+
///////////////////
56+
57+
Signature percentage_sig = "percentage($number)";
58+
BUILT_IN(percentage)
59+
{
60+
Number_Obj n = ARGN("$number");
61+
if (!n->is_unitless()) error("argument $number of `" + std::string(sig) + "` must be unitless", pstate, traces);
62+
return SASS_MEMORY_NEW(Number, pstate, n->value() * 100, "%");
63+
}
64+
65+
Signature round_sig = "round($number)";
66+
BUILT_IN(round)
67+
{
68+
Number_Obj r = ARGN("$number");
69+
r->value(Sass::round(r->value(), ctx.c_options.precision));
70+
r->pstate(pstate);
71+
return r.detach();
72+
}
73+
74+
Signature ceil_sig = "ceil($number)";
75+
BUILT_IN(ceil)
76+
{
77+
Number_Obj r = ARGN("$number");
78+
r->value(std::ceil(r->value()));
79+
r->pstate(pstate);
80+
return r.detach();
81+
}
82+
83+
Signature floor_sig = "floor($number)";
84+
BUILT_IN(floor)
85+
{
86+
Number_Obj r = ARGN("$number");
87+
r->value(std::floor(r->value()));
88+
r->pstate(pstate);
89+
return r.detach();
90+
}
91+
92+
Signature abs_sig = "abs($number)";
93+
BUILT_IN(abs)
94+
{
95+
Number_Obj r = ARGN("$number");
96+
r->value(std::abs(r->value()));
97+
r->pstate(pstate);
98+
return r.detach();
99+
}
100+
101+
Signature min_sig = "min($numbers...)";
102+
BUILT_IN(min)
103+
{
104+
List_Ptr arglist = ARG("$numbers", List);
105+
Number_Obj least = NULL;
106+
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
107+
Expression_Obj val = arglist->value_at_index(i);
108+
Number_Obj xi = Cast<Number>(val);
109+
if (!xi) {
110+
error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `min'", pstate, traces);
111+
}
112+
if (least) {
113+
if (*xi < *least) least = xi;
114+
} else least = xi;
115+
}
116+
return least.detach();
117+
}
118+
119+
Signature max_sig = "max($numbers...)";
120+
BUILT_IN(max)
121+
{
122+
List_Ptr arglist = ARG("$numbers", List);
123+
Number_Obj greatest = NULL;
124+
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
125+
Expression_Obj val = arglist->value_at_index(i);
126+
Number_Obj xi = Cast<Number>(val);
127+
if (!xi) {
128+
error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `max'", pstate, traces);
129+
}
130+
if (greatest) {
131+
if (*greatest < *xi) greatest = xi;
132+
} else greatest = xi;
133+
}
134+
return greatest.detach();
135+
}
136+
137+
Signature random_sig = "random($limit:false)";
138+
BUILT_IN(random)
139+
{
140+
AST_Node_Obj arg = env["$limit"];
141+
Value_Ptr v = Cast<Value>(arg);
142+
Number_Ptr l = Cast<Number>(arg);
143+
Boolean_Ptr b = Cast<Boolean>(arg);
144+
if (l) {
145+
double lv = l->value();
146+
if (lv < 1) {
147+
std::stringstream err;
148+
err << "$limit " << lv << " must be greater than or equal to 1 for `random'";
149+
error(err.str(), pstate, traces);
150+
}
151+
bool eq_int = std::fabs(trunc(lv) - lv) < NUMBER_EPSILON;
152+
if (!eq_int) {
153+
std::stringstream err;
154+
err << "Expected $limit to be an integer but got " << lv << " for `random'";
155+
error(err.str(), pstate, traces);
156+
}
157+
std::uniform_real_distribution<> distributor(1, lv + 1);
158+
uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand));
159+
return SASS_MEMORY_NEW(Number, pstate, (double)distributed);
160+
}
161+
else if (b) {
162+
std::uniform_real_distribution<> distributor(0, 1);
163+
double distributed = static_cast<double>(distributor(rand));
164+
return SASS_MEMORY_NEW(Number, pstate, distributed);
165+
} else if (v) {
166+
traces.push_back(Backtrace(pstate));
167+
throw Exception::InvalidArgumentType(pstate, traces, "random", "$limit", "number", v);
168+
} else {
169+
traces.push_back(Backtrace(pstate));
170+
throw Exception::InvalidArgumentType(pstate, traces, "random", "$limit", "number");
171+
}
172+
}
173+
174+
Signature unique_id_sig = "unique-id()";
175+
BUILT_IN(unique_id)
176+
{
177+
std::stringstream ss;
178+
std::uniform_real_distribution<> distributor(0, 4294967296); // 16^8
179+
uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand));
180+
ss << "u" << std::setfill('0') << std::setw(8) << std::hex << distributed;
181+
return SASS_MEMORY_NEW(String_Quoted, pstate, ss.str());
182+
}
183+
184+
Signature unit_sig = "unit($number)";
185+
BUILT_IN(unit)
186+
{
187+
Number_Obj arg = ARGN("$number");
188+
std::string str(quote(arg->unit(), '"'));
189+
return SASS_MEMORY_NEW(String_Quoted, pstate, str);
190+
}
191+
192+
Signature unitless_sig = "unitless($number)";
193+
BUILT_IN(unitless)
194+
{
195+
Number_Obj arg = ARGN("$number");
196+
bool unitless = arg->is_unitless();
197+
return SASS_MEMORY_NEW(Boolean, pstate, unitless);
198+
}
199+
200+
Signature comparable_sig = "comparable($number-1, $number-2)";
201+
BUILT_IN(comparable)
202+
{
203+
Number_Obj n1 = ARGN("$number-1");
204+
Number_Obj n2 = ARGN("$number-2");
205+
if (n1->is_unitless() || n2->is_unitless()) {
206+
return SASS_MEMORY_NEW(Boolean, pstate, true);
207+
}
208+
// normalize into main units
209+
n1->normalize(); n2->normalize();
210+
Units &lhs_unit = *n1, &rhs_unit = *n2;
211+
bool is_comparable = (lhs_unit == rhs_unit);
212+
return SASS_MEMORY_NEW(Boolean, pstate, is_comparable);
213+
}
214+
215+
}
216+
217+
}

src/fn_numbers.hpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#ifndef SASS_FN_NUMBERS_H
2+
#define SASS_FN_NUMBERS_H
3+
4+
#include "fn_utils.hpp"
5+
6+
namespace Sass {
7+
8+
namespace Functions {
9+
10+
// return a number object (copied since we want to have reduced units)
11+
#define ARGN(argname) get_arg_n(argname, env, sig, pstate, traces) // Number copy
12+
13+
extern Signature percentage_sig;
14+
extern Signature round_sig;
15+
extern Signature ceil_sig;
16+
extern Signature floor_sig;
17+
extern Signature abs_sig;
18+
extern Signature min_sig;
19+
extern Signature max_sig;
20+
extern Signature inspect_sig;
21+
extern Signature random_sig;
22+
extern Signature unique_id_sig;
23+
extern Signature unit_sig;
24+
extern Signature unitless_sig;
25+
extern Signature comparable_sig;
26+
27+
BUILT_IN(percentage);
28+
BUILT_IN(round);
29+
BUILT_IN(ceil);
30+
BUILT_IN(floor);
31+
BUILT_IN(abs);
32+
BUILT_IN(min);
33+
BUILT_IN(max);
34+
BUILT_IN(inspect);
35+
BUILT_IN(random);
36+
BUILT_IN(unique_id);
37+
BUILT_IN(unit);
38+
BUILT_IN(unitless);
39+
BUILT_IN(comparable);
40+
41+
}
42+
43+
}
44+
45+
#endif

src/fn_utils.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ namespace Sass {
1313
#define ARG(argname, argtype) get_arg<argtype>(argname, env, sig, pstate, traces)
1414
#define ARGM(argname, argtype, ctx) get_arg_m(argname, env, sig, pstate, traces)
1515

16-
// return a number object (copied since we want to have reduced units)
17-
#define ARGN(argname) get_arg_n(argname, env, sig, pstate, traces) // Number copy
18-
1916
// special function for weird hsla percent (10px == 10% == 10 != 0.1)
2017
#define ARGVAL(argname) get_arg_val(argname, env, sig, pstate, traces) // double
2118

src/functions.hpp

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,6 @@ namespace Sass {
5555
extern Signature str_slice_sig;
5656
extern Signature to_upper_case_sig;
5757
extern Signature to_lower_case_sig;
58-
extern Signature percentage_sig;
59-
extern Signature round_sig;
60-
extern Signature ceil_sig;
61-
extern Signature floor_sig;
62-
extern Signature abs_sig;
63-
extern Signature min_sig;
64-
extern Signature max_sig;
65-
extern Signature inspect_sig;
66-
extern Signature random_sig;
6758
extern Signature length_sig;
6859
extern Signature nth_sig;
6960
extern Signature index_sig;
@@ -72,9 +63,6 @@ namespace Sass {
7263
extern Signature zip_sig;
7364
extern Signature list_separator_sig;
7465
extern Signature type_of_sig;
75-
extern Signature unit_sig;
76-
extern Signature unitless_sig;
77-
extern Signature comparable_sig;
7866
extern Signature variable_exists_sig;
7967
extern Signature global_variable_exists_sig;
8068
extern Signature function_exists_sig;
@@ -91,7 +79,6 @@ namespace Sass {
9179
extern Signature map_has_key_sig;
9280
extern Signature keywords_sig;
9381
extern Signature set_nth_sig;
94-
extern Signature unique_id_sig;
9582
extern Signature selector_nest_sig;
9683
extern Signature selector_append_sig;
9784
extern Signature selector_extend_sig;
@@ -139,15 +126,7 @@ namespace Sass {
139126
BUILT_IN(str_slice);
140127
BUILT_IN(to_upper_case);
141128
BUILT_IN(to_lower_case);
142-
BUILT_IN(percentage);
143-
BUILT_IN(round);
144-
BUILT_IN(ceil);
145-
BUILT_IN(floor);
146-
BUILT_IN(abs);
147-
BUILT_IN(min);
148-
BUILT_IN(max);
149129
BUILT_IN(inspect);
150-
BUILT_IN(random);
151130
BUILT_IN(length);
152131
BUILT_IN(nth);
153132
BUILT_IN(index);
@@ -156,9 +135,6 @@ namespace Sass {
156135
BUILT_IN(zip);
157136
BUILT_IN(list_separator);
158137
BUILT_IN(type_of);
159-
BUILT_IN(unit);
160-
BUILT_IN(unitless);
161-
BUILT_IN(comparable);
162138
BUILT_IN(variable_exists);
163139
BUILT_IN(global_variable_exists);
164140
BUILT_IN(function_exists);
@@ -175,7 +151,6 @@ namespace Sass {
175151
BUILT_IN(map_has_key);
176152
BUILT_IN(keywords);
177153
BUILT_IN(set_nth);
178-
BUILT_IN(unique_id);
179154
BUILT_IN(selector_nest);
180155
BUILT_IN(selector_append);
181156
BUILT_IN(selector_extend);

win/libsass.targets

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
<ClInclude Include="$(LIBSASS_HEADERS_DIR)\file.hpp" />
3535
<ClInclude Include="$(LIBSASS_HEADERS_DIR)\fn_utils.hpp" />
3636
<ClInclude Include="$(LIBSASS_HEADERS_DIR)\functions.hpp" />
37+
<ClInclude Include="$(LIBSASS_HEADERS_DIR)\fn_numbers.hpp" />
3738
<ClInclude Include="$(LIBSASS_HEADERS_DIR)\inspect.hpp" />
3839
<ClInclude Include="$(LIBSASS_HEADERS_DIR)\json.hpp" />
3940
<ClInclude Include="$(LIBSASS_HEADERS_DIR)\kwd_arg_macros.hpp" />
@@ -88,6 +89,7 @@
8889
<ClCompile Include="$(LIBSASS_SRC_DIR)\extend.cpp" />
8990
<ClCompile Include="$(LIBSASS_SRC_DIR)\file.cpp" />
9091
<ClCompile Include="$(LIBSASS_SRC_DIR)\fn_utils.cpp" />
92+
<ClCompile Include="$(LIBSASS_SRC_DIR)\fn_numbers.cpp" />
9193
<ClCompile Include="$(LIBSASS_SRC_DIR)\functions.cpp" />
9294
<ClCompile Include="$(LIBSASS_SRC_DIR)\inspect.cpp" />
9395
<ClCompile Include="$(LIBSASS_SRC_DIR)\json.cpp" />

win/libsass.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@
114114
<ClInclude Include="$(LIBSASS_HEADERS_DIR)\functions.hpp">
115115
<Filter>Headers</Filter>
116116
</ClInclude>
117+
<ClInclude Include="$(LIBSASS_HEADERS_DIR)\fn_numbers.hpp">
118+
<Filter>Headers</Filter>
119+
</ClInclude>
117120
<ClInclude Include="$(LIBSASS_HEADERS_DIR)\inspect.hpp">
118121
<Filter>Headers</Filter>
119122
</ClInclude>
@@ -275,6 +278,9 @@
275278
<ClCompile Include="$(LIBSASS_SRC_DIR)\fn_utils.cpp">
276279
<Filter>Sources</Filter>
277280
</ClCompile>
281+
<ClCompile Include="$(LIBSASS_SRC_DIR)\fn_numbers.cpp">
282+
<Filter>Sources</Filter>
283+
</ClCompile>
278284
<ClCompile Include="$(LIBSASS_SRC_DIR)\functions.cpp">
279285
<Filter>Sources</Filter>
280286
</ClCompile>

0 commit comments

Comments
 (0)