sassc 1.11.4 → 1.12.0

Sign up to get free protection for your applications and to get access to all the features.
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
  }