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
be9bdb0311
commit
c7dd50c9ad
@ -36,6 +36,7 @@ task generateJavaSources() {
|
|||||||
def source = """
|
def source = """
|
||||||
package com.annimon.ownlang;
|
package com.annimon.ownlang;
|
||||||
class Gen {
|
class Gen {
|
||||||
|
private Gen() {}
|
||||||
public static final String BUILD_DATE = "${new Date().format('YYMMdd')}";
|
public static final String BUILD_DATE = "${new Date().format('YYMMdd')}";
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
@ -50,9 +50,9 @@ public class Console {
|
|||||||
public static void handleException(Thread thread, Throwable throwable) {
|
public static void handleException(Thread thread, Throwable throwable) {
|
||||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
try(final PrintStream ps = new PrintStream(baos)) {
|
try(final PrintStream ps = new PrintStream(baos)) {
|
||||||
ps.printf("%s in %s\n", throwable.getMessage(), thread.getName());
|
ps.printf("%s in %s%n", throwable.getMessage(), thread.getName());
|
||||||
for (CallStack.CallInfo call : CallStack.getCalls()) {
|
for (CallStack.CallInfo call : CallStack.getCalls()) {
|
||||||
ps.printf("\tat %s\n", call);
|
ps.printf("\tat %s%n", call);
|
||||||
}
|
}
|
||||||
ps.println();
|
ps.println();
|
||||||
throwable.printStackTrace(ps);
|
throwable.printStackTrace(ps);
|
||||||
@ -74,4 +74,6 @@ public class Console {
|
|||||||
}
|
}
|
||||||
return new File(filepath);
|
return new File(filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,25 +33,9 @@ public final class Main {
|
|||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
try {
|
try {
|
||||||
final Options options = new Options();
|
runDefault();
|
||||||
options.showAst = false;
|
|
||||||
options.showTokens = false;
|
|
||||||
options.showMeasurements = false;
|
|
||||||
options.lintMode = false;
|
|
||||||
options.optimizationLevel = 0;
|
|
||||||
run(SourceLoader.readSource("program.own"), options);
|
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
System.out.println("OwnLang version " + VERSION + "\n\n" +
|
printUsage();
|
||||||
"Usage: ownlang [options]\n" +
|
|
||||||
" options:\n" +
|
|
||||||
" -f, --file [input] Run program file. Required.\n" +
|
|
||||||
" -r, --repl Enter to a REPL mode\n" +
|
|
||||||
" -l, --lint Find bugs in code\n" +
|
|
||||||
" -o N, --optimize N Perform optimization with N passes\n" +
|
|
||||||
" -b, --beautify Beautify source code\n" +
|
|
||||||
" -a, --showast Show AST of program\n" +
|
|
||||||
" -t, --showtokens Show lexical tokens\n" +
|
|
||||||
" -m, --showtime Show elapsed time of parsing and execution");
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -139,6 +123,30 @@ public final class Main {
|
|||||||
run(input, options);
|
run(input, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void runDefault() throws IOException {
|
||||||
|
final Options options = new Options();
|
||||||
|
options.showAst = false;
|
||||||
|
options.showTokens = false;
|
||||||
|
options.showMeasurements = false;
|
||||||
|
options.lintMode = false;
|
||||||
|
options.optimizationLevel = 0;
|
||||||
|
run(SourceLoader.readSource("program.own"), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void printUsage() {
|
||||||
|
System.out.println("OwnLang version " + VERSION + "\n\n" +
|
||||||
|
"Usage: ownlang [options]\n" +
|
||||||
|
" options:\n" +
|
||||||
|
" -f, --file [input] Run program file. Required.\n" +
|
||||||
|
" -r, --repl Enter to a REPL mode\n" +
|
||||||
|
" -l, --lint Find bugs in code\n" +
|
||||||
|
" -o N, --optimize N Perform optimization with N passes\n" +
|
||||||
|
" -b, --beautify Beautify source code\n" +
|
||||||
|
" -a, --showast Show AST of program\n" +
|
||||||
|
" -t, --showtokens Show lexical tokens\n" +
|
||||||
|
" -m, --showtime Show elapsed time of parsing and execution");
|
||||||
|
}
|
||||||
|
|
||||||
private static void createOwnLangArgs(String[] javaArgs, int index) {
|
private static void createOwnLangArgs(String[] javaArgs, int index) {
|
||||||
if (index >= javaArgs.length) return;
|
if (index >= javaArgs.length) return;
|
||||||
ownlangArgs = new String[javaArgs.length - index];
|
ownlangArgs = new String[javaArgs.length - index];
|
||||||
@ -152,7 +160,8 @@ public final class Main {
|
|||||||
final List<Token> tokens = Lexer.tokenize(input);
|
final List<Token> tokens = Lexer.tokenize(input);
|
||||||
measurement.stop("Tokenize time");
|
measurement.stop("Tokenize time");
|
||||||
if (options.showTokens) {
|
if (options.showTokens) {
|
||||||
for (int i = 0; i < tokens.size(); i++) {
|
final int tokensCount = tokens.size();
|
||||||
|
for (int i = 0; i < tokensCount; i++) {
|
||||||
System.out.println(i + " " + tokens.get(i));
|
System.out.println(i + " " + tokens.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,7 +214,7 @@ public final class Main {
|
|||||||
boolean lintMode;
|
boolean lintMode;
|
||||||
int optimizationLevel;
|
int optimizationLevel;
|
||||||
|
|
||||||
public Options() {
|
Options() {
|
||||||
showTokens = false;
|
showTokens = false;
|
||||||
showAst = false;
|
showAst = false;
|
||||||
showMeasurements = false;
|
showMeasurements = false;
|
||||||
@ -213,8 +222,8 @@ public final class Main {
|
|||||||
optimizationLevel = 0;
|
optimizationLevel = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validate() {
|
void validate() {
|
||||||
if (lintMode == true) {
|
if (lintMode) {
|
||||||
showTokens = false;
|
showTokens = false;
|
||||||
showAst = false;
|
showAst = false;
|
||||||
showMeasurements = false;
|
showMeasurements = false;
|
||||||
|
@ -4,6 +4,8 @@ import com.annimon.ownlang.exceptions.ArgumentsMismatchException;
|
|||||||
|
|
||||||
public final class Arguments {
|
public final class Arguments {
|
||||||
|
|
||||||
|
private Arguments() { }
|
||||||
|
|
||||||
public static void check(int expected, int got) {
|
public static void check(int expected, int got) {
|
||||||
if (got != expected) throw new ArgumentsMismatchException(String.format(
|
if (got != expected) throw new ArgumentsMismatchException(String.format(
|
||||||
"%d %s expected, got %d", expected, pluralize(expected), got));
|
"%d %s expected, got %d", expected, pluralize(expected), got));
|
||||||
|
@ -5,7 +5,9 @@ import java.util.concurrent.ConcurrentLinkedDeque;
|
|||||||
|
|
||||||
public final class CallStack {
|
public final class CallStack {
|
||||||
|
|
||||||
private static final Deque<CallInfo> calls = new ConcurrentLinkedDeque<CallInfo>();;
|
private static final Deque<CallInfo> calls = new ConcurrentLinkedDeque<>();
|
||||||
|
|
||||||
|
private CallStack() { }
|
||||||
|
|
||||||
public static synchronized void clear() {
|
public static synchronized void clear() {
|
||||||
calls.clear();
|
calls.clear();
|
||||||
|
@ -15,6 +15,8 @@ public final class Functions {
|
|||||||
functions = new HashMap<>();
|
functions = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Functions() { }
|
||||||
|
|
||||||
public static void clear() {
|
public static void clear() {
|
||||||
functions.clear();
|
functions.clear();
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,15 @@ package com.annimon.ownlang.lib;
|
|||||||
*/
|
*/
|
||||||
public final class NumberValue implements Value {
|
public final class NumberValue implements Value {
|
||||||
|
|
||||||
public static final NumberValue MINUS_ONE, ZERO, ONE;
|
private static final int CACHE_MIN = -128;
|
||||||
|
private static final int CACHE_MAX = 127;
|
||||||
|
|
||||||
|
public static final NumberValue MINUS_ONE;
|
||||||
|
public static final NumberValue ZERO;
|
||||||
|
public static final NumberValue ONE;
|
||||||
|
|
||||||
private static final int CACHE_MIN = -128, CACHE_MAX = 127;
|
|
||||||
private static final NumberValue[] NUMBER_CACHE;
|
private static final NumberValue[] NUMBER_CACHE;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
final int length = CACHE_MAX - CACHE_MIN + 1;
|
final int length = CACHE_MAX - CACHE_MIN + 1;
|
||||||
NUMBER_CACHE = new NumberValue[length];
|
NUMBER_CACHE = new NumberValue[length];
|
||||||
|
@ -10,7 +10,8 @@ public final class Types {
|
|||||||
MAP = 4,
|
MAP = 4,
|
||||||
FUNCTION = 5;
|
FUNCTION = 5;
|
||||||
|
|
||||||
private static final int FIRST = OBJECT, LAST = FUNCTION;
|
private static final int FIRST = OBJECT;
|
||||||
|
private static final int LAST = FUNCTION;
|
||||||
private static final String[] NAMES = {"object", "number", "string", "array", "map", "function"};
|
private static final String[] NAMES = {"object", "number", "string", "array", "map", "function"};
|
||||||
|
|
||||||
public static String typeToString(int type) {
|
public static String typeToString(int type) {
|
||||||
@ -19,4 +20,6 @@ public final class Types {
|
|||||||
}
|
}
|
||||||
return "unknown (" + type + ")";
|
return "unknown (" + type + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Types() { }
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ import org.json.JSONObject;
|
|||||||
|
|
||||||
public final class ValueUtils {
|
public final class ValueUtils {
|
||||||
|
|
||||||
|
private ValueUtils() { }
|
||||||
|
|
||||||
public static Object toObject(Value val) {
|
public static Object toObject(Value val) {
|
||||||
switch (val.type()) {
|
switch (val.type()) {
|
||||||
case Types.ARRAY:
|
case Types.ARRAY:
|
||||||
@ -101,7 +103,7 @@ public final class ValueUtils {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Function consumeFunction(Value value, int argumentNumber) throws TypeException {
|
public static Function consumeFunction(Value value, int argumentNumber) {
|
||||||
final int type = value.type();
|
final int type = value.type();
|
||||||
if (type != Types.FUNCTION) {
|
if (type != Types.FUNCTION) {
|
||||||
throw new TypeException("Function expected at argument " + (argumentNumber + 1)
|
throw new TypeException("Function expected at argument " + (argumentNumber + 1)
|
||||||
|
@ -35,6 +35,8 @@ public final class Variables {
|
|||||||
Variables.clear();
|
Variables.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Variables() { }
|
||||||
|
|
||||||
public static Map<String, Value> variables() {
|
public static Map<String, Value> variables() {
|
||||||
return scope.variables;
|
return scope.variables;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ public final class canvasfx implements Module {
|
|||||||
private static GraphicsContext graphics;
|
private static GraphicsContext graphics;
|
||||||
private static Canvas canvas;
|
private static Canvas canvas;
|
||||||
|
|
||||||
private static enum Events {
|
private enum Events {
|
||||||
DRAG_DETECTED(MouseEvent.DRAG_DETECTED),
|
DRAG_DETECTED(MouseEvent.DRAG_DETECTED),
|
||||||
MOUSE_CLICKED(MouseEvent.MOUSE_CLICKED),
|
MOUSE_CLICKED(MouseEvent.MOUSE_CLICKED),
|
||||||
MOUSE_DRAGGED(MouseEvent.MOUSE_DRAGGED),
|
MOUSE_DRAGGED(MouseEvent.MOUSE_DRAGGED),
|
||||||
|
@ -156,7 +156,7 @@ public final class files implements Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static abstract class FileFunction implements Function {
|
private abstract static class FileFunction implements Function {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value execute(Value... args) {
|
public Value execute(Value... args) {
|
||||||
@ -252,7 +252,7 @@ public final class files implements Module {
|
|||||||
private static class setExecutable extends FileFunction {
|
private static class setExecutable extends FileFunction {
|
||||||
@Override
|
@Override
|
||||||
protected Value execute(FileInfo fileInfo, Value[] args) throws IOException {
|
protected Value execute(FileInfo fileInfo, Value[] args) throws IOException {
|
||||||
final boolean ownerOnly = (args.length >= 3) ? (args[2].asInt() != 0) : true;
|
final boolean ownerOnly = (args.length < 3) || (args[2].asInt() != 0);
|
||||||
return NumberValue.fromBoolean(
|
return NumberValue.fromBoolean(
|
||||||
fileInfo.file.setExecutable(args[1].asInt() != 0, ownerOnly));
|
fileInfo.file.setExecutable(args[1].asInt() != 0, ownerOnly));
|
||||||
}
|
}
|
||||||
@ -261,7 +261,7 @@ public final class files implements Module {
|
|||||||
private static class setReadable extends FileFunction {
|
private static class setReadable extends FileFunction {
|
||||||
@Override
|
@Override
|
||||||
protected Value execute(FileInfo fileInfo, Value[] args) throws IOException {
|
protected Value execute(FileInfo fileInfo, Value[] args) throws IOException {
|
||||||
final boolean ownerOnly = (args.length >= 3) ? (args[2].asInt() != 0) : true;
|
final boolean ownerOnly = (args.length < 3) || (args[2].asInt() != 0);
|
||||||
return NumberValue.fromBoolean(
|
return NumberValue.fromBoolean(
|
||||||
fileInfo.file.setReadable(args[1].asInt() != 0, ownerOnly));
|
fileInfo.file.setReadable(args[1].asInt() != 0, ownerOnly));
|
||||||
}
|
}
|
||||||
@ -270,7 +270,7 @@ public final class files implements Module {
|
|||||||
private static class setWritable extends FileFunction {
|
private static class setWritable extends FileFunction {
|
||||||
@Override
|
@Override
|
||||||
protected Value execute(FileInfo fileInfo, Value[] args) throws IOException {
|
protected Value execute(FileInfo fileInfo, Value[] args) throws IOException {
|
||||||
final boolean ownerOnly = (args.length >= 3) ? (args[2].asInt() != 0) : true;
|
final boolean ownerOnly = (args.length < 3) || (args[2].asInt() != 0);
|
||||||
return NumberValue.fromBoolean(
|
return NumberValue.fromBoolean(
|
||||||
fileInfo.file.setWritable(args[1].asInt() != 0, ownerOnly));
|
fileInfo.file.setWritable(args[1].asInt() != 0, ownerOnly));
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,9 @@ import javax.swing.SwingConstants;
|
|||||||
*/
|
*/
|
||||||
public final class Components {
|
public final class Components {
|
||||||
|
|
||||||
public static Value newWindow(Value... args) {
|
private Components() { }
|
||||||
|
|
||||||
|
static Value newWindow(Value... args) {
|
||||||
Arguments.checkOrOr(0, 1, args.length);
|
Arguments.checkOrOr(0, 1, args.length);
|
||||||
String title = (args.length == 1) ? args[0].asString() : "";
|
String title = (args.length == 1) ? args[0].asString() : "";
|
||||||
final JFrame frame = new JFrame(title);
|
final JFrame frame = new JFrame(title);
|
||||||
@ -22,7 +24,7 @@ public final class Components {
|
|||||||
return new JFrameValue(frame);
|
return new JFrameValue(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Value newPanel(Value... args) {
|
static Value newPanel(Value... args) {
|
||||||
Arguments.checkOrOr(0, 1, args.length);
|
Arguments.checkOrOr(0, 1, args.length);
|
||||||
final JPanel panel = new JPanel();
|
final JPanel panel = new JPanel();
|
||||||
if (args.length == 1) {
|
if (args.length == 1) {
|
||||||
@ -31,20 +33,20 @@ public final class Components {
|
|||||||
return new JPanelValue(panel);
|
return new JPanelValue(panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Value newButton(Value... args) {
|
static Value newButton(Value... args) {
|
||||||
Arguments.checkOrOr(0, 1, args.length);
|
Arguments.checkOrOr(0, 1, args.length);
|
||||||
String text = (args.length == 1) ? args[0].asString() : "";
|
String text = (args.length == 1) ? args[0].asString() : "";
|
||||||
return new JButtonValue(new JButton(text));
|
return new JButtonValue(new JButton(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Value newLabel(Value... args) {
|
static Value newLabel(Value... args) {
|
||||||
Arguments.checkRange(0, 2, args.length);
|
Arguments.checkRange(0, 2, args.length);
|
||||||
String text = (args.length >= 1) ? args[0].asString() : "";
|
String text = (args.length >= 1) ? args[0].asString() : "";
|
||||||
int align = (args.length == 2) ? args[1].asInt() : SwingConstants.LEADING;
|
int align = (args.length == 2) ? args[1].asInt() : SwingConstants.LEADING;
|
||||||
return new JLabelValue(new JLabel(text, align));
|
return new JLabelValue(new JLabel(text, align));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Value newTextField(Value... args) {
|
static Value newTextField(Value... args) {
|
||||||
Arguments.checkOrOr(0, 1, args.length);
|
Arguments.checkOrOr(0, 1, args.length);
|
||||||
String text = (args.length == 1) ? args[0].asString() : "";
|
String text = (args.length == 1) ? args[0].asString() : "";
|
||||||
return new JTextFieldValue(new JTextField(text));
|
return new JTextFieldValue(new JTextField(text));
|
||||||
|
@ -13,7 +13,9 @@ import javax.swing.BoxLayout;
|
|||||||
*/
|
*/
|
||||||
public final class LayoutManagers {
|
public final class LayoutManagers {
|
||||||
|
|
||||||
public static Value borderLayout(Value... args) {
|
private LayoutManagers() { }
|
||||||
|
|
||||||
|
static Value borderLayout(Value... args) {
|
||||||
Arguments.checkOrOr(0, 2, args.length);
|
Arguments.checkOrOr(0, 2, args.length);
|
||||||
int hgap = (args.length == 2) ? args[0].asInt() : 0;
|
int hgap = (args.length == 2) ? args[0].asInt() : 0;
|
||||||
int vgap = (args.length == 2) ? args[1].asInt() : 0;
|
int vgap = (args.length == 2) ? args[1].asInt() : 0;
|
||||||
@ -22,7 +24,7 @@ public final class LayoutManagers {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Value boxLayout(Value... args) {
|
static Value boxLayout(Value... args) {
|
||||||
Arguments.checkOrOr(1, 2, args.length);
|
Arguments.checkOrOr(1, 2, args.length);
|
||||||
int axis = (args.length == 2) ? args[1].asInt() : BoxLayout.PAGE_AXIS;
|
int axis = (args.length == 2) ? args[1].asInt() : BoxLayout.PAGE_AXIS;
|
||||||
return new LayoutManagerValue(
|
return new LayoutManagerValue(
|
||||||
@ -30,7 +32,7 @@ public final class LayoutManagers {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Value cardLayout(Value... args) {
|
static Value cardLayout(Value... args) {
|
||||||
Arguments.checkOrOr(0, 2, args.length);
|
Arguments.checkOrOr(0, 2, args.length);
|
||||||
int hgap = (args.length == 2) ? args[0].asInt() : 0;
|
int hgap = (args.length == 2) ? args[0].asInt() : 0;
|
||||||
int vgap = (args.length == 2) ? args[1].asInt() : 0;
|
int vgap = (args.length == 2) ? args[1].asInt() : 0;
|
||||||
@ -39,7 +41,7 @@ public final class LayoutManagers {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Value gridLayout(Value... args) {
|
static Value gridLayout(Value... args) {
|
||||||
Arguments.checkRange(0, 4, args.length);
|
Arguments.checkRange(0, 4, args.length);
|
||||||
int rows = 1, cols = 0, hgap = 0, vgap = 0;
|
int rows = 1, cols = 0, hgap = 0, vgap = 0;
|
||||||
switch (args.length) {
|
switch (args.length) {
|
||||||
@ -67,7 +69,7 @@ public final class LayoutManagers {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Value flowLayout(Value... args) {
|
static Value flowLayout(Value... args) {
|
||||||
Arguments.checkRange(0, 3, args.length);
|
Arguments.checkRange(0, 3, args.length);
|
||||||
final int align, hgap, vgap;
|
final int align, hgap, vgap;
|
||||||
switch (args.length) {
|
switch (args.length) {
|
||||||
|
@ -36,7 +36,7 @@ public final class functional_filter implements Function {
|
|||||||
|
|
||||||
private Value filterArray(ArrayValue array, Function predicate, boolean takeWhile) {
|
private Value filterArray(ArrayValue array, Function predicate, boolean takeWhile) {
|
||||||
final int size = array.size();
|
final int size = array.size();
|
||||||
final List<Value> values = new ArrayList<Value>(size);
|
final List<Value> values = new ArrayList<>(size);
|
||||||
for (Value value : array) {
|
for (Value value : array) {
|
||||||
if (predicate.execute(value) != NumberValue.ZERO) {
|
if (predicate.execute(value) != NumberValue.ZERO) {
|
||||||
values.add(value);
|
values.add(value);
|
||||||
|
@ -144,9 +144,10 @@ public final class http_http implements Function {
|
|||||||
return getStringRequestBody(params, options);
|
return getStringRequestBody(params, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RequestBody getMapRequestBody(MapValue params, MapValue options) throws UnsupportedEncodingException {
|
private RequestBody getMapRequestBody(MapValue params, MapValue options) {
|
||||||
final FormBody.Builder form = new FormBody.Builder();
|
final FormBody.Builder form = new FormBody.Builder();
|
||||||
final boolean alreadyEncoded = (options.containsKey(ENCODED_KEY) && options.get(ENCODED_KEY).asInt() != 0);
|
final boolean alreadyEncoded = (options.containsKey(ENCODED_KEY)
|
||||||
|
&& options.get(ENCODED_KEY).asInt() != 0);
|
||||||
for (Map.Entry<Value, Value> param : params) {
|
for (Map.Entry<Value, Value> param : params) {
|
||||||
final String name = param.getKey().asString();
|
final String name = param.getKey().asString();
|
||||||
final String value = param.getValue().asString();
|
final String value = param.getValue().asString();
|
||||||
|
@ -283,7 +283,7 @@ public final class java implements Module {
|
|||||||
methods.add(method);
|
methods.add(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (methods.size() == 0) {
|
if (methods.isEmpty()) {
|
||||||
return FunctionValue.EMPTY;
|
return FunctionValue.EMPTY;
|
||||||
}
|
}
|
||||||
return new FunctionValue(methodsToFunction(object, methods));
|
return new FunctionValue(methodsToFunction(object, methods));
|
||||||
@ -362,7 +362,7 @@ public final class java implements Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Value objectToValue(Class<?> clazz, Object o) {
|
private static Value objectToValue(Class<?> clazz, Object o) {
|
||||||
if (o == null | o == NULL) return NULL;
|
if (o == null || o == NULL) return NULL;
|
||||||
if (clazz.isPrimitive()) {
|
if (clazz.isPrimitive()) {
|
||||||
if (int.class.isAssignableFrom(clazz))
|
if (int.class.isAssignableFrom(clazz))
|
||||||
return NumberValue.of((int) o);
|
return NumberValue.of((int) o);
|
||||||
@ -394,6 +394,16 @@ public final class java implements Module {
|
|||||||
return (Value) o;
|
return (Value) o;
|
||||||
}
|
}
|
||||||
if (clazz.isArray()) {
|
if (clazz.isArray()) {
|
||||||
|
return arrayToValue(clazz, o);
|
||||||
|
}
|
||||||
|
final Class<?> componentType = clazz.getComponentType();
|
||||||
|
if (componentType != null) {
|
||||||
|
return objectToValue(componentType, o);
|
||||||
|
}
|
||||||
|
return new ObjectValue(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Value arrayToValue(Class<?> clazz, Object o) {
|
||||||
final int length = Array.getLength(o);
|
final int length = Array.getLength(o);
|
||||||
final ArrayValue result = new ArrayValue(length);
|
final ArrayValue result = new ArrayValue(length);
|
||||||
final Class<?> componentType = clazz.getComponentType();
|
final Class<?> componentType = clazz.getComponentType();
|
||||||
@ -437,12 +447,6 @@ public final class java implements Module {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
final Class<?> componentType = clazz.getComponentType();
|
|
||||||
if (componentType != null) {
|
|
||||||
return objectToValue(componentType, o);
|
|
||||||
}
|
|
||||||
return new ObjectValue(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object[] valuesToObjects(Value[] args) {
|
private static Object[] valuesToObjects(Value[] args) {
|
||||||
Object[] result = new Object[args.length];
|
Object[] result = new Object[args.length];
|
||||||
@ -459,15 +463,8 @@ public final class java implements Module {
|
|||||||
return value.raw();
|
return value.raw();
|
||||||
case Types.STRING:
|
case Types.STRING:
|
||||||
return value.asString();
|
return value.asString();
|
||||||
case Types.ARRAY: {
|
case Types.ARRAY:
|
||||||
final ArrayValue array = (ArrayValue) value;
|
return arrayToObject((ArrayValue) value);
|
||||||
final int size = array.size();
|
|
||||||
final Object[] result = new Object[size];
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
result[i] = valueToObject(array.get(i));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (value instanceof ObjectValue) {
|
if (value instanceof ObjectValue) {
|
||||||
return ((ObjectValue) value).object;
|
return ((ObjectValue) value).object;
|
||||||
@ -477,5 +474,14 @@ public final class java implements Module {
|
|||||||
}
|
}
|
||||||
return value.raw();
|
return value.raw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Object arrayToObject(ArrayValue value) {
|
||||||
|
final int size = value.size();
|
||||||
|
final Object[] result = new Object[size];
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
result[i] = valueToObject(value.get(i));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
}
|
}
|
||||||
|
@ -430,7 +430,7 @@ public final class jdbc implements Module {
|
|||||||
set("getBigDecimal", getObjectResult(rs::getBigDecimal, rs::getBigDecimal, (bd) -> new StringValue(bd.toString())));
|
set("getBigDecimal", getObjectResult(rs::getBigDecimal, rs::getBigDecimal, (bd) -> new StringValue(bd.toString())));
|
||||||
set("getBoolean", getBooleanResult(rs::getBoolean, rs::getBoolean));
|
set("getBoolean", getBooleanResult(rs::getBoolean, rs::getBoolean));
|
||||||
set("getByte", getNumberResult(rs::getByte, rs::getByte));
|
set("getByte", getNumberResult(rs::getByte, rs::getByte));
|
||||||
set("getBytes", getObjectResult(rs::getBytes, rs::getBytes, (bytes) -> ArrayValue.of(bytes)));
|
set("getBytes", getObjectResult(rs::getBytes, rs::getBytes, ArrayValue::of));
|
||||||
set("getDate", getObjectResult(rs::getDate, rs::getDate, (date) -> NumberValue.of(date.getTime())));
|
set("getDate", getObjectResult(rs::getDate, rs::getDate, (date) -> NumberValue.of(date.getTime())));
|
||||||
set("getDouble", getNumberResult(rs::getDouble, rs::getDouble));
|
set("getDouble", getNumberResult(rs::getDouble, rs::getDouble));
|
||||||
set("getFloat", getNumberResult(rs::getFloat, rs::getFloat));
|
set("getFloat", getNumberResult(rs::getFloat, rs::getFloat));
|
||||||
|
@ -8,6 +8,7 @@ import java.awt.event.InputEvent;
|
|||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.IntConsumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -83,12 +84,7 @@ public final class robot implements Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
private static Function convertFunction(IntConsumer consumer) {
|
||||||
private interface RobotIntConsumer {
|
|
||||||
void accept(int value) throws IllegalArgumentException;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Function convertFunction(RobotIntConsumer consumer) {
|
|
||||||
return args -> {
|
return args -> {
|
||||||
Arguments.check(1, args.length);
|
Arguments.check(1, args.length);
|
||||||
try {
|
try {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.annimon.ownlang.modules.robot;
|
package com.annimon.ownlang.modules.robot;
|
||||||
|
|
||||||
import com.annimon.ownlang.Console;
|
|
||||||
import com.annimon.ownlang.lib.Arguments;
|
import com.annimon.ownlang.lib.Arguments;
|
||||||
import com.annimon.ownlang.lib.ArrayValue;
|
import com.annimon.ownlang.lib.ArrayValue;
|
||||||
import com.annimon.ownlang.lib.Function;
|
import com.annimon.ownlang.lib.Function;
|
||||||
@ -10,7 +9,7 @@ import com.annimon.ownlang.lib.Value;
|
|||||||
|
|
||||||
public final class robot_exec implements Function {
|
public final class robot_exec implements Function {
|
||||||
|
|
||||||
public static enum Mode { EXEC, EXEC_AND_WAIT };
|
public enum Mode { EXEC, EXEC_AND_WAIT }
|
||||||
|
|
||||||
private final Mode mode;
|
private final Mode mode;
|
||||||
|
|
||||||
|
@ -8,7 +8,9 @@ import com.annimon.ownlang.lib.Value;
|
|||||||
|
|
||||||
public final class NumberFunctions {
|
public final class NumberFunctions {
|
||||||
|
|
||||||
public static Value toHexString(Value... args) {
|
private NumberFunctions() { }
|
||||||
|
|
||||||
|
static Value toHexString(Value... args) {
|
||||||
Arguments.check(1, args.length);
|
Arguments.check(1, args.length);
|
||||||
long value;
|
long value;
|
||||||
if (args[0].type() == Types.NUMBER) {
|
if (args[0].type() == Types.NUMBER) {
|
||||||
|
@ -6,13 +6,15 @@ import com.annimon.ownlang.lib.Value;
|
|||||||
|
|
||||||
public final class StringFunctions {
|
public final class StringFunctions {
|
||||||
|
|
||||||
public static Value parseInt(Value... args) {
|
private StringFunctions() { }
|
||||||
|
|
||||||
|
static Value parseInt(Value... args) {
|
||||||
Arguments.checkOrOr(1, 2, args.length);
|
Arguments.checkOrOr(1, 2, args.length);
|
||||||
final int radix = (args.length == 2) ? args[1].asInt() : 10;
|
final int radix = (args.length == 2) ? args[1].asInt() : 10;
|
||||||
return NumberValue.of(Integer.parseInt(args[0].asString(), radix));
|
return NumberValue.of(Integer.parseInt(args[0].asString(), radix));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Value parseLong(Value... args) {
|
static Value parseLong(Value... args) {
|
||||||
Arguments.checkOrOr(1, 2, args.length);
|
Arguments.checkOrOr(1, 2, args.length);
|
||||||
final int radix = (args.length == 2) ? args[1].asInt() : 10;
|
final int radix = (args.length == 2) ? args[1].asInt() : 10;
|
||||||
return NumberValue.of(Long.parseLong(args[0].asString(), radix));
|
return NumberValue.of(Long.parseLong(args[0].asString(), radix));
|
||||||
|
@ -3,7 +3,6 @@ package com.annimon.ownlang.modules.std;
|
|||||||
import com.annimon.ownlang.lib.Arguments;
|
import com.annimon.ownlang.lib.Arguments;
|
||||||
import com.annimon.ownlang.lib.ArrayValue;
|
import com.annimon.ownlang.lib.ArrayValue;
|
||||||
import com.annimon.ownlang.lib.Function;
|
import com.annimon.ownlang.lib.Function;
|
||||||
import com.annimon.ownlang.lib.StringValue;
|
|
||||||
import com.annimon.ownlang.lib.Value;
|
import com.annimon.ownlang.lib.Value;
|
||||||
|
|
||||||
public final class std_split implements Function {
|
public final class std_split implements Function {
|
||||||
|
@ -13,8 +13,7 @@ public final class yaml_decode implements Function {
|
|||||||
try {
|
try {
|
||||||
final String yamlRaw = args[0].asString();
|
final String yamlRaw = args[0].asString();
|
||||||
final Object root = new Yaml().load(yamlRaw);
|
final Object root = new Yaml().load(yamlRaw);
|
||||||
final Value process = process(root);
|
return process(root);
|
||||||
return process;
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new RuntimeException("Error while parsing yaml", ex);
|
throw new RuntimeException("Error while parsing yaml", ex);
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ public final class Lexer {
|
|||||||
|
|
||||||
private static final Map<String, TokenType> KEYWORDS;
|
private static final Map<String, TokenType> KEYWORDS;
|
||||||
static {
|
static {
|
||||||
KEYWORDS = new HashMap<String, TokenType>();
|
KEYWORDS = new HashMap<>();
|
||||||
KEYWORDS.put("print", TokenType.PRINT);
|
KEYWORDS.put("print", TokenType.PRINT);
|
||||||
KEYWORDS.put("println", TokenType.PRINTLN);
|
KEYWORDS.put("println", TokenType.PRINTLN);
|
||||||
KEYWORDS.put("if", TokenType.IF);
|
KEYWORDS.put("if", TokenType.IF);
|
||||||
|
@ -13,6 +13,8 @@ import com.annimon.ownlang.parser.optimization.SummaryOptimization;
|
|||||||
|
|
||||||
public final class Optimizer {
|
public final class Optimizer {
|
||||||
|
|
||||||
|
private Optimizer() { }
|
||||||
|
|
||||||
public static Statement optimize(Statement statement, int level, boolean showSummary) {
|
public static Statement optimize(Statement statement, int level, boolean showSummary) {
|
||||||
if (level == 0) return statement;
|
if (level == 0) return statement;
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import com.annimon.ownlang.lib.StringValue;
|
|||||||
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.Collections;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -305,7 +306,7 @@ public final class Parser {
|
|||||||
}
|
}
|
||||||
if (lookMatch(0, TokenType.DOT)) {
|
if (lookMatch(0, TokenType.DOT)) {
|
||||||
final List<Expression> indices = variableSuffix();
|
final List<Expression> indices = variableSuffix();
|
||||||
if (indices == null || indices.isEmpty()) return expr;
|
if (indices.isEmpty()) return expr;
|
||||||
|
|
||||||
if (lookMatch(0, TokenType.LPAREN)) {
|
if (lookMatch(0, TokenType.LPAREN)) {
|
||||||
// next function call
|
// next function call
|
||||||
@ -441,7 +442,7 @@ public final class Parser {
|
|||||||
private Expression assignmentStrict() {
|
private Expression assignmentStrict() {
|
||||||
final int position = pos;
|
final int position = pos;
|
||||||
final Expression targetExpr = qualifiedName();
|
final Expression targetExpr = qualifiedName();
|
||||||
if ((targetExpr == null) || !(targetExpr instanceof Accessible)) {
|
if (!(targetExpr instanceof Accessible)) {
|
||||||
pos = position;
|
pos = position;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -746,7 +747,7 @@ public final class Parser {
|
|||||||
if (!match(TokenType.WORD)) return null;
|
if (!match(TokenType.WORD)) return null;
|
||||||
|
|
||||||
final List<Expression> indices = variableSuffix();
|
final List<Expression> indices = variableSuffix();
|
||||||
if ((indices == null) || indices.isEmpty()) {
|
if (indices.isEmpty()) {
|
||||||
return new VariableExpression(current.getText());
|
return new VariableExpression(current.getText());
|
||||||
}
|
}
|
||||||
return new ContainerAccessExpression(current.getText(), indices);
|
return new ContainerAccessExpression(current.getText(), indices);
|
||||||
@ -755,7 +756,7 @@ public final class Parser {
|
|||||||
private List<Expression> variableSuffix() {
|
private List<Expression> variableSuffix() {
|
||||||
// .key1.arr1[expr1][expr2].key2
|
// .key1.arr1[expr1][expr2].key2
|
||||||
if (!lookMatch(0, TokenType.DOT) && !lookMatch(0, TokenType.LBRACKET)) {
|
if (!lookMatch(0, TokenType.DOT) && !lookMatch(0, TokenType.LBRACKET)) {
|
||||||
return null;
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
final List<Expression> indices = new ArrayList<>();
|
final List<Expression> indices = new ArrayList<>();
|
||||||
while (lookMatch(0, TokenType.DOT) || lookMatch(0, TokenType.LBRACKET)) {
|
while (lookMatch(0, TokenType.DOT) || lookMatch(0, TokenType.LBRACKET)) {
|
||||||
|
@ -7,6 +7,8 @@ import java.io.InputStream;
|
|||||||
|
|
||||||
public final class SourceLoader {
|
public final class SourceLoader {
|
||||||
|
|
||||||
|
private SourceLoader() { }
|
||||||
|
|
||||||
public static String readSource(String name) throws IOException {
|
public static String readSource(String name) throws IOException {
|
||||||
InputStream is = SourceLoader.class.getResourceAsStream(name);
|
InputStream is = SourceLoader.class.getResourceAsStream(name);
|
||||||
if (is != null) return readAndCloseStream(is);
|
if (is != null) return readAndCloseStream(is);
|
||||||
@ -19,9 +21,9 @@ public final class SourceLoader {
|
|||||||
final ByteArrayOutputStream result = new ByteArrayOutputStream();
|
final ByteArrayOutputStream result = new ByteArrayOutputStream();
|
||||||
final int bufferSize = 1024;
|
final int bufferSize = 1024;
|
||||||
final byte[] buffer = new byte[bufferSize];
|
final byte[] buffer = new byte[bufferSize];
|
||||||
int readed;
|
int read;
|
||||||
while ((readed = is.read(buffer)) != -1) {
|
while ((read = is.read(buffer)) != -1) {
|
||||||
result.write(buffer, 0, readed);
|
result.write(buffer, 0, read);
|
||||||
}
|
}
|
||||||
is.close();
|
is.close();
|
||||||
return result.toString("UTF-8");
|
return result.toString("UTF-8");
|
||||||
|
@ -16,7 +16,7 @@ import com.annimon.ownlang.lib.Value;
|
|||||||
*/
|
*/
|
||||||
public final class BinaryExpression implements Expression {
|
public final class BinaryExpression implements Expression {
|
||||||
|
|
||||||
public static enum Operator {
|
public enum Operator {
|
||||||
ADD("+"),
|
ADD("+"),
|
||||||
SUBTRACT("-"),
|
SUBTRACT("-"),
|
||||||
MULTIPLY("*"),
|
MULTIPLY("*"),
|
||||||
@ -40,7 +40,7 @@ public final class BinaryExpression implements Expression {
|
|||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
private Operator(String name) {
|
Operator(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ public final class BinaryExpression implements Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Value eval(Value value1, Value value2) throws OperationIsNotSupportedException {
|
private Value eval(Value value1, Value value2) {
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case ADD: return add(value1, value2);
|
case ADD: return add(value1, value2);
|
||||||
case SUBTRACT: return subtract(value1, value2);
|
case SUBTRACT: return subtract(value1, value2);
|
||||||
@ -141,7 +141,8 @@ public final class BinaryExpression implements Expression {
|
|||||||
switch (value1.type()) {
|
switch (value1.type()) {
|
||||||
case Types.NUMBER: return subtract((NumberValue) value1, value2);
|
case Types.NUMBER: return subtract((NumberValue) value1, value2);
|
||||||
default:
|
default:
|
||||||
throw new OperationIsNotSupportedException(operation, "for " + Types.typeToString(value1.type()));
|
throw new OperationIsNotSupportedException(operation,
|
||||||
|
"for " + Types.typeToString(value1.type()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,17 +178,10 @@ public final class BinaryExpression implements Expression {
|
|||||||
private Value multiply(Value value1, Value value2) {
|
private Value multiply(Value value1, Value value2) {
|
||||||
switch (value1.type()) {
|
switch (value1.type()) {
|
||||||
case Types.NUMBER: return multiply((NumberValue) value1, value2);
|
case Types.NUMBER: return multiply((NumberValue) value1, value2);
|
||||||
case Types.STRING: {
|
case Types.STRING: return multiply((StringValue) value1, value2);
|
||||||
final String string1 = value1.asString();
|
|
||||||
final int iterations = value2.asInt();
|
|
||||||
final StringBuilder buffer = new StringBuilder();
|
|
||||||
for (int i = 0; i < iterations; i++) {
|
|
||||||
buffer.append(string1);
|
|
||||||
}
|
|
||||||
return new StringValue(buffer.toString());
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
throw new OperationIsNotSupportedException(operation, "for " + Types.typeToString(value1.type()));
|
throw new OperationIsNotSupportedException(operation,
|
||||||
|
"for " + Types.typeToString(value1.type()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,11 +214,22 @@ public final class BinaryExpression implements Expression {
|
|||||||
return NumberValue.of(number1.intValue() * value2.asInt());
|
return NumberValue.of(number1.intValue() * value2.asInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Value multiply(StringValue value1, Value value2) {
|
||||||
|
final String string1 = value1.asString();
|
||||||
|
final int iterations = value2.asInt();
|
||||||
|
final StringBuilder buffer = new StringBuilder();
|
||||||
|
for (int i = 0; i < iterations; i++) {
|
||||||
|
buffer.append(string1);
|
||||||
|
}
|
||||||
|
return new StringValue(buffer.toString());
|
||||||
|
}
|
||||||
|
|
||||||
private Value divide(Value value1, Value value2) {
|
private Value divide(Value value1, Value value2) {
|
||||||
switch (value1.type()) {
|
switch (value1.type()) {
|
||||||
case Types.NUMBER: return divide((NumberValue) value1, value2);
|
case Types.NUMBER: return divide((NumberValue) value1, value2);
|
||||||
default:
|
default:
|
||||||
throw new OperationIsNotSupportedException(operation, "for " + Types.typeToString(value1.type()));
|
throw new OperationIsNotSupportedException(operation,
|
||||||
|
"for " + Types.typeToString(value1.type()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,7 +266,8 @@ public final class BinaryExpression implements Expression {
|
|||||||
switch (value1.type()) {
|
switch (value1.type()) {
|
||||||
case Types.NUMBER: return remainder((NumberValue) value1, value2);
|
case Types.NUMBER: return remainder((NumberValue) value1, value2);
|
||||||
default:
|
default:
|
||||||
throw new OperationIsNotSupportedException(operation, "for " + Types.typeToString(value1.type()));
|
throw new OperationIsNotSupportedException(operation,
|
||||||
|
"for " + Types.typeToString(value1.type()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,7 +304,8 @@ public final class BinaryExpression implements Expression {
|
|||||||
switch (value1.type()) {
|
switch (value1.type()) {
|
||||||
case Types.ARRAY: return ArrayValue.add((ArrayValue) value1, value2);
|
case Types.ARRAY: return ArrayValue.add((ArrayValue) value1, value2);
|
||||||
default:
|
default:
|
||||||
throw new OperationIsNotSupportedException(operation, "for " + Types.typeToString(value1.type()));
|
throw new OperationIsNotSupportedException(operation,
|
||||||
|
"for " + Types.typeToString(value1.type()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +313,8 @@ public final class BinaryExpression implements Expression {
|
|||||||
switch (value1.type()) {
|
switch (value1.type()) {
|
||||||
case Types.NUMBER: return and((NumberValue) value1, value2);
|
case Types.NUMBER: return and((NumberValue) value1, value2);
|
||||||
default:
|
default:
|
||||||
throw new OperationIsNotSupportedException(operation, "for " + Types.typeToString(value1.type()));
|
throw new OperationIsNotSupportedException(operation,
|
||||||
|
"for " + Types.typeToString(value1.type()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,7 +339,8 @@ public final class BinaryExpression implements Expression {
|
|||||||
switch (value1.type()) {
|
switch (value1.type()) {
|
||||||
case Types.NUMBER: return or((NumberValue) value1, value2);
|
case Types.NUMBER: return or((NumberValue) value1, value2);
|
||||||
default:
|
default:
|
||||||
throw new OperationIsNotSupportedException(operation, "for " + Types.typeToString(value1.type()));
|
throw new OperationIsNotSupportedException(operation,
|
||||||
|
"for " + Types.typeToString(value1.type()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,7 +365,8 @@ public final class BinaryExpression implements Expression {
|
|||||||
switch (value1.type()) {
|
switch (value1.type()) {
|
||||||
case Types.NUMBER: return xor((NumberValue) value1, value2);
|
case Types.NUMBER: return xor((NumberValue) value1, value2);
|
||||||
default:
|
default:
|
||||||
throw new OperationIsNotSupportedException(operation, "for " + Types.typeToString(value1.type()));
|
throw new OperationIsNotSupportedException(operation,
|
||||||
|
"for " + Types.typeToString(value1.type()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,13 +390,10 @@ public final class BinaryExpression implements Expression {
|
|||||||
private Value lshift(Value value1, Value value2) {
|
private Value lshift(Value value1, Value value2) {
|
||||||
switch (value1.type()) {
|
switch (value1.type()) {
|
||||||
case Types.NUMBER: return lshift((NumberValue) value1, value2);
|
case Types.NUMBER: return lshift((NumberValue) value1, value2);
|
||||||
case Types.ARRAY: {
|
case Types.ARRAY: return lshift((ArrayValue) value1, value2);
|
||||||
if (value2.type() != Types.ARRAY)
|
|
||||||
throw new TypeException("Cannot merge non array value to array");
|
|
||||||
return ArrayValue.merge((ArrayValue) value1, (ArrayValue) value2);
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
throw new OperationIsNotSupportedException(operation, "for " + Types.typeToString(value1.type()));
|
throw new OperationIsNotSupportedException(operation,
|
||||||
|
"for " + Types.typeToString(value1.type()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,11 +414,18 @@ public final class BinaryExpression implements Expression {
|
|||||||
return NumberValue.of(number1.intValue() << value2.asInt());
|
return NumberValue.of(number1.intValue() << value2.asInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Value lshift(ArrayValue value1, Value value2) {
|
||||||
|
if (value2.type() != Types.ARRAY)
|
||||||
|
throw new TypeException("Cannot merge non array value to array");
|
||||||
|
return ArrayValue.merge(value1, (ArrayValue) value2);
|
||||||
|
}
|
||||||
|
|
||||||
private Value rshift(Value value1, Value value2) {
|
private Value rshift(Value value1, Value value2) {
|
||||||
switch (value1.type()) {
|
switch (value1.type()) {
|
||||||
case Types.NUMBER: return rshift((NumberValue) value1, value2);
|
case Types.NUMBER: return rshift((NumberValue) value1, value2);
|
||||||
default:
|
default:
|
||||||
throw new OperationIsNotSupportedException(operation, "for " + Types.typeToString(value1.type()));
|
throw new OperationIsNotSupportedException(operation,
|
||||||
|
"for " + Types.typeToString(value1.type()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,7 +450,8 @@ public final class BinaryExpression implements Expression {
|
|||||||
switch (value1.type()) {
|
switch (value1.type()) {
|
||||||
case Types.NUMBER: return urshift((NumberValue) value1, value2);
|
case Types.NUMBER: return urshift((NumberValue) value1, value2);
|
||||||
default:
|
default:
|
||||||
throw new OperationIsNotSupportedException(operation, "for " + Types.typeToString(value1.type()));
|
throw new OperationIsNotSupportedException(operation,
|
||||||
|
"for " + Types.typeToString(value1.type()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import com.annimon.ownlang.lib.Value;
|
|||||||
*/
|
*/
|
||||||
public final class ConditionalExpression implements Expression {
|
public final class ConditionalExpression implements Expression {
|
||||||
|
|
||||||
public static enum Operator {
|
public enum Operator {
|
||||||
EQUALS("=="),
|
EQUALS("=="),
|
||||||
NOT_EQUALS("!="),
|
NOT_EQUALS("!="),
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ public final class MatchExpression extends InterruptableNode implements Expressi
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static abstract class Pattern {
|
public abstract static class Pattern {
|
||||||
public Statement result;
|
public Statement result;
|
||||||
public Expression optCondition;
|
public Expression optCondition;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import com.annimon.ownlang.lib.Value;
|
|||||||
*/
|
*/
|
||||||
public final class UnaryExpression implements Expression, Statement {
|
public final class UnaryExpression implements Expression, Statement {
|
||||||
|
|
||||||
public static enum Operator {
|
public enum Operator {
|
||||||
INCREMENT_PREFIX("++"),
|
INCREMENT_PREFIX("++"),
|
||||||
DECREMENT_PREFIX("--"),
|
DECREMENT_PREFIX("--"),
|
||||||
INCREMENT_POSTFIX("++"),
|
INCREMENT_POSTFIX("++"),
|
||||||
|
@ -260,8 +260,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
|||||||
final String variable = ((MatchExpression.VariablePattern) pattern).variable;
|
final String variable = ((MatchExpression.VariablePattern) pattern).variable;
|
||||||
final VariableExpression expr = new VariableExpression(variable);
|
final VariableExpression expr = new VariableExpression(variable);
|
||||||
final Node node = expr.accept(this, t);
|
final Node node = expr.accept(this, t);
|
||||||
if (node != expr) {
|
if ((node != expr) && isValue(node)) {
|
||||||
if (isValue(node)) {
|
|
||||||
changed = true;
|
changed = true;
|
||||||
final Value value = ((ValueExpression) node).value;
|
final Value value = ((ValueExpression) node).value;
|
||||||
final Expression optCondition = pattern.optCondition;
|
final Expression optCondition = pattern.optCondition;
|
||||||
@ -271,7 +270,6 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
|||||||
pattern.result = result;
|
pattern.result = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (pattern instanceof MatchExpression.TuplePattern) {
|
if (pattern instanceof MatchExpression.TuplePattern) {
|
||||||
final MatchExpression.TuplePattern tuple = (MatchExpression.TuplePattern) pattern;
|
final MatchExpression.TuplePattern tuple = (MatchExpression.TuplePattern) pattern;
|
||||||
|
@ -34,7 +34,7 @@ public class PrintVisitor implements ResultVisitor<StringBuilder, StringBuilder>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StringBuilder visit(AssignmentExpression s, StringBuilder t) {
|
public StringBuilder visit(AssignmentExpression s, StringBuilder t) {
|
||||||
((Node) s.target).accept(this, t);
|
s.target.accept(this, t);
|
||||||
t.append(' ').append((s.operation == null) ? "" : s.operation);
|
t.append(' ').append((s.operation == null) ? "" : s.operation);
|
||||||
t.append("= ");
|
t.append("= ");
|
||||||
s.expression.accept(this, t);
|
s.expression.accept(this, t);
|
||||||
@ -203,7 +203,8 @@ public class PrintVisitor implements ResultVisitor<StringBuilder, StringBuilder>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StringBuilder visit(FunctionalExpression s, StringBuilder t) {
|
public StringBuilder visit(FunctionalExpression s, StringBuilder t) {
|
||||||
if (s.functionExpr instanceof ValueExpression && ((ValueExpression)s.functionExpr).value.type() == Types.STRING) {
|
if (s.functionExpr instanceof ValueExpression
|
||||||
|
&& ((ValueExpression)s.functionExpr).value.type() == Types.STRING) {
|
||||||
t.append(((ValueExpression)s.functionExpr).value.asString());
|
t.append(((ValueExpression)s.functionExpr).value.asString());
|
||||||
} else {
|
} else {
|
||||||
s.functionExpr.accept(this, t);
|
s.functionExpr.accept(this, t);
|
||||||
|
@ -17,6 +17,8 @@ import java.util.Set;
|
|||||||
|
|
||||||
public final class VisitorUtils {
|
public final class VisitorUtils {
|
||||||
|
|
||||||
|
private VisitorUtils() { }
|
||||||
|
|
||||||
public static boolean isValue(Node node) {
|
public static boolean isValue(Node node) {
|
||||||
return (node instanceof ValueExpression);
|
return (node instanceof ValueExpression);
|
||||||
}
|
}
|
||||||
|
@ -7,19 +7,10 @@ import com.annimon.ownlang.lib.Value;
|
|||||||
import com.annimon.ownlang.lib.Variables;
|
import com.annimon.ownlang.lib.Variables;
|
||||||
import com.annimon.ownlang.modules.Module;
|
import com.annimon.ownlang.modules.Module;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.yaml.snakeyaml.DumperOptions;
|
import org.yaml.snakeyaml.DumperOptions;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
@ -28,14 +19,17 @@ public final class ModulesInfoCreator {
|
|||||||
|
|
||||||
private static final String MODULES_PATH = "src/main/java/com/annimon/ownlang/modules";
|
private static final String MODULES_PATH = "src/main/java/com/annimon/ownlang/modules";
|
||||||
|
|
||||||
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
|
public static void main(String[] args)
|
||||||
|
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
|
||||||
final Class<Module> clazz = Module.class; // get classloader for package
|
final Class<Module> clazz = Module.class; // get classloader for package
|
||||||
|
|
||||||
final List<ModuleInfo> moduleInfos = new ArrayList<>();
|
final List<ModuleInfo> moduleInfos = new ArrayList<>();
|
||||||
|
|
||||||
String[] moduleNames = Arrays.stream(new File(MODULES_PATH).listFiles())
|
String[] moduleNames = Optional.ofNullable(new File(MODULES_PATH).listFiles())
|
||||||
.filter(p -> p.isDirectory())
|
.map(Arrays::stream)
|
||||||
.map(p -> p.getName())
|
.orElse(Stream.empty())
|
||||||
|
.filter(File::isDirectory)
|
||||||
|
.map(File::getName)
|
||||||
.toArray(String[]::new);
|
.toArray(String[]::new);
|
||||||
for (String moduleName : moduleNames) {
|
for (String moduleName : moduleNames) {
|
||||||
final String moduleClassPath = String.format("com.annimon.ownlang.modules.%s.%s", moduleName, moduleName);
|
final String moduleClassPath = String.format("com.annimon.ownlang.modules.%s.%s", moduleName, moduleName);
|
||||||
@ -57,16 +51,16 @@ public final class ModulesInfoCreator {
|
|||||||
|
|
||||||
System.out.println("Total modules: " + moduleInfos.size());
|
System.out.println("Total modules: " + moduleInfos.size());
|
||||||
System.out.println("Total functions: " + moduleInfos.stream()
|
System.out.println("Total functions: " + moduleInfos.stream()
|
||||||
.flatMap(m -> m.functions.stream())
|
.mapToLong(m -> m.functions.size())
|
||||||
.count()
|
.sum()
|
||||||
);
|
);
|
||||||
System.out.println("Total constants: " + moduleInfos.stream()
|
System.out.println("Total constants: " + moduleInfos.stream()
|
||||||
.flatMap(m -> m.constants.keySet().stream())
|
.mapToLong(m -> m.constants.keySet().size())
|
||||||
.count()
|
.sum()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void printAsJson(List<ModuleInfo> moduleInfos) throws JSONException {
|
private static void printAsJson(List<ModuleInfo> moduleInfos) {
|
||||||
final JSONArray modulesJson = new JSONArray();
|
final JSONArray modulesJson = new JSONArray();
|
||||||
for (ModuleInfo moduleInfo : moduleInfos) {
|
for (ModuleInfo moduleInfo : moduleInfos) {
|
||||||
modulesJson.put(new JSONObject(moduleInfo.info()));
|
modulesJson.put(new JSONObject(moduleInfo.info()));
|
||||||
@ -128,7 +122,7 @@ public final class ModulesInfoCreator {
|
|||||||
public List<Map<String, Object>> constants() {
|
public List<Map<String, Object>> constants() {
|
||||||
final List<Map<String, Object>> result = new ArrayList<>();
|
final List<Map<String, Object>> result = new ArrayList<>();
|
||||||
constants.entrySet().stream()
|
constants.entrySet().stream()
|
||||||
.sorted(Comparator.comparing(e -> e.getKey()))
|
.sorted(Comparator.comparing(Map.Entry::getKey))
|
||||||
.forEach(entry -> {
|
.forEach(entry -> {
|
||||||
final Value value = entry.getValue();
|
final Value value = entry.getValue();
|
||||||
|
|
||||||
@ -140,7 +134,7 @@ public final class ModulesInfoCreator {
|
|||||||
String text = ((Map<Value, Value>) value.raw()).entrySet().stream()
|
String text = ((Map<Value, Value>) value.raw()).entrySet().stream()
|
||||||
.sorted(Comparator.comparing(
|
.sorted(Comparator.comparing(
|
||||||
e -> ((MapValue)value).size() > 16 ? e.getKey() : e.getValue()))
|
e -> ((MapValue)value).size() > 16 ? e.getKey() : e.getValue()))
|
||||||
.map(s -> s.toString())
|
.map(Object::toString)
|
||||||
.collect(Collectors.joining(", ", "{", "}"));
|
.collect(Collectors.joining(", ", "{", "}"));
|
||||||
constant.put("value", text);
|
constant.put("value", text);
|
||||||
} else {
|
} else {
|
||||||
|
@ -68,7 +68,6 @@ public final class OptimizationDumper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String nodeToString(Node n) {
|
private static String nodeToString(Node n) {
|
||||||
// return n.toString();
|
|
||||||
return n.accept(new PrintVisitor(), new StringBuilder()).toString();
|
return n.accept(new PrintVisitor(), new StringBuilder()).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +129,8 @@ public final class Repl {
|
|||||||
|
|
||||||
int maxLength = commands.stream()
|
int maxLength = commands.stream()
|
||||||
.mapToInt(String::length)
|
.mapToInt(String::length)
|
||||||
.max().getAsInt();
|
.max()
|
||||||
|
.orElse(20);
|
||||||
|
|
||||||
final int maxCols = 2;
|
final int maxCols = 2;
|
||||||
final int size = commands.size();
|
final int size = commands.size();
|
||||||
|
@ -2,6 +2,7 @@ package com.annimon.ownlang.parser;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.openjdk.jmh.annotations.*;
|
import org.openjdk.jmh.annotations.*;
|
||||||
import org.openjdk.jmh.runner.Runner;
|
import org.openjdk.jmh.runner.Runner;
|
||||||
@ -31,7 +32,8 @@ public class LexerBenchmarkTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Test
|
@Ignore
|
||||||
|
@Test
|
||||||
public void executeBenchmark() throws RunnerException {
|
public void executeBenchmark() throws RunnerException {
|
||||||
Options opt = new OptionsBuilder()
|
Options opt = new OptionsBuilder()
|
||||||
.include(LexerBenchmarkTest.class.getSimpleName())
|
.include(LexerBenchmarkTest.class.getSimpleName())
|
||||||
|
@ -3,6 +3,7 @@ package com.annimon.ownlang.parser;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.openjdk.jmh.annotations.*;
|
import org.openjdk.jmh.annotations.*;
|
||||||
import org.openjdk.jmh.infra.Blackhole;
|
import org.openjdk.jmh.infra.Blackhole;
|
||||||
@ -33,7 +34,8 @@ public class ParserBenchmarkTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Test
|
@Ignore
|
||||||
|
@Test
|
||||||
public void executeBenchmark() throws RunnerException {
|
public void executeBenchmark() throws RunnerException {
|
||||||
Options opt = new OptionsBuilder()
|
Options opt = new OptionsBuilder()
|
||||||
.include(ParserBenchmarkTest.class.getSimpleName())
|
.include(ParserBenchmarkTest.class.getSimpleName())
|
||||||
|
Loading…
Reference in New Issue
Block a user