package io.gitlab.jfronny.muscript; import io.gitlab.jfronny.muscript.data.Scope; import io.gitlab.jfronny.muscript.data.dynamic.*; import io.gitlab.jfronny.muscript.data.dynamic.additional.*; import java.time.LocalDate; import java.time.LocalTime; import java.util.Map; import java.util.Random; import static io.gitlab.jfronny.muscript.data.dynamic.additional.DFinal.of; public class StandardLib { private static final Random rnd = new Random(); public static Scope createScope() { return addTo(new Scope()); } public static Scope addTo(Scope scope) { return scope .set("PI", Math.PI) .set("E", Math.E) .set("date", new DCallableObject(Map.of( "today", new DDate(LocalDate::now) ), DFinal.of(args -> { // Constructor if (args.size() == 1) return new DDate(() -> LocalDate.ofEpochDay(args.get(0).asNumber().getValue().longValue())); if (args.size() != 3) throw new IllegalArgumentException("Expected 3 arguments for full date constructor"); int a0 = args.get(0).asNumber().getValue().intValue(); int a1 = args.get(1).asNumber().getValue().intValue(); int a2 = args.get(2).asNumber().getValue().intValue(); return new DDate(() -> LocalDate.of(a0, a1, a2)); }, () -> "date"))) .set("time", new DCallableObject(Map.of( "now", new DTime(LocalTime::now) ), DFinal.of(args -> { // Constructor if (args.size() == 1) return new DTime(() -> LocalTime.ofSecondOfDay(args.get(0).asNumber().getValue().intValue())); if (args.size() != 3) throw new IllegalArgumentException("Expected 3 arguments for full time constructor"); int a0 = args.get(0).asNumber().getValue().intValue(); int a1 = args.get(1).asNumber().getValue().intValue(); int a2 = args.get(2).asNumber().getValue().intValue(); return new DTime(() -> LocalTime.of(a0, a1, a2)); }, () -> "time"))) .set("round", StandardLib::round) .set("floor", StandardLib::floor) .set("ceil", StandardLib::ceil) .set("abs", StandardLib::abs) .set("random", StandardLib::random) .set("toUpper", StandardLib::toUpper) .set("toLower", StandardLib::toLower) .set("contains", StandardLib::contains) .set("replace", StandardLib::replace) .set("listOf", StandardLib::listOf) .set("len", StandardLib::len) .set("isEmpty", StandardLib::isEmpty) .set("concat", StandardLib::concat) .set("filter", StandardLib::filter) .set("map", StandardLib::map) .set("flatMap", StandardLib::flatMap) .set("fold", StandardLib::fold) .set("forEach", StandardLib::forEach) .set("callableObject", StandardLib::callableObject) .set("enum", StandardLib::enum_); } // Numbers public static DNumber round(DList args) { if (args.size() == 1) { return of(Math.round(args.get(0).asNumber().getValue())); } else if (args.size() == 2) { double x = Math.pow(10, (int) (double) args.get(1).asNumber().getValue()); return of(Math.round(args.get(0).asNumber().getValue() * x) / x); } else { throw new IllegalArgumentException("Invalid number of arguments for round: expected 1 or 2 but got " + args.size()); } } public static DNumber floor(DList args) { if (args.size() != 1) throw new IllegalArgumentException("Invalid number of arguments for floor: expected 1 but got " + args.size()); return of(Math.floor(args.get(0).asNumber().getValue())); } public static DNumber ceil(DList args) { if (args.size() != 1) throw new IllegalArgumentException("Invalid number of arguments for ceil: expected 1 but got " + args.size()); return of(Math.ceil(args.get(0).asNumber().getValue())); } public static DNumber abs(DList args) { if (args.size() != 1) throw new IllegalArgumentException("Invalid number of arguments for abs: expected 1 but got " + args.size()); return of(Math.abs(args.get(0).asNumber().getValue())); } public static DNumber random(DList args) { if (args.size() == 0) return of(rnd.nextDouble()); else if (args.size() == 2) { double min = args.get(0).asNumber().getValue(); double max = args.get(1).asNumber().getValue(); return of(min + (max - min) * rnd.nextDouble()); } throw new IllegalArgumentException("Invalid number of arguments for random: expected 0 or 2 but got " + args.size()); } // Strings public static DString toUpper(DList args) { if (args.size() != 1) throw new IllegalArgumentException("Invalid number of arguments for toUpper: expected 1 but got " + args.size()); return of(args.get(0).asString().getValue().toUpperCase()); } public static DString toLower(DList args) { if (args.size() != 1) throw new IllegalArgumentException("Invalid number of arguments for toLower: expected 1 but got " + args.size()); return of(args.get(0).asString().getValue().toLowerCase()); } public static DBool contains(DList args) { if (args.size() != 2) throw new IllegalArgumentException("Invalid number of arguments for contains: expected 2 but got " + args.size()); return of(args.get(0).asString().getValue().contains(args.get(1).asString().getValue())); } public static DString replace(DList args) { if (args.size() != 3) throw new IllegalArgumentException("Invalid number of arguments for replace: expected 3 but got " + args.size()); return of(args.get(0).asString().getValue().replace(args.get(1).asString().getValue(), args.get(2).asString().getValue())); } // Lists public static DList listOf(DList args) { return args; } public static DNumber len(DList args) { if (args.size() != 1) throw new IllegalArgumentException("Invalid number of arguments for len: expected 1 but got " + args.size()); Dynamic d = args.get(0); return of(d instanceof DString ds ? ds.getValue().length() : d.asList().size()); } public static DBool isEmpty(DList args) { if (args.size() != 1) throw new IllegalArgumentException("Invalid number of arguments for isEmpty: expected 1 but got " + args.size()); return of(args.get(0).asList().isEmpty()); } public static DList concat(DList args) { return of(args.getValue().stream().flatMap(s -> s.asList().getValue().stream()).toList()); } public static DList filter(DList args) { if (args.size() != 2) throw new IllegalArgumentException("Invalid number of arguments for filter: expected 2 but got " + args.size()); DCallable dc = args.get(1).asCallable(); return of(args.get(0).asList().getValue().stream().filter(a -> dc.call(a).asBool().getValue()).toList()); } public static DList map(DList args) { if (args.size() != 2) throw new IllegalArgumentException("Invalid number of arguments for map: expected 2 but got " + args.size()); return of(args.get(0).asList().getValue().stream().>map(args.get(1).asCallable()::call).toList()); } public static DList flatMap(DList args) { if (args.size() != 2) throw new IllegalArgumentException("Invalid number of arguments for flatMap: expected 2 but got " + args.size()); DCallable dc = args.get(1).asCallable(); return of(args.get(0).asList().getValue().stream().flatMap(a -> dc.call(a).asList().getValue().stream()).toList()); } public static Dynamic fold(DList args) { if (args.size() != 3) throw new IllegalArgumentException("Invalid number of arguments for fold: expected 3 but got " + args.size()); return args.get(0).asList().getValue().stream().reduce(args.get(1), args.get(2).asCallable()::call); } public static Dynamic forEach(DList args) { if (args.size() != 2) throw new IllegalArgumentException("Invalid number of arguments for forEach: expected 2 but got " + args.size()); Dynamic result = new DNull(); DCallable dc = args.get(1).asCallable(); for (Dynamic dynamic : args.get(0).asList().getValue()) { result = dc.call(dynamic); } return result; } // Objects public static DCallableObject callableObject(DList args) { if (args.size() != 2) throw new IllegalArgumentException("Invalid number of arguments for callableObject: expected 2 but got " + args.size()); return new DCallableObject(args.get(0).asObject().getValue(), args.get(1).asCallable()); } public static DEnum enum_(DList args) { if (args.size() == 1) return new DEnum(args.get(0).asObject().getValue()); else if (args.size() == 2) return new DEnum(args.get(0).asObject().getValue(), args.get(1).asString().getValue()); else throw new IllegalArgumentException("Invalid number of arguments for enum: expected 1 or 2 but got " + args.size()); } }