1
0
Fork 0
mirror of https://github.com/Reuh/anselme.git synced 2025-10-27 16:49:31 +00:00

Update README, bump version

This commit is contained in:
Étienne Fildadut 2022-09-10 17:59:22 +09:00
parent 1263c32572
commit 7b756ad092
7 changed files with 137 additions and 25 deletions

View file

@ -248,7 +248,7 @@ Functions can return a value using a [return line](#lines-that-can-t-have-childr
Functions always have the following variables defined in its namespace by default:
`👁️`: number, number of times the function was executed before
`🔖`: funcion reference, last reached checkpoint. `nil` if no checkpoint reached.
`🔖`: function reference, last reached checkpoint. `nil` if no checkpoint reached.
* `§`: checkpoint. Followed by an [identifier](#identifiers), then eventually an [alias](#aliases). Define a checkpoint. Also define a new namespace for its children.
@ -630,9 +630,9 @@ Default types are:
* `annotated`: a couple of values. Types can be mixed. Can be defined using colon `expr::type`. The second value is used in type constraints, this is intended to be use to give a custom type to a value.
* `function reference`: reference to one or more function(s) with a given name. Can be defined using `&function name`, which will create a reference to every function with this name accessible from the current namespace. Can be called as if it was the original function using `func ref!` and `func ref(args)`.
* `function reference`: reference to one or more function(s) with a given name. Can be defined using `&function name`, which will create a reference to every function with this name accessible from the current namespace. Will behave as if it was the original function (can be called using `func ref`, `func ref!` or `func ref(args)`).
* `variable reference`: reference to a single variable with a given name. Can be defined using `&variable name`, which will create a reference to the closest variable with this name accessible from the current namespace. Can get the referenced variable value using `var ref!`.
* `variable reference`: reference to a single variable with a given name. Can be defined using `&variable name`, which will create a reference to the closest variable with this name accessible from the current namespace. Will behave as if it was the original variable, returning the value when called (value can be retrieved using `var ref!` or simply `var ref`).
* `list`: a list of values. Mutable. Types can be mixed. Can be defined between square brackets and use comma as a separator '[1,2,3,4]'.
@ -676,11 +676,17 @@ These can be used to represent some caracters in string and other text elements
* `\"` for `"`
* `\n` for a newline
* `\t` for a tabulation
* `\{` for `{`
* `\[` for `[`
* `\{` and `\}` for `{` and `}`
* `\[` and `\]` for `[` and `]`
* `\~` for `~`
* `\#` for `#`
* `\$` for `$`
* `\(` for `(`
* `\>` for `>`
* `\%` for `%`
* `\§` for `§`
* `\@` for `@`
* `\:` for `:`
#### Truethness
@ -941,8 +947,9 @@ _*_ _//_ _/_ _%_
_::_
-_ !_
_^_
_._ _!_
_!_
&_
_._
```
A series of operators with the same priority are evaluated left-to-right.
@ -1009,15 +1016,19 @@ This only works on strings:
`fn!`: call the function, checkpoint or function reference without arguments. Can leads to different behaviour that the syntax with parantheses; see [function calls](#function-calls).
`&fn`: returns a function reference to the given function.
`fn`: call the function, checkpoint or function reference without arguments. Can leads to different behaviour that the other syntaxes; see [function calls](#function-calls).
`&fn`: returns a function reference to the given function. If it is already a reference, returns the same reference.
`a!fn(args)`: call the function or function reference with the variable as first argument. Parantheses are optional.
##### Variable references
`&var`: returns a variable reference to the given variable.
`&var`: returns a variable reference to the given variable. If it is already a reference, returns the same reference.
`a!`: returns the value associated with the reference variable.
`a!`: returns the value associated with the referenced variable.
`a`: returns the value associated with the referenced variable.
##### Various
@ -1031,9 +1042,9 @@ This only works on strings:
`a # b`: evaluates b, then evaluates a with b added to the active tags (wrap b in a map and merges it with the current tag map). Returns a.
`a.b`: if a is a function reference, returns the first found variable (or reference to a subfunction) named `b` in the referenced function namespace. When overloading this operator, if `b` is an identifier, the operator will interpret it as a string (instead of returning the evaluated value of the variable eventually associated to the identifier).
`a.b`: if a is a function reference, returns the first found variable named `b` in the referenced function namespace; or if `b` is a subfunction in the referenced function, will call it (you can use the usual ways to call functions and gives arguments as well: `a.b!` or `a.b(x, y, ...)`). When overloading this operator, if `b` is an identifier, the operator will interpret it as a string (instead of returning the evaluated value of the variable eventually associated to the identifier).
`object.b`: if object is an object, returns the first found variable (or reference to a subfunction) named `b` in the object, or, if the object does not contain it, its base class.
`object.b`: if object is an object, returns the first found variable named `b` in the object, or, if the object does not contain it, found in its base class. If `b` is a subfunction in the base class, will call it (arguments can also be given using the usual syntax).
`list(b)`: evaluate b (number), returns the value with this index in the list. Use 1-based indexing. If a negative value is given, will look from the end of the list (`-1` is the last element, `-2` the one before, etc.). Error on invalid index. Operator is named `()`.
@ -1091,7 +1102,7 @@ This only works on strings:
#### Built-in variables
Variables for default types (each is associated to a string of the internal variable type name): `nil`, `number`, `string`, `list`, `pair`, `function reference`, `variable reference`.
Variables for default types (each is associated to a string of the internal variable type name): `nil`, `number`, `string`, `list`, `map`, `pair`, `function reference`, `variable reference`.
The π constant is also defined in `pi`.

View file

@ -66,6 +66,8 @@ Othertimes we don't:
TODO: stupidly complex script
See [TUTORIAL.md](TUTORIAL.md) for a short introduction (not yet done).
Reference
------------------

77
TUTORIAL.md Normal file
View file

@ -0,0 +1,77 @@
Anselme short tutorial
======================
This document is a work-in-progress and currently mostly useless.
Level 1: basics
---------------
Basics of Anselme. Should be enough to make a "choose-your-own-adventure" type script using the test game runner.
### Text
Writing simple text.
### Choices
Defining multiple choices.
### Basic functions
Defining functions without arguments and switching to them.
### Variables and conditions
Variable & constant definition, simple conditions and expressions.
Level 2: intermediate
---------------------
More advanced features that you would likely need if you intend to integrate Anselme into your game.
### Checkpoints
Purpose and how they work.
### Tags
Tag lines, subtexts.
### Events and adding Anselme to your game
Events buffer, basic Lua API.
### Other line types
Loops, comments.
Level 3: advanced
-----------------
If you want to make full use of Anselme's features for your game, or just want to flex about a language nobody's heard of in your CV. This part will assume previous programming knowledge.
### Advanced functions
Arguments, scopes, return values.
### Advanced expressions
Variable types, operators, built-in functions. This part is going to be long...
#### General rules of an expression
#### Operators
#### Main types
#### Sequences and maps
#### Objects
#### References
#### Function dispatch
### Translation
Aliases, what can be translated, what is saved.

View file

@ -54,14 +54,14 @@ local anselme = {
-- * `language`, which is incremented at each update which may break script file compatibility
-- * `api`, which is incremented at each update which may break Lua API compatibility
versions = {
save = 1,
language = 22,
save = 2,
language = 23,
api = 5
},
--- General version number.
--
-- It is incremented at each update.
version = 23,
version = 24,
--- Currently running [interpreter](#interpreters).
-- `nil` if no interpreter running.
running = nil

View file

@ -43,11 +43,24 @@ Reserved symbols that are still not used as a line type: `^+-=</[]*{}|\_!?.,;)"&
Broad goals and ideas that may never be implemented. Mostly used as personal post-it notes.
TODO: type system is not super nice to use
TODO: support parametric types in contraints: list(number)
should then also allow polymorphic constraint like
$ fn(l::list('a), x::'a)
(push a constraint context when checking compatibility)
or more generic constraints? allow custom functions to check constraints, etc (performance?)
TODO: distinguish between list and argument list to confuse less pairs with named arguments
TODO: a way to alias key names in pairs/maps? the alias should not end up in the save file... we could use variable for that, like
TODO: some sensible way to capture text event in string litterals (string interpolation)? -> meh, this means we can capture choice events, and choice events contain their code block, and we don't want to store code blocks in the save file (as code can be updated/translated/whatever)
:foo:bar = "key"
:map = {bar=42}
i.e. just remove the special case of interpreting identifiers as strings in pairs. But then might need to distinguish from the named argument syntax in function calls.
TODO: type system is not super nice to use.
UPDATE: tried to implement a static type system, ain't worth it. Would require major refactoring to go full static with good type inference. The language is supposed to allow to not have to worry about low level stuff, so no deal if the type inference isn't good. Thank you multiple dispatch for making everything complicated (i still love you though)... Well, if I ever reimplement Anselme, let's thank the Julia devs for doing the hard work: https://docs.julialang.org/en/v1/devdocs/inference/
TODO: some sensible way to capture text event in string litterals (string interpolation/subtexts)? -> meh, this means we can capture choice events, and choice events contain their code block, and we don't want to store code blocks in the save file (as code can be updated/translated/whatever)
ignoring choice events, we might be able to use subtexts in string litterals; using the same code for text lines and text litterals? we would lose tags...
TODO: the function decorator feels a bit glued-on to the current syntax
@ -65,7 +78,7 @@ TODO: fn/checkpoint/tag: maybe consider them a regular func call that takes chil
:a = $(args)
stuff
how are children passed on? overloading?
how are children passed on? overloading? -> means a code block would be passed as a value, how to avoid it ending up in the save file?
if not possible, at least make checkpoint or fn defined using the other or some superset... -> checkpoints defined using fn
@ -83,18 +96,18 @@ TODO: fn/checkpoint/tag: maybe consider them a regular func call that takes chil
TODO: perform seen/reached/etc default variable not in interpreter but using parse-time macro
TODO: no function call without () (reference to fn instead?). Fn could be stored in save but replaced with new versions on code reload... -> how to track these references?
if we make fn first class this means anonymous fn, is it ok?
if we make fn first class this means anonymous fn, is it ok? -> no way to track anonymous fn, so no.
TODO: make language simple enough to be able to reimplement it in, say, nim. Especially the AST interpreter (we could precompile a lot of stuff...)
TODO: test reacheability of script paths
TODO: test reacheability of script paths + visualization of different branches the script can take. For one of those overarching story visualization thingy.
TODO: redisign the checkpoint system to work better when used with parallel scripts (if both change the same variable, will be overwritten); not sure how to do that, would need some complicated conflict resolution code or something like CRDT...
TODO: redisign a static type checking system
If we want to go full gradual typing, it would help to:
* add type anotation+type check to variables (:a::number=5) and functions return ($ f()::number)
* enforce some restrictions on type (assume they're constant?)
* add type anotation+type check to functions return ($ f()::number) -> there's a lot of function calls, so probably checked at compiling only
* enforce some restrictions on type (assume they're constant/sublanguage, not full expressions)
* make some tuple/list distinction (homogenous/heterogenous types) as right now index operations are a type roulette. Or type annotate lists using some parametric type.
Advantages:
* can be used for better static variant selection; if everything is type annotated, selection could be restricted to a single function

View file

@ -62,13 +62,22 @@ common = {
["\\t"] = "\t",
-- string interpolation
["\\{"] = "{",
["\\}"] = "}",
-- subtext
["\\["] = "[",
["\\]"] = "]",
-- end of text line expressions
["\\~"] = "~",
["\\#"] = "#",
-- decorators
["\\$"] = "$"
["\\$"] = "$",
-- line types
["\\("] = "(",
["\\>"] = ">",
["\\%"] = "%",
["\\§"] = "§",
["\\@"] = "@",
["\\:"] = ":",
},
-- list of possible injections and their associated name in vm.state.inject
injections = {

View file

@ -268,6 +268,6 @@ else
if args["write-all"] then
print("Wrote test results.")
else
print(("%s/%s tests success."):format(success, total))
print(("%s/%s tests passed."):format(success, total))
end
end