@@ -7,6 +7,7 @@ library code_builder.src.specs.expression;
77import 'package:meta/meta.dart' ;
88
99import '../base.dart' ;
10+ import '../emitter.dart' ;
1011import '../visitors.dart' ;
1112import 'code.dart' ;
1213import 'reference.dart' ;
@@ -25,31 +26,77 @@ abstract class Expression implements Spec {
2526 @override
2627 R accept <R >(covariant ExpressionVisitor <R > visitor, [R context]);
2728
29+ /// Returns the expression as a valid [Code] block.
30+ Code asCode () => new _AsExpressionCode (this );
31+
2832 /// Returns the result of [this] `&&` [other] .
2933 Expression and (Expression other) {
3034 return new BinaryExpression ._(toExpression (), other, '&&' );
3135 }
3236
3337 /// Call this expression as a method.
34- Expression call () {
35- return new InvokeExpression ._(this );
38+ Expression call (
39+ List <Expression > positionalArguments, [
40+ Map <String , Expression > namedArguments = const {},
41+ ]) {
42+ return new InvokeExpression ._(
43+ this ,
44+ positionalArguments,
45+ namedArguments,
46+ );
47+ }
48+
49+ /// Returns an expression accessing `.<name>` on this expression.
50+ Expression property (String name) {
51+ return new BinaryExpression ._(
52+ this ,
53+ new LiteralExpression ._(name),
54+ '.' ,
55+ false ,
56+ );
3657 }
3758
3859 /// Returns a new instance of this expression.
39- Expression newInstance () {
40- return new InvokeExpression ._new (this );
60+ Expression newInstance (
61+ List <Expression > positionalArguments, [
62+ Map <String , Expression > namedArguments = const {},
63+ ]) {
64+ return new InvokeExpression ._new (
65+ this ,
66+ positionalArguments,
67+ namedArguments,
68+ );
4169 }
4270
4371 /// Returns a const instance of this expression.
44- Expression constInstance () {
45- return new InvokeExpression ._const (this );
72+ Expression constInstance (
73+ List <Expression > positionalArguments, [
74+ Map <String , Expression > namedArguments = const {},
75+ ]) {
76+ return new InvokeExpression ._const (
77+ this ,
78+ positionalArguments,
79+ namedArguments,
80+ );
4681 }
4782
4883 /// May be overriden to support other types implementing [Expression] .
4984 @visibleForOverriding
5085 Expression toExpression () => this ;
5186}
5287
88+ /// Represents a [code] block that wraps an [Expression] .
89+ class _AsExpressionCode implements Code {
90+ final Expression code;
91+
92+ const _AsExpressionCode (this .code);
93+
94+ @override
95+ R accept <R >(CodeVisitor <R > visitor, [R context]) {
96+ return code.accept (visitor as ExpressionVisitor <R >, context);
97+ }
98+ }
99+
53100/// Knowledge of different types of expressions in Dart.
54101///
55102/// **INTERNAL ONLY**.
@@ -59,6 +106,7 @@ abstract class ExpressionVisitor<T> implements SpecVisitor<T> {
59106 T visitInvokeExpression (InvokeExpression expression, [T context]);
60107 T visitLiteralExpression (LiteralExpression expression, [T context]);
61108 T visitLiteralListExpression (LiteralListExpression expression, [T context]);
109+ T visitLiteralMapExpression (LiteralMapExpression expression, [T context]);
62110}
63111
64112/// Knowledge of how to write valid Dart code from [ExpressionVisitor] .
@@ -68,12 +116,16 @@ abstract class ExpressionEmitter implements ExpressionVisitor<StringSink> {
68116 @override
69117 visitBinaryExpression (BinaryExpression expression, [StringSink output]) {
70118 output ?? = new StringBuffer ();
71- return output
72- ..write (expression.left.accept (this ))
73- ..write (' ' )
74- ..write (expression.operator )
75- ..write (' ' )
76- ..write (expression.right.accept (this ));
119+ expression.left.accept (this , output);
120+ if (expression.addSpace) {
121+ output.write (' ' );
122+ }
123+ output.write (expression.operator );
124+ if (expression.addSpace) {
125+ output.write (' ' );
126+ }
127+ expression.right.accept (this , output);
128+ return output;
77129 }
78130
79131 @override
@@ -95,7 +147,19 @@ abstract class ExpressionEmitter implements ExpressionVisitor<StringSink> {
95147 break ;
96148 }
97149 expression.target.accept (this , output);
98- return output..write ('()' );
150+ output.write ('(' );
151+ visitAll <Spec >(expression.positionalArguments, output, (spec) {
152+ spec.accept (this , output);
153+ });
154+ if (expression.positionalArguments.isNotEmpty &&
155+ expression.namedArguments.isNotEmpty) {
156+ output.write (', ' );
157+ }
158+ visitAll <String >(expression.namedArguments.keys, output, (name) {
159+ output..write (name)..write (': ' );
160+ expression.namedArguments[name].accept (this , output);
161+ });
162+ return output..write (')' );
99163 }
100164
101165 @override
@@ -104,6 +168,14 @@ abstract class ExpressionEmitter implements ExpressionVisitor<StringSink> {
104168 return output..write (expression.literal);
105169 }
106170
171+ void _acceptLiteral (Object literalOrSpec, StringSink output) {
172+ if (literalOrSpec is Spec ) {
173+ literalOrSpec.accept (this , output);
174+ return ;
175+ }
176+ literal (literalOrSpec).accept (this , output);
177+ }
178+
107179 @override
108180 visitLiteralListExpression (
109181 LiteralListExpression expression, [
@@ -119,18 +191,39 @@ abstract class ExpressionEmitter implements ExpressionVisitor<StringSink> {
119191 output.write ('>' );
120192 }
121193 output.write ('[' );
122- // ignore: prefer_final_locals
123- for (var i = 0 , l = expression.values.length; i < l; i++ ) {
124- final value = expression.values[i];
125- if (value is Spec ) {
126- value.accept (this , output);
194+ visitAll <Object >(expression.values, output, (value) {
195+ _acceptLiteral (value, output);
196+ });
197+ return output..write (']' );
198+ }
199+
200+ @override
201+ visitLiteralMapExpression (
202+ LiteralMapExpression expression, [
203+ StringSink output,
204+ ]) {
205+ output ?? = new StringBuffer ();
206+ if (expression.isConst) {
207+ output.write ('const ' );
208+ }
209+ if (expression.keyType != null ) {
210+ output.write ('<' );
211+ expression.keyType.accept (this , output);
212+ output.write (', ' );
213+ if (expression.valueType == null ) {
214+ const Reference ('dynamic' , 'dart:core' ).accept (this , output);
127215 } else {
128- literal (value).accept (this , output);
129- }
130- if (i < l - 1 ) {
131- output.write (', ' );
216+ expression.valueType.accept (this , output);
132217 }
218+ output.write ('>' );
133219 }
134- return output..write (']' );
220+ output.write ('{' );
221+ visitAll <Object >(expression.values.keys, output, (key) {
222+ final value = expression.values[key];
223+ _acceptLiteral (key, output);
224+ output.write (': ' );
225+ _acceptLiteral (value, output);
226+ });
227+ return output..write ('}' );
135228 }
136229}
0 commit comments