Add call().

This commit is contained in:
Natalie Weizenbaum 2016-09-22 16:23:51 -07:00 committed by Natalie Weizenbaum
parent ad1bbcc9bc
commit af4234aedd
6 changed files with 47 additions and 1 deletions

View File

@ -19,6 +19,7 @@ export 'sass/expression/number.dart';
export 'sass/expression/selector.dart';
export 'sass/expression/string.dart';
export 'sass/expression/unary_operation.dart';
export 'sass/expression/value.dart';
export 'sass/expression/variable.dart';
export 'sass/interpolation.dart';
export 'sass/media_query.dart';

View File

@ -0,0 +1,26 @@
// Copyright 2016 Google Inc. Use of this source code is governed by an
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
import 'package:source_span/source_span.dart';
import '../../../visitor/interface/expression.dart';
import '../../../value.dart';
import '../expression.dart';
/// An expression that directly embeds a [Value].
///
/// This is never constructed by the parser. It's only used when ASTs are
/// constructed dynamically, as for the `call()` function.
class ValueExpression implements Expression {
final Value value;
FileSpan get span => null;
ValueExpression(this.value);
/*=T*/ accept/*<T>*/(ExpressionVisitor/*<T>*/ visitor) =>
visitor.visitValueExpression(this);
String toString() => value.toString();
}

View File

@ -832,6 +832,8 @@ void defineCoreFunctions(Environment environment) {
var number2 = arguments[1].assertNumber("number2");
return new SassBoolean(number1.isComparableTo(number2));
});
// call() is defined in PerformVisitor to provide it access to private APIs.
}
num _percentageOrUnitless(SassNumber number, num max, String name) {

View File

@ -61,6 +61,9 @@ int listHash(List list) => const ListEquality().hash(list);
FileSpan spanForList(List<AstNode> nodes) {
if (nodes.isEmpty) return null;
// Spans may be null for dynamically-constructed ASTs.
if (nodes.first.span == null) return null;
if (nodes.last.span == null) return null;
return nodes.first.span.expand(nodes.last.span);
}

View File

@ -16,5 +16,6 @@ abstract class ExpressionVisitor<T> {
T visitSelectorExpression(SelectorExpression node);
T visitStringExpression(StringExpression node);
T visitUnaryOperationExpression(UnaryOperationExpression node);
T visitValueExpression(ValueExpression node);
T visitVariableExpression(VariableExpression node);
}

View File

@ -58,7 +58,18 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
PerformVisitor({Iterable<String> loadPaths, Environment environment})
: _loadPaths = loadPaths == null ? const [] : new List.from(loadPaths),
_environment = environment ?? new Environment();
_environment = environment ?? new Environment() {
_environment.defineFunction("call", r"$name, $args...", (arguments) {
var name = arguments[0].assertString("name");
var args = arguments[1] as SassArgumentList;
var expression = new FunctionExpression(
new Interpolation([name.text], null),
new ArgumentInvocation([], {}, null,
rest: new ValueExpression(args)));
return expression.accept(this);
});
}
void visit(node) {
if (node is Statement) {
@ -613,6 +624,8 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
}, node.span);
}
Value visitValueExpression(ValueExpression node) => node.value;
Value visitVariableExpression(VariableExpression node) {
var result = _environment.getVariable(node.name);
if (result != null) return result;