Реструктуризующее присваивание

This commit is contained in:
Victor 2016-02-09 13:28:40 +02:00
parent 95c71753ca
commit 9536c7f5b0
7 changed files with 109 additions and 1 deletions

View File

@ -185,4 +185,15 @@ println class.add(2, class.mul(2, 2))
println split("1/2/3/4/5/6", "/") println split("1/2/3/4/5/6", "/")
println join(nums, ", ") println join(nums, ", ")
println join(nums, "|", "/") println join(nums, "|", "/")
println join(nums, ", ", "[", "]") println join(nums, ", ", "[", "]")
// Destructuring assignment
arr = ["a", "b", "c"]
extract(var1, var2, var3) = arr
echo(var1, var2, var3)
// Swap
extract(var2, var1) = [var1, var2]
echo(var1, var2)
extract(, , var4) = arr
println var4

View File

@ -74,6 +74,7 @@ public final class Lexer {
KEYWORDS.put("use", TokenType.USE); KEYWORDS.put("use", TokenType.USE);
KEYWORDS.put("match", TokenType.MATCH); KEYWORDS.put("match", TokenType.MATCH);
KEYWORDS.put("case", TokenType.CASE); KEYWORDS.put("case", TokenType.CASE);
KEYWORDS.put("extract", TokenType.EXTRACT);
} }
private final String input; private final String input;

View File

@ -87,6 +87,9 @@ public final class Parser {
if (match(TokenType.MATCH)) { if (match(TokenType.MATCH)) {
return new ExprStatement(match()); return new ExprStatement(match());
} }
if (match(TokenType.EXTRACT)) {
return destructuringAssignment();
}
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LPAREN)) { if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LPAREN)) {
return new ExprStatement(function(qualifiedName())); return new ExprStatement(function(qualifiedName()));
} }
@ -107,6 +110,22 @@ public final class Parser {
throw new ParseException("Unknown statement: " + get(0)); throw new ParseException("Unknown statement: " + get(0));
} }
private DestructuringAssignmentStatement destructuringAssignment() {
// extract(var1, var2, ...) = ...
consume(TokenType.LPAREN);
final List<String> variables = new ArrayList<>();
while (!match(TokenType.RPAREN)) {
if (lookMatch(0, TokenType.WORD)) {
variables.add(consume(TokenType.WORD).getText());
} else {
variables.add(null);
}
match(TokenType.COMMA);
}
consume(TokenType.EQ);
return new DestructuringAssignmentStatement(variables, expression());
}
private Statement ifElse() { private Statement ifElse() {
final Expression condition = expression(); final Expression condition = expression();
final Statement ifStatement = statementOrBlock(); final Statement ifStatement = statementOrBlock();

View File

@ -26,6 +26,7 @@ public enum TokenType {
USE, USE,
MATCH, MATCH,
CASE, CASE,
EXTRACT,
PLUS, // + PLUS, // +
MINUS, // - MINUS, // -

View File

@ -0,0 +1,70 @@
package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.ArrayValue;
import com.annimon.ownlang.lib.MapValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.Variables;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
*
* @author aNNiMON
*/
public final class DestructuringAssignmentStatement implements Statement {
public final List<String> variables;
public final Expression containerExpression;
public DestructuringAssignmentStatement(List<String> arguments, Expression container) {
this.variables = arguments;
this.containerExpression = container;
}
@Override
public void execute() {
final Value container = containerExpression.eval();
switch (container.type()) {
case Types.ARRAY:
execute((ArrayValue) container);
break;
case Types.MAP:
execute((MapValue) container);
break;
}
}
private void execute(ArrayValue array) {
final int size = variables.size();
for (int i = 0; i < size; i++) {
final String variable = variables.get(i);
if (variable != null) {
Variables.set(variable, array.get(i));
}
}
}
private void execute(MapValue map) {
int i = 0;
for (Map.Entry<Value, Value> entry : map) {
final String variable = variables.get(i);
if (variable != null) {
Variables.set(variable, new ArrayValue(
new Value[] { entry.getKey(), entry.getValue() }
));
}
i++;
}
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@Override
public String toString() {
return variables.toString();
}
}

View File

@ -16,6 +16,7 @@ public interface Visitor {
void visit(ConditionalExpression s); void visit(ConditionalExpression s);
void visit(ContinueStatement s); void visit(ContinueStatement s);
void visit(DoWhileStatement s); void visit(DoWhileStatement s);
void visit(DestructuringAssignmentStatement s);
void visit(ForStatement s); void visit(ForStatement s);
void visit(ForeachArrayStatement s); void visit(ForeachArrayStatement s);
void visit(ForeachMapStatement s); void visit(ForeachMapStatement s);

View File

@ -61,6 +61,11 @@ public abstract class AbstractVisitor implements Visitor {
@Override @Override
public void visit(ContinueStatement s) { public void visit(ContinueStatement s) {
} }
@Override
public void visit(DestructuringAssignmentStatement s) {
s.containerExpression.accept(this);
}
@Override @Override
public void visit(DoWhileStatement s) { public void visit(DoWhileStatement s) {