Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
node-sass
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
楚学文
node-sass
Commits
2dbc45a0
Commit
2dbc45a0
authored
Oct 03, 2012
by
Aaron Leung
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
More fixes for evaluation edge-cases.
parent
f25d02b2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
222 additions
and
142 deletions
+222
-142
document_parser.cpp
document_parser.cpp
+60
-66
eval_apply.cpp
eval_apply.cpp
+162
-76
No files found.
document_parser.cpp
View file @
2dbc45a0
...
...
@@ -215,12 +215,10 @@ namespace Sass {
if
(
lex
<
exactly
<
'('
>
>
())
{
if
(
!
peek
<
exactly
<
')'
>
>
(
position
))
{
Node
arg
(
parse_argument
(
Node
::
none
));
arg
.
should_eval
()
=
true
;
args
<<
arg
;
if
(
arg
.
type
()
==
Node
::
assignment
)
arg_type
=
Node
::
assignment
;
while
(
lex
<
exactly
<
','
>
>
())
{
Node
arg
(
parse_argument
(
arg_type
));
arg
.
should_eval
()
=
true
;
args
<<
arg
;
if
(
arg
.
type
()
==
Node
::
assignment
)
arg_type
=
Node
::
assignment
;
}
...
...
@@ -239,6 +237,7 @@ namespace Sass {
Node
var
(
context
.
new_Node
(
Node
::
variable
,
path
,
line
,
lexed
));
lex
<
exactly
<
':'
>
>
();
Node
val
(
parse_space_list
());
// val.should_eval() = true;
Node
assn
(
context
.
new_Node
(
Node
::
assignment
,
path
,
line
,
2
));
assn
<<
var
<<
val
;
return
assn
;
...
...
@@ -254,23 +253,14 @@ namespace Sass {
Node
var
(
context
.
new_Node
(
Node
::
variable
,
path
,
line
,
lexed
));
lex
<
exactly
<
':'
>
>
();
Node
val
(
parse_space_list
());
// val.should_eval() = true;
Node
assn
(
context
.
new_Node
(
Node
::
assignment
,
path
,
line
,
2
));
assn
<<
var
<<
val
;
return
assn
;
}
return
parse_space_list
();
// if (peek< sequence < variable, spaces_and_comments, exactly<':'> > >()) {
// lex< variable >();
// Node var(context.new_Node(Node::variable, path, line, lexed));
// lex< exactly<':'> >();
// Node val(parse_space_list());
// Node assn(context.new_Node(Node::assignment, path, line, 2));
// assn << var << val;
// return assn;
// }
// else {
// return parse_space_list();
// }
Node
val
(
parse_space_list
());
val
.
should_eval
()
=
true
;
return
val
;
}
Node
Document
::
parse_assignment
()
...
...
@@ -909,45 +899,45 @@ namespace Sass {
if
(
lex
<
identifier
>
())
{
return
context
.
new_Node
(
Node
::
identifier
,
path
,
line
,
lexed
);
}
// if (lex< percentage >())
// { return context.new_Node(Node::textual_percentage, path, line, lexed); }
// if (lex< dimension >())
// { return context.new_Node(Node::textual_dimension, path, line, lexed); }
if
(
lex
<
percentage
>
())
{
return
context
.
new_Node
(
Node
::
textual_percentage
,
path
,
line
,
lexed
);
}
// if (lex< number
>())
// { return context.new_Node(Node::textual_number
, path, line, lexed); }
if
(
lex
<
dimension
>
())
{
return
context
.
new_Node
(
Node
::
textual_dimension
,
path
,
line
,
lexed
);
}
// if (lex< hex
>())
// { return context.new_Node(Node::textual_hex
, path, line, lexed); }
if
(
lex
<
number
>
())
{
return
context
.
new_Node
(
Node
::
textual_number
,
path
,
line
,
lexed
);
}
if
(
lex
<
percentage
>
())
{
return
context
.
new_Node
(
path
,
line
,
atof
(
lexed
.
begin
),
Node
::
numeric_percentage
);
}
if
(
lex
<
hex
>
())
{
return
context
.
new_Node
(
Node
::
textual_hex
,
path
,
line
,
lexed
);
}
if
(
lex
<
dimension
>
())
{
return
context
.
new_Node
(
path
,
line
,
atof
(
lexed
.
begin
),
Token
::
make
(
Prelexer
::
number
(
lexed
.
begin
),
lexed
.
end
));
}
// if (lex< percentage >())
// { return context.new_Node(path, line, atof(lexed.begin), Node::numeric_percentage); }
if
(
lex
<
number
>
())
{
return
context
.
new_Node
(
path
,
line
,
atof
(
lexed
.
begin
));
}
// if (lex< dimension >()) {
// return context.new_Node(path, line, atof(lexed.begin),
// Token::make(Prelexer::number(lexed.begin), lexed.end));
// }
if
(
lex
<
hex
>
())
{
Node
triple
(
context
.
new_Node
(
Node
::
numeric_color
,
path
,
line
,
4
));
Token
hext
(
Token
::
make
(
lexed
.
begin
+
1
,
lexed
.
end
));
if
(
hext
.
length
()
==
6
)
{
for
(
int
i
=
0
;
i
<
6
;
i
+=
2
)
{
triple
<<
context
.
new_Node
(
path
,
line
,
static_cast
<
double
>
(
strtol
(
string
(
hext
.
begin
+
i
,
2
).
c_str
(),
NULL
,
16
)));
}
}
else
{
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
triple
<<
context
.
new_Node
(
path
,
line
,
static_cast
<
double
>
(
strtol
(
string
(
2
,
hext
.
begin
[
i
]).
c_str
(),
NULL
,
16
)));
}
}
triple
<<
context
.
new_Node
(
path
,
line
,
1.0
);
return
triple
;
}
// if (lex< number >())
// { return context.new_Node(path, line, atof(lexed.begin)); }
// if (lex< hex >()) {
// Node triple(context.new_Node(Node::numeric_color, path, line, 4));
// Token hext(Token::make(lexed.begin+1, lexed.end));
// if (hext.length() == 6) {
// for (int i = 0; i < 6; i += 2) {
// triple << context.new_Node(path, line, static_cast<double>(strtol(string(hext.begin+i, 2).c_str(), NULL, 16)));
// }
// }
// else {
// for (int i = 0; i < 3; ++i) {
// triple << context.new_Node(path, line, static_cast<double>(strtol(string(2, hext.begin[i]).c_str(), NULL, 16)));
// }
// }
// triple << context.new_Node(path, line, 1.0);
// return triple;
// }
if
(
peek
<
string_constant
>
())
{
return
parse_string
();
}
...
...
@@ -1023,30 +1013,34 @@ namespace Sass {
schema
<<
context
.
new_Node
(
Node
::
identifier
,
path
,
line
,
lexed
);
}
else
if
(
lex
<
percentage
>
())
{
schema
<<
context
.
new_Node
(
path
,
line
,
atof
(
lexed
.
begin
),
Node
::
numeric_percentage
);
schema
<<
context
.
new_Node
(
Node
::
textual_percentage
,
path
,
line
,
lexed
);
// schema << context.new_Node(path, line, atof(lexed.begin), Node::numeric_percentage);
}
else
if
(
lex
<
dimension
>
())
{
schema
<<
context
.
new_Node
(
path
,
line
,
atof
(
lexed
.
begin
),
Token
::
make
(
Prelexer
::
number
(
lexed
.
begin
),
lexed
.
end
));
schema
<<
context
.
new_Node
(
Node
::
textual_dimension
,
path
,
line
,
lexed
);
// schema << context.new_Node(path, line, atof(lexed.begin),
// Token::make(Prelexer::number(lexed.begin), lexed.end));
}
else
if
(
lex
<
number
>
())
{
schema
<<
context
.
new_Node
(
path
,
line
,
atof
(
lexed
.
begin
));
schema
<<
context
.
new_Node
(
Node
::
textual_number
,
path
,
line
,
lexed
);
// schema << context.new_Node(path, line, atof(lexed.begin));
}
else
if
(
lex
<
hex
>
())
{
Node
triple
(
context
.
new_Node
(
Node
::
numeric_color
,
path
,
line
,
4
));
Token
hext
(
Token
::
make
(
lexed
.
begin
+
1
,
lexed
.
end
));
if
(
hext
.
length
()
==
6
)
{
for
(
int
i
=
0
;
i
<
6
;
i
+=
2
)
{
triple
<<
context
.
new_Node
(
path
,
line
,
static_cast
<
double
>
(
strtol
(
string
(
hext
.
begin
+
i
,
2
).
c_str
(),
NULL
,
16
)));
}
}
else
{
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
triple
<<
context
.
new_Node
(
path
,
line
,
static_cast
<
double
>
(
strtol
(
string
(
2
,
hext
.
begin
[
i
]).
c_str
(),
NULL
,
16
)));
}
}
triple
<<
context
.
new_Node
(
path
,
line
,
1.0
);
schema
<<
triple
;
schema
<<
context
.
new_Node
(
Node
::
textual_hex
,
path
,
line
,
lexed
);
// Node triple(context.new_Node(Node::numeric_color, path, line, 4));
// Token hext(Token::make(lexed.begin+1, lexed.end));
// if (hext.length() == 6) {
// for (int i = 0; i < 6; i += 2) {
// triple << context.new_Node(path, line, static_cast<double>(strtol(string(hext.begin+i, 2).c_str(), NULL, 16)));
// }
// }
// else {
// for (int i = 0; i < 3; ++i) {
// triple << context.new_Node(path, line, static_cast<double>(strtol(string(2, hext.begin[i]).c_str(), NULL, 16)));
// }
// }
// triple << context.new_Node(path, line, 1.0);
// schema << triple;
}
else
if
(
lex
<
string_constant
>
())
{
Node
str
(
context
.
new_Node
(
Node
::
string_constant
,
path
,
line
,
lexed
));
...
...
eval_apply.cpp
View file @
2dbc45a0
...
...
@@ -45,20 +45,18 @@ namespace Sass {
if
(
!
env
.
query
(
name
))
throw_eval_error
(
"mixin "
+
name
.
to_string
()
+
" is undefined"
,
expr
.
path
(),
expr
.
line
());
Node
mixin
(
env
[
name
]);
Node
expansion
(
apply_mixin
(
mixin
,
args
,
prefix
,
env
,
f_env
,
new_Node
,
ctx
));
expr
.
pop_back
();
// pop the mixin name
expr
.
pop_back
();
// pop the mixin args
expr
.
pop_all
();
// pop the mixin metadata
expr
+=
expansion
;
// push the expansion
}
break
;
case
Node
:
:
propset
:
{
// TO DO: perform the property expansion here, rather than in the emitter
// TO DO: perform the property expansion here, rather than in the emitter
(also requires the parser to allow interpolants in the property names)
expand
(
expr
[
1
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
}
break
;
case
Node
:
:
ruleset
:
{
// if the selector contains interpolants, eval it and re-parse
if
(
expr
[
0
].
type
()
==
Node
::
selector_schema
)
{
// expr[0] = eval(expr[0], prefix, env, f_env, new_Node, ctx);
Node
schema
(
expr
[
0
]);
string
expansion
;
for
(
size_t
i
=
0
,
S
=
schema
.
size
();
i
<
S
;
++
i
)
{
...
...
@@ -106,7 +104,7 @@ namespace Sass {
}
}
// expand the body with the
current
selector as the prefix
// expand the body with the
newly expanded
selector as the prefix
expand
(
expr
[
1
],
expr
.
back
(),
env
,
f_env
,
new_Node
,
ctx
);
}
break
;
...
...
@@ -139,7 +137,7 @@ namespace Sass {
val
=
eval
(
val
,
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
}
// If a binding exists (possibl
e
upframe), then update it.
// If a binding exists (possibl
y
upframe), then update it.
// Otherwise, make a new on in the current frame.
if
(
env
.
query
(
var
.
token
()))
{
env
[
var
.
token
()]
=
val
;
...
...
@@ -172,7 +170,7 @@ namespace Sass {
for
(
size_t
i
=
0
,
S
=
expr
.
size
();
i
<
S
;
i
+=
2
)
{
if
(
expr
[
i
].
type
()
!=
Node
::
block
)
{
Node
predicate_val
(
eval
(
expr
[
i
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
));
if
(
(
predicate_val
.
type
()
!=
Node
::
boolean
)
||
predicate_val
.
boolean_valu
e
())
{
if
(
!
predicate_val
.
is_fals
e
())
{
expand
(
expansion
=
expr
[
i
+
1
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
break
;
}
...
...
@@ -224,6 +222,7 @@ namespace Sass {
expr
.
pop_all
();
for
(
size_t
i
=
0
,
S
=
list
.
size
();
i
<
S
;
++
i
)
{
Node
fake_arg
(
new_Node
(
Node
::
arguments
,
expr
.
path
(),
expr
.
line
(),
1
));
list
[
i
].
should_eval
()
=
true
;
fake_arg
<<
eval
(
list
[
i
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
expr
+=
apply_mixin
(
fake_mixin
,
fake_arg
,
prefix
,
env
,
f_env
,
new_Node
,
ctx
,
true
);
}
...
...
@@ -240,7 +239,7 @@ namespace Sass {
expr
.
pop_back
();
expr
.
pop_back
();
Node
ev_pred
(
eval
(
pred
,
prefix
,
env
,
f_env
,
new_Node
,
ctx
));
while
(
(
ev_pred
.
type
()
!=
Node
::
boolean
)
||
ev_pred
.
boolean_valu
e
())
{
while
(
!
ev_pred
.
is_fals
e
())
{
expr
+=
apply_mixin
(
fake_mixin
,
fake_arg
,
prefix
,
env
,
f_env
,
new_Node
,
ctx
,
true
);
ev_pred
=
eval
(
pred
,
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
}
...
...
@@ -277,7 +276,7 @@ namespace Sass {
// Evaluation function for nodes in a value context.
Node
eval
(
Node
expr
,
Node
prefix
,
Environment
&
env
,
map
<
string
,
Function
>&
f_env
,
Node_Factory
&
new_Node
,
Context
&
ctx
,
bool
function_name
)
{
Node
result
;
Node
result
=
Node
()
;
switch
(
expr
.
type
())
{
// case Node::selector_schema: {
...
...
@@ -306,9 +305,6 @@ namespace Sass {
result
<<
eval
(
expr
[
0
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
for
(
size_t
i
=
1
,
S
=
expr
.
size
();
i
<
S
;
++
i
)
result
<<
expr
[
i
];
}
else
{
result
=
expr
;
}
}
break
;
case
Node
:
:
disjunction
:
{
...
...
@@ -364,41 +360,38 @@ namespace Sass {
}
result
=
reduce
(
list
,
1
,
list
[
0
],
new_Node
);
}
else
{
result
=
expr
;
}
}
break
;
//
case Node::textual_percentage: {
//
result = new_Node(expr.path(), expr.line(), std::atof(expr.token().begin), Node::numeric_percentage);
//
} break;
case
Node
:
:
textual_percentage
:
{
result
=
new_Node
(
expr
.
path
(),
expr
.
line
(),
std
::
atof
(
expr
.
token
().
begin
),
Node
::
numeric_percentage
);
}
break
;
//
case Node::textual_dimension: {
//
result = new_Node(expr.path(), expr.line(),
//
std::atof(expr.token().begin),
//
Token::make(Prelexer::number(expr.token().begin),
//
expr.token().end));
//
} break;
case
Node
:
:
textual_dimension
:
{
result
=
new_Node
(
expr
.
path
(),
expr
.
line
(),
std
::
atof
(
expr
.
token
().
begin
),
Token
::
make
(
Prelexer
::
number
(
expr
.
token
().
begin
),
expr
.
token
().
end
));
}
break
;
//
case Node::textual_number: {
//
result = new_Node(expr.path(), expr.line(), std::atof(expr.token().begin));
//
} break;
case
Node
:
:
textual_number
:
{
result
=
new_Node
(
expr
.
path
(),
expr
.
line
(),
std
::
atof
(
expr
.
token
().
begin
));
}
break
;
//
case Node::textual_hex: {
// result = new_Node(Node::numeric_color, expr.path(), expr.line(), 4)
);
//
Token hext(Token::make(expr.token().begin+1, expr.token().end));
//
if (hext.length() == 6) {
//
for (int i = 0; i < 6; i += 2) {
//
result << new_Node(expr.path(), expr.line(), static_cast<double>(std::strtol(string(hext.begin+i, 2).c_str(), NULL, 16)));
//
}
//
}
//
else {
//
for (int i = 0; i < 3; ++i) {
//
result << new_Node(expr.path(), expr.line(), static_cast<double>(std::strtol(string(2, hext.begin[i]).c_str(), NULL, 16)));
//
}
//
}
//
result << new_Node(expr.path(), expr.line(), 1.0);
//
} break;
case
Node
:
:
textual_hex
:
{
result
=
new_Node
(
Node
::
numeric_color
,
expr
.
path
(),
expr
.
line
(),
4
);
Token
hext
(
Token
::
make
(
expr
.
token
().
begin
+
1
,
expr
.
token
().
end
));
if
(
hext
.
length
()
==
6
)
{
for
(
int
i
=
0
;
i
<
6
;
i
+=
2
)
{
result
<<
new_Node
(
expr
.
path
(),
expr
.
line
(),
static_cast
<
double
>
(
std
::
strtol
(
string
(
hext
.
begin
+
i
,
2
).
c_str
(),
NULL
,
16
)));
}
}
else
{
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
result
<<
new_Node
(
expr
.
path
(),
expr
.
line
(),
static_cast
<
double
>
(
std
::
strtol
(
string
(
2
,
hext
.
begin
[
i
]).
c_str
(),
NULL
,
16
)));
}
}
result
<<
new_Node
(
expr
.
path
(),
expr
.
line
(),
1.0
);
}
break
;
case
Node
:
:
variable
:
{
if
(
!
env
.
query
(
expr
.
token
()))
throw_eval_error
(
"reference to unbound variable "
+
expr
.
token
().
to_string
(),
expr
.
path
(),
expr
.
line
());
...
...
@@ -422,6 +415,12 @@ namespace Sass {
Node
evaluated_args
(
new_Node
(
Node
::
arguments
,
args
.
path
(),
args
.
line
(),
args
.
size
()));
for
(
size_t
i
=
0
,
S
=
args
.
size
();
i
<
S
;
++
i
)
{
evaluated_args
<<
eval
(
args
[
i
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
if
(
evaluated_args
.
back
().
type
()
==
Node
::
list
)
{
Node
arg_list
(
evaluated_args
.
back
());
for
(
size_t
j
=
0
,
S
=
arg_list
.
size
();
j
<
S
;
++
j
)
{
if
(
arg_list
[
j
].
should_eval
())
arg_list
[
j
]
=
eval
(
arg_list
[
j
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
}
}
}
result
=
new_Node
(
Node
::
function_call
,
expr
.
path
(),
expr
.
line
(),
2
);
result
<<
name_node
<<
evaluated_args
;
...
...
@@ -477,9 +476,6 @@ namespace Sass {
b
.
numeric_value
(),
a
.
numeric_value
());
}
else
{
result
=
expr
;
}
}
break
;
case
Node
:
:
string_schema
:
...
...
@@ -501,6 +497,7 @@ namespace Sass {
result
=
expr
;
}
break
;
}
if
(
result
.
is_null
())
result
=
expr
;
return
result
;
}
...
...
@@ -515,13 +512,6 @@ namespace Sass {
Node
::
Type
optype
=
op
.
type
();
Node
::
Type
ltype
=
acc
.
type
();
Node
::
Type
rtype
=
rhs
.
type
();
// if (ltype == Node::number && rhs.is_string()) {
// acc = (new_Node(Node::concatenation, list.path(), list.line(), 2) << acc);
// if (optype != Node::add) acc << op;
// if (rtype == Node::concatenation) acc += rhs;
// else acc << rhs;
// acc.is_quoted() = rhs.is_quoted();
// }
if
(
ltype
==
Node
::
number
&&
rtype
==
Node
::
number
)
{
acc
=
new_Node
(
list
.
path
(),
list
.
line
(),
operate
(
op
,
acc
.
numeric_value
(),
rhs
.
numeric_value
()));
}
...
...
@@ -696,24 +686,72 @@ namespace Sass {
Node
params
(
mixin
[
1
]);
Node
body
(
new_Node
(
mixin
[
2
]));
// clone the body
// evaluate arguments in the current environment
Node
evaluated_args
=
new_Node
(
args
);
// Node evaluated_args = new_Node(args);
// for (size_t i = 0, S = evaluated_args.size(); i < S; ++i) {
// if (evaluated_args[i].type() != Node::assignment) {
// evaluated_args[i] = eval(evaluated_args[i], prefix, env, f_env, new_Node, ctx);
// }
// else {
// evaluated_args[i][1] = eval(evaluated_args[i][1], prefix, env, f_env, new_Node, ctx);
// }
// }
// // need to eval twice because some expressions get delayed
// for (size_t i = 0, S = args.size(); i < S; ++i) {
// if (args[i].type() != Node::assignment) {
// args[i].should_eval() = true;
// args[i] = eval(args[i], prefix, env, f_env, new_Node, ctx);
// }
// else {
// args[i][1].should_eval() = true;
// args[i][1] = eval(args[i][1], prefix, env, f_env, new_Node, ctx);
// }
// }
Node
evaluated_args
(
new_Node
(
Node
::
arguments
,
args
.
path
(),
args
.
line
(),
args
.
size
()));
for
(
size_t
i
=
0
,
S
=
args
.
size
();
i
<
S
;
++
i
)
{
if
(
args
[
i
].
type
()
!=
Node
::
assignment
)
{
evaluated_args
<<
eval
(
args
[
i
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
if
(
evaluated_args
.
back
().
type
()
==
Node
::
list
)
{
Node
arg_list
(
evaluated_args
.
back
());
for
(
size_t
j
=
0
,
S
=
arg_list
.
size
();
j
<
S
;
++
j
)
{
if
(
arg_list
[
j
].
should_eval
())
arg_list
[
j
]
=
eval
(
arg_list
[
j
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
}
}
}
else
{
Node
kwdarg
(
new_Node
(
Node
::
assignment
,
args
[
i
].
path
(),
args
[
i
].
line
(),
2
));
kwdarg
<<
args
[
i
][
0
];
kwdarg
<<
eval
(
args
[
i
][
1
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
if
(
kwdarg
.
back
().
type
()
==
Node
::
list
)
{
Node
arg_list
(
kwdarg
.
back
());
for
(
size_t
j
=
0
,
S
=
arg_list
.
size
();
j
<
S
;
++
j
)
{
if
(
arg_list
[
j
].
should_eval
())
arg_list
[
j
]
=
eval
(
arg_list
[
j
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
}
}
evaluated_args
<<
kwdarg
;
}
}
// eval twice because args maybe delayed
for
(
size_t
i
=
0
,
S
=
evaluated_args
.
size
();
i
<
S
;
++
i
)
{
if
(
evaluated_args
[
i
].
type
()
!=
Node
::
assignment
)
{
evaluated_args
[
i
]
=
eval
(
evaluated_args
[
i
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
if
(
evaluated_args
[
i
].
type
()
==
Node
::
list
)
{
Node
arg_list
(
evaluated_args
[
i
]);
for
(
size_t
j
=
0
,
S
=
arg_list
.
size
();
j
<
S
;
++
j
)
{
if
(
arg_list
[
j
].
should_eval
())
arg_list
[
j
]
=
eval
(
arg_list
[
j
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
}
else
{
evaluated_args
[
i
][
1
]
=
eval
(
evaluated_args
[
i
][
1
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
}
}
// need to eval twice because some expressions get delayed
for
(
size_t
i
=
0
,
S
=
args
.
size
();
i
<
S
;
++
i
)
{
if
(
args
[
i
].
type
()
!=
Node
::
assignment
)
{
args
[
i
].
should_eval
()
=
true
;
args
[
i
]
=
eval
(
args
[
i
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
}
else
{
args
[
i
][
1
].
should_eval
()
=
true
;
args
[
i
][
1
]
=
eval
(
args
[
i
][
1
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
Node
kwdarg
(
evaluated_args
[
i
]);
kwdarg
[
1
]
=
eval
(
kwdarg
[
1
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
if
(
kwdarg
[
1
].
type
()
==
Node
::
list
)
{
Node
arg_list
(
kwdarg
[
1
]);
for
(
size_t
j
=
0
,
S
=
arg_list
.
size
();
j
<
S
;
++
j
)
{
if
(
arg_list
[
j
].
should_eval
())
arg_list
[
j
]
=
eval
(
arg_list
[
j
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
}
}
evaluated_args
[
i
]
=
kwdarg
;
}
}
...
...
@@ -743,35 +781,83 @@ namespace Sass {
// Apply a function -- bind the arguments and pass them to the underlying
// primitive function implementation, then return its value.
Node
apply_function
(
const
Function
&
f
,
const
Node
a
a
rgs
,
Node
prefix
,
Environment
&
env
,
map
<
string
,
Function
>&
f_env
,
Node_Factory
&
new_Node
,
Context
&
ctx
,
string
&
path
,
size_t
line
)
Node
apply_function
(
const
Function
&
f
,
const
Node
args
,
Node
prefix
,
Environment
&
env
,
map
<
string
,
Function
>&
f_env
,
Node_Factory
&
new_Node
,
Context
&
ctx
,
string
&
path
,
size_t
line
)
{
Node
args
=
new_Node
(
aargs
);
// evaluate arguments in the current environment
// Node args = new_Node(aargs);
// // evaluate arguments in the current environment
// for (size_t i = 0, S = args.size(); i < S; ++i) {
// if (args[i].type() != Node::assignment) {
// args[i] = eval(args[i], prefix, env, f_env, new_Node, ctx);
// }
// else {
// args[i][1] = eval(args[i][1], prefix, env, f_env, new_Node, ctx);
// }
// }
// // need to eval twice because some expressions get delayed
// for (size_t i = 0, S = args.size(); i < S; ++i) {
// if (args[i].type() != Node::assignment) {
// args[i].should_eval() = true;
// args[i] = eval(args[i], prefix, env, f_env, new_Node, ctx);
// }
// else {
// args[i][1].should_eval() = true;
// args[i][1] = eval(args[i][1], prefix, env, f_env, new_Node, ctx);
// }
// }
Node
evaluated_args
(
new_Node
(
Node
::
arguments
,
args
.
path
(),
args
.
line
(),
args
.
size
()));
for
(
size_t
i
=
0
,
S
=
args
.
size
();
i
<
S
;
++
i
)
{
if
(
args
[
i
].
type
()
!=
Node
::
assignment
)
{
args
[
i
]
=
eval
(
args
[
i
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
evaluated_args
<<
eval
(
args
[
i
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
if
(
evaluated_args
.
back
().
type
()
==
Node
::
list
)
{
Node
arg_list
(
evaluated_args
.
back
());
for
(
size_t
j
=
0
,
S
=
arg_list
.
size
();
j
<
S
;
++
j
)
{
if
(
arg_list
[
j
].
should_eval
())
arg_list
[
j
]
=
eval
(
arg_list
[
j
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
}
}
}
else
{
args
[
i
][
1
]
=
eval
(
args
[
i
][
1
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
Node
kwdarg
(
new_Node
(
Node
::
assignment
,
args
[
i
].
path
(),
args
[
i
].
line
(),
2
));
kwdarg
<<
args
[
i
][
0
];
kwdarg
<<
eval
(
args
[
i
][
1
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
if
(
kwdarg
.
back
().
type
()
==
Node
::
list
)
{
Node
arg_list
(
kwdarg
.
back
());
for
(
size_t
j
=
0
,
S
=
arg_list
.
size
();
j
<
S
;
++
j
)
{
if
(
arg_list
[
j
].
should_eval
())
arg_list
[
j
]
=
eval
(
arg_list
[
j
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
}
}
evaluated_args
<<
kwdarg
;
}
}
// eval twice because args maybe delayed
for
(
size_t
i
=
0
,
S
=
evaluated_args
.
size
();
i
<
S
;
++
i
)
{
if
(
evaluated_args
[
i
].
type
()
!=
Node
::
assignment
)
{
evaluated_args
[
i
]
=
eval
(
evaluated_args
[
i
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
if
(
evaluated_args
[
i
].
type
()
==
Node
::
list
)
{
Node
arg_list
(
evaluated_args
[
i
]);
for
(
size_t
j
=
0
,
S
=
arg_list
.
size
();
j
<
S
;
++
j
)
{
if
(
arg_list
[
j
].
should_eval
())
arg_list
[
j
]
=
eval
(
arg_list
[
j
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
}
}
// need to eval twice because some expressions get delayed
for
(
size_t
i
=
0
,
S
=
args
.
size
();
i
<
S
;
++
i
)
{
if
(
args
[
i
].
type
()
!=
Node
::
assignment
)
{
args
[
i
].
should_eval
()
=
true
;
args
[
i
]
=
eval
(
args
[
i
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
}
else
{
args
[
i
][
1
].
should_eval
()
=
true
;
args
[
i
][
1
]
=
eval
(
args
[
i
][
1
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
Node
kwdarg
(
evaluated_args
[
i
]);
kwdarg
[
1
]
=
eval
(
kwdarg
[
1
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
if
(
kwdarg
[
1
].
type
()
==
Node
::
list
)
{
Node
arg_list
(
kwdarg
[
1
]);
for
(
size_t
j
=
0
,
S
=
arg_list
.
size
();
j
<
S
;
++
j
)
{
if
(
arg_list
[
j
].
should_eval
())
arg_list
[
j
]
=
eval
(
arg_list
[
j
],
prefix
,
env
,
f_env
,
new_Node
,
ctx
);
}
}
evaluated_args
[
i
]
=
kwdarg
;
}
}
// bind arguments
Environment
bindings
;
Node
params
(
f
.
primitive
?
f
.
parameters
:
f
.
definition
[
1
]);
bindings
.
link
(
env
.
global
?
*
env
.
global
:
env
);
bind_arguments
(
"function "
+
f
.
name
,
params
,
args
,
prefix
,
bindings
,
f_env
,
new_Node
,
ctx
);
bind_arguments
(
"function "
+
f
.
name
,
params
,
evaluated_
args
,
prefix
,
bindings
,
f_env
,
new_Node
,
ctx
);
if
(
f
.
primitive
)
{
return
f
.
primitive
(
f
.
parameter_names
,
bindings
,
new_Node
,
path
,
line
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment