sassc 1.11.4 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +2 -2
  3. data/CODE_OF_CONDUCT.md +10 -0
  4. data/README.md +4 -1
  5. data/ext/libsass/.editorconfig +1 -1
  6. data/ext/libsass/.github/CONTRIBUTING.md +7 -7
  7. data/ext/libsass/.github/ISSUE_TEMPLATE.md +31 -6
  8. data/ext/libsass/.gitignore +3 -0
  9. data/ext/libsass/.travis.yml +37 -18
  10. data/ext/libsass/GNUmakefile.am +23 -37
  11. data/ext/libsass/Makefile +10 -6
  12. data/ext/libsass/Makefile.conf +3 -0
  13. data/ext/libsass/Readme.md +68 -63
  14. data/ext/libsass/appveyor.yml +7 -3
  15. data/ext/libsass/configure.ac +10 -14
  16. data/ext/libsass/docs/api-context-internal.md +29 -21
  17. data/ext/libsass/docs/api-context.md +26 -6
  18. data/ext/libsass/docs/api-doc.md +49 -16
  19. data/ext/libsass/docs/api-function-example.md +1 -1
  20. data/ext/libsass/docs/api-function.md +31 -7
  21. data/ext/libsass/docs/api-importer.md +19 -19
  22. data/ext/libsass/docs/api-value.md +4 -2
  23. data/ext/libsass/docs/build-on-windows.md +4 -4
  24. data/ext/libsass/docs/build-with-mingw.md +3 -3
  25. data/ext/libsass/docs/build.md +9 -9
  26. data/ext/libsass/docs/custom-functions-internal.md +10 -8
  27. data/ext/libsass/docs/implementations.md +20 -8
  28. data/ext/libsass/docs/unicode.md +16 -10
  29. data/ext/libsass/include/sass/base.h +0 -3
  30. data/ext/libsass/include/sass/context.h +20 -2
  31. data/ext/libsass/include/sass/functions.h +31 -0
  32. data/ext/libsass/include/sass/values.h +3 -1
  33. data/ext/libsass/include/sass/version.h +1 -1
  34. data/ext/libsass/include/sass/version.h.in +1 -1
  35. data/ext/libsass/include/sass2scss.h +1 -1
  36. data/ext/libsass/res/resource.rc +6 -6
  37. data/ext/libsass/script/ci-build-libsass +10 -5
  38. data/ext/libsass/script/ci-build-plugin +62 -0
  39. data/ext/libsass/script/ci-install-compiler +1 -1
  40. data/ext/libsass/script/ci-install-deps +4 -7
  41. data/ext/libsass/script/ci-report-coverage +13 -3
  42. data/ext/libsass/script/tap-driver +1 -1
  43. data/ext/libsass/script/tap-runner +1 -1
  44. data/ext/libsass/src/GNUmakefile.am +1 -1
  45. data/ext/libsass/src/ast.cpp +537 -762
  46. data/ext/libsass/src/ast.hpp +377 -419
  47. data/ext/libsass/src/ast_def_macros.hpp +26 -1
  48. data/ext/libsass/src/ast_fwd_decl.cpp +29 -0
  49. data/ext/libsass/src/ast_fwd_decl.hpp +94 -21
  50. data/ext/libsass/src/b64/encode.h +3 -1
  51. data/ext/libsass/src/backtrace.cpp +46 -0
  52. data/ext/libsass/src/backtrace.hpp +7 -54
  53. data/ext/libsass/src/bind.cpp +72 -50
  54. data/ext/libsass/src/bind.hpp +0 -1
  55. data/ext/libsass/src/cencode.c +6 -0
  56. data/ext/libsass/src/check_nesting.cpp +157 -135
  57. data/ext/libsass/src/check_nesting.hpp +11 -10
  58. data/ext/libsass/src/color_maps.cpp +10 -6
  59. data/ext/libsass/src/color_maps.hpp +6 -8
  60. data/ext/libsass/src/constants.cpp +4 -3
  61. data/ext/libsass/src/constants.hpp +4 -3
  62. data/ext/libsass/src/context.cpp +110 -47
  63. data/ext/libsass/src/context.hpp +11 -1
  64. data/ext/libsass/src/cssize.cpp +105 -94
  65. data/ext/libsass/src/cssize.hpp +4 -5
  66. data/ext/libsass/src/debugger.hpp +247 -244
  67. data/ext/libsass/src/emitter.cpp +30 -6
  68. data/ext/libsass/src/emitter.hpp +7 -0
  69. data/ext/libsass/src/environment.cpp +67 -16
  70. data/ext/libsass/src/environment.hpp +28 -7
  71. data/ext/libsass/src/error_handling.cpp +92 -64
  72. data/ext/libsass/src/error_handling.hpp +64 -43
  73. data/ext/libsass/src/eval.cpp +494 -544
  74. data/ext/libsass/src/eval.hpp +17 -23
  75. data/ext/libsass/src/expand.cpp +182 -154
  76. data/ext/libsass/src/expand.hpp +4 -5
  77. data/ext/libsass/src/extend.cpp +299 -291
  78. data/ext/libsass/src/extend.hpp +46 -11
  79. data/ext/libsass/src/file.cpp +103 -36
  80. data/ext/libsass/src/file.hpp +21 -4
  81. data/ext/libsass/src/functions.cpp +561 -312
  82. data/ext/libsass/src/functions.hpp +8 -5
  83. data/ext/libsass/src/inspect.cpp +108 -53
  84. data/ext/libsass/src/inspect.hpp +5 -2
  85. data/ext/libsass/src/lexer.cpp +15 -7
  86. data/ext/libsass/src/lexer.hpp +13 -4
  87. data/ext/libsass/src/listize.cpp +3 -2
  88. data/ext/libsass/src/listize.hpp +0 -1
  89. data/ext/libsass/src/memory/SharedPtr.cpp +16 -18
  90. data/ext/libsass/src/memory/SharedPtr.hpp +47 -43
  91. data/ext/libsass/src/node.cpp +34 -38
  92. data/ext/libsass/src/node.hpp +6 -8
  93. data/ext/libsass/src/operation.hpp +2 -2
  94. data/ext/libsass/src/operators.cpp +240 -0
  95. data/ext/libsass/src/operators.hpp +30 -0
  96. data/ext/libsass/src/output.cpp +22 -20
  97. data/ext/libsass/src/parser.cpp +719 -358
  98. data/ext/libsass/src/parser.hpp +57 -22
  99. data/ext/libsass/src/plugins.cpp +28 -10
  100. data/ext/libsass/src/position.cpp +21 -3
  101. data/ext/libsass/src/position.hpp +2 -1
  102. data/ext/libsass/src/prelexer.cpp +104 -19
  103. data/ext/libsass/src/prelexer.hpp +10 -3
  104. data/ext/libsass/src/remove_placeholders.cpp +9 -10
  105. data/ext/libsass/src/remove_placeholders.hpp +1 -5
  106. data/ext/libsass/src/sass.cpp +62 -4
  107. data/ext/libsass/src/sass.hpp +5 -2
  108. data/ext/libsass/src/sass_context.cpp +96 -58
  109. data/ext/libsass/src/sass_context.hpp +7 -5
  110. data/ext/libsass/src/sass_functions.cpp +63 -1
  111. data/ext/libsass/src/sass_functions.hpp +19 -1
  112. data/ext/libsass/src/sass_util.cpp +3 -3
  113. data/ext/libsass/src/sass_util.hpp +4 -4
  114. data/ext/libsass/src/sass_values.cpp +42 -39
  115. data/ext/libsass/src/sass_values.hpp +2 -1
  116. data/ext/libsass/src/source_map.cpp +16 -18
  117. data/ext/libsass/src/subset_map.cpp +6 -8
  118. data/ext/libsass/src/subset_map.hpp +6 -6
  119. data/ext/libsass/src/to_c.cpp +2 -2
  120. data/ext/libsass/src/to_value.cpp +8 -3
  121. data/ext/libsass/src/to_value.hpp +1 -0
  122. data/ext/libsass/src/units.cpp +349 -45
  123. data/ext/libsass/src/units.hpp +39 -22
  124. data/ext/libsass/src/utf8/checked.h +7 -0
  125. data/ext/libsass/src/utf8/unchecked.h +7 -0
  126. data/ext/libsass/src/utf8_string.cpp +1 -1
  127. data/ext/libsass/src/util.cpp +139 -45
  128. data/ext/libsass/src/util.hpp +4 -7
  129. data/ext/libsass/src/values.cpp +15 -23
  130. data/ext/libsass/win/libsass.sln +13 -2
  131. data/ext/libsass/win/libsass.sln.DotSettings +9 -0
  132. data/ext/libsass/win/libsass.targets +3 -0
  133. data/ext/libsass/win/libsass.vcxproj.filters +9 -0
  134. data/lib/sassc/version.rb +1 -1
  135. data/sassc.gemspec +1 -1
  136. data/test/native_test.rb +1 -1
  137. metadata +11 -4
@@ -5,35 +5,70 @@
5
5
  #include <set>
6
6
 
7
7
  #include "ast.hpp"
8
+ #include "node.hpp"
9
+ #include "eval.hpp"
8
10
  #include "operation.hpp"
9
11
  #include "subset_map.hpp"
12
+ #include "ast_fwd_decl.hpp"
10
13
 
11
14
  namespace Sass {
12
15
 
13
- class Context;
14
- class Node;
16
+ Node subweave(Node& one, Node& two);
15
17
 
16
18
  class Extend : public Operation_CRTP<void, Extend> {
17
19
 
18
- Context& ctx;
19
20
  Subset_Map& subset_map;
21
+ Eval* eval;
20
22
 
21
23
  void fallback_impl(AST_Node_Ptr n) { }
22
24
 
25
+ private:
26
+
27
+ std::unordered_map<
28
+ Selector_List_Obj, // key
29
+ Selector_List_Obj, // value
30
+ HashNodes, // hasher
31
+ CompareNodes // compare
32
+ > memoizeList;
33
+
34
+ std::unordered_map<
35
+ Complex_Selector_Obj, // key
36
+ Node, // value
37
+ HashNodes, // hasher
38
+ CompareNodes // compare
39
+ > memoizeComplex;
40
+
41
+ /* this turned out to be too much overhead
42
+ re-evaluate once we store an ast selector
43
+ std::unordered_map<
44
+ Compound_Selector_Obj, // key
45
+ Node, // value
46
+ HashNodes, // hasher
47
+ CompareNodes // compare
48
+ > memoizeCompound;
49
+ */
50
+
51
+ void extendObjectWithSelectorAndBlock(Ruleset_Ptr pObject);
52
+ Node extendComplexSelector(Complex_Selector_Ptr sel, CompoundSelectorSet& seen, bool isReplace, bool isOriginal);
53
+ Node extendCompoundSelector(Compound_Selector_Ptr sel, CompoundSelectorSet& seen, bool isReplace);
54
+ bool complexSelectorHasExtension(Complex_Selector_Ptr selector, CompoundSelectorSet& seen);
55
+ Node trim(Node& seqses, bool isReplace);
56
+ Node weave(Node& path);
57
+
23
58
  public:
24
- static Node subweave(Node& one, Node& two, Context& ctx);
25
- static Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, Context& ctx, Subset_Map& subset_map, bool isReplace, bool& extendedSomething, std::set<Compound_Selector>& seen);
26
- static Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, Context& ctx, Subset_Map& subset_map, bool isReplace, bool& extendedSomething);
27
- static Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, Context& ctx, Subset_Map& subset_map, bool isReplace = false) {
59
+ void setEval(Eval& eval);
60
+ Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, bool isReplace, bool& extendedSomething, CompoundSelectorSet& seen);
61
+ Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, bool isReplace = false) {
28
62
  bool extendedSomething = false;
29
- return extendSelectorList(pSelectorList, ctx, subset_map, isReplace, extendedSomething);
63
+ CompoundSelectorSet seen;
64
+ return extendSelectorList(pSelectorList, isReplace, extendedSomething, seen);
30
65
  }
31
- static Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, Context& ctx, Subset_Map& subset_map, std::set<Compound_Selector>& seen) {
66
+ Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, CompoundSelectorSet& seen) {
32
67
  bool isReplace = false;
33
68
  bool extendedSomething = false;
34
- return extendSelectorList(pSelectorList, ctx, subset_map, isReplace, extendedSomething, seen);
69
+ return extendSelectorList(pSelectorList, isReplace, extendedSomething, seen);
35
70
  }
36
- Extend(Context&, Subset_Map&);
71
+ Extend(Subset_Map&);
37
72
  ~Extend() { }
38
73
 
39
74
  void operator()(Block_Ptr);
@@ -1,3 +1,4 @@
1
+ #include "sass.hpp"
1
2
  #ifdef _WIN32
2
3
  # ifdef __MINGW32__
3
4
  # ifndef off64_t
@@ -9,7 +10,6 @@
9
10
  #else
10
11
  # include <unistd.h>
11
12
  #endif
12
- #include "sass.hpp"
13
13
  #include <iostream>
14
14
  #include <fstream>
15
15
  #include <cctype>
@@ -20,6 +20,7 @@
20
20
  #include "context.hpp"
21
21
  #include "prelexer.hpp"
22
22
  #include "utf8_string.hpp"
23
+ #include "sass_functions.hpp"
23
24
  #include "sass2scss.h"
24
25
 
25
26
  #ifdef _WIN32
@@ -48,15 +49,22 @@ namespace Sass {
48
49
 
49
50
  // return the current directory
50
51
  // always with forward slashes
52
+ // always with trailing slash
51
53
  std::string get_cwd()
52
54
  {
53
- const size_t wd_len = 1024;
55
+ const size_t wd_len = 4096;
54
56
  #ifndef _WIN32
55
57
  char wd[wd_len];
56
- std::string cwd = getcwd(wd, wd_len);
58
+ char* pwd = getcwd(wd, wd_len);
59
+ // we should check error for more detailed info (e.g. ENOENT)
60
+ // http://man7.org/linux/man-pages/man2/getcwd.2.html#ERRORS
61
+ if (pwd == NULL) throw Exception::OperationError("cwd gone missing");
62
+ std::string cwd = pwd;
57
63
  #else
58
64
  wchar_t wd[wd_len];
59
- std::string cwd = wstring_to_string(_wgetcwd(wd, wd_len));
65
+ wchar_t* pwd = _wgetcwd(wd, wd_len);
66
+ if (pwd == NULL) throw Exception::OperationError("cwd gone missing");
67
+ std::string cwd = wstring_to_string(pwd);
60
68
  //convert backslashes to forward slashes
61
69
  replace(cwd.begin(), cwd.end(), '\\', '/');
62
70
  #endif
@@ -68,8 +76,15 @@ namespace Sass {
68
76
  bool file_exists(const std::string& path)
69
77
  {
70
78
  #ifdef _WIN32
71
- std::wstring wpath = UTF_8::convert_to_utf16(path);
72
- DWORD dwAttrib = GetFileAttributesW(wpath.c_str());
79
+ wchar_t resolved[32768];
80
+ // windows unicode filepaths are encoded in utf16
81
+ std::string abspath(join_paths(get_cwd(), path));
82
+ std::wstring wpath(UTF_8::convert_to_utf16("\\\\?\\" + abspath));
83
+ std::replace(wpath.begin(), wpath.end(), '/', '\\');
84
+ DWORD rv = GetFullPathNameW(wpath.c_str(), 32767, resolved, NULL);
85
+ if (rv > 32767) throw Exception::OperationError("Path is too long");
86
+ if (rv == 0) throw Exception::OperationError("Path could not be resolved");
87
+ DWORD dwAttrib = GetFileAttributesW(resolved);
73
88
  return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
74
89
  (!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)));
75
90
  #else
@@ -99,7 +114,7 @@ namespace Sass {
99
114
  // helper function to find the last directory seperator
100
115
  inline size_t find_last_folder_separator(const std::string& path, size_t limit = std::string::npos)
101
116
  {
102
- size_t pos = std::string::npos;
117
+ size_t pos;
103
118
  size_t pos_p = path.find_last_of('/', limit);
104
119
  #ifdef _WIN32
105
120
  size_t pos_w = path.find_last_of('\\', limit);
@@ -150,7 +165,7 @@ namespace Sass {
150
165
  pos = 0; // remove all self references inside the path string
151
166
  while((pos = path.find("/./", pos)) != std::string::npos) path.erase(pos, 2);
152
167
 
153
- pos = 0; // remove all leading and trailing self references
168
+ // remove all leading and trailing self references
154
169
  while(path.length() > 1 && path.substr(0, 2) == "./") path.erase(0, 2);
155
170
  while((pos = path.length()) > 1 && path.substr(pos - 2) == "/.") path.erase(pos - 2);
156
171
 
@@ -191,6 +206,13 @@ namespace Sass {
191
206
  if (is_absolute_path(r)) return r;
192
207
  if (l[l.length()-1] != '/') l += '/';
193
208
 
209
+ // this does a logical cleanup of the right hand path
210
+ // Note that this does collapse x/../y sections into y.
211
+ // This is by design. If /foo on your system is a symlink
212
+ // to /bar/baz, then /foo/../cd is actually /bar/cd,
213
+ // not /cd as a naive ../ removal would give you.
214
+ // will only work on leading double dot dirs on rhs
215
+ // therefore it is safe if lhs is already resolved cwd
194
216
  while ((r.length() > 3) && ((r.substr(0, 3) == "../") || (r.substr(0, 3)) == "..\\")) {
195
217
  size_t L = l.length(), pos = find_last_folder_separator(l, L - 2);
196
218
  bool is_slash = pos + 2 == L && (l[pos+1] == '/' || l[pos+1] == '\\');
@@ -301,13 +323,9 @@ namespace Sass {
301
323
  // (2) underscore + given
302
324
  // (3) underscore + given + extension
303
325
  // (4) given + extension
304
- std::vector<Include> resolve_includes(const std::string& root, const std::string& file)
326
+ std::vector<Include> resolve_includes(const std::string& root, const std::string& file, const std::vector<std::string>& exts)
305
327
  {
306
328
  std::string filename = join_paths(root, file);
307
- // supported extensions
308
- const std::vector<std::string> exts = {
309
- ".scss", ".sass", ".css"
310
- };
311
329
  // split the filename
312
330
  std::string base(dir_name(file));
313
331
  std::string name(base_name(file));
@@ -324,20 +342,53 @@ namespace Sass {
324
342
  for(auto ext : exts) {
325
343
  rel_path = join_paths(base, "_" + name + ext);
326
344
  abs_path = join_paths(root, rel_path);
327
- if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
345
+ if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path, ext == ".css" });
328
346
  }
329
347
  // next test plain name with exts
330
348
  for(auto ext : exts) {
331
349
  rel_path = join_paths(base, name + ext);
332
350
  abs_path = join_paths(root, rel_path);
333
- if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
351
+ if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path, ext == ".css" });
334
352
  }
335
353
  // nothing found
336
354
  return includes;
337
355
  }
338
356
 
339
- // helper function to resolve a filename
357
+ std::vector<std::string> find_files(const std::string& file, const std::vector<std::string> paths)
358
+ {
359
+ std::vector<std::string> includes;
360
+ for (std::string path : paths) {
361
+ std::string abs_path(join_paths(path, file));
362
+ if (file_exists(abs_path)) includes.push_back(abs_path);
363
+ }
364
+ return includes;
365
+ }
366
+
367
+ std::vector<std::string> find_files(const std::string& file, struct Sass_Compiler* compiler)
368
+ {
369
+ // get the last import entry to get current base directory
370
+ // struct Sass_Options* options = sass_compiler_get_options(compiler);
371
+ Sass_Import_Entry import = sass_compiler_get_last_import(compiler);
372
+ const std::vector<std::string>& incs = compiler->cpp_ctx->include_paths;
373
+ // create the vector with paths to lookup
374
+ std::vector<std::string> paths(1 + incs.size());
375
+ paths.push_back(dir_name(import->abs_path));
376
+ paths.insert(paths.end(), incs.begin(), incs.end());
377
+ // dispatch to find files in paths
378
+ return find_files(file, paths);
379
+ }
380
+
381
+ // helper function to search one file in all include paths
382
+ // this is normally not used internally by libsass (C-API sugar)
340
383
  std::string find_file(const std::string& file, const std::vector<std::string> paths)
384
+ {
385
+ if (file.empty()) return file;
386
+ auto res = find_files(file, paths);
387
+ return res.empty() ? "" : res.front();
388
+ }
389
+
390
+ // helper function to resolve a filename
391
+ std::string find_include(const std::string& file, const std::vector<std::string> paths)
341
392
  {
342
393
  // search in every include path for a match
343
394
  for (size_t i = 0, S = paths.size(); i < S; ++i)
@@ -349,20 +400,6 @@ namespace Sass {
349
400
  return std::string("");
350
401
  }
351
402
 
352
- // inc paths can be directly passed from C code
353
- std::string find_file(const std::string& file, const char* paths[])
354
- {
355
- if (paths == 0) return std::string("");
356
- std::vector<std::string> includes(0);
357
- // includes.push_back(".");
358
- const char** it = paths;
359
- while (it && *it) {
360
- includes.push_back(*it);
361
- ++it;
362
- }
363
- return find_file(file, includes);
364
- }
365
-
366
403
  // try to load the given filename
367
404
  // returned memory must be freed
368
405
  // will auto convert .sass files
@@ -371,16 +408,24 @@ namespace Sass {
371
408
  #ifdef _WIN32
372
409
  BYTE* pBuffer;
373
410
  DWORD dwBytes;
411
+ wchar_t resolved[32768];
374
412
  // windows unicode filepaths are encoded in utf16
375
- std::wstring wpath = UTF_8::convert_to_utf16(path);
376
- HANDLE hFile = CreateFileW(wpath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
413
+ std::string abspath(join_paths(get_cwd(), path));
414
+ std::wstring wpath(UTF_8::convert_to_utf16("\\\\?\\" + abspath));
415
+ std::replace(wpath.begin(), wpath.end(), '/', '\\');
416
+ DWORD rv = GetFullPathNameW(wpath.c_str(), 32767, resolved, NULL);
417
+ if (rv > 32767) throw Exception::OperationError("Path is too long");
418
+ if (rv == 0) throw Exception::OperationError("Path could not be resolved");
419
+ HANDLE hFile = CreateFileW(resolved, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
377
420
  if (hFile == INVALID_HANDLE_VALUE) return 0;
378
421
  DWORD dwFileLength = GetFileSize(hFile, NULL);
379
422
  if (dwFileLength == INVALID_FILE_SIZE) return 0;
380
423
  // allocate an extra byte for the null char
381
- pBuffer = (BYTE*)malloc((dwFileLength+1)*sizeof(BYTE));
424
+ // and another one for edge-cases in lexer
425
+ pBuffer = (BYTE*)malloc((dwFileLength+2)*sizeof(BYTE));
382
426
  ReadFile(hFile, pBuffer, dwFileLength, &dwBytes, NULL);
383
- pBuffer[dwFileLength] = '\0';
427
+ pBuffer[dwFileLength+0] = '\0';
428
+ pBuffer[dwFileLength+1] = '\0';
384
429
  CloseHandle(hFile);
385
430
  // just convert from unsigned char*
386
431
  char* contents = (char*) pBuffer;
@@ -392,10 +437,12 @@ namespace Sass {
392
437
  if (file.is_open()) {
393
438
  size_t size = file.tellg();
394
439
  // allocate an extra byte for the null char
395
- contents = (char*) malloc((size+1)*sizeof(char));
440
+ // and another one for edge-cases in lexer
441
+ contents = (char*) malloc((size+2)*sizeof(char));
396
442
  file.seekg(0, std::ios::beg);
397
443
  file.read(contents, size);
398
- contents[size] = '\0';
444
+ contents[size+0] = '\0';
445
+ contents[size+1] = '\0';
399
446
  file.close();
400
447
  }
401
448
  #endif
@@ -414,5 +461,25 @@ namespace Sass {
414
461
  }
415
462
  }
416
463
 
464
+ // split a path string delimited by semicolons or colons (OS dependent)
465
+ std::vector<std::string> split_path_list(const char* str)
466
+ {
467
+ std::vector<std::string> paths;
468
+ if (str == NULL) return paths;
469
+ // find delimiter via prelexer (return zero at end)
470
+ const char* end = Prelexer::find_first<PATH_SEP>(str);
471
+ // search until null delimiter
472
+ while (end) {
473
+ // add path from current position to delimiter
474
+ paths.push_back(std::string(str, end - str));
475
+ str = end + 1; // skip delimiter
476
+ end = Prelexer::find_first<PATH_SEP>(str);
477
+ }
478
+ // add path from current position to end
479
+ paths.push_back(std::string(str));
480
+ // return back
481
+ return paths;
482
+ }
483
+
417
484
  }
418
485
  }
@@ -4,6 +4,7 @@
4
4
  #include <string>
5
5
  #include <vector>
6
6
 
7
+ #include "sass/context.h"
7
8
  #include "ast_fwd_decl.hpp"
8
9
 
9
10
  namespace Sass {
@@ -47,9 +48,16 @@ namespace Sass {
47
48
  std::string abs2rel(const std::string& path, const std::string& base = ".", const std::string& cwd = get_cwd());
48
49
 
49
50
  // helper function to resolve a filename
51
+ // searching without variations in all paths
52
+ std::string find_file(const std::string& file, struct Sass_Compiler* options);
50
53
  std::string find_file(const std::string& file, const std::vector<std::string> paths);
51
- // inc paths can be directly passed from C code
52
- std::string find_file(const std::string& file, const char** paths);
54
+
55
+ // helper function to resolve a include filename
56
+ // this has the original resolve logic for sass include
57
+ std::string find_include(const std::string& file, const std::vector<std::string> paths);
58
+
59
+ // split a path string delimited by semicolons or colons (OS dependent)
60
+ std::vector<std::string> split_path_list(const char* paths);
53
61
 
54
62
  // try to load the given filename
55
63
  // returned memory must be freed
@@ -81,9 +89,14 @@ namespace Sass {
81
89
  public:
82
90
  // resolved absolute path
83
91
  std::string abs_path;
92
+ // is a deprecated file type
93
+ bool deprecated;
84
94
  public:
95
+ Include(const Importer& imp, std::string abs_path, bool deprecated)
96
+ : Importer(imp), abs_path(abs_path), deprecated(deprecated)
97
+ { }
85
98
  Include(const Importer& imp, std::string abs_path)
86
- : Importer(imp), abs_path(abs_path)
99
+ : Importer(imp), abs_path(abs_path), deprecated(false)
87
100
  { }
88
101
  };
89
102
 
@@ -113,7 +126,11 @@ namespace Sass {
113
126
 
114
127
  namespace File {
115
128
 
116
- std::vector<Include> resolve_includes(const std::string& root, const std::string& file);
129
+ static std::vector<std::string> defaultExtensions = { ".scss", ".sass" };
130
+
131
+ std::vector<Include> resolve_includes(const std::string& root, const std::string& file,
132
+ const std::vector<std::string>& exts = defaultExtensions);
133
+
117
134
 
118
135
  }
119
136
 
@@ -10,6 +10,7 @@
10
10
  #include "eval.hpp"
11
11
  #include "util.hpp"
12
12
  #include "expand.hpp"
13
+ #include "operators.hpp"
13
14
  #include "utf8_string.hpp"
14
15
  #include "sass/base.h"
15
16
  #include "utf8.h"
@@ -30,9 +31,26 @@
30
31
  #include "wincrypt.h"
31
32
  #endif
32
33
 
33
- #define ARG(argname, argtype) get_arg<argtype>(argname, env, sig, pstate, backtrace)
34
- #define ARGR(argname, argtype, lo, hi) get_arg_r(argname, env, sig, pstate, lo, hi, backtrace)
35
- #define ARGM(argname, argtype, ctx) get_arg_m(argname, env, sig, pstate, backtrace, ctx)
34
+ #define ARG(argname, argtype) get_arg<argtype>(argname, env, sig, pstate, traces)
35
+ #define ARGM(argname, argtype, ctx) get_arg_m(argname, env, sig, pstate, traces, ctx)
36
+
37
+ // return a number object (copied since we want to have reduced units)
38
+ #define ARGN(argname) get_arg_n(argname, env, sig, pstate, traces) // Number copy
39
+
40
+ // special function for weird hsla percent (10px == 10% == 10 != 0.1)
41
+ #define ARGVAL(argname) get_arg_val(argname, env, sig, pstate, traces) // double
42
+
43
+ // macros for common ranges (u mean unsigned or upper, r for full range)
44
+ #define DARG_U_FACT(argname) get_arg_r(argname, env, sig, pstate, traces, - 0.0, 1.0) // double
45
+ #define DARG_R_FACT(argname) get_arg_r(argname, env, sig, pstate, traces, - 1.0, 1.0) // double
46
+ #define DARG_U_BYTE(argname) get_arg_r(argname, env, sig, pstate, traces, - 0.0, 255.0) // double
47
+ #define DARG_R_BYTE(argname) get_arg_r(argname, env, sig, pstate, traces, - 255.0, 255.0) // double
48
+ #define DARG_U_PRCT(argname) get_arg_r(argname, env, sig, pstate, traces, - 0.0, 100.0) // double
49
+ #define DARG_R_PRCT(argname) get_arg_r(argname, env, sig, pstate, traces, - 100.0, 100.0) // double
50
+
51
+ // macros for color related inputs (rbg and alpha/opacity values)
52
+ #define COLOR_NUM(argname) color_num(argname, env, sig, pstate, traces) // double
53
+ #define ALPHA_NUM(argname) alpha_num(argname, env, sig, pstate, traces) // double
36
54
 
37
55
  namespace Sass {
38
56
  using std::stringstream;
@@ -40,7 +58,7 @@ namespace Sass {
40
58
 
41
59
  Definition_Ptr make_native_function(Signature sig, Native_Function func, Context& ctx)
42
60
  {
43
- Parser sig_parser = Parser::from_c_str(sig, ctx, ParserState("[built-in function]"));
61
+ Parser sig_parser = Parser::from_c_str(sig, ctx, ctx.traces, ParserState("[built-in function]"));
44
62
  sig_parser.lex<Prelexer::identifier>();
45
63
  std::string name(Util::normalize_underscores(sig_parser.lexed));
46
64
  Parameters_Obj params = sig_parser.parse_parameters();
@@ -58,7 +76,7 @@ namespace Sass {
58
76
  using namespace Prelexer;
59
77
 
60
78
  const char* sig = sass_function_get_signature(c_func);
61
- Parser sig_parser = Parser::from_c_str(sig, ctx, ParserState("[c function]"));
79
+ Parser sig_parser = Parser::from_c_str(sig, ctx, ctx.traces, ParserState("[c function]"));
62
80
  // allow to overload generic callback plus @warn, @error and @debug with custom functions
63
81
  sig_parser.lex < alternatives < identifier, exactly <'*'>,
64
82
  exactly < Constants::warn_kwd >,
@@ -84,31 +102,31 @@ namespace Sass {
84
102
 
85
103
  namespace Functions {
86
104
 
87
- inline void handle_utf8_error (const ParserState& pstate, Backtrace* backtrace)
105
+ inline void handle_utf8_error (const ParserState& pstate, Backtraces traces)
88
106
  {
89
107
  try {
90
108
  throw;
91
109
  }
92
110
  catch (utf8::invalid_code_point) {
93
111
  std::string msg("utf8::invalid_code_point");
94
- error(msg, pstate, backtrace);
112
+ error(msg, pstate, traces);
95
113
  }
96
114
  catch (utf8::not_enough_room) {
97
115
  std::string msg("utf8::not_enough_room");
98
- error(msg, pstate, backtrace);
116
+ error(msg, pstate, traces);
99
117
  }
100
118
  catch (utf8::invalid_utf8) {
101
119
  std::string msg("utf8::invalid_utf8");
102
- error(msg, pstate, backtrace);
120
+ error(msg, pstate, traces);
103
121
  }
104
122
  catch (...) { throw; }
105
123
  }
106
124
 
107
125
  template <typename T>
108
- T* get_arg(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace)
126
+ T* get_arg(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
109
127
  {
110
128
  // Minimal error handling -- the expectation is that built-ins will be written correctly!
111
- T* val = dynamic_cast<T*>(&env[argname]);
129
+ T* val = Cast<T>(env[argname]);
112
130
  if (!val) {
113
131
  std::string msg("argument `");
114
132
  msg += argname;
@@ -116,74 +134,138 @@ namespace Sass {
116
134
  msg += sig;
117
135
  msg += "` must be a ";
118
136
  msg += T::type_name();
119
- error(msg, pstate, backtrace);
137
+ error(msg, pstate, traces);
120
138
  }
121
139
  return val;
122
140
  }
123
141
 
124
- Map_Ptr get_arg_m(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx)
142
+ Map_Ptr get_arg_m(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx)
125
143
  {
126
144
  // Minimal error handling -- the expectation is that built-ins will be written correctly!
127
- Map_Ptr val = SASS_MEMORY_CAST(Map, env[argname]);
145
+ Map_Ptr val = Cast<Map>(env[argname]);
128
146
  if (val) return val;
129
147
 
130
- List_Ptr lval = SASS_MEMORY_CAST(List, env[argname]);
148
+ List_Ptr lval = Cast<List>(env[argname]);
131
149
  if (lval && lval->length() == 0) return SASS_MEMORY_NEW(Map, pstate, 0);
132
150
 
133
151
  // fallback on get_arg for error handling
134
- val = get_arg<Map>(argname, env, sig, pstate, backtrace);
152
+ val = get_arg<Map>(argname, env, sig, pstate, traces);
135
153
  return val;
136
154
  }
137
155
 
138
- Number_Ptr get_arg_r(const std::string& argname, Env& env, Signature sig, ParserState pstate, double lo, double hi, Backtrace* backtrace)
156
+ double get_arg_r(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, double lo, double hi)
139
157
  {
140
158
  // Minimal error handling -- the expectation is that built-ins will be written correctly!
141
- Number_Ptr val = get_arg<Number>(argname, env, sig, pstate, backtrace);
142
- double v = val->value();
159
+ Number_Ptr val = get_arg<Number>(argname, env, sig, pstate, traces);
160
+ Number tmpnr(val);
161
+ tmpnr.reduce();
162
+ double v = tmpnr.value();
143
163
  if (!(lo <= v && v <= hi)) {
144
164
  std::stringstream msg;
145
165
  msg << "argument `" << argname << "` of `" << sig << "` must be between ";
146
166
  msg << lo << " and " << hi;
147
- error(msg.str(), pstate, backtrace);
167
+ error(msg.str(), pstate, traces);
148
168
  }
169
+ return v;
170
+ }
171
+
172
+ Number_Ptr get_arg_n(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
173
+ {
174
+ // Minimal error handling -- the expectation is that built-ins will be written correctly!
175
+ Number_Ptr val = get_arg<Number>(argname, env, sig, pstate, traces);
176
+ val = SASS_MEMORY_COPY(val);
177
+ val->reduce();
149
178
  return val;
150
179
  }
151
180
 
152
- #define ARGSEL(argname, seltype, contextualize) get_arg_sel<seltype>(argname, env, sig, pstate, backtrace, ctx)
181
+ double get_arg_v(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
182
+ {
183
+ // Minimal error handling -- the expectation is that built-ins will be written correctly!
184
+ Number_Ptr val = get_arg<Number>(argname, env, sig, pstate, traces);
185
+ Number tmpnr(val);
186
+ tmpnr.reduce();
187
+ /*
188
+ if (tmpnr.unit() == "%") {
189
+ tmpnr.value(tmpnr.value() / 100);
190
+ tmpnr.numerators.clear();
191
+ } else {
192
+ if (!tmpnr.is_unitless()) error("argument " + argname + " of `" + std::string(sig) + "` must be unitless", pstate);
193
+ }
194
+ */
195
+ return tmpnr.value();
196
+ }
197
+
198
+ double get_arg_val(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
199
+ {
200
+ // Minimal error handling -- the expectation is that built-ins will be written correctly!
201
+ Number_Ptr val = get_arg<Number>(argname, env, sig, pstate, traces);
202
+ Number tmpnr(val);
203
+ tmpnr.reduce();
204
+ return tmpnr.value();
205
+ }
206
+
207
+ double color_num(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
208
+ {
209
+ Number_Ptr val = get_arg<Number>(argname, env, sig, pstate, traces);
210
+ Number tmpnr(val);
211
+ tmpnr.reduce();
212
+ if (tmpnr.unit() == "%") {
213
+ return std::min(std::max(tmpnr.value() * 255 / 100.0, 0.0), 255.0);
214
+ } else {
215
+ return std::min(std::max(tmpnr.value(), 0.0), 255.0);
216
+ }
217
+ }
218
+
219
+
220
+ inline double alpha_num(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces) {
221
+ Number_Ptr val = get_arg<Number>(argname, env, sig, pstate, traces);
222
+ Number tmpnr(val);
223
+ tmpnr.reduce();
224
+ if (tmpnr.unit() == "%") {
225
+ return std::min(std::max(tmpnr.value(), 0.0), 100.0);
226
+ } else {
227
+ return std::min(std::max(tmpnr.value(), 0.0), 1.0);
228
+ }
229
+ }
230
+
231
+ #define ARGSEL(argname, seltype, contextualize) get_arg_sel<seltype>(argname, env, sig, pstate, traces, ctx)
153
232
 
154
233
  template <typename T>
155
- T get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx);
234
+ T get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx);
156
235
 
157
236
  template <>
158
- Selector_List_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx) {
237
+ Selector_List_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx) {
159
238
  Expression_Obj exp = ARG(argname, Expression);
160
239
  if (exp->concrete_type() == Expression::NULL_VAL) {
161
240
  std::stringstream msg;
162
241
  msg << argname << ": null is not a valid selector: it must be a string,\n";
163
242
  msg << "a list of strings, or a list of lists of strings for `" << function_name(sig) << "'";
164
- error(msg.str(), pstate);
243
+ error(msg.str(), pstate, traces);
165
244
  }
166
- if (String_Constant_Ptr str = SASS_MEMORY_CAST(String_Constant, exp)) {
245
+ if (String_Constant_Ptr str = Cast<String_Constant>(exp)) {
167
246
  str->quote_mark(0);
168
247
  }
169
- std::string exp_src = exp->to_string(ctx.c_options) + "{";
170
- return Parser::parse_selector(exp_src.c_str(), ctx);
248
+ std::string exp_src = exp->to_string(ctx.c_options);
249
+ return Parser::parse_selector(exp_src.c_str(), ctx, traces);
171
250
  }
172
251
 
173
252
  template <>
174
- Compound_Selector_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx) {
253
+ Compound_Selector_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx) {
175
254
  Expression_Obj exp = ARG(argname, Expression);
176
255
  if (exp->concrete_type() == Expression::NULL_VAL) {
177
256
  std::stringstream msg;
178
257
  msg << argname << ": null is not a string for `" << function_name(sig) << "'";
179
- error(msg.str(), pstate);
258
+ error(msg.str(), pstate, traces);
180
259
  }
181
- if (String_Constant_Ptr str = SASS_MEMORY_CAST(String_Constant, exp)) {
260
+ if (String_Constant_Ptr str = Cast<String_Constant>(exp)) {
182
261
  str->quote_mark(0);
183
262
  }
184
- std::string exp_src = exp->to_string(ctx.c_options) + "{";
185
- Selector_List_Obj sel_list = Parser::parse_selector(exp_src.c_str(), ctx);
186
- return (sel_list->length() > 0) ? &sel_list->first()->tail()->head() : 0;
263
+ std::string exp_src = exp->to_string(ctx.c_options);
264
+ Selector_List_Obj sel_list = Parser::parse_selector(exp_src.c_str(), ctx, traces);
265
+ if (sel_list->length() == 0) return NULL;
266
+ Complex_Selector_Obj first = sel_list->first();
267
+ if (!first->tail()) return first->head();
268
+ return first->tail()->head();
187
269
  }
188
270
 
189
271
  #ifdef __MINGW32__
@@ -219,56 +301,110 @@ namespace Sass {
219
301
  "global-variable-shadowing",
220
302
  "extend-selector-pseudoclass",
221
303
  "at-error",
222
- "units-level-3"
304
+ "units-level-3",
305
+ "custom-property"
223
306
  };
224
307
 
225
308
  ////////////////
226
309
  // RGB FUNCTIONS
227
310
  ////////////////
228
311
 
229
- inline double color_num(Number_Ptr n) {
230
- if (n->unit() == "%") {
231
- return std::min(std::max(n->value() * 255 / 100.0, 0.0), 255.0);
232
- } else {
233
- return std::min(std::max(n->value(), 0.0), 255.0);
234
- }
235
- }
236
-
237
- inline double alpha_num(Number_Ptr n) {
238
- if (n->unit() == "%") {
239
- return std::min(std::max(n->value(), 0.0), 100.0);
240
- } else {
241
- return std::min(std::max(n->value(), 0.0), 1.0);
312
+ inline bool special_number(String_Constant_Ptr s) {
313
+ if (s) {
314
+ std::string calc("calc(");
315
+ std::string var("var(");
316
+ std::string ss(s->value());
317
+ return std::equal(calc.begin(), calc.end(), ss.begin()) ||
318
+ std::equal(var.begin(), var.end(), ss.begin());
242
319
  }
320
+ return false;
243
321
  }
244
322
 
245
323
  Signature rgb_sig = "rgb($red, $green, $blue)";
246
324
  BUILT_IN(rgb)
247
325
  {
326
+ if (
327
+ special_number(Cast<String_Constant>(env["$red"])) ||
328
+ special_number(Cast<String_Constant>(env["$green"])) ||
329
+ special_number(Cast<String_Constant>(env["$blue"]))
330
+ ) {
331
+ return SASS_MEMORY_NEW(String_Constant, pstate, "rgb("
332
+ + env["$red"]->to_string()
333
+ + ", "
334
+ + env["$green"]->to_string()
335
+ + ", "
336
+ + env["$blue"]->to_string()
337
+ + ")"
338
+ );
339
+ }
340
+
248
341
  return SASS_MEMORY_NEW(Color,
249
342
  pstate,
250
- color_num(ARG("$red", Number)),
251
- color_num(ARG("$green", Number)),
252
- color_num(ARG("$blue", Number)));
343
+ COLOR_NUM("$red"),
344
+ COLOR_NUM("$green"),
345
+ COLOR_NUM("$blue"));
253
346
  }
254
347
 
255
348
  Signature rgba_4_sig = "rgba($red, $green, $blue, $alpha)";
256
349
  BUILT_IN(rgba_4)
257
350
  {
351
+ if (
352
+ special_number(Cast<String_Constant>(env["$red"])) ||
353
+ special_number(Cast<String_Constant>(env["$green"])) ||
354
+ special_number(Cast<String_Constant>(env["$blue"])) ||
355
+ special_number(Cast<String_Constant>(env["$alpha"]))
356
+ ) {
357
+ return SASS_MEMORY_NEW(String_Constant, pstate, "rgba("
358
+ + env["$red"]->to_string()
359
+ + ", "
360
+ + env["$green"]->to_string()
361
+ + ", "
362
+ + env["$blue"]->to_string()
363
+ + ", "
364
+ + env["$alpha"]->to_string()
365
+ + ")"
366
+ );
367
+ }
368
+
258
369
  return SASS_MEMORY_NEW(Color,
259
370
  pstate,
260
- color_num(ARG("$red", Number)),
261
- color_num(ARG("$green", Number)),
262
- color_num(ARG("$blue", Number)),
263
- alpha_num(ARG("$alpha", Number)));
371
+ COLOR_NUM("$red"),
372
+ COLOR_NUM("$green"),
373
+ COLOR_NUM("$blue"),
374
+ ALPHA_NUM("$alpha"));
264
375
  }
265
376
 
266
377
  Signature rgba_2_sig = "rgba($color, $alpha)";
267
378
  BUILT_IN(rgba_2)
268
379
  {
380
+ if (
381
+ special_number(Cast<String_Constant>(env["$color"]))
382
+ ) {
383
+ return SASS_MEMORY_NEW(String_Constant, pstate, "rgba("
384
+ + env["$color"]->to_string()
385
+ + ", "
386
+ + env["$alpha"]->to_string()
387
+ + ")"
388
+ );
389
+ }
390
+
269
391
  Color_Ptr c_arg = ARG("$color", Color);
392
+
393
+ if (
394
+ special_number(Cast<String_Constant>(env["$alpha"]))
395
+ ) {
396
+ std::stringstream strm;
397
+ strm << "rgba("
398
+ << (int)c_arg->r() << ", "
399
+ << (int)c_arg->g() << ", "
400
+ << (int)c_arg->b() << ", "
401
+ << env["$alpha"]->to_string()
402
+ << ")";
403
+ return SASS_MEMORY_NEW(String_Constant, pstate, strm.str());
404
+ }
405
+
270
406
  Color_Ptr new_c = SASS_MEMORY_COPY(c_arg);
271
- new_c->a(alpha_num(ARG("$alpha", Number)));
407
+ new_c->a(ALPHA_NUM("$alpha"));
272
408
  new_c->disp("");
273
409
  return new_c;
274
410
  }
@@ -285,14 +421,8 @@ namespace Sass {
285
421
  BUILT_IN(blue)
286
422
  { return SASS_MEMORY_NEW(Number, pstate, ARG("$color", Color)->b()); }
287
423
 
288
- Signature mix_sig = "mix($color-1, $color-2, $weight: 50%)";
289
- BUILT_IN(mix)
290
- {
291
- Color_Ptr color1 = ARG("$color-1", Color);
292
- Color_Ptr color2 = ARG("$color-2", Color);
293
- Number_Ptr weight = ARGR("$weight", Number, 0, 100);
294
-
295
- double p = weight->value()/100;
424
+ Color* colormix(Context& ctx, ParserState& pstate, Color* color1, Color* color2, double weight) {
425
+ double p = weight/100;
296
426
  double w = 2*p - 1;
297
427
  double a = color1->a() - color2->a();
298
428
 
@@ -307,6 +437,16 @@ namespace Sass {
307
437
  color1->a()*p + color2->a()*(1-p));
308
438
  }
309
439
 
440
+ Signature mix_sig = "mix($color-1, $color-2, $weight: 50%)";
441
+ BUILT_IN(mix)
442
+ {
443
+ Color_Obj color1 = ARG("$color-1", Color);
444
+ Color_Obj color2 = ARG("$color-2", Color);
445
+ double weight = DARG_U_PRCT("$weight");
446
+ return colormix(ctx, pstate, color1, color2, weight);
447
+
448
+ }
449
+
310
450
  ////////////////
311
451
  // HSL FUNCTIONS
312
452
  ////////////////
@@ -323,9 +463,11 @@ namespace Sass {
323
463
  double min = std::min(r, std::min(g, b));
324
464
  double delta = max - min;
325
465
 
326
- double h = 0, s = 0, l = (max + min) / 2.0;
466
+ double h = 0;
467
+ double s;
468
+ double l = (max + min) / 2.0;
327
469
 
328
- if (max == min) {
470
+ if (NEAR_EQUAL(max, min)) {
329
471
  h = s = 0; // achromatic
330
472
  }
331
473
  else {
@@ -390,9 +532,24 @@ namespace Sass {
390
532
  Signature hsl_sig = "hsl($hue, $saturation, $lightness)";
391
533
  BUILT_IN(hsl)
392
534
  {
393
- return hsla_impl(ARG("$hue", Number)->value(),
394
- ARG("$saturation", Number)->value(),
395
- ARG("$lightness", Number)->value(),
535
+ if (
536
+ special_number(Cast<String_Constant>(env["$hue"])) ||
537
+ special_number(Cast<String_Constant>(env["$saturation"])) ||
538
+ special_number(Cast<String_Constant>(env["$lightness"]))
539
+ ) {
540
+ return SASS_MEMORY_NEW(String_Constant, pstate, "hsl("
541
+ + env["$hue"]->to_string()
542
+ + ", "
543
+ + env["$saturation"]->to_string()
544
+ + ", "
545
+ + env["$lightness"]->to_string()
546
+ + ")"
547
+ );
548
+ }
549
+
550
+ return hsla_impl(ARGVAL("$hue"),
551
+ ARGVAL("$saturation"),
552
+ ARGVAL("$lightness"),
396
553
  1.0,
397
554
  ctx,
398
555
  pstate);
@@ -401,10 +558,28 @@ namespace Sass {
401
558
  Signature hsla_sig = "hsla($hue, $saturation, $lightness, $alpha)";
402
559
  BUILT_IN(hsla)
403
560
  {
404
- return hsla_impl(ARG("$hue", Number)->value(),
405
- ARG("$saturation", Number)->value(),
406
- ARG("$lightness", Number)->value(),
407
- ARG("$alpha", Number)->value(),
561
+ if (
562
+ special_number(Cast<String_Constant>(env["$hue"])) ||
563
+ special_number(Cast<String_Constant>(env["$saturation"])) ||
564
+ special_number(Cast<String_Constant>(env["$lightness"])) ||
565
+ special_number(Cast<String_Constant>(env["$alpha"]))
566
+ ) {
567
+ return SASS_MEMORY_NEW(String_Constant, pstate, "hsla("
568
+ + env["$hue"]->to_string()
569
+ + ", "
570
+ + env["$saturation"]->to_string()
571
+ + ", "
572
+ + env["$lightness"]->to_string()
573
+ + ", "
574
+ + env["$alpha"]->to_string()
575
+ + ")"
576
+ );
577
+ }
578
+
579
+ return hsla_impl(ARGVAL("$hue"),
580
+ ARGVAL("$saturation"),
581
+ ARGVAL("$lightness"),
582
+ ARGVAL("$alpha"),
408
583
  ctx,
409
584
  pstate);
410
585
  }
@@ -443,11 +618,11 @@ namespace Sass {
443
618
  BUILT_IN(adjust_hue)
444
619
  {
445
620
  Color_Ptr rgb_color = ARG("$color", Color);
446
- Number_Ptr degrees = ARG("$degrees", Number);
621
+ double degrees = ARGVAL("$degrees");
447
622
  HSL hsl_color = rgb_to_hsl(rgb_color->r(),
448
623
  rgb_color->g(),
449
624
  rgb_color->b());
450
- return hsla_impl(hsl_color.h + degrees->value(),
625
+ return hsla_impl(hsl_color.h + degrees,
451
626
  hsl_color.s,
452
627
  hsl_color.l,
453
628
  rgb_color->a(),
@@ -459,7 +634,7 @@ namespace Sass {
459
634
  BUILT_IN(lighten)
460
635
  {
461
636
  Color_Ptr rgb_color = ARG("$color", Color);
462
- Number_Ptr amount = ARGR("$amount", Number, 0, 100);
637
+ double amount = DARG_U_PRCT("$amount");
463
638
  HSL hsl_color = rgb_to_hsl(rgb_color->r(),
464
639
  rgb_color->g(),
465
640
  rgb_color->b());
@@ -471,7 +646,7 @@ namespace Sass {
471
646
 
472
647
  return hsla_impl(hsl_color.h,
473
648
  hsl_color.s,
474
- hslcolorL + amount->value(),
649
+ hslcolorL + amount,
475
650
  rgb_color->a(),
476
651
  ctx,
477
652
  pstate);
@@ -481,7 +656,7 @@ namespace Sass {
481
656
  BUILT_IN(darken)
482
657
  {
483
658
  Color_Ptr rgb_color = ARG("$color", Color);
484
- Number_Ptr amount = ARGR("$amount", Number, 0, 100);
659
+ double amount = DARG_U_PRCT("$amount");
485
660
  HSL hsl_color = rgb_to_hsl(rgb_color->r(),
486
661
  rgb_color->g(),
487
662
  rgb_color->b());
@@ -494,7 +669,7 @@ namespace Sass {
494
669
 
495
670
  return hsla_impl(hsl_color.h,
496
671
  hsl_color.s,
497
- hslcolorL - amount->value(),
672
+ hslcolorL - amount,
498
673
  rgb_color->a(),
499
674
  ctx,
500
675
  pstate);
@@ -504,18 +679,17 @@ namespace Sass {
504
679
  BUILT_IN(saturate)
505
680
  {
506
681
  // CSS3 filter function overload: pass literal through directly
507
- Number_Ptr amount = SASS_MEMORY_CAST(Number, env["$amount"]);
508
- if (!amount) {
682
+ if (!Cast<Number>(env["$amount"])) {
509
683
  return SASS_MEMORY_NEW(String_Quoted, pstate, "saturate(" + env["$color"]->to_string(ctx.c_options) + ")");
510
684
  }
511
685
 
512
- ARGR("$amount", Number, 0, 100);
686
+ double amount = DARG_U_PRCT("$amount");
513
687
  Color_Ptr rgb_color = ARG("$color", Color);
514
688
  HSL hsl_color = rgb_to_hsl(rgb_color->r(),
515
689
  rgb_color->g(),
516
690
  rgb_color->b());
517
691
 
518
- double hslcolorS = hsl_color.s + amount->value();
692
+ double hslcolorS = hsl_color.s + amount;
519
693
 
520
694
  // Saturation cannot be below 0 or above 100
521
695
  if (hslcolorS < 0) {
@@ -537,12 +711,12 @@ namespace Sass {
537
711
  BUILT_IN(desaturate)
538
712
  {
539
713
  Color_Ptr rgb_color = ARG("$color", Color);
540
- Number_Ptr amount = ARGR("$amount", Number, 0, 100);
714
+ double amount = DARG_U_PRCT("$amount");
541
715
  HSL hsl_color = rgb_to_hsl(rgb_color->r(),
542
716
  rgb_color->g(),
543
717
  rgb_color->b());
544
718
 
545
- double hslcolorS = hsl_color.s - amount->value();
719
+ double hslcolorS = hsl_color.s - amount;
546
720
 
547
721
  // Saturation cannot be below 0 or above 100
548
722
  if (hslcolorS <= 0) {
@@ -564,7 +738,7 @@ namespace Sass {
564
738
  BUILT_IN(grayscale)
565
739
  {
566
740
  // CSS3 filter function overload: pass literal through directly
567
- Number_Ptr amount = SASS_MEMORY_CAST(Number, env["$color"]);
741
+ Number_Ptr amount = Cast<Number>(env["$color"]);
568
742
  if (amount) {
569
743
  return SASS_MEMORY_NEW(String_Quoted, pstate, "grayscale(" + amount->to_string(ctx.c_options) + ")");
570
744
  }
@@ -596,22 +770,24 @@ namespace Sass {
596
770
  pstate);
597
771
  }
598
772
 
599
- Signature invert_sig = "invert($color)";
773
+ Signature invert_sig = "invert($color, $weight: 100%)";
600
774
  BUILT_IN(invert)
601
775
  {
602
776
  // CSS3 filter function overload: pass literal through directly
603
- Number_Ptr amount = SASS_MEMORY_CAST(Number, env["$color"]);
777
+ Number_Ptr amount = Cast<Number>(env["$color"]);
604
778
  if (amount) {
605
779
  return SASS_MEMORY_NEW(String_Quoted, pstate, "invert(" + amount->to_string(ctx.c_options) + ")");
606
780
  }
607
781
 
782
+ double weight = DARG_U_PRCT("$weight");
608
783
  Color_Ptr rgb_color = ARG("$color", Color);
609
- return SASS_MEMORY_NEW(Color,
784
+ Color_Obj inv = SASS_MEMORY_NEW(Color,
610
785
  pstate,
611
786
  255 - rgb_color->r(),
612
787
  255 - rgb_color->g(),
613
788
  255 - rgb_color->b(),
614
789
  rgb_color->a());
790
+ return colormix(ctx, pstate, inv, rgb_color, weight);
615
791
  }
616
792
 
617
793
  ////////////////////
@@ -621,13 +797,13 @@ namespace Sass {
621
797
  Signature opacity_sig = "opacity($color)";
622
798
  BUILT_IN(alpha)
623
799
  {
624
- String_Constant_Ptr ie_kwd = SASS_MEMORY_CAST(String_Constant, env["$color"]);
800
+ String_Constant_Ptr ie_kwd = Cast<String_Constant>(env["$color"]);
625
801
  if (ie_kwd) {
626
802
  return SASS_MEMORY_NEW(String_Quoted, pstate, "alpha(" + ie_kwd->value() + ")");
627
803
  }
628
804
 
629
805
  // CSS3 filter function overload: pass literal through directly
630
- Number_Ptr amount = SASS_MEMORY_CAST(Number, env["$color"]);
806
+ Number_Ptr amount = Cast<Number>(env["$color"]);
631
807
  if (amount) {
632
808
  return SASS_MEMORY_NEW(String_Quoted, pstate, "opacity(" + amount->to_string(ctx.c_options) + ")");
633
809
  }
@@ -640,7 +816,7 @@ namespace Sass {
640
816
  BUILT_IN(opacify)
641
817
  {
642
818
  Color_Ptr color = ARG("$color", Color);
643
- double amount = ARGR("$amount", Number, 0, 1)->value();
819
+ double amount = DARG_U_FACT("$amount");
644
820
  double alpha = std::min(color->a() + amount, 1.0);
645
821
  return SASS_MEMORY_NEW(Color,
646
822
  pstate,
@@ -655,7 +831,7 @@ namespace Sass {
655
831
  BUILT_IN(transparentize)
656
832
  {
657
833
  Color_Ptr color = ARG("$color", Color);
658
- double amount = ARGR("$amount", Number, 0, 1)->value();
834
+ double amount = DARG_U_FACT("$amount");
659
835
  double alpha = std::max(color->a() - amount, 0.0);
660
836
  return SASS_MEMORY_NEW(Color,
661
837
  pstate,
@@ -673,25 +849,25 @@ namespace Sass {
673
849
  BUILT_IN(adjust_color)
674
850
  {
675
851
  Color_Ptr color = ARG("$color", Color);
676
- Number_Ptr r = SASS_MEMORY_CAST(Number, env["$red"]);
677
- Number_Ptr g = SASS_MEMORY_CAST(Number, env["$green"]);
678
- Number_Ptr b = SASS_MEMORY_CAST(Number, env["$blue"]);
679
- Number_Ptr h = SASS_MEMORY_CAST(Number, env["$hue"]);
680
- Number_Ptr s = SASS_MEMORY_CAST(Number, env["$saturation"]);
681
- Number_Ptr l = SASS_MEMORY_CAST(Number, env["$lightness"]);
682
- Number_Ptr a = SASS_MEMORY_CAST(Number, env["$alpha"]);
852
+ Number_Ptr r = Cast<Number>(env["$red"]);
853
+ Number_Ptr g = Cast<Number>(env["$green"]);
854
+ Number_Ptr b = Cast<Number>(env["$blue"]);
855
+ Number_Ptr h = Cast<Number>(env["$hue"]);
856
+ Number_Ptr s = Cast<Number>(env["$saturation"]);
857
+ Number_Ptr l = Cast<Number>(env["$lightness"]);
858
+ Number_Ptr a = Cast<Number>(env["$alpha"]);
683
859
 
684
860
  bool rgb = r || g || b;
685
861
  bool hsl = h || s || l;
686
862
 
687
863
  if (rgb && hsl) {
688
- error("Cannot specify HSL and RGB values for a color at the same time for `adjust-color'", pstate);
864
+ error("Cannot specify HSL and RGB values for a color at the same time for `adjust-color'", pstate, traces);
689
865
  }
690
866
  if (rgb) {
691
- double rr = r ? ARGR("$red", Number, -255, 255)->value() : 0;
692
- double gg = g ? ARGR("$green", Number, -255, 255)->value() : 0;
693
- double bb = b ? ARGR("$blue", Number, -255, 255)->value() : 0;
694
- double aa = a ? ARGR("$alpha", Number, -1, 1)->value() : 0;
867
+ double rr = r ? DARG_R_BYTE("$red") : 0;
868
+ double gg = g ? DARG_R_BYTE("$green") : 0;
869
+ double bb = b ? DARG_R_BYTE("$blue") : 0;
870
+ double aa = a ? DARG_R_FACT("$alpha") : 0;
695
871
  return SASS_MEMORY_NEW(Color,
696
872
  pstate,
697
873
  color->r() + rr,
@@ -701,9 +877,9 @@ namespace Sass {
701
877
  }
702
878
  if (hsl) {
703
879
  HSL hsl_struct = rgb_to_hsl(color->r(), color->g(), color->b());
704
- double ss = s ? ARGR("$saturation", Number, -100, 100)->value() : 0;
705
- double ll = l ? ARGR("$lightness", Number, -100, 100)->value() : 0;
706
- double aa = a ? ARGR("$alpha", Number, -1, 1)->value() : 0;
880
+ double ss = s ? DARG_R_PRCT("$saturation") : 0;
881
+ double ll = l ? DARG_R_PRCT("$lightness") : 0;
882
+ double aa = a ? DARG_R_FACT("$alpha") : 0;
707
883
  return hsla_impl(hsl_struct.h + (h ? h->value() : 0),
708
884
  hsl_struct.s + ss,
709
885
  hsl_struct.l + ll,
@@ -719,7 +895,7 @@ namespace Sass {
719
895
  color->b(),
720
896
  color->a() + (a ? a->value() : 0));
721
897
  }
722
- error("not enough arguments for `adjust-color'", pstate);
898
+ error("not enough arguments for `adjust-color'", pstate, traces);
723
899
  // unreachable
724
900
  return color;
725
901
  }
@@ -728,25 +904,25 @@ namespace Sass {
728
904
  BUILT_IN(scale_color)
729
905
  {
730
906
  Color_Ptr color = ARG("$color", Color);
731
- Number_Ptr r = SASS_MEMORY_CAST(Number, env["$red"]);
732
- Number_Ptr g = SASS_MEMORY_CAST(Number, env["$green"]);
733
- Number_Ptr b = SASS_MEMORY_CAST(Number, env["$blue"]);
734
- Number_Ptr h = SASS_MEMORY_CAST(Number, env["$hue"]);
735
- Number_Ptr s = SASS_MEMORY_CAST(Number, env["$saturation"]);
736
- Number_Ptr l = SASS_MEMORY_CAST(Number, env["$lightness"]);
737
- Number_Ptr a = SASS_MEMORY_CAST(Number, env["$alpha"]);
907
+ Number_Ptr r = Cast<Number>(env["$red"]);
908
+ Number_Ptr g = Cast<Number>(env["$green"]);
909
+ Number_Ptr b = Cast<Number>(env["$blue"]);
910
+ Number_Ptr h = Cast<Number>(env["$hue"]);
911
+ Number_Ptr s = Cast<Number>(env["$saturation"]);
912
+ Number_Ptr l = Cast<Number>(env["$lightness"]);
913
+ Number_Ptr a = Cast<Number>(env["$alpha"]);
738
914
 
739
915
  bool rgb = r || g || b;
740
916
  bool hsl = h || s || l;
741
917
 
742
918
  if (rgb && hsl) {
743
- error("Cannot specify HSL and RGB values for a color at the same time for `scale-color'", pstate);
919
+ error("Cannot specify HSL and RGB values for a color at the same time for `scale-color'", pstate, traces);
744
920
  }
745
921
  if (rgb) {
746
- double rscale = (r ? ARGR("$red", Number, -100.0, 100.0)->value() : 0.0) / 100.0;
747
- double gscale = (g ? ARGR("$green", Number, -100.0, 100.0)->value() : 0.0) / 100.0;
748
- double bscale = (b ? ARGR("$blue", Number, -100.0, 100.0)->value() : 0.0) / 100.0;
749
- double ascale = (a ? ARGR("$alpha", Number, -100.0, 100.0)->value() : 0.0) / 100.0;
922
+ double rscale = (r ? DARG_R_PRCT("$red") : 0.0) / 100.0;
923
+ double gscale = (g ? DARG_R_PRCT("$green") : 0.0) / 100.0;
924
+ double bscale = (b ? DARG_R_PRCT("$blue") : 0.0) / 100.0;
925
+ double ascale = (a ? DARG_R_PRCT("$alpha") : 0.0) / 100.0;
750
926
  return SASS_MEMORY_NEW(Color,
751
927
  pstate,
752
928
  color->r() + rscale * (rscale > 0.0 ? 255 - color->r() : color->r()),
@@ -755,10 +931,10 @@ namespace Sass {
755
931
  color->a() + ascale * (ascale > 0.0 ? 1.0 - color->a() : color->a()));
756
932
  }
757
933
  if (hsl) {
758
- double hscale = (h ? ARGR("$hue", Number, -100.0, 100.0)->value() : 0.0) / 100.0;
759
- double sscale = (s ? ARGR("$saturation", Number, -100.0, 100.0)->value() : 0.0) / 100.0;
760
- double lscale = (l ? ARGR("$lightness", Number, -100.0, 100.0)->value() : 0.0) / 100.0;
761
- double ascale = (a ? ARGR("$alpha", Number, -100.0, 100.0)->value() : 0.0) / 100.0;
934
+ double hscale = (h ? DARG_R_PRCT("$hue") : 0.0) / 100.0;
935
+ double sscale = (s ? DARG_R_PRCT("$saturation") : 0.0) / 100.0;
936
+ double lscale = (l ? DARG_R_PRCT("$lightness") : 0.0) / 100.0;
937
+ double ascale = (a ? DARG_R_PRCT("$alpha") : 0.0) / 100.0;
762
938
  HSL hsl_struct = rgb_to_hsl(color->r(), color->g(), color->b());
763
939
  hsl_struct.h += hscale * (hscale > 0.0 ? 360.0 - hsl_struct.h : hsl_struct.h);
764
940
  hsl_struct.s += sscale * (sscale > 0.0 ? 100.0 - hsl_struct.s : hsl_struct.s);
@@ -767,7 +943,7 @@ namespace Sass {
767
943
  return hsla_impl(hsl_struct.h, hsl_struct.s, hsl_struct.l, alpha, ctx, pstate);
768
944
  }
769
945
  if (a) {
770
- double ascale = (a ? ARGR("$alpha", Number, -100.0, 100.0)->value() : 0.0) / 100.0;
946
+ double ascale = (DARG_R_PRCT("$alpha")) / 100.0;
771
947
  return SASS_MEMORY_NEW(Color,
772
948
  pstate,
773
949
  color->r(),
@@ -775,7 +951,7 @@ namespace Sass {
775
951
  color->b(),
776
952
  color->a() + ascale * (ascale > 0.0 ? 1.0 - color->a() : color->a()));
777
953
  }
778
- error("not enough arguments for `scale-color'", pstate);
954
+ error("not enough arguments for `scale-color'", pstate, traces);
779
955
  // unreachable
780
956
  return color;
781
957
  }
@@ -784,38 +960,38 @@ namespace Sass {
784
960
  BUILT_IN(change_color)
785
961
  {
786
962
  Color_Ptr color = ARG("$color", Color);
787
- Number_Ptr r = SASS_MEMORY_CAST(Number, env["$red"]);
788
- Number_Ptr g = SASS_MEMORY_CAST(Number, env["$green"]);
789
- Number_Ptr b = SASS_MEMORY_CAST(Number, env["$blue"]);
790
- Number_Ptr h = SASS_MEMORY_CAST(Number, env["$hue"]);
791
- Number_Ptr s = SASS_MEMORY_CAST(Number, env["$saturation"]);
792
- Number_Ptr l = SASS_MEMORY_CAST(Number, env["$lightness"]);
793
- Number_Ptr a = SASS_MEMORY_CAST(Number, env["$alpha"]);
963
+ Number_Ptr r = Cast<Number>(env["$red"]);
964
+ Number_Ptr g = Cast<Number>(env["$green"]);
965
+ Number_Ptr b = Cast<Number>(env["$blue"]);
966
+ Number_Ptr h = Cast<Number>(env["$hue"]);
967
+ Number_Ptr s = Cast<Number>(env["$saturation"]);
968
+ Number_Ptr l = Cast<Number>(env["$lightness"]);
969
+ Number_Ptr a = Cast<Number>(env["$alpha"]);
794
970
 
795
971
  bool rgb = r || g || b;
796
972
  bool hsl = h || s || l;
797
973
 
798
974
  if (rgb && hsl) {
799
- error("Cannot specify HSL and RGB values for a color at the same time for `change-color'", pstate);
975
+ error("Cannot specify HSL and RGB values for a color at the same time for `change-color'", pstate, traces);
800
976
  }
801
977
  if (rgb) {
802
978
  return SASS_MEMORY_NEW(Color,
803
979
  pstate,
804
- r ? ARGR("$red", Number, 0, 255)->value() : color->r(),
805
- g ? ARGR("$green", Number, 0, 255)->value() : color->g(),
806
- b ? ARGR("$blue", Number, 0, 255)->value() : color->b(),
807
- a ? ARGR("$alpha", Number, 0, 255)->value() : color->a());
980
+ r ? DARG_U_BYTE("$red") : color->r(),
981
+ g ? DARG_U_BYTE("$green") : color->g(),
982
+ b ? DARG_U_BYTE("$blue") : color->b(),
983
+ a ? DARG_U_BYTE("$alpha") : color->a());
808
984
  }
809
985
  if (hsl) {
810
986
  HSL hsl_struct = rgb_to_hsl(color->r(), color->g(), color->b());
811
987
  if (h) hsl_struct.h = std::fmod(h->value(), 360.0);
812
- if (s) hsl_struct.s = ARGR("$saturation", Number, 0, 100)->value();
813
- if (l) hsl_struct.l = ARGR("$lightness", Number, 0, 100)->value();
814
- double alpha = a ? ARGR("$alpha", Number, 0, 1.0)->value() : color->a();
988
+ if (s) hsl_struct.s = DARG_U_PRCT("$saturation");
989
+ if (l) hsl_struct.l = DARG_U_PRCT("$lightness");
990
+ double alpha = a ? DARG_U_FACT("$alpha") : color->a();
815
991
  return hsla_impl(hsl_struct.h, hsl_struct.s, hsl_struct.l, alpha, ctx, pstate);
816
992
  }
817
993
  if (a) {
818
- double alpha = a ? ARGR("$alpha", Number, 0, 1.0)->value() : color->a();
994
+ double alpha = DARG_U_FACT("$alpha");
819
995
  return SASS_MEMORY_NEW(Color,
820
996
  pstate,
821
997
  color->r(),
@@ -823,7 +999,7 @@ namespace Sass {
823
999
  color->b(),
824
1000
  alpha);
825
1001
  }
826
- error("not enough arguments for `change-color'", pstate);
1002
+ error("not enough arguments for `change-color'", pstate, traces);
827
1003
  // unreachable
828
1004
  return color;
829
1005
  }
@@ -866,25 +1042,26 @@ namespace Sass {
866
1042
  BUILT_IN(sass_unquote)
867
1043
  {
868
1044
  AST_Node_Obj arg = env["$string"];
869
- if (String_Quoted_Ptr string_quoted = SASS_MEMORY_CAST(String_Quoted, arg)) {
1045
+ if (String_Quoted_Ptr string_quoted = Cast<String_Quoted>(arg)) {
870
1046
  String_Constant_Ptr result = SASS_MEMORY_NEW(String_Constant, pstate, string_quoted->value());
871
1047
  // remember if the string was quoted (color tokens)
872
1048
  result->is_delayed(true); // delay colors
873
1049
  return result;
874
1050
  }
875
- else if (SASS_MEMORY_CAST(String_Constant, arg)) {
876
- return (Expression_Ptr) &arg;
1051
+ else if (String_Constant_Ptr str = Cast<String_Constant>(arg)) {
1052
+ return str;
877
1053
  }
878
- else {
1054
+ else if (Expression_Ptr ex = Cast<Expression>(arg)) {
879
1055
  Sass_Output_Style oldstyle = ctx.c_options.output_style;
880
1056
  ctx.c_options.output_style = SASS_STYLE_NESTED;
881
1057
  std::string val(arg->to_string(ctx.c_options));
882
- val = SASS_MEMORY_CAST(Null, arg) ? "null" : val;
1058
+ val = Cast<Null>(arg) ? "null" : val;
883
1059
  ctx.c_options.output_style = oldstyle;
884
1060
 
885
1061
  deprecated_function("Passing " + val + ", a non-string value, to unquote()", pstate);
886
- return (Expression_Ptr) &arg;
1062
+ return ex;
887
1063
  }
1064
+ throw std::runtime_error("Invalid Data Type for unquote");
888
1065
  }
889
1066
 
890
1067
  Signature quote_sig = "quote($string)";
@@ -892,7 +1069,7 @@ namespace Sass {
892
1069
  {
893
1070
  AST_Node_Obj arg = env["$string"];
894
1071
  // only set quote mark to true if already a string
895
- if (String_Quoted_Ptr qstr = SASS_MEMORY_CAST(String_Quoted, arg)) {
1072
+ if (String_Quoted_Ptr qstr = Cast<String_Quoted>(arg)) {
896
1073
  qstr->quote_mark('*');
897
1074
  return qstr;
898
1075
  }
@@ -915,7 +1092,7 @@ namespace Sass {
915
1092
  }
916
1093
  // handle any invalid utf8 errors
917
1094
  // other errors will be re-thrown
918
- catch (...) { handle_utf8_error(pstate, backtrace); }
1095
+ catch (...) { handle_utf8_error(pstate, traces); }
919
1096
  // return something even if we had an error (-1)
920
1097
  return SASS_MEMORY_NEW(Number, pstate, (double)len);
921
1098
  }
@@ -931,8 +1108,7 @@ namespace Sass {
931
1108
  String_Constant_Ptr i = ARG("$insert", String_Constant);
932
1109
  std::string ins = i->value();
933
1110
  ins = unquote(ins);
934
- Number_Ptr ind = ARG("$index", Number);
935
- double index = ind->value();
1111
+ double index = ARGVAL("$index");
936
1112
  size_t len = UTF_8::code_point_count(str, 0, str.size());
937
1113
 
938
1114
  if (index > 0 && index <= len) {
@@ -956,13 +1132,13 @@ namespace Sass {
956
1132
  str = ins + str;
957
1133
  }
958
1134
 
959
- if (String_Quoted_Ptr ss = SASS_MEMORY_CAST_PTR(String_Quoted, s)) {
1135
+ if (String_Quoted_Ptr ss = Cast<String_Quoted>(s)) {
960
1136
  if (ss->quote_mark()) str = quote(str);
961
1137
  }
962
1138
  }
963
1139
  // handle any invalid utf8 errors
964
1140
  // other errors will be re-thrown
965
- catch (...) { handle_utf8_error(pstate, backtrace); }
1141
+ catch (...) { handle_utf8_error(pstate, traces); }
966
1142
  return SASS_MEMORY_NEW(String_Quoted, pstate, str);
967
1143
  }
968
1144
 
@@ -986,7 +1162,7 @@ namespace Sass {
986
1162
  }
987
1163
  // handle any invalid utf8 errors
988
1164
  // other errors will be re-thrown
989
- catch (...) { handle_utf8_error(pstate, backtrace); }
1165
+ catch (...) { handle_utf8_error(pstate, traces); }
990
1166
  // return something even if we had an error (-1)
991
1167
  return SASS_MEMORY_NEW(Number, pstate, (double)index);
992
1168
  }
@@ -997,15 +1173,15 @@ namespace Sass {
997
1173
  std::string newstr;
998
1174
  try {
999
1175
  String_Constant_Ptr s = ARG("$string", String_Constant);
1000
- double start_at = ARG("$start-at", Number)->value();
1001
- double end_at = ARG("$end-at", Number)->value();
1002
- String_Quoted_Ptr ss = SASS_MEMORY_CAST_PTR(String_Quoted, s);
1176
+ double start_at = ARGVAL("$start-at");
1177
+ double end_at = ARGVAL("$end-at");
1178
+ String_Quoted_Ptr ss = Cast<String_Quoted>(s);
1003
1179
 
1004
1180
  std::string str = unquote(s->value());
1005
1181
 
1006
1182
  size_t size = utf8::distance(str.begin(), str.end());
1007
1183
 
1008
- if (!SASS_MEMORY_CAST(Number, env["$end-at"])) {
1184
+ if (!Cast<Number>(env["$end-at"])) {
1009
1185
  end_at = -1;
1010
1186
  }
1011
1187
 
@@ -1039,7 +1215,7 @@ namespace Sass {
1039
1215
  }
1040
1216
  // handle any invalid utf8 errors
1041
1217
  // other errors will be re-thrown
1042
- catch (...) { handle_utf8_error(pstate, backtrace); }
1218
+ catch (...) { handle_utf8_error(pstate, traces); }
1043
1219
  return SASS_MEMORY_NEW(String_Quoted, pstate, newstr);
1044
1220
  }
1045
1221
 
@@ -1055,7 +1231,7 @@ namespace Sass {
1055
1231
  }
1056
1232
  }
1057
1233
 
1058
- if (String_Quoted_Ptr ss = SASS_MEMORY_CAST_PTR(String_Quoted, s)) {
1234
+ if (String_Quoted_Ptr ss = Cast<String_Quoted>(s)) {
1059
1235
  String_Quoted_Ptr cpy = SASS_MEMORY_COPY(ss);
1060
1236
  cpy->value(str);
1061
1237
  return cpy;
@@ -1076,7 +1252,7 @@ namespace Sass {
1076
1252
  }
1077
1253
  }
1078
1254
 
1079
- if (String_Quoted_Ptr ss = SASS_MEMORY_CAST_PTR(String_Quoted, s)) {
1255
+ if (String_Quoted_Ptr ss = Cast<String_Quoted>(s)) {
1080
1256
  String_Quoted_Ptr cpy = SASS_MEMORY_COPY(ss);
1081
1257
  cpy->value(str);
1082
1258
  return cpy;
@@ -1092,49 +1268,45 @@ namespace Sass {
1092
1268
  Signature percentage_sig = "percentage($number)";
1093
1269
  BUILT_IN(percentage)
1094
1270
  {
1095
- Number_Ptr n = ARG("$number", Number);
1096
- if (!n->is_unitless()) error("argument $number of `" + std::string(sig) + "` must be unitless", pstate);
1271
+ Number_Obj n = ARGN("$number");
1272
+ if (!n->is_unitless()) error("argument $number of `" + std::string(sig) + "` must be unitless", pstate, traces);
1097
1273
  return SASS_MEMORY_NEW(Number, pstate, n->value() * 100, "%");
1098
1274
  }
1099
1275
 
1100
1276
  Signature round_sig = "round($number)";
1101
1277
  BUILT_IN(round)
1102
1278
  {
1103
- Number_Ptr n = ARG("$number", Number);
1104
- Number_Ptr r = SASS_MEMORY_COPY(n);
1105
- r->pstate(pstate);
1279
+ Number_Obj r = ARGN("$number");
1106
1280
  r->value(Sass::round(r->value(), ctx.c_options.precision));
1107
- return r;
1281
+ r->pstate(pstate);
1282
+ return r.detach();
1108
1283
  }
1109
1284
 
1110
1285
  Signature ceil_sig = "ceil($number)";
1111
1286
  BUILT_IN(ceil)
1112
1287
  {
1113
- Number_Ptr n = ARG("$number", Number);
1114
- Number_Ptr r = SASS_MEMORY_COPY(n);
1115
- r->pstate(pstate);
1288
+ Number_Obj r = ARGN("$number");
1116
1289
  r->value(std::ceil(r->value()));
1117
- return r;
1290
+ r->pstate(pstate);
1291
+ return r.detach();
1118
1292
  }
1119
1293
 
1120
1294
  Signature floor_sig = "floor($number)";
1121
1295
  BUILT_IN(floor)
1122
1296
  {
1123
- Number_Ptr n = ARG("$number", Number);
1124
- Number_Ptr r = SASS_MEMORY_COPY(n);
1125
- r->pstate(pstate);
1297
+ Number_Obj r = ARGN("$number");
1126
1298
  r->value(std::floor(r->value()));
1127
- return r;
1299
+ r->pstate(pstate);
1300
+ return r.detach();
1128
1301
  }
1129
1302
 
1130
1303
  Signature abs_sig = "abs($number)";
1131
1304
  BUILT_IN(abs)
1132
1305
  {
1133
- Number_Ptr n = ARG("$number", Number);
1134
- Number_Ptr r = SASS_MEMORY_COPY(n);
1135
- r->pstate(pstate);
1306
+ Number_Obj r = ARGN("$number");
1136
1307
  r->value(std::abs(r->value()));
1137
- return r;
1308
+ r->pstate(pstate);
1309
+ return r.detach();
1138
1310
  }
1139
1311
 
1140
1312
  Signature min_sig = "min($numbers...)";
@@ -1144,9 +1316,9 @@ namespace Sass {
1144
1316
  Number_Obj least = NULL;
1145
1317
  for (size_t i = 0, L = arglist->length(); i < L; ++i) {
1146
1318
  Expression_Obj val = arglist->value_at_index(i);
1147
- Number_Obj xi = SASS_MEMORY_CAST(Number, val);
1319
+ Number_Obj xi = Cast<Number>(val);
1148
1320
  if (!xi) {
1149
- error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `min'", pstate);
1321
+ error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `min'", pstate, traces);
1150
1322
  }
1151
1323
  if (least) {
1152
1324
  if (*xi < *least) least = xi;
@@ -1162,9 +1334,9 @@ namespace Sass {
1162
1334
  Number_Obj greatest = NULL;
1163
1335
  for (size_t i = 0, L = arglist->length(); i < L; ++i) {
1164
1336
  Expression_Obj val = arglist->value_at_index(i);
1165
- Number_Obj xi = SASS_MEMORY_CAST(Number, val);
1337
+ Number_Obj xi = Cast<Number>(val);
1166
1338
  if (!xi) {
1167
- error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `max'", pstate);
1339
+ error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `max'", pstate, traces);
1168
1340
  }
1169
1341
  if (greatest) {
1170
1342
  if (*greatest < *xi) greatest = xi;
@@ -1177,23 +1349,23 @@ namespace Sass {
1177
1349
  BUILT_IN(random)
1178
1350
  {
1179
1351
  AST_Node_Obj arg = env["$limit"];
1180
- Value_Ptr v = SASS_MEMORY_CAST(Value, arg);
1181
- Number_Ptr l = SASS_MEMORY_CAST(Number, arg);
1182
- Boolean_Ptr b = SASS_MEMORY_CAST(Boolean, arg);
1352
+ Value_Ptr v = Cast<Value>(arg);
1353
+ Number_Ptr l = Cast<Number>(arg);
1354
+ Boolean_Ptr b = Cast<Boolean>(arg);
1183
1355
  if (l) {
1184
- double v = l->value();
1185
- if (v < 1) {
1356
+ double lv = l->value();
1357
+ if (lv < 1) {
1186
1358
  stringstream err;
1187
- err << "$limit " << v << " must be greater than or equal to 1 for `random'";
1188
- error(err.str(), pstate);
1359
+ err << "$limit " << lv << " must be greater than or equal to 1 for `random'";
1360
+ error(err.str(), pstate, traces);
1189
1361
  }
1190
- bool eq_int = std::fabs(trunc(v) - v) < NUMBER_EPSILON;
1362
+ bool eq_int = std::fabs(trunc(lv) - lv) < NUMBER_EPSILON;
1191
1363
  if (!eq_int) {
1192
1364
  stringstream err;
1193
- err << "Expected $limit to be an integer but got " << v << " for `random'";
1194
- error(err.str(), pstate);
1365
+ err << "Expected $limit to be an integer but got " << lv << " for `random'";
1366
+ error(err.str(), pstate, traces);
1195
1367
  }
1196
- std::uniform_real_distribution<> distributor(1, v + 1);
1368
+ std::uniform_real_distribution<> distributor(1, lv + 1);
1197
1369
  uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand));
1198
1370
  return SASS_MEMORY_NEW(Number, pstate, (double)distributed);
1199
1371
  }
@@ -1202,11 +1374,12 @@ namespace Sass {
1202
1374
  double distributed = static_cast<double>(distributor(rand));
1203
1375
  return SASS_MEMORY_NEW(Number, pstate, distributed);
1204
1376
  } else if (v) {
1205
- throw Exception::InvalidArgumentType(pstate, "random", "$limit", "number", v);
1377
+ traces.push_back(Backtrace(pstate));
1378
+ throw Exception::InvalidArgumentType(pstate, traces, "random", "$limit", "number", v);
1206
1379
  } else {
1207
- throw Exception::InvalidArgumentType(pstate, "random", "$limit", "number");
1380
+ traces.push_back(Backtrace(pstate));
1381
+ throw Exception::InvalidArgumentType(pstate, traces, "random", "$limit", "number");
1208
1382
  }
1209
- return 0;
1210
1383
  }
1211
1384
 
1212
1385
  /////////////////
@@ -1216,25 +1389,25 @@ namespace Sass {
1216
1389
  Signature length_sig = "length($list)";
1217
1390
  BUILT_IN(length)
1218
1391
  {
1219
- if (Selector_List_Ptr sl = SASS_MEMORY_CAST(Selector_List, env["$list"])) {
1392
+ if (Selector_List_Ptr sl = Cast<Selector_List>(env["$list"])) {
1220
1393
  return SASS_MEMORY_NEW(Number, pstate, (double)sl->length());
1221
1394
  }
1222
1395
  Expression_Ptr v = ARG("$list", Expression);
1223
1396
  if (v->concrete_type() == Expression::MAP) {
1224
- Map_Ptr map = SASS_MEMORY_CAST(Map, env["$list"]);
1397
+ Map_Ptr map = Cast<Map>(env["$list"]);
1225
1398
  return SASS_MEMORY_NEW(Number, pstate, (double)(map ? map->length() : 1));
1226
1399
  }
1227
1400
  if (v->concrete_type() == Expression::SELECTOR) {
1228
- if (Compound_Selector_Ptr h = dynamic_cast<Compound_Selector_Ptr>(v)) {
1401
+ if (Compound_Selector_Ptr h = Cast<Compound_Selector>(v)) {
1229
1402
  return SASS_MEMORY_NEW(Number, pstate, (double)h->length());
1230
- } else if (Selector_List_Ptr ls = SASS_MEMORY_CAST_PTR(Selector_List, v)) {
1403
+ } else if (Selector_List_Ptr ls = Cast<Selector_List>(v)) {
1231
1404
  return SASS_MEMORY_NEW(Number, pstate, (double)ls->length());
1232
1405
  } else {
1233
1406
  return SASS_MEMORY_NEW(Number, pstate, 1);
1234
1407
  }
1235
1408
  }
1236
1409
 
1237
- List_Ptr list = SASS_MEMORY_CAST(List, env["$list"]);
1410
+ List_Ptr list = Cast<List>(env["$list"]);
1238
1411
  return SASS_MEMORY_NEW(Number,
1239
1412
  pstate,
1240
1413
  (double)(list ? list->size() : 1));
@@ -1243,20 +1416,20 @@ namespace Sass {
1243
1416
  Signature nth_sig = "nth($list, $n)";
1244
1417
  BUILT_IN(nth)
1245
1418
  {
1246
- Number_Ptr n = ARG("$n", Number);
1247
- Map_Ptr m = SASS_MEMORY_CAST(Map, env["$list"]);
1248
- if (Selector_List_Ptr sl = SASS_MEMORY_CAST(Selector_List, env["$list"])) {
1419
+ double nr = ARGVAL("$n");
1420
+ Map_Ptr m = Cast<Map>(env["$list"]);
1421
+ if (Selector_List_Ptr sl = Cast<Selector_List>(env["$list"])) {
1249
1422
  size_t len = m ? m->length() : sl->length();
1250
1423
  bool empty = m ? m->empty() : sl->empty();
1251
- if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate);
1252
- double index = std::floor(n->value() < 0 ? len + n->value() : n->value() - 1);
1253
- if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate);
1424
+ if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate, traces);
1425
+ double index = std::floor(nr < 0 ? len + nr : nr - 1);
1426
+ if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate, traces);
1254
1427
  // return (*sl)[static_cast<int>(index)];
1255
1428
  Listize listize;
1256
1429
  return (*sl)[static_cast<int>(index)]->perform(&listize);
1257
1430
  }
1258
- List_Obj l = SASS_MEMORY_CAST(List, env["$list"]);
1259
- if (n->value() == 0) error("argument `$n` of `" + std::string(sig) + "` must be non-zero", pstate);
1431
+ List_Obj l = Cast<List>(env["$list"]);
1432
+ if (nr == 0) error("argument `$n` of `" + std::string(sig) + "` must be non-zero", pstate, traces);
1260
1433
  // if the argument isn't a list, then wrap it in a singleton list
1261
1434
  if (!m && !l) {
1262
1435
  l = SASS_MEMORY_NEW(List, pstate, 1);
@@ -1264,9 +1437,9 @@ namespace Sass {
1264
1437
  }
1265
1438
  size_t len = m ? m->length() : l->length();
1266
1439
  bool empty = m ? m->empty() : l->empty();
1267
- if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate);
1268
- double index = std::floor(n->value() < 0 ? len + n->value() : n->value() - 1);
1269
- if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate);
1440
+ if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate, traces);
1441
+ double index = std::floor(nr < 0 ? len + nr : nr - 1);
1442
+ if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate, traces);
1270
1443
 
1271
1444
  if (m) {
1272
1445
  l = SASS_MEMORY_NEW(List, pstate, 1);
@@ -1284,8 +1457,8 @@ namespace Sass {
1284
1457
  Signature set_nth_sig = "set-nth($list, $n, $value)";
1285
1458
  BUILT_IN(set_nth)
1286
1459
  {
1287
- Map_Obj m = SASS_MEMORY_CAST(Map, env["$list"]);
1288
- List_Obj l = SASS_MEMORY_CAST(List, env["$list"]);
1460
+ Map_Obj m = Cast<Map>(env["$list"]);
1461
+ List_Obj l = Cast<List>(env["$list"]);
1289
1462
  Number_Obj n = ARG("$n", Number);
1290
1463
  Expression_Obj v = ARG("$value", Expression);
1291
1464
  if (!l) {
@@ -1293,12 +1466,12 @@ namespace Sass {
1293
1466
  l->append(ARG("$list", Expression));
1294
1467
  }
1295
1468
  if (m) {
1296
- l = m->to_list(ctx, pstate);
1469
+ l = m->to_list(pstate);
1297
1470
  }
1298
- if (l->empty()) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate);
1471
+ if (l->empty()) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate, traces);
1299
1472
  double index = std::floor(n->value() < 0 ? l->length() + n->value() : n->value() - 1);
1300
- if (index < 0 || index > l->length() - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate);
1301
- List_Ptr result = SASS_MEMORY_NEW(List, pstate, l->length(), l->separator());
1473
+ if (index < 0 || index > l->length() - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate, traces);
1474
+ List_Ptr result = SASS_MEMORY_NEW(List, pstate, l->length(), l->separator(), false, l->is_bracketed());
1302
1475
  for (size_t i = 0, L = l->length(); i < L; ++i) {
1303
1476
  result->append(((i == index) ? v : (*l)[i]));
1304
1477
  }
@@ -1308,67 +1481,75 @@ namespace Sass {
1308
1481
  Signature index_sig = "index($list, $value)";
1309
1482
  BUILT_IN(index)
1310
1483
  {
1311
- Map_Obj m = SASS_MEMORY_CAST(Map, env["$list"]);
1312
- List_Obj l = SASS_MEMORY_CAST(List, env["$list"]);
1484
+ Map_Obj m = Cast<Map>(env["$list"]);
1485
+ List_Obj l = Cast<List>(env["$list"]);
1313
1486
  Expression_Obj v = ARG("$value", Expression);
1314
1487
  if (!l) {
1315
1488
  l = SASS_MEMORY_NEW(List, pstate, 1);
1316
1489
  l->append(ARG("$list", Expression));
1317
1490
  }
1318
1491
  if (m) {
1319
- l = m->to_list(ctx, pstate);
1492
+ l = m->to_list(pstate);
1320
1493
  }
1321
1494
  for (size_t i = 0, L = l->length(); i < L; ++i) {
1322
- if (Eval::eq(l->value_at_index(i), v)) return SASS_MEMORY_NEW(Number, pstate, (double)(i+1));
1495
+ if (Operators::eq(l->value_at_index(i), v)) return SASS_MEMORY_NEW(Number, pstate, (double)(i+1));
1323
1496
  }
1324
1497
  return SASS_MEMORY_NEW(Null, pstate);
1325
1498
  }
1326
1499
 
1327
- Signature join_sig = "join($list1, $list2, $separator: auto)";
1500
+ Signature join_sig = "join($list1, $list2, $separator: auto, $bracketed: auto)";
1328
1501
  BUILT_IN(join)
1329
1502
  {
1330
- Map_Obj m1 = SASS_MEMORY_CAST(Map, env["$list1"]);
1331
- Map_Obj m2 = SASS_MEMORY_CAST(Map, env["$list2"]);
1332
- List_Obj l1 = SASS_MEMORY_CAST(List, env["$list1"]);
1333
- List_Obj l2 = SASS_MEMORY_CAST(List, env["$list2"]);
1503
+ Map_Obj m1 = Cast<Map>(env["$list1"]);
1504
+ Map_Obj m2 = Cast<Map>(env["$list2"]);
1505
+ List_Obj l1 = Cast<List>(env["$list1"]);
1506
+ List_Obj l2 = Cast<List>(env["$list2"]);
1334
1507
  String_Constant_Obj sep = ARG("$separator", String_Constant);
1335
1508
  enum Sass_Separator sep_val = (l1 ? l1->separator() : SASS_SPACE);
1509
+ Value* bracketed = ARG("$bracketed", Value);
1510
+ bool is_bracketed = (l1 ? l1->is_bracketed() : false);
1336
1511
  if (!l1) {
1337
1512
  l1 = SASS_MEMORY_NEW(List, pstate, 1);
1338
1513
  l1->append(ARG("$list1", Expression));
1339
1514
  sep_val = (l2 ? l2->separator() : SASS_SPACE);
1515
+ is_bracketed = (l2 ? l2->is_bracketed() : false);
1340
1516
  }
1341
1517
  if (!l2) {
1342
1518
  l2 = SASS_MEMORY_NEW(List, pstate, 1);
1343
1519
  l2->append(ARG("$list2", Expression));
1344
1520
  }
1345
1521
  if (m1) {
1346
- l1 = m1->to_list(ctx, pstate);
1522
+ l1 = m1->to_list(pstate);
1347
1523
  sep_val = SASS_COMMA;
1348
1524
  }
1349
1525
  if (m2) {
1350
- l2 = m2->to_list(ctx, pstate);
1526
+ l2 = m2->to_list(pstate);
1351
1527
  }
1352
1528
  size_t len = l1->length() + l2->length();
1353
1529
  std::string sep_str = unquote(sep->value());
1354
1530
  if (sep_str == "space") sep_val = SASS_SPACE;
1355
1531
  else if (sep_str == "comma") sep_val = SASS_COMMA;
1356
- else if (sep_str != "auto") error("argument `$separator` of `" + std::string(sig) + "` must be `space`, `comma`, or `auto`", pstate);
1357
- List_Obj result = SASS_MEMORY_NEW(List, pstate, len, sep_val);
1358
- result->concat(&l1);
1359
- result->concat(&l2);
1532
+ else if (sep_str != "auto") error("argument `$separator` of `" + std::string(sig) + "` must be `space`, `comma`, or `auto`", pstate, traces);
1533
+ String_Constant_Obj bracketed_as_str = Cast<String_Constant>(bracketed);
1534
+ bool bracketed_is_auto = bracketed_as_str && unquote(bracketed_as_str->value()) == "auto";
1535
+ if (!bracketed_is_auto) {
1536
+ is_bracketed = !bracketed->is_false();
1537
+ }
1538
+ List_Obj result = SASS_MEMORY_NEW(List, pstate, len, sep_val, false, is_bracketed);
1539
+ result->concat(l1);
1540
+ result->concat(l2);
1360
1541
  return result.detach();
1361
1542
  }
1362
1543
 
1363
1544
  Signature append_sig = "append($list, $val, $separator: auto)";
1364
1545
  BUILT_IN(append)
1365
1546
  {
1366
- Map_Obj m = SASS_MEMORY_CAST(Map, env["$list"]);
1367
- List_Obj l = SASS_MEMORY_CAST(List, env["$list"]);
1547
+ Map_Obj m = Cast<Map>(env["$list"]);
1548
+ List_Obj l = Cast<List>(env["$list"]);
1368
1549
  Expression_Obj v = ARG("$val", Expression);
1369
- if (Selector_List_Ptr sl = SASS_MEMORY_CAST(Selector_List, env["$list"])) {
1550
+ if (Selector_List_Ptr sl = Cast<Selector_List>(env["$list"])) {
1370
1551
  Listize listize;
1371
- l = SASS_MEMORY_CAST_PTR(List, sl->perform(&listize));
1552
+ l = Cast<List>(sl->perform(&listize));
1372
1553
  }
1373
1554
  String_Constant_Obj sep = ARG("$separator", String_Constant);
1374
1555
  if (!l) {
@@ -1376,14 +1557,14 @@ namespace Sass {
1376
1557
  l->append(ARG("$list", Expression));
1377
1558
  }
1378
1559
  if (m) {
1379
- l = m->to_list(ctx, pstate);
1560
+ l = m->to_list(pstate);
1380
1561
  }
1381
1562
  List_Ptr result = SASS_MEMORY_COPY(l);
1382
1563
  std::string sep_str(unquote(sep->value()));
1383
1564
  if (sep_str != "auto") { // check default first
1384
1565
  if (sep_str == "space") result->separator(SASS_SPACE);
1385
1566
  else if (sep_str == "comma") result->separator(SASS_COMMA);
1386
- else error("argument `$separator` of `" + std::string(sig) + "` must be `space`, `comma`, or `auto`", pstate);
1567
+ else error("argument `$separator` of `" + std::string(sig) + "` must be `space`, `comma`, or `auto`", pstate, traces);
1387
1568
  }
1388
1569
  if (l->is_arglist()) {
1389
1570
  result->append(SASS_MEMORY_NEW(Argument,
@@ -1405,20 +1586,20 @@ namespace Sass {
1405
1586
  List_Obj arglist = SASS_MEMORY_COPY(ARG("$lists", List));
1406
1587
  size_t shortest = 0;
1407
1588
  for (size_t i = 0, L = arglist->length(); i < L; ++i) {
1408
- List_Obj ith = SASS_MEMORY_CAST(List, arglist->value_at_index(i));
1409
- Map_Obj mith = SASS_MEMORY_CAST(Map, arglist->value_at_index(i));
1589
+ List_Obj ith = Cast<List>(arglist->value_at_index(i));
1590
+ Map_Obj mith = Cast<Map>(arglist->value_at_index(i));
1410
1591
  if (!ith) {
1411
1592
  if (mith) {
1412
- ith = mith->to_list(ctx, pstate);
1593
+ ith = mith->to_list(pstate);
1413
1594
  } else {
1414
1595
  ith = SASS_MEMORY_NEW(List, pstate, 1);
1415
1596
  ith->append(arglist->value_at_index(i));
1416
1597
  }
1417
1598
  if (arglist->is_arglist()) {
1418
- Argument_Obj arg = (Argument_Ptr)(&arglist->at(i));
1419
- arg->value(&ith);
1599
+ Argument_Obj arg = (Argument_Ptr)(arglist->at(i).ptr()); // XXX
1600
+ arg->value(ith);
1420
1601
  } else {
1421
- (*arglist)[i] = &ith;
1602
+ (*arglist)[i] = ith;
1422
1603
  }
1423
1604
  }
1424
1605
  shortest = (i ? std::min(shortest, ith->length()) : ith->length());
@@ -1428,7 +1609,7 @@ namespace Sass {
1428
1609
  for (size_t i = 0; i < shortest; ++i) {
1429
1610
  List_Ptr zipper = SASS_MEMORY_NEW(List, pstate, L);
1430
1611
  for (size_t j = 0; j < L; ++j) {
1431
- zipper->append(SASS_MEMORY_CAST(List, arglist->value_at_index(j))->at(i));
1612
+ zipper->append(Cast<List>(arglist->value_at_index(j))->at(i));
1432
1613
  }
1433
1614
  zippers->append(zipper);
1434
1615
  }
@@ -1438,7 +1619,7 @@ namespace Sass {
1438
1619
  Signature list_separator_sig = "list_separator($list)";
1439
1620
  BUILT_IN(list_separator)
1440
1621
  {
1441
- List_Obj l = SASS_MEMORY_CAST(List, env["$list"]);
1622
+ List_Obj l = Cast<List>(env["$list"]);
1442
1623
  if (!l) {
1443
1624
  l = SASS_MEMORY_NEW(List, pstate, 1);
1444
1625
  l->append(ARG("$list", Expression));
@@ -1460,8 +1641,10 @@ namespace Sass {
1460
1641
  Map_Obj m = ARGM("$map", Map, ctx);
1461
1642
  Expression_Obj v = ARG("$key", Expression);
1462
1643
  try {
1463
- Expression_Obj val = m->at(v); // XXX
1464
- return val ? val.detach() : SASS_MEMORY_NEW(Null, pstate);
1644
+ Expression_Obj val = m->at(v);
1645
+ if (!val) return SASS_MEMORY_NEW(Null, pstate);
1646
+ val->set_delayed(false);
1647
+ return val.detach();
1465
1648
  } catch (const std::out_of_range&) {
1466
1649
  return SASS_MEMORY_NEW(Null, pstate);
1467
1650
  }
@@ -1507,8 +1690,8 @@ namespace Sass {
1507
1690
  size_t len = m1->length() + m2->length();
1508
1691
  Map_Ptr result = SASS_MEMORY_NEW(Map, pstate, len);
1509
1692
  // concat not implemented for maps
1510
- *result += &m1;
1511
- *result += &m2;
1693
+ *result += m1;
1694
+ *result += m2;
1512
1695
  return result;
1513
1696
  }
1514
1697
 
@@ -1522,7 +1705,7 @@ namespace Sass {
1522
1705
  for (auto key : m->keys()) {
1523
1706
  remove = false;
1524
1707
  for (size_t j = 0, K = arglist->length(); j < K && !remove; ++j) {
1525
- remove = Eval::eq(key, arglist->value_at_index(j));
1708
+ remove = Operators::eq(key, arglist->value_at_index(j));
1526
1709
  }
1527
1710
  if (!remove) *result << std::make_pair(key, m->at(key));
1528
1711
  }
@@ -1536,7 +1719,7 @@ namespace Sass {
1536
1719
  Map_Obj result = SASS_MEMORY_NEW(Map, pstate, 1);
1537
1720
  for (size_t i = arglist->size(), L = arglist->length(); i < L; ++i) {
1538
1721
  Expression_Obj obj = arglist->at(i);
1539
- Argument_Obj arg = (Argument_Ptr)&obj;
1722
+ Argument_Obj arg = (Argument_Ptr) obj.ptr(); // XXX
1540
1723
  std::string name = std::string(arg->name());
1541
1724
  name = name.erase(0, 1); // sanitize name (remove dollar sign)
1542
1725
  *result << std::make_pair(SASS_MEMORY_NEW(String_Quoted,
@@ -1559,23 +1742,33 @@ namespace Sass {
1559
1742
 
1560
1743
  Signature unit_sig = "unit($number)";
1561
1744
  BUILT_IN(unit)
1562
- { return SASS_MEMORY_NEW(String_Quoted, pstate, quote(ARG("$number", Number)->unit(), '"')); }
1745
+ {
1746
+ Number_Obj arg = ARGN("$number");
1747
+ std::string str(quote(arg->unit(), '"'));
1748
+ return SASS_MEMORY_NEW(String_Quoted, pstate, str);
1749
+ }
1563
1750
 
1564
1751
  Signature unitless_sig = "unitless($number)";
1565
1752
  BUILT_IN(unitless)
1566
- { return SASS_MEMORY_NEW(Boolean, pstate, ARG("$number", Number)->is_unitless()); }
1753
+ {
1754
+ Number_Obj arg = ARGN("$number");
1755
+ bool unitless = arg->is_unitless();
1756
+ return SASS_MEMORY_NEW(Boolean, pstate, unitless);
1757
+ }
1567
1758
 
1568
1759
  Signature comparable_sig = "comparable($number-1, $number-2)";
1569
1760
  BUILT_IN(comparable)
1570
1761
  {
1571
- Number_Ptr n1 = ARG("$number-1", Number);
1572
- Number_Ptr n2 = ARG("$number-2", Number);
1762
+ Number_Obj n1 = ARGN("$number-1");
1763
+ Number_Obj n2 = ARGN("$number-2");
1573
1764
  if (n1->is_unitless() || n2->is_unitless()) {
1574
1765
  return SASS_MEMORY_NEW(Boolean, pstate, true);
1575
1766
  }
1576
- Number tmp_n2(n2); // copy
1577
- tmp_n2.normalize(n1->find_convertible_unit());
1578
- return SASS_MEMORY_NEW(Boolean, pstate, n1->unit() == tmp_n2.unit());
1767
+ // normalize into main units
1768
+ n1->normalize(); n2->normalize();
1769
+ Units &lhs_unit = *n1, &rhs_unit = *n2;
1770
+ bool is_comparable = (lhs_unit == rhs_unit);
1771
+ return SASS_MEMORY_NEW(Boolean, pstate, is_comparable);
1579
1772
  }
1580
1773
 
1581
1774
  Signature variable_exists_sig = "variable-exists($name)";
@@ -1607,9 +1800,14 @@ namespace Sass {
1607
1800
  Signature function_exists_sig = "function-exists($name)";
1608
1801
  BUILT_IN(function_exists)
1609
1802
  {
1610
- std::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
1803
+ String_Constant_Ptr ss = Cast<String_Constant>(env["$name"]);
1804
+ if (!ss) {
1805
+ error("$name: " + (env["$name"]->to_string()) + " is not a string for `function-exists'", pstate, traces);
1806
+ }
1807
+
1808
+ std::string name = Util::normalize_underscores(unquote(ss->value()));
1611
1809
 
1612
- if(d_env.has_global(s+"[f]")) {
1810
+ if(d_env.has_global(name+"[f]")) {
1613
1811
  return SASS_MEMORY_NEW(Boolean, pstate, true);
1614
1812
  }
1615
1813
  else {
@@ -1646,24 +1844,37 @@ namespace Sass {
1646
1844
  Signature call_sig = "call($name, $args...)";
1647
1845
  BUILT_IN(call)
1648
1846
  {
1649
- std::string name = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
1847
+ std::string name;
1848
+ Function_Ptr ff = Cast<Function>(env["$name"]);
1849
+ String_Constant_Ptr ss = Cast<String_Constant>(env["$name"]);
1850
+
1851
+ if (ss) {
1852
+ name = Util::normalize_underscores(unquote(ss->value()));
1853
+ std::cerr << "DEPRECATION WARNING: ";
1854
+ std::cerr << "Passing a string to call() is deprecated and will be illegal" << std::endl;
1855
+ std::cerr << "in Sass 4.0. Use call(get-function(" + quote(name) + ")) instead." << std::endl;
1856
+ std::cerr << std::endl;
1857
+ } else if (ff) {
1858
+ name = ff->name();
1859
+ }
1860
+
1650
1861
  List_Obj arglist = SASS_MEMORY_COPY(ARG("$args", List));
1651
1862
 
1652
1863
  Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate);
1653
1864
  // std::string full_name(name + "[f]");
1654
- // Definition_Ptr def = d_env.has(full_name) ? static_cast<Definition_Ptr>((d_env)[full_name]) : 0;
1865
+ // Definition_Ptr def = d_env.has(full_name) ? Cast<Definition>((d_env)[full_name]) : 0;
1655
1866
  // Parameters_Ptr params = def ? def->parameters() : 0;
1656
1867
  // size_t param_size = params ? params->length() : 0;
1657
1868
  for (size_t i = 0, L = arglist->length(); i < L; ++i) {
1658
1869
  Expression_Obj expr = arglist->value_at_index(i);
1659
1870
  // if (params && params->has_rest_parameter()) {
1660
1871
  // Parameter_Obj p = param_size > i ? (*params)[i] : 0;
1661
- // List_Ptr list = SASS_MEMORY_CAST(List, expr);
1872
+ // List_Ptr list = Cast<List>(expr);
1662
1873
  // if (list && p && !p->is_rest_parameter()) expr = (*list)[0];
1663
1874
  // }
1664
1875
  if (arglist->is_arglist()) {
1665
1876
  Expression_Obj obj = arglist->at(i);
1666
- Argument_Obj arg = (Argument_Ptr)&obj;
1877
+ Argument_Obj arg = (Argument_Ptr) obj.ptr(); // XXX
1667
1878
  args->append(SASS_MEMORY_NEW(Argument,
1668
1879
  pstate,
1669
1880
  expr,
@@ -1674,11 +1885,11 @@ namespace Sass {
1674
1885
  args->append(SASS_MEMORY_NEW(Argument, pstate, expr));
1675
1886
  }
1676
1887
  }
1677
- Function_Call_Obj func = SASS_MEMORY_NEW(Function_Call, pstate, name, &args);
1678
- Expand expand(ctx, &d_env, backtrace, &selector_stack);
1888
+ Function_Call_Obj func = SASS_MEMORY_NEW(Function_Call, pstate, name, args);
1889
+ Expand expand(ctx, &d_env, &selector_stack);
1679
1890
  func->via_call(true); // calc invoke is allowed
1891
+ if (ff) func->func(ff);
1680
1892
  return func->perform(&expand.eval);
1681
-
1682
1893
  }
1683
1894
 
1684
1895
  ////////////////////
@@ -1696,24 +1907,13 @@ namespace Sass {
1696
1907
  // { return ARG("$condition", Expression)->is_false() ? ARG("$if-false", Expression) : ARG("$if-true", Expression); }
1697
1908
  BUILT_IN(sass_if)
1698
1909
  {
1699
- Expand expand(ctx, &d_env, backtrace, &selector_stack);
1910
+ Expand expand(ctx, &d_env, &selector_stack);
1700
1911
  Expression_Obj cond = ARG("$condition", Expression)->perform(&expand.eval);
1701
1912
  bool is_true = !cond->is_false();
1702
- Expression_Ptr res = ARG(is_true ? "$if-true" : "$if-false", Expression);
1913
+ Expression_Obj res = ARG(is_true ? "$if-true" : "$if-false", Expression);
1703
1914
  res = res->perform(&expand.eval);
1704
1915
  res->set_delayed(false); // clone?
1705
- return res;
1706
- }
1707
-
1708
- ////////////////
1709
- // URL FUNCTIONS
1710
- ////////////////
1711
-
1712
- Signature image_url_sig = "image-url($path, $only-path: false, $cache-buster: false)";
1713
- BUILT_IN(image_url)
1714
- {
1715
- error("`image_url` has been removed from libsass because it's not part of the Sass spec", pstate);
1716
- return 0; // suppress warning, error will exit anyway
1916
+ return res.detach();
1717
1917
  }
1718
1918
 
1719
1919
  //////////////////////////
@@ -1754,24 +1954,24 @@ namespace Sass {
1754
1954
 
1755
1955
  // Not enough parameters
1756
1956
  if( arglist->length() == 0 )
1757
- error("$selectors: At least one selector must be passed for `selector-nest'", pstate);
1957
+ error("$selectors: At least one selector must be passed for `selector-nest'", pstate, traces);
1758
1958
 
1759
1959
  // Parse args into vector of selectors
1760
1960
  std::vector<Selector_List_Obj> parsedSelectors;
1761
1961
  for (size_t i = 0, L = arglist->length(); i < L; ++i) {
1762
- Expression_Obj exp = SASS_MEMORY_CAST(Expression, arglist->value_at_index(i));
1962
+ Expression_Obj exp = Cast<Expression>(arglist->value_at_index(i));
1763
1963
  if (exp->concrete_type() == Expression::NULL_VAL) {
1764
1964
  std::stringstream msg;
1765
1965
  msg << "$selectors: null is not a valid selector: it must be a string,\n";
1766
1966
  msg << "a list of strings, or a list of lists of strings for 'selector-nest'";
1767
- error(msg.str(), pstate);
1967
+ error(msg.str(), pstate, traces);
1768
1968
  }
1769
- if (String_Constant_Obj str = SASS_MEMORY_CAST(String_Constant, exp)) {
1969
+ if (String_Constant_Obj str = Cast<String_Constant>(exp)) {
1770
1970
  str->quote_mark(0);
1771
1971
  }
1772
- std::string exp_src = exp->to_string(ctx.c_options) + "{";
1773
- Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx);
1774
- parsedSelectors.push_back(&sel);
1972
+ std::string exp_src = exp->to_string(ctx.c_options);
1973
+ Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces);
1974
+ parsedSelectors.push_back(sel);
1775
1975
  }
1776
1976
 
1777
1977
  // Nothing to do
@@ -1787,8 +1987,8 @@ namespace Sass {
1787
1987
  for(;itr != parsedSelectors.end(); ++itr) {
1788
1988
  Selector_List_Obj child = *itr;
1789
1989
  std::vector<Complex_Selector_Obj> exploded;
1790
- selector_stack.push_back(&result);
1791
- Selector_List_Obj rv = child->resolve_parent_refs(ctx, selector_stack);
1990
+ selector_stack.push_back(result);
1991
+ Selector_List_Obj rv = child->resolve_parent_refs(selector_stack, traces);
1792
1992
  selector_stack.pop_back();
1793
1993
  for (size_t m = 0, mLen = rv->length(); m < mLen; ++m) {
1794
1994
  exploded.push_back((*rv)[m]);
@@ -1807,24 +2007,24 @@ namespace Sass {
1807
2007
 
1808
2008
  // Not enough parameters
1809
2009
  if( arglist->length() == 0 )
1810
- error("$selectors: At least one selector must be passed for `selector-append'", pstate);
2010
+ error("$selectors: At least one selector must be passed for `selector-append'", pstate, traces);
1811
2011
 
1812
2012
  // Parse args into vector of selectors
1813
2013
  std::vector<Selector_List_Obj> parsedSelectors;
1814
2014
  for (size_t i = 0, L = arglist->length(); i < L; ++i) {
1815
- Expression_Obj exp = SASS_MEMORY_CAST(Expression, arglist->value_at_index(i));
2015
+ Expression_Obj exp = Cast<Expression>(arglist->value_at_index(i));
1816
2016
  if (exp->concrete_type() == Expression::NULL_VAL) {
1817
2017
  std::stringstream msg;
1818
2018
  msg << "$selectors: null is not a valid selector: it must be a string,\n";
1819
2019
  msg << "a list of strings, or a list of lists of strings for 'selector-append'";
1820
- error(msg.str(), pstate);
2020
+ error(msg.str(), pstate, traces);
1821
2021
  }
1822
- if (String_Constant_Ptr str = SASS_MEMORY_CAST(String_Constant, exp)) {
2022
+ if (String_Constant_Ptr str = Cast<String_Constant>(exp)) {
1823
2023
  str->quote_mark(0);
1824
2024
  }
1825
- std::string exp_src = exp->to_string() + "{";
1826
- Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx);
1827
- parsedSelectors.push_back(&sel);
2025
+ std::string exp_src = exp->to_string();
2026
+ Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces);
2027
+ parsedSelectors.push_back(sel);
1828
2028
  }
1829
2029
 
1830
2030
  // Nothing to do
@@ -1861,29 +2061,29 @@ namespace Sass {
1861
2061
  msg += "\" to \"";
1862
2062
  msg += parentSeqClone->to_string();
1863
2063
  msg += "\" for `selector-append'";
1864
- error(msg, pstate, backtrace);
2064
+ error(msg, pstate, traces);
1865
2065
  }
1866
2066
 
1867
2067
  // Cannot be a Universal selector
1868
- Element_Selector_Obj pType = SASS_MEMORY_CAST(Element_Selector, childSeq->head()->first());
2068
+ Element_Selector_Obj pType = Cast<Element_Selector>(childSeq->head()->first());
1869
2069
  if(pType && pType->name() == "*") {
1870
2070
  std::string msg("Can't append \"");
1871
2071
  msg += childSeq->to_string();
1872
2072
  msg += "\" to \"";
1873
2073
  msg += parentSeqClone->to_string();
1874
2074
  msg += "\" for `selector-append'";
1875
- error(msg, pstate, backtrace);
2075
+ error(msg, pstate, traces);
1876
2076
  }
1877
2077
 
1878
2078
  // TODO: Add check for namespace stuff
1879
2079
 
1880
2080
  // append any selectors in childSeq's head
1881
- parentSeqClone->innermost()->head()->concat(&base->head());
2081
+ parentSeqClone->innermost()->head()->concat(base->head());
1882
2082
 
1883
2083
  // Set parentSeqClone new tail
1884
2084
  parentSeqClone->innermost()->tail( base->tail() );
1885
2085
 
1886
- newElements.push_back(&parentSeqClone);
2086
+ newElements.push_back(parentSeqClone);
1887
2087
  }
1888
2088
  }
1889
2089
 
@@ -1900,7 +2100,7 @@ namespace Sass {
1900
2100
  Selector_List_Obj selector1 = ARGSEL("$selector1", Selector_List_Obj, p_contextualize);
1901
2101
  Selector_List_Obj selector2 = ARGSEL("$selector2", Selector_List_Obj, p_contextualize);
1902
2102
 
1903
- Selector_List_Obj result = selector1->unify_with(&selector2, ctx);
2103
+ Selector_List_Obj result = selector1->unify_with(selector2);
1904
2104
  Listize listize;
1905
2105
  return result->perform(&listize);
1906
2106
  }
@@ -1930,9 +2130,10 @@ namespace Sass {
1930
2130
  Selector_List_Obj extender = ARGSEL("$extender", Selector_List_Obj, p_contextualize);
1931
2131
 
1932
2132
  Subset_Map subset_map;
1933
- extender->populate_extends(extendee, ctx, subset_map);
2133
+ extender->populate_extends(extendee, subset_map);
2134
+ Extend extend(subset_map);
1934
2135
 
1935
- Selector_List_Obj result = Extend::extendSelectorList(selector, ctx, subset_map, false);
2136
+ Selector_List_Obj result = extend.extendSelectorList(selector, false);
1936
2137
 
1937
2138
  Listize listize;
1938
2139
  return result->perform(&listize);
@@ -1945,9 +2146,10 @@ namespace Sass {
1945
2146
  Selector_List_Obj original = ARGSEL("$original", Selector_List_Obj, p_contextualize);
1946
2147
  Selector_List_Obj replacement = ARGSEL("$replacement", Selector_List_Obj, p_contextualize);
1947
2148
  Subset_Map subset_map;
1948
- replacement->populate_extends(original, ctx, subset_map);
2149
+ replacement->populate_extends(original, subset_map);
2150
+ Extend extend(subset_map);
1949
2151
 
1950
- Selector_List_Obj result = Extend::extendSelectorList(selector, ctx, subset_map, true);
2152
+ Selector_List_Obj result = extend.extendSelectorList(selector, true);
1951
2153
 
1952
2154
  Listize listize;
1953
2155
  return result->perform(&listize);
@@ -1981,5 +2183,52 @@ namespace Sass {
1981
2183
  return SASS_MEMORY_NEW(String_Quoted, pstate, ss.str());
1982
2184
  }
1983
2185
 
2186
+ Signature is_bracketed_sig = "is-bracketed($list)";
2187
+ BUILT_IN(is_bracketed)
2188
+ {
2189
+ Value_Obj value = ARG("$list", Value);
2190
+ List_Obj list = Cast<List>(value);
2191
+ return SASS_MEMORY_NEW(Boolean, pstate, list && list->is_bracketed());
2192
+ }
2193
+
2194
+ Signature content_exists_sig = "content-exists()";
2195
+ BUILT_IN(content_exists)
2196
+ {
2197
+ if (!d_env.has_global("is_in_mixin")) {
2198
+ error("Cannot call content-exists() except within a mixin.", pstate, traces);
2199
+ }
2200
+ return SASS_MEMORY_NEW(Boolean, pstate, d_env.has_lexical("@content[m]"));
2201
+ }
2202
+
2203
+ Signature get_function_sig = "get-function($name, $css: false)";
2204
+ BUILT_IN(get_function)
2205
+ {
2206
+ String_Constant_Ptr ss = Cast<String_Constant>(env["$name"]);
2207
+ if (!ss) {
2208
+ error("$name: " + (env["$name"]->to_string()) + " is not a string for `get-function'", pstate, traces);
2209
+ }
2210
+
2211
+ std::string name = Util::normalize_underscores(unquote(ss->value()));
2212
+ std::string full_name = name + "[f]";
2213
+
2214
+ Boolean_Obj css = ARG("$css", Boolean);
2215
+ if (!css->is_false()) {
2216
+ Definition_Ptr def = SASS_MEMORY_NEW(Definition,
2217
+ pstate,
2218
+ name,
2219
+ SASS_MEMORY_NEW(Parameters, pstate),
2220
+ SASS_MEMORY_NEW(Block, pstate, 0, false),
2221
+ Definition::FUNCTION);
2222
+ return SASS_MEMORY_NEW(Function, pstate, def, true);
2223
+ }
2224
+
2225
+
2226
+ if (!d_env.has_global(full_name)) {
2227
+ error("Function not found: " + name, pstate, traces);
2228
+ }
2229
+
2230
+ Definition_Ptr def = Cast<Definition>(d_env[full_name]);
2231
+ return SASS_MEMORY_NEW(Function, pstate, def, false);
2232
+ }
1984
2233
  }
1985
2234
  }