From e84f8adc8845487450e6bc0d8fa4326559da885a Mon Sep 17 00:00:00 2001 From: JFronny Date: Fri, 25 Aug 2023 18:53:04 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20Document=20StandardLib=20and=20GsonLib?= =?UTF-8?q?=20functions=20for=20=CE=BCScript=20users?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- muscript-gson/README.md | 10 +++ muscript/README.md | 3 + muscript/StandardLib.md | 77 +++++++++++++++++++ .../gitlab/jfronny/muscript/StandardLib.java | 2 +- .../muscript/data/dynamic/Dynamic.java | 3 +- muscript/src/test/resources/example.md | 7 +- 6 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 muscript-gson/README.md create mode 100644 muscript/StandardLib.md diff --git a/muscript-gson/README.md b/muscript-gson/README.md new file mode 100644 index 0000000..bac0443 --- /dev/null +++ b/muscript-gson/README.md @@ -0,0 +1,10 @@ +# μScript-gson +μScript-gson bridges the gap between μScript and commons-gson by supporting the serialization and deserialization of `Dynamic` to json and exposing this functionality to μScript scripts. +The gson type adapters are automatically registered to any `GsonHolder`, but the μScript methods need to be added to your `Scope` manually via `GsonLib.addTo(scope)`. +Other than that, no setup is needed. + +## Exposed functions +| signature | description | +|------------------------------|-------------------------------------------------------| +| `toJson(src: any): string` | Serializes `scr` to json | +| `fromJson(src: string): any` | Deserialized `src` into the appropriate μScript types | \ No newline at end of file diff --git a/muscript/README.md b/muscript/README.md index b50a7dd..99e5408 100644 --- a/muscript/README.md +++ b/muscript/README.md @@ -9,8 +9,11 @@ The language is parsed into an AST representation which is executed in-place, no μScript supports outputting data using various types, not just strings or booleans. The purpose of this document is to be a guide on embedding μScript in your application or library. + For details on how to use the language, look [here](src/test/resources/example.md). +For details on the standard library provided by μScript, look [here](StandardLib.md). + ## Embedding μScript μScript is available as a [maven package](https://maven.frohnmeyer-wds.de/#/artifacts/io/gitlab/jfronny/muscript) which you can add to your diff --git a/muscript/StandardLib.md b/muscript/StandardLib.md new file mode 100644 index 0000000..15777b0 --- /dev/null +++ b/muscript/StandardLib.md @@ -0,0 +1,77 @@ +# μScript Standard Library + +The purpose of this document is to be a guide to the standard library provided by μScript. +It is not intended to explain the syntax of the language or provide information on its history, implementation, or how to embed it in programs. + +For information on that, look at the [language guide](src/test/resources/example.md) and the [developer info](README.md). + +## Types +| name | description | +|----------|-----------------------------------------------------------------------------------------------------| +| number | Equivalent to a java double, the only number type in muScript | +| bool | A boolean. Either true or false | +| null | Equivalent to null in java or Unit in kotlin | +| string | A sequence of characters | +| list | An ordered sequence of items of any type | +| object | A mapping between keys (string) and values (any) | +| callable | A value that can be invoked via `()` | +| date | Represents a calendar date. Can be represented as string, number (days since 01-01-1970) and object | +| time | Represents a time of day. Can be represented as a string, number (second of day) and object | +| enum | Details below | +| try | Details below | + +### Enum +A map between names and values of any type. Can also be represented as a list of names. +One entry may be selected, its index will be accessible as the number representation and its name as the string representation of the enum. + +### Try +An `object` returned by the `try` function. Contains the following entries: +- `result`: The result of executing the closure, the result of `catch` if it failed and `catch` was called, or `null` +- `catch(handler: {string -> any})`: If the execution of the closure failed, + `handler` will be executed with the error message and its result will be provided as `result`. + No more than one `catch` may exist per `try`. + +## Functions +The standard library also provides a number of default utility functions. +Below, these are listed alongside their arguments. +The syntax used for signatures in this list is not used elsewhere and not part of the language. + +### Signature syntax +- If a parameter is suffixed with `?`, it can be omitted. If omission is equivalent to a default value, it will be listed with the default behind an equals sign +- If a parameter is suffixed with `...`, it will be variadic (support 0 or more arguments) +- If multiple types are possible, they are listed as `T1 / T2`, where T1 is preferred over T2 +- If an object supports multiple representations, it will be denoted as `T1 & T2` +- Callables are represented like closures but with types instead of names + +### Supported functions +| signature | description | +|---------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `round(value: number, decimalPlaces?: number = 0): number` | Rounds `value` while retaining `decimalPlaces` places after the comma | +| `floor(value: number): number` | Returns the largest integer lower than or equal to `value` | +| `ceil(value: number): number` | Returns the smallest integer larger than or equal to `value` | +| `abs(value: number): number` | Returns the absolute value of `value` (always positive or zero) | +| `random(min?: number = 0, max?: number = 1): number` | Returns a random number between `min` and `max`. If `min` is provided, `max` cannot be omitted. | +| `toUpper(value: string): string` | Converts all characters in `value` to upper case | +| `toLower(value: string): string` | Converts all characters in `value` to lower case | +| `contains(in: list / object / string, find: any): bool` | Checks whether `find` is an element of the list, a key of the object or a substring of the string provided as `in` | +| `replace(source: string, target: string, replacement: string): string` | Replaces all instances of `target` in `source` with `replacement` and returns the result | +| `listOf(elements: any...): list` | Creates a list with the provided elements | +| `len(toCheck: string / object / list): number` | Gets the amount of characters in the string or entries in the object or list provided as `toCheck` | +| `isEmpty(toCheck: object / list): bool` | Checks whether the object or list provided as `toCheck` contain any entries | +| `concat(lists: list...): list` | Returns a list containing all elements of all provided lists in their original order | +| `filter(in: list, with: {any -> bool}): list` | Returns a list of all elements `el` of `in` for which `with(el)` returned true | +| `allMatch(in: list, with: {any -> bool}): bool` | Whether `with(el)` is true for all elements `el` of `in` | +| `anyMatch(in: list, with: {any -> bool}): bool` | Whether `with(el)` is true for any element `el` of `in` | +| `map(in: list, with: {any -> any}): list` | Returns a list of the results of applying `with` to all elements of `in` | +| `flatMap(in: list, with: {any -> list}): list` | Returns the concatenated list of the results of applying `with` to all elements of `in` | +| `fold(in: list, identity: any, operator: {any, any -> any}): any` | Runs `operator(previous, current)` for every element in `in` where `previous` is the previous result of `operator`, starting with `identity` and `current` is the current element | +| `forEach(in: list, with: {any -> any}): any` | Runs `with` for each element in `in`, returning the last result or `null` for empty lists | +| `toObject(from: list, keyMapper: {any -> string}, valueMapper: {any -> any}): object` | Creates an object mapping the results of `keyMapper` to the results of `valueMapper` for every element in `from` | +| `callableObject(source: object, action: callable): object & callable` | Returns an object equivalent to `source` that can be called, resulting in the invocation of `action` | +| `enum(values: object, selected?: string): enum` | Creates an enum with the values provided as `values`, optionally marking the one with the key `selected` as such | +| `keys(ob: object): list` | Returns the list of names of entries of the object `ob` | +| `values(ob: object): list` | Returns the list of values of entries of the object `ob` | +| `try(closure: {any... -> any}, args: any...): try` | Attempts to execute the closure with the provided args and returns a `try`. For details on what to do with that, look above. | + +Other project-specific functions (like [μScript-gson](../muscript-gson/README.md)) will likely also be available to your scripts. +Please consult the documentation for the project using μScript for more information on what is available or use `this::keys()` to view everything. \ No newline at end of file diff --git a/muscript/src/main/java/io/gitlab/jfronny/muscript/StandardLib.java b/muscript/src/main/java/io/gitlab/jfronny/muscript/StandardLib.java index 572139b..27d5bb9 100644 --- a/muscript/src/main/java/io/gitlab/jfronny/muscript/StandardLib.java +++ b/muscript/src/main/java/io/gitlab/jfronny/muscript/StandardLib.java @@ -194,7 +194,7 @@ public class StandardLib { 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()); + return of(args.get(0).asList().getValue().stream().map(args.get(1).asCallable()::call).toList()); } public static DList flatMap(DList args) { diff --git a/muscript/src/main/java/io/gitlab/jfronny/muscript/data/dynamic/Dynamic.java b/muscript/src/main/java/io/gitlab/jfronny/muscript/data/dynamic/Dynamic.java index 685bc07..7b79c2b 100644 --- a/muscript/src/main/java/io/gitlab/jfronny/muscript/data/dynamic/Dynamic.java +++ b/muscript/src/main/java/io/gitlab/jfronny/muscript/data/dynamic/Dynamic.java @@ -7,6 +7,7 @@ import io.gitlab.jfronny.muscript.ast.Expr; import io.gitlab.jfronny.muscript.compiler.ExprWriter; import io.gitlab.jfronny.muscript.compiler.Parser; import io.gitlab.jfronny.muscript.data.dynamic.additional.*; +import io.gitlab.jfronny.muscript.data.dynamic.lens.DStringLens; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -76,7 +77,7 @@ public sealed interface Dynamic permits DBool, DCallable, DList, DNull, DNumber, default DString asString() { if (this instanceof DString string) return string; - else return DFinal.of(StringFormatter.toString(getValue())); + else return new DStringLens(this, () -> StringFormatter.toString(getValue())); } default boolean isObject() { diff --git a/muscript/src/test/resources/example.md b/muscript/src/test/resources/example.md index d4a4234..0fef8f2 100644 --- a/muscript/src/test/resources/example.md +++ b/muscript/src/test/resources/example.md @@ -2,8 +2,11 @@ The purpose of this document is to be a guide to using the μScript language. It is not intended to explain any history of the language, implementation details or details on how to embed μScript in programs. + For information on that, look [here](../../../README.md). +For information on the standard library provided by μScript, look [here](../../../StandardLib.md) + ## Types μScript supports a couple of basic types, namely: - [Numbers](#numbers) (double-precision floating-point) @@ -43,12 +46,12 @@ listOf( 4 >= 4, 5 != 2, 8 == 8, - round(PI, 2) + floor(E) // round also accepts a second argument: precision, but it can be ommitted to round to a whole number + round(PI, floor(E)) // round also accepts a second argument: decimalPlaces, but it can be ommitted to round to a whole number ) ``` Result: ``` -[7, -3, 2, 8, 12, 2, 2, 1024, true, false, true, true, true, 5.1400] +[7, -3, 2, 8, 12, 2, 2, 1024, true, false, true, true, true, 3.14] ```