Обновлён проект

This commit is contained in:
Victor 2017-11-10 11:13:46 +02:00
parent db939ec9ee
commit c7f87f75f6
13 changed files with 140 additions and 80 deletions

View File

@ -0,0 +1,70 @@
use "canvasfx"
use "math"
use "functional"
// https://github.com/SeTSeR/KochSnowflake
width = 675 height = 500
context = window("Koch Snowflake", width, height)
GO = 0 TURN = 1
def Fractal(startStep = 0) {
result = {}
result.fract = startStep ? [[GO, startStep]] : []
result.next = def(fract) {
fractal = Fractal()
def translate(input) = input[0] == GO ? [input[0], input[1] / 3] : input
fractlist = map(fract, ::translate)
fractal.fract = fractlist
fractal.fract ::= [TURN, -PI / 3]
fractal.fract <<= fractlist
fractal.fract ::= [TURN, 2*PI / 3]
fractal.fract <<= fractlist
fractal.fract ::= [TURN, -PI / 3]
fractal.fract <<= fractlist
return fractal
}
result.toDraw = def(fract) {
res = Fractal()
res.fract = fract
res.fract ::= [TURN, 2*PI / 3]
res.fract <<= fract
res.fract ::= [TURN, 2*PI / 3]
res.fract <<= fract
return res
}
return result
}
def draw(fractal) {
x = 200
y = height - 100 / sqrt(3)
angle = -PI / 2
context.setFill(Color.BLACK)
context.fillRect(0, 0, width, height)
context.setStroke(Color.GREEN)
context.beginPath()
context.moveTo(x, y)
for action : fractal.fract {
match action[0] {
case GO: {
x += action[1] * cos(angle)
y += action[1] * sin(angle)
context.lineTo(x, y)
}
case TURN: angle += action[1]
}
}
context.closePath()
context.stroke()
}
fractal = Fractal(400.0)
draw(fractal.toDraw(fractal.fract))
addEventHandler(Events.KEY_PRESSED, def(e) {
if (e.code == KeyCode.SPACE) {
fractal = fractal.next(fractal.fract)
draw(fractal.toDraw(fractal.fract))
}
})

View File

@ -1,5 +1,6 @@
package com.annimon.ownlang.lib;
import com.annimon.ownlang.exceptions.TypeException;
import java.util.Iterator;
import java.util.Map;
import org.json.JSONArray;
@ -99,4 +100,13 @@ public final class ValueUtils {
}
return result;
}
public static Function consumeFunction(Value value, int argumentNumber) throws TypeException {
final int type = value.type();
if (type != Types.FUNCTION) {
throw new TypeException("Function expected at argument " + (argumentNumber + 1)
+ ", but found " + Types.typeToString(type));
}
return ((FunctionValue) value).getValue();
}
}

View File

@ -1,16 +1,14 @@
package com.annimon.ownlang.modules.forms;
import com.annimon.ownlang.exceptions.TypeException;
import com.annimon.ownlang.lib.Arguments;
import com.annimon.ownlang.lib.ArrayValue;
import static com.annimon.ownlang.lib.Converters.*;
import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.FunctionValue;
import com.annimon.ownlang.lib.MapValue;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.ValueUtils;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
@ -18,6 +16,12 @@ import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.function.Consumer;
import java.util.function.Supplier;
import static com.annimon.ownlang.lib.Converters.booleanOptToVoid;
import static com.annimon.ownlang.lib.Converters.stringToVoid;
import static com.annimon.ownlang.lib.Converters.voidToBoolean;
import static com.annimon.ownlang.lib.Converters.voidToInt;
import static com.annimon.ownlang.lib.Converters.voidToString;
import static com.annimon.ownlang.lib.Converters.voidToVoid;
public abstract class ComponentValue extends MapValue {
@ -75,11 +79,7 @@ public abstract class ComponentValue extends MapValue {
private Value addKeyListener(Value... args) {
Arguments.check(1, args.length);
final int type = args[0].type();
if (type != Types.FUNCTION) {
throw new TypeException("Function expected, but found " + Types.typeToString(type));
}
final Function action = ((FunctionValue) args[0]).getValue();
final Function action = ValueUtils.consumeFunction(args[0], 0);
component.addKeyListener(new KeyListener() {
@Override

View File

@ -1,12 +1,11 @@
package com.annimon.ownlang.modules.forms;
import com.annimon.ownlang.exceptions.TypeException;
import com.annimon.ownlang.lib.Arguments;
import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.FunctionValue;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.ValueUtils;
import javax.swing.JButton;
public class JButtonValue extends JComponentValue {
@ -26,11 +25,7 @@ public class JButtonValue extends JComponentValue {
private Value addActionListener(Value... args) {
Arguments.check(1, args.length);
final int type = args[0].type();
if (type != Types.FUNCTION) {
throw new TypeException("Function expected, but found " + Types.typeToString(type));
}
final Function action = ((FunctionValue) args[0]).getValue();
final Function action = ValueUtils.consumeFunction(args[0], 0);
button.addActionListener(e -> action.execute());
return NumberValue.ZERO;
}

View File

@ -1,14 +1,13 @@
package com.annimon.ownlang.modules.forms;
import com.annimon.ownlang.exceptions.TypeException;
import com.annimon.ownlang.lib.Arguments;
import static com.annimon.ownlang.lib.Converters.*;
import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.FunctionValue;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
import javax.swing.JTextField;
import static com.annimon.ownlang.lib.ValueUtils.consumeFunction;
public class JTextFieldValue extends JComponentValue {
@ -41,11 +40,7 @@ public class JTextFieldValue extends JComponentValue {
private Value addActionListener(Value... args) {
Arguments.check(1, args.length);
final int type = args[0].type();
if (type != Types.FUNCTION) {
throw new TypeException("Function expected, but found " + Types.typeToString(type));
}
final Function action = ((FunctionValue) args[0]).getValue();
Function action = consumeFunction(args[0], 1);
textField.addActionListener(e -> action.execute());
return NumberValue.ZERO;
}

View File

@ -4,9 +4,9 @@ import com.annimon.ownlang.exceptions.TypeException;
import com.annimon.ownlang.lib.Arguments;
import com.annimon.ownlang.lib.ArrayValue;
import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.FunctionValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.ValueUtils;
import java.util.ArrayList;
import java.util.List;
@ -18,11 +18,7 @@ public final class functional_flatmap implements Function {
if (args[0].type() != Types.ARRAY) {
throw new TypeException("Array expected in first argument");
}
if (args[1].type() != Types.FUNCTION) {
throw new TypeException("Function expected in second argument");
}
final Function mapper = ((FunctionValue) args[1]).getValue();
final Function mapper = ValueUtils.consumeFunction(args[1], 1);
return flatMapArray((ArrayValue) args[0], mapper);
}

View File

@ -1,7 +1,13 @@
package com.annimon.ownlang.modules.functional;
import com.annimon.ownlang.exceptions.TypeException;
import com.annimon.ownlang.lib.*;
import com.annimon.ownlang.lib.Arguments;
import com.annimon.ownlang.lib.ArrayValue;
import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.MapValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.ValueUtils;
import java.util.Map;
public final class functional_foreach implements Function {
@ -9,12 +15,8 @@ public final class functional_foreach implements Function {
@Override
public Value execute(Value... args) {
Arguments.check(2, args.length);
if (args[1].type() != Types.FUNCTION) {
throw new TypeException("Function expected in second arg");
}
final Value container = args[0];
final Function consumer = ((FunctionValue) args[1]).getValue();
final Function consumer = ValueUtils.consumeFunction(args[1], 1);
if (container.type() == Types.ARRAY) {
final ArrayValue array = (ArrayValue) container;
for (Value element : array) {

View File

@ -4,9 +4,9 @@ import com.annimon.ownlang.exceptions.TypeException;
import com.annimon.ownlang.lib.Arguments;
import com.annimon.ownlang.lib.ArrayValue;
import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.FunctionValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.ValueUtils;
import java.util.Arrays;
public final class functional_sortby implements Function {
@ -17,12 +17,8 @@ public final class functional_sortby implements Function {
if (args[0].type() != Types.ARRAY) {
throw new TypeException("Array expected in first argument");
}
if (args[1].type() != Types.FUNCTION) {
throw new TypeException("Function expected in second argument");
}
final Value[] elements = ((ArrayValue) args[0]).getCopyElements();
final Function function = ((FunctionValue) args[1]).getValue();
final Function function = ValueUtils.consumeFunction(args[1], 1);
Arrays.sort(elements, (o1, o2) -> function.execute(o1).compareTo(function.execute(o2)));
return new ArrayValue(elements);
}

View File

@ -42,41 +42,44 @@ public final class robot implements Module {
@Override
public void init() {
initConstants();
initialize();
Functions.set("click", convertFunction(robot::click));
Functions.set("delay", convertFunction(awtRobot::delay));
Functions.set("setAutoDelay", convertFunction(awtRobot::setAutoDelay));
Functions.set("keyPress", convertFunction(awtRobot::keyPress));
Functions.set("keyRelease", convertFunction(awtRobot::keyRelease));
Functions.set("mousePress", convertFunction(awtRobot::mousePress));
Functions.set("mouseRelease", convertFunction(awtRobot::mouseRelease));
Functions.set("mouseWheel", convertFunction(awtRobot::mouseWheel));
Functions.set("mouseMove", (args) -> {
Arguments.check(2, args.length);
try {
awtRobot.mouseMove(args[0].asInt(), args[1].asInt());
} catch (IllegalArgumentException iae) { }
return NumberValue.ZERO;
});
Functions.set("typeText", (args) -> {
Arguments.check(1, args.length);
try {
typeText(args[0].asString());
} catch (IllegalArgumentException iae) { }
return NumberValue.ZERO;
});
Functions.set("toClipboard", new robot_toclipboard());
Functions.set("fromClipboard", new robot_fromclipboard());
boolean isRobotInitialized = initialize();
if (isRobotInitialized) {
Functions.set("click", convertFunction(robot::click));
Functions.set("delay", convertFunction(awtRobot::delay));
Functions.set("setAutoDelay", convertFunction(awtRobot::setAutoDelay));
Functions.set("keyPress", convertFunction(awtRobot::keyPress));
Functions.set("keyRelease", convertFunction(awtRobot::keyRelease));
Functions.set("mousePress", convertFunction(awtRobot::mousePress));
Functions.set("mouseRelease", convertFunction(awtRobot::mouseRelease));
Functions.set("mouseWheel", convertFunction(awtRobot::mouseWheel));
Functions.set("mouseMove", (args) -> {
Arguments.check(2, args.length);
try {
awtRobot.mouseMove(args[0].asInt(), args[1].asInt());
} catch (IllegalArgumentException iae) { }
return NumberValue.ZERO;
});
Functions.set("typeText", (args) -> {
Arguments.check(1, args.length);
try {
typeText(args[0].asString());
} catch (IllegalArgumentException iae) { }
return NumberValue.ZERO;
});
Functions.set("toClipboard", new robot_toclipboard());
Functions.set("fromClipboard", new robot_fromclipboard());
}
Functions.set("execProcess", new robot_exec(robot_exec.Mode.EXEC));
Functions.set("execProcessAndWait", new robot_exec(robot_exec.Mode.EXEC_AND_WAIT));
}
private static void initialize() {
private static boolean initialize() {
try {
awtRobot = new Robot();
return true;
} catch (AWTException awte) {
throw new RuntimeException("Unable to create robot instance", awte);
//throw new RuntimeException("Unable to create robot instance", awte);
return false;
}
}

View File

@ -5,9 +5,9 @@ import com.annimon.ownlang.exceptions.TypeException;
import com.annimon.ownlang.lib.Arguments;
import com.annimon.ownlang.lib.ArrayValue;
import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.FunctionValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.ValueUtils;
import java.util.Arrays;
public final class std_sort implements Function {
@ -25,10 +25,7 @@ public final class std_sort implements Function {
Arrays.sort(elements);
break;
case 2:
if (args[1].type() != Types.FUNCTION) {
throw new TypeException("Function expected in second argument");
}
final Function comparator = ((FunctionValue) args[1]).getValue();
final Function comparator = ValueUtils.consumeFunction(args[1], 1);
Arrays.sort(elements, (o1, o2) -> comparator.execute(o1, o2).asInt());
break;
default:

View File

@ -2,7 +2,6 @@ package com.annimon.ownlang.parser;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.junit.Ignore;
import org.junit.Test;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
@ -13,7 +12,6 @@ import org.openjdk.jmh.runner.options.OptionsBuilder;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Benchmark)
@Ignore
public class LexerBenchmarkTest {
@Param({"1000"})
@ -33,7 +31,7 @@ public class LexerBenchmarkTest {
}
}
@Test
//@Test
public void executeBenchmark() throws RunnerException {
Options opt = new OptionsBuilder()
.include(LexerBenchmarkTest.class.getSimpleName())

View File

@ -3,7 +3,6 @@ package com.annimon.ownlang.parser;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.junit.Ignore;
import org.junit.Test;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
@ -15,7 +14,6 @@ import org.openjdk.jmh.runner.options.OptionsBuilder;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Benchmark)
@Ignore
public class ParserBenchmarkTest {
@Param({"1000"})
@ -35,7 +33,7 @@ public class ParserBenchmarkTest {
}
}
@Test
//@Test
public void executeBenchmark() throws RunnerException {
Options opt = new OptionsBuilder()
.include(ParserBenchmarkTest.class.getSimpleName())