Skip to content

Commit 9536c7f

Browse files
committed
Реструктуризующее присваивание
1 parent 95c7175 commit 9536c7f

File tree

7 files changed

+109
-1
lines changed

7 files changed

+109
-1
lines changed

program.own

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,4 +185,15 @@ println class.add(2, class.mul(2, 2))
185185
println split("1/2/3/4/5/6", "/")
186186
println join(nums, ", ")
187187
println join(nums, "|", "/")
188-
println join(nums, ", ", "[", "]")
188+
println join(nums, ", ", "[", "]")
189+
190+
// Destructuring assignment
191+
arr = ["a", "b", "c"]
192+
extract(var1, var2, var3) = arr
193+
echo(var1, var2, var3)
194+
// Swap
195+
extract(var2, var1) = [var1, var2]
196+
echo(var1, var2)
197+
198+
extract(, , var4) = arr
199+
println var4

src/com/annimon/ownlang/parser/Lexer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ public final class Lexer {
7474
KEYWORDS.put("use", TokenType.USE);
7575
KEYWORDS.put("match", TokenType.MATCH);
7676
KEYWORDS.put("case", TokenType.CASE);
77+
KEYWORDS.put("extract", TokenType.EXTRACT);
7778
}
7879

7980
private final String input;

src/com/annimon/ownlang/parser/Parser.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ private Statement statement() {
8787
if (match(TokenType.MATCH)) {
8888
return new ExprStatement(match());
8989
}
90+
if (match(TokenType.EXTRACT)) {
91+
return destructuringAssignment();
92+
}
9093
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LPAREN)) {
9194
return new ExprStatement(function(qualifiedName()));
9295
}
@@ -107,6 +110,22 @@ private Statement assignmentStatement() {
107110
throw new ParseException("Unknown statement: " + get(0));
108111
}
109112

113+
private DestructuringAssignmentStatement destructuringAssignment() {
114+
// extract(var1, var2, ...) = ...
115+
consume(TokenType.LPAREN);
116+
final List<String> variables = new ArrayList<>();
117+
while (!match(TokenType.RPAREN)) {
118+
if (lookMatch(0, TokenType.WORD)) {
119+
variables.add(consume(TokenType.WORD).getText());
120+
} else {
121+
variables.add(null);
122+
}
123+
match(TokenType.COMMA);
124+
}
125+
consume(TokenType.EQ);
126+
return new DestructuringAssignmentStatement(variables, expression());
127+
}
128+
110129
private Statement ifElse() {
111130
final Expression condition = expression();
112131
final Statement ifStatement = statementOrBlock();

src/com/annimon/ownlang/parser/TokenType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public enum TokenType {
2626
USE,
2727
MATCH,
2828
CASE,
29+
EXTRACT,
2930

3031
PLUS, // +
3132
MINUS, // -
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.annimon.ownlang.parser.ast;
2+
3+
import com.annimon.ownlang.lib.ArrayValue;
4+
import com.annimon.ownlang.lib.MapValue;
5+
import com.annimon.ownlang.lib.Types;
6+
import com.annimon.ownlang.lib.Value;
7+
import com.annimon.ownlang.lib.Variables;
8+
import java.util.Iterator;
9+
import java.util.List;
10+
import java.util.Map;
11+
12+
/**
13+
*
14+
* @author aNNiMON
15+
*/
16+
public final class DestructuringAssignmentStatement implements Statement {
17+
18+
public final List<String> variables;
19+
public final Expression containerExpression;
20+
21+
public DestructuringAssignmentStatement(List<String> arguments, Expression container) {
22+
this.variables = arguments;
23+
this.containerExpression = container;
24+
}
25+
26+
@Override
27+
public void execute() {
28+
final Value container = containerExpression.eval();
29+
switch (container.type()) {
30+
case Types.ARRAY:
31+
execute((ArrayValue) container);
32+
break;
33+
case Types.MAP:
34+
execute((MapValue) container);
35+
break;
36+
}
37+
}
38+
39+
private void execute(ArrayValue array) {
40+
final int size = variables.size();
41+
for (int i = 0; i < size; i++) {
42+
final String variable = variables.get(i);
43+
if (variable != null) {
44+
Variables.set(variable, array.get(i));
45+
}
46+
}
47+
}
48+
private void execute(MapValue map) {
49+
int i = 0;
50+
for (Map.Entry<Value, Value> entry : map) {
51+
final String variable = variables.get(i);
52+
if (variable != null) {
53+
Variables.set(variable, new ArrayValue(
54+
new Value[] { entry.getKey(), entry.getValue() }
55+
));
56+
}
57+
i++;
58+
}
59+
}
60+
61+
@Override
62+
public void accept(Visitor visitor) {
63+
visitor.visit(this);
64+
}
65+
66+
@Override
67+
public String toString() {
68+
return variables.toString();
69+
}
70+
}

src/com/annimon/ownlang/parser/ast/Visitor.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public interface Visitor {
1616
void visit(ConditionalExpression s);
1717
void visit(ContinueStatement s);
1818
void visit(DoWhileStatement s);
19+
void visit(DestructuringAssignmentStatement s);
1920
void visit(ForStatement s);
2021
void visit(ForeachArrayStatement s);
2122
void visit(ForeachMapStatement s);

src/com/annimon/ownlang/parser/visitors/AbstractVisitor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ public void visit(ConditionalExpression s) {
6161
@Override
6262
public void visit(ContinueStatement s) {
6363
}
64+
65+
@Override
66+
public void visit(DestructuringAssignmentStatement s) {
67+
s.containerExpression.accept(this);
68+
}
6469

6570
@Override
6671
public void visit(DoWhileStatement s) {

0 commit comments

Comments
 (0)