From d272efa49173c3708ddde54a96486261b73d7908 Mon Sep 17 00:00:00 2001 From: Nathanael Sensfelder Date: Sat, 15 Jan 2022 00:13:48 +0100 Subject: ... --- Makefile | 3 +- content/fate_v1/_index.md | 4 +- .../fate_v1/instructions/player_choices/_index.md | 14 + content/wyrd_v1/_index.md | 92 ++-- content/wyrd_v1/computation/_index.md | 179 ++++++++ content/wyrd_v1/computations/_index.md | 100 ----- content/wyrd_v1/extensions/_index.md | 5 - content/wyrd_v1/file/_index.md | 5 + content/wyrd_v1/input/_index.md | 5 + content/wyrd_v1/instruction/_index.md | 291 +++++++++++++ content/wyrd_v1/instruction_result/_index.md | 5 + content/wyrd_v1/instructions/_index.md | 76 ---- content/wyrd_v1/state/_index.md | 46 ++ content/wyrd_v1/value/_index.md | 11 + dia/wyrd_interpreter_overview.dia | Bin 0 -> 2052 bytes layouts/shortcodes/svg.html | 3 + static/images/wyrd_interpreter_overview.svg | 474 +++++++++++++++++++++ 17 files changed, 1079 insertions(+), 234 deletions(-) create mode 100644 content/wyrd_v1/computation/_index.md delete mode 100644 content/wyrd_v1/computations/_index.md delete mode 100644 content/wyrd_v1/extensions/_index.md create mode 100644 content/wyrd_v1/file/_index.md create mode 100644 content/wyrd_v1/input/_index.md create mode 100644 content/wyrd_v1/instruction/_index.md create mode 100644 content/wyrd_v1/instruction_result/_index.md delete mode 100644 content/wyrd_v1/instructions/_index.md create mode 100644 content/wyrd_v1/state/_index.md create mode 100644 content/wyrd_v1/value/_index.md create mode 100755 dia/wyrd_interpreter_overview.dia create mode 100644 layouts/shortcodes/svg.html create mode 100755 static/images/wyrd_interpreter_overview.svg diff --git a/Makefile b/Makefile index e5efc23..125a902 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ compile: hugo - scp -r public/* dreamhost:~/tonkadur/ + #scp -r public/* dreamhost:~/tonkadur/ + rsync -rzP --delete public/ dreamhost:~/tonkadur/ diff --git a/content/fate_v1/_index.md b/content/fate_v1/_index.md index 2b14b63..43075d1 100644 --- a/content/fate_v1/_index.md +++ b/content/fate_v1/_index.md @@ -1,6 +1,6 @@ --- -title: "Fate (Version 1)" -menuTitle: "Fate" +title: "Fate Language (Version 1) Documentation" +menuTitle: "Fate Language" weight: 3 --- diff --git a/content/fate_v1/instructions/player_choices/_index.md b/content/fate_v1/instructions/player_choices/_index.md index 4b54789..7b7ac58 100644 --- a/content/fate_v1/instructions/player_choices/_index.md +++ b/content/fate_v1/instructions/player_choices/_index.md @@ -30,6 +30,20 @@ A special version of the `for` loop is also possible, as described below: ### USER CHOICE - FOR TODO +### COMMAND PROMPT +{{< fatecode >}}(prompt_command! [(STRING LIST) REFERENCE] [MIN = INT] [MAX = INT] [TEXT]){{< /fatecode >}} + +Prompts the user for a list of strings separated by spaces. `[MIN]` and `[MAX]` +indicate the total number of characters (spaces included) allowed as input. +The `[TEXT]` message is prompted to the user. The result is stored in +`[(STRING LIST) REFERENCE]`. + +### FLOAT PROMPT +{{< fatecode >}}(prompt_float! [FLOAT REFERENCE] [MIN = FLOAT] [MAX = FLOAT] [TEXT]){{< /fatecode >}} + +Prompts the user for a float between `[MIN]` and `[MAX]` by displaying the +message `[TEXT]`. The result is stored in `[FLOAT REFERENCE]`. + ### INTEGER PROMPT {{< fatecode >}}(prompt_integer! [INT REFERENCE] [MIN = INT] [MAX = INT] [TEXT]){{< /fatecode >}} diff --git a/content/wyrd_v1/_index.md b/content/wyrd_v1/_index.md index c6e6e97..ac49ebe 100644 --- a/content/wyrd_v1/_index.md +++ b/content/wyrd_v1/_index.md @@ -1,57 +1,49 @@ --- -menuTitle: Wyrd -title: Wyrd (Version 1) +menuTitle: Wyrd Interpreter +title: Coding a Wyrd (Version 1) Interpreter weight: 4 --- Wyrd is the language in which the narrative is given to the game engine. It is purposefully kept small and simple to facilitate porting Tonkadur to a new engine. -The memory is seen as a table mapping strings to values. These values may also -be tables. Thus a reference is a list of strings corresponding to a move from -one table to the next. - -The program is a list of instructions. These instructions may use computations -as parameters. They sometimes use hard-coded strings parameters as well. -Instructions cannot take instructions as parameters. Instructions are not -associated to any value. - -An integer, called _Program Counter_ is used to indicate the current -instruction. In most cases, this integer is incremented by one after every -instruction. There is an instruction to modify the value of the Program Counter, -which allows conditional jumps and loops to be described. - -Computations are values and operations returning values. These are solely used -as parameters of instructions. They do not alter memory (with one exception) -and do not interact with the Program Counter in any way. An execution cannot be -stopped during the evaluation of a computation: it is part of its parent -instruction and is thus completed exactly when that instruction is performed. -Computations may _read_ from the memory, as they may need to fetch the value -associated with an address or traverse tables. All computations have a return -type. - -Wyrd does not have the notion of sequence or that lambda functions. It does not -even associate player choices with lists of actions. It's all done by carefully -managing the Program Counter. - -Lambda functions are stored as an `INT` corresponding to a line in the program. - -## Types -* `ADDRESS` (or `POINTER`, or `REFERENCE`), a list of `STRING` (note: not a - `STRING COLLECTION`). -* `BOOL`. This should be changed to `BOOL` soon, for consistency's sake. -* `[SOMETHING] COLLECTION`, table mapping `STRING` to `[SOMETHING]`. -* `FLOAT`. -* `INT`. -* `TEXT`, a list of `STRINGS` with attributes attached. -* `STRING`. -* `STRUCTURE` (or `DICTIONARY`), table mapping `STRING` to values of any type. -* `{String}`, a hard-coded string. - -#### Aliases sometimes used to refer to types -* `? ADDRESS`: an `ADDRESS` pointing to a particular type. -* `BASE TYPE`: `INT`, `FLOAT`, `BOOL`, `STRING`. -* `COMPARABLE`: `INT`, `FLOAT`, `BOOL`, `STRING`, `TEXT`, `ADDRESS`. -* `COLLECTION`: any `? COLLECTION`. -* `COMPUTATION`: any type. -* `NUMBER`: `INT` or `FLOAT`. +This part of the website guides you through the implementation of a Wyrd +interpreter. + +Wyrd files are meant to use easily parsable formats. Tonkadur provides Wyrd +files as JSON, since JSON parsers are commonly available in pretty much any +general programming language. However, the code generating this output is +cleanly separated from the rest of the compiler, so changing the compiler to +output in a different format should be approachable. + +As with Fate, Wyrd is split into computations and instructions. As a +reminder, computations do not modify the memory, whereas instructions may. +Furthermore, a computation in Fate may actually result in instructions in +Wyrd (a notable example being the `random` Fate computation, which is actually +implemented using the `set_random` Wyrd instruction). + +Here is an overview of the Wyrd interpreter: +{{< svg "static/images/wyrd_interpreter_overview.svg" "1000px" >}} + +The state a Wyrd story is described by ``, a structure defined on [this +page](/wyrd_v1/state). + +* `execute()` executes the next `` and returns the updated + ``. The semantics of each `` is explained on [this + page](/wyrd_v1/instruction). Their effect on the `{User Interface}` is + communicated by a `` member of ``, but this it can + alternatively be returned alongside the updated `` if the + implementation language permits it. All possible such effects are described + on [this page](/wyrd_v1/instruction_result). +* Calls to `compute(, )` come from two sources: resolving + the parameters of an `` and resolving the parameters of + `` (recursive call). The semantics of each `` is + defined on [this page](/wyrd_v1/computation) and is computed according to + current `` (they do not, however, modify it). The result is given as a + ``, the semantics of which can be found on [this page](/wyrd_v1/value). +* The user may be called to provide an ``. This is presented by + `handle_input(, )` on the figure above. The different + ``s and how to handle them are described on [this + page](/wyrd_v1/input). +* The parsing process (`parse()`) is described on [this + page](/wyrd_v1/file). diff --git a/content/wyrd_v1/computation/_index.md b/content/wyrd_v1/computation/_index.md new file mode 100644 index 0000000..d0462a0 --- /dev/null +++ b/content/wyrd_v1/computation/_index.md @@ -0,0 +1,179 @@ +--- +menuTitle: +title: Computation +weight: 3 +--- +This page presents all the ``s that can be performed in Wyrd. +``s do not modify the memory, but they always return a ``. + +**Shortcut to each ``:** +* [`(add_text_effect {name: String} {parameters: List} {values: list})`](#add_text_effect) +* [`(address )`](#address) +* [`(cast {from: String} {to: String} )`](#cast) +* [`(constant {type: String} {value: String})`](#constant) +* [`(get_allocable_address)`](#get_allocable_address) +* [`(if_else )`](#if_else) +* [`(last_choice_index)`](#last_choice_index) +* [`(newline)`](#newline) +* [`(operation {operator: String} )`](#unary-operation) +* [`(operation {operator: String} )`](#operation) +* [`(relative_address )`](#relative_address) +* [`(size )`](#target) +* [`(text {values: List})`](#text) +* [`(value_of )`](#value_of) +* [`({extra_computation} {parameters: List})`](#extra_computation) + +### add_text_effect +`(add_text_effect {name: String} {parameters: List} {values: list})` + +Add an effect to a list of texts, returning it as a single text. + +**Parameters:** +* `name` is a `{String}` indicating the name of the effect. +* `parameters` is a `{List}` of `` that will yield the ``s + used as parameters for the effect. +* `values` is a `{ List}` that will yield the texts to merge and + apply the effect to. These will yield ``s. + +**Process:** +* Compute the `{params: List}` corresponding to `parameters` (keep the + order). +* Compute the `{texts: List}` corresponding to `values` (keep the + order). +* Return a new `` `` with `texts` as `content`, + `name` as `effect_name`, and `params` as `effect_parameters`. + +### address +`(address )` + +Converts to an address. + +**Parameters:** +* `value_or_target` is a `` that will either result in in a + `` or a ``. + +**Process:** +* Compute the `` corresponding to `value_or_target`. +* If this resulted in a ``, return the value as is. +* If this resulted in a ``, interpret the value as + `{addr: String}`, return a new `` built from a singleton list + with `addr` as its only element. + +### cast +`(cast {from: String} {to: String} )` + +Convert from one type to another. + +**Parameters:** +* `from` is a `{String}` naming the type `content` will result to. +* `to` is a `{String}` naming the type to convert `content` to. +* `content` is a `` that will yield the `` to convert. + +**Process:** +* Compute the `` associate with `content`. +* Convert this `` from `from` to `to`. +* Return the converted value. + +**Note:** +The following conversions are expected to be available: +* A type to the same type, returning the same value. +* `` to ``, returning `(StringValue "true")` if + `` is `(BoolValue TRUE)` and `(StringValue "false")` otherwise. +* `` to ``, same as above, but with text instead of + string. +* `` to ``. +* `` to ``. +* `` to ``, using a *floor* function. +* `` to ``. +* `` to ``. +* `` to ``. +* `` to ``, with `0` being `(BoolValue FALSE)` and + anything else being `(BoolValue TRUE)`. +* `` to ``. +* `` to ``. +* `` to ``, `(BoolValue TRUE)` if the string is + `"true"`, `(BoolValue FALSE)` if it is `"false"`. Convert to lowercase prior + to checking. +* `` to ``, by recursively converting all content to + `{String}`, discarding effects and newlines, and appending it all. +* `` to ``, by converting it to `` first. +* `` to ``, by converting it to `` first. +* `` to ``, by converting it to `` first. + +### constant +`(constant {type: String} {value: String})` + +**Parameters:** + +**Process:** + +### get_allocable_address +`(get_allocable_address)` + +**Process:** + +### if_else +`(if_else )` + +**Parameters:** + +**Process:** + +### last_choice_index +`(last_choice_index)` + +**Process:** + +### newline +`(newline)` + +**Process:** + +### Unary operation +`(operation {operator: String} )` + +**Parameters:** + +**Process:** + +### operation +`(operation {operator: String} )` + +**Parameters:** + +**Process:** + +### relative_address +`(relative_address )` + +**Parameters:** + +**Process:** + +### size +`(size )` + +**Parameters:** + +**Process:** + +### text +`(text {values: List})` + +**Parameters:** + +**Process:** + +### value_of +`(value_of )` + +**Parameters:** + +**Process:** + +### extra_computation +`({extra_computation} {parameters: List})` + +**Parameters:** + +**Process:** diff --git a/content/wyrd_v1/computations/_index.md b/content/wyrd_v1/computations/_index.md deleted file mode 100644 index bc30f12..0000000 --- a/content/wyrd_v1/computations/_index.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: Computations -weight: 1 ---- -This page presents all the computations that can be performed in Wyrd. -Computations may access the current memory, but, with one exception, do not -change it. The one exception is `(new t)`. All computations return values. -The terms 'value' and 'computation' are interchangeable. - -## CONSTANT -{{< fatecode >}}(const [BASE TYPE] {string}){{< /fatecode >}} -Returns the `[BASE TYPE]` represented by `{string}`. - -## CAST -{{< fatecode >}}(cast [COMPUTATION] [BASE TYPE]){{< /fatecode >}} -Converts `[COMPUTATION]` to `[BASE TYPE]`, returns the result. - -Note: -* Converting from `FLOAT` to `INT` returns `floor(v)`. -* Converting from `BOOL` to `STRING` yields either `True` or `False`. - -The following must be supported: -* `[FLOAT]` to `[FLOAT]`, `[INT]`, and `[STRING]`. -* `[INT]` to `[FLOAT]`, `[INT]`, and `[STRING]`. -* `[BOOL]` to `[BOOL]` and `[STRING]`. -* `[STRING]` to `[BOOL]` (`true` and `false`), `[FLOAT]`, `[INT]`, and`[STRING]`. - -## IF-ELSE -{{< fatecode >}}(if_else [BOOL] [C0 = COMPUTATION] [C1 = COMPUTATION]){{< /fatecode >}} -Returns `C0` if `[BOOL]` holds _true_, `C1` otherwise. `C0` and `C1` both -have the same type. - -## EQUALS -{{< fatecode >}}(equals [C0 = COMPUTATION] [C1 = COMPUTATION]){{< /fatecode >}} -Returns a `BOOL`, _true_ if `C0` and `C1` hold the same value. `C0` and `C1` -are both of the same type. - -## MATHEMATICAL OPERATORS -{{< fatecode >}}(divide [C0 = NUMBER] [C1 = NUMBER]){{< /fatecode >}} - -{{< fatecode >}}(minus [C0 = NUMBER] [C1 = NUMBER]){{< /fatecode >}} - -{{< fatecode >}}(plus [C0 = NUMBER] [C1 = NUMBER]){{< /fatecode >}} - -{{< fatecode >}}(power [C0 = NUMBER] [C1 = NUMBER]){{< /fatecode >}} - -{{< fatecode >}}(times [C0 = NUMBER] [C1 = NUMBER]){{< /fatecode >}} -The operation returns a value of the same type as `C0` and `C1` (both `C0` and -`C1` are also of the same type). Thus, `(divide C0 C1)` is an integer division -(the remainder is discarded) if `C0` and `C1` are of type `INT`, and a standard -division if they are of type `FLOAT`. - -{{< fatecode >}}(rand [C0 = INT] [C1 = INT]){{< /fatecode >}} -Returns a random value between `C0` and `C1`, inclusive. Raises a runtime error -if `C0 > C1`. - -## MATHEMATICAL COMPARISON -{{< fatecode >}}(less_than [C0 = COMPARABLE] [C1 = COMPARABLE]){{< /fatecode >}} -Returns a `[BOOL]` indicating if `C0` is strictly less than `C1`. -`C0` and `C1` are both of the same type. - -## LOGICAL OPERATORS -{{< fatecode >}}(and [C0 = BOOL] [C1 = BOOL]){{< /fatecode >}} - -{{< fatecode >}}(not [C0 = BOOL]){{< /fatecode >}} - -## SIZE -{{< fatecode >}}(size [COLLECTION ADDRESS]){{< /fatecode >}} -Returns the number of elements held by the collection at -`[COLLECTION ADDRESS]`. - -## REFERENCES -{{< fatecode >}}(address [COMPUTATION]){{< /fatecode >}} -Returns an `ADDRESS` to the memory element at address `[COMPUTATION]`. Raises a -runtime error if `[COMPUTATION]` is not a memory element. - -{{< fatecode >}}(relative_address [R0 = (COLLECTION|STRUCTURE) ADDRESS] [STRING]){{< /fatecode >}} -Returns a `REFERENCE` to member `[STRING]` of `R0`. - -{{< fatecode >}}(value_of [ADDRESS]){{< /fatecode >}} -Returns the value held at the memory location `[ADDRESS]`. - -{{< fatecode >}}(new [TYPE]){{< /fatecode >}} -Returns an `[TYPE] ADDRESS` to a newly allocated memory element of -type `[TYPE]`. - -## TEXT -{{< fatecode >}}(newline){{< /fatecode >}} -Returns a `TEXT` value corresponding to a newline. - -{{< fatecode >}}(text [S0 = STRING] ... [SN = STRING]){{< /fatecode >}} -Returns a single value `[TEXT]` representing the elements `S0` ... `S1`. - -{{< fatecode >}}(add_text_effect ({string} [V0 = COMPUTATION] ... [VN = COMPUTATION]) [TEXT]){{< /fatecode >}} -Returns a `[TEXT]` value of `[TEXT]` with the given effect enabled. - -## LAST USER CHOICE -{{< fatecode >}}(get_last_user_choice){{< /fatecode >}} -Returns the number corresponding to the option last chosen by the user in a -`(resolve_choices)`, or `-1` if there is no such value. diff --git a/content/wyrd_v1/extensions/_index.md b/content/wyrd_v1/extensions/_index.md deleted file mode 100644 index 5ce9946..0000000 --- a/content/wyrd_v1/extensions/_index.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Extensions -weight: 3 ---- -Not available in Version 1. diff --git a/content/wyrd_v1/file/_index.md b/content/wyrd_v1/file/_index.md new file mode 100644 index 0000000..e0aa619 --- /dev/null +++ b/content/wyrd_v1/file/_index.md @@ -0,0 +1,5 @@ +--- +menuTitle: +title: File +weight: 7 +--- diff --git a/content/wyrd_v1/input/_index.md b/content/wyrd_v1/input/_index.md new file mode 100644 index 0000000..d6bbc87 --- /dev/null +++ b/content/wyrd_v1/input/_index.md @@ -0,0 +1,5 @@ +--- +menuTitle: +title: Input +weight: 6 +--- diff --git a/content/wyrd_v1/instruction/_index.md b/content/wyrd_v1/instruction/_index.md new file mode 100644 index 0000000..d441ee1 --- /dev/null +++ b/content/wyrd_v1/instruction/_index.md @@ -0,0 +1,291 @@ +--- +menuTitle: +title: Instruction +weight: 2 +--- +This page presents all the ``s that can be performed in Wyrd. +``s do not return values. + +Unless otherwise specified, all ``s: +* Increment the ``'s `program_counter` by 1. +* Set the ``'s `last_instruction_result` to `(MUST_CONTINUE)`. + +Implementing `execute()` to recurse/loop as long as the newly updated +``'s `last_instruction_result` is `(MUST_CONTINUE)` is acceptable. + +**Shortcut to each ``:** +* [`(add_event_option! {name: String} {parameters: List})`](#add_event_option) +* [`(add_text_option! )`](#add_text_option) +* [`(assert! )`](#assert) +* [`(display! )`](#display) +* [`(end!)`](#end) +* [`(initialize! {type: String} )`](#initialize) +* [`(prompt_command! )`](#prompt_command) +* [`(prompt_float! )`](#prompt_float) +* [`(prompt_integer! )`](#prompt_integer) +* [`(prompt_string! )`](#prompt_string) +* [`(remove! )`](#remove) +* [`(resolve_choice!)`](#resolve_choice) +* [`(set_pc! )`](#set_pc) +* [`(set_random! )`](#set_random) +* [`(set_value! )`](#set_value) +* [`({extra_instruction: String}! {parameters: List})`](#extra_instruction) + +### add_event_option +`(add_event_option! {name: String} {parameters: List})` + +Adds an `