TeaScript 0.11.0 was published on the 11th December in 2023 and can be downloaded for free:
☛☛☛ Download is available here. ☚☚☚
(or browse the source code of the TeaScript C++ Library on Github)
TeaScript 0.11.0 is also an anniversary release, since the first public release was made one year ago. Happy Birthday TeaScript! 🎂
What is new?
The biggest new features in version 0.11.0 are the integrated TOML Support and the various (Named) Tuple extensions, especially the Subscript Operator []
.
The main features are:
- integrated TOML support (optional for the C++ Library)
- Subscript Operator
[]
(TeaScript and C++) - String Literals (UTF-8) for Named Tuple access
- Raw String literals
- minimum_version required check
- CoreLibrary configuration now also available in the Host Application and REPL
Are you new to TeaScript? Then you may read here first: Overview and Highlights of TeaScript.
Before diving into the integrated TOML Support feature below, introducing the features which are useful for it.
Subscript Operator
(TeaScript language and C++ Library feature)
The from many other languages well known Subscript Operator []
(square brackets) is now also available in TeaScript. You can use it for index based as well as for key based access of (Named) Tuples.
For a recap: The article of the last release has a very nice introduction of the (Named) Tuple feature.
Here are some examples how to use it, starting with a “normal” Tuple.
// create a Tuple
def tup := (1,2,3)
// now use the new subscript operator
println( tup[0] ) // 1
println( tup[1] ) // 2
println( tup[2] ) // 3
// better use a loop...
const size := _tuple_size( tup )
def idx := 0
repeat {
if( idx == size ) { stop }
println( tup[idx] )
idx := idx + 1
}
// can modify as well
tup[1] := 10
println( tup[1] ) // now prints 10
Now an example for Named Tuple.
// create a Named Tuple (with the Uniform Definition Syntax)
def tup := _tuple_create() // start with an empty tuple
def tup.abc := "Something"
def tup.flag := true
def tup.num := 123
// now use the new subscript operator (key based access)
println( tup["abc"] ) // "Something"
println( tup["flag"] ) // true
println( tup["num"] ) // 123
// index based access also works
println( tup[0] ) // "Something"
println( tup[1] ) // true
println( tup[2] ) // 123
// can modify as well (NOTE: You cannot create a new element with this!)
tup["num"] := 456
println( tup["num"] ) // prints 456 now
// nested elements are also accessible
def tup.inner := (1,2,3) // create an inner tuple
// access it
println( tup["inner"][1] ) // 2
println( tup[3][2] ) // 3
// of course you can mix the accessing methods like you want ...
println( tup.inner[1] ) // 2
println( tup[3].2 ) // 3
On C++ level the teascript::Tuple
as well as the teascript::ValueObject
have subsrcipt operators as well. You can see an example in the TOML Support section below.
String Literals for Named Tuple access
(TeaScript language feature)
In TOML you can use the full (printable) Unicode range for naming the key of an element by using an UTF-8 encoded String Literal. The same you can do now in TeaScript with a Named Tuple. (Authors note: The syntaxhighlighter is not able to display new Unicode signs, so the examples are a little limited here… )
def tup := _tuple_create() // empty tuple
// first add a key the old way...
// add a value where key has whitespace and non ASCII chars.
_tuple_named_append( tup, "₿ ぜ 马 克", 1337 )
// now access it the new way with a string literal
println( tup."₿ ぜ 马 克" ) // 1337
// can be modified as well
tup."₿ ぜ 马 克" := 987 // is 987 now
// add a new key with the Uniform Definition Syntax the new way
def tup."สวัสดี ครับ" := "Hello"
println( tup."สวัสดี ครับ" ) // "Hello"
// remove one
undef tup."₿ ぜ 马 克" // "₿ ぜ 马 克" no longer exists
// can be nested of course
def tup."ถัง" := _tuple_create()
def tup."ถัง"."ตัวเลข" := 123
println( tup."ถัง"."ตัวเลข" ) // 123
println( tup."ถัง".0 ) // 123
Raw String Literals
(TeaScript language feature)
TeaScript supports now raw string literals where no escaping is done and all characters (including line feeds) are taken as is and count to the resulting string. Also, they don’t support in-string evaluation.
You starting a raw string by 3 (or more) double quotes, like this """
. The string ends when the amount of the starting double quotes occurs again, e.g. if you started with 3, the string must end with 3, but if you started with 4 it will not end with 3 but only with 4 double quotes.
Also, if the very first character after the starting quotes is a newline character (LF, '\n'
, 0x0a), then this newline will not be included to the string.
// start a raw string with an immediate new line (which will not count to the string)
const rawstr := """
01 first line, this " or this "" don't end the string...
02 second line \t (the "\t" will not be replaced)
03 // this comment belongs to the string
/* as well
this one */
# this line as well
""" // <-- here is the string end!
// one raw string in one line containing 3 double quotes as content
println( """"3"""quotes"""" ) // prints "3"""quotes"
TOML Support
(TeaScript language and C++ Library feature)
The Windows and Linux TeaScript Host Application distribution packages contain an already compiled executable with integrated TOML Support. You can just use and try it.
If you use the source code of the Host Application or the TeaScript C++ Library the feature is optional.
For enabling it, you must take these few and easy steps:
- Download the source of the toml++ library here: Github tomlplusplus
(tested with version 3.4.0) - Set the include path for your project(s) / during compilation.
- Compile. Thats all!
(You can check if the include is found in “teascript/TomlSupport.hpp”)
The integrated TOML Support feature adds 2 new Core Library functions for the core config level “LevelUtil” or above:readtomlstring
and readtomlfile
.
Both functions taking a String as the only argument and returning a Named Tuple with the loaded TOML structure or a Bool(false) on error.
The first function interprets the string parameter as the TOML formatted content and builds a Named Tuple structure from it.
The second function reads the TOML formatted content from a file given as the string parameter instead.
// NOTE: Unfortunately the syntaxhiglighter don't support the raw string literal syntax...
// read a TOML formatted string
// -----------------------------------------
def toml := readtomlstring( """
[name]
first = "Tom"
last = "Preston-Werner"
[point]
x = 1
y = 2
[animal]
type.name = "pug"
""" )
// -----------------------------------------
// use the result...
println( toml.name.first ) // "Tom"
println( toml.point.y ) // 2
// second example with some arrays
// -----------------------------------------
def root := readtomlstring( """
integers = [ 1, 2, 3 ]
colors = [ "red", "yellow", "green" ]
nested = [ [ 1, 2 ], [3, 4, 5] ]
mixed = [ [ 1, 2 ], ["a", "b", "c"] ]
"""
// -----------------------------------------
// use the result
println( root.integers[0] ) // 1
println( root.integers[1] ) // 2
println( root.integers[2] ) // 3
println( root.colors[1] ) // "yellow"
println( root.nested[1][2] ) // 5
println( root[3].1[0] ) // "a"
On C++ level you have 2 choices how to use it. If you like the Named Tuple access in TeaScript, you could execute one line of TeaScript for each ‘path’ of the TOML element of interest (see below).
Or, you can now also use the subscript operator for the Tuple class and even for the ValueObject, if the inner type is a Tuple.
// NOTE: Unfortunately the syntaxhiglighter don't support the raw string literal syntax...
// default engine
teascript::Engine engine;
// read some TOML
// -----------------------------------------
engine.ExecuteCode( R"_SCRIPT_(
const stock := readtomlstring( """
[[products]]
name = "Hammer"
sku = 738594937
[[products]]
name = "Nail"
sku = 284758393
color = "gray"
""" )
)_SCRIPT_" );
// -----------------------------------------
// access TOML element by its 'path' with the help of TeaScript
std::cout << "name of 2nd product: "
<< engine.ExecuteCode( "stock.products[1].name" ).GetValue<std::string>()
<< std::endl; // "Nail"
// or use Tuple / ValueObject
// we only want the 'toml array' products.
auto const products = engine.ExecuteCode( "stock.products" );
std::cout << "name of first entry: "
<< products[0]["name"].GetValue<std::string>()
<< std::endl; // Hammer
More examples can be found in the teascript_demo.cpp or by executing the toml_test01.tea file which is included as an example in the packages.
Minimum version required check
(TeaScript language feature)
A new Parser option (when a line starts with 2 hashes ##
) was added to check for a minimum version. If the version is older than the minimum version the Parser will stop with a specific parsing error and the script will not be evaluated.
This is useful because all Parser options will be evaluated immediately when they get parsed. That means that all lines below this option are not parsed yet. With that you can protect against old versions if your script relies on some new syntax which older Parsers don’t understand.
The form is like this:##minimum_version major[.minor[.patch]]
// this script will not run on the current 0.11.0 release
// but only on the next minor release or newer.
##minimum_version 0.12
... here could be arbitrary content when executed with 0.11 ...
123 "test" สวัสดี ครับ
NOTE: Because of this features was just added with 0.11.0 it will be effectively useful only starting with the next future release. Older versions will just ignore this line.
TIPP: If you want to protect against all versions older than 0.11.0 you can use a raw string literal which will produce a parsing error at its occurrence.
// older versions (0.10.0 and below) will produce a parse error when raw string literals are used...
// cover this case here first and try to produce a readable error.
if( _version_major < 1 and _version_minor < 11 ) {
// return from 'main' exists since 0.8.0 which was the first public release...
return """Version is too old. Need 0.11.0 as minimum."""
}
CoreLibrary Configuration
(TeaScript Host Application feature)
Like with the TeaScript C++ Library you can now set a fine grained CoreLibrary config in the TeaScript Host Application and decide which level and which feature shall be loaded or not.
You can do this either when invoking it for run a script file or inside the REPL.
For executing TeaScript files use --config=0x<hex>
and from inside the REPL the command :reset=0x<hex>
, where hex must be the hexadecimal representation of the desired config. :reset
without a value and without =
will always use “LevelFull” with all features enabled.
Possible config values can be found in CoreLibrary.hpp.
Misc
Added experimental is
query for const
like this:
def a := 1
const b := 2
// Please note the capital C
a is Const // false
b is Const // true
3 is Const // true (it is a constant value)
The Host Application on Linux uses the GNU Readline Library for a better REPL experience. Now a history as well as nice editing features are available when typing the next code line.
Fixed that the name of Named Tuple elements were not displayed correctly when using the debug
operator.
Some smaller fixes and improvements.
More Infos
More information about the TeaScript language is available here:
✯ Overview and Highlights
✯ TeaScript language documentation
✯ Core Library documentation
☛☛☛ Try and download TeaScript here. ☚☚☚
Final notes and Outlook
Personally I think that the 0.11.0 release is a smaller one but a very fine release for the anniversary of TeaScript and for the end of the year. The extensions for the (Named) Tuple and the straight forward integration for TOML support are showing the great and flexible usability of the (Named) Tuples and TeaScript in general and completing nicely the Tuple 1.0 feature set (2.0 is planned already 😉 ).
After a half year of struggling with other things where I was not clear anymore about the future and the direction of the TeaScript development, I know think I found a new personal goal and concept again.
Since it is (unfortunately) not possible to work full-time on TeaScript, I am planning to doing some few smaller releases during the year with the goal to demonstrate my planned feature set step by step.
Actually, there are way too many features on the list for the next release. There is no chance to implement them all but I did not decided yet which I will choose to implement. The next release schedule adjustment and planning still has to be done. Probably I will provide a new blog entry after I made a final planning for 0.12.
Do you have some feature wishes for TeaScript?
Do you like or dislike this current release? Don’t hesitiate to let me know your opinion. I would be happy about any feedback.