Добавлен тип данных Map

This commit is contained in:
Victor 2016-01-08 12:51:55 +02:00
parent 08847a59f1
commit cea99d4105
13 changed files with 231 additions and 6 deletions

View File

@ -81,4 +81,10 @@ for i = 0, i < 4, i = i + 1 {
print functions[i] print functions[i]
print "\n" print "\n"
print function(functions[i], 6, 3) print function(functions[i], 6, 3)
} }
// map
map = {"+" : add, "-" : sub. "*" : mul, "/" : div}
//print map["+"]
print "\n"
print function(map["+"], 4, 5)

View File

@ -18,7 +18,7 @@ import java.util.List;
public final class Main { public final class Main {
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
final String file = "examples/game/agar.own"; final String file = "program.own";
final String input = new String( Files.readAllBytes(Paths.get(file)), "UTF-8"); final String input = new String( Files.readAllBytes(Paths.get(file)), "UTF-8");
final List<Token> tokens = new Lexer(input).tokenize(); final List<Token> tokens = new Lexer(input).tokenize();
for (int i = 0; i < tokens.size(); i++) { for (int i = 0; i < tokens.size(); i++) {

View File

@ -41,6 +41,25 @@ public final class ArrayValue implements Value {
return Arrays.toString(elements); return Arrays.toString(elements);
} }
@Override
public int hashCode() {
int hash = 5;
hash = 79 * hash + Arrays.deepHashCode(this.elements);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass())
return false;
final ArrayValue other = (ArrayValue) obj;
return Arrays.deepEquals(this.elements, other.elements);
}
@Override @Override
public String toString() { public String toString() {
return asString(); return asString();

View File

@ -1,5 +1,7 @@
package com.annimon.ownlang.lib; package com.annimon.ownlang.lib;
import java.util.Objects;
/** /**
* *
* @author aNNiMON * @author aNNiMON
@ -26,6 +28,23 @@ public final class FunctionValue implements Value {
return value; return value;
} }
@Override
public int hashCode() {
int hash = 7;
hash = 71 * hash + Objects.hashCode(this.value);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass())
return false;
final FunctionValue other = (FunctionValue) obj;
return Objects.equals(this.value, other.value);
}
@Override @Override
public String toString() { public String toString() {
return asString(); return asString();

View File

@ -0,0 +1,60 @@
package com.annimon.ownlang.lib;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
*
* @author aNNiMON
*/
public final class MapValue implements Value {
private final Map<Value, Value> map;
public MapValue(int size) {
this.map = new HashMap<>(size);
}
public Value get(Value key) {
return map.get(key);
}
public void set(Value key, Value value) {
map.put(key, value);
}
@Override
public double asNumber() {
throw new RuntimeException("Cannot cast map to number");
}
@Override
public String asString() {
return map.toString();
}
@Override
public int hashCode() {
int hash = 5;
hash = 37 * hash + Objects.hashCode(this.map);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass())
return false;
final MapValue other = (MapValue) obj;
return Objects.equals(this.map, other.map);
}
@Override
public String toString() {
return asString();
}
}

View File

@ -29,6 +29,25 @@ public final class NumberValue implements Value {
return Double.toString(value); return Double.toString(value);
} }
@Override
public int hashCode() {
int hash = 3;
hash = 71 * hash + (int) (Double.doubleToLongBits(this.value) ^ (Double.doubleToLongBits(this.value) >>> 32));
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass())
return false;
final NumberValue other = (NumberValue) obj;
return Double.doubleToLongBits(this.value) == Double.doubleToLongBits(other.value);
}
@Override @Override
public String toString() { public String toString() {
return asString(); return asString();

View File

@ -1,5 +1,7 @@
package com.annimon.ownlang.lib; package com.annimon.ownlang.lib;
import java.util.Objects;
/** /**
* *
* @author aNNiMON * @author aNNiMON
@ -26,6 +28,23 @@ public final class StringValue implements Value {
return value; return value;
} }
@Override
public int hashCode() {
int hash = 3;
hash = 97 * hash + Objects.hashCode(this.value);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass())
return false;
final StringValue other = (StringValue) obj;
return Objects.equals(this.value, other.value);
}
@Override @Override
public String toString() { public String toString() {
return asString(); return asString();

View File

@ -36,4 +36,9 @@ public final class UserDefinedFunction implements Function {
return rt.getResult(); return rt.getResult();
} }
} }
@Override
public String toString() {
return String.format("function %s %s", argNames.toString(), body.toString());
}
} }

View File

@ -3,7 +3,9 @@ package com.annimon.ownlang.parser;
import com.annimon.ownlang.lib.UserDefinedFunction; import com.annimon.ownlang.lib.UserDefinedFunction;
import com.annimon.ownlang.parser.ast.*; import com.annimon.ownlang.parser.ast.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* *
@ -170,6 +172,19 @@ public final class Parser {
return new ArrayExpression(elements); return new ArrayExpression(elements);
} }
private Expression map() {
consume(TokenType.LBRACE);
final Map<Expression, Expression> elements = new HashMap<>();
while (!match(TokenType.RBRACE)) {
final Expression key = primary();
consume(TokenType.COLON);
final Expression value = expression();
elements.put(key, value);
match(TokenType.COMMA);
}
return new MapExpression(elements);
}
private ArrayAccessExpression element() { private ArrayAccessExpression element() {
final String variable = consume(TokenType.WORD).getText(); final String variable = consume(TokenType.WORD).getText();
final List<Expression> indices = new ArrayList<>(); final List<Expression> indices = new ArrayList<>();
@ -393,15 +408,18 @@ public final class Parser {
if (match(TokenType.HEX_NUMBER)) { if (match(TokenType.HEX_NUMBER)) {
return new ValueExpression(Long.parseLong(current.getText(), 16)); return new ValueExpression(Long.parseLong(current.getText(), 16));
} }
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LPAREN)) {
return function();
}
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LBRACKET)) { if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LBRACKET)) {
return element(); return element();
} }
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LPAREN)) {
return function();
}
if (lookMatch(0, TokenType.LBRACKET)) { if (lookMatch(0, TokenType.LBRACKET)) {
return array(); return array();
} }
if (lookMatch(0, TokenType.LBRACE)) {
return map();
}
if (match(TokenType.WORD)) { if (match(TokenType.WORD)) {
return new VariableExpression(current.getText()); return new VariableExpression(current.getText());
} }

View File

@ -1,6 +1,7 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.ArrayValue; import com.annimon.ownlang.lib.ArrayValue;
import com.annimon.ownlang.lib.MapValue;
import com.annimon.ownlang.lib.Value; import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.Variables; import com.annimon.ownlang.lib.Variables;
import java.util.List; import java.util.List;
@ -21,7 +22,11 @@ public final class ArrayAccessExpression implements Expression {
@Override @Override
public Value eval() { public Value eval() {
return getArray().get(lastIndex()); Value container = Variables.get(variable);
if (container instanceof ArrayValue) {
return getArray().get(lastIndex());
}
return consumeMap(container).get(indices.get(0).eval());
} }
public ArrayValue getArray() { public ArrayValue getArray() {
@ -49,6 +54,14 @@ public final class ArrayAccessExpression implements Expression {
} }
} }
private MapValue consumeMap(Value value) {
if (value instanceof MapValue) {
return (MapValue) value;
} else {
throw new RuntimeException("Map expected");
}
}
@Override @Override
public void accept(Visitor visitor) { public void accept(Visitor visitor) {
visitor.visit(this); visitor.visit(this);

View File

@ -0,0 +1,38 @@
package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.MapValue;
import com.annimon.ownlang.lib.Value;
import java.util.Map;
/**
*
* @author aNNiMON
*/
public final class MapExpression implements Expression {
public final Map<Expression, Expression> elements;
public MapExpression(Map<Expression, Expression> arguments) {
this.elements = arguments;
}
@Override
public Value eval() {
final int size = elements.size();
final MapValue map = new MapValue(size);
for (Expression key : elements.keySet()) {
map.set(key.eval(), elements.get(key).eval());
}
return map;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@Override
public String toString() {
return elements.toString();
}
}

View File

@ -21,6 +21,7 @@ public interface Visitor {
void visit(FunctionStatement s); void visit(FunctionStatement s);
void visit(FunctionalExpression s); void visit(FunctionalExpression s);
void visit(IfStatement s); void visit(IfStatement s);
void visit(MapExpression s);
void visit(PrintStatement s); void visit(PrintStatement s);
void visit(ReturnStatement s); void visit(ReturnStatement s);
void visit(TernaryExpression s); void visit(TernaryExpression s);

View File

@ -99,6 +99,14 @@ public abstract class AbstractVisitor implements Visitor {
s.elseStatement.accept(this); s.elseStatement.accept(this);
} }
} }
@Override
public void visit(MapExpression s) {
for (Expression key : s.elements.keySet()) {
key.accept(this);
s.elements.get(key).accept(this);
}
}
@Override @Override
public void visit(PrintStatement s) { public void visit(PrintStatement s) {