sassc 1.11.4 → 1.12.0

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