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
@@ -19,12 +19,21 @@ class LocalOption {
19
19
  this->orig = var;
20
20
  *(this->var) = orig;
21
21
  }
22
+ void reset()
23
+ {
24
+ *(this->var) = this->orig;
25
+ }
22
26
  ~LocalOption() {
23
27
  *(this->var) = this->orig;
24
28
  }
25
29
  };
26
30
 
27
31
  #define LOCAL_FLAG(name,opt) LocalOption<bool> flag_##name(name, opt)
32
+ #define LOCAL_COUNT(name,opt) LocalOption<size_t> cnt_##name(name, opt)
33
+
34
+ #define NESTING_GUARD(name) \
35
+ LocalOption<size_t> cnt_##name(name, name + 1); \
36
+ if (name > MAX_NESTING) throw Exception::NestingLimitError(pstate, traces); \
28
37
 
29
38
  #define ATTACH_OPERATIONS()\
30
39
  virtual void perform(Operation<void>* op) { (*op)(this); }\
@@ -44,7 +53,7 @@ public:\
44
53
  type name(type name##__) { return name##_ = name##__; }\
45
54
  private:
46
55
 
47
- #define ADD_HASHED(type, name)\
56
+ #define HASH_PROPERTY(type, name)\
48
57
  protected:\
49
58
  type name##_;\
50
59
  public:\
@@ -52,4 +61,20 @@ public:\
52
61
  type name(type name##__) { hash_ = 0; return name##_ = name##__; }\
53
62
  private:
54
63
 
64
+ #define ADD_CONSTREF(type, name) \
65
+ protected: \
66
+ type name##_; \
67
+ public: \
68
+ const type& name() const { return name##_; } \
69
+ void name(type name##__) { name##_ = name##__; } \
70
+ private:
71
+
72
+ #define HASH_CONSTREF(type, name) \
73
+ protected: \
74
+ type name##_; \
75
+ public: \
76
+ const type& name() const { return name##_; } \
77
+ void name(type name##__) { hash_ = 0; name##_ = name##__; } \
78
+ private:
79
+
55
80
  #endif
@@ -0,0 +1,29 @@
1
+ #include "ast.hpp"
2
+
3
+ namespace Sass {
4
+
5
+ #define IMPLEMENT_BASE_CAST(T) \
6
+ template<> \
7
+ T* Cast(AST_Node* ptr) { \
8
+ return dynamic_cast<T*>(ptr); \
9
+ }; \
10
+ \
11
+ template<> \
12
+ const T* Cast(const AST_Node* ptr) { \
13
+ return dynamic_cast<const T*>(ptr); \
14
+ }; \
15
+
16
+ IMPLEMENT_BASE_CAST(AST_Node)
17
+ IMPLEMENT_BASE_CAST(Expression)
18
+ IMPLEMENT_BASE_CAST(Statement)
19
+ IMPLEMENT_BASE_CAST(Has_Block)
20
+ IMPLEMENT_BASE_CAST(PreValue)
21
+ IMPLEMENT_BASE_CAST(Value)
22
+ IMPLEMENT_BASE_CAST(List)
23
+ IMPLEMENT_BASE_CAST(String)
24
+ IMPLEMENT_BASE_CAST(String_Constant)
25
+ IMPLEMENT_BASE_CAST(Supports_Condition)
26
+ IMPLEMENT_BASE_CAST(Selector)
27
+ IMPLEMENT_BASE_CAST(Simple_Selector)
28
+
29
+ }
@@ -1,12 +1,17 @@
1
1
  #ifndef SASS_AST_FWD_DECL_H
2
2
  #define SASS_AST_FWD_DECL_H
3
3
 
4
+ #include <map>
5
+ #include <set>
6
+ #include <deque>
4
7
  #include <vector>
8
+ #include <typeinfo>
5
9
  #include <iostream>
6
10
  #include <algorithm>
7
11
  #include <unordered_map>
8
12
  #include <unordered_set>
9
13
  #include "memory/SharedPtr.hpp"
14
+ #include "sass/functions.h"
10
15
 
11
16
  /////////////////////////////////////////////
12
17
  // Forward declarations for the AST visitors.
@@ -128,6 +133,9 @@ namespace Sass {
128
133
  class Map;
129
134
  typedef Map* Map_Ptr;
130
135
  typedef Map const* Map_Ptr_Const;
136
+ class Function;
137
+ typedef Function* Function_Ptr;
138
+ typedef Function const* Function_Ptr_Const;
131
139
 
132
140
  class Mixin_Call;
133
141
  typedef Mixin_Call* Mixin_Call_Ptr;
@@ -154,9 +162,6 @@ namespace Sass {
154
162
  class Variable;
155
163
  typedef Variable* Variable_Ptr;
156
164
  typedef Variable const* Variable_Ptr_Const;
157
- class Textual;
158
- typedef Textual* Textual_Ptr;
159
- typedef Textual const* Textual_Ptr_Const;
160
165
  class Number;
161
166
  typedef Number* Number_Ptr;
162
167
  typedef Number const* Number_Ptr_Const;
@@ -310,6 +315,7 @@ namespace Sass {
310
315
  IMPL_MEM_OBJ(Expression);
311
316
  IMPL_MEM_OBJ(List);
312
317
  IMPL_MEM_OBJ(Map);
318
+ IMPL_MEM_OBJ(Function);
313
319
  IMPL_MEM_OBJ(Binary_Expression);
314
320
  IMPL_MEM_OBJ(Unary_Expression);
315
321
  IMPL_MEM_OBJ(Function_Call);
@@ -317,7 +323,6 @@ namespace Sass {
317
323
  IMPL_MEM_OBJ(Custom_Warning);
318
324
  IMPL_MEM_OBJ(Custom_Error);
319
325
  IMPL_MEM_OBJ(Variable);
320
- IMPL_MEM_OBJ(Textual);
321
326
  IMPL_MEM_OBJ(Number);
322
327
  IMPL_MEM_OBJ(Color);
323
328
  IMPL_MEM_OBJ(Boolean);
@@ -353,37 +358,105 @@ namespace Sass {
353
358
  IMPL_MEM_OBJ(Complex_Selector);
354
359
  IMPL_MEM_OBJ(Selector_List);
355
360
 
361
+ // ###########################################################################
362
+ // Implement compare, order and hashing operations for AST Nodes
363
+ // ###########################################################################
356
364
 
357
- struct HashExpression {
358
- size_t operator() (Expression_Obj ex) const;
365
+ struct HashNodes {
366
+ template <class T>
367
+ size_t operator() (const T& ex) const {
368
+ return ex.isNull() ? 0 : ex->hash();
369
+ }
359
370
  };
360
- struct CompareExpression {
361
- bool operator()(const Expression_Obj& lhs, const Expression_Obj& rhs) const;
371
+ struct OrderNodes {
372
+ template <class T>
373
+ bool operator() (const T& lhs, const T& rhs) const {
374
+ return !lhs.isNull() && !rhs.isNull() && *lhs < *rhs;
375
+ }
362
376
  };
363
-
364
- struct HashSimpleSelector {
365
- size_t operator() (Simple_Selector_Obj ex) const;
377
+ struct CompareNodes {
378
+ template <class T>
379
+ bool operator() (const T& lhs, const T& rhs) const {
380
+ // code around sass logic issue. 1px == 1 is true
381
+ // but both items are still different keys in maps
382
+ if (dynamic_cast<Number*>(lhs.ptr()))
383
+ if (dynamic_cast<Number*>(rhs.ptr()))
384
+ return lhs->hash() == rhs->hash();
385
+ return !lhs.isNull() && !rhs.isNull() && *lhs == *rhs;
386
+ }
366
387
  };
367
388
 
368
- struct CompareSimpleSelector {
369
- bool operator()(Simple_Selector_Obj lhs, Simple_Selector_Obj rhs) const;
370
- };
389
+ // ###########################################################################
390
+ // some often used typedefs
391
+ // ###########################################################################
371
392
 
372
393
  typedef std::unordered_map<
373
394
  Expression_Obj, // key
374
395
  Expression_Obj, // value
375
- HashExpression, // hasher
376
- CompareExpression // compare
396
+ HashNodes, // hasher
397
+ CompareNodes // compare
377
398
  > ExpressionMap;
378
399
  typedef std::unordered_set<
379
400
  Expression_Obj, // value
380
- HashExpression, // hasher
381
- CompareExpression // compare
401
+ HashNodes, // hasher
402
+ CompareNodes // compare
382
403
  > ExpressionSet;
383
404
 
384
- typedef std::string Subset_Map_Key;
385
- typedef std::vector<size_t> Subset_Map_Arr;
386
- typedef std::pair<Complex_Selector_Obj, Compound_Selector_Obj> Subset_Map_Val;
405
+ typedef std::string SubSetMapKey;
406
+ typedef std::vector<std::string> SubSetMapKeys;
407
+
408
+ typedef std::pair<Complex_Selector_Obj, Compound_Selector_Obj> SubSetMapPair;
409
+ typedef std::pair<Compound_Selector_Obj, Complex_Selector_Obj> SubSetMapLookup;
410
+ typedef std::vector<SubSetMapPair> SubSetMapPairs;
411
+ typedef std::vector<SubSetMapLookup> SubSetMapLookups;
412
+
413
+ typedef std::pair<Complex_Selector_Obj, SubSetMapPairs> SubSetMapResult;
414
+ typedef std::vector<SubSetMapResult> SubSetMapResults;
415
+
416
+ typedef std::deque<Complex_Selector_Obj> ComplexSelectorDeque;
417
+ typedef std::set<Simple_Selector_Obj, OrderNodes> SimpleSelectorSet;
418
+ typedef std::set<Complex_Selector_Obj, OrderNodes> ComplexSelectorSet;
419
+ typedef std::set<Compound_Selector_Obj, OrderNodes> CompoundSelectorSet;
420
+ typedef std::unordered_set<Simple_Selector_Obj, HashNodes, CompareNodes> SimpleSelectorDict;
421
+
422
+ typedef std::vector<Sass_Import_Entry>* ImporterStack;
423
+
424
+ // only to switch implementations for testing
425
+ #define environment_map std::map
426
+
427
+ // ###########################################################################
428
+ // explicit type conversion functions
429
+ // ###########################################################################
430
+
431
+ template<class T>
432
+ T* Cast(AST_Node* ptr);
433
+
434
+ template<class T>
435
+ const T* Cast(const AST_Node* ptr);
436
+
437
+ // sometimes you know the class you want to cast to is final
438
+ // in this case a simple typeid check is faster and safe to use
439
+
440
+ #define DECLARE_BASE_CAST(T) \
441
+ template<> T* Cast(AST_Node* ptr); \
442
+ template<> const T* Cast(const AST_Node* ptr); \
443
+
444
+ // ###########################################################################
445
+ // implement specialization for final classes
446
+ // ###########################################################################
447
+
448
+ DECLARE_BASE_CAST(AST_Node)
449
+ DECLARE_BASE_CAST(Expression)
450
+ DECLARE_BASE_CAST(Statement)
451
+ DECLARE_BASE_CAST(Has_Block)
452
+ DECLARE_BASE_CAST(PreValue)
453
+ DECLARE_BASE_CAST(Value)
454
+ DECLARE_BASE_CAST(List)
455
+ DECLARE_BASE_CAST(String)
456
+ DECLARE_BASE_CAST(String_Constant)
457
+ DECLARE_BASE_CAST(Supports_Condition)
458
+ DECLARE_BASE_CAST(Selector)
459
+ DECLARE_BASE_CAST(Simple_Selector)
387
460
 
388
461
  }
389
462
 
@@ -24,7 +24,9 @@ namespace base64
24
24
 
25
25
  encoder(int buffersize_in = BUFFERSIZE)
26
26
  : _buffersize(buffersize_in)
27
- {}
27
+ {
28
+ base64_init_encodestate(&_state);
29
+ }
28
30
 
29
31
  int encode(char value_in)
30
32
  {
@@ -0,0 +1,46 @@
1
+ #include "backtrace.hpp"
2
+
3
+ namespace Sass {
4
+
5
+ const std::string traces_to_string(Backtraces traces, std::string indent) {
6
+
7
+ std::stringstream ss;
8
+ std::string cwd(File::get_cwd());
9
+
10
+ bool first = true;
11
+ size_t i_beg = traces.size() - 1;
12
+ size_t i_end = std::string::npos;
13
+ for (size_t i = i_beg; i != i_end; i --) {
14
+
15
+ const Backtrace& trace = traces[i];
16
+
17
+ // make path relative to the current directory
18
+ std::string rel_path(File::abs2rel(trace.pstate.path, cwd, cwd));
19
+
20
+ // skip functions on error cases (unsure why ruby sass does this)
21
+ // if (trace.caller.substr(0, 6) == ", in f") continue;
22
+
23
+ if (first) {
24
+ ss << indent;
25
+ ss << "on line ";
26
+ ss << trace.pstate.line + 1;
27
+ ss << " of " << rel_path;
28
+ // ss << trace.caller;
29
+ first = false;
30
+ } else {
31
+ ss << trace.caller;
32
+ ss << std::endl;
33
+ ss << indent;
34
+ ss << "from line ";
35
+ ss << trace.pstate.line + 1;
36
+ ss << " of " << rel_path;
37
+ }
38
+
39
+ }
40
+
41
+ ss << std::endl;
42
+ return ss.str();
43
+
44
+ }
45
+
46
+ };
@@ -1,75 +1,28 @@
1
1
  #ifndef SASS_BACKTRACE_H
2
2
  #define SASS_BACKTRACE_H
3
3
 
4
+ #include <vector>
4
5
  #include <sstream>
5
-
6
6
  #include "file.hpp"
7
7
  #include "position.hpp"
8
8
 
9
9
  namespace Sass {
10
10
 
11
-
12
11
  struct Backtrace {
13
12
 
14
- Backtrace* parent;
15
13
  ParserState pstate;
16
- std::string caller;
14
+ std::string caller;
17
15
 
18
- Backtrace(Backtrace* prn, ParserState pstate, std::string c)
19
- : parent(prn),
20
- pstate(pstate),
16
+ Backtrace(ParserState pstate, std::string c = "")
17
+ : pstate(pstate),
21
18
  caller(c)
22
19
  { }
23
20
 
24
- std::string to_string(bool warning = false)
25
- {
26
- size_t i = -1;
27
- std::stringstream ss;
28
- std::string cwd(Sass::File::get_cwd());
29
- Backtrace* this_point = this;
30
-
31
- if (!warning) ss << std::endl << "Backtrace:";
32
- // the first tracepoint (which is parent-less) is an empty placeholder
33
- while (this_point->parent) {
34
-
35
- // make path relative to the current directory
36
- std::string rel_path(Sass::File::abs2rel(this_point->pstate.path, cwd, cwd));
37
-
38
- if (warning) {
39
- ss << std::endl
40
- << "\t"
41
- << (++i == 0 ? "on" : "from")
42
- << " line "
43
- << this_point->pstate.line + 1
44
- << " of "
45
- << rel_path;
46
- } else {
47
- ss << std::endl
48
- << "\t"
49
- << rel_path
50
- << ":"
51
- << this_point->pstate.line + 1
52
- << this_point->parent->caller;
53
- }
54
-
55
- this_point = this_point->parent;
56
- }
57
-
58
- return ss.str();
59
- }
21
+ };
60
22
 
61
- size_t depth()
62
- {
63
- size_t d = 0;
64
- Backtrace* p = parent;
65
- while (p) {
66
- ++d;
67
- p = p->parent;
68
- }
69
- return d-1;
70
- }
23
+ typedef std::vector<Backtrace> Backtraces;
71
24
 
72
- };
25
+ const std::string traces_to_string(Backtraces traces, std::string indent = "\t");
73
26
 
74
27
  }
75
28
 
@@ -2,6 +2,7 @@
2
2
  #include "bind.hpp"
3
3
  #include "ast.hpp"
4
4
  #include "context.hpp"
5
+ #include "expand.hpp"
5
6
  #include "eval.hpp"
6
7
  #include <map>
7
8
  #include <iostream>
@@ -14,9 +15,11 @@ namespace Sass {
14
15
  std::string callee(type + " " + name);
15
16
 
16
17
  std::map<std::string, Parameter_Obj> param_map;
18
+ List_Obj varargs = SASS_MEMORY_NEW(List, as->pstate());
19
+ varargs->is_arglist(true); // enable keyword size handling
17
20
 
18
21
  for (size_t i = 0, L = as->length(); i < L; ++i) {
19
- if (auto str = SASS_MEMORY_CAST(String_Quoted, (*as)[i]->value())) {
22
+ if (auto str = Cast<String_Quoted>((*as)[i]->value())) {
20
23
  // force optional quotes (only if needed)
21
24
  if (str->quote_mark()) {
22
25
  str->quote_mark('*');
@@ -42,7 +45,7 @@ namespace Sass {
42
45
  if (ip >= LP) {
43
46
  // skip empty rest arguments
44
47
  if (a->is_rest_argument()) {
45
- if (List_Obj l = SASS_MEMORY_CAST(List, a->value())) {
48
+ if (List_Obj l = Cast<List>(a->value())) {
46
49
  if (l->length() == 0) {
47
50
  ++ ia; continue;
48
51
  }
@@ -51,7 +54,7 @@ namespace Sass {
51
54
  std::stringstream msg;
52
55
  msg << "wrong number of arguments (" << LA << " for " << LP << ")";
53
56
  msg << " for `" << name << "'";
54
- return error(msg.str(), as->pstate());
57
+ return error(msg.str(), as->pstate(), eval->exp.traces);
55
58
  }
56
59
  Parameter_Obj p = ps->at(ip);
57
60
 
@@ -61,7 +64,7 @@ namespace Sass {
61
64
  if (a->is_rest_argument()) {
62
65
 
63
66
  // We should always get a list for rest arguments
64
- if (List_Obj rest = SASS_MEMORY_CAST(List, a->value())) {
67
+ if (List_Obj rest = Cast<List>(a->value())) {
65
68
  // create a new list object for wrapped items
66
69
  List_Ptr arglist = SASS_MEMORY_NEW(List,
67
70
  p->pstate(),
@@ -70,12 +73,12 @@ namespace Sass {
70
73
  true);
71
74
  // wrap each item from list as an argument
72
75
  for (Expression_Obj item : rest->elements()) {
73
- if (Argument_Obj arg = SASS_MEMORY_CAST(Argument, item)) {
76
+ if (Argument_Obj arg = Cast<Argument>(item)) {
74
77
  arglist->append(SASS_MEMORY_COPY(arg)); // copy
75
78
  } else {
76
79
  arglist->append(SASS_MEMORY_NEW(Argument,
77
80
  item->pstate(),
78
- &item,
81
+ item,
79
82
  "",
80
83
  false,
81
84
  false));
@@ -93,15 +96,20 @@ namespace Sass {
93
96
  // expand keyword arguments into their parameters
94
97
  List_Ptr arglist = SASS_MEMORY_NEW(List, p->pstate(), 0, SASS_COMMA, true);
95
98
  env->local_frame()[p->name()] = arglist;
96
- Map_Obj argmap = SASS_MEMORY_CAST(Map, a->value());
99
+ Map_Obj argmap = Cast<Map>(a->value());
97
100
  for (auto key : argmap->keys()) {
98
- std::string name = unquote(SASS_MEMORY_CAST(String_Constant, key)->value());
99
- arglist->append(SASS_MEMORY_NEW(Argument,
100
- key->pstate(),
101
- argmap->at(key),
102
- "$" + name,
103
- false,
104
- false));
101
+ if (String_Constant_Obj str = Cast<String_Constant>(key)) {
102
+ std::string param = unquote(str->value());
103
+ arglist->append(SASS_MEMORY_NEW(Argument,
104
+ key->pstate(),
105
+ argmap->at(key),
106
+ "$" + param,
107
+ false,
108
+ false));
109
+ } else {
110
+ eval->exp.traces.push_back(Backtrace(key->pstate()));
111
+ throw Exception::InvalidVarKwdType(key->pstate(), eval->exp.traces, key->inspect(), a);
112
+ }
105
113
  }
106
114
 
107
115
  } else {
@@ -117,25 +125,25 @@ namespace Sass {
117
125
  // get and post inc
118
126
  a = (*as)[ia++];
119
127
  // maybe we have another list as argument
120
- List_Obj ls = SASS_MEMORY_CAST(List, a->value());
128
+ List_Obj ls = Cast<List>(a->value());
121
129
  // skip any list completely if empty
122
130
  if (ls && ls->empty() && a->is_rest_argument()) continue;
123
131
 
124
132
  Expression_Obj value = a->value();
125
- if (Argument_Obj arg = SASS_MEMORY_CAST(Argument, value)) {
126
- arglist->append(&arg);
133
+ if (Argument_Obj arg = Cast<Argument>(value)) {
134
+ arglist->append(arg);
127
135
  }
128
136
  // check if we have rest argument
129
137
  else if (a->is_rest_argument()) {
130
138
  // preserve the list separator from rest args
131
- if (List_Obj rest = SASS_MEMORY_CAST(List, a->value())) {
139
+ if (List_Obj rest = Cast<List>(a->value())) {
132
140
  arglist->separator(rest->separator());
133
141
 
134
- for (size_t i = 0, L = rest->size(); i < L; ++i) {
135
- Expression_Obj obj = rest->at(i);
142
+ for (size_t i = 0, L = rest->length(); i < L; ++i) {
143
+ Expression_Obj obj = rest->value_at_index(i);
136
144
  arglist->append(SASS_MEMORY_NEW(Argument,
137
145
  obj->pstate(),
138
- &obj,
146
+ obj,
139
147
  "",
140
148
  false,
141
149
  false));
@@ -155,7 +163,7 @@ namespace Sass {
155
163
  }
156
164
  }
157
165
  // assign new arglist to environment
158
- env->local_frame()[p->name()] = &arglist;
166
+ env->local_frame()[p->name()] = arglist;
159
167
  }
160
168
  // consumed parameter
161
169
  ++ip;
@@ -166,9 +174,16 @@ namespace Sass {
166
174
  // If the current argument is the rest argument, extract a value for processing
167
175
  else if (a->is_rest_argument()) {
168
176
  // normal param and rest arg
169
- List_Obj arglist = SASS_MEMORY_CAST(List, a->value());
177
+ List_Obj arglist = Cast<List>(a->value());
178
+ if (!arglist) {
179
+ if (Expression_Obj arg = Cast<Expression>(a->value())) {
180
+ arglist = SASS_MEMORY_NEW(List, a->pstate(), 1);
181
+ arglist->append(arg);
182
+ }
183
+ }
184
+
170
185
  // empty rest arg - treat all args as default values
171
- if (!arglist->length()) {
186
+ if (!arglist || !arglist->length()) {
172
187
  break;
173
188
  } else {
174
189
  if (arglist->length() > LP - ip && !ps->has_rest_parameter()) {
@@ -187,8 +202,8 @@ namespace Sass {
187
202
  }
188
203
  // otherwise move one of the rest args into the param, converting to argument if necessary
189
204
  Expression_Obj obj = arglist->at(0);
190
- if (!(a = SASS_MEMORY_CAST(Argument, obj))) {
191
- Expression_Ptr a_to_convert = &obj;
205
+ if (!(a = Cast<Argument>(obj))) {
206
+ Expression_Ptr a_to_convert = obj;
192
207
  a = SASS_MEMORY_NEW(Argument,
193
208
  a_to_convert->pstate(),
194
209
  a_to_convert,
@@ -202,17 +217,22 @@ namespace Sass {
202
217
  }
203
218
 
204
219
  } else if (a->is_keyword_argument()) {
205
- Map_Obj argmap = SASS_MEMORY_CAST(Map, a->value());
220
+ Map_Obj argmap = Cast<Map>(a->value());
206
221
 
207
222
  for (auto key : argmap->keys()) {
208
- std::string name = "$" + unquote(SASS_MEMORY_CAST(String_Constant, key)->value());
223
+ String_Constant_Ptr val = Cast<String_Constant>(key);
224
+ if (val == NULL) {
225
+ eval->exp.traces.push_back(Backtrace(key->pstate()));
226
+ throw Exception::InvalidVarKwdType(key->pstate(), eval->exp.traces, key->inspect(), a);
227
+ }
228
+ std::string param = "$" + unquote(val->value());
209
229
 
210
- if (!param_map.count(name)) {
230
+ if (!param_map.count(param)) {
211
231
  std::stringstream msg;
212
- msg << callee << " has no parameter named " << name;
213
- error(msg.str(), a->pstate());
232
+ msg << callee << " has no parameter named " << param;
233
+ error(msg.str(), a->pstate(), eval->exp.traces);
214
234
  }
215
- env->local_frame()[name] = &argmap->at(&key);
235
+ env->local_frame()[param] = argmap->at(key);
216
236
  }
217
237
  ++ia;
218
238
  continue;
@@ -225,32 +245,38 @@ namespace Sass {
225
245
  std::stringstream msg;
226
246
  msg << "parameter " << p->name()
227
247
  << " provided more than once in call to " << callee;
228
- error(msg.str(), a->pstate());
248
+ error(msg.str(), a->pstate(), eval->exp.traces);
229
249
  }
230
250
  // ordinal arg -- bind it to the next param
231
- env->local_frame()[p->name()] = &a->value();
251
+ env->local_frame()[p->name()] = a->value();
232
252
  ++ip;
233
253
  }
234
254
  else {
235
255
  // named arg -- bind it to the appropriately named param
236
256
  if (!param_map.count(a->name())) {
237
- std::stringstream msg;
238
- msg << callee << " has no parameter named " << a->name();
239
- error(msg.str(), a->pstate());
257
+ if (ps->has_rest_parameter()) {
258
+ varargs->append(a);
259
+ } else {
260
+ std::stringstream msg;
261
+ msg << callee << " has no parameter named " << a->name();
262
+ error(msg.str(), a->pstate(), eval->exp.traces);
263
+ }
240
264
  }
241
- if (param_map[a->name()]->is_rest_parameter()) {
242
- std::stringstream msg;
243
- msg << "argument " << a->name() << " of " << callee
244
- << "cannot be used as named argument";
245
- error(msg.str(), a->pstate());
265
+ if (param_map[a->name()]) {
266
+ if (param_map[a->name()]->is_rest_parameter()) {
267
+ std::stringstream msg;
268
+ msg << "argument " << a->name() << " of " << callee
269
+ << "cannot be used as named argument";
270
+ error(msg.str(), a->pstate(), eval->exp.traces);
271
+ }
246
272
  }
247
273
  if (env->has_local(a->name())) {
248
274
  std::stringstream msg;
249
275
  msg << "parameter " << p->name()
250
276
  << "provided more than once in call to " << callee;
251
- error(msg.str(), a->pstate());
277
+ error(msg.str(), a->pstate(), eval->exp.traces);
252
278
  }
253
- env->local_frame()[a->name()] = &a->value();
279
+ env->local_frame()[a->name()] = a->value();
254
280
  }
255
281
  }
256
282
  // EO while ia
@@ -265,11 +291,7 @@ namespace Sass {
265
291
  // cerr << "********" << endl;
266
292
  if (!env->has_local(leftover->name())) {
267
293
  if (leftover->is_rest_parameter()) {
268
- env->local_frame()[leftover->name()] = SASS_MEMORY_NEW(List,
269
- leftover->pstate(),
270
- 0,
271
- SASS_COMMA,
272
- true);
294
+ env->local_frame()[leftover->name()] = varargs;
273
295
  }
274
296
  else if (leftover->default_value()) {
275
297
  Expression_Ptr dv = leftover->default_value()->perform(eval);
@@ -277,7 +299,7 @@ namespace Sass {
277
299
  }
278
300
  else {
279
301
  // param is unbound and has no default value -- error
280
- throw Exception::MissingArgument(as->pstate(), name, leftover->name(), type);
302
+ throw Exception::MissingArgument(as->pstate(), eval->exp.traces, name, leftover->name(), type);
281
303
  }
282
304
  }
283
305
  }