[std] Add parseDouble, nanotime, exit, getenv, getprop

This commit is contained in:
aNNiMON 2023-10-28 18:54:19 +03:00 committed by Victor Melnik
parent c3a893ea25
commit 5d00598e8c
38 changed files with 146 additions and 142 deletions

View File

@ -10,7 +10,7 @@ import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.ValueUtils;
import java.io.UnsupportedEncodingException;
public final class ArrayFunctions {
final class ArrayFunctions {
private ArrayFunctions() { }

View File

@ -6,7 +6,7 @@ import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
public final class NumberFunctions {
final class NumberFunctions {
private NumberFunctions() { }

View File

@ -8,7 +8,7 @@ import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Value;
import java.io.UnsupportedEncodingException;
public final class StringFunctions {
final class StringFunctions {
private StringFunctions() { }
@ -22,6 +22,11 @@ public final class StringFunctions {
}
}
static Value parseDouble(Value[] args) {
Arguments.check(1, args.length);
return NumberValue.of(Double.parseDouble(args[0].asString()));
}
static Value parseInt(Value[] args) {
Arguments.checkOrOr(1, 2, args.length);
final int radix = (args.length == 2) ? args[1].asInt() : 10;
@ -45,7 +50,7 @@ public final class StringFunctions {
// First blank line is omitted
final StringBuilder sb = new StringBuilder();
final int firstLineIndex = (isBlank(lines[0])) ? 1 : 0;
final int firstLineIndex = (lines[0].isBlank()) ? 1 : 0;
final int lastLineIndex = lines.length - 1;
int index = firstLineIndex;
while (true) {
@ -54,7 +59,7 @@ public final class StringFunctions {
sb.append('\n');
}
// Process last line
if (lastLineIndex >= (firstLineIndex + 1) && !isBlank(lines[lastLineIndex])) {
if (lastLineIndex >= (firstLineIndex + 1) && !lines[lastLineIndex].isBlank()) {
sb.append('\n').append(strip(lines[lastLineIndex], marginPrefix));
}
return new StringValue(sb.toString());
@ -69,10 +74,6 @@ public final class StringFunctions {
}
}
private static boolean isBlank(String str) {
return firstNonBlankIndex(str) == str.length();
}
private static int firstNonBlankIndex(String str) {
final int length = str.length();
for (int index = 0; index < length; index++) {

View File

@ -0,0 +1,42 @@
package com.annimon.ownlang.modules.std;
import com.annimon.ownlang.lib.*;
final class SystemFunctions {
private SystemFunctions() { }
static Value exit(Value[] args) {
Arguments.check(1, args.length);
System.exit(args[0].asInt());
return NumberValue.ZERO;
}
static Value getenv(Value[] args) {
Arguments.checkOrOr(1, 2, args.length);
final var env = System.getenv(args[0].asString());
if (env == null) {
return args.length == 2 ? args[1] : StringValue.EMPTY;
}
return new StringValue(env);
}
static Value getprop(Value[] args) {
Arguments.checkOrOr(1, 2, args.length);
final var env = System.getProperty(args[0].asString());
if (env == null) {
return args.length == 2 ? args[1] : StringValue.EMPTY;
}
return new StringValue(env);
}
static Value time(Value[] args) {
Arguments.check(0, args.length);
return NumberValue.of(System.currentTimeMillis());
}
static Value nanotime(Value[] args) {
Arguments.check(0, args.length);
return NumberValue.of(System.nanoTime());
}
}

View File

@ -4,6 +4,7 @@ import com.annimon.ownlang.Shared;
import com.annimon.ownlang.Version;
import com.annimon.ownlang.lib.*;
import com.annimon.ownlang.modules.Module;
import java.util.HashMap;
import java.util.Map;
import static java.util.Map.entry;
@ -30,22 +31,31 @@ public final class std implements Module {
@Override
public Map<String, Function> functions() {
return Map.ofEntries(
// std, System
final var result = new HashMap<>(Map.ofEntries(
entry("echo", new std_echo()),
entry("readln", new std_readln()),
entry("length", new std_length()),
entry("rand", new std_rand()),
entry("time", new std_time()),
entry("time", SystemFunctions::time),
entry("nanotime", SystemFunctions::nanotime),
entry("sleep", new std_sleep()),
entry("thread", new std_thread()),
entry("sync", new std_sync()),
entry("try", new std_try()),
entry("default", new std_default()),
entry("exit", SystemFunctions::exit),
entry("getenv", SystemFunctions::getenv),
entry("getprop", SystemFunctions::getprop)
));
// Numbers
entry("toHexString", NumberFunctions::toHexString),
result.putAll(Map.ofEntries(
entry("toHexString", NumberFunctions::toHexString)
));
// String
result.putAll(Map.ofEntries(
entry("getBytes", StringFunctions::getBytes),
entry("sprintf", new std_sprintf()),
entry("split", new std_split()),
@ -62,9 +72,12 @@ public final class std implements Module {
entry("replaceFirst", new std_replacefirst()),
entry("parseInt", StringFunctions::parseInt),
entry("parseLong", StringFunctions::parseLong),
entry("stripMargin", StringFunctions::stripMargin),
entry("parseDouble", StringFunctions::parseDouble),
entry("stripMargin", StringFunctions::stripMargin)
));
// Arrays and map,
// Arrays and map
result.putAll(Map.ofEntries(
entry("newarray", new std_newarray()),
entry("join", new std_join()),
entry("sort", new std_sort()),
@ -75,6 +88,7 @@ public final class std implements Module {
entry("arraySplice", new std_arraySplice()),
entry("range", new std_range()),
entry("stringFromBytes", ArrayFunctions::stringFromBytes)
);
));
return Map.copyOf(result);
}
}

View File

@ -8,7 +8,7 @@ import com.annimon.ownlang.lib.MapValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
public final class std_arrayCombine implements Function {
final class std_arrayCombine implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -8,7 +8,7 @@ import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
public final class std_arrayKeyExists implements Function {
final class std_arrayKeyExists implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -11,7 +11,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public final class std_arrayKeys implements Function {
final class std_arrayKeys implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -7,7 +7,7 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
public final class std_arraySplice implements Function {
final class std_arraySplice implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -11,7 +11,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public final class std_arrayValues implements Function {
final class std_arrayValues implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -5,7 +5,7 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
public final class std_charat implements Function {
final class std_charat implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -1,13 +1,8 @@
package com.annimon.ownlang.modules.std;
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.*;
public final class std_default implements Function {
final class std_default implements Function {
@Override
public Value execute(Value[] args) {
@ -22,17 +17,13 @@ public final class std_default implements Function {
if (value == null || value.raw() == null) {
return true;
}
switch (value.type()) {
case Types.NUMBER:
return (value.asInt() == 0);
case Types.STRING:
return (value.asString().isEmpty());
case Types.ARRAY:
return ((ArrayValue) value).size() == 0;
case Types.MAP:
return ((MapValue) value).size() == 0;
default:
return false;
}
return switch (value.type()) {
case Types.NUMBER -> (value.asInt() == 0);
case Types.STRING -> (value.asString().isEmpty());
case Types.ARRAY -> ((ArrayValue) value).size() == 0;
case Types.MAP -> ((MapValue) value).size() == 0;
case Types.CLASS -> ((ClassInstance) value).getThisMap().size() == 0;
default -> false;
};
}
}

View File

@ -5,14 +5,14 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
public final class std_echo implements Function {
final class std_echo implements Function {
@Override
public Value execute(Value[] args) {
final StringBuilder sb = new StringBuilder();
for (Value arg : args) {
sb.append(arg.asString());
sb.append(" ");
sb.append(' ');
}
Console.println(sb.toString());
return NumberValue.ZERO;

View File

@ -5,7 +5,7 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
public final class std_indexof implements Function {
final class std_indexof implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -8,7 +8,7 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
public final class std_join implements Function {
final class std_join implements Function {
@Override
public Value execute(Value[] args) {
@ -18,17 +18,12 @@ public final class std_join implements Function {
}
final ArrayValue array = (ArrayValue) args[0];
switch (args.length) {
case 1:
return ArrayValue.joinToString(array, "", "", "");
case 2:
return ArrayValue.joinToString(array, args[1].asString(), "", "");
case 3:
return ArrayValue.joinToString(array, args[1].asString(), args[2].asString(), args[2].asString());
case 4:
return ArrayValue.joinToString(array, args[1].asString(), args[2].asString(), args[3].asString());
default:
throw new ArgumentsMismatchException("Wrong number of arguments");
}
return switch (args.length) {
case 1 -> ArrayValue.joinToString(array, "", "", "");
case 2 -> ArrayValue.joinToString(array, args[1].asString(), "", "");
case 3 -> ArrayValue.joinToString(array, args[1].asString(), args[2].asString(), args[2].asString());
case 4 -> ArrayValue.joinToString(array, args[1].asString(), args[2].asString(), args[3].asString());
default -> throw new ArgumentsMismatchException("Wrong number of arguments");
};
}
}

View File

@ -5,7 +5,7 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
public final class std_lastindexof implements Function {
final class std_lastindexof implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -2,32 +2,24 @@ package com.annimon.ownlang.modules.std;
import com.annimon.ownlang.lib.*;
public final class std_length implements Function {
final class std_length implements Function {
@Override
public Value execute(Value[] args) {
Arguments.check(1, args.length);
final Value val = args[0];
final int length;
switch (val.type()) {
case Types.ARRAY:
length = ((ArrayValue) val).size();
break;
case Types.MAP:
length = ((MapValue) val).size();
break;
case Types.STRING:
length = ((StringValue) val).length();
break;
case Types.FUNCTION:
final Function func = ((FunctionValue) val).getValue();
length = func.getArgsCount();
break;
default:
length = 0;
final Value value = args[0];
final int length = switch (value.type()) {
case Types.ARRAY -> ((ArrayValue) value).size();
case Types.MAP -> ((MapValue) value).size();
case Types.CLASS -> ((ClassInstance) value).getThisMap().size();
case Types.STRING -> ((StringValue) value).length();
case Types.FUNCTION -> {
final Function func = ((FunctionValue) value).getValue();
yield func.getArgsCount();
}
default -> 0;
};
return NumberValue.of(length);
}
}

View File

@ -5,7 +5,7 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
public final class std_newarray implements Function {
final class std_newarray implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -6,7 +6,7 @@ import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
import java.util.Random;
public final class std_rand implements Function {
final class std_rand implements Function {
private static final Random RND = new Random();

View File

@ -3,32 +3,16 @@ package com.annimon.ownlang.modules.std;
import com.annimon.ownlang.lib.*;
import java.util.Iterator;
public final class std_range implements Function {
final class std_range implements Function {
@Override
public Value execute(Value[] args) {
Arguments.checkRange(1, 3, args.length);
final long from, to, step;
switch (args.length) {
default:
case 1:
from = 0;
to = getLong(args[0]);
step = 1;
break;
case 2:
from = getLong(args[0]);
to = getLong(args[1]);
step = 1;
break;
case 3:
from = getLong(args[0]);
to = getLong(args[1]);
step = getLong(args[2]);
break;
}
return RangeValue.of(from, to, step);
return switch (args.length) {
default -> RangeValue.of(0, getLong(args[0]), 1);
case 2 -> RangeValue.of(getLong(args[0]), getLong(args[1]), 1);
case 3 -> RangeValue.of(getLong(args[0]), getLong(args[1]), getLong(args[2]));
};
}
private static long getLong(Value v) {

View File

@ -5,7 +5,7 @@ import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Value;
import java.util.Scanner;
public final class std_readln implements Function {
final class std_readln implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -5,7 +5,7 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Value;
public final class std_replace implements Function {
final class std_replace implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -5,7 +5,7 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Value;
public final class std_replaceall implements Function {
final class std_replaceall implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -5,7 +5,7 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Value;
public final class std_replacefirst implements Function {
final class std_replacefirst implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -5,7 +5,7 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
public final class std_sleep implements Function {
final class std_sleep implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -10,7 +10,7 @@ import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.ValueUtils;
import java.util.Arrays;
public final class std_sort implements Function {
final class std_sort implements Function {
@Override
public Value execute(Value[] args) {
@ -21,15 +21,12 @@ public final class std_sort implements Function {
final Value[] elements = ((ArrayValue) args[0]).getCopyElements();
switch (args.length) {
case 1:
Arrays.sort(elements);
break;
case 2:
case 1 -> Arrays.sort(elements);
case 2 -> {
final Function comparator = ValueUtils.consumeFunction(args[1], 1);
Arrays.sort(elements, (o1, o2) -> comparator.execute(o1, o2).asInt());
break;
default:
throw new ArgumentsMismatchException("Wrong number of arguments");
}
default -> throw new ArgumentsMismatchException("Wrong number of arguments");
}
return new ArrayValue(elements);

View File

@ -5,7 +5,7 @@ import com.annimon.ownlang.lib.ArrayValue;
import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.Value;
public final class std_split implements Function {
final class std_split implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -6,7 +6,7 @@ import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
public final class std_sprintf implements Function {
final class std_sprintf implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -5,7 +5,7 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Value;
public final class std_substring implements Function {
final class std_substring implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -10,7 +10,7 @@ import com.annimon.ownlang.lib.ValueUtils;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public final class std_sync implements Function {
final class std_sync implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -3,7 +3,7 @@ package com.annimon.ownlang.modules.std;
import com.annimon.ownlang.Console;
import com.annimon.ownlang.lib.*;
public final class std_thread implements Function {
final class std_thread implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -1,13 +0,0 @@
package com.annimon.ownlang.modules.std;
import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
public final class std_time implements Function {
@Override
public Value execute(Value[] args) {
return NumberValue.of(System.currentTimeMillis());
}
}

View File

@ -5,7 +5,7 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Value;
public final class std_tochar implements Function {
final class std_tochar implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -5,7 +5,7 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Value;
public final class std_tolowercase implements Function {
final class std_tolowercase implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -5,7 +5,7 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Value;
public final class std_touppercase implements Function {
final class std_touppercase implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -5,7 +5,7 @@ import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Value;
public final class std_trim implements Function {
final class std_trim implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -2,7 +2,7 @@ package com.annimon.ownlang.modules.std;
import com.annimon.ownlang.lib.*;
public final class std_try implements Function {
final class std_try implements Function {
@Override
public Value execute(Value[] args) {

View File

@ -19,7 +19,8 @@ public final class types implements Module {
entry("STRING", NumberValue.of(Types.STRING)),
entry("ARRAY", NumberValue.of(Types.ARRAY)),
entry("MAP", NumberValue.of(Types.MAP)),
entry("FUNCTION", NumberValue.of(Types.FUNCTION))
entry("FUNCTION", NumberValue.of(Types.FUNCTION)),
entry("CLASS", NumberValue.of(Types.CLASS))
);
}