Current Release
  • Version: 0.1.2

Sourceforge










SourceForge.net Logo
Last Modified:
June 05, 2008

TScript



Welcome to the TScript's homepage.

TScript is a script language originated by pure personal interest. It currently includes a compiler, a virtual machine, two demos, together with some tiny games written by friends in TScript.
The code was written mainly in 2004 and 2005, and it's covered fully by dust. Considering the time spent on this, finally I get some time to publish it. Wish the messy code can be useful to someone.

If you have any questions, comments, or complaints feel free to email me or post in the SourceForge Forums.

Table of Content


Origin & Introduction
Start From the Demos
Grammar
How to Build
TScript Workflow
Potential Use and How to Extend TScript
Advanced Topic: Weakness of TScript
License


Origin & Introduction

  • TScript is a script language with C-like grammar, but much weaker. The source script of TScript runs on TScript Virtual Machine.
    This project was originated purely by my interest after my graduation on 2004. What I needed that time was something like:
    "Hi, my cute computer, I have a symbol 'A' = 5, tell me A + 3 = ?"
    var a
    mov a, 5
    add a, 3, a
    display a

    From then on I could not stop but continuously added something to it. Finally it came to a script which has similar grammar to C:
    void func1() {
    int a = 5;
    DisplayString("" + (a + 3) );
    }
    Here's another sample which prints Fibonacci series by recursive function call:
    int f(int n) {
        if(n < 2)
            return 1;
        return f(n - 1) + f(n - 2);
    }

    void main() {
        for(int i = 0; i < 10; i++)
            DisplayString( "" + f(i) );
    }

Start From the Demos

    Currently there're two demos.

  • Demo with console functions
    • The first one is a TScript Runner (the VM) implementation with console functions. The implemented functions are only two functions - something like "getchar" and "printf". Together with this implementation there're several tiny games written in TScript by friends. The games include a Hannoi auto resolver, A* path finding, an RPG game: Gladiator, and a few other ones. Because of the function limitation (only read char and print out a string with line bread), do not expect much of them :)...
      Originally the purpose of writing games in such Stone Age development environment is to make more random test cases...finally more games added. Note that several of the games contain Chinese characters. If you're interested, please refer to readme.txt in the package on how to adjust your console to display these characters.

      The demo locates in directory "env". To run the demo, issue:
      "run_demo.bat" (for Windows)
      or
      "./run.sh demo" (for Linux)

      To run your own script, just type
      run <your script name> (for Windows)
      ./run.sh <your script name> (for Linux)




    • The demo also contains some simple algorithm implementation, but TScript is not suitable for complex algorithm. Just a demo here.


  • Suspendable script demo
    • This demo is for the suspendable feature. It's something like the Coroutine in LUA and Squirrel. From script developer's perspective it looks like a manual-switched threading. LUA creates coroutine within the language, but TScript hides this concept behind the script, and the parallel execution of script is handled by the specific script loader. This is similar to the scripting engine of a famous game: Neverwinter Nights (NWN).
      This project also demonstrates the pattern of expending TScript VM by expanding TsTarget classes.
      The project was built only for Window. It locates in directory "ssdemo".
      Please refer to the readme.txt in the project for details.
    • In this demo, there're several "sprites". The behavior of each sprite is controlled by a script (though several sprites are configured with the same script). The scripts are written from the perspective of "controllee": the sprites are all doing something endlessly, so naturally the script is an endless loop. This is a natural way to define the behavior of the object. Several scripts are executed parallelly, without considering others. This is supported by script execution:
      suspend execution -> execute another script -> resume a suspended execution. This feature helps developers to focus on the logic of the target: as one writes the script (AI) for an object, he views the world from the same perspective as the object itself. It's not needed to concern the execution of scripts of other objects much.



Grammar

  • It's C-like, mixed with a few C++ grammar types. Here's a list of general language feature supported:
    Flow control
    Complex expression calculation
    User defined function
        Function default parameter
        Recursive function call
    String operation
    Include file
    Macro definition
    Suspending support
    Global variable
    Global initialization (complex expression)
    ...
    Please refer to doc TScript Language Description in old doc archive in the release package for details. There're also many things that is different to C. For example, "i++" and "++i" in TScript is treated the same as "++i" in C. "i++" should be implemented as "move value i to register and increase i, use register value as expression value", while "++i" means "increase i and move its value to register, use register value as expression value". I lacked of that knowledge when I wrote the compiler.

How to Build

  • Please refer to src/readme.txt in the release package. Generally, for Windows, you need MS Visual Studio 98. I've not tested on later version.
    For Linux, only a simple build script is created without autoconf. Luckily it works on SLES10, RHEL4, and also Cygwin, with gcc. In addition, different platforms have different STLs, and STL also differs from each other. For example, STLPort do not support internal sharing feature of string (copy on write), which makes the low efficiency script much worse.

TScript Workflow

  • Firstly a script file (*.tss) need to be compiled. The compiler (TSC) is responsible to compile the source file into TScript binary image (*.tsb), with intermedium called TScript Assemble File (*.tsa). Finally a concrete TScript runner (the VM) loads the binary (tsb) and executes it.


  • The binary (TSB) is then executed on the Virtual Machine, supported by native system. Native system is a concept which represents any specific functionality you already have/want to access. For example, it’s OS which provides standard IO if you want to use standard IO, or is existing product which TSVM is embedded in.


Potential Use and How to Extend TScript

  • If you have a system and want it to be configurable at a script level, TScript may help you. For example, to configure behavior of acting objects (simple AI).
    It's simple to extend TScript. The basic steps to deploy it with your own system are:
    • 1. Decide what methods you want to expose from your system. That is, the API provided by your system. These APIs will be mapped to new functions in TScript.
    • 2. Create your new Virtual Machine class: derive from TsRunner class in module "tsrbase", implement your new APIs. In this step, it should be decided that how the new VM object is embedded into the target system.
    • 3. Modify "tsfdusr.tsd" and "TSFDUsr.tsh" in env/data directory, which is for the compiler (TSC) to correctly compile TScript source which contains the new APIs.
    That's all.

    There're also some old comments on how to extend the VM in "doc" directory, but I believe they're out of date. There're many changes after that.

    If there're multiple targets in the system to be handled by scripts, it's recommended to use the TsLoader together with TsLinker and TsTarget. TsLoader is a script manager, and TsLinker links event to target and script. One of the two demos - ssdemo - demonstrates this pattern.

    Please follow project "tsr" (TScript VM implementation with simple console) or "ssdemo" (Suspendable script demo) source code as examples.
    The first one has "getchar" & "displaystring" functions extended. The second one adds some demo specific functions, and has several objects managed by separated AI scripts.

  • TScript VM has explicit logic (the static script)/context (the volatile runtime memory)/VM (the runner)/target (the command receiver) separation in code. So it's easy to suspend/store/restore/resume the execution at any time and refactor the source for further use. For more info please refer to Suspendable Script doc and ppt in the doc directory.
  • TScript virtual machine base (TsRunner) is written in C++. So if the target system is implemented in other languages, some tricky bridge is required.

Advanced Topic: Weakness of TScript

  • Memory model. Here I'll introduce something that is really tricky, and describe the weakness of this script language compiler and VM.
    The VM has only one memory accessing method: by value. Normally a machine should have two methods: by value and by value of value, or named "direct addressing" and "indirect addressing". By value means something like "go and fetch things at address 12345", and by value of value means "go and fetch things at address A. What's A? It's the item stored in address 12345". This is the intrinsic limitation of TScript. The reason? My laziness...Originally I didn't expect to do so much for this plaything. This limitation is the greatest one, which limits the following things: pointer, reference, natural function stack, dynamic object array allocation, and so on... One may ask: "Then how can recursive function call be implemented in the demos? How can those other demos implemented, which absolutely requires dynamic array support?" Oh...That's all implemented trickily. Function recursive call can be automatically implemented in C because each time a function is called, a block of memory on stack is occupied for local variables of the function (stack grows). This is very natural. TScript lacks of this, and doesn't need recursive function at the beginning, until one of my friend yields "I MUST have this to implement my code!" So it's implemented, ugly by VM native stack (push value, pop value). In fact, as long as we have something with stack feature, it can be used to fulfill such requirement, and then, the efficiency is a stranger here.
    For dynamic array allocation limitation, string is a native type in TScript. It's mapped to std::string, which is dynamically allocatable, so...another tricky implementations.
  • Performance. Performance is not a concern at the very beginning for such a scripting language. It's a drawback of all scripting language as well. The mechanism here looks like that of java at the beginning: compile source to bytecode, and parse the bytecode during execution. Then java has the JIT compiler, which greatly improves the performance. In addition, TScript has no referencing mechanism according to the aforementioned memory details. So TScript is poor in performance. Certainly, that's concluded by a comparison with some great languages.
  • The language. From a high level perspective, TScript has no explicit "purpose", it's something emerged from interest, more like a practice, though it can be of some use now. Without a major purpose, it's developed with copying of features here and there. We like things to be elegant, but TScript gets no chance to be embellished by the word from the beginning.

License

  • The software is open source software and is licensed under MIT. So it's extremely free. I'm happy that the experimental and messy code can be of help to someone. If you're interested in it, it's nice of you to mail me what it can help you. I'm really interested in that.
  • Note that part of the source code (lex & yacc of the source (tss) to assemble (tsa) compiler) is generated by Parser Generator (ParGen) 0.60 by P. D. Stearns in 1998. I believe that there's updated version of that now. Thank Stearns for the powerful tool.