sassc 1.11.4 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +2 -2
  3. data/CODE_OF_CONDUCT.md +10 -0
  4. data/README.md +4 -1
  5. data/ext/libsass/.editorconfig +1 -1
  6. data/ext/libsass/.github/CONTRIBUTING.md +7 -7
  7. data/ext/libsass/.github/ISSUE_TEMPLATE.md +31 -6
  8. data/ext/libsass/.gitignore +3 -0
  9. data/ext/libsass/.travis.yml +37 -18
  10. data/ext/libsass/GNUmakefile.am +23 -37
  11. data/ext/libsass/Makefile +10 -6
  12. data/ext/libsass/Makefile.conf +3 -0
  13. data/ext/libsass/Readme.md +68 -63
  14. data/ext/libsass/appveyor.yml +7 -3
  15. data/ext/libsass/configure.ac +10 -14
  16. data/ext/libsass/docs/api-context-internal.md +29 -21
  17. data/ext/libsass/docs/api-context.md +26 -6
  18. data/ext/libsass/docs/api-doc.md +49 -16
  19. data/ext/libsass/docs/api-function-example.md +1 -1
  20. data/ext/libsass/docs/api-function.md +31 -7
  21. data/ext/libsass/docs/api-importer.md +19 -19
  22. data/ext/libsass/docs/api-value.md +4 -2
  23. data/ext/libsass/docs/build-on-windows.md +4 -4
  24. data/ext/libsass/docs/build-with-mingw.md +3 -3
  25. data/ext/libsass/docs/build.md +9 -9
  26. data/ext/libsass/docs/custom-functions-internal.md +10 -8
  27. data/ext/libsass/docs/implementations.md +20 -8
  28. data/ext/libsass/docs/unicode.md +16 -10
  29. data/ext/libsass/include/sass/base.h +0 -3
  30. data/ext/libsass/include/sass/context.h +20 -2
  31. data/ext/libsass/include/sass/functions.h +31 -0
  32. data/ext/libsass/include/sass/values.h +3 -1
  33. data/ext/libsass/include/sass/version.h +1 -1
  34. data/ext/libsass/include/sass/version.h.in +1 -1
  35. data/ext/libsass/include/sass2scss.h +1 -1
  36. data/ext/libsass/res/resource.rc +6 -6
  37. data/ext/libsass/script/ci-build-libsass +10 -5
  38. data/ext/libsass/script/ci-build-plugin +62 -0
  39. data/ext/libsass/script/ci-install-compiler +1 -1
  40. data/ext/libsass/script/ci-install-deps +4 -7
  41. data/ext/libsass/script/ci-report-coverage +13 -3
  42. data/ext/libsass/script/tap-driver +1 -1
  43. data/ext/libsass/script/tap-runner +1 -1
  44. data/ext/libsass/src/GNUmakefile.am +1 -1
  45. data/ext/libsass/src/ast.cpp +537 -762
  46. data/ext/libsass/src/ast.hpp +377 -419
  47. data/ext/libsass/src/ast_def_macros.hpp +26 -1
  48. data/ext/libsass/src/ast_fwd_decl.cpp +29 -0
  49. data/ext/libsass/src/ast_fwd_decl.hpp +94 -21
  50. data/ext/libsass/src/b64/encode.h +3 -1
  51. data/ext/libsass/src/backtrace.cpp +46 -0
  52. data/ext/libsass/src/backtrace.hpp +7 -54
  53. data/ext/libsass/src/bind.cpp +72 -50
  54. data/ext/libsass/src/bind.hpp +0 -1
  55. data/ext/libsass/src/cencode.c +6 -0
  56. data/ext/libsass/src/check_nesting.cpp +157 -135
  57. data/ext/libsass/src/check_nesting.hpp +11 -10
  58. data/ext/libsass/src/color_maps.cpp +10 -6
  59. data/ext/libsass/src/color_maps.hpp +6 -8
  60. data/ext/libsass/src/constants.cpp +4 -3
  61. data/ext/libsass/src/constants.hpp +4 -3
  62. data/ext/libsass/src/context.cpp +110 -47
  63. data/ext/libsass/src/context.hpp +11 -1
  64. data/ext/libsass/src/cssize.cpp +105 -94
  65. data/ext/libsass/src/cssize.hpp +4 -5
  66. data/ext/libsass/src/debugger.hpp +247 -244
  67. data/ext/libsass/src/emitter.cpp +30 -6
  68. data/ext/libsass/src/emitter.hpp +7 -0
  69. data/ext/libsass/src/environment.cpp +67 -16
  70. data/ext/libsass/src/environment.hpp +28 -7
  71. data/ext/libsass/src/error_handling.cpp +92 -64
  72. data/ext/libsass/src/error_handling.hpp +64 -43
  73. data/ext/libsass/src/eval.cpp +494 -544
  74. data/ext/libsass/src/eval.hpp +17 -23
  75. data/ext/libsass/src/expand.cpp +182 -154
  76. data/ext/libsass/src/expand.hpp +4 -5
  77. data/ext/libsass/src/extend.cpp +299 -291
  78. data/ext/libsass/src/extend.hpp +46 -11
  79. data/ext/libsass/src/file.cpp +103 -36
  80. data/ext/libsass/src/file.hpp +21 -4
  81. data/ext/libsass/src/functions.cpp +561 -312
  82. data/ext/libsass/src/functions.hpp +8 -5
  83. data/ext/libsass/src/inspect.cpp +108 -53
  84. data/ext/libsass/src/inspect.hpp +5 -2
  85. data/ext/libsass/src/lexer.cpp +15 -7
  86. data/ext/libsass/src/lexer.hpp +13 -4
  87. data/ext/libsass/src/listize.cpp +3 -2
  88. data/ext/libsass/src/listize.hpp +0 -1
  89. data/ext/libsass/src/memory/SharedPtr.cpp +16 -18
  90. data/ext/libsass/src/memory/SharedPtr.hpp +47 -43
  91. data/ext/libsass/src/node.cpp +34 -38
  92. data/ext/libsass/src/node.hpp +6 -8
  93. data/ext/libsass/src/operation.hpp +2 -2
  94. data/ext/libsass/src/operators.cpp +240 -0
  95. data/ext/libsass/src/operators.hpp +30 -0
  96. data/ext/libsass/src/output.cpp +22 -20
  97. data/ext/libsass/src/parser.cpp +719 -358
  98. data/ext/libsass/src/parser.hpp +57 -22
  99. data/ext/libsass/src/plugins.cpp +28 -10
  100. data/ext/libsass/src/position.cpp +21 -3
  101. data/ext/libsass/src/position.hpp +2 -1
  102. data/ext/libsass/src/prelexer.cpp +104 -19
  103. data/ext/libsass/src/prelexer.hpp +10 -3
  104. data/ext/libsass/src/remove_placeholders.cpp +9 -10
  105. data/ext/libsass/src/remove_placeholders.hpp +1 -5
  106. data/ext/libsass/src/sass.cpp +62 -4
  107. data/ext/libsass/src/sass.hpp +5 -2
  108. data/ext/libsass/src/sass_context.cpp +96 -58
  109. data/ext/libsass/src/sass_context.hpp +7 -5
  110. data/ext/libsass/src/sass_functions.cpp +63 -1
  111. data/ext/libsass/src/sass_functions.hpp +19 -1
  112. data/ext/libsass/src/sass_util.cpp +3 -3
  113. data/ext/libsass/src/sass_util.hpp +4 -4
  114. data/ext/libsass/src/sass_values.cpp +42 -39
  115. data/ext/libsass/src/sass_values.hpp +2 -1
  116. data/ext/libsass/src/source_map.cpp +16 -18
  117. data/ext/libsass/src/subset_map.cpp +6 -8
  118. data/ext/libsass/src/subset_map.hpp +6 -6
  119. data/ext/libsass/src/to_c.cpp +2 -2
  120. data/ext/libsass/src/to_value.cpp +8 -3
  121. data/ext/libsass/src/to_value.hpp +1 -0
  122. data/ext/libsass/src/units.cpp +349 -45
  123. data/ext/libsass/src/units.hpp +39 -22
  124. data/ext/libsass/src/utf8/checked.h +7 -0
  125. data/ext/libsass/src/utf8/unchecked.h +7 -0
  126. data/ext/libsass/src/utf8_string.cpp +1 -1
  127. data/ext/libsass/src/util.cpp +139 -45
  128. data/ext/libsass/src/util.hpp +4 -7
  129. data/ext/libsass/src/values.cpp +15 -23
  130. data/ext/libsass/win/libsass.sln +13 -2
  131. data/ext/libsass/win/libsass.sln.DotSettings +9 -0
  132. data/ext/libsass/win/libsass.targets +3 -0
  133. data/ext/libsass/win/libsass.vcxproj.filters +9 -0
  134. data/lib/sassc/version.rb +1 -1
  135. data/sassc.gemspec +1 -1
  136. data/test/native_test.rb +1 -1
  137. metadata +11 -4
@@ -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
  }