Урок 9. Функции

This commit is contained in:
Victor 2015-06-15 14:45:52 +03:00
parent 3a4ea7b3b1
commit 7756e36179
6 changed files with 149 additions and 2 deletions

View File

@ -21,7 +21,7 @@ if (40 < 50 || 50 > 60) {
i = 0
print "while"
while (i < 10) {
print "i = " + i + "\n"
print "i = " + i + sin(i) + "\n"
i = i + 1
}
print "for"
@ -29,4 +29,7 @@ if (40 < 50 || 50 > 60) {
print "i = " + i + "\n"
}
}
else print "false"
else print "false"
print "sin(PI) = " + sin(PI/2)
echo(1,2,3,"4","5","text",sin(0),cos(0),sin(PI),cos(PI),PI)

View File

@ -0,0 +1,10 @@
package com.annimon.ownlang.lib;
/**
*
* @author aNNiMON
*/
public interface Function {
Value execute(Value... args);
}

View File

@ -0,0 +1,49 @@
package com.annimon.ownlang.lib;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author aNNiMON
*/
public final class Functions {
private static final NumberValue ZERO = new NumberValue(0);
private static final Map<String, Function> functions;
static {
functions = new HashMap<>();
functions.put("sin", new Function() {
@Override
public Value execute(Value... args) {
if (args.length != 1) throw new RuntimeException("One arg expected");
return new NumberValue(Math.sin(args[0].asNumber()));
}
});
functions.put("cos", (Function) (Value... args) -> {
if (args.length != 1) throw new RuntimeException("One arg expected");
return new NumberValue(Math.cos(args[0].asNumber()));
});
functions.put("echo", args -> {
for (Value arg : args) {
System.out.println(arg.asString());
}
return ZERO;
});
}
public static boolean isExists(String key) {
return functions.containsKey(key);
}
public static Function get(String key) {
if (!isExists(key)) throw new RuntimeException("Unknown function " + key);
return functions.get(key);
}
public static void set(String key, Function function) {
functions.put(key, function);
}
}

View File

@ -65,6 +65,9 @@ public final class Parser {
if (match(TokenType.FOR)) {
return forStatement();
}
if (get(0).getType() == TokenType.WORD && get(1).getType() == TokenType.LPAREN) {
return new FunctionStatement(function());
}
return assignmentStatement();
}
@ -114,6 +117,16 @@ public final class Parser {
return new ForStatement(initialization, termination, increment, statement);
}
private FunctionalExpression function() {
final String name = consume(TokenType.WORD).getText();
consume(TokenType.LPAREN);
final FunctionalExpression function = new FunctionalExpression(name);
while (!match(TokenType.RPAREN)) {
function.addArgument(expression());
match(TokenType.COMMA);
}
return function;
}
private Expression expression() {
return logicalOr();
@ -241,6 +254,9 @@ public final class Parser {
if (match(TokenType.HEX_NUMBER)) {
return new ValueExpression(Long.parseLong(current.getText(), 16));
}
if (get(0).getType() == TokenType.WORD && get(1).getType() == TokenType.LPAREN) {
return function();
}
if (match(TokenType.WORD)) {
return new VariableExpression(current.getText());
}

View File

@ -0,0 +1,24 @@
package com.annimon.ownlang.parser.ast;
/**
*
* @author aNNiMON
*/
public final class FunctionStatement implements Statement {
private final FunctionalExpression function;
public FunctionStatement(FunctionalExpression function) {
this.function = function;
}
@Override
public void execute() {
function.eval();
}
@Override
public String toString() {
return function.toString();
}
}

View File

@ -0,0 +1,45 @@
package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.Functions;
import com.annimon.ownlang.lib.Value;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author aNNiMON
*/
public final class FunctionalExpression implements Expression {
private final String name;
private final List<Expression> arguments;
public FunctionalExpression(String name) {
this.name = name;
arguments = new ArrayList<>();
}
public FunctionalExpression(String name, List<Expression> arguments) {
this.name = name;
this.arguments = arguments;
}
public void addArgument(Expression arg) {
arguments.add(arg);
}
@Override
public Value eval() {
final int size = arguments.size();
final Value[] values = new Value[size];
for (int i = 0; i < size; i++) {
values[i] = arguments.get(i).eval();
}
return Functions.get(name).execute(values);
}
@Override
public String toString() {
return name + "(" + arguments.toString() + ")";
}
}