mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 08:44:20 +03:00
Обновлён проект
This commit is contained in:
parent
db939ec9ee
commit
c7f87f75f6
70
examples/canvas/fx_koch_snowflake.own
Normal file
70
examples/canvas/fx_koch_snowflake.own
Normal 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))
|
||||
}
|
||||
})
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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())
|
||||
|
@ -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())
|
||||
|
Loading…
Reference in New Issue
Block a user