Simplicity is prerequisite for reliability.

Edsger Dijkstra



Home


Introduction
Performance
Syntax
Types
  Numbers
  Pointers
  Strings
Operators
  Numeric operators
  String operators
Instructions
  Keywords
  Comments
Functions
  User declared functions
  Delphi imported functions
  Functions signatures
  Functions overloading
  The & operator and indirect function calls
Identifiers
Dictionaries
Commands
  Assignment
    LET
      Assignment variants
  Input / Output instructions
    PRINT
    CLS
    INPUT
  Loop instuctions
    FOR .. NEXT
    REPEAT .. UNTIL
    WHILE .. END WHILE
    BREAK and CONTINUE
  Conditional instructions
    IF .. THEN .. ELSE
    SELECT .. CASE
  Handling data in code
    DATA READ RESTORE
    DATA
    READ
    RESTORE
Embedding Meeseeks in Delphi Apps
Important notice
Interpreter sources
Interpreter classes
Usage with Delphi
  Compiling and running a script
  Compiling and running script functions
  Extending the interpreter
Working with the intermediate code
  Load and execute intermediate code
Meeseeks engine main classes headers
  TMeeseeksEngine
  TBasicLexer
  TBasicParser
  TAsmLexer
  TCompiler
  TExec
The Meeseeks libraries
  Math library
    ABS(n)
    ACOS(n)
    ACOSH(n)
    ASIN(n)
    ASINH(n)
    ATAN(n)
    ATAN2(n,m)
    ATANH(n)
    CINT(n)
    CMPVAL(n,n[,n])
    COS(n)
    COSH(n)
    DEGTORAD(n)
    EXP(n)
    FIX(n)
    FRAC(n)
    INT(n)
    LN(n)
    LOG2(n)
    LOG10(n)
    RADTODEG(n)
    RND()
    RND(n)
    ROUND(n)
    SIN(n)
    SINH(n)
    SQR(n)
    SGN(n)
    TAN(n)
    TANH(n)
  String library
    ASC($)
    LCASE$($)
    UCASE$($)
    LTRIM$($)
    RTRIM$($)
    LEN($)
    CHR$(n)
    STR$(n)
    BIN$(n)
    HEX$(n)
    OCT$(n)
    MID$($,n[,n])
    LTAB$($,n)
    RTAB$($,n)
    LFILL$($,n,n)
    RFILL$($,n,n)
    LEFT$($,n)
    RIGHT$($,n)
    VAL($)
    CONTAINSSTR($,$)
    CONTAINSTEXT($,$)
    MULSTRING($,n)
    ENDSTR($,$)
    ENDTEXT($,$)
    REPLACESTR$($,$,$)
    REPLACETEXT$($,$,$)
    REVERSE$($)
    STARTSSTR($,$)
    STARTSTEXT($,$)
    STUFFSTRING$($,n,n,$)
  String functions multirows
    COUNT($)
    OPENTEXT$($,$)
    SAVETEXT$($,$,$)
    COPYTEXT$($)
    PASTETEXT$()
  Standard library
    NUMBER(#)
    POINTER(n)
    PAUSE(n)
    DATE$()
    TIME$()
    DATETIME$()
    TIMETOSTR$()
    STRTOTIME($)
    DATETIMETOSTR$(n)
    STRTODATETIME($)
    DATETOSTR$(n)
    STRTODATE($)
    DAYOFWEEK(n)
    DAYOFTHEWEEK(n)
    DAYOF(n)
    DAYOFTHEMONTH(n)
    DAYOFTHEYEAR(n)
    DAYSBETWEEN(n,n)
    DAYSINAMONTH(n,n)
    DAYSINAYEAR(n)
    DAYSINMONTH(n)
    DAYSINYEAR(n)
    DAYSPAN(n,n)
    HOUROF(n)
    HOURSBETWEEN(n,n)
    HOURSPAN(n,n)
    MILLISECONDOF(n)
    MILLISECONDSBETWEEN(n,n)
    MILLISECONDSPAN(n,n)
    MINUTEOF(n)
    MINUTESBETWEEN(n,n)
    MINUTESPAN(n,n)
    MONTHOF(n)
    MONTHOFTHEYEAR(n)
    MONTHSBETWEEN(n,n)
    MONTHSPAN(n,n)
    INCDAY(n,n)
    INCHOUR(n,n)
    INCMILLISECOND(n,n)
    INCMINUTE(n,n)
    INCSECOND(n,n)
    INCWEEK(n,n)
    INCYEAR(n,n)
    ISAM(n)
    ISINLEAPYEAR(n)
    ISPM(n)
    ISSAMEDAY(n,n)
    ISTODAY(n)
    WEEKOF(n)
    WEEKOFTHEMONTH(n)
    WEEKOFTHEYEAR(n)
    WEEKSBETWEEN(n,n)
    WEEKSINAYEAR(n)
    WEEKSINYEAR(n)
    WEEKSPAN(n,n)
    YEAROF(n)
    YEARSBETWEEN(n,n)
    YEARSPAN(n,n)
    YESTERDAY()
    FORMATSETTINGS($,$)
    PROCESSMESSAGES()
    HANDLEMESSAGE()
    ISNAN(n)
    ISNULL($)
    ISNIL(#)
  System library
    CHDIR($)
    KILL($)
    FILEEXISTS($,n)
    CHANGEFILEEXT$($,$)
    EXTRACTFILEEXT$($)
    EXTRACTFILENAME$($)
    EXTRACTFILEPATH$($)
    MKDIR($)
    FORCEDIRECTORIES($)
    RMDIR($)
    ENVIRON$($)
    RANDONFILENAME$()
    GUIDFILENAME$(n)
    TEMPFILENAME$()
    TEMPPATH$()
    HOMEPATH$()
    DOCUMENTSPATH$()
    SHAREDDOCUMENTSPATH$()
    LIBRARYPATH$()
    CACHEPATH$()
    PUBLICPATH$()
    PICTURESPATH$()
    SHAREDPICTURESPATH$()
    CAMERAPATH$()
    SHAREDCAMERAPATH$()
    MUSICPATH$()
    SHAREDMUSICPATH$()
    MOVIESPATH$()
    SHAREDMOVIESPATH$()
    ALARMSPATH$()
    SHAREDALARMSPATH$()
    DOWNLOADSPATH$()
    SHAREDDOWNLOADSPATH$()
    RINGTONESPATH$()
    SHAREDRINGTONESPATH$()
    DIRSEPARATOR$()
    PATHSEPARATOR$()
  Memory stream library
    NEW#()
    FREE(#)
    CLEAR(#)
    POSITION(#[,n])
    SIZE(#[,n])
    LOADFROMFILE(#,$)
    SEEK(#,n,$)
    SAVETOFILE(#,$)
    WRITE(#,$)
    WRITE(#,n)
    WRITE(#,#)
    READ$(#,n)
    READ$(#,n,$)
    READ(#)
    READ#(#)
  String stream library
    NEW#($)
    FREE(#)
    CLEAR(#)
    COPYFROM(#,#,n)
    DATASTRING$(#)
    POSITION(#[,n])
    SIZE(#[,n])
    LOADFROMFILE(#,$)
    SEEK(#,n,$)
    SAVETOFILE(#,$)
    SAVETOSTREAM(#,#)
    WRITESTRING(#,$)
    READSTRING$(#,n)
    WRITE(#,$)
    WRITE(#,n)
    WRITE(#,#)
    READ$(#,n)
    READ$(#,n,$)
    READ(#)
    READ#(#)
  File stream library
    NEW#($,$)
    FREE(#)
    FILENAME$(#)
    POSITION(#[,n])
    COPYFROM(#,#,n)
    SIZE(#)
    SEEK(#,n,$)
    WRITE(#,$)
    WRITE(#,n)
    WRITE(#,#)
    READ$(#,n)
    READ$(#,n,$)
    READ(#)
    READ#(#)
  Strings library
    NEW#()
    FREE(#)
    CAPACITY(#[,n])
    CASESENSITIVE(#[,n])
    COMMATEXT(#,$)
    COMMATEXT$(#)
    COUNT(#)
    DEFAULTENCODING(#,$)
    DEFAULTENCODING$(#)
    DELIMITEDTEXT(#,$)
    DELIMITEDTEXT$(#)
    DELIMITER(#,$)
    DELIMITER$(#)
    DUPLICATES(#,$)
    DUPLICATES$(#)
    ENCODING$(#)
    LINEBREAK(#,$)
    LINEBREAK$(#)
    NAMES$(#,N)
    NAMEVALUESEPARATOR(#,$)
    NAMEVALUESEPARATOR$(#)
    QUOTECHAR(#,$)
    QUOTECHAR$(#)
    SORTED(#[,n])
    STRICTDELIMITER(#[,n])
    STRINGS(#,n,$)
    STRINGS$(#,n)
    TEXT(#,$)
    TEXT$(#)
    VALUEFROMINDEX(#,n,$)
    VALUEFROMINDEX$(#,n)
    VALUES(#,$,$)
    VALUES$(#,$)
    WRITEBOM(#[,n])
    ADD(#,$)
    APPEND(#,$)
    BEGINUPDATE(#)
    CLEAR(#)
    DELETE(#, n)
    ENDUPDATE(#)
    EQUALS(#,#)
    EXCHANGE(#,n,n)
    FIND(#,$)
    INDEXOF(#,$)
    INDEXOFNAME(#,$)
    INSERT(#,n,$)
    LOADFROMFILE(#,$,$)
    LOADFROMSTREAM(#,#,$)
    MOVE(#,n,n)
    SAVETOFILE(#,$,$)
    SAVETOSTREAM(#,#,$)
    SORT(#)
  Dictionary library
    NEW#(n)
    FREE(#)
    ADD(#,n,n)
    ADD(#,n,#)
    ADD(#,n,$)
    ADD(#,$,n)
    ADD(#,$,#)
    ADD(#,$,$)
    ADDORSET(#,n,n)
    ADDORSET(#,n,#)
    ADDORSET(#,n,$)
    ADDORSET(#,$,n)
    ADDORSET(#,$,#)
    ADDORSET(#,$,$)
    HASKEY(#,n)
    HASKEY(#,$)
    HASVALUE(#,n)
    HASVALUE(#,$)
    HASVALUE(#,#)
    REMOVE(#,n)
    REMOVE(#,$)
    GET(#,n)
    GET(#,$)
    GET$(#,n)
    GET$(#,$)
    GET#(#,n)
    GET#(#,$)
    CLEAR(#)
    COUNT(#)
    TRIMEXCESS(#)
  Functions arguments support
    RESET(#)
    PUSH(#,n)
    PUSH(#,#)
    PUSH(#,$)
    POP(#)
    POP#(#)
    POP$(#)
  Self contained Meeseeks engine
    NEW#()
    FREE(#)
    COMPILE(#,$)
    RUN(#,#)
    ERROR.POS(#)
    ERROR.LINE(#)
    ERROR.MSG$(#)
    ASM$(#)
    ASM(#,$)
    CALL(#,#,$)
    CALL#(#,#,$)
    CALL$(#,#,$)
    CALL.RESULT(#)
    CALL.RESULT#(#)
    CALL.RESULT$(#)
    GET(#,$)
    GET#(#,$)
    GET$(#,$)
    RTEXCEPT(#)
    RTEXCEPT.MSG$(#)
  Self contained Meeseeks engine register libraries
    ME(#)
    MATH(#)
    STR(#)
    STD(#)
    SYS(#)
    MS(#)
    SS(#)
    FS(#)
    STRS(#)
    DICT(#)

Introduction

The Meeseeks Box     

Meeseeks is an imperative scripting language, designed to be embedded in Delphi applications for Microsoft Windows and Android.

The name Meeseeks is a tribute to the character of the Rick and Morty cartoon, if you are still needing a short explanation, take a look in here. Similarly to the cartoon character, a Meeseeks script is supposed to have a short existence. It should be called from the host application to help in a specific computation, performing simple calculations or tasks, presenting its results and then stopping its existence.

All the source code for this project can be found here.

Performance

Scripts are compiled to a postfix notation before being executed by a stack machine. This process makes the script execution faster.

Syntax

The language syntax is very clear and easy to learn, the script source code can be structured in functions and it's basically a list of instructions executed in sequence. It resembles structured BASIC but it's not compatible with it. The language syntax is not case sensitive; commands, functions names and variables can be written in upper or lower case, just like in Pascal and Basic. The example application shows the integration between the script engine and RAD Studio applications for MS-Windows or Android, also, it shows how Delphi functions and objects can be accessed by the user scripts.

  --As taught by Kernighan and Ritchie.
  Print 'Hello world.'

The interpreter has no default functions, before a function can be called it must be declared in the script or imported from Delphi. Functionalities could or couldn't be added according to what is needed in the host application, making it more secure and reducing its final size.

The interpreter engine could be used, for example, as a calculator. There is a default math library as part of the project which includes a lot of the Delphi original math functions.

  function triangle_area(base, height)
    if base <= 0 or height <= 0 then return -1
    return (base * height) / 2
  end function

  --Output will be 72
  print 'Triangle area: '; triangle_area(12,12)

Note: Comments start with '--' or by using the keyword REM and continue until the end of the line.

Types

There are three types available: numbers, pointers and strings.

Global variables do not need to be declared, they are automatically created by the interpreter after the first assignment, the exceptions are local variables in functions, these must be defined in the function declaration.

The interpreter recognizes a variable as a string if its name ends with a dollar ($) and a pointer if its name ends with a (#) character.

Numbers

A numeric variables are internally represented by a floating point value with double precision (Delphi double type, 64 bit, 15 significant digits).

Double precision can also represent 32 bit integers when necessary.

Numeric variables are used with operators to perform math expressions and are used as counters in loop instructions.

Example:

  a := 10
  b := a + 7.5 --b = 17.5

Pointers

A pointer variable is usually passed to the interpreter to interact with Delphi objects. For example:

  -- Create a new memory stream control.
  -- Store its pointer in the mems# variable
  mems# := ms.new#()

Strings

A string variable contains text. This text may be a single row or multiline. The length of a string variable is defined by the length of the text present on it.

The interpreter string type is nothing more than a wrapper to the Delphi standard string type.

Use single quotes to define string constants.

Example:

  a$ := 'Hello' + 'World' + '!'

The value of the variable a$ is now 'HelloWorld!'

String variables can be used with operators to create string expressions.

A single row of a multi-line string can be read/written using square brackets, example:

if a$ contains:

  'This is a
  text placed on
  three rows'

The code below shows how to access text lines individually:

  b$ := a$[1] -- Now b$ contains: 'text placed on'
  b$ := a$ -- b$ keeps the full original text
  b$[1] := 'text replaced on'

  -- Now b$ contains:
  'This is a
  text replaced on
  three rows'

Note: The bracket lines index is zero based, the first line has the index 0, the second line has the index 1, and so on.

A single char in a string can be accessed using double brackets, example:

if a$ contains:

  'ABCDE12345'

The code below shows how to access individual chars from the string:

  c$ := a$[[0]] -- c$ holds: 'A'
  c1$ := a$[[1]] -- c1$ holds: 'B'
  c2$ := a$[[5]] -- c2$ holds: '1'
  a$[[1]] := 'b' -- string index 1 changed to 'b'

  -- Now a$ contains:
  'AbCDE12345'

Note: The double bracket index is also zero based, the first character has the index 0, the second has the index 1, and so on.

Operators

Operators are classified as arithmetic and string.

Precedence

Operators with higher precedence are performed before operators with lower precedence.

Operators with equal precedence are performed from left to right.

Numeric operators

apply in numeric expressions, the language supports the following operators:

 Operator   Description 
+ Addition
- Subtraction
* Multiplication
/ Division
^ Power
?> Maximum
?< Minimum
mod Modulo

Higher precedence
  ( )
  - (unary)
  ^
  * / mod
  + - ?> ?<
Lower precedence

Example:

  7 * 5 = 35
  3 * 5.5 = 16.5
  2 + 3 * 5 = 17
  (2 + 3) * 5 = 25
  10 / 4 = 2.5
  18 mod 8 = 2
  10 ?> 5 = 10   10 ?< 5 = 5

String operators

String operators apply in string expressions, the language supports the following operators:

 Operator   Description 
+ Addition
/ New line addition
- Deletion

Precedence

All string operators have the same precedence and are evaluated from left to right.

Example:

  'Hello' + 'World' = 'HelloWorld'
  'Hello' - 2 = 'Hel'
  'Hello' / 'World' =
  'Hello
  World'

Instructions

A script is nothing more than a list of instructions.

Each instruction in the script source code is separated by a new line or a colon (:).

Example (newline):

  print 'One year has'
  print 365/7
  print 'weeks'

Example (colon):

  print 'One year has' : print 365/7 : print 'weeks'

Keywords

The language take the following identifiers as reserved words, these should not be used to reference new variables or functions:

  IF OR TO
  AND CLS END FOR LET MOD NOT REM
  CASE DATA ELSE EXIT NEXT READ STEP THEN
  BREAK ENDIF INPUT LOCAL PRINT WHILE UNTIL
  ENDFOR REPEAT RETURN SELECT
  RESTORE
  CONTINUE ENDWHILE FUNCTION
  ENDSELECT
  ENDFUNCTION

Comments

Comments can be added with the keyword REM (ripped from BASIC) or the chars '--' (ripped from LUA).

Comments are valid until the end of line.

Examples:

  REM this is a comment
  -- and this is too
  -- but shorter

Functions

There is support for two kinds of functions:

User declared functions

A function is defined as a set of instructions that computes and returns a value.

The result can be discarded (like in BASIC and Delphi) or simply not returned, making it a procedure (subroutine). Local variables can be defined and recursive function calls are supported.

Syntax:

  Function <Name> ( parameters ) [ Local <local variables> ]
    ...
    [Return <result>]
    ...
  End Function

Examples:

  FUNCTION sum(a,b)
    RETURN a+b --Returns the sum of values passed in arguments a and b
  END FUNCTION

  FUNCTION intpower(a,b) LOCAL t,r
    r := 1
    FOR t := 1 TO b
      r *= a
    END FOR
    RETURN r
  END FUNCTION

  FUNCTION hello$(a$)
    RETURN 'Hello to you ' + a$
  ENDFUNCTION

As already mentioned, recursion is fully supported.

Example:

  FUNCTION factorial(n)
    IF n <= 1 THEN RETURN 1
    RETURN n * factorial(n-1)
  ENDFUNCTION

Note: The END FUNCTION and ENDFUNCTION statements are equivalent.

The language syntax supports name helpers that can be used in functions definitions. Function names must start with a letter which can be followed by letters, digits or the '_' char. A dot (.) can be used to divide the function name in segments, helping to organize functions based on user defined classifications.

For example, the functions...

  FUNCTION str.copy$(string1$, string2$)
    ...
  END FUNCTION

  FUNCTION str.invert$(string$)
    ...
  END FUNCTION

...are defined using the word 'str.' as part of its name classification.

There is no limit for the total of segments in a function name. It's up to the programmer not to abuse this functionality.

This functionality is constantly used in the libraries source code.

Delphi imported functions

Delphi functions can be directly accessed in scripts. Further in this material I'll detail the rules to include Delphi functions to the interpreter engine.

Functions signatures

The interpreter engine keeps track of both user declared and Delphi imported functions through functions signatures. A function signature is a string made by the function's name and argument types, it's used by the stack machine as the key to find functions entry points in memory.

Lets take a look in the following functions declaration:

  FUNCTION mul2(num)
    RETURN num * 2
  END FUNCTION

  FUNCTION replicate$(sstr$, qtd) LOCAL dstr$, i
    dstr$ := ''
    IF qtd <= 1 THEN RETURN sstr$
    FOR i := 1 TO qtd
      dstr$ := dstr$ + sstr$
    END FOR
    RETURN dstr$
  END FUNCTION

During the script compilation to the postfix notation, these function would by identified like:

  'mul2@n'
  'replicate$@$n'

The signatures are composed by the function name, which also identifies the function return type, followed by an @ and the types of the function's arguments. The types are identified by the chars n, $ and #:

This technique allows functions overloading and indirect function calls.

Functions overloading

Functions overloading is obtained by changing the functions arguments and/or return type in their declarations, for example, all the declarations below are valid in the same script:

  FUNCTION fn(p1)
  ...
  -- signature 'fn@n'

  FUNCTION fn(p1,p2)
  ...
  -- signature 'fn@nn'

  FUNCTION fn$(p1)
  ...
  -- signature 'fn$@n'

Observe that just changing the arguments "names" is not enough to avoid duplicity. The two declarations below would be invalid in the same script and would generate an error during compile time:

  FUNCTION fn(a)
  ...
  -- signature 'fn@n'

  FUNCTION fn(b)
  ...
  -- signature 'fn@n', duplicated function

The & operator and indirect function calls

Functions can be called indirectly by using the & operator and its variants (&$ and &#). The general syntax is:

  &( <function signature> [, expression1 [, expression2, ... , expression<n>]] )

If the called function has no parameters just ignore the part after the '@' symbol. The signature must exist at the stack machine dictionary and could be either a user declared function or a function imported from Delphi.

  FUNCTION mulstr$(txt$, num) LOCAL i, s$
    IF num <= 1 THEN RETURN txt$
    s$ := ''
    FOR i := 1 TO num
      s$ := s$ + txt$
    NEXT
    RETURN s$
  END FUNCTION

  FUNCTION hello$()
    RETURN 'Hello world.'
  END FUNCTION

  PRINT 'Calling mulstr$ using its name: ';mulstr$('Aa',5)
  PRINT 'Indirect call to mulstr$: '; &$('mulstr$@$n', 'Bb', 5)
  PRINT '"Far" functions can also be called: '; &('math.abs@n', -10) * 2
  PRINT 'Indirect call to a function without parameters: '; &$('hello$@')
  PRINT 'That'+chr$(39)+'s it.'

The &( ) operator must wrap the signature followed by the values that will be passed as parameters to the function. It can be used in an expression just like a regular function call, its type in the expression is defined by the called function return type. Use the variant &$ if trying to indirect call a function that returns a string, the &# syntax must be used if trying to call a function that returns a pointer.

Identifiers

Identifiers denote variables and functions, they can have any length and must begin with a letter and can't contain spaces.

Pointer identifiers denote pointer variables and pointer functions. The last character must be a (#)

String identifiers denote string variables and string functions. The last character must be a ($)

Examples:

  counter, temp, pix, i, n, n2
  handle#, p#, myobj#, buffer#
  name$, address2$, filename$, v$

Dictionaries

The Meeseeks interpreter has a library of functions designed to manage information stored as a collection of key and data pairs.

Dictionaries are pointer variables which points to a specific dictionary object. To create a new dictionary, it's necessary to use the function dict.new#(). For example:

d# := dict.new#(0) --The "0" means the dictionary can grow indefinitely.

Now the variable d# points to a dictionary object in memory. We could populate this dictionary using the dict.add() function and its variants. For example:

d# := dict.new#(0) --The "0" means the dictionary can grow indefinitely.
dict.add(d#, 'name', 'John Doe')
dict.add(d#, 'age', 45)
print 'Name: ';dict.get$(d#, 'name')
print 'Age: ';dict.get(d#, 'age')
dict.free(d#)

The script above creates a new dictionary using the variable d# and stores two values at it. Both keys are in the string format ('name' and 'age'), storing respectively the string and numeric values 'John Doe' and 45.

Take a look at the material about the dictionary library to see a list of all the functions which are part of it.

Commands

Assignment

LET

Assigns the result of an expression to a variable.

Syntax:

  [LET] <variable> := <expression>

The LET statement is actually optional, the syntax

<variable> := <expression>
can be used and the interpreter will assume the rest of the command.

Assignment variants

Numeric:

var += <expression> is equivalent to var := var + <expression>

var -= <expression> is equivalent to var := var - <expression>

var *= <expression> is equivalent to var := var * <expression>

var /= <expression> is equivalent to var := var / <expression>

String:

var$ += <string expression> is equivalent to var$ := var$ + <string expression>

var$ -= <string expression> is equivalent to var$ := var$ - <string expression>

var$ /= <string expression> is equivalent to var$ := var$ / <string expression>

Input / Output instructions

PRINT

Sends a text to the output control.

Syntax:

  PRINT [ expression [, expression] [; expression] ]

PRINT syntax is very similar to the homonymous BASIC language statement. Every expression must be separated by a semicolon or comma; if a semicolon is used then no spaces are added between the expressions. If comma is used then a TAB separator is added between the expressions. Numbers are always printed preceded by a single space. The numbers are formatted according to the operating system settings.

Example:

  PRINT 'Some math' ; 3+5 ; 4*4*4 ; sin(2.5)

CLS

Clear the contents of the output control.

The PRINT command sends its outputs to a TStrings object defined in the application hosting the interpreter. The CLS statement clear all the lines at this control.

INPUT

Use INPUT to open a window where the user can enter a value.

Syntax:

  INPUT <caption> , <question> , <default text|value>, <function name>

Note: The Android O.S. does not have "modal" dialogs and that's reflected in the INPUT statement.

The following parameters must be present during a call to the INPUT command:

  1. The input window caption;
  2. The question will be asked on it;
  3. The default value which can be of type string or numeric;
  4. The name of the function to call if the user presses the OK button.

It is important to understand that if running the below script in Android, the script flow will not stop while the INPUT popup window still on screen, this is not the case if running it under MS Windows. Take a look at the code below:

  --used with string values
  FUNCTION rettest(value$)
    PRINT 'String: ';value$
  END FUNCTION

  --used with numeric values
  FUNCTION rettest(value)
    PRINT 'Value: ';value
  END FUNCTION

  --INPUT 'Caption', 'Label', 'default text', rettest
  INPUT 'Caption', 'Label', 44, rettest

  --In Android this loop will be active even after the
  --INPUT window is opened.
  FOR i := 0 TO 200
    PRINT i
    std.handlemessages() --update the screen
  END FOR

If the user doesn't click the OK button the function rettest is not called. The calling function must have a single numeric or string argument, depending on the default value defined in the INPUT call.

Loop instructions

The language supports three kind of loop commands.

FOR, WHILE and REPEAT

Let's take a look on each one of them.

FOR .. NEXT

The complete syntax is:

  FOR <variable> := <expression> TO <expression> [STEP <constant>]
    ...
    ...
  END FOR | NEXT

Examples

  FOR angle := 1+ASIN(0.4) TO 1+ASIN(0.75) STEP 0.1
    PRINT angle
  NEXT

  FOR y := 1 TO 200
    FOR x := 1 TO 320
      s += x*y
    NEXT
  NEXT

The use of tabulation is not mandatory, but it makes much easier to understand the structure of the source code.

REPEAT .. UNTIL

This command repeats a series of instructions until the condition is evaluated to True. The command block begins with the REPEAT instruction and ends with the UNTIL instruction followed by the condition to evaluate.

Example:

  a = 1
  REPEAT
    PRINT a
    a := a + 1
  UNTIL a > 10

WHILE .. END WHILE

This command evaluates a condition at the beginning of the loop. If the condition is false then the cycle stops and execution continues after the END WHILE instruction.

Example:

  a := 1
  WHILE a <= 10
    PRINT a
    a := a + 1
  END WHILE

Since the WHILE statement evaluates the condition at the beginning of the loop, the instructions inside the loop may never be executed.

BREAK and CONTINUE

The BREAK and CONTINUE instructions make sense only inside loop constructions.

BREAK

Instantly terminates a loop, so in the example below the cycle stops when the variable a becomes greater than 5.

  FOR a := 1 TO 10
    PRINT a
    IF a < 5 then BREAK
  END FOR

CONTINUE

Transfers control to the next iteration of the loop, the control variable is updated and a new iteration starts immediately.

In the example below, the hello message is printed while the variable a is lower or equal to 5.

  FOR a := 1 TO 10
    PRINT a
    IF a > 5 THEN CONTINUE
    PRINT 'hello'
  NEXT --same as END FOR

Conditional instructions

IF .. THEN .. ELSE

The IF .. THEN statement evaluates a logical expression and determines the flow of the program based on the result of that expression.

Examples of logical expressions:

  a > 5 and b > 5
  a >= 3 or not b <> 5 and b+3 = c

Operators precedence

  Higher precedence:
    < , > , <= , >= , <> , =
    NOT
    AND
    OR
  Lower precedence

Syntax:

  IF <logical expression> THEN
  ...
  ...
  [ELSE IF <logical expression> THEN]
  ...
  ...
  [ELSE]
  ...
  ...
  ENDIF

Compact syntax:

  IF <logical expression> THEN <instruction> : <instruction> : ...

IF instructions can be nested without limits; the ELSE IF/ELSE parts are optional and not allowed in the compact syntax.

Examples:

  IF a < 0 and a > -10 THEN PRINT 'Small negative number': a := -a

  IF a >= 0 THEN
    PRINT a
    IF a = 12 THEN PRINT 'A perfect number !'
    IF a > 1000 THEN
      PRINT 'What a big number'
    ENDIF
  ELSE
    PRINT 'Negative numbers not allowed!'
  ENDIF

  a := 10 : b := 10

  IF a = 5 THEN
    print 'a = 5'
  ELSE IF a = 10 THEN
    print 'a = 10'
    IF b = 10 THEN
      print 'b = 10'
    ELSE IF b = 20 THEN
      print 'b = 20'
    ELSE IF b = 30 THEN
      print 'b = 30'
    ELSE
      print 'none of the above'
    ENDIF
  ELSE
    print 'none of the above'
  ENDIF

The ELSE IF construction is just syntactic sugar for a series of nested IF .. THEN .. ELSE statements. It helps to make the source code shorter and more readable. For example:

This code:

  a := 10
  IF a = 5 THEN
    print 'a = 5'
  ELSE
    IF a = 10 THEN
      print 'a = 10'
    ELSE
      IF a = 20 THEN
        print 'a = 20'
      ELSE
        print 'none of the above'
      ENDIF
    ENDIF
  ENDIF

is equivalente to the following:

  a := 10
  IF a = 5 THEN
    print 'a = 5'
  ELSE IF a = 10 THEN
    print 'a = 10'
  ELSE IF a = 20 THEN
    print 'a = 20'
  ELSE
    print 'none of the above'
  ENDIF

Once again, tabulations are not mandatory but certainly help to make the command structure more legible.

Note: The Meeseeks stack machine takes advantage of Delphi math functions in order to perform comparisons using floating point numbers with extreme precision. The following script demonstrates such functionality.

  x := 301.840002 - 301.000001
  if x = .840001 then
    print 'Perfect precision!'
  else
    print 'Not quite right...sorry.'
    print 'x = ';x
  end if

Take a look at the function math.cmpval to see more about logical operations using floating point numbers.

SELECT .. CASE

The SELECT .. CASE statement, also refered only as the CASE statement, allows the program to execute one set of statements out of many based on what a given expression evaluates to. Currently, the CASE statement can handle numerical and string expressions. Pointers in Meeseeks can be handled as numeric using the STD.NUMBER and STD.POINTER convertion functions.

Syntax:

SELECT [ CASE ] <numerical or string expression>
   [ CASE <expr1>[, <expr2>, ..., <exprN>]
       [ statements ] ]
   [ CASE ELSE
       [ elsestatements ] ]
END SELECT

Example1:

a := 5
SELECT CASE a
  CASE 1
    print 'variable a equals to 1'
    a := a + 1
    print 'a new value:';a
  CASE 2,3
    print 'variable a equals to 2 or 3'
    a := a + 2
    print 'a new value';a*2
  CASE 4,5,6
    print 'variable a equals to 4,5 or 6'
    a := a + 3
    print 'a new value';a*3
  CASE ELSE
    print 'none of the above.'
END SELECT

Note: The CASE instruction just after the SELECT is optional.

Example2:

a$ := '$$'
SELECT a$
  CASE 'aa','bb'
     print 'string a equals to "aa" or "bb"'
  CASE 'cc','dd'
     print 'string a equals to "cc" or "dd"'
  CASE 'ee'
     print 'string a equals to "ee"'
  CASE ELSE
     print 'none of the above.'
END SELECT

Any valid string or numerical expression can be used in the SELECT clause. Expressions cannot be mixed, the CASE tests must have the same type used in the SELECT clause.

Handling data in code

DATA READ RESTORE

DATA statements can be embedded in Meeseeks scripts to simplify the access to string and numeric data. DATA is accessed by the program with the READ statement, which reads the DATA items in sequence. The RESTORE statement causes the next READ statement to start at the first DATA statement listed.

DATA

The DATA statement provides a convenient way to insert data into programs. The DATA can be read once or many times using the READ statement. A DATA statement doesn't actually perform an action.

  DATA 'one', 1, 'two', 2, 'three', 3, 'end', 0

One or more DATA statements form the whole set of data elements. For example, the data represented in the example above can also be listed in more than one DATA statement:

  REM here is our data in two lines instead of one
  DATA 'one', 1, 'two', 2
  DATA 'three', 3, 'end', 0

Note: The DATA statement cannot be declared inside functions.

READ

Fetches the next strings or numeric value from a DATA statement in a script. The READ statement will fetch enough items to fill the variable names specified. The values fetched must fit the variables listed (string or numeric).

For example:

  REM read the numbers and their descriptions
  WHILE desc$ <> 'end'
    READ desc$, value
    PRINT desc$; ' is the name for '; value
  END WHILE
  REM here is our data
  DATA 'one hundred', 100, 'two', 2, 'three', 3, 'end', 0

READ statement variables may be numeric or string, and the values read must agree with the variable types specified. If they do not agree, an "Invalid data type for READ instruction" results.

Note: If the number of variables in the list of variables exceeds the number of elements in the DATA statement(s), a "READ past DATA" runtime error will result.

If the number of variables specified is fewer than the number of elements in the DATA statement(s), subsequent READ statements begin reading data at the first unread element. If there are no subsequent READ statements, the extra data is ignored.

To reread DATA statements from the start, use the RESTORE statement.

RESTORE

The RESTORE statement will reset the reading of DATA statements so that the next READ will get information from the first DATA statement in the program

For example:

  REM show me my data in all uppercase
  WHILE string$ <> 'end'
    READ string$
    PRINT str.ucase$(string$)
  END WHILE
  string$ := '' : REM clear this for next while/wend loop

  REM now reset the data reading to the beginning
  RESTORE

  REM show me my data in all lowercase
  WHILE string$ <> 'end'
    READ string$
    PRINT str.lcase$(string$)
  END WHILE

  DATA 'The', 'Quick', 'Brown', 'Fox', 'Jumped'
  DATA 'Over', 'The', 'Lazy', 'Dog', 'end'

It's important to note that all the data managed by the DATA and READ statements are stored directly in the script postfix code. The memory is used only to keep track the position of the DATA statements in the postfix code and the READ statement last control index.


Embedding Meeseeks in Delphi Apps

Important notice

Do not forget that (at least for the moment) the interpreter engine discussed here was developed to run only in Android and MS-Windows.

Interpreter sources

All sources were developed and tested under Delphi 10 Seattle.

Interpreter classes

The Meeseeks interpreter is written as a library in one single file, all its source code is contained at the uMeeseeks.pas file.

The file uMeeseeksLib.pas has type definitions and some methods used to exchange data between the interpreter and Delphi functions. Also, there are a few small libraries which could be integrated to the interpreter engine, in order to give it some minimal functionalities.

The file uMeeseeksLocalization.pas contains the string constants that hold all messages used in the script engine. The contents of this file can be changed in order to localize the interpreter messages to different languages.

Once you have opened in the Delphi IDE the Android application where you want to embed the interpreter, include these three files into it. The files must be among the project files in the RAD Studio Project Manager.

The interpreter engine has an object oriented interface to interact with Delphi applications, the classes which are part of the interpreter are listed below:

Now that we known more about the interpreter structure and how it was implemented, let's see how to use it.

Usage with Delphi

Compiling and running a script

Following are the steps to execute a script from the Delphi host application:

The steps above could be resumed in the following Delphi code:

  uses
    ... uMeeseeks, ...
  ...
  var
    source: TStringList;
    basic: TMeeseeksEngine;
    res: Integer;
    fncDict: TFunctionsDictionary;
  begin
    source := TStringList.Create;
    source.Add('PRINT ''Hello world.''');
    
    //fncDict holds the functions from all libraries
    fncDict := TFunctionsDictionary.Create();
    
    basic := TMeeseeksEngine.Create;
    res := basic.Compile(source, fncDict);
    if (res = 0) then //compilation Ok.
    begin
      try
        //Try to execute the entire script. PRINT outputs to "Memo1"
        basic.ExecuteProgram(Memo1.Lines);
      except
        On E:Exception do
        begin
          Memo1.Lines.Add('Exception: '+E.Message);
          Memo1.Lines.Add('IP: '+IntToStr(basic.Parser.exec.IP));
          Memo1.Lines.Add('Lin: '+IntToStr(basic.Parser.exec.SourceLine));
        end;
      end;
    end
    else
    begin
      Memo1.Lines.Add('*** ERROR ***');
      Memo1.Lines.Add('-> '+basic.ErrorMessage);
      Memo1.Lines.Add('Lin: '+IntToStr(basic.ErrorLine));
    end;
  end;
  ...

The Compile method compiles the script source code stored as a TStringList object in the first parameter. The second parameter is a dictionary with references to Delphi functions that will be linked to the interpreter engine and accessed by the stack machine. In this particular example this dictionary is empty because functions are not being declared or called in the script source code. Always pass a dictionary to this method even if it is an empty one.

I will talk in details about Delphi functions linkage next in this material.

The ExecuteProgram method runs the compiled script. Its parameter is an object of type TStrings that will keep all the outputs produced by the PRINT command.

Compiling and running script functions

It is possible after the successfull compilation of a script, to call for a specific function declared in it, instead of run it's entire code.

  uses
    ... uMeeseeks, uMeeseeksLib, ...
  ...
  var
    source: TStringList;
    fncDict: TFunctionsDictionary;
    basic: TMeeseeksEngine;
    res: Integer;
    Args: Array of TAsmData;
    rettype: TExprKind;
    retval: TAsmData;
  begin
    source := TStringList.Create;
    source.Add('FUNCTION mulstr$(txt$, num) LOCAL i, s$');
    source.Add('  IF num <= 1 THEN RETURN txt$');
    source.Add('  s$ := ''''');
    source.Add('  FOR i := 1 TO num');
    source.Add('    s$ := s$ + txt$');
    source.Add('  NEXT');
    source.Add('  RETURN s$');
    source.Add('END FUNCTION');
    source.Add('');
    source.Add('PRINT ''You should not see any of these lines...''');
    source.Add('PRINT ''...if running this script from the test''');
    source.Add('PRINT ''program.''');
    source.Add('PRINT');
    
    //Functions dictionary cannot be nil when functions are called or declared in
    //the script source code, but it can be empty.
    fncDict := TFunctionsDictionary.Create();
    basic := TMeeseeksEngine.Create;
    res := basic.Compile(source, fncDict);
    if (res = 0) then //compilation Ok.
    begin
      SetLength(Args, 2);
      Args[0].s := 'Yes!!!';
      Args[1].n := 5;
      try
        //Try to execute the function. PRINT outputs to "Memo1"
        basic.ExecuteUserFunction(Memo1.Lines, 'mulstr$@$n', Args, rettype, retval);
        case rettype of
          TExprKind.ekNumber:
            Memo1.Lines.Add('Numeric return: '+FloatToStr2(retval.n));
          TExprKind.ekPointer:
            Memo1.Lines.Add('Pointer return: '+IntToStr(Integer(retval.p)));
          TExprKind.ekString:
            Memo1.Lines.Add('String return: '+retval.s); //it must be this one
        end;
      except
        On E:Exception do
        begin
          Memo1.Lines.Add('Exception: '+E.Message);
          Memo1.Lines.Add('IP: '+IntToStr(basic.Parser.exec.IP));
          Memo1.Lines.Add('Lin: '+IntToStr(basic.Parser.exec.SourceLine));
        end;
      end;
    end
    else
    begin
      Memo1.Lines.Add('*** ERROR ***');
      Memo1.Lines.Add('-> '+basic.ErrorMessage);
      Memo1.Lines.Add('Lin: '+IntToStr(basic.ErrorLine));
    end;
  end;
  ...

In this example the method ExecuteUserFunction is invoked to execute a user defined function after the script is successfully compiled. As the name implies, only local functions which are declared in the script source can be used with this method, Delphi imported functions cannot be called by it.

This example includes the file uMeeseeksLib.pas in the uses clause, because there are references to the TAsmData type which is declared in this file. This type is used internally by the interpreter engine to exchange any of the language three available data types (numeric, pointer and string) with Delphi functions.

The rettype and retval parameters are updated respectivelly to the function return type and value. As showed in the example above, retval can be used to test what kind of result was produced after the function call.

The script example function, mulstr$, returns a string passed as the first parameter concatenated with itself by the number of times passed on its second parameter. In the example above, the string:

Yes!!!Yes!!!Yes!!!Yes!!!Yes!!!

is added as a new line in the host application Memo1 component after the function execution is finished.

Extending the interpreter

As promised, I will talk about how to link Delphi functions to the interpreter engine.

The way the interpreter engine was written makes very easy to integrate new Delphi functions to it, it's just necessary to respect a few rules.

The Delphi function must have the following format:

  function function_name(var Args: Array of TAsmData): TAsmData;
  begin
    ...
  end;

Basically, the function return type must be TAsmData. Also, the function must have only one var parameter which is an array to this same type. This function format is actually the one defined by TBindFunction. That's almost it, we can include any function to the interpreter dictionary through this format.

There is nothing better as simple examples to demonstrate how code works. Below there are two functions written according to the format previously described:

  function s_toupper(var Args: Array of TAsmData): TAsmData;
  begin
    Result.s := UpperCase(Args[0].s);
  end;

  function n_times3(var Args: Array of TAsmData): TAsmData;
  begin
    Result.n := Args[0].n * 3;
  end;

These two functions are intentionally very simple. The s_toupper function takes the first parameter (Args[0].s) of the function as a string, converts it to uppercase storing the new text in the string part of the function result (Result.s). The function n_times3 multiplies by 3 the first parameter from the function (Args[0].n) passed as numeric, storing the new value in the numeric part of the function result (Result.n).

In order to use these two functions in a script, it's necessary to include the descriptions for them in the interpreter dictionary:

  var
    source: TStringList;
    fncDict: TFunctionsDictionary;
    fncData: TLinkFunction; //Functions access data
    ...
  begin
    source := TStringList.Create;
    source.Add('PRINT toupper$(''this string is in uppercase'')');
    source.Add('PRINT ''10 * 3 = '';times3(10)');
    source.Add('PRINT ''Done.''');

    fncDict := TFunctionsDictionary.Create();

    fncData.FarCall := True; //Always 'True' to imported functions.

    fncData.Entry := s_toupper; //Function's entry point
    fncDict.Add('toupper$@$', fncData); //include new string function 'toupper$'

    fncData.Entry := n_times3;
    fncDict.Add('times3@n', fncData); //include new numeric function 'times3'
    ...
    res := basic.Compile(source, fncDict);
    if (res = 0) then //compilation Ok.
    begin
      try
        basic.ExecuteProgram(Memo1.Lines);
      except
    ...

That's it. That's all the necessary information needed to add new functions to the interpreter engine. Take a look at the test project to see the code above in action.

It's important to notice the function's signature as the key used by the engine to recover functions data.

Don't forget the part before the @ is the actual function name, its last char defines the function return value, if it ends with a $ the expected result is a string, if it ends with a # the expected result is a pointer, otherwise it will be a numerical function.

The length of the string after the @, defines the total number of arguments to the new function; each symbol means the argument type at that specific position.

If the function has no parameters, the signature must finish at the @ char.

The parameters index is zero based in Delphi. As we can see in the code above, the first parameter of the script function is accessed in Delphi using Args[0], the second would be Args[1] and so on.

To see examples of functions returning pointers and using pointer parameters, take a look at the code inside uMeeseeksLib.pas, specifically the libraries to import streams and the string list object. After read this section of the material, it should be easier to understand the libraries code.

In the next topic I'm going to talk about language events, it's also a good opportunity to understand how pointers are useful to make the interpreter engine interact with Delphi.

Working with the intermediate code

At the beginning of this material, I mentioned that the Meeseeks interpreter actually behaves quite similarly to a compiler. Scripts source code must be compiled to a postfix format before being executed by the stack machine. After a successful compilation, the language processor generates two kinds of postfix code, the intermediate code and the final assembly instructions which are actually interpreted by the stack machine. The interpreter main class (TMeeseeksEngine) stores these two postfix representations at the properties INTCode (the intermediate code) and ASMCode (the final set of instructions).

The intermediate code is a high level representation of the source script in postfix notation, this code retains some characteristics found at the script source, like the functions and variables names, if you are familiar to stack based programming languages like FORTH and PostScript, then it's not really difficult to read and understand the intermediate code produced by the Meeseeks compiler.

This intermediate form can be stored and passed directly to the interpreter engine, avoiding having to compile the script source code every time we need to execute its functionalities, making the script execution even faster.

Let's take the (very simple) script below as an example:

    PRINT 2 + 2

The intermediate postfix form produced by the Meeseeks engine for this source code is showed below:

    ,
    PUSHC 2
    PUSHC 2
    ADD
    PUSHC 1
    PRINT
    ,
    ,
    END

The postfix instruction PUSHC pushes a numeric constant into the stack, the instruction ADD will try to pop two numerical values from the stack pushing back the sum of them. The PRINT instruction initially pops a numeric value from the top of the stack, which must represent the total of stack items that will be popped and printed to the specified output, in this case, we have only the result of the addition to show, so the value poped from the stack must be 1 as defined by the last PUSHC instruction. The END instruction just finishes the stack machine execution.

Let's see some other examples:

Script source

    PRINT 'Hello world.'

Intermediate form:

    ,
    PUSHC$ 'Hello world.'
    PUSHC 1
    PRINT
    ,
    ,
    END

PUSHC$ pushes a string constant into the top of the stack.

Script source

    FUNCTION mul2(n)
      RETURN n * 2
    END FUNCTION

    PRINT '10 times 2 ='; mul2(10)

Intermediate form:

    ,
    FUNCTION mul2@n
    * 0 @0 @1 @2 n *
    ,
    PUSH @n
    PUSHC 2
    MUL
    RETFUNCTION
    ,
    PUSHC 0
    RETFUNCTION
    ENDFUNCTION
    ,
    ,
    PUSHC$ '10 times 2 ='
    PUSHC$ ';'
    PUSHC 10
    PUSHC 1
    CALLEX 'mul2@n'
    PUSHC 3
    PRINT
    ,
    ,
    END

The PUSH instruction will push the content of a numeric var into the top of the stack. The MUL instruction pops two values from the stack pushing back the result of the multiplication between them.

The CALLEX instruction call a function based on the string signature passed as argument.

The intermediate form could become really difficult to read if the script gets bigger and includes complex calculations and a lot of functions call/definitions, but it's a efficient way to the computer process calculations and it's also a way to inhibit changes to the source script functionality.

*** Note to myself ***: I will take some time during vacations to write a guide to each one of the Meeseeks stack machine instructions.

Load and execute intermediate code

The interpreter engine has methods to deal directly with code in the intermediate format, with no need to have the source script as part of the execution process.

After call the Compile method, the intermediate code is saved at the Memo2 control. In this example, the script functionality is obtained by passing this intermediate code stored in the Memo2.Lines property to the interpreter engine.

    // Execute intermediate code.
    //
    //
    //Get the lines from the produced intermediate code
    source.Clear;
    for i:=0 to Memo2.Lines.Count-1 do
      source.Add(Memo2.Lines[i]);
    
    res := basic.LoadIntermediate(source, fncDict);
    if res = 0 then
    begin
      try
        basic.ExecuteProgram(Memo3.Lines);
      except
        On E:Exception do
        begin
          Memo3.Lines.Add('*** Exception raised ***');
          Memo3.Lines.Add('');
          memo3.Lines.Add('>>> '+E.Message);
          Memo3.Lines.Add('IP: '+IntToStr(basic.Parser.exec.IP));
          Memo3.Lines.Add('Lin: '+IntToStr(basic.Parser.exec.SourceLine));
        end;
      end;
    end
    else
    begin
      Memo3.Lines.Add('*** ERROR ***');
      Memo3.Lines.Add('-> '+basic.ErrorMessage);
      Memo3.Lines.Add('Lin: '+IntToStr(basic.ErrorLine));
    end;

Meeseeks engine classes headers

TMeeseeksEngine

constructor Create;ConstructorClass constructor.
destructor Destroy; override;DestructorClass destructor.
Parser: TBasicParser;Public variable: TBasicParserThe Parser object handles the source code lexical analysis and parsing, as well as the postfix code generation and execution. The TMeeseeksEngine class uses it to perform and check the result of all these steps.
OnProgress: TNotifyEvent;Public variable: TNotifyEventThis variable is used to identify a TNotifyEvent method that can be used to debug a compiled script. The TNotifyEvent method pointed by it will be called for each instruction executed by the stack machine.
function Compile(source: TStrings): Integer; overload;MethodCompile a script stored at a TStrings type object. Returns zero if success, different than zero otherwise.
function Compile(source: PChar): Integer; overload;MethodCompile a script pointed by a PChar string. Returns zero if success, different than zero otherwise.
function LoadIntermediate(source: TStrList): Integer;MethodLoad the intermediate code instructions stored at a TStrList type object. Returns zero if success, different than zero otherwise.
function TotalTokens: Cardinal;MethodReturns the total of processed tokens by the engine after a script is successfully compiled.
procedure ExecuteUserFunction(
  stdout: TStrings;
  FunctionSignature: String;
  Parameters: Array of TAsmData;
  out RetType: TExprKind;
  out RetValue: TAsmData
);
Method Execute a user defined function identified in the parameter FunctionSignature. This type of function must be declared in the script source code.
The result of any PRINT command is redirected to the TStrings type object identified in the parameter stdout.
The function's parameters (if any) must be present in the same order of the function's header at the Parameters array. If the function has no parameter, the array must be left empty.
The variable RetType will keep the function return type if the execution was successful, the variable RetValue will keep the function returned value after its successful execution.
procedure ExecuteProgram(stdout: TStrings);MethodExecutes a successfully compiled script after a call to Compile. The results of any PRINT command is redirected to the TStrings type object defined by the stdout parameter.
procedure Stop;MethodImmediately stops the execution of a script.
function GetGlobalNum(const name: String; out index: Integer): Double;MethodGets the value of the numerical global var identified by the parameter name. If the variable was found, the index parameter is updated with the variable index at the HeapMem array and the value stored at the variable is returned. If the variable was not found, then the index parameter is set to -1 and the returned value is unpredictable.
function GetGlobalPtr(const name: String; out index: Integer): Pointer;MethodGets the value of the pointer global var identified by the parameter name. If the variable was found, the index parameter is updated with the variable index at the HeapMem array and the pointer address stored at the variable is returned. If the variable was not found, then the index parameter is set to -1 and the returned value is unpredictable.
function GetGlobalStr(const name: String; out index: Integer): String;MethodGets the value of the string global var identified by the parameter name. If the variable was found, the index parameter is updated with the variable index at the HeapMem array and the string stored at the variable is returned. If the variable was not found, then the index parameter is set to -1 and the returned value is unpredictable.
property INTCode: TStringItems read INTSource;Property: TStringItemsReturns the intermediate code produced by a successful compilation of a script.
property ASMCode: TStringItems read ASMSource;Property: TStringItemsReturns the final assembly code produced by a successful compilation of a script.
property ErrorPos: Integer read errPos;Property: IntegerReturns the absolute position of an error in the script.
property ErrorLine: Integer read errLine;Property: IntegerReturns the line number of an error in the script.
property ErrorMessage: String read errMessage;Property: StringReturns the message text of an error in the script.
property Functions: TFunctionsDictionary read FFunctions write FFunctions;Property: TFunctionsDictionaryUse this property to register Delphi functions to the interpreter engine.
property UserFunctions: TUserFunctionsDictionary read UserFunctionsTable;Property: TUserFunctionsDictionaryUse this property to access the informations (signature, entry point, total of arguments, arguments types) about any user defined function in a script. The script must be compiled first.
property LibFunctions: TFunctionsDictionary read LibFunctionsTable;Property: TFunctionsDictionaryKeep the signatures and entry points for all functions available in the script (user defined and Delphi imported). Can be used after source code compilation to get the signatures and entry points for all these available functions.
property RuntimeExceptionMsg: String read FRTExceptionMsg write FRTExceptionMsg;Property: StringCase an exception is raised when running a script using the self contained interpreter object, this property will retain the exception message.
property ScriptTimeOut: Int64 read FScriptTimeOut write SetScriptTimeOut;Property: Int64Define the time limit (in seconds) for the execution of a script, if the script exceeds this time limit, it will be immediately stopped. Case this property is setted to zero or less than zero, there will be no time check for the script execution (Warning!!! This can be a problem when wild loops are present at the script code).

TBasicLexer

constructor Create;ConstructorClass constructor.
destructor Destroy; override;DestructorClass destructor.
procedure LoadProg(source: PChar);MethodLoad and tokenize a Meeseeks source script
procedure Advance;MethodAdvance one token in the tokens list.
procedure PutBack;MethodSet the tokens list position to the anterior token.
function CurrS: String;MethodString representation of the current token.
function CurrN: Double;MethodNumeric representation of the current token.
function CurrPos: Integer;MethodCurrent position of the tokens list index.
function CurrTok: TBasToken;MethodCurrent token.
function PrevTok: TBasToken;MethodPrevious token.
function NextTok: TBasToken;MethodNext token.
procedure GotoToken(n: Integer);MethodGo to the token at the index defined by the parameter n.
function TotalTokens: Cardinal;MethodTotal of tokens in the tokens list.

TBasicParser

constructor Create;ConstructorClass constructor.
destructor Destroy; override;DestructorClass destructor.
lexer: TBasicLexer;Public variable: TBasicLexerThe lexer object.
exec: TExec;Public variable: TExecThe stack machine object.
function Compile(
  input: PChar;
  debug: TStrList;
  var INTOutput, ASMOutput: TStringItems;
  var libFuncs: TFunctionsDictionary
): Integer;
MethodCompile the script present at the input parameter. Sets the INTOutput and ASMOutput variables with respectively the intermediate code and the final assembly code if the compilation was successful. Link all the functions added to the libFuncs dictionary to the stack machine.
function ProcessPostfixCode(
  PF: TStringItems;
  var ASMOutput: TStringItems;
  var libFuncs: TFunctionsDictionary;
  debug: TStrList
): Integer;
MethodProcess the postfix code present at the PF parameter. Sets the ASMOutput variable with the final assembly code if the processing was successful. Link all the functions added to the libFuncs dictionary to the stack machine.
property Error: String read lastErr;Property: StringIf an error occurred during the parsing process, the error message can be accessed using this property.
property ErrorPos: Integer read errPos;Property: IntegerParsing error absolute position.
property ErrorLine: Integer read errLine;Property: IntegerParsing error line number
property CompileStatus: TBasStatus read status;Property: TBasStatusObject status after a script parsing and compilation.

TAsmLexer

constructor Create;ConstructorClass constructor.
destructor Destroy; override;DestructorClass destructor.
procedure LoadLine(p: PChar);MethodSets the string passed as parameter as the textual representation of the instruction to be processed by the assembly lexer.
function SecondArg(s: String): String;MethodReturns the parameter for an assembly instruction
function NextString: String;MethodReturns the next token for the loaded assembly instruction.
procedure Advance(
  var data: String;
  var tokenPos: Integer;
  var tok: TAsmToken
);
MethodThe lexer advances to the next token in the instruction. After execution data holds the token string representation, tokenPos holds the token start position, tok holds the token label.

TCompiler

constructor Create;ConstructorClass constructor.
destructor Destroy; override;DestructorClass destructor.
function Compile(
  source: TStringItems;
  funcs: TFunctionsDictionary
): TCompResult;
MethodProcess the intermediate code present at source and tries to convert it to the final assembly representation. All the registered functions present in funcs are available to be used in the final set of instructions.
function ReturnRegisteredFunctions: TUserFunctionsDictionary;MethodReturns a dictionary with all the functions registered during the script compilation.
function RegisterFuncData(
  source: String;
  out Signature: String;
  out ParamCount: Word;
  out ParamType: Array of TExprKind
): Boolean;
MethodThis method takes the function definition using the intermediate format at the source parameter and returns the function signature, arguments count and arguments types respectivelly in the Signature, ParamCount and ParamType parameters.

TExec

constructor Create;ConstructorClass constructor.
destructor Destroy; override;DestructorClass destructor.
procedure Clear;MethodClean the stack, registers and memory instructions. Reset the stack machine to the initial state.
procedure LoadSource(ls: TStringItems);MethodLoad the assembly instructions that will be executed by the stack machine.
procedure ExecuteFunction(
  Entry: Integer;
  ParamCount: Integer;
  ParamType: Array of TExprKind;
  Params: Array of TAsmData;
  RetType: TExprKind;
  out RetValue: TAsmData
);
MethodExecute a function at the loaded code. Entry identifies the function entry point at the code, ParamCount is the total of arguments that should be passed to the function, ParamType is an array that identifies each argument type, Params is an array that holds the values to be passed as parameters to the function, RetType identifies the function return type and RetValue will hold the value returned by the function after its execution.
procedure ExecuteProgram;MethodExecute the entire set of loaded instructions.
function GetGlobalNum(const Index: Integer): Double;MethodIf a global var exists at the specified index, this method tries to return its contents as a number.
function GetGlobalPtr(const Index: Integer): Pointer;MethodIf a global var exists at the specified index, this method tries to return its contents as a pointer.
function GetGlobalStr(const Index: Integer): String;MethodIf a global var exists at the specified index, this method tries to return its contents as a string.
procedure RTError(
  msg: TRTErrors;
  unkInstr: TAsmToken;
  auxMsg: String=''
);
MethodSets a runtime error condition in the stack machine. The argument msg identifies one of the possible enumerations for a runtime error. If we have to deal with an error not present at the original set of enumerations, then an unknown instruction and message could be provided to the method using the unkInstr and auxMsg arguments.
procedure Stop;MethodImmediately stops the stack machine.
property TotalASMInst: Integer Read FTotInsts;Property: IntegerReturns the total of assembly instructions currently in the stack machine.
property IP: Integer read PRG_IP;Property: IntegerThe stack machine instruction pointer. During the execution of a program the IP property will keep the index of the instruction being currently executed.
property SourceLine: Integer read srcLine;Property: IntegerReturns the equivalent script source line for the instruction currently in execution by the stack machine.
property PrintProc: TPrintProc read FPrintProc write FPrintProc;Property: TPrintProcSets the Delphi procedure that will handle the PRINT instruction outputs.
property CallbackProc: TNotifyEvent read FCallbackProc write FCallbackProc;Property: TNotifyEventA Delphi TNotifyEvent type method. If this property is set, this method will be called between each instruction executed by the stack machine.
property CallbackObj: TObject read FCallbackObj write FCallbackObj;Property: TObjectA Delphi object that will be used as the sender in the CallbackProc property.
property TimeOut: Int64 read FTimeOut write FTimeOut;Property: Int64This property specify the time (in seconds) that will be the maximum execution time for the stack machine. When the stack machine starts the execution of a set of instructions, the execution time cannot exceed the value specified by this property, if that happens, the stack machine execution will be immediately stopped.

The Meeseeks libraries

The file uMeeseeksLib.pas contains the methods for the Meeseeks functions libraries. These methods are organized according to its functionalities.


Math library

Math related functions that can be registered to the interpreter using the RegisterNumFuncs method.

Library: Math

Namespace 'math.'

ABS(n)

Signature: 'math.abs@n'

Returns the absolute value of a number.

ACOS(n)

Signature: 'math.acos@n'

Returns the inverse cosine of a number.

ACOSH(n)

Signature: 'math.acosh@n'

Returns the inverse hyperbolic cosine of a number.

ASIN(n)

Signature: 'math.asin@n'

Returns the inverse sine of a number.

ASINH(n)

Signature: 'math.asinh@n'

Returns the inverse hyperbolic sine of a number.

ATAN(n)

Signature: 'math.atan@n'

Returns the inverse tangent of a number.

ATAN2(n,m)

Signature: 'math.atan2@nn'

Returns the inverse tangent of n/m with right quadrant.

ATANH(n)

Signature: 'math.atanh@n'

Inverse hyperbolic tangent

CINT(n)

Signature: 'math.cint@n'

Returns the truncated integer part of a number.

CMPVAL(n,n[,n])

Signature:

    'math.cmpval@nn'

    'math.cmpval@nnn'

Allows floating point numbers to be compared in a tolerant way. If the two numbers are close enough together, they are deemed to be equal. The optional third parameter is the permitted tolerance, it's the maximum amount by which the numbers at the first and second parameters can differ and still be considered the same value.

math.cmpval returns one of the following constants:

 Return value   Description 
-1 if the first number is less than the second number (by more than the third parameter if specified).
0 if the first number is equivalent to the second number (the same, or within the third parameter if specified).
+1 if the first number is larger than the second number (by more than the third parameter if specified).

For example:

  x := 301.840002 - 301.000001
  if x = .840001 then
    print 'Perfect precision!'
  else
    print 'Not quite right...sorry.'
  end if
  print 'x =';x
  print 'cmpval: ';math.cmpval(x, .840001) -- (0)
  print 'cmpval: ';math.cmpval(x, .840005, .000002) -- (-1)
  print 'cmpval: ';math.cmpval(x, .839996, .000002) -- (1)
  print 'cmpval: ';math.cmpval(x, .840005, .000004) -- (0)

COS(n)

Signature: math.'cos@n'

Returns the cosine of a number.

COSH(n)

Signature: 'math.cosh@n'

Returns the hyperbolic cosine of a number.

DEGTORAD(n)

Signature: 'math.degtorad@n'

Returns the conversion of a value from degrees to radians.

EXP(n)

Signature: 'math.exp@n'

Returns the value of e raised to the power of n, where e is the base of natural logarithms.

FIX(n)

Signature: 'math.fix@n'

Returns the integer part of number 'n' rounded toward zero.

FRAC(n)

Signature: 'math.frac@n'

Returns the fractional part of a number.

INT(n)

Signature: 'math.int@n'

Returns the integer part of a number.

LN(n)

Signature: 'math.ln@n'

Returns the natural logarithm, base e of a number.

LOG2(n)

Signature: 'math.log2@n'

Returns the logarithm, base 2 of a number.

LOG10(n)

Signature: 'math.log10@n'

Logarithm, base 10

RADTODEG(n)

Signature: 'math.radtodeg@n'

Returns the radians to degrees conversion of anumber

RND()

Signature: 'math.rnd@'

Returns a random number in the range between 0 .. 1

RND(n)

Signature: 'math.rnd@n'

Returns a random number in the range between 0 .. n

ROUND(n)

Signature: 'math.round@n'

Returns the value of n rounded to the integer number.

SIN(n)

Signature: 'math.sin@n'

Returns the sine of a number, in radians.

SINH(n)

Signature: 'math.sinh@n'

Returns the hyperbolic sine of a value.

SQR(n)

Signature: 'math.sqr@n'

Returns the square root of a number.

SGN(n)

Signature: 'math.sgn@n'

Returns the sign of n, +1 0 -1.

TAN(n)

Signature: 'math.tan@n'

Returns the tangent of a number.

TANH(n)

Signature: 'math.tanh@n'

Returns the hyperbolic tangent of a number


String library

String management functions that can be registered to the interpreter by the RegisterStrFuncs method.

Library: String

Namespace 'str.'

ASC($)

Signature: 'str.asc@$'

Returns the ASCII code of a char. If a string with more than one char is passed as the parameter, only the first char will be relevant to the function result.

LCASE$($)

Signature: 'str.lcase$@$'

Returns the string in lowercase form.

UCASE$($)

Signature: 'str.ucase$@$'

Returns the string in the uppercase form.

LTRIM$($)

Signature: 'str.ltrim$@$'

Remove any left blank in the parameter string, returns the resultant string.

RTRIM$($)

Signature: 'str.rtrim$@$'

Remove any right blank in the parameter string, returns the resultant string.

LEN($)

Signature: 'str.len@$'

Returns the length of a string.

CHR$(n)

Signature: 'str.chr$@n'

ASCII to char conversion

STR$(n)

Signature: 'str.str$@n'

Number to string conversion (*)

(*) Operating system 'DecimalSeparator' value is used with this function.

BIN$(n)

Signature: 'str.bin$@n'

Converts a number to its binary format. Returns the result as a string.

HEX$(n)

Signature: 'str.hex$@n'

Converts a number to its hexadecimal format. Returns the result as a string.

OCT$(n)

Signature: 'str.oct$@n'

Converts a number to its octal format. Returns the result as a string.

MID$($,n[,n])

Signature:

       'str.mid$@$n'

       'str.mid$@$nn'

Substring extraction. The first parameter is the original string, the second is the zero based substring starting index, the third parameter is optional and defines the length of the substring to extract, if not specified, the substring is formed to the end of the original one.

LTAB$($,n)

Signature: 'str.ltab$@$n'

Left insertion of blank spaces in a string.

RTAB$($,n)

Signature: 'str.rtab$@$n'

Right insertion of blank spaces in a string.

LFILL$($,n,n)

Signature: 'str.lfill$@$nn'

Multiple left insertions of a char into a string. The first parameter is the original string, second parameter is the ASCII code of the char to insert, third parameter is the amount of insertions to perform.

RFILL$($,n,n)

Signature: 'str.rfill$@$nn'

Multiple right insertions of a char into a string. The first parameter is the original string, second parameter is the ASCII code of the char to insert, third parameter is the amount of insertions to perform.

LEFT$($,n)

Signature: 'str.left$@$n'

Returns 'n' characters from the left part of a string.

RIGHT$($,n)

Signature: 'str.right$@$n'

Returns 'n' characters from the right part of a string.

VAL($)

Signature: 'str.val@$'

String to number conversion.

CONTAINSSTR($,$)

Signature: 'str.containsstr@$$'

Performs a case sensitive search for a substring in a str. Returns 1 if one or more instances of the substring exists in the original string, 0 otherwise. The first argument is the original string, second argument is the substring to search for.

CONTAINSTEXT($,$)

Signature: 'str.containstext@$$'

Performs a case insensitive search for a substring in a string. Returns 1 if one or more instances of the substring exists in the original string, 0 otherwise. The first argument is the original string, second argument is the substring to search for.

MULSTRING($,n)

Signature: 'str.mulstring$@$n'

Returns the concatenation of a string with itself a specified number of repeats.

ENDSTR($,$)

Signature: 'str.endsstr@$$'

Determines if the original string ends with the substring using a case sensitive string comparison. Returns 1 if that's the case, 0 otherwise. The first argument is the original string, second argument is the substring to test.

ENDTEXT($,$)

Signature: 'str.endstext@$$'

Determines if the original string ends with the substring using a case insensitive string comparison. Returns 1 if that's the case, 0 otherwise. The first argument is the original string, second argument is the substring to test.

REPLACESTR$($,$,$)

Signature: 'str.replacestr$@$$$'

Replaces all occurrences of a substring within a string, using case-sensitive search, returns the new formed string. First argument is the original string, second argument is the text to search for, third argument is the text to replace with.

REPLACETEXT$($,$,$)

Signature: 'str.replacetext$@$$$'

Replaces all occurrences of a substring within a string, using case-insensitive search, returns the new formed string. First argument is the original string, second argument is the text to search for, third argument is the text to replace with.

REVERSE$($)

Signature: 'str.reverse$@$'

returns the parameter string in reverse.

STARTSSTR($,$)

Signature: 'str.startsstr@$$'

Determines if the original string starts with the substring using a case sensitive string comparison. Returns 1 if that's the case, 0 otherwise. The first argument is the original string, second argument is the substring to test.

STARTSTEXT($,$)

Signature: 'str.startstext@$$'

Determines if the original string starts with the substring using a case insensitive string comparison. Returns 1 if that's the case, 0 otherwise. The first argument is the original string, second argument is the substring to test.

STUFFSTRING$($,n,n,$)

Signature: 'str.stuffstring$@$nn$'

Inserts a substring into a specified position of a string, replacing the current characters. Returns a new string that is constructed by replacing the characters of the first argument string, with range specified by the second and third arguments (start, length), with the string specified in the fourth argument.


String functions, multirows  

COUNT($)

Signature: 'str.count@$'

Returns the total of rows in a multi row string.

OPENTEXT$($,$)

Signature: 'str.opentext$@$$'

Opens a text file into a string.

SAVETEXT$($,$,$)

Signature: 'str.savetext$@$$$'

Save the string as a text file.

COPYTEXT$($)

Signature: 'copytext$@$'

Copy the string to the clipboard.

PASTETEXT$()

Signature: 'str.pastetext$@'

Paste text from clipboard into the resulting string.


Standard library

Standard functions to handle types and messages. Date and time functions are included here.

This library can be registered to the interpreter by the RegisterStdFuncs method.

Library: Std

Namespace: 'std.'

NUMBER(#)

Signature: 'std.number@#'

Returns the pointer to number conversion.

POINTER(n)

Signature: 'std.pointer#@n'

Returns the number to pointer conversion.

PAUSE(n)

Signature: 'std.pause@n'

Suspend execution for n seconds.

DATE$()

Signature: 'std.date$@'

Returns the current system date in string format.

TIME$()

Signature: 'std.time$@'

Returns current system time in string format.

DATETIME$()

Signature: 'std.datetime$@'

Returns the current system date and time in string format.

TIMETOSTR$()

Signature: 'std.timetostr$@n'

Returns a string that represents a date and time value passed as numeric.

STRTOTIME($)

Signature: 'std.strtotime@$'

Returns the numeric representation of a time passed as string.

DATETIMETOSTR$(n)

Signature: 'std.datetimetostr$@n'

Converts  the numeric representation of a date and time value to a string. It uses the local settings for converting it. The date and time value is a double precision number.

STRTODATETIME($)

Signature: 'std.strtodatetime@$'

Returns the numeric value that represents a date and time in string format.

DATETOSTR$(n)

Signature: 'std.datetostr$@n'

Converts a date and time value into a string containing only the date part.

STRTODATE($)

Signature: 'std.strtodate@$'

Converts the string representation of a date to its numeric form.

DAYOFWEEK(n)

Signature: 'std.dayofweek@n'

Returns the day of the week of the specified date as an integer between 1 and 7, where Sunday is the first day of the week and Saturday is the seventh. The date must be supplied to the function using its numeric representation.

Note: DAYOFWEEK is not compliant with the ISO 8601 standard, which defines Monday as the first day of the week. For an ISO 8601 compliant version, use the DAYOFTHEWEEK function instead.

DAYOFTHEWEEK(n)

Signature: 'std.dayoftheweek@n'

Returns the day of the week represented by a specified date in the numeric format. DAYOFTHEWEEK returns a value from 1 through 7, where 1 indicates Monday and 7 indicates Sunday.

Note: DAYOFTHEWEEK is ISO 8601 compliant (where Monday is considered the first day of the week). To obtain the day of the week, where Sunday is considered the first day of the week, use the DAYOFWEEK function instead.

DAYOF(n)

Signature: 'std.dayof@n'

Returns the day of the month represented by a date and time numeric value.

Note: DAYOF returns the same value as the DAYOFTHEMONTH function.

DAYOFTHEMONTH(n)

Signature: 'std.dayofthemonth@n'

Call DAYOFTHEMONTH to obtain the day of the month represented by a specified date and time numeric value. DAYOFTHEMONTH returns a value from 1 through 31.

DAYOFTHEYEAR(n)

Signature: 'std.dayoftheyear@n'

Returns the ordinal position of a date and time value's day within its year. Thus, a date and time value that refers to January 1 generates a result of 1, dates on January 2 return 2, dates on February 1 return 32, and so on.

DAYSBETWEEN(n,n)

Signature: 'std.daysbetween@nn'

Returns the difference, in days, between two date and time values.

This function counts only whole days. Thus, it reports the difference between Dec 31, 1999 11:59 P.M. and Jan 1, 2000 11:58 P.M. as 0, because the difference is one minute short of an entire day.

This function always returns a positive result and therefore the parameter values are interchangeable.

DAYSINAMONTH(n,n)

Signature: 'std.daysinamonth@nn'

Returns the number of days in the specified month of the specified year.

First parameter is a year from 1 through 9999 (inclusive).

Second parameter is a month from 1 through 12 (inclusive).

DAYSINAYEAR(n)

Signature: 'std.daysinayear@n'

Returns the number of days in the year specified by the parameter. The parameter must be a year from 1 through 9999 (inclusive).

DAYSINMONTH(n)

Signature: 'std.daysinmonth@n'

Returns the number of days in the month of the date and time value specified by the parameter.

DAYSINYEAR(n)

Signature: 'std.daysinyear@n'

Returns the number of days in the year of the date and time value specified by the parameter.

DAYSPAN(n,n)

Signature: 'std.dayspan@nn'

Returns the number of days (including fractional days) between the two specified date and time values.

Unlike the DAYSBETWEEN function, which only counts whole days, DAYSPAN reports incomplete days as a fraction of an entire day.

DAYSPAN always returns a positive result and therefore the parameter values are interchangeable.

HOUROF(n)

Signature: 'std.hourof@n'

Returns the hour of the day represented by a specified date and time value. HOUROF returns a value from 0 through 23.

HOURSBETWEEN(n,n)

Signature: 'std.hoursbetween@nn'

Returns the difference, in hours, between two date and time values. HOURSBETWEEN counts only entire hours. Thus, it reports the difference between 9:00 A.M. and 9:59:59 A.M. as 0 because the difference is one second short of an entire hour.

HOURSBETWEEN always returns a positive result and therefore the parameter values are interchangeable.

HOURSPAN(n,n)

Signature: 'std.hourspan@nn'

Returns the difference, in hours, between two date and time values. Unlike the HOURSBETWEEN function, which only counts entire hours, it reports incomplete hours as a fraction of an entire hour.

HOURSPAN always returns a positive result and therefore the parameter values are interchangeable.

MILLISECONDOF(n)

Signature: 'std.millisecondof@n'

Returns the millisecond of the second represented by a specified date and time value. MILLISECONDOF returns a value from 0 through 999.

MILLISECONDSBETWEEN(n,n)

Signature: 'std.millisecondsbetween@nn'

Call MILLISECONDSBETWEEN to obtain the difference, in milliseconds, between two date and time values.

MILLISECONDSBETWEEN always returns a positive result and therefore the parameter values are interchangeable.

MILLISECONDSPAN(n,n)

Signature: 'std.millisecondspan@nn'

Returns the difference, in milliseconds, between two date and time values. MILLISECONDSPAN returns the same value as MILLISECONDS, but as a floating-point type instead of an integer.

MILLISECONDSPAN always returns a positive result and therefore the parameter values are interchangeable.

MINUTEOF(n)

Signature: 'std.minuteof@n'

Returns the minute of the hour represented by a specified date and time value. MINUTEOF returns a value from 0 through 59.

MINUTESBETWEEN(n,n)

Signature: 'std.minutesbetween@nn'

Returns the difference, in minutes, between two date and time values. MINUTESBETWEEN counts only entire minutes. Thus, it reports the difference between 9:00:00 A.M. and 9:00:59:999 A.M. as 0, because the difference is one millisecond short of an entire minute.

MINUTESBETWEEN always returns a positive result and therefore the parameter values are interchangeable.

MINUTESPAN(n,n)

Signature: 'std.minutespan@nn'

Returns the difference, in minutes, between two date and time values. Unlike the MINUTESBETWEEN function, which only counts entire minutes, it reports incomplete minutes as a fraction of an entire minute.

MINUTESPAN always returns a positive result and therefore the parameter values are interchangeable.

MONTHOF(n)

Signature: 'std.monthof@n'

Returns the month of the year represented by a specified date and time value. MONTHOF returns a value from 1 through 12.

Note: MONTHOF returns the same value as the MONTHOFTHEYEAR function.

MONTHOFTHEYEAR(n)

Signature: 'std.monthoftheyear@n'

Returns the month of the year represented by a specified date and time value. MONTHOFTHEYEAR returns a value from 1 through 12.

Note: MONTHOFTHEYEAR returns the same value as the MONTHOF function.

MONTHSBETWEEN(n,n)

Signature: 'std.monthsbetween@nn'

Returns the difference, in months, between two date and time values. Because months are not all the same length, MONTHSBETWEEN returns an approximation based on an assumption of 30.4375 days per month. Fractional months are not counted. Thus, for example, it reports the difference between February 1 and March 1 as 0.

MONTHSBETWEEN always returns a positive result and therefore the parameter values are interchangeable.

MONTHSPAN(n,n)

Signature: 'std.monthspan@nn'

Returns the difference, in months, between two date and time values. Because months are not all the same length, MONTHSPAN returns an approximation based on an assumption of 30.4375 days per month. Unlike the MONTHSBETWEEN function, which does not report fractional months, MONTHSPAN reports incomplete months as a fraction of an entire month.

MONTHSPAN always returns a positive result and therefore the parameter values are interchangeable.

INCDAY(n,n)

Signature: 'std.incday@nn'

Returns the value of the date in the first parameter (numeric representation), incremented by the number of days specified in the second parameter. The second parameter can be negative, to return a date N days previous.

The time of day specified by the first parameter is copied to the result.

INCHOUR(n,n)

Signature: 'std.inchour@nn'

Returns the date and time value in the first parameter, incremented by the number of hours specified in the second parameter. The total of hours in the second parameter can be negative, to return a date and time N hours prior to the original one.

INCMILLISECOND(n,n)

Signature: 'std.incmillisecond@nn'

Returns the date and time value in the first parameter, incremented by the amount of milliseconds  defined in the second parameter. The second parameter can be negative, to return a date and time N milliseconds prior to the original one.

INCMINUTE(n,n)

Signature: 'std.incminute@nn'

Returns the date and time value in the first parameter, incremented by the amount of minutes defined in the second parameter. The second parameter can be negative, to return a date and time N minutes prior to the original one.

INCSECOND(n,n)

Signature: 'std.incsecond@nn'

Returns the date and time value in the first parameter, incremented by the amount of seconds defined in the second parameter. The second parameter can be negative, to return a date and time N seconds prior to the original one.

INCWEEK(n,n)

Signature: 'std.incweek@nn'

Returns the date and time value in the first parameter, incremented by the amount of weeks defined in the second parameter. The second parameter can be negative, to return a date and time N weeks prior to the original one.

INCYEAR(n,n)

Signature: 'std.incyear@nn'

Returns the date and time value in the first parameter, incremented by the amount of years defined in the second parameter. The second parameter can be negative, to return a date and time N years prior to the original one.

ISAM(n)

Signature: 'std.isam@n'

Returns 1 if the time portion of parameter occurs after 00:00 (midnight) and before or at 12:00 (noon). 0 otherwise.

ISINLEAPYEAR(n)

Signature: 'std.isinleapyear@n'

Returns 1 if the year of the date specified in the parameter occurs in a leap year. 0 otherwise.

ISPM(n)

Signature: 'std.ispm@n'

Returns 1 if the time portion of parameter occurs on or after 12:00 noon and before 00:00 midnight. 0 otherwise.

ISSAMEDAY(n,n)

Signature: 'std.issameday@nn'

Returns 1 if the date in the first parameter occurs in the same day of the second one. 0 otherwise.

ISTODAY(n)

Signature: 'std.istoday@n'

returns 1 if the specified date and time value occurs on the current date. 0 otherwise.

WEEKOF(n)

Signature: 'std.weekof@n'

Returns the week of the year represented by a date and time value.

Call WEEKOF to obtain the week of the year represented by a specified date and time value. WEEKOF returns a value from 1 through 53.

WEEKOF uses the ISO 8601 standard to define the week of the year. That is, a week is defined as running from Monday through Sunday, and the first week of the year is the one that includes the first Thursday of the year (the first week that includes four or more days in the year). This means that if the first calendar day of the year is a Friday, Saturday, or Sunday, then for the first three, two, or one days of the calendar year, WEEKOF returns the last week of the previous year. Similarly, if the last calendar day of the year is a Monday, Tuesday, or Wednesday, then for the last one, two, or three days of the calendar year, WEEKOF returns 1 (the first week of the next calendar year).

Note: WEEKOF returns the same value as the WEEKOFTHEYEAR function.

WEEKOFTHEMONTH(n)

Signature: 'std.weekofthemonth@n'

Returns the week of the month represented by a specified date and time value. WEEKOFTHEMONTH returns a value from 1 through 6.

Note: WEEKOFTHEMONTH uses the ISO 8601 standard definition of a week. That is, a week is considered to start on a Monday and end on a Sunday.

WEEKOFTHEYEAR(n)

Signature: 'std.weekoftheyear@n'

Returns the week of the year represented by a specified date and time value. WEEKOFTHEYEAR returns a value from 1 through 53.

WEEKSBETWEEN(n,n)

Signature: 'std.weeksbetween@nn'

Returns the number of whole weeks between two specified date and time values.

WEEKSINAYEAR(n)

Signature: 'std.weeksinayear@n'

Returns the number of weeks in a specified year.

Note: WEEKSINAYEAR defines the first week of the year according to the ISO 8601 standard. That is, the first week of the year is the one that includes the first Thursday of the year (the first week that has four or more days in the year). This means that WEEKSINAYEAR always returns either 52 or 53.

WEEKSINYEAR(n)

Signature: 'std.weeksinyear@n'

Returns the number of weeks in the year of the date and time value specified in the parameter.

Note: WEEKSINYEAR defines the first week of the year according to the ISO 8601 standard. That is, the first week of the year is the one that includes the first Thursday of the year (the first week that has four or more days in the year). This means that WEEKSINYEAR always returns either 52 or 53.

WEEKSPAN(n,n)

Signature: 'std.weekspan@nn'

Returns the number of weeks (including fractional weeks) between two specified date and time values.

WEEKSPAN always returns a positive result and therefore the parameter values are interchangeable.

YEAROF(n)

Signature: 'std.yearof@n'

Returns the year of the date and time value in the parameter.

YEARSBETWEEN(n,n)

Signature: 'std.yearsbetween@nn'

Returns the approximate number of years between two specified date and time values.

YEARSPAN(n,n)

Signature: 'std.yearspan@nn'

Returns the approximate number of years (including fractions thereof) between two specified date and time values.

YEARSPAN always returns a positive result and therefore the parameter values are interchangeable.

YESTERDAY()

Signature: 'std.yesterday@'

Returns a date and time value that represents the preceding day.

FORMATSETTINGS($,$)

Signature:

       'std.formatsettings@$$'

       'std.formatsettings$@$'

This function allows the configuration of certain operating system locale options that will directly impact in the result of some of the standard functions. The available list of options is shown below, the options are really self explanatory.

If the function is called with two arguments, the first must be one of the options above and the second the new content for it, if the option is a valid one and the new value was actually assigned, the function returns 1, if for any reason the assignment was not done, the function returns 0.

Calling the function with a single argument, which must be one of the options described above, will result in a string that is the current value assigned to it.

PROCESSMESSAGES()

Signature: 'std.processmessages@'

Interrupts the execution of a program so that it can process the message queue.

Call PROCESSMESSAGES to permit the program to process messages that are currently in the message queue. PROCESSMESSAGES cycles the operating system message loop until it is empty, and then returns control to the program.

Note: PROCESSMESSAGES does not allow the program to go idle, whereas HandleMessage does.

HANDLEMESSAGE()

Signature: 'std.handlemessages@'

Interrupts the execution of a program while processing a message in the message queue.

HANDLEMESSAGE interrupts the execution of the program so that a single message from the message queue is processed, before returning the control to the program.

Note: If the application goes idle, HANDLEMESSAGE may take a long time to return. Therefore, do not call HANDLEMESSAGE when waiting for something message-based while priority actions are also being processed. Instead, call PROCESSMESSAGES when processing more than just messages.

ISNAN(n)

Signature: 'std.isnan@n'

Use ISNAN to test whether the value specified by the argument represents NaN (not a number).

ISNULL($)

Signature: 'std.isnull@$'

Use ISNULL to check if the string in the argument does not have any data assigned to it.

ISNIL(#)

Signature: 'std.isnil@#'

Use ISNIL to test if the pointer passed as argument is unassigned.


System library

OS specific functions that can be registered to the interpreter by the RegisterSysFuncs method.

Library: Sys

Namespace: 'sys.'

CHDIR($)

Signature: 'sys.chdir$@$'

Changes the current directory.

Note: CHDIR changes the current directory to the path specified by its parameter. If this operation fails, an exception is raised.

CHDIR always returns 1.

KILL($)

Signature: 'sys.kill@$'

Deletes a file from disk.

KILL deletes the file named from the disk. If the file cannot be deleted or does not exist, the function returns 0. Otherwise 1 is returned.

Note: KILL can delete a symbolic link from a file or a directory and is the preferred method for deleting symlinks.

FILEEXISTS($,n)

Signature: 'sys.fileexists@$n'

Tests whether the specified file exists.

FILEEXISTS returns 1 if the file specified by the parameter exists. If the file does not exist, 0 is returned.

Note: If the first parameter (file) is a symbolic link and the second parameter is set to a value different than zero, the method is performed on the target file. If the first condition is True, but the second parameter is set to zero, the symbolic link is used, regardless whether the link is broken (the target file is invalid).

Method behavior if the first parameter is a file:

File Exists Second Param Result
YES <> 0 1
YES 0 1
NO <> 0 0
NO 0 0

Method behavior if the FileName parameter is a symbolic link:

Target Exists Second Param Result
YES <> 0 1
YES 0 1
NO <> 0 0
NO 0 1

CHANGEFILEEXT$($,$)

Signature: 'sys.changefileext$@$$'

Changes the extension of a file name.

CHANGEFILEEXT takes the file name passed in first parameter and changes the extension of it to the one passed in the second parameter. The second parameter specifies the new extension, including the initial dot character.

CHANGEFILEEXT does not rename the actual file, it just creates a new file name string.

Note: This function works with multi-byte character sets (MBCS).

EXTRACTFILEEXT$($)

Signature: 'sys.extractfileext$@$'

Returns the extension portions of a file name.

Use EXTRACTFILEEXT to obtain the extension of a file name. For example, the following code returns the extension of the file named 'myfile.txt' (.txt):

fileextension$ = extractfileext$('myfile.txt')

PRINT fileextension$ --shows '.txt'

The resulting string includes the period character that separates the name and extension parts. This string is empty if the given file name has no extension.

Note: This function works for multi-byte character systems (MBCS).

EXTRACTFILENAME$($)

Signature: 'sys.extractfilename$@$'

Extracts the name and extension parts of a file name.

The resulting string is the rightmost characters of FileName, starting with the first character after the colon or backslash that separates the path information from the name and extension.

fileandpath$ = '/data/com.murlang.android.comp/files/myfile.txt'
file$ = extractfilename$(fileandpath$)
PRINT file$ --shows 'myfile.txt'

The resulting string is equal to the one in the parameter, if contains no drive and directory parts.

Note: This function works for multi-byte character systems (MBCS).

EXTRACTFILEPATH$($)

Signature: 'sys.extractfilepath$@$'

Returns the drive and directory portions of a file name.

The resulting string is the leftmost characters of the file name given as parameter, up to and including the colon or backslash that separates the path information from the name and extension.

fileandpath$ = '/data/com.murlang.android.comp/files/myfile.txt'
path$ = extractfilepath$(fileandpath$)
PRINT path$ --shows '/data/com.murlang.android.comp/files/'

The resulting string is empty if the parameter contains no drive and directory parts.

Note: This function works for multi-byte character systems (MBCS).

MKDIR($)

Signature: 'sys.mkdir@$'

Creates a new subdirectory.

MKDIR creates a new subdirectory with the path specified in the parameter.

The last item in the path cannot be an existing file name. MKDIR creates only the last directory; it does not create parent directories, whereas FORCEDIRECTORY does.

Note: If the new directory cannot be created an exception is raised. MKDIR always returns 1.

FORCEDIRECTORIES($)

Signature: 'sys.forcedirectories@$'

Creates a new directory, including the creation of parent directories as needed.

FORCEDIRECTORIES creates a new directory as specified in the parameter, which must be a fully-qualified path name. If the directories given in the path do not yet exist, FORCEDIRECTORIES attempts to create them.

ForceDirectories returns 1 if it successfully creates all necessary directories, 0 if it could not create a needed directory.

Note: Do not call FORCEDIRECTORIES with an empty string. Doing so causes the function to raise an exception.

RMDIR($)

Signature: 'sys.rmdir@$'

Deletes an empty subdirectory.

RMDIR removes the subdirectory in the path specified by the parameter. If the path does not exist, is non empty, or is the currently logged directory, an I/O error occurs.

ENVIRON$($)

Signature: 'sys.environ$@$'

Retrieves an environment variable value.

Call ENVIRON$ to retrieve the value of an environment variable, passed as the parameter, for the current process.

Note: The case of the specified environment variable Name is ignored.

RANDONFILENAME$()

Signature: 'sys.randomfilename$@'

Generates a new random file name.

Call RANDOMFILENAME$ to generate a new random file name. The function does not guarantee a unique file name. If a unique file name is desired, use GUIDFILENAME$ method instead. To generate a real uniquely-named temporary file, use the GETTEMPFILENAME$ method.

GUIDFILENAME$(n)

Signature: 'sys.guidfilename$@n'

Generates a new GUID that can be used as a unique file name.

Call GUIDFILENAME$ to generate a new GUID suitable as a unique name for a file or directory. This function only generates a file name and does not create a real file.

The numeric parameter defines if the function will produce names which contains the GUID separator char (the minus sign) or not. If the parameter value is zero, the GUID character will not be present in the produced name, any value different than zero will make the resulting name includes the GUID character.

TEMPFILENAME$()

Signature: 'sys.tempfilename$@'

Generates a unique temporary file.

Call TEMPFILENAME$ to generate a new uniquely-named temporary file. The function actually creates a zero-sized file in a temporary location and returns its name. The caller must delete the file after it is not used anymore.

Note: TEMPFILENAME$ raises an exception if the user has no access to the system's temporary directory.

TEMPPATH$()

Signature: 'sys.temppath$@'

Returns the path to a directory to store temporary files. This directory is a system-managed location; files saved here may be deleted between application sessions or system restarts.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

HOMEPATH$()

Signature: 'sys.homepath$@'

Returns either the home path of the user or the application's writable scratch directory or storage. Call HOMEPATH$ to obtain the user's home path on the supported target platforms.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

DOCUMENTSPATH$()

Signature: 'sys.documentspath$@'

Returns the path to the directory where user documents are stored.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

SHAREDDOCUMENTSPATH$()

Signature: 'sys.shareddocumentspath$@'

Returns the path to the directory where documents shared between users are stored.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

LIBRARYPATH$()

Signature: 'sys.librarypath$@'

Returns the path to a directory to store any data that your application needs store, regardless of the user, such as files, caches, resources, and preferences.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

CACHEPATH$()

Signature: 'sys.cachepath$@'

Returns the path to the directory where your application can store cache files.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

PUBLICPATH$()

Signature: 'sys.publicpath$@'

Returns the path to the directory where you can store application data that can be shared with other applications.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

PICTURESPATH$()

Signature: 'sys.picturespath$@'

Returns the path to the directory where user pictures are stored.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

SHAREDPICTURESPATH$()

Signature: 'sys.sharedpicturespath$@'

Returns the path to the directory where user shared pictures are stored.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

CAMERAPATH$()

Signature: 'sys.camerapath$@'

Returns the path to the directory where user pictures taken with a camera are stored.

This function works the same as PICTURESPATH$ except for the Android platform, where it returns the path to the folder where Android stores photos and videos taken with the device camera.

SHAREDCAMERAPATH$()

Signature: 'sys.sharedcamerapath$@'

Returns the path to the directory where user shared pictures taken with a camera are stored.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

This function works the same as PICTURESPATH$ except for the Android platform, where it returns the path to the folder where Android stores photos and videos taken with the device camera.

MUSICPATH$()

Signature: 'sys.musicpath$@'

Returns the path to the directory where user music is stored.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

SHAREDMUSICPATH$()

Signature: 'sys.sharedmusicpath$@'

Returns the path to the directory where user shared music is stored.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

MOVIESPATH$()

Signature: 'sys.moviespath$@'

Returns the path to the directory where user movies are stored.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

SHAREDMOVIESPATH$()

Signature: 'sys.sharedmoviespath$@'

Returns the path to the directory where user shared movies are stored.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

ALARMSPATH$()

Signature: 'sys.alarmspath$@'

Returns the path to the directory where user alarm sound files are stored.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

This function works the same as MUSICPATH$ except for the Android platform, where it returns the path to the folder where Android stores alarm sound files.

SHAREDALARMSPATH$()

Signature: 'sys.sharedalarmspath$@'

Returns the path to the directory where user shared alarm sound files are stored.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

This function works the same as SHAREDMUSICPATH$ except for the Android platform, where it returns the path to the folder where Android stores alarm sound files.

DOWNLOADSPATH$()

Signature: 'sys.downloadspath$@'

Returns the path to the directory where user stores downloaded files.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

SHAREDDOWNLOADSPATH$()

Signature: 'sys.shareddownloadspath$@'

Returns the path to the directory where user stores shared downloaded files.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

RINGTONESPATH$()

Signature: 'sys.ringtonespath$@'

Returns the path to the directory where user ring tones are stored.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

This function works the same as MUSICPATH$ except for the Android platform, where it returns the path to the folder where Android stores ring tones.

SHAREDRINGTONESPATH$()

Signature: 'sys.sharedringtonespath$@'

Returns the path to the directory where user shared ring tones are stored.

If the system running your application does not support the requested folder, or if the requested folder does not exist in the system, this function returns an empty string instead.

This functions works the same as SHAREDMUSICPATH$ except for the Android platform, where it returns the path to the folder where Android stores ring tones.

DIRSEPARATOR$()

Signature: 'sys.dirseparator$@'

Returns the character used to separate directory levels in a path string.

Use the value returned by the dirseparator function in routines that require the identification of individual directory levels in a path string.

PATHSEPARATOR$()

Signature: 'sys.pathseparator$@'

Returns the character used to separate path strings in environment variables.

Use the value returned by the pathseparator function in routines that require manipulation of environment variables. pathseparator is used to separate individual paths in a single environment variable string.


Memory stream library

Memory streams management library that can be registered to the interpreter by the RegisterMemoryStreamFuncs method.

Library: MemoryStream

Namespace: 'ms.'

Use a memory stream to store data in a dynamic memory buffer that is enhanced with file-like access capabilities. A memory stream provides the general I/O capabilities of a stream object while introducing methods and properties to manage a dynamic memory buffer.

Memory streams are useful as intermediary objects that can hold information as well as read it from or write it to another storage medium. They provide a useful format for comparing the contents of streams, or for manipulating data that is stored in a less accessible medium.

NEW#()

Signature: 'ms.new#@'

Parameters: None.

Creates a new memorystream control returning its address to the pointer variable.

ms# = ms.new#()

FREE(#)

Signature: 'ms.free@#'

Parameters:

  1. memory stream identity pointer

Forces the freeing of the memory stream control identified by the pointer in the parameter.

ms# = ms.new#()
...
ms.free(ms#)

It is not necessary to call this function in Android. Meeseeks automatically cleans all the controls created during the program execution, when the program is finished.

CLEAR(#)

Signature: 'ms.clear@#'

Parameters:

  1. memory stream identity pointer

Frees the memory buffer, discarding all data associated with the stream.

Use Clear to empty the memory buffer for the stream and free all associated memory.

In addition to freeing the memory associated with the memory buffer, CLEAR:

Sets the used memory to nil.

Sets the stream position to 0.

Sets the stream size to 0.

POSITION(#[,n])

Signature:

       'ms.position@#n'

       'ms.position@#'

Parameters:

  1. memory stream identity pointer (#)
  2. stream new position (n - optional)

Indicates the current offset into the stream for reading and writing.

Use POSITION to obtain or to set the current position of the stream. This is the number of bytes from the beginning of the streamed data.

If the function is called with only the control identity pointer, it returns the current position in the memory stream, if the position parameter is entered, it is used to set the control's current position.

SIZE(#[,n])

Signature:

       'ms.size@#n'

       'ms.size@#'

Parameters:

  1. memory stream identity pointer (#)
  2. stream new size (n - optional)

Sets or gets the size of the memory stream.

Use SIZE with the second parameter defined (numeric size in bytes) to set the size of a stream before filling it with data. SIZE allocates the memory buffer to hold the specified amount of bytes, preserving as much of the existing data as possible.

If the function is called with only the control's identity pointer parameter, the current memory size occupied by the control is returned.

Use SIZE before filling the memory buffer with data from various sources, or from a portion of another stream. If the intended contents of the stream is exactly the same as the contents of another stream or file, use LOADFROMSTREAM or LOADFROMFILE instead.

LOADFROMFILE(#,$)

Signature: 'ms.loadfromfile@#$'

Parameters:

  1. memory stream identity pointer (#)
  2. filename ($)

Loads the entire contents of a file into the memory buffer.

LOADFROMFILE allows an application to read the contents of a file into the stream without having to explicitly create and free a file stream control.

The function reallocates the memory buffer so that the contents of the file will exactly fit it. It sets the size of the stream accordingly, and then reads the entire contents of the file into the memory buffer. Thus, LOADFROMFILE will discard any pre-existing data stored in the stream.

SEEK(#,n,$)

Signature: 'ms.seek@#n$'

Parameters:

  1. memory stream identity pointer (#)
  2. offset (n)
  3. origin ($)

Moves to a specified position in the stream.

Call SEEK to move the current position of the stream in its particular storage medium (such as memory or a disk file).

The origin parameter indicates how to interpret the offset parameter. Origin should be one of the following values:

Value Meaning
'begin' Offset is from the beginning of the resource. Seek moves to the position Offset. Offset must be >= 0.
'current' Offset is from the current position in the resource. Seek moves to "current position" + Offset.
'end' Offset is from the end of the resource. Offset must be <= 0 to indicate a number of bytes before the end of the file.

Note: If the string passed as the origin parameter does not match any of the three above, 'current' will be used by default. It is not relevant if the string is case sensitive.

SAVETOFILE(#,$)

Signature: 'ms.savetofile@#$'

Parameters:

  1. memory stream identity pointer (#)
  2. filename ($)

Writes the entire contents of the memory stream to the file with a given file name.

The function allows a program to write out the contents of the stream without having to explicitly create and free a file stream control. In case the file already exists, the current file contents will be completely replaced with the new one. If the named file cannot be created or opened, SAVETOFILE raises an exception.

WRITE(#,$)

Signature: 'ms.write@#$'

Writes the string in the second parameter to the current position in the memory buffer and updates the current position by the length of the string.

Parameters:

  1. memory stream identity pointer (#)
  2. text to write ($)

ms# = ms.new#()
...
ms.seek(ms#, 0, 'begin')
ms.write(ms#, 'Some text to write')
...

The function returns the updated size of the memory stream after the writing operation is complete.

WRITE(#,n)

Signature: 'ms.write@#n'

Parameters:

  1. memory stream identity pointer (#)
  2. numeric value to write (n)

Writes the number in the second parameter to the current position in the memory buffer and updates the current position. A number in Meeseeks is always represented using double precision (64 bits, 15 significant digits), that means an offset of 8 bytes in length.

The function returns the updated size of the stream after the writing operation is complete.

WRITE(#,#)

Signature: 'ms.write@##'

Parameters:

  1. memory stream identity pointer (#)
  2. pointer value to write (#)

Writes the pointer representation in the second parameter to the current position in the memory buffer and updates the current position. A pointer in Meeseeks is always represented as a 32 bits integer, that means an offset of 4 bytes in length.

The function returns the updated size of the stream after the writing operation is complete.

READ$(#,n)

Signature: 'ms.read$@#n'

Parameters:

  1. memory stream identity pointer (#)
  2. number of characters to read (#)

Reads up to the number of characters defined in the second parameter from the stream, returning the read information as a string. Advances the current position of the stream by the number of characters read.

ms# = ms.new#()
...
ms.seek(ms#, 0, 'begin')
sv1$ = 'A text'
ms.write(ms#, string.len(sv1$), sv1$)
...
ms.seek(ms#, 0, 'begin')
sv2$ = ms.read$(ms#, string.len('A text'))
PRINT sv2$ --'A text'

READ$(#,n,$)

Signature: 'ms.read$@#n$'

Parameters:

  1. memory stream identity pointer (#)
  2. number of characters to read (n)
  3. encoding name ($)

Reads up to the number of characters from the stream, returning the read information as a string. Advances the current position of the stream by the number of characters read. The third parameter is the type of encoding to be applied to the extracted string.

The available encodings are:

Value Meaning
'default' OS default string encoding format.
'utf8' encoding for the UTF-8 format.
'utf7' encoding for the UTF-7 format.
'ansi' encoding for the ANSI format.
'ascii' encoding for the ASCII format.
'bigendianunicode' encoding for the UTF-16 format with big-endian byte order.
'unicode' encoding for the UTF-16 format with little-endian byte order.

http1# := http.new#()
ms1# := ms.new#()
print 'Size: '; ms.size(ms1#);' byte(s)' --right now is 0
http.get(http1#, 'http://www.andremurta.com', ms1#)
ms.seek(ms1#, 0, 'begin')
print 'Size: ';ms.size(ms1#);' byte(s)' --file size
httpstr$ := ms.read$(ms1#, ms.size(ms1#), 'utf8')
print httpstr$
ms.free(ms1#)
http.free(http1#)
print 'That'+chr$(39)+'s all folks.'

READ(#)

Signature: 'ms.read@#'

Parameters:

  1. memory stream identity pointer (#)

Reads a double precision number (64 bits, 15 significant digits) from the stream.

ms# := ms.new#()
...
ms.seek(ms#, 0, 'begin')
sv1$ = 'A text'
ms.write(ms#, string.len(sv1$), sv1$)
ms.write(ms#, 10.5)
...
ms.seek(ms#, 0, 'begin')
sv2$ = ms.read$(ms#, string.len('A text'), 'DEFAULT')
PRINT sv2$ --'A text'
num = ms.read(ms#)
PRINT num == 10.5

READ#(#)

Signature: 'ms.read#@#'

Parameters:

  1. memory stream identity pointer (#)

Reads a pointer stored as a 32 bits integer number from the stream.


String stream library

String streams management library that can be registered to the interpreter by the RegisterStringStreamFuncs method.

Library: StringStream

Namespace: 'ss.'

Use a string stream to store data as a long string enhanced with I/O capabilities. A string stream is useful as an intermediary object that can hold text as well as read it from or write it to another storage medium. A string stream provides a mechanism for manipulating text that is obtained from a less accessible medium.

NEW#($)

Signature: 'ss.new#@$'

Parameters:

  1. initial data string ($)

Creates a new stringstream, returning the pointer address for the newly created control.

Call NEW to instantiate a string stream object. The function initializes the return value of DATASTRING to the default string passed in the parameter.

strm# := ss.new#('Some initial text')

FREE(#)

Signature: 'ss.free@#'

Parameters:

  1. string stream identity pointer (#)

Forces the freeing of the memory stream control identified by the pointer in the parameter.

strm# = ss.new#()
...
ss.free(strm#)

It is not necessary to call this function if running in Android. Meeseeks automatically cleans all the controls created during the program execution, when the program is finished.

CLEAR(#)

Signature: 'ss.clear@#'

Parameters:

  1. string stream identity pointer (#)

Frees the memory buffer, discarding all data associated with the string stream.

Use Clear to empty the memory buffer for the string stream and free all associated memory. In addition to freeing the memory associated with the memory buffer, CLEAR:

Sets the used memory to nil.

Sets the stream position to 0.

Sets the stream size to 0.

COPYFROM(#,#,n)

Signature: 'ss.copyfrom@##n'

Parameters:

  1. target string stream identity pointer (#)
  2. source stream identity pointer (#)
  3. number of bytes to copy (n)

Copies a specified number of bytes from one stream to another.

Using COPYFROM eliminates the need to create, read into, write from, and free a buffer when copying data.

After the copy operation, the function moves the current position by the number of bytes read and returns the new size of the destination stream.

If the specified amount of bytes is 0, COPYFROM sets the source stream position to 0 before reading and then copies the entire contents of it into the destination string stream. If the specified amount of bytes is greater than or less than 0, COPYFROM reads from the current position in the source stream.

If the specified amount of bytes to read is greater than the source stream size, the function will throw an exception stating that a stream read error has occured.

DATASTRING$(#)

Signature: 'ss.datastring$@#'

Parameters:

  1. string stream identity pointer (#)

Provides direct access to the string that stores the text represented by the string stream control.

POSITION(#[,n])

Signature:

       'ss.position@#n'

       'ss.position@#''

Parameters:

  1. string stream identity pointer (#)
  2. stream new position (n - optional)

Indicates the current offset into the stream for reading and writing.

Use POSITION to obtain or to set the current position of the stream. This is the number of bytes from the beginning of the streamed data.

If the function is called with only the control pointer, it returns the current position in the string stream, if the second parameter is entered, it is used to set the control's current position.

SIZE(#[,n])

Signature:

       'ss.size@#n'

       'ss.size@#'

Parameters:

  1. string stream identity pointer (#)
  2. stream new size (n - optional)

Sets or gets the size of the string stream.

Use SIZE with the second parameter (numeric size in bytes) to set the size of a string stream before filling it with data. SIZE allocates the memory buffer to hold the specified amount of bytes, preserving as much of the existing data as possible.

If the function is called with only the pointer parameter, the current memory size occupied by the control is returned.

Use SIZE before filling the memory buffer with data from various sources, or from a portion of another stream. If the intended contents of the memory stream is exactly the same as the contents of another stream or file, use LOADFROMSTREAM or LOADFROMFILE instead.

LOADFROMFILE(#,$)

Signature: 'ss.loadfromfile@#$'

Parameters:

  1. string stream identity pointer (#)
  2. filename ($)

Loads the entire contents of a file into the memory buffer.

LOADFROMFILE allows an application to read the contents of a file into the stream without having to explicitly create and free a file stream control.

The function reallocates the memory buffer so that the contents of the file will exactly fit it. It sets the size of the stream accordingly, and then reads the entire contents of the file into the memory buffer. Thus, LOADFROMFILE will discard any pre-existing data stored in the stream.

SEEK(#,n,$)

Signature: 'ss.seek@#n$'

Parameters:

  1. string stream identity pointer (#)
  2. offset (n)
  3. origin ($)

Moves to a specified position in the stream.

Call SEEK to move the current position of the stream in its particular storage medium (such as memory or a disk file).

The origin parameter indicates how to interpret the offset parameter. Origin should be one of the following values:

Value Meaning
'begin' Offset is from the beginning of the resource. Seek moves to the position Offset. Offset must be >= 0.
'current' Offset is from the current position in the resource. Seek moves to "current position" + Offset.
'end' Offset is from the end of the resource. Offset must be <= 0 to indicate a number of bytes before the end of the file.

Note: If the string passed as the origin parameter does not match any of the three above, 'current' will be used by default. It is not relevant if the string is case sensitive.

SAVETOFILE(#,$)

Signature: 'ss.savetofile@#$'

Parameters:

  1. string stream identity pointer (#)
  2. filename ($)

Writes the entire contents of the stream to the file with a given file name .

Use SAVETOFILE to write the contents of memory to a file. The function allows a program to write out the contents of the stream without having to explicitly create and free a file stream control. In case the file already exists, the current file contents will be completely replaced with the new one. If the named file cannot be created or opened, SAVETOFILE raises an exception.

SAVETOSTREAM(#,#)

Signature: 'ss.savetostream@##'

Parameters:

  1. source string stream identity pointer (#)
  2. target stream identity pointer (#)

Writes the entire contents of the source string stream to the target stream control.

Use SAVETOSTREAM to copy data that is stored in memory into another storage medium. SAVETOSTREAM writes the entire contents of memory into the indicated stream control, starting at the current position in the stream that was passed as the source of data.

When the source stream parameter is a filestream control, SAVETOSTREAM does much the same thing as the SAVETOFILE function. However, SAVETOSTREAM writes to the current position in the target stream. Thus, for example, SAVETOSTREAM can be used to append the contents of Memory to a file stream, rather than replace the contents of the file the way SAVETOFILE does.

If the entire contents of the memory stream cannot be written to the target stream, SAVETOSTREAM raises an exception.

WRITESTRING(#,$)

Signature: 'ss.writestring@#$'

Parameters:

  1. string stream identity pointer (#)
  2. text to write ($)

Concatenates a specified string to the current position in the string stream, and updates the current position accordingly.

Use WRITESTRING to replace the end of the string from the current position on with the string specified by the string parameter. WRITESTRING changes the size of the stream to reflect the new length returned by DATASTRING.

READSTRING$(#,n)

Signature: 'ss.readstring$@#n'

Parameters:

  1. string stream identity pointer (#)
  2. bytes to read (n)

Returns a string that consists of up to the total of bytes specified in the second parameter, from the current position in the string stream. Advances the current position of the stream by the number of bytes read.

WRITE(#,$)

Signature: 'ss.write@#$'

Parameters:

  1. string stream identity pointer (#)
  2. text to write ($)

Writes the string in the second parameter to the current position in the memory buffer and updates the current position by the length of the string.

ms# = ss.new#()
...
ms.seek(ms#, 0, 'begin')
ms.write(ms#, 'some text to write')
...

The function returns the updated size of the stream after the writing operation is complete.

WRITE(#,n)

Signature: 'ss.write@#n'

Parameters:

  1. string stream identity pointer (#)
  2. numeric value to write (n)

Writes the number in the second parameter to the current position in the memory buffer and updates the current position. A number in Meeseeks is always represented using double precision (64 bits, 15 significant digits), that means an offset of 8 bytes in length.

The function returns the updated size of the stream after the writing operation is complete.

WRITE(#,#)

Signature: 'ss.write@##'

Parameters:

  1. string stream identity pointer (#)
  2. pointer value to write (#)

Writes the pointer in the second parameter to the current position in the memory buffer and updates the current position. A pointer in Meeseeks is always represented as a 32 bits integer, that means an offset of 4 bytes in length.

The function returns the updated size of the stream after the writing operation is complete.

READ$(#,n)

Signature: 'ss.read$@#n'

Parameters:

  1. string stream identity pointer (#)
  2. number of characters to read (n)

Reads up to the number of characters defined in the second parameter from the stream, returning the read information as a string. Advances the current position of the stream by the number of characters read.

The functions parameters are respectively:

The stream identity pointer (#);

The total of characters to read from the stream (n);

stream# = ss.new#()
...
ss.seek(stream#, 0, 'begin')
sv1$ = 'some text to write'
ss.write(stream#, string.len(sv1$), sv1$)
...
ss.seek(stream#, 0, 'begin')
sv2$ = ss.read$(stream#, string.len(sv1$))
PRINT sv2$ --'some text to write'

READ$(#,n,$)

Signature: 'ss.read$@#n$'

Parameters:

  1. memory stream identity pointer (#)
  2. number of characters to read (n)
  3. encoding name ($)

Reads up to the number of characters defined in the second parameter from the stream, returning the read information as a string. Advances the current position of the stream by the number of characters read. The third parameter is the type of encoding to be applied to the extracted string.

The available encodings are:

Value Meaning
'default' OS default string encoding format.
'utf8' encoding for the UTF-8 format.
'utf7' encoding for the UTF-7 format.
'ansi' encoding for the ANSI format.
'ascii' encoding for the ASCII format.
'bigendianunicode' encoding for the UTF-16 format with big-endian byte order.
'unicode' encoding for the UTF-16 format with little-endian byte order.

READ(#)

Signature: 'ss.read@#'

Parameters:

  1. memory stream identity pointer (#)

Read a double precision number (64 bits, 15 significant digits) from the stream.

READ#(#)

Signature: 'ss.read#@#'

Parameters:

  1. memory stream identity pointer (#)

Read a pointer stored as a 32 bits integer number from the stream.


File stream library

File streams management library that can be registered to the interpreter by the RegisterFileStreamFuncs method.

Library: FileStream

Namespace: 'fs.'

Use a file stream to access the information in disk files. A file stream will open a named file and provide methods to read from or write to it.

NEW#($,$)

Signature: 'fs.new#@$$'

Parameters:

  1. filename ($)
  2. open mode ($)

Creates an instance of a file stream control.

Call NEW to instantiate a file stream for reading from or writing to the named file.

The mode parameter indicates how the file is to be opened. The open mode must be one of the following values:

Value Meaning
'create' Create a file with the given name. If a file with the given name exists, override the existing file and open it in write mode.
'read' Open the file for reading only.
'write' Open the file for writing only. Writing to the file completely replaces the current contents.
'readwrite' Open the file to modify the current contents rather than replace them.

If the value in the mode parameter is not one of the listed above, the function will try to open the file using the 'readwrite' mode. The mode parameter is not case sensitive.

The function returns the pointer address of the newly created control.

FREE(#)

Signature: 'fs.free@#'

Parameters:

  1. file stream identity pointer (#)

Forces the freeing of the file stream control identified by the pointer in the parameter.

It is not necessary to call this function in Android. Meeseeks automatically cleans all the controls created during the program execution, when the program is finished.

FILENAME$(#)

Signature: 'fs.filename$@#'

Parameters:

  1. file stream identity pointer (#)

Returns the file name of the file associated with the file stream.

POSITION(#[,n])

Signature:

       'fs.position@#n'

       'fs.position@#'

Parameters:

  1. filestream stream identity pointer (#)
  2. new position (n - optional)

Indicates the current offset into the stream for reading and writing.

Use POSITION to obtain or to set the current position of the stream. This is the number of bytes from the beginning of the streamed data.

If the function is called with only the control pointer, it returns the current position in the file stream, if the second parameter is entered, it is used to set the control's current position.

COPYFROM(#,#,n)

Signature: 'fs.copyfrom@##n'

Parameters:

  1. target file stream identity pointer (#)
  2. source stream identity pointer (#)
  3. number of bytes to copy (n)

Copies a specified number of bytes from one stream to another.

Use COPYFROM to copy data from one stream to a different one. Using COPYFROM eliminates the need to create, read into, write from, and free a buffer when copying data.

After the copy operation, the function moves the current position by the number of bytes read and returns the new size of the destination stream.

If the specified amount of bytes is 0, COPYFROM sets the source stream position to 0 before reading and then copies the entire contents of it into the destination file stream. If the specified amount of bytes is greater than or less than 0, COPYFROM reads from the current position in the source stream.

If the specified amount of bytes to read is greater than the source stream size, the function will throw an exception stating that a stream read error has occured.

SIZE(#)

Signature: 'fs.size@#'

Parameters:

  1. file stream identity pointer (#)

Returns the current size in bytes of the file stream.

SEEK(#,n,$)

Signature: 'fs.seek@#n$'

Parameters:

  1. file stream identity pointer (#)
  2. offset (n)
  3. origin ($)

Moves to a specified position in the stream.

Call SEEK to move the current position of the stream in its particular storage medium (such as memory or a disk file).

The origin parameter indicates how to interpret the offset parameter. Origin should be one of the following values:

Value Meaning
'begin' Offset is from the beginning of the resource. Seek moves to the position Offset. Offset must be >= 0.
'current' Offset is from the current position in the resource. Seek moves to "current position" + Offset.
'end' Offset is from the end of the resource. Offset must be <= 0 to indicate a number of bytes before the end of the file.

Note: If the string passed as the origin parameter does not match any of the three above, 'current' will be used by default. The parameter content is not case sensitive.

WRITE(#,$)

Signature: 'fs.write@#$'

Parameters:

  1. file stream identity pointer (#)
  2. text to write ($)

Writes the string in the second parameter to the current position in the memory buffer and updates the current position by the length of the string.

ms# = fs.new#('myfile.dat','readwrite')
...
fs.seek(ms#, 0, 'begin')
fs.write(ms#, 'some text in the file')
...

The function returns the updated size of the stream after the writing operation is complete.

WRITE(#,n)

Signature: 'fs.write@#n'

Parameters:

  1. file stream identity pointer (#)
  2. numeric value to write (n)

Writes the number in the second parameter to the current position in the memory buffer and updates the current position. A number in Meeseeks is always represented using double precision (64 bits, 15 significant digits), that means an offset of 8 bytes in length.

The function returns the updated size of the stream after the writing operation is complete.

WRITE(#,#)

Signature: 'fs.write@##'

Parameters:

  1. file stream identity pointer (#)
  2. pointer value to write (#)

Writes the pointer in the second parameter to the current position in the memory buffer and updates the current position. A pointer in Meeseeks is always represented as a 32 bits integer, that means an offset of 4 bytes in length.

The function returns the updated size of the stream after the writing operation is complete.

READ$(#,n)

Signature: 'fs.read$@#n'

Parameters:

  1. file stream identity pointer (#)
  2. number of characters to read (n)

Reads up to the number of characters defined in the second parameter from the stream, returning the read information as a string. Advances the current position of the stream by the number of characters read.

The functions parameters are respectively:

The stream identity pointer (#);

The total of characters to read from the stream (n);

fs# = fs.new#('myfile.dat', 'readwrite')
...
fs.seek(fs#, 0, 'begin')
sv1$ = 'some text to write'
fs.write(fs#, string.len(sv1$), sv1$)
...
fs.seek(fs#, 0, 'begin')
sv2$ = fs.read$(fs#, string.len(sv1$))
PRINT sv2$ --'some text to write'

READ$(#,n,$)

Signature: 'fs.read$@#n$'

Parameters:

  1. file stream identity pointer (#)
  2. number of characters to read (n)
  3. encoding name ($)

Reads up to the number of characters defined in the second parameter from the stream, returning the read information as a string. Advances the current position of the stream by the number of characters read. The third parameter is the type of encoding to be applied to the extracted string.

The available encodings are:

READ(#)

Signature: 'fs.read@#'

Parameters:

  1. file stream identity pointer (#)

Reads a double precision number (64 bits, 15 significant digits) from the stream.

READ#(#)

Signature: 'fs.read#@#'

Parameters:

  1. file stream identity pointer (#)

Reads a pointer stored as a 32 bits integer number from the stream.


Strings library

String list management that can be registered to the interpreter by the RegisterStringsFuncs method.

Library: Strings

Namespace: 'strings.'

Use a strings control to store and manipulate a list of strings. The strings control allows, among many other features, to:

NEW#()

Signature: 'strings.new#@'

Parameters: None.

Use NEW to create a new instance of a string list control. The function returns the identity pointer to the newly created string list.

FREE(#)

Signature: 'strings.free@#'

Parameters:

  1. string list identity pointer (#)

Forces the freeing of the string list control identified in the parameter.

It is not necessary to call this function in Android. Meeseeks automatically cleans all the controls created during the program execution, when the program is finished.

CAPACITY(#[,n])

Signature:

       'strings.capacity@#n'

       'strings.capacity@#'

Parameters:

  1. string list identity pointer (#)
  2. new capacity (n - optional)

This function indicates the number of strings the string list can currently hold. If it's called with the second parameter, it defines this number.

CASESENSITIVE(#[,n])

Signature:

       'strings.casesensitive@#n'

       'strings.casesensitive@#'

Parameters:

  1. string list identity pointer (#)
  2. option flag (n - optional)

Controls whether strings in a string list are located, sorted, and identified as duplicates in a case-sensitive or case-insensitive manner.

Calling the function with the flag parameter as zero disables case sensitivity, any other value enables it.

The function returns the current setting if called with only the string list pointer. The possible return values are:

COMMATEXT(#,$)

Signature: 'strings.commatext@#$'

Parameters:

  1. string list identity pointer (#)
  2. comma text ($)

COMMATEXT$(#)

Signature: 'strings.commatext$@#'

Parameters:

  1. string list identity pointer (#)

Call COMMATEXT to list or define the strings in the string list control, using a system data format (SDF) representation.

When COMMATEXT is called with only the single parameter format, the function returns the text in the string list control in SDF format, any string in the list that include spaces, commas or quotes will be contained in double quotes, and any double quotes in a string will be repeated. For example, if the list contains the following strings:

Stri,ng 1
Stri"ng 2
String 3
String4

COMMATEXT will return:

"Stri,ng 1","Stri""ng 2","String 3",String4

When COMMATEXT is called with two parameters, assigning the comma text string, the string passed in the parameter is parsed as a SDF formatted text. For SDF format, strings are separated by commas or spaces, and optionally enclosed in double quotes. Double quote marks that are part of the string are repeated to distinguish them from the quotes that surround the string. Spaces and commas that are not contained within double quote marks are delimiters. Two commas next to each other will indicate an empty string, but spaces that appear next to another delimiter are ignored. For example, suppose the comma text is set to:

"Stri,ng 1", "Stri""ng 2" , String 3,String4

The list will then contain:

Stri,ng 1
Stri"ng 2
String
3
String4

Note: COMMATEXT is the same as call the DELIMITEDTEXT function with a delimiter of ',' and a quote character of '"'.

Including a trailing comma in the source string causes a blank item to be included in the string list. For example, if the string parameter in COMMATEXT is set to

"String1, String 2, String 3,"

the string list will contain

String1
String2
String3
<Blank>

COUNT(#)

Signature: 'strings.count@#'

Parameters:

  1. string list identity pointer (#)

Returns the number of strings in the string list control.

DEFAULTENCODING(#,$)

Signature: 'strings.defaultencoding@#$'

Parameters:

  1. string list identity pointer (#)
  2. encoding name ($)

DEFAULTENCODING$(#)

Signature: 'strings.defaultencoding$@#'

Parameters:

  1. string list identity pointer (#)

Sets or gets the default encoding type for the strings in the string list control.

Default encoding is used when the encoding cannot be detected.

The available encodings are:

Value Meaning
'default' OS default string encoding format.
'utf8' encoding for the UTF-8 format.
'utf7' encoding for the UTF-7 format.
'ansi' encoding for the ANSI format.
'ascii' encoding for the ASCII format.
'bigendianunicode' encoding for the UTF-16 format with big-endian byte order.
'unicode' encoding for the UTF-16 format with little-endian byte order.

DELIMITEDTEXT(#,$)

Signature: 'strings.delimitedtext@#$'

Parameters:

  1. string list identity pointer (#)
  2. delimited text ($)

DELIMITEDTEXT$(#)

Signature: 'strings.delimitedtext$@#'

Parameters:

  1. string list identity pointer (#)

Call DELIMITEDTEXT to get or set all the strings in the string list control in a single string, separated by the character specified by the DELIMITER function.

When DELIMITEDTEXT is called with only the string list pointer, any string in the list that includes spaces or the delimiter and quotation marks characters specified by the functions DELIMITER and QUOTECHAR will be surrounded (before and after) by the quotation mark character (QUOTECHAR), in addition, any QUOTECHAR character contained in an individual string will be repeated. The result of this process is returned as a single string by the function.

Again, when DELIMITEDTEXT is called with only the string list identity pointer, the resulting value delimits individual strings in two ways: each string is surrounded (before and after) by the quotation marks character specified by the QUOTECHAR function. In addition, individual strings are separated by the character specified by the DELIMITER function.

When DELIMITEDTEXT is called also specifying the delimited string, individual strings must be separated using the configured delimiter marks, and optionally enclosed in QUOTECHAR characters.

Also, when DELIMITEDTEXT is called specifying the delimited string, the string contents are parsed as a SDF formatted text. For SDF format, strings are separated by DELIMITER characters or spaces, and optionally enclosed in QUOTECHAR characters. QUOTECHAR marks that are part of the string are repeated to distinguish them from the QUOTECHAR characters that surround the string. Spaces and DELIMITER characters that are not contained within QUOTECHAR marks are delimiters. Two DELIMITER characters next to each other will indicate an empty string, but spaces that appear next to another DELIMITER character are ignored.

If STRICTDELIMITER was set to false, the space character is also interpreted as a delimiter, regardless of the value of delimiter. This is not true when the space character occurs between quotation marks.

Note: COMMATEXT is the same as the DELIMITEDTEXT setting when DELIMITER is ',' and QUOTECHAR is '"'. Including a trailing DELIMITER in the source string causes a blank item to be included in the string list.

DELIMITER(#,$)

Signature: 'strings.delimiter@#$'

Parameters:

  1. string list identity pointer (#)
  2. delimiter ($)

DELIMITER$(#)

Signature: 'strings.delimiter$@#'

Parameters:

  1. string list identity pointer (#)

Use DELIMITER to get or set the string delimiter used by the string list control. DELIMITEDTEXT returns all of the strings in the control as a single string, with individual strings separated by the character that is the value set by DELIMITER.

If DELIMITER is called with the delimiter char parameter, only the first character of the passed string is considered as the delimiter.

The default delimiter is represented by a comma (,).

DUPLICATES(#,$)

Signature: 'strings.duplicates@#$'

Parameters:

  1. string list identity pointer (#)
  2. duplicate string setup ($)

DUPLICATES$(#)

Signature: 'strings.duplicates$@#'

Parameters:

  1. string list identity pointer (#)

Specifies whether duplicate strings can be added to sorted lists.

Call DUPLICATES to specify what should happen when an attempt is made to add a duplicate string to a sorted list.

The value of the second parameter should be one of the following:

Value Meaning
'ignore' Ignore attempts to add duplicate strings to the list.
'error' raise an exception when an attempt is made to add duplicate strings to the sorted list.
'accept' Allows duplicate strings in the sorted list.

Call CASESENSITIVE to specify if two strings are considered duplicates if they are identical except for differences in case.

Calling DUPLICATES using only the identity pointer as the parameter returns the current configuration in the string list control.

ENCODING$(#)

Signature: 'strings.encoding$@#'

Parameters:

  1. string list identity pointer (#)

ENCODING returns the value of the encoding detected when the LOADFROMSTREAM or LOADFROMFILE methods are called. If the file does not contain a BOM, the value of the encoding cannot be detected and the string list control encoding is set to the default standard encoding, which can be specified by the DEFAULTENCODING function.

ENCODING is used in the SAVETOSTREAM and SAVETOFILE methods.

LINEBREAK(#,$)

Signature: 'strings.linebreak@#$'

Parameters:

  1. string list identity pointer (#)
  2. linebreak character ($)

LINEBREAK$(#)

Signature: 'strings.linebreak$@#'

Parameters:

  1. string list identity pointer (#)

Defines line-break characters.

Call LINEBREAK to set or read the string terminator characters in multistring output operations.

For example, the TEXT method returns a long string containing all strings in the string list, each of which is terminated by the value defined by LINEBREAK.

NAMES$(#,N)

Signature: 'strings.names$@#n'

Parameters:

  1. string list identity pointer (#)
  2. name index (n)

Indicates the name part of strings that are name-value pairs.

When the list of strings for the string list control includes strings that are name-value pairs, use NAMES to access the name part of a string. NAMES returns the name part of the string with the index specified by the second parameter, where 0 is the first string, 1 is the second string, and so on. If the string is not a name-value pair, NAMES returns an empty string.

NAMEVALUESEPARATOR(#,$)

Signature: 'strings.namevalueseparator@#$'

Parameters:

  1. string list identity pointer (#)
  2. separator ($)

NAMEVALUESEPARATOR$(#)

Signature: 'strings.namevalueseparator$@#'

Parameters:

  1. string list identity pointer (#)

Sets or returns the character used to separate names from values.

Strings that contain the specified character are considered name-value pairs. NAMEVALUESEPARATOR defaults to the equal sign (=).

Strings that are name-value pairs consist of a name part, the separator character, and a value part. Any spaces around the separator character are part of the name or value. This convention corresponds to the format used in many initialization files. For example:

DisplayGrid=1
SnapToGrid=1
GridSizeX=8
GridSizeY=8

QUOTECHAR(#,$)

Signature: 'strings.quotechar@#$'

Parameters:

  1. string list identity pointer (#)
  2. quote character ($)

QUOTECHAR$(#)

Signature: 'strings.quotechar$@#'

Parameters:

  1. string list identity pointer (#)

Specifies the quote character used by DELIMITEDTEXT.

Use QUOTECHAR to get or set the quote character that is used to enclose individual strings.

When QUOTECHAR is called with the quote parameter set to chr$(0), then DELIMITEDTEXT does the following:

That is, you can call QUOTECHAR with the second parameter set to chr$(0) to disable quoting in DELIMITEDTEXT.

If a string with more than one character is passed as the quote parameter, only the first character is considered.

SORTED(#[,n])

Signature:

       'strings.sorted@#n'

       'strings.sorted@#'

Parameters:

  1. string list identity pointer (#)
  2. sort option flag (n - optional)

Specifies whether the strings in the list should be automatically sorted.

Call SORTED with the second parameter with a value different than zero to cause the strings in the list to be automatically sorted in ascending order. Call SORTED with the second parameter set to zero to allow strings to remain where they are inserted. You can execute a sort in a string list at any time using the SORT method.

When using this function to sort the string, do not use INSERT to add strings to the list. Instead, use ADD, which will insert the new strings in the appropriate position. When SORTED is called to disable the sort in the string list, use INSERT to add strings to an arbitrary position in the list, or ADD to add strings to the end of it.

Note: Use CASESENSITIVE to controls whether the strings in the list are sorted based on a case-sensitive or case-insensitive comparison. The sort order takes into account the locale of the system on which the application is running.

STRICTDELIMITER(#[,n])

Signature:

       'strings.strictdelimiter@#n'

       'strings.strictdelimiter@#'

Parameters:

  1. string list identity pointer (#)
  2. strict delimiter option flag (n - optional)

Determines how the configuration defined by the DELIMITER method is used.

Use this function to specify whether the DELIMITER made config is the only value used within the DELIMITEDTEXT function result. If called with the second argument different than zero, individual strings in DELIMITEDTEXT result are separated only by the character that is the value defined by DELIMITER. If second argument is set to zero, individual strings in DELIMITEDTEXT result can be separated by a space, a non-printable character, or the character that is the value configured in DELIMITER.

STRINGS(#,n,$)

Signature: 'strings.strings@#n$'

Parameters:

  1. string list identity pointer (#)
  2. string index (n)
  3. string to store ($)

STRINGS$(#,n)

Signature: 'strings.strings$@#n'

Parameters:

  1. string list identity pointer (#)
  2. string index (n)

References the strings in the list by their positions.

Use the STRINGS function to get or set the string at a particular position. The second parameter is the index for the position of the string, where 0 is the first string, 1 is the second string, and so on.

To store a string as a name-value pair, call STRINGS with the third argument setted to a value that includes the NAMEVALUESEPARATOR character. The name and value will then be accessible separately using the NAMES and VALUES functions.

TEXT(#,$)

Signature: 'strings.text@#$'

Parameters:

  1. string list identity pointer (#)
  2. text representation ($)

TEXT$(#)

Signature: 'strings.text$@#'

Parameters:

  1. string list identity pointer (#)

Lists all the strings in the string list as a single string with the individual strings delimited by carriage returns.

Use TEXT to get or set all the strings in the control by a single string delimited by carriage returns.

When calling TEXT with only the string list identity pointer, the strings in the list will be returned separated by carriage return. If any of the strings in the list contain a carriage return, the resulting value of Text will appear to contain more strings than is indicated by the COUNT method.

When setting TEXT by passing the text through the second argument, the value will be parsed by separating into substrings whenever a carriage return is encountered.

VALUEFROMINDEX(#,n,$)

Signature: 'strings.valuefromindex@#n$'

Parameters:

  1. string list identity pointer (#)
  2. index (n)
  3. value part ($)

VALUEFROMINDEX$(#,n)

Signature: 'strings.valuefromindex$@#n'

Parameters:

  1. string list identity pointer (#)
  2. index (n)

Use VALUEFROMINDEX to get or set the value part of a string with a given index, on strings that are name-value pairs.

When the list of strings for the control includes strings that are name-value pairs, use VALUEFROMINDEX to get or set the value part of a string associated with an index.

For more information on name-value pairs, refer to the NAMEVALUESEPARATOR.

VALUES(#,$,$)

Signature: 'strings.values@#$$'

Parameters:

  1. string list identity pointer (#)
  2. string name ($)
  3. string value ($)

VALUES$(#,$)

Signature: 'strings.values$@#$'

Parameters:

  1. string list identity pointer (#)
  2. string name ($)

Call VALUES to get or set the value part of a string associated with a given name, on strings that are name-value pairs.

When the list of strings for the control includes strings that are name-value pairs, use VALUES to get or set the value part of a string associated with a specific name part.

For more information on name-value pairs, refer to the NAMEVALUESEPARATOR.

Note: The name index is case-insensitive. That is, values is the value part for the first occurrence of name or an equivalent string that differs only in case.

WRITEBOM(#[,n])

Signature:

       'strings.writebom@#n'

       'strings.writebom@#'

Parameters:

  1. string list identity pointer (#)
  2. BOM writing flag (n - optional)

Will cause SAVETOSTREAM or SAVETOFILE to write a BOM.

Call WRITEBOM with the second argument with a value different than zero to cause SAVETOSTREAM to write a BOM (byte-order mark) to the stream and to cause SAVETOFILE to write a BOM to the file.

ADD(#,$)

Signature: 'strings.add@#$'

Parameters:

  1. string list identity pointer (#)
  2. string to add to the list ($)

Adds a new string to the list.

Call ADD to add a new string to the list. If the list is sorted, the new entry is added to the appropriate position in the sort order. If the list is not sorted, the new string is added to the end of the list. ADD returns the position of the item in the list, where the first item has a value of 0.

Note: For sorted lists, ADD will raise an exception if the string already appears in the list and the DUPLICATES function was called with the 'error' option. If DUPLICATES is set to 'ignore', trying to add a duplicate string causes ADD to return the index of the existing entry.

APPEND(#,$)

Signature: 'strings.append@#$'

Parameters:

  1. string list identity pointer (#)
  2. string to append to the list ($)

Adds a string to the list.

APPEND is the same as the ADD method, except that it does return the list total of items after the appending. Use Append when there is no need to know the index of the string after it has been added.

BEGINUPDATE(#)

Signature: 'strings.beginupdate@#'

Parameters:

  1. string list identity pointer (#)

Enables the string list control to track when the list of strings is changing.

When implementing code that change the list in a string list control, call BEGINUPDATE before the changes are made, and ENDUPDATE when the changes are complete. That operation will make sure, for example, that GUI controls which are binded to the list control, like a memo or a listbox, will repaint when the updates are complete.

CLEAR(#)

Signature: 'strings.clear@#'

Parameters:

  1. string list identity pointer (#)

Deletes all the strings from the list.

Call CLEAR to empty all the entries in the list of strings.

DELETE(#, n)

Signature: 'strings.delete@#n'

Parameters:

  1. string list identity pointer (#)
  2. index (n)

Removes the string which index is specified by the index parameter.

Call DELETE to remove a single string from the list. The numeric parameter gives the position of the string, where 0 is the first string, 1 is the second string, and so on.

ENDUPDATE(#)

Signature: 'strings.endupdate@#'

Parameters:

  1. string list identity pointer (#)

Enables the string list control to keep track of when the list of strings has finished changing.

When implementing code that change the list in string lists, call BEGINUPDATE before the changes are made, and ENDUPDATE when the changes are complete. That operation will make sure, for example, that GUI controls which are binded to the list control, like a memo or a listbox, will repaint when the updates are complete.

EQUALS(#,#)

Signature: 'strings.equals@##'

Parameters:

  1. string list identity pointer (#)
  2. string list identity pointer (#)

Compares the list of strings between two string list controls and returns 1 if the two lists match, 0 otherwise.

EQUALS returns 1 if the lists for both controls have the same number of strings and the strings in each list match. EQUALS returns 0 if the lists are different in length, if they contain different strings, or if the order of the strings in the two lists differ.

Note: The EQUALS function does not provide a context-insensitive option.

EXCHANGE(#,n,n)

Signature: 'strings.exchange@#nn'

Parameters:

  1. string list identity pointer (#)
  2. index1 (n)
  3. index2 (n)

Swaps the position of two strings in the list.

Call EXCHANGE to rearrange the strings in the list. The strings are specified by their index values in the second and third parameters. Indexes are zero-based, so the first string in the list has an index value of 0, the second has an index value of 1, and so on.

Warning: Do not call EXCHANGE on a sorted list, EXCHANGE does not check whether the list is sorted, and can destroy the sort order of a sorted list.

FIND(#,$)

Signature: 'strings.find@#$'

Parameters:

  1. string list identity pointer (#)
  2. string to find ($)

Locates the index for a string in a sorted list and indicates whether a string with that value already exists in the list.

Use FIND to obtain the index in a sorted list where the string in the second parameter should be added. If the string or a string that differs from the one passed in the parameter only in case when CASESENSITIVE is set  to false, already exists in the list, FIND returns the string index. If the list does not contain a string that matches the one in the parameter, Find returns -1. The value of the returned index is zero-based, where the first string has the index 0, the second string has the index 1, and so on.

Note: Only use FIND with sorted lists. For unsorted lists, use the INDEXOF method instead.

INDEXOF(#,$)

Signature: 'strings.indexof@#$'

Parameters:

  1. string list identity pointer (#)
  2. string to return index ($)

Returns the position of a string in the list.

Call INDEXOF to obtain the position of the first occurrence of a string that matches the string passed in the second parameter. A string matches the one in the parameter if it is identical to it or, if CASESENSITIVE was called and set to false, and they differ only in case.

INDEXOF will work in this way on the condition that the list is not sorted and DUPLICATES was set to 'ignore' or 'error'. This reflects the internal definition of INDEXOF, which calls FIND if the list is sorted and will locate any string in the list that matches the parameter. Consequently, if DUPLICATES was set to 'accept', the result will not always be the first string matching the parameter.

INDEXOS returns the 0-based index of the string. Thus, if the parameter matches the first string in the list, INDEXOF returns 0, if the parameter is the second string, it returns 1, and so on. If the string does not have a match in the string list, INDEXOF returns -1.

INDEXOFNAME(#,$)

Signature: 'strings.indexofname@#$'

Parameters:

  1. string list identity pointer (#)
  2. name to return index ($)

Returns the position of the first name-value pair with the specified name.

Call INDEXOFNAME to locate the first occurrence of a name-value pair where the name part is equal to the string parameter or differs only in case. INDEXOFNAME returns the 0-based index of the string. If no string in the list has the indicated name, it returns -1.

Note: If there is more than one name-value pair with a name portion matching the Name parameter, INDEXOFNAME returns the position of the first one.

INSERT(#,n,$)

Signature: 'strings.insert@#n$'

Parameters:

  1. string list identity pointer (#)
  2. index (n)
  3. string to insert ($)

Inserts the string passed in the string parameter to the list at the position specified by the numeric parameter.

Call INSERT to add the string to the list at the position specified by the second argument. If the passed index is 0, the string is inserted at the beginning of the list. If the index is 1, the string is put in the second position of the list, and so on.

Note: If the list is sorted, calling INSERT will raise an exception. Use ADD or APPEND with sorted lists.

LOADFROMFILE(#,$,$)

Signature: 'strings.loadfromfile@#$$'

Parameters:

  1. string list identity pointer (#)
  2. filename ($)
  3. encoding name ($)

Fills the list with the lines of text in a specified file.

Call LOADFROMFILE to fill the list of strings from the file specified in the second parameter. LOADFROMFILE first clears any strings already in the list. As indicated by end of line characters, each line in the file is then appended in the list as a string.

The third parameter is the encoding. LOADFROMFILE then saves the value of the encoding in the property accessed by ENCODING, to be used if the file is saved.

The available encodings are:

Value Meaning
'default' OS default string encoding format.
'utf8' encoding for the UTF-8 format.
'utf7' encoding for the UTF-7 format.
'ansi' encoding for the ANSI format.
'ascii' encoding for the ASCII format.
'bigendianunicode' encoding for the UTF-16 format with big-endian byte order.
'unicode' encoding for the UTF-16 format with little-endian byte order.

Note: loadfromfile uses the Add method to add the strings that are read from the file. If the specified file is not found, an exception is raised.

LOADFROMSTREAM(#,#,$)

Signature: 'strings.loadfromstream@##$'

Parameters:

  1. string list identity pointer (#)
  2. source stream identity pointer (#)
  3. encoding name ($)

Fills the list with lines of text read from a stream.

Call LOADFROMSTREAM to fill the string list from the stream specified by the second parameter. The text read from the stream is parsed into strings separated by end of line characters. Thus, LOADFROMSTREAM reads the value of the Text property.

The third parameter is the encoding. LOADFROMSTREAM then saves the value of the encoding in the property accessed by ENCODING, to be used if the file is saved.

The available encodings are:

Value Meaning
'default' OS default string encoding format.
'utf8' encoding for the UTF-8 format.
'utf7' encoding for the UTF-7 format.
'ansi' encoding for the ANSI format.
'ascii' encoding for the ASCII format.
'bigendianunicode' encoding for the UTF-16 format with big-endian byte order.
'unicode' encoding for the UTF-16 format with little-endian byte order.

If the stream is a file stream, LOADFROMSTREAM does the same thing as LOADFROMFILE, except the application must create and destroy the file stream

MOVE(#,n,n)

Signature: 'strings.move@#nn'

Parameters:

  1. string list identity pointer (#)
  2. current index (n)
  3. new index (n)

Changes the position of a string in the list.

Use MOVE to move the string at position identified by the second parameter so that it occupies the new position specified by the third parameter. The positions are specified as 0-based indexes. For example, the following lines of code move the string in the first position to the last position:

mylist# = strings.new#()
...
strings.move(mylist#, 0, strings.count(mylist#)-1)

SAVETOFILE(#,$,$)

Signature: 'strings.savetofile@#$$'

Parameters:

  1. string list identity pointer (#)
  2. filename ($)
  3. encoding name ($)

Saves the strings in the list to the specified file.

Call SAVETOFILE to save the strings in the list to the file specified by the second parameter. Each string in the list is written to a separate line in the file.

The third parameter defines the encoding to be used in the saved file. The available encodings are:

Value Meaning
'default' OS default string encoding format.
'utf8' encoding for the UTF-8 format.
'utf7' encoding for the UTF-7 format.
'ansi' encoding for the ANSI format.
'ascii' encoding for the ASCII format.
'bigendianunicode' encoding for the UTF-16 format with big-endian byte order.
'unicode' encoding for the UTF-16 format with little-endian byte order.

SAVETOSTREAM(#,#,$)

Signature: 'strings.savetostream@##$'

Parameters:

  1. string list identity pointer (#)
  2. target stream identity pointer (#)
  3. encoding name ($)

Writes the string list text to a stream control.

Call SAVETOSTREAM to save the strings in the list to the stream specified by the second parameter. SAVETOSTREAM writes the strings delimited by the end of line character. If the stream is a file stream, SAVETOSTREAM does the same thing as SAVETOFILE, except the application must create and destroy the file stream.

The third parameter defines the encoding to be used in the stream content. The available encodings are:

Value Meaning
'default' OS default string encoding format.
'utf8' encoding for the UTF-8 format.
'utf7' encoding for the UTF-7 format.
'ansi' encoding for the ANSI format.
'ascii' encoding for the ASCII format.
'bigendianunicode' encoding for the UTF-16 format with big-endian byte order.
'unicode' encoding for the UTF-16 format with little-endian byte order.

SORT(#)

Signature: 'strings.sort@#'

Parameters:

  1. string list identity pointer (#)

Sorts the strings in the list in ascending order.

Call SORT to sort the strings in a list which SORTED function was set to false. If the function SORTED was called with the sort parameter set to true, then the strings in the list are automatically sorted.


Dictionary library

Dictionaries related functions that can be registered to the interpreter by the RegisterDictFuncs method.

Library: Dict

Namespace: 'dict.'

Collection of key-value pairs.

A dictionary represents a generic collection of key-value pairs.

Dictionary keys cannot be empty and are made by numeric or string values, the associated value can also store pointers besides numbers and strings.

A pointer CANNOT be used as a dictionary key, but it can be converted to its numeric form to be associated to a value, the numeric value can be casted back to a pointer, see the STD.POINTER and STD.NUMBER functions in the standard library.

You can add a key that is associated with a corresponding value with the DICT.ADD or DICT.ADDORSET methods. You can remove entries with DICT.REMOVE or DICT.CLEAR, which removes all key-value pairs. Adding or removing a key-value pair and looking up a key are efficient, close to O(1), because keys are hashed.

You can test for the presence or keys and values with the DICT.HASKEY and DICT.HASVALUE methods.

NEW#(n)

Signature: 'dict.new#@n'

Parameters:

  1. Dictionary capacity (n)

Use NEW to create and initialize a new instance of a dictionary control. The function returns the identity pointer to the newly created control.

The numeric parameter determines the initial capacity for the dictionary.

FREE(#)

Signature: 'dict.free@#'

Parameters:

  1. Dictionary control pointer (#)

Forces the freeing of the dictionary control identified by the pointer in the parameter.

myhash# = dict.new#(0) --dynamically grows
dict.add(myhash#, 1, 10) --key 1, value 10
dict.add(myhash#, 2, 20) --key 2, value 20
dict.add(myhash#, 3, 30) --key 3, value 30
dict.add(myhash#, 4, 40) --key 4, value 40
dict.add(myhash#, 5, 50) --key 5, value 50
PRINT dict.count(myhash#)
PRINT dict.get(myhash#, 3) --prints 30
...
dict.free(myhash#)

It is not necessary to call this function. Meeseeks automatically cleans all the controls created during the program execution, after the program is finished.

ADD(#,n,n)

Signature: 'dict.add@#nn'

Parameters:

  1. Dictionary control pointer (#)
  2. Key (n)
  3. Value (n)

Add a key-value pair.

This overload of the DICT.ADD function adds a numeric key and its corresponding numeric value to the dictionary. The key cannot be empty, but the value can.

If the key already exists in the dictionary, an exception is thrown.

ADD(#,n,#)

Signature: 'dict.add@#n#'

Parameters:

  1. Dictionary control pointer (#)
  2. Key (n)
  3. Value (#)

Add a key-value pair.

This overload of the DICT.ADD function adds a numeric key and its corresponding pointer to the dictionary. The key cannot be empty, but the value can.

If the key already exists in the dictionary, an exception is thrown.

ADD(#,n,$)

Signature: 'dict.add@#n$'

Parameters:

  1. Dictionary control pointer (#)
  2. Key (n)
  3. Value ($)

Add a key-value pair.

This overload of the DICT.ADD function adds a numeric key and its corresponding string value to the dictionary. The key cannot be empty, but the value can.

If the key already exists in the dictionary, an exception is thrown.

ADD(#,$,n)

Signature: 'dict.add@#$n'

Parameters:

  1. Dictionary control pointer (#)
  2. Key ($)
  3. Value (n)

Add a key-value pair.

This overload of the DICT.ADD function adds a string key and its corresponding numeric value to the dictionary. The key cannot be empty, but the value can.

If the key already exists in the dictionary, an exception is thrown.

ADD(#,$,#)

Signature: 'dict.add@#$#'

Parameters:

  1. Dictionary control pointer (#)
  2. Key ($)
  3. Value (n)

Add a key-value pair.

This overload of the DICT.ADD function adds a string key and its corresponding pointer to the dictionary. The key cannot be empty, but the value can.

If the key already exists in the dictionary, an exception is thrown.

ADD(#,$,$)

Signature: 'dict.add@#$$'

Parameters:

  1. Dictionary control pointer (#)
  2. Key ($)
  3. Value ($)

Add a key-value pair.

This overload of the DICT.ADD function adds a string key and its corresponding string value to the dictionary. The key cannot be empty, but the value can.

If the key already exists in the dictionary, an exception is thrown.

ADDORSET(#,n,n)

Signature: 'dict.addorset@#nn'

Parameters:

  1. Dictionary control pointer (#)
  2. Key (n)
  3. Value (n)

Add key-value pair even when key already exists.

This overload of DICT.ADDORSET function adds a key-value pair to a dictionary even if the key already exists. The key cannot be empty, but the value can. This method checks to see if the key exists in the dictionary, and if it does, it is equivalent to DICT.SET(dict#, key, value). Otherwise it is equivalent to DICT.ADD(dict#, key, value).

ADDORSET(#,n,#)

Signature: 'dict.addorset@#n#'

Parameters:

  1. Dictionary control pointer (#)
  2. Key (n)
  3. Value (#)

Add key-value pair even when key already exists.

This overload of DICT.ADDORSET function adds a key-value pair to a dictionary even if the key already exists. The key cannot be empty, but the value can. This method checks to see if the key exists in the dictionary, and if it does, it is equivalent to DICT.SET(dict#, key, value#). Otherwise it is equivalent to DICT.ADD(dict#, key, value#).

ADDORSET(#,n,$)

Signature: 'dict.addorset@#n$'

Parameters:

  1. Dictionary control pointer (#)
  2. Key (n)
  3. Value ($)

Add key-value pair even when key already exists.

This overload of DICT.ADDORSET function adds a key-value pair to a dictionary even if the key already exists. The key cannot be empty, but the value can. This method checks to see if the key exists in the dictionary, and if it does, it is equivalent to DICT.SET(dict#, key, value$). Otherwise it is equivalent to DICT.ADD(dict#, key, value$).

ADDORSET(#,$,n)

Signature: 'dict.addorset@#$n'

Parameters:

  1. Dictionary control pointer (#)
  2. Key ($)
  3. Value (n)

Add key-value pair even when key already exists.

This overload of DICT.ADDORSET function adds a key-value pair to a dictionary even if the key already exists. The key cannot be empty, but the value can. This method checks to see if the key exists in the dictionary, and if it does, it is equivalent to DICT.SET(dict#, key$, value). Otherwise it is equivalent to DICT.ADD(dict#, key$, value).

ADDORSET(#,$,#)

Signature: 'dict.addorset@#$#'

Parameters:

  1. Dictionary control pointer (#)
  2. Key ($)
  3. Value (#)

Add key-value pair even when key already exists.

This overload of DICT.ADDORSET function adds a key-value pair to a dictionary even if the key already exists. The key cannot be empty, but the value can. This method checks to see if the key exists in the dictionary, and if it does, it is equivalent to DICT.SET(dict#, key$, value#). Otherwise it is equivalent to DICT.ADD(dict#, key$, value#).

ADDORSET(#,$,$)

Signature: 'dict.addorset@#$$'

Parameters:

  1. Dictionary control pointer (#)
  2. Key ($)
  3. Value ($)

Add key-value pair even when key already exists.

This overload of DICT.ADDORSET function adds a key-value pair to a dictionary even if the key already exists. The key cannot be empty, but the value can. This method checks to see if the key exists in the dictionary, and if it does, it is equivalent to DICT.SET(dict#, key$, value$). Otherwise it is equivalent to DICT.ADD(dict#, key$, value$).

HASKEY(#,n)

Signature: 'dict.haskey@#n'

Parameters:

  1. Dictionary control pointer (#)
  2. Key (n)

This overload of DICT.HASKEY returns 1 if the numeric key is present in the dictionary, otherwise returns 0.

HASKEY(#,$)

Signature: 'dict.haskey@#$'

Parameters:

  1. Dictionary control pointer (#)
  2. Key ($)

This overload of DICT.HASKEY returns 1 if the string key is present in the dictionary, otherwise returns 0.

HASVALUE(#,n)

Signature: 'dict.hasvalue@#n'

Parameters:

  1. Dictionary control pointer (#)
  2. Value (n)

This overload of DICT.HASVALUE returns 1 if the numeric value is present in the dictionary, otherwise returns 0.

HASVALUE(#,$)

Signature: 'dict.hasvalue@#$'

Parameters:

  1. Dictionary control pointer (#)
  2. Value ($)

This overload of DICT.HASVALUE returns 1 if the string value is present in the dictionary, otherwise returns 0.

HASVALUE(#,#)

Signature: 'dict.hasvalue@##'

Parameters:

  1. Dictionary control pointer (#)
  2. Value (#)

This overload of DICT.HASVALUE returns 1 if the pointer is present in the dictionary, otherwise returns 0.

REMOVE(#,n)

Signature: 'dict.remove@#n'

Parameters:

  1. Dictionary control pointer (#)
  2. Key (n)

This overload of DICT.REMOVE removes the given numeric key and its associated value from the dictionary. No exception is thrown if the key is not in the dictionary. This is an O(1) operation.

REMOVE(#,$)

Signature: 'dict.remove@#$'

Parameters:

  1. Dictionary control pointer (#)
  2. Key ($)

This overload of DICT.REMOVE removes the given string key and its associated value from the dictionary. No exception is thrown if the key is not in the dictionary. This is an O(1) operation.

GET(#,n)

Signature: 'dict.get@#n'

Parameters:

  1. Dictionary control pointer (#)
  2. Key (n)

Returns a numeric value associated with the numeric key passed as parameter. If the key is not present in the dictionary an exception is raised.

GET(#,$)

Signature: 'dict.get@#$'

Parameters:

  1. Dictionary control pointer (#)
  2. Key ($)

Returns a numeric value associated with the string key passed as parameter. If the key is not present in the dictionary an exception is raised.

GET$(#,n)

Signature: 'dict.get$@#n'

Parameters:

  1. Dictionary control pointer (#)
  2. Key (n)

Returns a string value associated with the numeric key passed as parameter. If the key is not present in the dictionary an exception is raised.

GET$(#,$)

Signature: 'dict.get$@#$'

Parameters:

  1. Dictionary control pointer (#)
  2. Key ($)

Returns a string value associated with the string key passed as parameter. If the key is not present in the dictionary an exception is raised.

GET#(#,n)

Signature: 'dict.get#@#n'

Parameters:

  1. Dictionary control pointer (#)
  2. Key (n)

Returns a pointer associated with the numeric key passed as parameter. If the key is not present in the dictionary an exception is raised.

GET#(#,$)

Signature: 'dict.get#@#$'

Parameters:

  1. Dictionary control pointer (#)
  2. Key ($)

Returns a pointer associated with the string key passed as parameter. If the key is not present in the dictionary an exception is raised.

CLEAR(#)

Signature: 'dict.clear@#'

Parameters:

  1. Dictionary control pointer (#)

Clear all data in the dictionary.

The DICT.CLEAR function removes all keys and values from the dictionary. The dictionary count is set to 0. The dictionary capacity is also set to 0. This operation requires O(n) time, where n is the number of dictionary entries.

COUNT(#)

Signature: 'dict.count@#'

Parameters:

  1. Dictionary control pointer (#)

Number of entries in the dictionary.

DICT.COUNT returns the number of key-value pairs in the dictionary.

TRIMEXCESS(#)

Signature: 'dict.trimexcess@#'

Parameters:

  1. Dictionary control pointer (#)

Reduces the capacity of the dictionary to the current number of entries.

This function rehashes the internal dictionary table to save space. This is only useful after a lot of items have been deleted from the dictionary.

Dictionary Properties

Not applicable.

Dictionary Events

Not applicable.


Functions arguments support

The functions arguments support library is registered to the interpreter when the RegisterMeeseeksFuncs method is called.

This set of functions is auxiliary to the self contained Meeseeks engine library. The functions presented here are used to setup functions arguments when calling a script function through the Meeseeks engine library.

Library: fa

Namespace: 'fa.'

Self contained script engine functions arguments.

RESET(#)

Signature: 'fa.reset@#'

Parameters:

  1. Meeseeks engine control pointer (#)

Use RESET to empty the function arguments list before a function call through the self contained Meeseeks engine.

For example:

str$ := 'FUNCTION mul2(num)'
str$ /= '  PRINT '+str.chr$(39)+'This is inside the called function:'+str.chr$(39)+';num'
str$ /= '  RETURN num * 2'
str$ /= 'END FUNCTION'

m# := me.new#()
res := me.compile(m#, str$)
print 'Compiling result:';res
IF res = 0 THEN
  pf$ := me.asm$(m#)
  fa.reset(m#)
  fa.push(m#, 10)
  value := me.call(m#, stdout#(), 'mul2@n')
  print 'Returned value:';value
ELSE
  print me.error.line(m#)
  print me.error.msg$(m#)
END IF
me.free(m#)

PUSH(#,n)

Signature: 'fa.push@#n'

Parameters:

  1. Meeseeks engine control pointer (#)

Push a numeric argument to the self contained Meeseeks engine arguments stack.

For example:

str$ := 'FUNCTION mul2(num)'
str$ /= '  PRINT '+str.chr$(39)+'This is inside the called function:'+str.chr$(39)+';num'
str$ /= '  RETURN num * 2'
str$ /= 'END FUNCTION'

m# := me.new#()
res := me.compile(m#, str$)
print 'Compiling result:';res
IF res = 0 THEN
  pf$ := me.asm$(m#)
  fa.reset(m#)
  fa.push(m#, 10)
  value := me.call(m#, stdout#(), 'mul2@n')
  print 'Returned value:';value
ELSE
  print me.error.line(m#)
  print me.error.msg$(m#)
END IF
me.free(m#)

PUSH(#,#)

Signature: 'fa.push@##'

Parameters:

  1. Meeseeks engine control pointer (#)

Push a pointer argument to the self contained Meeseeks engine arguments stack.

PUSH(#,$)

Signature: 'fa.push@##'

Parameters:

  1. Meeseeks engine control pointer (#)

Push a string argument to the self contained Meeseeks engine arguments stack.

POP(#)

Signature: 'fa.pop@#'

Parameters:

  1. Meeseeks engine control pointer (#)

Pop a numeric value from the self contained Meeseeks engine arguments stack.

POP#(#)

Signature: 'fa.pop#@#'

Parameters:

  1. Meeseeks engine control pointer (#)

Pop a pointer value from the self contained Meeseeks engine arguments stack.

POP$(#)

Signature: 'fa.pop$@#'

Parameters:

  1. Meeseeks engine control pointer (#)

Pop a string value from the self contained Meeseeks engine arguments stack.


Self contained Meeseeks engine

The complete Meeseeks engine is wrapped in the form of a library, the engine can create independent copies of it through the user scripts. These copies can compile new scripts stored in text files, string variables or even string list variables. The result produced by the processing of such child scripts could be used by the master script, the memory used by the Meeseeks engine variable could be freed when is not necessary to use it anymore.

Library: me

Namespace: 'me.'

Self contained script engine.

NEW#()

Signature: 'me.new#@'

Parameters: None.

Use NEW to create and initialize a new instance of a Meeseeks engine. The function returns the identity pointer to the newly created engine.

FREE(#)

Signature: 'me.free@#'

Parameters:

  1. Meeseeks engine control pointer (#)

Forces the freeing of the Meeseeks engine control identified by the pointer in the parameter.

str$ := 'FUNCTION mul2(num)'
str$ /= '  PRINT '+str.chr$(39)+'This is inside the called function:'+str.chr$(39)+';num'
str$ /= '  RETURN num * 2'
str$ /= 'END FUNCTION'

m# := me.new#()
res := me.compile(m#, str$)
print 'Compiling result:';res
IF res = 0 THEN
  pf$ := me.asm$(m#)
  fa.reset(m#)
  fa.push(m#, 10)
  value := me.call(m#, stdout#(), 'mul2@n')
  print 'Returned value:';value
ELSE
  print me.error.line(m#)
  print me.error.msg$(m#)
END IF
me.free(m#)

It is not necessary to call this function. Meeseeks automatically cleans all the controls created during the program execution, after the program is finished.

COMPILE(#,$)

Signature: 'me.compile@#$'

Parameters:

  1. Meeseeks engine control pointer (#)
  2. Script source code ($)

After successfully create a new instance of a Meeseeks engine, call the COMPILE function in order to compile a script code stored at the second parameter. If the compilation is successful, the engine instance will hold the intermediate code that can be executed when demanded.

This function returns zero in case of a successful compilation, different of zero otherwise.

RUN(#,#)

Signature: 'me.run@##'

Parameters:

  1. Meeseeks engine control pointer (#)
  2. Output control pointer (#)

If the source script managed by the Meeseeks engine instance was successfully compiled, use the function RUN to execute it. It's necessary to define the output control at the second parameter. This control could be a pointer to a Meeseeks stringlist control, or could be used a function that points to a Delphi TStringList object.

ERROR.POS(#)

Signature: 'me.error.pos@#'

Parameters:

  1. Meeseeks engine control pointer (#)

In case the script source code used with the COMPILE function has a syntax error, the error absolute position can be identified using ERROR.POS.

ERROR.LINE(#)

Signature: 'me.error.line@#'

Parameters:

  1. Meeseeks engine control pointer (#)

In case the script source code used with the COMPILE function has a syntax error, the line where the error occurred can be identified using ERROR.LINE.

ERROR.MSG$(#)

Signature: 'me.error.msg$@#'

Parameters:

  1. Meeseeks engine control pointer (#)

In case the script source code used with the COMPILE function has a syntax error, the error message can be returned using ERROR.MSG$.

ASM$(#)

Signature: 'me.asm$@#'

Parameters:

  1. Meeseeks engine control pointer (#)

Returns the text of the postfix intermediate code produced after a successful compilation in the Meeseeks engine pointed by the parameter.

ASM(#,$)

Signature: 'me.asm@#$'

Parameters:

  1. Meeseeks engine control pointer (#)
  2. Intermediate code text ($)

Sets the intermediate code for the engine instance pointed by the first parameter. If this code is set directly in the engine instance, the RUN function can be called without a call to COMPILE.

CALL(#,#,$)

Signature: 'me.call@##$'

Parameters:

  1. Meeseeks engine control pointer (#)
  2. Output control pointer (#)
  3. Function signature ($)

Call a compiled script function that returns a number. The function arguments (if present), must be set using the function arguments support library.

CALL#(#,#,$)

Signature: 'me.call#@##$'

Parameters:

  1. Meeseeks engine control pointer (#)
  2. Output control pointer (#)
  3. Function signature ($)

Call a compiled script function that returns a pointer. The function arguments (if present), must be set using the function arguments support library.

CALL$(#,#,$)

Signature: 'me.call$@##$'

Parameters:

  1. Meeseeks engine control pointer (#)
  2. Output control pointer (#)
  3. Function signature ($)

Call a compiled script function that returns a string. The function arguments (if present), must be set using the function arguments support library.

CALL.RESULT(#)

Signature: 'me.call.result@#'

Parameters:

  1. Meeseeks engine control pointer (#)

Returns the last result obtained by a call to CALL.

CALL.RESULT#(#)

Signature: 'me.call.result#@#'

Parameters:

  1. Meeseeks engine control pointer (#)

Returns the last result obtained by a call to CALL#.

CALL.RESULT$(#)

Signature: 'me.call.result$@#'

Parameters:

  1. Meeseeks engine control pointer (#)

Returns the last result obtained by a call to CALL$.

GET(#,$)

Signature: 'me.get@#$'

Parameters:

  1. Meeseeks engine control pointer (#)
  2. Global var name ($)

Gets the numeric value stored at the global var identified by the second parameter.

GET#(#,$)

Signature: 'me.get#@#$'

Parameters:

  1. Meeseeks engine control pointer (#)
  2. Global var name ($)

Gets the pointer value stored at the global var identified by the second parameter.

GET$(#,$)

Signature: 'me.get$@#$'

Parameters:

  1. Meeseeks engine control pointer (#)
  2. Global var name ($)

Gets the string value stored at the global var identified by the second parameter.

RTEXCEPT(#)

Signature: 'me.rtexcept@#'

Parameters:

  1. Meeseeks engine control pointer (#)

This function returns one (1) if a runtime excpetion occurred during the execution of the script in the specified engine. Zero (0) otherwise.

RTEXCEPT.MSG$(#)

Signature: 'me.rtexcept.msg$@#'

Parameters:

  1. Meeseeks engine control pointer (#)

If a runtime exception occurred during the execution of the script in the engine instance, this function can be used to return the text of the occurred exception.

Self contained Meeseeks engine register libraries

The functions libraries can or cannot be included in a self contained Meeseeks engined. Each one of the libraries hold a set of functions focused at a specific type of problem solving. In order to spare memory, the libraries could be included according to the type of processing desired in the source script.

Library: reg

Namespace: 'reg.'

The libraries register functions always return 1.

ME(#)

Signature: 'reg.me@#'

Parameters:

  1. Meeseeks engine control pointer (#)

This function register the Meeseeks engine self contained functions library to the specified Meeseeks engine control pointer.

MATH(#)

Signature: 'reg.math@#'

Parameters:

  1. Meeseeks engine control pointer (#)

This function register the math library to the specified Meeseeks engine control pointer.

STR(#)

Signature: 'reg.str@#'

Parameters:

  1. Meeseeks engine control pointer (#)

This function register the string library to the specified Meeseeks engine control pointer.

STD(#)

Signature: 'reg.std@#'

Parameters:

  1. Meeseeks engine control pointer (#)

This function register the standard library to the specified Meeseeks engine control pointer.

SYS(#)

Signature: 'reg.sys@#'

Parameters:

  1. Meeseeks engine control pointer (#)

This function register the system library to the specified Meeseeks engine control pointer.

MS(#)

Signature: 'reg.ms@#'

Parameters:

  1. Meeseeks engine control pointer (#)

This function register the memory stream library to the specified Meeseeks engine control pointer.

SS(#)

Signature: 'reg.ss@#'

Parameters:

  1. Meeseeks engine control pointer (#)

This function register the string stream library to the specified Meeseeks engine control pointer.

FS(#)

Signature: 'reg.fs@#'

Parameters:

  1. Meeseeks engine control pointer (#)

This function register the file stream library to the specified Meeseeks engine control pointer.

STRS(#)

Signature: 'reg.strs@#'

Parameters:

  1. Meeseeks engine control pointer (#)

This function register the string list library to the specified Meeseeks engine control pointer.

DICT(#)

Signature: 'reg.dict@#'

Parameters:

  1. Meeseeks engine control pointer (#)

This function register the dictionary (hash map) library to the specified Meeseeks engine control pointer.