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,6 +5,9 @@
5
5
  #include <sstream>
6
6
  #include <stdexcept>
7
7
  #include "position.hpp"
8
+ #include "backtrace.hpp"
9
+ #include "ast_fwd_decl.hpp"
10
+ #include "sass/functions.h"
8
11
 
9
12
  namespace Sass {
10
13
 
@@ -15,6 +18,7 @@ namespace Sass {
15
18
  const std::string def_msg = "Invalid sass detected";
16
19
  const std::string def_op_msg = "Undefined operation";
17
20
  const std::string def_op_null_msg = "Invalid null operation";
21
+ const std::string def_nesting_limit = "Code too deeply neested";
18
22
 
19
23
  class Base : public std::runtime_error {
20
24
  protected:
@@ -22,9 +26,9 @@ namespace Sass {
22
26
  std::string prefix;
23
27
  public:
24
28
  ParserState pstate;
25
- std::vector<Sass_Import_Entry>* import_stack;
29
+ Backtraces traces;
26
30
  public:
27
- Base(ParserState pstate, std::string msg = def_msg, std::vector<Sass_Import_Entry>* import_stack = 0);
31
+ Base(ParserState pstate, std::string msg, Backtraces traces);
28
32
  virtual const char* errtype() const { return prefix.c_str(); }
29
33
  virtual const char* what() const throw() { return msg.c_str(); }
30
34
  virtual ~Base() throw() {};
@@ -32,7 +36,7 @@ namespace Sass {
32
36
 
33
37
  class InvalidSass : public Base {
34
38
  public:
35
- InvalidSass(ParserState pstate, std::string msg);
39
+ InvalidSass(ParserState pstate, Backtraces traces, std::string msg);
36
40
  virtual ~InvalidSass() throw() {};
37
41
  };
38
42
 
@@ -41,7 +45,7 @@ namespace Sass {
41
45
  Selector_Ptr parent;
42
46
  Selector_Ptr selector;
43
47
  public:
44
- InvalidParent(Selector_Ptr parent, Selector_Ptr selector);
48
+ InvalidParent(Selector_Ptr parent, Backtraces traces, Selector_Ptr selector);
45
49
  virtual ~InvalidParent() throw() {};
46
50
  };
47
51
 
@@ -51,7 +55,7 @@ namespace Sass {
51
55
  std::string arg;
52
56
  std::string fntype;
53
57
  public:
54
- MissingArgument(ParserState pstate, std::string fn, std::string arg, std::string fntype);
58
+ MissingArgument(ParserState pstate, Backtraces traces, std::string fn, std::string arg, std::string fntype);
55
59
  virtual ~MissingArgument() throw() {};
56
60
  };
57
61
 
@@ -62,38 +66,29 @@ namespace Sass {
62
66
  std::string type;
63
67
  const Value_Ptr value;
64
68
  public:
65
- InvalidArgumentType(ParserState pstate, std::string fn, std::string arg, std::string type, const Value_Ptr value = 0);
69
+ InvalidArgumentType(ParserState pstate, Backtraces traces, std::string fn, std::string arg, std::string type, const Value_Ptr value = 0);
66
70
  virtual ~InvalidArgumentType() throw() {};
67
71
  };
68
72
 
69
- class InvalidSyntax : public Base {
73
+ class InvalidVarKwdType : public Base {
74
+ protected:
75
+ std::string name;
76
+ const Argument_Ptr arg;
70
77
  public:
71
- InvalidSyntax(ParserState pstate, std::string msg, std::vector<Sass_Import_Entry>* import_stack = 0);
72
- virtual ~InvalidSyntax() throw() {};
78
+ InvalidVarKwdType(ParserState pstate, Backtraces traces, std::string name, const Argument_Ptr arg = 0);
79
+ virtual ~InvalidVarKwdType() throw() {};
73
80
  };
74
81
 
75
- /* common virtual base class (has no pstate) */
76
- class OperationError : public std::runtime_error {
77
- protected:
78
- std::string msg;
79
- public:
80
- OperationError(std::string msg = def_op_msg)
81
- : std::runtime_error(msg), msg(msg)
82
- {};
82
+ class InvalidSyntax : public Base {
83
83
  public:
84
- virtual const char* errtype() const { return "Error"; }
85
- virtual const char* what() const throw() { return msg.c_str(); }
86
- virtual ~OperationError() throw() {};
84
+ InvalidSyntax(ParserState pstate, Backtraces traces, std::string msg);
85
+ virtual ~InvalidSyntax() throw() {};
87
86
  };
88
87
 
89
- class ZeroDivisionError : public OperationError {
90
- protected:
91
- const Expression& lhs;
92
- const Expression& rhs;
88
+ class NestingLimitError : public Base {
93
89
  public:
94
- ZeroDivisionError(const Expression& lhs, const Expression& rhs);
95
- virtual const char* errtype() const { return "ZeroDivisionError"; }
96
- virtual ~ZeroDivisionError() throw() {};
90
+ NestingLimitError(ParserState pstate, Backtraces traces, std::string msg = def_nesting_limit);
91
+ virtual ~NestingLimitError() throw() {};
97
92
  };
98
93
 
99
94
  class DuplicateKeyError : public Base {
@@ -101,7 +96,7 @@ namespace Sass {
101
96
  const Map& dup;
102
97
  const Expression& org;
103
98
  public:
104
- DuplicateKeyError(const Map& dup, const Expression& org);
99
+ DuplicateKeyError(Backtraces traces, const Map& dup, const Expression& org);
105
100
  virtual const char* errtype() const { return "Error"; }
106
101
  virtual ~DuplicateKeyError() throw() {};
107
102
  };
@@ -111,7 +106,7 @@ namespace Sass {
111
106
  const Expression& var;
112
107
  const std::string type;
113
108
  public:
114
- TypeMismatch(const Expression& var, const std::string type);
109
+ TypeMismatch(Backtraces traces, const Expression& var, const std::string type);
115
110
  virtual const char* errtype() const { return "Error"; }
116
111
  virtual ~TypeMismatch() throw() {};
117
112
  };
@@ -120,7 +115,7 @@ namespace Sass {
120
115
  protected:
121
116
  const Expression& val;
122
117
  public:
123
- InvalidValue(const Expression& val);
118
+ InvalidValue(Backtraces traces, const Expression& val);
124
119
  virtual const char* errtype() const { return "Error"; }
125
120
  virtual ~InvalidValue() throw() {};
126
121
  };
@@ -129,17 +124,42 @@ namespace Sass {
129
124
  protected:
130
125
  const AST_Node& node;
131
126
  public:
132
- StackError(const AST_Node& node);
127
+ StackError(Backtraces traces, const AST_Node& node);
133
128
  virtual const char* errtype() const { return "SystemStackError"; }
134
129
  virtual ~StackError() throw() {};
135
130
  };
136
131
 
132
+ /* common virtual base class (has no pstate or trace) */
133
+ class OperationError : public std::runtime_error {
134
+ protected:
135
+ std::string msg;
136
+ public:
137
+ OperationError(std::string msg = def_op_msg)
138
+ : std::runtime_error(msg), msg(msg)
139
+ {};
140
+ public:
141
+ virtual const char* errtype() const { return "Error"; }
142
+ virtual const char* what() const throw() { return msg.c_str(); }
143
+ virtual ~OperationError() throw() {};
144
+ };
145
+
146
+ class ZeroDivisionError : public OperationError {
147
+ protected:
148
+ const Expression& lhs;
149
+ const Expression& rhs;
150
+ public:
151
+ ZeroDivisionError(const Expression& lhs, const Expression& rhs);
152
+ virtual const char* errtype() const { return "ZeroDivisionError"; }
153
+ virtual ~ZeroDivisionError() throw() {};
154
+ };
155
+
137
156
  class IncompatibleUnits : public OperationError {
138
157
  protected:
139
- const Number& lhs;
140
- const Number& rhs;
158
+ // const Sass::UnitType lhs;
159
+ // const Sass::UnitType rhs;
141
160
  public:
142
- IncompatibleUnits(const Number& lhs, const Number& rhs);
161
+ IncompatibleUnits(const Units& lhs, const Units& rhs);
162
+ IncompatibleUnits(const UnitType lhs, const UnitType rhs);
143
163
  virtual ~IncompatibleUnits() throw() {};
144
164
  };
145
165
 
@@ -147,16 +167,16 @@ namespace Sass {
147
167
  protected:
148
168
  Expression_Ptr_Const lhs;
149
169
  Expression_Ptr_Const rhs;
150
- const std::string op;
170
+ const Sass_OP op;
151
171
  public:
152
- UndefinedOperation(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, const std::string& op);
172
+ UndefinedOperation(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, enum Sass_OP op);
153
173
  // virtual const char* errtype() const { return "Error"; }
154
174
  virtual ~UndefinedOperation() throw() {};
155
175
  };
156
176
 
157
177
  class InvalidNullOperation : public UndefinedOperation {
158
178
  public:
159
- InvalidNullOperation(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, const std::string& op);
179
+ InvalidNullOperation(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, enum Sass_OP op);
160
180
  virtual ~InvalidNullOperation() throw() {};
161
181
  };
162
182
 
@@ -164,16 +184,16 @@ namespace Sass {
164
184
  protected:
165
185
  Expression_Ptr_Const lhs;
166
186
  Expression_Ptr_Const rhs;
167
- const std::string op;
187
+ const Sass_OP op;
168
188
  public:
169
- AlphaChannelsNotEqual(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, const std::string& op);
189
+ AlphaChannelsNotEqual(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, enum Sass_OP op);
170
190
  // virtual const char* errtype() const { return "Error"; }
171
191
  virtual ~AlphaChannelsNotEqual() throw() {};
172
192
  };
173
193
 
174
194
  class SassValueError : public Base {
175
195
  public:
176
- SassValueError(ParserState pstate, OperationError& err);
196
+ SassValueError(Backtraces traces, ParserState pstate, OperationError& err);
177
197
  virtual ~SassValueError() throw() {};
178
198
  };
179
199
 
@@ -181,14 +201,15 @@ namespace Sass {
181
201
 
182
202
  void warn(std::string msg, ParserState pstate);
183
203
  void warn(std::string msg, ParserState pstate, Backtrace* bt);
204
+ void warning(std::string msg, ParserState pstate);
184
205
 
185
206
  void deprecated_function(std::string msg, ParserState pstate);
186
- void deprecated(std::string msg, std::string msg2, ParserState pstate);
207
+ void deprecated(std::string msg, std::string msg2, bool with_column, ParserState pstate);
187
208
  void deprecated_bind(std::string msg, ParserState pstate);
188
209
  // void deprecated(std::string msg, ParserState pstate, Backtrace* bt);
189
210
 
190
- void error(std::string msg, ParserState pstate);
191
- void error(std::string msg, ParserState pstate, Backtrace* bt);
211
+ void coreError(std::string msg, ParserState pstate);
212
+ void error(std::string msg, ParserState pstate, Backtraces& traces);
192
213
 
193
214
  }
194
215
 
@@ -12,6 +12,7 @@
12
12
  #include "bind.hpp"
13
13
  #include "util.hpp"
14
14
  #include "inspect.hpp"
15
+ #include "operators.hpp"
15
16
  #include "environment.hpp"
16
17
  #include "position.hpp"
17
18
  #include "sass/values.h"
@@ -24,34 +25,21 @@
24
25
  #include "parser.hpp"
25
26
  #include "expand.hpp"
26
27
  #include "color_maps.hpp"
28
+ #include "sass_functions.hpp"
27
29
 
28
30
  namespace Sass {
29
31
 
30
- inline double add(double x, double y) { return x + y; }
31
- inline double sub(double x, double y) { return x - y; }
32
- inline double mul(double x, double y) { return x * y; }
33
- inline double div(double x, double y) { return x / y; } // x/0 checked by caller
34
- inline double mod(double x, double y) { // x/0 checked by caller
35
- if ((x > 0 && y < 0) || (x < 0 && y > 0)) {
36
- double ret = std::fmod(x, y);
37
- return ret ? ret + y : ret;
38
- } else {
39
- return std::fmod(x, y);
40
- }
41
- }
42
- typedef double (*bop)(double, double);
43
- bop ops[Sass_OP::NUM_OPS] = {
44
- 0, 0, // and, or
45
- 0, 0, 0, 0, 0, 0, // eq, neq, gt, gte, lt, lte
46
- add, sub, mul, div, mod
47
- };
48
-
49
32
  Eval::Eval(Expand& exp)
50
33
  : exp(exp),
51
34
  ctx(exp.ctx),
35
+ traces(exp.traces),
52
36
  force(false),
53
- is_in_comment(false)
54
- { }
37
+ is_in_comment(false),
38
+ is_in_selector_schema(false)
39
+ {
40
+ bool_true = SASS_MEMORY_NEW(Boolean, "[NA]", true);
41
+ bool_false = SASS_MEMORY_NEW(Boolean, "[NA]", false);
42
+ }
55
43
  Eval::~Eval() { }
56
44
 
57
45
  Env* Eval::environment()
@@ -64,11 +52,6 @@ namespace Sass {
64
52
  return exp.selector();
65
53
  }
66
54
 
67
- Backtrace* Eval::backtrace()
68
- {
69
- return exp.backtrace();
70
- }
71
-
72
55
  Expression_Ptr Eval::operator()(Block_Ptr b)
73
56
  {
74
57
  Expression_Ptr val = 0;
@@ -86,7 +69,7 @@ namespace Sass {
86
69
  if (a->is_global()) {
87
70
  if (a->is_default()) {
88
71
  if (env->has_global(var)) {
89
- Expression_Ptr e = SASS_MEMORY_CAST(Expression, env->get_global(var));
72
+ Expression_Ptr e = Cast<Expression>(env->get_global(var));
90
73
  if (!e || e->concrete_type() == Expression::NULL_VAL) {
91
74
  env->set_global(var, a->value()->perform(this));
92
75
  }
@@ -105,7 +88,7 @@ namespace Sass {
105
88
  while (cur && cur->is_lexical()) {
106
89
  if (cur->has_local(var)) {
107
90
  if (AST_Node_Obj node = cur->get_local(var)) {
108
- Expression_Ptr e = SASS_MEMORY_CAST(Expression, node);
91
+ Expression_Ptr e = Cast<Expression>(node);
109
92
  if (!e || e->concrete_type() == Expression::NULL_VAL) {
110
93
  cur->set_local(var, a->value()->perform(this));
111
94
  }
@@ -121,7 +104,7 @@ namespace Sass {
121
104
  }
122
105
  else if (env->has_global(var)) {
123
106
  if (AST_Node_Obj node = env->get_global(var)) {
124
- Expression_Ptr e = SASS_MEMORY_CAST(Expression, node);
107
+ Expression_Ptr e = Cast<Expression>(node);
125
108
  if (!e || e->concrete_type() == Expression::NULL_VAL) {
126
109
  env->set_global(var, a->value()->perform(this));
127
110
  }
@@ -164,28 +147,28 @@ namespace Sass {
164
147
  std::string variable(f->variable());
165
148
  Expression_Obj low = f->lower_bound()->perform(this);
166
149
  if (low->concrete_type() != Expression::NUMBER) {
167
- throw Exception::TypeMismatch(*low, "integer");
150
+ traces.push_back(Backtrace(low->pstate()));
151
+ throw Exception::TypeMismatch(traces, *low, "integer");
168
152
  }
169
153
  Expression_Obj high = f->upper_bound()->perform(this);
170
154
  if (high->concrete_type() != Expression::NUMBER) {
171
- throw Exception::TypeMismatch(*high, "integer");
155
+ traces.push_back(Backtrace(high->pstate()));
156
+ throw Exception::TypeMismatch(traces, *high, "integer");
172
157
  }
173
- Number_Obj sass_start = SASS_MEMORY_CAST(Number, low);
174
- Number_Obj sass_end = SASS_MEMORY_CAST(Number, high);
158
+ Number_Obj sass_start = Cast<Number>(low);
159
+ Number_Obj sass_end = Cast<Number>(high);
175
160
  // check if units are valid for sequence
176
161
  if (sass_start->unit() != sass_end->unit()) {
177
162
  std::stringstream msg; msg << "Incompatible units: '"
178
163
  << sass_end->unit() << "' and '"
179
164
  << sass_start->unit() << "'.";
180
- error(msg.str(), low->pstate(), backtrace());
165
+ error(msg.str(), low->pstate(), traces);
181
166
  }
182
167
  double start = sass_start->value();
183
168
  double end = sass_end->value();
184
169
  // only create iterator once in this environment
185
170
  Env env(environment(), true);
186
171
  exp.env_stack.push_back(&env);
187
- Number_Ptr it = SASS_MEMORY_NEW(Number, low->pstate(), start, sass_end->unit());
188
- env.set_local(variable, it);
189
172
  Block_Obj body = f->block();
190
173
  Expression_Ptr val = 0;
191
174
  if (start < end) {
@@ -193,7 +176,7 @@ namespace Sass {
193
176
  for (double i = start;
194
177
  i < end;
195
178
  ++i) {
196
- it->value(i);
179
+ Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit());
197
180
  env.set_local(variable, it);
198
181
  val = body->perform(this);
199
182
  if (val) break;
@@ -203,7 +186,7 @@ namespace Sass {
203
186
  for (double i = start;
204
187
  i > end;
205
188
  --i) {
206
- it->value(i);
189
+ Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit());
207
190
  env.set_local(variable, it);
208
191
  val = body->perform(this);
209
192
  if (val) break;
@@ -224,19 +207,19 @@ namespace Sass {
224
207
  List_Obj list = 0;
225
208
  Map_Ptr map = 0;
226
209
  if (expr->concrete_type() == Expression::MAP) {
227
- map = SASS_MEMORY_CAST(Map, expr);
210
+ map = Cast<Map>(expr);
228
211
  }
229
- else if (Selector_List_Ptr ls = SASS_MEMORY_CAST(Selector_List, expr)) {
212
+ else if (Selector_List_Ptr ls = Cast<Selector_List>(expr)) {
230
213
  Listize listize;
231
214
  Expression_Obj rv = ls->perform(&listize);
232
- list = dynamic_cast<List_Ptr>(&rv);
215
+ list = Cast<List>(rv);
233
216
  }
234
217
  else if (expr->concrete_type() != Expression::LIST) {
235
218
  list = SASS_MEMORY_NEW(List, expr->pstate(), 1, SASS_COMMA);
236
219
  list->append(expr);
237
220
  }
238
221
  else {
239
- list = SASS_MEMORY_CAST(List, expr);
222
+ list = Cast<List>(expr);
240
223
  }
241
224
 
242
225
  Block_Obj body = e->block();
@@ -252,8 +235,8 @@ namespace Sass {
252
235
  variable->append(value);
253
236
  env.set_local(variables[0], variable);
254
237
  } else {
255
- env.set_local(variables[0], &key);
256
- env.set_local(variables[1], &value);
238
+ env.set_local(variables[0], key);
239
+ env.set_local(variables[1], value);
257
240
  }
258
241
 
259
242
  val = body->perform(this);
@@ -261,15 +244,15 @@ namespace Sass {
261
244
  }
262
245
  }
263
246
  else {
264
- if (list->length() == 1 && SASS_MEMORY_CAST(Selector_List, list)) {
265
- list = SASS_MEMORY_CAST(List, list);
247
+ if (list->length() == 1 && Cast<Selector_List>(list)) {
248
+ list = Cast<List>(list);
266
249
  }
267
250
  for (size_t i = 0, L = list->length(); i < L; ++i) {
268
- Expression_Ptr e = &list->at(i);
251
+ Expression_Ptr item = list->at(i);
269
252
  // unwrap value if the expression is an argument
270
- if (Argument_Ptr arg = SASS_MEMORY_CAST_PTR(Argument, e)) e = &arg->value();
253
+ if (Argument_Ptr arg = Cast<Argument>(item)) item = arg->value();
271
254
  // check if we got passed a list of args (investigate)
272
- if (List_Ptr scalars = SASS_MEMORY_CAST_PTR(List, e)) {
255
+ if (List_Ptr scalars = Cast<List>(item)) {
273
256
  if (variables.size() == 1) {
274
257
  Expression_Ptr var = scalars;
275
258
  env.set_local(variables[0], var);
@@ -278,13 +261,13 @@ namespace Sass {
278
261
  for (size_t j = 0, K = variables.size(); j < K; ++j) {
279
262
  Expression_Ptr res = j >= scalars->length()
280
263
  ? SASS_MEMORY_NEW(Null, expr->pstate())
281
- : &scalars->at(j);
264
+ : scalars->at(j);
282
265
  env.set_local(variables[j], res);
283
266
  }
284
267
  }
285
268
  } else {
286
269
  if (variables.size() > 0) {
287
- env.set_local(variables.at(0), e);
270
+ env.set_local(variables.at(0), item);
288
271
  for (size_t j = 1, K = variables.size(); j < K; ++j) {
289
272
  // XXX: this is never hit via spec tests
290
273
  Expression_Ptr res = SASS_MEMORY_NEW(Null, expr->pstate());
@@ -334,17 +317,28 @@ namespace Sass {
334
317
  // try to use generic function
335
318
  if (env->has("@warn[f]")) {
336
319
 
337
- Definition_Ptr def = SASS_MEMORY_CAST(Definition, (*env)["@warn[f]"]);
320
+ // add call stack entry
321
+ ctx.callee_stack.push_back({
322
+ "@warn",
323
+ w->pstate().path,
324
+ w->pstate().line + 1,
325
+ w->pstate().column + 1,
326
+ SASS_CALLEE_FUNCTION,
327
+ { env }
328
+ });
329
+
330
+ Definition_Ptr def = Cast<Definition>((*env)["@warn[f]"]);
338
331
  // Block_Obj body = def->block();
339
332
  // Native_Function func = def->native_function();
340
333
  Sass_Function_Entry c_function = def->c_function();
341
334
  Sass_Function_Fn c_func = sass_function_get_function(c_function);
342
335
 
343
336
  To_C to_c;
344
- union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
337
+ union Sass_Value* c_args = sass_make_list(1, SASS_COMMA, false);
345
338
  sass_list_set_value(c_args, 0, message->perform(&to_c));
346
339
  union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
347
340
  ctx.c_options.output_style = outstyle;
341
+ ctx.callee_stack.pop_back();
348
342
  sass_delete_value(c_args);
349
343
  sass_delete_value(c_val);
350
344
  return 0;
@@ -352,11 +346,12 @@ namespace Sass {
352
346
  }
353
347
 
354
348
  std::string result(unquote(message->to_sass()));
355
- Backtrace top(backtrace(), w->pstate(), "");
356
- std::cerr << "WARNING: " << result;
357
- std::cerr << top.to_string();
358
- std::cerr << std::endl << std::endl;
349
+ std::cerr << "WARNING: " << result << std::endl;
350
+ traces.push_back(Backtrace(w->pstate()));
351
+ std::cerr << traces_to_string(traces, " ");
352
+ std::cerr << std::endl;
359
353
  ctx.c_options.output_style = outstyle;
354
+ traces.pop_back();
360
355
  return 0;
361
356
  }
362
357
 
@@ -370,17 +365,28 @@ namespace Sass {
370
365
  // try to use generic function
371
366
  if (env->has("@error[f]")) {
372
367
 
373
- Definition_Ptr def = SASS_MEMORY_CAST(Definition, (*env)["@error[f]"]);
368
+ // add call stack entry
369
+ ctx.callee_stack.push_back({
370
+ "@error",
371
+ e->pstate().path,
372
+ e->pstate().line + 1,
373
+ e->pstate().column + 1,
374
+ SASS_CALLEE_FUNCTION,
375
+ { env }
376
+ });
377
+
378
+ Definition_Ptr def = Cast<Definition>((*env)["@error[f]"]);
374
379
  // Block_Obj body = def->block();
375
380
  // Native_Function func = def->native_function();
376
381
  Sass_Function_Entry c_function = def->c_function();
377
382
  Sass_Function_Fn c_func = sass_function_get_function(c_function);
378
383
 
379
384
  To_C to_c;
380
- union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
385
+ union Sass_Value* c_args = sass_make_list(1, SASS_COMMA, false);
381
386
  sass_list_set_value(c_args, 0, message->perform(&to_c));
382
387
  union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
383
388
  ctx.c_options.output_style = outstyle;
389
+ ctx.callee_stack.pop_back();
384
390
  sass_delete_value(c_args);
385
391
  sass_delete_value(c_val);
386
392
  return 0;
@@ -389,7 +395,7 @@ namespace Sass {
389
395
 
390
396
  std::string result(unquote(message->to_sass()));
391
397
  ctx.c_options.output_style = outstyle;
392
- error(result, e->pstate());
398
+ error(result, e->pstate(), traces);
393
399
  return 0;
394
400
  }
395
401
 
@@ -403,17 +409,28 @@ namespace Sass {
403
409
  // try to use generic function
404
410
  if (env->has("@debug[f]")) {
405
411
 
406
- Definition_Ptr def = SASS_MEMORY_CAST(Definition, (*env)["@debug[f]"]);
412
+ // add call stack entry
413
+ ctx.callee_stack.push_back({
414
+ "@debug",
415
+ d->pstate().path,
416
+ d->pstate().line + 1,
417
+ d->pstate().column + 1,
418
+ SASS_CALLEE_FUNCTION,
419
+ { env }
420
+ });
421
+
422
+ Definition_Ptr def = Cast<Definition>((*env)["@debug[f]"]);
407
423
  // Block_Obj body = def->block();
408
424
  // Native_Function func = def->native_function();
409
425
  Sass_Function_Entry c_function = def->c_function();
410
426
  Sass_Function_Fn c_func = sass_function_get_function(c_function);
411
427
 
412
428
  To_C to_c;
413
- union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
429
+ union Sass_Value* c_args = sass_make_list(1, SASS_COMMA, false);
414
430
  sass_list_set_value(c_args, 0, message->perform(&to_c));
415
431
  union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
416
432
  ctx.c_options.output_style = outstyle;
433
+ ctx.callee_stack.pop_back();
417
434
  sass_delete_value(c_args);
418
435
  sass_delete_value(c_val);
419
436
  return 0;
@@ -441,14 +458,15 @@ namespace Sass {
441
458
  l->length() / 2);
442
459
  for (size_t i = 0, L = l->length(); i < L; i += 2)
443
460
  {
444
- Expression_Ptr key = (*l)[i+0]->perform(this);
445
- Expression_Ptr val = (*l)[i+1]->perform(this);
461
+ Expression_Obj key = (*l)[i+0]->perform(this);
462
+ Expression_Obj val = (*l)[i+1]->perform(this);
446
463
  // make sure the color key never displays its real name
447
464
  key->is_delayed(true); // verified
448
465
  *lm << std::make_pair(key, val);
449
466
  }
450
467
  if (lm->has_duplicate_key()) {
451
- throw Exception::DuplicateKeyError(*lm, *l);
468
+ traces.push_back(Backtrace(l->pstate()));
469
+ throw Exception::DuplicateKeyError(traces, *lm, *l);
452
470
  }
453
471
 
454
472
  lm->is_interpolant(l->is_interpolant());
@@ -461,7 +479,8 @@ namespace Sass {
461
479
  l->pstate(),
462
480
  l->length(),
463
481
  l->separator(),
464
- l->is_arglist());
482
+ l->is_arglist(),
483
+ l->is_bracketed());
465
484
  for (size_t i = 0, L = l->length(); i < L; ++i) {
466
485
  ll->append((*l)[i]->perform(this));
467
486
  }
@@ -478,7 +497,8 @@ namespace Sass {
478
497
  // make sure we're not starting with duplicate keys.
479
498
  // the duplicate key state will have been set in the parser phase.
480
499
  if (m->has_duplicate_key()) {
481
- throw Exception::DuplicateKeyError(*m, *m);
500
+ traces.push_back(Backtrace(m->pstate()));
501
+ throw Exception::DuplicateKeyError(traces, *m, *m);
482
502
  }
483
503
 
484
504
  Map_Obj mm = SASS_MEMORY_NEW(Map,
@@ -486,13 +506,16 @@ namespace Sass {
486
506
  m->length());
487
507
  for (auto key : m->keys()) {
488
508
  Expression_Ptr ex_key = key->perform(this);
489
- Expression_Ptr ex_val = m->at(key)->perform(this);
509
+ Expression_Ptr ex_val = m->at(key);
510
+ if (ex_val == NULL) continue;
511
+ ex_val = ex_val->perform(this);
490
512
  *mm << std::make_pair(ex_key, ex_val);
491
513
  }
492
514
 
493
515
  // check the evaluated keys aren't duplicates.
494
516
  if (mm->has_duplicate_key()) {
495
- throw Exception::DuplicateKeyError(*mm, *m);
517
+ traces.push_back(Backtrace(m->pstate()));
518
+ throw Exception::DuplicateKeyError(traces, *mm, *m);
496
519
  }
497
520
 
498
521
  mm->is_expanded(true);
@@ -502,16 +525,141 @@ namespace Sass {
502
525
  Expression_Ptr Eval::operator()(Binary_Expression_Ptr b_in)
503
526
  {
504
527
 
505
- String_Schema_Obj ret_schema;
528
+ Expression_Obj lhs = b_in->left();
529
+ Expression_Obj rhs = b_in->right();
530
+ enum Sass_OP op_type = b_in->optype();
531
+
532
+ if (op_type == Sass_OP::AND) {
533
+ // LOCAL_FLAG(force, true);
534
+ lhs = lhs->perform(this);
535
+ if (!*lhs) return lhs.detach();
536
+ return rhs->perform(this);
537
+ }
538
+ else if (op_type == Sass_OP::OR) {
539
+ // LOCAL_FLAG(force, true);
540
+ lhs = lhs->perform(this);
541
+ if (*lhs) return lhs.detach();
542
+ return rhs->perform(this);
543
+ }
544
+
545
+ // Evaluate variables as early o
546
+ while (Variable_Ptr l_v = Cast<Variable>(lhs)) {
547
+ lhs = operator()(l_v);
548
+ }
549
+ while (Variable_Ptr r_v = Cast<Variable>(rhs)) {
550
+ rhs = operator()(r_v);
551
+ }
552
+
506
553
  Binary_Expression_Obj b = b_in;
507
- enum Sass_OP op_type = b->type();
554
+
555
+ // Evaluate sub-expressions early on
556
+ while (Binary_Expression_Ptr l_b = Cast<Binary_Expression>(lhs)) {
557
+ if (!force && l_b->is_delayed()) break;
558
+ lhs = operator()(l_b);
559
+ }
560
+ while (Binary_Expression_Ptr r_b = Cast<Binary_Expression>(rhs)) {
561
+ if (!force && r_b->is_delayed()) break;
562
+ rhs = operator()(r_b);
563
+ }
564
+
565
+ // don't eval delayed expressions (the '/' when used as a separator)
566
+ if (!force && op_type == Sass_OP::DIV && b->is_delayed()) {
567
+ b->right(b->right()->perform(this));
568
+ b->left(b->left()->perform(this));
569
+ return b.detach();
570
+ }
571
+
572
+ // specific types we know are final
573
+ // handle them early to avoid overhead
574
+ if (Number_Ptr l_n = Cast<Number>(lhs)) {
575
+ // lhs is number and rhs is number
576
+ if (Number_Ptr r_n = Cast<Number>(rhs)) {
577
+ try {
578
+ switch (op_type) {
579
+ case Sass_OP::EQ: return *l_n == *r_n ? bool_true : bool_false;
580
+ case Sass_OP::NEQ: return *l_n == *r_n ? bool_false : bool_true;
581
+ case Sass_OP::LT: return *l_n < *r_n ? bool_true : bool_false;
582
+ case Sass_OP::GTE: return *l_n < *r_n ? bool_false : bool_true;
583
+ case Sass_OP::LTE: return *l_n < *r_n || *l_n == *r_n ? bool_true : bool_false;
584
+ case Sass_OP::GT: return *l_n < *r_n || *l_n == *r_n ? bool_false : bool_true;
585
+ case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
586
+ return Operators::op_numbers(op_type, *l_n, *r_n, ctx.c_options, b_in->pstate());
587
+ default: break;
588
+ }
589
+ }
590
+ catch (Exception::OperationError& err)
591
+ {
592
+ traces.push_back(Backtrace(b_in->pstate()));
593
+ throw Exception::SassValueError(traces, b_in->pstate(), err);
594
+ }
595
+ }
596
+ // lhs is number and rhs is color
597
+ else if (Color_Ptr r_c = Cast<Color>(rhs)) {
598
+ try {
599
+ switch (op_type) {
600
+ case Sass_OP::EQ: return *l_n == *r_c ? bool_true : bool_false;
601
+ case Sass_OP::NEQ: return *l_n == *r_c ? bool_false : bool_true;
602
+ case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
603
+ return Operators::op_number_color(op_type, *l_n, *r_c, ctx.c_options, b_in->pstate());
604
+ default: break;
605
+ }
606
+ }
607
+ catch (Exception::OperationError& err)
608
+ {
609
+ traces.push_back(Backtrace(b_in->pstate()));
610
+ throw Exception::SassValueError(traces, b_in->pstate(), err);
611
+ }
612
+ }
613
+ }
614
+ else if (Color_Ptr l_c = Cast<Color>(lhs)) {
615
+ // lhs is color and rhs is color
616
+ if (Color_Ptr r_c = Cast<Color>(rhs)) {
617
+ try {
618
+ switch (op_type) {
619
+ case Sass_OP::EQ: return *l_c == *r_c ? bool_true : bool_false;
620
+ case Sass_OP::NEQ: return *l_c == *r_c ? bool_false : bool_true;
621
+ case Sass_OP::LT: return *l_c < *r_c ? bool_true : bool_false;
622
+ case Sass_OP::GTE: return *l_c < *r_c ? bool_false : bool_true;
623
+ case Sass_OP::LTE: return *l_c < *r_c || *l_c == *r_c ? bool_true : bool_false;
624
+ case Sass_OP::GT: return *l_c < *r_c || *l_c == *r_c ? bool_false : bool_true;
625
+ case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
626
+ return Operators::op_colors(op_type, *l_c, *r_c, ctx.c_options, b_in->pstate());
627
+ default: break;
628
+ }
629
+ }
630
+ catch (Exception::OperationError& err)
631
+ {
632
+ traces.push_back(Backtrace(b_in->pstate()));
633
+ throw Exception::SassValueError(traces, b_in->pstate(), err);
634
+ }
635
+ }
636
+ // lhs is color and rhs is number
637
+ else if (Number_Ptr r_n = Cast<Number>(rhs)) {
638
+ try {
639
+ switch (op_type) {
640
+ case Sass_OP::EQ: return *l_c == *r_n ? bool_true : bool_false;
641
+ case Sass_OP::NEQ: return *l_c == *r_n ? bool_false : bool_true;
642
+ case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
643
+ return Operators::op_color_number(op_type, *l_c, *r_n, ctx.c_options, b_in->pstate());
644
+ default: break;
645
+ }
646
+ }
647
+ catch (Exception::OperationError& err)
648
+ {
649
+ traces.push_back(Backtrace(b_in->pstate()));
650
+ throw Exception::SassValueError(traces, b_in->pstate(), err);
651
+ }
652
+ }
653
+ }
654
+
655
+ String_Schema_Obj ret_schema;
508
656
 
509
657
  // only the last item will be used to eval the binary expression
510
- if (String_Schema_Ptr s_l = SASS_MEMORY_CAST(String_Schema, b->left())) {
658
+ if (String_Schema_Ptr s_l = Cast<String_Schema>(b->left())) {
511
659
  if (!s_l->has_interpolant() && (!s_l->is_right_interpolant())) {
512
660
  ret_schema = SASS_MEMORY_NEW(String_Schema, b->pstate());
513
661
  Binary_Expression_Obj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(),
514
- b->op(), &s_l->last(), b->right());
662
+ b->op(), s_l->last(), b->right());
515
663
  bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // unverified
516
664
  for (size_t i = 0; i < s_l->length() - 1; ++i) {
517
665
  ret_schema->append(s_l->at(i)->perform(this));
@@ -520,12 +668,12 @@ namespace Sass {
520
668
  return ret_schema->perform(this);
521
669
  }
522
670
  }
523
- if (String_Schema_Ptr s_r = SASS_MEMORY_CAST(String_Schema, b->right())) {
671
+ if (String_Schema_Ptr s_r = Cast<String_Schema>(b->right())) {
524
672
 
525
673
  if (!s_r->has_interpolant() && (!s_r->is_left_interpolant() || op_type == Sass_OP::DIV)) {
526
674
  ret_schema = SASS_MEMORY_NEW(String_Schema, b->pstate());
527
675
  Binary_Expression_Obj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(),
528
- b->op(), b->left(), &s_r->first());
676
+ b->op(), b->left(), s_r->first());
529
677
  bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // verified
530
678
  ret_schema->append(bin_ex->perform(this));
531
679
  for (size_t i = 1; i < s_r->length(); ++i) {
@@ -535,16 +683,6 @@ namespace Sass {
535
683
  }
536
684
  }
537
685
 
538
- // don't eval delayed expressions (the '/' when used as a separator)
539
- if (!force && op_type == Sass_OP::DIV && b->is_delayed()) {
540
- b->right(b->right()->perform(this));
541
- b->left(b->left()->perform(this));
542
- return b.detach();
543
- }
544
-
545
- Expression_Obj lhs = b->left();
546
- Expression_Obj rhs = b->right();
547
-
548
686
  // fully evaluate their values
549
687
  if (op_type == Sass_OP::EQ ||
550
688
  op_type == Sass_OP::NEQ ||
@@ -565,32 +703,19 @@ namespace Sass {
565
703
  lhs = lhs->perform(this);
566
704
  }
567
705
 
568
- Binary_Expression_Obj u3 = b;
569
- switch (op_type) {
570
- case Sass_OP::AND: {
571
- return *lhs ? b->right()->perform(this) : lhs.detach();
572
- } break;
573
-
574
- case Sass_OP::OR: {
575
- return *lhs ? lhs.detach() : b->right()->perform(this);
576
- } break;
577
-
578
- default:
579
- break;
580
- }
581
706
  // not a logical connective, so go ahead and eval the rhs
582
707
  rhs = rhs->perform(this);
583
- AST_Node_Obj lu = &lhs;
584
- AST_Node_Obj ru = &rhs;
708
+ AST_Node_Obj lu = lhs;
709
+ AST_Node_Obj ru = rhs;
585
710
 
586
- Expression::Concrete_Type l_type = lhs->concrete_type();
587
- Expression::Concrete_Type r_type = rhs->concrete_type();
711
+ Expression::Concrete_Type l_type;
712
+ Expression::Concrete_Type r_type;
588
713
 
589
714
  // Is one of the operands an interpolant?
590
- String_Schema_Obj s1 = SASS_MEMORY_CAST(String_Schema, b->left());
591
- String_Schema_Obj s2 = SASS_MEMORY_CAST(String_Schema, b->right());
592
- Binary_Expression_Obj b1 = SASS_MEMORY_CAST(Binary_Expression, b->left());
593
- Binary_Expression_Obj b2 = SASS_MEMORY_CAST(Binary_Expression, b->right());
715
+ String_Schema_Obj s1 = Cast<String_Schema>(b->left());
716
+ String_Schema_Obj s2 = Cast<String_Schema>(b->right());
717
+ Binary_Expression_Obj b1 = Cast<Binary_Expression>(b->left());
718
+ Binary_Expression_Obj b2 = Cast<Binary_Expression>(b->right());
594
719
 
595
720
  bool schema_op = false;
596
721
 
@@ -604,40 +729,26 @@ namespace Sass {
604
729
  if (op_type == Sass_OP::DIV || op_type == Sass_OP::MUL || op_type == Sass_OP::MOD || op_type == Sass_OP::ADD || op_type == Sass_OP::SUB ||
605
730
  op_type == Sass_OP::EQ) {
606
731
  // If possible upgrade LHS to a number (for number to string compare)
607
- if (String_Constant_Ptr str = SASS_MEMORY_CAST(String_Constant, lhs)) {
732
+ if (String_Constant_Ptr str = Cast<String_Constant>(lhs)) {
608
733
  std::string value(str->value());
609
734
  const char* start = value.c_str();
610
735
  if (Prelexer::sequence < Prelexer::dimension, Prelexer::end_of_file >(start) != 0) {
611
- Textual_Obj l = SASS_MEMORY_NEW(Textual, b->pstate(), Textual::DIMENSION, str->value());
612
- lhs = l->perform(this);
736
+ lhs = Parser::lexed_dimension(b->pstate(), str->value());
613
737
  }
614
738
  }
615
739
  // If possible upgrade RHS to a number (for string to number compare)
616
- if (String_Constant_Ptr str = SASS_MEMORY_CAST(String_Constant, rhs)) {
740
+ if (String_Constant_Ptr str = Cast<String_Constant>(rhs)) {
617
741
  std::string value(str->value());
618
742
  const char* start = value.c_str();
619
743
  if (Prelexer::sequence < Prelexer::dimension, Prelexer::number >(start) != 0) {
620
- Textual_Obj r = SASS_MEMORY_NEW(Textual, b->pstate(), Textual::DIMENSION, str->value());
621
- rhs = r->perform(this);
744
+ rhs = Parser::lexed_dimension(b->pstate(), str->value());
622
745
  }
623
746
  }
624
747
  }
625
748
 
626
749
  To_Value to_value(ctx);
627
- Value_Obj v_l = dynamic_cast<Value_Ptr>(lhs->perform(&to_value));
628
- Value_Obj v_r = dynamic_cast<Value_Ptr>(rhs->perform(&to_value));
629
- l_type = lhs->concrete_type();
630
- r_type = rhs->concrete_type();
631
-
632
- if (s2 && s2->has_interpolants() && s2->length()) {
633
- Textual_Obj front = SASS_MEMORY_CAST(Textual, s2->elements().front());
634
- if (front && !front->is_interpolant())
635
- {
636
- // XXX: this is never hit via spec tests
637
- schema_op = true;
638
- rhs = front->perform(this);
639
- }
640
- }
750
+ Value_Obj v_l = Cast<Value>(lhs->perform(&to_value));
751
+ Value_Obj v_r = Cast<Value>(rhs->perform(&to_value));
641
752
 
642
753
  if (force_delay) {
643
754
  std::string str("");
@@ -655,19 +766,20 @@ namespace Sass {
655
766
  // see if it's a relational expression
656
767
  try {
657
768
  switch(op_type) {
658
- case Sass_OP::EQ: return SASS_MEMORY_NEW(Boolean, b->pstate(), eq(lhs, rhs));
659
- case Sass_OP::NEQ: return SASS_MEMORY_NEW(Boolean, b->pstate(), !eq(lhs, rhs));
660
- case Sass_OP::GT: return SASS_MEMORY_NEW(Boolean, b->pstate(), !lt(lhs, rhs, "gt") && !eq(lhs, rhs));
661
- case Sass_OP::GTE: return SASS_MEMORY_NEW(Boolean, b->pstate(), !lt(lhs, rhs, "gte"));
662
- case Sass_OP::LT: return SASS_MEMORY_NEW(Boolean, b->pstate(), lt(lhs, rhs, "lt"));
663
- case Sass_OP::LTE: return SASS_MEMORY_NEW(Boolean, b->pstate(), lt(lhs, rhs, "lte") || eq(lhs, rhs));
664
- default: break;
769
+ case Sass_OP::EQ: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::eq(lhs, rhs));
770
+ case Sass_OP::NEQ: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::neq(lhs, rhs));
771
+ case Sass_OP::GT: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::gt(lhs, rhs));
772
+ case Sass_OP::GTE: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::gte(lhs, rhs));
773
+ case Sass_OP::LT: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::lt(lhs, rhs));
774
+ case Sass_OP::LTE: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::lte(lhs, rhs));
775
+ default: break;
665
776
  }
666
777
  }
667
778
  catch (Exception::OperationError& err)
668
779
  {
669
780
  // throw Exception::Base(b->pstate(), err.what());
670
- throw Exception::SassValueError(b->pstate(), err);
781
+ traces.push_back(Backtrace(b->pstate()));
782
+ throw Exception::SassValueError(traces, b->pstate(), err);
671
783
  }
672
784
 
673
785
  l_type = lhs->concrete_type();
@@ -675,53 +787,56 @@ namespace Sass {
675
787
 
676
788
  // ToDo: throw error in op functions
677
789
  // ToDo: then catch and re-throw them
678
- Expression_Obj rv = 0;
790
+ Expression_Obj rv;
679
791
  try {
680
792
  ParserState pstate(b->pstate());
681
793
  if (l_type == Expression::NUMBER && r_type == Expression::NUMBER) {
682
- Number_Ptr l_n = SASS_MEMORY_CAST(Number, lhs);
683
- Number_Ptr r_n = SASS_MEMORY_CAST(Number, rhs);
684
- rv = op_numbers(op_type, *l_n, *r_n, ctx.c_options, &pstate);
794
+ Number_Ptr l_n = Cast<Number>(lhs);
795
+ Number_Ptr r_n = Cast<Number>(rhs);
796
+ l_n->reduce(); r_n->reduce();
797
+ rv = Operators::op_numbers(op_type, *l_n, *r_n, ctx.c_options, pstate);
685
798
  }
686
799
  else if (l_type == Expression::NUMBER && r_type == Expression::COLOR) {
687
- Number_Ptr l_n = SASS_MEMORY_CAST(Number, lhs);
688
- Color_Ptr r_c = SASS_MEMORY_CAST(Color, rhs);
689
- rv = op_number_color(op_type, *l_n, *r_c, ctx.c_options, &pstate);
800
+ Number_Ptr l_n = Cast<Number>(lhs);
801
+ Color_Ptr r_c = Cast<Color>(rhs);
802
+ rv = Operators::op_number_color(op_type, *l_n, *r_c, ctx.c_options, pstate);
690
803
  }
691
804
  else if (l_type == Expression::COLOR && r_type == Expression::NUMBER) {
692
- Color_Ptr l_c = SASS_MEMORY_CAST(Color, lhs);
693
- Number_Ptr r_n = SASS_MEMORY_CAST(Number, rhs);
694
- rv = op_color_number(op_type, *l_c, *r_n, ctx.c_options, &pstate);
805
+ Color_Ptr l_c = Cast<Color>(lhs);
806
+ Number_Ptr r_n = Cast<Number>(rhs);
807
+ rv = Operators::op_color_number(op_type, *l_c, *r_n, ctx.c_options, pstate);
695
808
  }
696
809
  else if (l_type == Expression::COLOR && r_type == Expression::COLOR) {
697
- Color_Ptr l_c = SASS_MEMORY_CAST(Color, lhs);
698
- Color_Ptr r_c = SASS_MEMORY_CAST(Color, rhs);
699
- rv = op_colors(op_type, *l_c, *r_c, ctx.c_options, &pstate);
810
+ Color_Ptr l_c = Cast<Color>(lhs);
811
+ Color_Ptr r_c = Cast<Color>(rhs);
812
+ rv = Operators::op_colors(op_type, *l_c, *r_c, ctx.c_options, pstate);
700
813
  }
701
814
  else {
702
815
  To_Value to_value(ctx);
703
816
  // this will leak if perform does not return a value!
704
- Value_Obj v_l = SASS_MEMORY_CAST_PTR(Value, lhs->perform(&to_value));
705
- Value_Obj v_r = SASS_MEMORY_CAST_PTR(Value, rhs->perform(&to_value));
817
+ Value_Obj v_l = Cast<Value>(lhs->perform(&to_value));
818
+ Value_Obj v_r = Cast<Value>(rhs->perform(&to_value));
706
819
  bool interpolant = b->is_right_interpolant() ||
707
820
  b->is_left_interpolant() ||
708
821
  b->is_interpolant();
709
822
  if (op_type == Sass_OP::SUB) interpolant = false;
710
823
  // if (op_type == Sass_OP::DIV) interpolant = true;
711
824
  // check for type violations
712
- if (l_type == Expression::MAP) {
713
- throw Exception::InvalidValue(*v_l);
825
+ if (l_type == Expression::MAP || l_type == Expression::FUNCTION_VAL) {
826
+ traces.push_back(Backtrace(v_l->pstate()));
827
+ throw Exception::InvalidValue(traces, *v_l);
714
828
  }
715
- if (r_type == Expression::MAP) {
716
- throw Exception::InvalidValue(*v_r);
829
+ if (r_type == Expression::MAP || l_type == Expression::FUNCTION_VAL) {
830
+ traces.push_back(Backtrace(v_r->pstate()));
831
+ throw Exception::InvalidValue(traces, *v_r);
717
832
  }
718
- Value_Ptr ex = op_strings(b->op(), *v_l, *v_r, ctx.c_options, &pstate, !interpolant); // pass true to compress
719
- if (String_Constant_Ptr str = dynamic_cast<String_Constant_Ptr>(ex))
833
+ Value_Ptr ex = Operators::op_strings(b->op(), *v_l, *v_r, ctx.c_options, pstate, !interpolant); // pass true to compress
834
+ if (String_Constant_Ptr str = Cast<String_Constant>(ex))
720
835
  {
721
836
  if (str->concrete_type() == Expression::STRING)
722
837
  {
723
- String_Constant_Ptr lstr = SASS_MEMORY_CAST(String_Constant, lhs);
724
- String_Constant_Ptr rstr = SASS_MEMORY_CAST(String_Constant, rhs);
838
+ String_Constant_Ptr lstr = Cast<String_Constant>(lhs);
839
+ String_Constant_Ptr rstr = Cast<String_Constant>(rhs);
725
840
  if (op_type != Sass_OP::SUB) {
726
841
  if (String_Constant_Ptr org = lstr ? lstr : rstr)
727
842
  { str->quote_mark(org->quote_mark()); }
@@ -734,8 +849,9 @@ namespace Sass {
734
849
  }
735
850
  catch (Exception::OperationError& err)
736
851
  {
852
+ traces.push_back(Backtrace(b->pstate()));
737
853
  // throw Exception::Base(b->pstate(), err.what());
738
- throw Exception::SassValueError(b->pstate(), err);
854
+ throw Exception::SassValueError(traces, b->pstate(), err);
739
855
  }
740
856
 
741
857
  if (rv) {
@@ -753,31 +869,36 @@ namespace Sass {
753
869
  Expression_Ptr Eval::operator()(Unary_Expression_Ptr u)
754
870
  {
755
871
  Expression_Obj operand = u->operand()->perform(this);
756
- if (u->type() == Unary_Expression::NOT) {
872
+ if (u->optype() == Unary_Expression::NOT) {
757
873
  Boolean_Ptr result = SASS_MEMORY_NEW(Boolean, u->pstate(), (bool)*operand);
758
874
  result->value(!result->value());
759
875
  return result;
760
876
  }
761
- else if (operand->concrete_type() == Expression::NUMBER) {
762
- Number_Ptr result = SASS_MEMORY_NEW(Number, static_cast<Number_Ptr>(&operand));
763
- result->value(u->type() == Unary_Expression::MINUS
764
- ? -result->value()
765
- : result->value());
766
- return result;
877
+ else if (Number_Obj nr = Cast<Number>(operand)) {
878
+ // negate value for minus unary expression
879
+ if (u->optype() == Unary_Expression::MINUS) {
880
+ Number_Obj cpy = SASS_MEMORY_COPY(nr);
881
+ cpy->value( - cpy->value() ); // negate value
882
+ return cpy.detach(); // return the copy
883
+ }
884
+ else if (u->optype() == Unary_Expression::SLASH) {
885
+ std::string str = '/' + nr->to_string(ctx.c_options);
886
+ return SASS_MEMORY_NEW(String_Constant, u->pstate(), str);
887
+ }
888
+ // nothing for positive
889
+ return nr.detach();
767
890
  }
768
891
  else {
769
892
  // Special cases: +/- variables which evaluate to null ouput just +/-,
770
893
  // but +/- null itself outputs the string
771
- if (operand->concrete_type() == Expression::NULL_VAL && SASS_MEMORY_CAST(Variable, u->operand())) {
894
+ if (operand->concrete_type() == Expression::NULL_VAL && Cast<Variable>(u->operand())) {
772
895
  u->operand(SASS_MEMORY_NEW(String_Quoted, u->pstate(), ""));
773
896
  }
774
897
  // Never apply unary opertions on colors @see #2140
775
- else if (operand->concrete_type() == Expression::COLOR) {
776
- Color_Ptr c = dynamic_cast<Color_Ptr>(&operand);
777
-
898
+ else if (Color_Ptr color = Cast<Color>(operand)) {
778
899
  // Use the color name if this was eval with one
779
- if (c->disp().length() > 0) {
780
- operand = SASS_MEMORY_NEW(String_Constant, operand->pstate(), c->disp());
900
+ if (color->disp().length() > 0) {
901
+ operand = SASS_MEMORY_NEW(String_Constant, operand->pstate(), color->disp());
781
902
  u->operand(operand);
782
903
  }
783
904
  }
@@ -785,10 +906,9 @@ namespace Sass {
785
906
  u->operand(operand);
786
907
  }
787
908
 
788
- String_Constant_Ptr result = SASS_MEMORY_NEW(String_Quoted,
789
- u->pstate(),
790
- u->inspect());
791
- return result;
909
+ return SASS_MEMORY_NEW(String_Quoted,
910
+ u->pstate(),
911
+ u->inspect());
792
912
  }
793
913
  // unreachable
794
914
  return u;
@@ -796,11 +916,11 @@ namespace Sass {
796
916
 
797
917
  Expression_Ptr Eval::operator()(Function_Call_Ptr c)
798
918
  {
799
- if (backtrace()->parent != NULL && backtrace()->depth() > Constants::MaxCallStack) {
919
+ if (traces.size() > Constants::MaxCallStack) {
800
920
  // XXX: this is never hit via spec tests
801
921
  std::ostringstream stm;
802
922
  stm << "Stack depth exceeded max of " << Constants::MaxCallStack;
803
- error(stm.str(), c->pstate(), backtrace());
923
+ error(stm.str(), c->pstate(), traces);
804
924
  }
805
925
  std::string name(Util::normalize_underscores(c->name()));
806
926
  std::string full_name(name + "[f]");
@@ -811,17 +931,17 @@ namespace Sass {
811
931
  if (!env->has(full_name) || (!c->via_call() && Prelexer::re_special_fun(name.c_str()))) {
812
932
  if (!env->has("*[f]")) {
813
933
  for (Argument_Obj arg : args->elements()) {
814
- if (List_Obj ls = SASS_MEMORY_CAST(List, arg->value())) {
815
- if (ls->size() == 0) error("() isn't a valid CSS value.", c->pstate());
934
+ if (List_Obj ls = Cast<List>(arg->value())) {
935
+ if (ls->size() == 0) error("() isn't a valid CSS value.", c->pstate(), traces);
816
936
  }
817
937
  }
818
- args = SASS_MEMORY_CAST_PTR(Arguments, args->perform(this));
938
+ args = Cast<Arguments>(args->perform(this));
819
939
  Function_Call_Obj lit = SASS_MEMORY_NEW(Function_Call,
820
940
  c->pstate(),
821
941
  c->name(),
822
- &args);
942
+ args);
823
943
  if (args->has_named_arguments()) {
824
- error("Function " + c->name() + " doesn't support keyword arguments", c->pstate());
944
+ error("Function " + c->name() + " doesn't support keyword arguments", c->pstate(), traces);
825
945
  }
826
946
  String_Quoted_Ptr str = SASS_MEMORY_NEW(String_Quoted,
827
947
  c->pstate(),
@@ -839,9 +959,11 @@ namespace Sass {
839
959
  args->set_delayed(false); // verified
840
960
  }
841
961
  if (full_name != "if[f]") {
842
- args = SASS_MEMORY_CAST_PTR(Arguments, args->perform(this));
962
+ args = Cast<Arguments>(args->perform(this));
843
963
  }
844
- Definition_Ptr def = SASS_MEMORY_CAST(Definition, (*env)[full_name]);
964
+ Definition_Ptr def = Cast<Definition>((*env)[full_name]);
965
+
966
+ if (c->func()) def = c->func()->definition();
845
967
 
846
968
  if (def->is_overload_stub()) {
847
969
  std::stringstream ss;
@@ -849,15 +971,15 @@ namespace Sass {
849
971
  // account for rest arguments
850
972
  if (args->has_rest_argument() && args->length() > 0) {
851
973
  // get the rest arguments list
852
- List_Ptr rest = SASS_MEMORY_CAST(List, args->last()->value());
974
+ List_Ptr rest = Cast<List>(args->last()->value());
853
975
  // arguments before rest argument plus rest
854
976
  if (rest) L += rest->length() - 1;
855
977
  }
856
978
  ss << full_name << L;
857
979
  full_name = ss.str();
858
980
  std::string resolved_name(full_name);
859
- if (!env->has(resolved_name)) error("overloaded function `" + std::string(c->name()) + "` given wrong number of arguments", c->pstate());
860
- def = SASS_MEMORY_CAST(Definition, (*env)[resolved_name]);
981
+ if (!env->has(resolved_name)) error("overloaded function `" + std::string(c->name()) + "` given wrong number of arguments", c->pstate(), traces);
982
+ def = Cast<Definition>((*env)[resolved_name]);
861
983
  }
862
984
 
863
985
  Expression_Obj result = c;
@@ -865,25 +987,37 @@ namespace Sass {
865
987
  Native_Function func = def->native_function();
866
988
  Sass_Function_Entry c_function = def->c_function();
867
989
 
990
+ if (c->is_css()) return result.detach();
991
+
868
992
  Parameters_Obj params = def->parameters();
869
993
  Env fn_env(def->environment());
870
994
  exp.env_stack.push_back(&fn_env);
871
995
 
872
996
  if (func || body) {
873
997
  bind(std::string("Function"), c->name(), params, args, &ctx, &fn_env, this);
874
- Backtrace here(backtrace(), c->pstate(), ", in function `" + c->name() + "`");
875
- exp.backtrace_stack.push_back(&here);
998
+ std::string msg(", in function `" + c->name() + "`");
999
+ traces.push_back(Backtrace(c->pstate(), msg));
1000
+ ctx.callee_stack.push_back({
1001
+ c->name().c_str(),
1002
+ c->pstate().path,
1003
+ c->pstate().line + 1,
1004
+ c->pstate().column + 1,
1005
+ SASS_CALLEE_FUNCTION,
1006
+ { env }
1007
+ });
1008
+
876
1009
  // eval the body if user-defined or special, invoke underlying CPP function if native
877
1010
  if (body /* && !Prelexer::re_special_fun(name.c_str()) */) {
878
1011
  result = body->perform(this);
879
1012
  }
880
1013
  else if (func) {
881
- result = func(fn_env, *env, ctx, def->signature(), c->pstate(), backtrace(), exp.selector_stack);
1014
+ result = func(fn_env, *env, ctx, def->signature(), c->pstate(), traces, exp.selector_stack);
882
1015
  }
883
1016
  if (!result) {
884
- error(std::string("Function ") + c->name() + " did not return a value", c->pstate());
1017
+ error(std::string("Function ") + c->name() + " finished without @return", c->pstate(), traces);
885
1018
  }
886
- exp.backtrace_stack.pop_back();
1019
+ ctx.callee_stack.pop_back();
1020
+ traces.pop_back();
887
1021
  }
888
1022
 
889
1023
  // else if it's a user-defined c function
@@ -893,36 +1027,44 @@ namespace Sass {
893
1027
  if (full_name == "*[f]") {
894
1028
  String_Quoted_Obj str = SASS_MEMORY_NEW(String_Quoted, c->pstate(), c->name());
895
1029
  Arguments_Obj new_args = SASS_MEMORY_NEW(Arguments, c->pstate());
896
- new_args->append(SASS_MEMORY_NEW(Argument, c->pstate(), &str));
897
- new_args->concat(&args);
1030
+ new_args->append(SASS_MEMORY_NEW(Argument, c->pstate(), str));
1031
+ new_args->concat(args);
898
1032
  args = new_args;
899
1033
  }
900
1034
 
901
1035
  // populates env with default values for params
902
1036
  std::string ff(c->name());
903
1037
  bind(std::string("Function"), c->name(), params, args, &ctx, &fn_env, this);
904
-
905
- Backtrace here(backtrace(), c->pstate(), ", in function `" + c->name() + "`");
906
- exp.backtrace_stack.push_back(&here);
1038
+ std::string msg(", in function `" + c->name() + "`");
1039
+ traces.push_back(Backtrace(c->pstate(), msg));
1040
+ ctx.callee_stack.push_back({
1041
+ c->name().c_str(),
1042
+ c->pstate().path,
1043
+ c->pstate().line + 1,
1044
+ c->pstate().column + 1,
1045
+ SASS_CALLEE_C_FUNCTION,
1046
+ { env }
1047
+ });
907
1048
 
908
1049
  To_C to_c;
909
- union Sass_Value* c_args = sass_make_list(params->length(), SASS_COMMA);
1050
+ union Sass_Value* c_args = sass_make_list(params->length(), SASS_COMMA, false);
910
1051
  for(size_t i = 0; i < params->length(); i++) {
911
1052
  Parameter_Obj param = params->at(i);
912
1053
  std::string key = param->name();
913
1054
  AST_Node_Obj node = fn_env.get_local(key);
914
- Expression_Obj arg = SASS_MEMORY_CAST(Expression, node);
1055
+ Expression_Obj arg = Cast<Expression>(node);
915
1056
  sass_list_set_value(c_args, i, arg->perform(&to_c));
916
1057
  }
917
1058
  union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
918
1059
  if (sass_value_get_tag(c_val) == SASS_ERROR) {
919
- error("error in C function " + c->name() + ": " + sass_error_get_message(c_val), c->pstate(), backtrace());
1060
+ error("error in C function " + c->name() + ": " + sass_error_get_message(c_val), c->pstate(), traces);
920
1061
  } else if (sass_value_get_tag(c_val) == SASS_WARNING) {
921
- error("warning in C function " + c->name() + ": " + sass_warning_get_message(c_val), c->pstate(), backtrace());
1062
+ error("warning in C function " + c->name() + ": " + sass_warning_get_message(c_val), c->pstate(), traces);
922
1063
  }
923
- result = cval_to_astnode(c_val, backtrace(), c->pstate());
1064
+ result = cval_to_astnode(c_val, traces, c->pstate());
924
1065
 
925
- exp.backtrace_stack.pop_back();
1066
+ ctx.callee_stack.pop_back();
1067
+ traces.pop_back();
926
1068
  sass_delete_value(c_args);
927
1069
  if (c_val != c_args)
928
1070
  sass_delete_value(c_val);
@@ -951,104 +1093,22 @@ namespace Sass {
951
1093
 
952
1094
  Expression_Ptr Eval::operator()(Variable_Ptr v)
953
1095
  {
954
- std::string name(v->name());
955
1096
  Expression_Obj value = 0;
956
1097
  Env* env = environment();
957
- if (env->has(name)) {
958
- value = SASS_MEMORY_CAST(Expression, (*env)[name]);
959
- }
960
- else error("Undefined variable: \"" + v->name() + "\".", v->pstate());
961
- if (typeid(*value) == typeid(Argument)) {
962
- value = SASS_MEMORY_CAST(Argument, value)->value();
963
- }
964
-
965
- // behave according to as ruby sass (add leading zero)
966
- if (Number_Ptr nr = SASS_MEMORY_CAST(Number, value)) {
967
- nr->zero(true);
968
- }
969
-
1098
+ const std::string& name(v->name());
1099
+ EnvResult rv(env->find(name));
1100
+ if (rv.found) value = static_cast<Expression*>(rv.it->second.ptr());
1101
+ else error("Undefined variable: \"" + v->name() + "\".", v->pstate(), traces);
1102
+ if (Argument_Ptr arg = Cast<Argument>(value)) value = arg->value();
1103
+ if (Number_Ptr nr = Cast<Number>(value)) nr->zero(true); // force flag
970
1104
  value->is_interpolant(v->is_interpolant());
971
1105
  if (force) value->is_expanded(false);
972
1106
  value->set_delayed(false); // verified
973
1107
  value = value->perform(this);
974
- if(!force) (*env)[name] = &value;
1108
+ if(!force) rv.it->second = value;
975
1109
  return value.detach();
976
1110
  }
977
1111
 
978
- Expression_Ptr Eval::operator()(Textual_Ptr t)
979
- {
980
- using Prelexer::number;
981
- Expression_Obj result = 0;
982
- size_t L = t->value().length();
983
- bool zero = !( (L > 0 && t->value().substr(0, 1) == ".") ||
984
- (L > 1 && t->value().substr(0, 2) == "0.") ||
985
- (L > 1 && t->value().substr(0, 2) == "-.") ||
986
- (L > 2 && t->value().substr(0, 3) == "-0.")
987
- );
988
-
989
- const std::string& text = t->value();
990
- size_t num_pos = text.find_first_not_of(" \n\r\t");
991
- if (num_pos == std::string::npos) num_pos = text.length();
992
- size_t unit_pos = text.find_first_not_of("-+0123456789.", num_pos);
993
- if (unit_pos == std::string::npos) unit_pos = text.length();
994
- const std::string& num = text.substr(num_pos, unit_pos - num_pos);
995
-
996
- switch (t->type())
997
- {
998
- case Textual::NUMBER:
999
- result = SASS_MEMORY_NEW(Number,
1000
- t->pstate(),
1001
- sass_atof(num.c_str()),
1002
- "",
1003
- zero);
1004
- break;
1005
- case Textual::PERCENTAGE:
1006
- result = SASS_MEMORY_NEW(Number,
1007
- t->pstate(),
1008
- sass_atof(num.c_str()),
1009
- "%",
1010
- true);
1011
- break;
1012
- case Textual::DIMENSION:
1013
- result = SASS_MEMORY_NEW(Number,
1014
- t->pstate(),
1015
- sass_atof(num.c_str()),
1016
- Token(number(text.c_str())),
1017
- zero);
1018
- break;
1019
- case Textual::HEX: {
1020
- if (t->value().substr(0, 1) != "#") {
1021
- result = SASS_MEMORY_NEW(String_Quoted, t->pstate(), t->value());
1022
- break;
1023
- }
1024
- std::string hext(t->value().substr(1)); // chop off the '#'
1025
- if (hext.length() == 6) {
1026
- std::string r(hext.substr(0,2));
1027
- std::string g(hext.substr(2,2));
1028
- std::string b(hext.substr(4,2));
1029
- result = SASS_MEMORY_NEW(Color,
1030
- t->pstate(),
1031
- static_cast<double>(strtol(r.c_str(), NULL, 16)),
1032
- static_cast<double>(strtol(g.c_str(), NULL, 16)),
1033
- static_cast<double>(strtol(b.c_str(), NULL, 16)),
1034
- 1, // alpha channel
1035
- t->value());
1036
- }
1037
- else {
1038
- result = SASS_MEMORY_NEW(Color,
1039
- t->pstate(),
1040
- static_cast<double>(strtol(std::string(2,hext[0]).c_str(), NULL, 16)),
1041
- static_cast<double>(strtol(std::string(2,hext[1]).c_str(), NULL, 16)),
1042
- static_cast<double>(strtol(std::string(2,hext[2]).c_str(), NULL, 16)),
1043
- 1, // alpha channel
1044
- t->value());
1045
- }
1046
- } break;
1047
- }
1048
- result->is_interpolant(t->is_interpolant());
1049
- return result.detach();
1050
- }
1051
-
1052
1112
  Expression_Ptr Eval::operator()(Color_Ptr c)
1053
1113
  {
1054
1114
  return c;
@@ -1068,7 +1128,7 @@ namespace Sass {
1068
1128
 
1069
1129
  bool needs_closing_brace = false;
1070
1130
 
1071
- if (Arguments_Ptr args = SASS_MEMORY_CAST(Arguments, ex)) {
1131
+ if (Arguments_Ptr args = Cast<Arguments>(ex)) {
1072
1132
  List_Ptr ll = SASS_MEMORY_NEW(List, args->pstate(), 0, SASS_COMMA);
1073
1133
  for(auto arg : args->elements()) {
1074
1134
  ll->append(arg->value());
@@ -1078,15 +1138,18 @@ namespace Sass {
1078
1138
  res += "(";
1079
1139
  ex = ll;
1080
1140
  }
1081
- if (Number_Ptr nr = SASS_MEMORY_CAST(Number, ex)) {
1082
- if (!nr->is_valid_css_unit()) {
1083
- throw Exception::InvalidValue(*nr);
1141
+ if (Number_Ptr nr = Cast<Number>(ex)) {
1142
+ Number reduced(nr);
1143
+ reduced.reduce();
1144
+ if (!reduced.is_valid_css_unit()) {
1145
+ traces.push_back(Backtrace(nr->pstate()));
1146
+ throw Exception::InvalidValue(traces, *nr);
1084
1147
  }
1085
1148
  }
1086
- if (Argument_Ptr arg = SASS_MEMORY_CAST(Argument, ex)) {
1087
- ex = &arg->value();
1149
+ if (Argument_Ptr arg = Cast<Argument>(ex)) {
1150
+ ex = arg->value();
1088
1151
  }
1089
- if (String_Quoted_Ptr sq = SASS_MEMORY_CAST(String_Quoted, ex)) {
1152
+ if (String_Quoted_Ptr sq = Cast<String_Quoted>(ex)) {
1090
1153
  if (was_itpl) {
1091
1154
  bool was_interpolant = ex->is_interpolant();
1092
1155
  ex = SASS_MEMORY_NEW(String_Constant, sq->pstate(), sq->value());
@@ -1094,22 +1157,22 @@ namespace Sass {
1094
1157
  }
1095
1158
  }
1096
1159
 
1097
- if (SASS_MEMORY_CAST(Null, ex)) { return; }
1160
+ if (Cast<Null>(ex)) { return; }
1098
1161
 
1099
1162
  // parent selector needs another go
1100
- if (SASS_MEMORY_CAST(Parent_Selector, ex)) {
1163
+ if (Cast<Parent_Selector>(ex)) {
1101
1164
  // XXX: this is never hit via spec tests
1102
1165
  ex = ex->perform(this);
1103
1166
  }
1104
1167
 
1105
- if (List_Ptr l = SASS_MEMORY_CAST(List, ex)) {
1168
+ if (List_Ptr l = Cast<List>(ex)) {
1106
1169
  List_Obj ll = SASS_MEMORY_NEW(List, l->pstate(), 0, l->separator());
1107
1170
  // this fixes an issue with bourbon sample, not really sure why
1108
- // if (l->size() && dynamic_cast<Null_Ptr>((*l)[0])) { res += ""; }
1171
+ // if (l->size() && Cast<Null>((*l)[0])) { res += ""; }
1109
1172
  for(Expression_Obj item : *l) {
1110
1173
  item->is_interpolant(l->is_interpolant());
1111
- std::string rl(""); interpolation(ctx, rl, &item, into_quotes, l->is_interpolant());
1112
- bool is_null = dynamic_cast<Null_Ptr>(&item) != 0; // rl != ""
1174
+ std::string rl(""); interpolation(ctx, rl, item, into_quotes, l->is_interpolant());
1175
+ bool is_null = Cast<Null>(item) != 0; // rl != ""
1113
1176
  if (!is_null) ll->append(SASS_MEMORY_NEW(String_Quoted, item->pstate(), rl));
1114
1177
  }
1115
1178
  // Check indicates that we probably should not get a list
@@ -1117,6 +1180,7 @@ namespace Sass {
1117
1180
  if (l->size() > 1) {
1118
1181
  // string_to_output would fail "#{'_\a' '_\a'}";
1119
1182
  std::string str(ll->to_string(ctx.c_options));
1183
+ str = read_hex_escapes(str); // read escapes
1120
1184
  newline_to_space(str); // replace directly
1121
1185
  res += str; // append to result string
1122
1186
  } else {
@@ -1126,7 +1190,6 @@ namespace Sass {
1126
1190
  }
1127
1191
 
1128
1192
  // Value
1129
- // Textual
1130
1193
  // Function_Call
1131
1194
  // Selector_List
1132
1195
  // String_Quoted
@@ -1138,7 +1201,9 @@ namespace Sass {
1138
1201
  if (into_quotes && ex->is_interpolant()) {
1139
1202
  res += evacuate_escapes(ex ? ex->to_string(ctx.c_options) : "");
1140
1203
  } else {
1141
- res += ex ? ex->to_string(ctx.c_options) : "";
1204
+ std::string str(ex ? ex->to_string(ctx.c_options) : "");
1205
+ if (into_quotes) str = read_hex_escapes(str);
1206
+ res += str; // append to result string
1142
1207
  }
1143
1208
  }
1144
1209
 
@@ -1151,9 +1216,9 @@ namespace Sass {
1151
1216
  size_t L = s->length();
1152
1217
  bool into_quotes = false;
1153
1218
  if (L > 1) {
1154
- if (!SASS_MEMORY_CAST(String_Quoted, (*s)[0]) && !SASS_MEMORY_CAST(String_Quoted, (*s)[L - 1])) {
1155
- if (String_Constant_Ptr l = SASS_MEMORY_CAST(String_Constant, (*s)[0])) {
1156
- if (String_Constant_Ptr r = SASS_MEMORY_CAST(String_Constant, (*s)[L - 1])) {
1219
+ if (!Cast<String_Quoted>((*s)[0]) && !Cast<String_Quoted>((*s)[L - 1])) {
1220
+ if (String_Constant_Ptr l = Cast<String_Constant>((*s)[0])) {
1221
+ if (String_Constant_Ptr r = Cast<String_Constant>((*s)[L - 1])) {
1157
1222
  if (r->value().size() > 0) {
1158
1223
  if (l->value()[0] == '"' && r->value()[r->value().size() - 1] == '"') into_quotes = true;
1159
1224
  if (l->value()[0] == '\'' && r->value()[r->value().size() - 1] == '\'') into_quotes = true;
@@ -1166,21 +1231,21 @@ namespace Sass {
1166
1231
  bool was_interpolant = false;
1167
1232
  std::string res("");
1168
1233
  for (size_t i = 0; i < L; ++i) {
1169
- bool is_quoted = SASS_MEMORY_CAST(String_Quoted, (*s)[i]) != NULL;
1234
+ bool is_quoted = Cast<String_Quoted>((*s)[i]) != NULL;
1170
1235
  if (was_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
1171
1236
  else if (i > 0 && is_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
1172
1237
  Expression_Obj ex = (*s)[i]->perform(this);
1173
1238
  interpolation(ctx, res, ex, into_quotes, ex->is_interpolant());
1174
- was_quoted = SASS_MEMORY_CAST(String_Quoted, (*s)[i]) != NULL;
1239
+ was_quoted = Cast<String_Quoted>((*s)[i]) != NULL;
1175
1240
  was_interpolant = (*s)[i]->is_interpolant();
1176
1241
 
1177
1242
  }
1178
1243
  if (!s->is_interpolant()) {
1179
1244
  if (s->length() > 1 && res == "") return SASS_MEMORY_NEW(Null, s->pstate());
1180
- return SASS_MEMORY_NEW(String_Constant, s->pstate(), res);
1245
+ return SASS_MEMORY_NEW(String_Constant, s->pstate(), res, s->css());
1181
1246
  }
1182
1247
  // string schema seems to have a special unquoting behavior (also handles "nested" quotes)
1183
- String_Quoted_Obj str = SASS_MEMORY_NEW(String_Quoted, s->pstate(), res, 0, false, false, false);
1248
+ String_Quoted_Obj str = SASS_MEMORY_NEW(String_Quoted, s->pstate(), res, 0, false, false, false, s->css());
1184
1249
  // if (s->is_interpolant()) str->quote_mark(0);
1185
1250
  // String_Constant_Ptr str = SASS_MEMORY_NEW(String_Constant, s->pstate(), res);
1186
1251
  if (str->quote_mark()) str->quote_mark('*');
@@ -1192,13 +1257,6 @@ namespace Sass {
1192
1257
 
1193
1258
  Expression_Ptr Eval::operator()(String_Constant_Ptr s)
1194
1259
  {
1195
- if (!s->is_delayed() && name_to_color(s->value())) {
1196
- Color_Ptr c = SASS_MEMORY_COPY(name_to_color(s->value())); // copy
1197
- c->pstate(s->pstate());
1198
- c->disp(s->value());
1199
- c->is_delayed(true);
1200
- return c;
1201
- }
1202
1260
  return s;
1203
1261
  }
1204
1262
 
@@ -1217,8 +1275,8 @@ namespace Sass {
1217
1275
  Expression_Ptr right = c->right()->perform(this);
1218
1276
  Supports_Operator_Ptr cc = SASS_MEMORY_NEW(Supports_Operator,
1219
1277
  c->pstate(),
1220
- dynamic_cast<Supports_Condition_Ptr>(left),
1221
- dynamic_cast<Supports_Condition_Ptr>(right),
1278
+ Cast<Supports_Condition>(left),
1279
+ Cast<Supports_Condition>(right),
1222
1280
  c->operand());
1223
1281
  return cc;
1224
1282
  }
@@ -1228,7 +1286,7 @@ namespace Sass {
1228
1286
  Expression_Ptr condition = c->condition()->perform(this);
1229
1287
  Supports_Negation_Ptr cc = SASS_MEMORY_NEW(Supports_Negation,
1230
1288
  c->pstate(),
1231
- dynamic_cast<Supports_Condition_Ptr>(condition));
1289
+ Cast<Supports_Condition>(condition));
1232
1290
  return cc;
1233
1291
  }
1234
1292
 
@@ -1260,18 +1318,18 @@ namespace Sass {
1260
1318
  value = (value ? value->perform(this) : 0);
1261
1319
  Expression_Ptr ee = SASS_MEMORY_NEW(At_Root_Query,
1262
1320
  e->pstate(),
1263
- dynamic_cast<String_Ptr>(&feature),
1321
+ Cast<String>(feature),
1264
1322
  value);
1265
1323
  return ee;
1266
1324
  }
1267
1325
 
1268
- Expression_Ptr Eval::operator()(Media_Query_Ptr q)
1326
+ Media_Query_Ptr Eval::operator()(Media_Query_Ptr q)
1269
1327
  {
1270
1328
  String_Obj t = q->media_type();
1271
- t = static_cast<String_Ptr>(&t ? t->perform(this) : 0);
1329
+ t = static_cast<String_Ptr>(t.isNull() ? 0 : t->perform(this));
1272
1330
  Media_Query_Obj qq = SASS_MEMORY_NEW(Media_Query,
1273
1331
  q->pstate(),
1274
- &t,
1332
+ t,
1275
1333
  q->length(),
1276
1334
  q->is_negated(),
1277
1335
  q->is_restricted());
@@ -1285,18 +1343,18 @@ namespace Sass {
1285
1343
  {
1286
1344
  Expression_Obj feature = e->feature();
1287
1345
  feature = (feature ? feature->perform(this) : 0);
1288
- if (feature && SASS_MEMORY_CAST(String_Quoted, feature)) {
1346
+ if (feature && Cast<String_Quoted>(feature)) {
1289
1347
  feature = SASS_MEMORY_NEW(String_Quoted,
1290
1348
  feature->pstate(),
1291
- SASS_MEMORY_CAST(String_Quoted, feature)->value());
1349
+ Cast<String_Quoted>(feature)->value());
1292
1350
  }
1293
1351
  Expression_Obj value = e->value();
1294
1352
  value = (value ? value->perform(this) : 0);
1295
- if (value && SASS_MEMORY_CAST(String_Quoted, value)) {
1353
+ if (value && Cast<String_Quoted>(value)) {
1296
1354
  // XXX: this is never hit via spec tests
1297
1355
  value = SASS_MEMORY_NEW(String_Quoted,
1298
1356
  value->pstate(),
1299
- SASS_MEMORY_CAST(String_Quoted, value)->value());
1357
+ Cast<String_Quoted>(value)->value());
1300
1358
  }
1301
1359
  return SASS_MEMORY_NEW(Media_Query_Expression,
1302
1360
  e->pstate(),
@@ -1328,7 +1386,7 @@ namespace Sass {
1328
1386
  SASS_COMMA,
1329
1387
  true);
1330
1388
  wrapper->append(val);
1331
- val = &wrapper;
1389
+ val = wrapper;
1332
1390
  }
1333
1391
  }
1334
1392
  return SASS_MEMORY_NEW(Argument,
@@ -1345,7 +1403,7 @@ namespace Sass {
1345
1403
  if (a->length() == 0) return aa.detach();
1346
1404
  for (size_t i = 0, L = a->length(); i < L; ++i) {
1347
1405
  Expression_Obj rv = (*a)[i]->perform(this);
1348
- Argument_Ptr arg = SASS_MEMORY_CAST(Argument, rv);
1406
+ Argument_Ptr arg = Cast<Argument>(rv);
1349
1407
  if (!(arg->is_rest_argument() || arg->is_keyword_argument())) {
1350
1408
  aa->append(arg);
1351
1409
  }
@@ -1353,11 +1411,11 @@ namespace Sass {
1353
1411
 
1354
1412
  if (a->has_rest_argument()) {
1355
1413
  Expression_Obj rest = a->get_rest_argument()->perform(this);
1356
- Expression_Obj splat = SASS_MEMORY_CAST(Argument, rest)->value()->perform(this);
1414
+ Expression_Obj splat = Cast<Argument>(rest)->value()->perform(this);
1357
1415
 
1358
1416
  Sass_Separator separator = SASS_COMMA;
1359
- List_Ptr ls = SASS_MEMORY_CAST(List, splat);
1360
- Map_Ptr ms = SASS_MEMORY_CAST(Map, splat);
1417
+ List_Ptr ls = Cast<List>(splat);
1418
+ Map_Ptr ms = Cast<Map>(splat);
1361
1419
 
1362
1420
  List_Obj arglist = SASS_MEMORY_NEW(List,
1363
1421
  splat->pstate(),
@@ -1375,13 +1433,13 @@ namespace Sass {
1375
1433
  arglist->append(splat);
1376
1434
  }
1377
1435
  if (arglist->length()) {
1378
- aa->append(SASS_MEMORY_NEW(Argument, splat->pstate(), &arglist, "", true));
1436
+ aa->append(SASS_MEMORY_NEW(Argument, splat->pstate(), arglist, "", true));
1379
1437
  }
1380
1438
  }
1381
1439
 
1382
1440
  if (a->has_keyword_argument()) {
1383
1441
  Expression_Obj rv = a->get_keyword_argument()->perform(this);
1384
- Argument_Ptr rvarg = SASS_MEMORY_CAST(Argument, rv);
1442
+ Argument_Ptr rvarg = Cast<Argument>(rv);
1385
1443
  Expression_Obj kwarg = rvarg->value()->perform(this);
1386
1444
 
1387
1445
  aa->append(SASS_MEMORY_NEW(Argument, kwarg->pstate(), kwarg, "", false, true));
@@ -1401,191 +1459,7 @@ namespace Sass {
1401
1459
 
1402
1460
  // All the binary helpers.
1403
1461
 
1404
- bool Eval::eq(Expression_Obj lhs, Expression_Obj rhs)
1405
- {
1406
- // use compare operator from ast node
1407
- return lhs && rhs && *lhs == *rhs;
1408
- }
1409
-
1410
- bool Eval::lt(Expression_Obj lhs, Expression_Obj rhs, std::string op)
1411
- {
1412
- Number_Obj l = SASS_MEMORY_CAST(Number, lhs);
1413
- Number_Obj r = SASS_MEMORY_CAST(Number, rhs);
1414
- // use compare operator from ast node
1415
- if (!l || !r) throw Exception::UndefinedOperation(&lhs, &rhs, op);
1416
- // use compare operator from ast node
1417
- return *l < *r;
1418
- }
1419
-
1420
- Value_Ptr Eval::op_numbers(enum Sass_OP op, const Number& l, const Number& r, struct Sass_Inspect_Options opt, ParserState* pstate)
1421
- {
1422
- double lv = l.value();
1423
- double rv = r.value();
1424
- if (op == Sass_OP::DIV && rv == 0) {
1425
- // XXX: this is never hit via spec tests
1426
- return SASS_MEMORY_NEW(String_Quoted, pstate ? *pstate : l.pstate(), lv ? "Infinity" : "NaN");
1427
- }
1428
- if (op == Sass_OP::MOD && !rv) {
1429
- // XXX: this is never hit via spec tests
1430
- throw Exception::ZeroDivisionError(l, r);
1431
- }
1432
-
1433
- Number tmp(&r); // copy
1434
- bool strict = op != Sass_OP::MUL && op != Sass_OP::DIV;
1435
- tmp.normalize(l.find_convertible_unit(), strict);
1436
- std::string l_unit(l.unit());
1437
- std::string r_unit(tmp.unit());
1438
- Number_Obj v = SASS_MEMORY_COPY(&l); // copy
1439
- v->pstate(pstate ? *pstate : l.pstate());
1440
- if (l_unit.empty() && (op == Sass_OP::ADD || op == Sass_OP::SUB || op == Sass_OP::MOD)) {
1441
- v->numerator_units() = r.numerator_units();
1442
- v->denominator_units() = r.denominator_units();
1443
- }
1444
-
1445
- if (op == Sass_OP::MUL) {
1446
- v->value(ops[op](lv, rv));
1447
- for (size_t i = 0, S = r.numerator_units().size(); i < S; ++i) {
1448
- v->numerator_units().push_back(r.numerator_units()[i]);
1449
- }
1450
- for (size_t i = 0, S = r.denominator_units().size(); i < S; ++i) {
1451
- v->denominator_units().push_back(r.denominator_units()[i]);
1452
- }
1453
- }
1454
- else if (op == Sass_OP::DIV) {
1455
- v->value(ops[op](lv, rv));
1456
- for (size_t i = 0, S = r.numerator_units().size(); i < S; ++i) {
1457
- v->denominator_units().push_back(r.numerator_units()[i]);
1458
- }
1459
- for (size_t i = 0, S = r.denominator_units().size(); i < S; ++i) {
1460
- v->numerator_units().push_back(r.denominator_units()[i]);
1461
- }
1462
- } else {
1463
- v->value(ops[op](lv, r.value() * r.convert_factor(l)));
1464
- // v->normalize();
1465
- return v.detach();
1466
-
1467
- v->value(ops[op](lv, tmp.value()));
1468
- }
1469
- v->normalize();
1470
- return v.detach();
1471
- }
1472
-
1473
- Value_Ptr Eval::op_number_color(enum Sass_OP op, const Number& l, const Color& r, struct Sass_Inspect_Options opt, ParserState* pstate)
1474
- {
1475
- double lv = l.value();
1476
- switch (op) {
1477
- case Sass_OP::ADD:
1478
- case Sass_OP::MUL: {
1479
- return SASS_MEMORY_NEW(Color,
1480
- pstate ? *pstate : l.pstate(),
1481
- ops[op](lv, r.r()),
1482
- ops[op](lv, r.g()),
1483
- ops[op](lv, r.b()),
1484
- r.a());
1485
- } break;
1486
- case Sass_OP::SUB:
1487
- case Sass_OP::DIV: {
1488
- std::string sep(op == Sass_OP::SUB ? "-" : "/");
1489
- std::string color(r.to_string(opt));
1490
- return SASS_MEMORY_NEW(String_Quoted,
1491
- pstate ? *pstate : l.pstate(),
1492
- l.to_string(opt)
1493
- + sep
1494
- + color);
1495
- } break;
1496
- case Sass_OP::MOD: {
1497
- throw Exception::UndefinedOperation(&l, &r, sass_op_to_name(op));
1498
- } break;
1499
- default: break; // caller should ensure that we don't get here
1500
- }
1501
- // unreachable
1502
- return NULL;
1503
- }
1504
-
1505
- Value_Ptr Eval::op_color_number(enum Sass_OP op, const Color& l, const Number& r, struct Sass_Inspect_Options opt, ParserState* pstate)
1506
- {
1507
- double rv = r.value();
1508
- if (op == Sass_OP::DIV && !rv) {
1509
- // comparison of Fixnum with Float failed?
1510
- throw Exception::ZeroDivisionError(l, r);
1511
- }
1512
- return SASS_MEMORY_NEW(Color,
1513
- pstate ? *pstate : l.pstate(),
1514
- ops[op](l.r(), rv),
1515
- ops[op](l.g(), rv),
1516
- ops[op](l.b(), rv),
1517
- l.a());
1518
- }
1519
-
1520
- Value_Ptr Eval::op_colors(enum Sass_OP op, const Color& l, const Color& r, struct Sass_Inspect_Options opt, ParserState* pstate)
1521
- {
1522
- if (l.a() != r.a()) {
1523
- throw Exception::AlphaChannelsNotEqual(&l, &r, "+");
1524
- }
1525
- if (op == Sass_OP::DIV && (!r.r() || !r.g() ||!r.b())) {
1526
- // comparison of Fixnum with Float failed?
1527
- throw Exception::ZeroDivisionError(l, r);
1528
- }
1529
- return SASS_MEMORY_NEW(Color,
1530
- pstate ? *pstate : l.pstate(),
1531
- ops[op](l.r(), r.r()),
1532
- ops[op](l.g(), r.g()),
1533
- ops[op](l.b(), r.b()),
1534
- l.a());
1535
- }
1536
-
1537
- Value_Ptr Eval::op_strings(Sass::Operand operand, Value& lhs, Value& rhs, struct Sass_Inspect_Options opt, ParserState* pstate, bool delayed)
1538
- {
1539
- Expression::Concrete_Type ltype = lhs.concrete_type();
1540
- Expression::Concrete_Type rtype = rhs.concrete_type();
1541
- enum Sass_OP op = operand.operand;
1542
-
1543
- String_Quoted_Ptr lqstr = dynamic_cast<String_Quoted_Ptr>(&lhs);
1544
- String_Quoted_Ptr rqstr = dynamic_cast<String_Quoted_Ptr>(&rhs);
1545
-
1546
- std::string lstr(lqstr ? lqstr->value() : lhs.to_string(opt));
1547
- std::string rstr(rqstr ? rqstr->value() : rhs.to_string(opt));
1548
-
1549
- if (ltype == Expression::NULL_VAL) throw Exception::InvalidNullOperation(&lhs, &rhs, sass_op_to_name(op));
1550
- if (rtype == Expression::NULL_VAL) throw Exception::InvalidNullOperation(&lhs, &rhs, sass_op_to_name(op));
1551
- if (op == Sass_OP::MOD) throw Exception::UndefinedOperation(&lhs, &rhs, sass_op_to_name(op));
1552
- if (op == Sass_OP::MUL) throw Exception::UndefinedOperation(&lhs, &rhs, sass_op_to_name(op));
1553
- std::string sep;
1554
- switch (op) {
1555
- case Sass_OP::SUB: sep = "-"; break;
1556
- case Sass_OP::DIV: sep = "/"; break;
1557
- case Sass_OP::MUL: sep = "*"; break;
1558
- case Sass_OP::MOD: sep = "%"; break;
1559
- case Sass_OP::EQ: sep = "=="; break;
1560
- case Sass_OP::NEQ: sep = "!="; break;
1561
- case Sass_OP::LT: sep = "<"; break;
1562
- case Sass_OP::GT: sep = ">"; break;
1563
- case Sass_OP::LTE: sep = "<="; break;
1564
- case Sass_OP::GTE: sep = ">="; break;
1565
- default: break;
1566
- }
1567
-
1568
- if ( (sep == "") /* &&
1569
- (sep != "/" || !rqstr || !rqstr->quote_mark()) */
1570
- ) {
1571
- // create a new string that might be quoted on output (but do not unquote what we pass)
1572
- return SASS_MEMORY_NEW(String_Quoted, pstate ? *pstate : lhs.pstate(), lstr + rstr, 0, false, true);
1573
- }
1574
-
1575
- if (sep != "" && !delayed) {
1576
- if (operand.ws_before) sep = " " + sep;
1577
- if (operand.ws_after) sep = sep + " ";
1578
- }
1579
-
1580
- if (op == Sass_OP::SUB || op == Sass_OP::DIV) {
1581
- if (lqstr && lqstr->quote_mark()) lstr = quote(lstr);
1582
- if (rqstr && rqstr->quote_mark()) rstr = quote(rstr);
1583
- }
1584
-
1585
- return SASS_MEMORY_NEW(String_Constant, pstate ? *pstate : lhs.pstate(), lstr + sep + rstr);
1586
- }
1587
-
1588
- Expression_Ptr cval_to_astnode(union Sass_Value* v, Backtrace* backtrace, ParserState pstate)
1462
+ Expression_Ptr cval_to_astnode(union Sass_Value* v, Backtraces traces, ParserState pstate)
1589
1463
  {
1590
1464
  using std::strlen;
1591
1465
  using std::strcpy;
@@ -1610,16 +1484,17 @@ namespace Sass {
1610
1484
  case SASS_LIST: {
1611
1485
  List_Ptr l = SASS_MEMORY_NEW(List, pstate, sass_list_get_length(v), sass_list_get_separator(v));
1612
1486
  for (size_t i = 0, L = sass_list_get_length(v); i < L; ++i) {
1613
- l->append(cval_to_astnode(sass_list_get_value(v, i), backtrace, pstate));
1487
+ l->append(cval_to_astnode(sass_list_get_value(v, i), traces, pstate));
1614
1488
  }
1489
+ l->is_bracketed(sass_list_get_is_bracketed(v));
1615
1490
  e = l;
1616
1491
  } break;
1617
1492
  case SASS_MAP: {
1618
1493
  Map_Ptr m = SASS_MEMORY_NEW(Map, pstate);
1619
1494
  for (size_t i = 0, L = sass_map_get_length(v); i < L; ++i) {
1620
1495
  *m << std::make_pair(
1621
- cval_to_astnode(sass_map_get_key(v, i), backtrace, pstate),
1622
- cval_to_astnode(sass_map_get_value(v, i), backtrace, pstate));
1496
+ cval_to_astnode(sass_map_get_key(v, i), traces, pstate),
1497
+ cval_to_astnode(sass_map_get_value(v, i), traces, pstate));
1623
1498
  }
1624
1499
  e = m;
1625
1500
  } break;
@@ -1627,11 +1502,12 @@ namespace Sass {
1627
1502
  e = SASS_MEMORY_NEW(Null, pstate);
1628
1503
  } break;
1629
1504
  case SASS_ERROR: {
1630
- error("Error in C function: " + std::string(sass_error_get_message(v)), pstate, backtrace);
1505
+ error("Error in C function: " + std::string(sass_error_get_message(v)), pstate, traces);
1631
1506
  } break;
1632
1507
  case SASS_WARNING: {
1633
- error("Warning in C function: " + std::string(sass_warning_get_message(v)), pstate, backtrace);
1508
+ error("Warning in C function: " + std::string(sass_warning_get_message(v)), pstate, traces);
1634
1509
  } break;
1510
+ default: break;
1635
1511
  }
1636
1512
  return e;
1637
1513
  }
@@ -1644,7 +1520,7 @@ namespace Sass {
1644
1520
  sl->media_block(s->media_block());
1645
1521
  sl->is_optional(s->is_optional());
1646
1522
  for (size_t i = 0, iL = s->length(); i < iL; ++i) {
1647
- rv.push_back(operator()(&(*s)[i]));
1523
+ rv.push_back(operator()((*s)[i]));
1648
1524
  }
1649
1525
 
1650
1526
  // we should actually permutate parent first
@@ -1672,37 +1548,72 @@ namespace Sass {
1672
1548
  Selector_List_Ptr Eval::operator()(Complex_Selector_Ptr s)
1673
1549
  {
1674
1550
  bool implicit_parent = !exp.old_at_root_without_rule;
1675
- return s->resolve_parent_refs(ctx, exp.selector_stack, implicit_parent);
1551
+ if (is_in_selector_schema) exp.selector_stack.push_back(0);
1552
+ Selector_List_Obj resolved = s->resolve_parent_refs(exp.selector_stack, traces, implicit_parent);
1553
+ if (is_in_selector_schema) exp.selector_stack.pop_back();
1554
+ for (size_t i = 0; i < resolved->length(); i++) {
1555
+ Complex_Selector_Ptr is = resolved->at(i)->first();
1556
+ while (is) {
1557
+ if (is->head()) {
1558
+ is->head(operator()(is->head()));
1559
+ }
1560
+ is = is->tail();
1561
+ }
1562
+ }
1563
+ return resolved.detach();
1676
1564
  }
1677
1565
 
1678
- // XXX: this is never hit via spec tests
1679
- Attribute_Selector_Ptr Eval::operator()(Attribute_Selector_Ptr s)
1566
+ Compound_Selector_Ptr Eval::operator()(Compound_Selector_Ptr s)
1680
1567
  {
1681
- String_Obj attr = s->value();
1682
- if (attr) { attr = static_cast<String_Ptr>(attr->perform(this)); }
1683
- Attribute_Selector_Ptr ss = SASS_MEMORY_COPY(s);
1684
- ss->value(attr);
1685
- return ss;
1568
+ for (size_t i = 0; i < s->length(); i++) {
1569
+ Simple_Selector_Ptr ss = s->at(i);
1570
+ // skip parents here (called via resolve_parent_refs)
1571
+ if (ss == NULL || Cast<Parent_Selector>(ss)) continue;
1572
+ s->at(i) = Cast<Simple_Selector>(ss->perform(this));
1573
+ }
1574
+ return s;
1686
1575
  }
1687
1576
 
1688
1577
  Selector_List_Ptr Eval::operator()(Selector_Schema_Ptr s)
1689
1578
  {
1579
+ LOCAL_FLAG(is_in_selector_schema, true);
1690
1580
  // the parser will look for a brace to end the selector
1581
+ ctx.c_options.in_selector = true; // do not compress colors
1691
1582
  Expression_Obj sel = s->contents()->perform(this);
1692
1583
  std::string result_str(sel->to_string(ctx.c_options));
1693
- result_str = unquote(Util::rtrim(result_str)) + "\n{";
1694
- Parser p = Parser::from_c_str(result_str.c_str(), ctx, s->pstate());
1584
+ ctx.c_options.in_selector = false; // flag temporary only
1585
+ result_str = unquote(Util::rtrim(result_str));
1586
+ char* temp_cstr = sass_copy_c_string(result_str.c_str());
1587
+ ctx.strings.push_back(temp_cstr); // attach to context
1588
+ Parser p = Parser::from_c_str(temp_cstr, ctx, traces, s->pstate());
1695
1589
  p.last_media_block = s->media_block();
1696
- Selector_List_Obj sl = p.parse_selector_list(exp.block_stack.back()->is_root());
1697
- if (s->has_parent_ref()) sl->remove_parent_selectors();
1698
- return operator()(&sl);
1590
+ // a selector schema may or may not connect to parent?
1591
+ bool chroot = s->connect_parent() == false;
1592
+ Selector_List_Obj sl = p.parse_selector_list(chroot);
1593
+ auto vec_str_rend = ctx.strings.rend();
1594
+ auto vec_str_rbegin = ctx.strings.rbegin();
1595
+ // remove the first item searching from the back
1596
+ // we cannot assume our item is still the last one
1597
+ // order is not important, so we can optimize this
1598
+ auto it = std::find(vec_str_rbegin, vec_str_rend, temp_cstr);
1599
+ // undefined behavior if not found!
1600
+ if (it != vec_str_rend) {
1601
+ // overwrite with last item
1602
+ *it = ctx.strings.back();
1603
+ // remove last one from vector
1604
+ ctx.strings.pop_back();
1605
+ // free temporary copy
1606
+ free(temp_cstr);
1607
+ }
1608
+ flag_is_in_selector_schema.reset();
1609
+ return operator()(sl);
1699
1610
  }
1700
1611
 
1701
1612
  Expression_Ptr Eval::operator()(Parent_Selector_Ptr p)
1702
1613
  {
1703
1614
  if (Selector_List_Obj pr = selector()) {
1704
1615
  exp.selector_stack.pop_back();
1705
- Selector_List_Obj rv = operator()(&pr);
1616
+ Selector_List_Obj rv = operator()(pr);
1706
1617
  exp.selector_stack.push_back(rv);
1707
1618
  return rv.detach();
1708
1619
  } else {
@@ -1710,4 +1621,43 @@ namespace Sass {
1710
1621
  }
1711
1622
  }
1712
1623
 
1624
+ Simple_Selector_Ptr Eval::operator()(Simple_Selector_Ptr s)
1625
+ {
1626
+ return s;
1627
+ }
1628
+
1629
+ // hotfix to avoid invalid nested `:not` selectors
1630
+ // probably the wrong place, but this should ultimately
1631
+ // be fixed by implement superselector correctly for `:not`
1632
+ // first use of "find" (ATM only implemented for selectors)
1633
+ bool hasNotSelector(AST_Node_Obj obj) {
1634
+ if (Wrapped_Selector_Ptr w = Cast<Wrapped_Selector>(obj)) {
1635
+ return w->name() == ":not";
1636
+ }
1637
+ return false;
1638
+ }
1639
+
1640
+ Wrapped_Selector_Ptr Eval::operator()(Wrapped_Selector_Ptr s)
1641
+ {
1642
+
1643
+ if (s->name() == ":not") {
1644
+ if (exp.selector_stack.back()) {
1645
+ if (s->selector()->find(hasNotSelector)) {
1646
+ s->selector()->clear();
1647
+ s->name(" ");
1648
+ } else if (s->selector()->length() == 1) {
1649
+ Complex_Selector_Ptr cs = s->selector()->at(0);
1650
+ if (cs->tail()) {
1651
+ s->selector()->clear();
1652
+ s->name(" ");
1653
+ }
1654
+ } else if (s->selector()->length() > 1) {
1655
+ s->selector()->clear();
1656
+ s->name(" ");
1657
+ }
1658
+ }
1659
+ }
1660
+ return s;
1661
+ };
1662
+
1713
1663
  }