Introduction
C-Talk is interpreted scripting language with C-like syntax and dynamic type
checking. Variables in C-Talk have no type. So there is no compile time type
checking in C-Talk, all checking is performed at runtime.
To preserve reference integrity, explicit memory deallocation is prohibited
in C-Talk, unused objects are automatically deallocated by garbage collector.
C-Talk support integer, real, string, associative array, thread and mutex types.
There is no structures, classes, unions and pointers. Structures can be
emulated by associative array, for example the expression x.foo
is
equivalent to x["foo"]
and access element of associative array with
key "foo"
.
C-Talk provides very simple interface with C and C++. Programmer can easily
define various primitives which can be called from the C-Talk as normal
functions.
C-Talk is intented to be used in the same area as Perl, VB-Script, Java-Script
languages. It is for the people who are familiar with C and prefer it's syntax
to something else. The other advantage of C-Talk is that it is open source free
software. It is distributed under MIT license - almost no restrictions on
using this language in any project (unlike GPL). Also C-Talk is very
simple and compact language, only - 6000 lines of code.
It very simple to extend the language with new primitives and types
needed for your application.
Syntax
The syntax of C-Talk language is similar with C/Java.
program: import-list {stmt}
import-list: "import" module {"," module}
module: identifier
func-def: "function" func-name "(" params-list ")" block-stmt
func-name: identifier
params-list: empty | intentifier { "," intentifier }
stmt: ";" | expr ";" | block-stmt
| while-stmt | do-while-stmt | for-stmt | if-stmt | break-stmt | continue-stmt
| return-stmt | throw-stmt | try-catch-stmt
while-stmt: "while" "(" condition ")" stmt
do-while-stmt: "do" stmt "while" "(" condition ")" ";"
for-stmt: "for" "(" opt-expr ";" opt-expr ";" opt-expr ")" stmt
if-stmt: "if" "(" condition ")" stmt ["else" stmt]
condition: expr
opt-expr: empty | expr
break-stmt: "break" ";"
continue-stmt: "continue" ";"
throw-stmt: "throw" expr ";"
return-stmt: "return" opt-expr ";"
try-catch-stmt: "try" stmt "catch" "(" exception-var ")" stmt
exception-var: identifier
block-stmt: "{" { stmt } "}"
expr: literal | func-call | start-thread | binary-expr | unary-expr |
"(" expr ")" | | variable | index-expr | env-var
literal: string | integer | real | array-constructor
variable: identifier
index-expr: expr "[" expr "]" | expr "." identifier
env-var: "$" identifier
array-constructor: "[" empty | array-elem { "," array-elem } "]"
array-elem: expr ":" expr
func-call: expr "(" expr-list ")"
start-thread: "par" func-call
expr-list: empty | expr { "," expr }
binary-expr: expr bin-op expr
unary-expr: unary-op expr
bin-op: "+" | "-" | "/" | "*" | ">>" | "<<" | ">>>" | "|" | "&" | "^" |
| "+=" | "-=" | "/=" | "*=" | ">>=" | "<<=" | "|=" | "&=" | "^=" | "="
| "==" | ">" | ">=" | "<" | "<=" | "!="
unary-op: "~" | "!" | "-" | "+"
Syntax of identifiers, comments, string, integer and real
literals is the same as in C, with the exception that in C-Talk there is no
difference between character and string literals.
The table below summarize differences between C and C-Talk syntax
- C-Talk has no preprocessor
- C-Talk has
"function"
keyword
- C-Talk treats " and ' equally, so
"ok"
and 'ok'
means the same string character constant
- C-Talk program consist of modules loaded by "import" construction
- C-Talk expression
a.x
is syntax sugar for a["x"]
and is treated as associative
array access operation
- C-Talk variable has no types - so no function return type, formal parameter type or variable type should not (and can not) be specified.
- C-Talk has no goto construction
- C-Talk has
"par"
construction for starting thread
Types
C-Talk provides the following types
- Integer (32 bit signed integer type with operations similar to C, but shift right operation is unsigned - doesn't replicate the sign bit)
- Real (32 bit ANSI double type)
- String (+ operator)
- Associative array (index of the array can be object of any type, for example a["foo"])
- Raw pointer (used only by primitives, C-Talk can only store such value to variables
and pass them to the functions, example is C FILE* type)
- Thread type (with associated FIFO queue)
- Function type (function is first class value and can assigned to variable
and passed as parameter to other function)
String operations
Example | Description |
s = "ok" | relation operations |
s + "cxx" | concatenation of strings |
indexOf(s, "xxx") | index of first occurrence of substring |
lastIndexOf(s, "xxx") | index of first occurance of substring |
substring(s, star | os, end-pos) - extract substring |
toLower(s) | convert to lower case |
toUpper(s) | convert to upper case |
trim(s) | remove trailing spaces |
startsWith(s, prefix) | check if string has specified prefix |
endsWith(s, suffix) | check if string has specified suffix |
string(x) | convert argument to string |
integer("100") | convert string to integer |
real("5.5") | convert string to real |
length(x) | length of string |
Arrays operations
a[x] = y | store element |
x = a[y] | fetch element |
x = [0:"red", 1:"green", 2:"blue"] | array constructor |
x += ['one':1, 'two':2] | concatenate arrays |
a - x | remove element(s) from the array, x can be array or key of element |
length(a) | length of array |
cloneArray(a) | create a copy of the array |
deleteArray(a) | deallocate array |
clearArray(a) | truncate array to size 0 |
getKeys(a) | get array of keys |
Mutex operations
m = createMutex() | create mutex |
lockMutex(m) | lock mutex |
unlockMutex(m) | unlock mutex |
deleteMutex(m) | delete mutex |
Thread operations
m = getMessage(t) | get message from thread queue |
putMessage(t, m) | put message in thread queue |
t = currentThread() | get reference to current thread |
IO operations:
f = createFile("test.txt", "r") | create file with specified name and access mode |
deleteFile(f) | close file |
flushFile(f) | flush buffers |
printFile(f, "x=", x) | print varying number of arguments to the file |
printlnFile(f, "x=", x) | the same as above but append '\n' |
print("x=", x) | print varying number of arguments to the console |
println("x=", x) | the same as above but append '\n' |
input("> ") | input string from console or specified file, the single optional argument of this function should be file or propmt string |
Type check operations:
isString(x) | checks if argument is string |
isArray(x) | checks if argument is array |
isInteger(x) | checks if argument is integer |
isReal(x) | checks if argument is real |
isNull(x) | checks if argument is null |
isFunction(x) | checks if argument is function |
isPrimitive(x) | checks if argument is primitive |
isMutex(x) | checks if argument is mutex |
isFile(x) | checks if argument is file |
getType(x) | returns argument's type code (integer as defined in ctalk.h) |
getTypeName(x) | returns argument's type name |
Miscellaneous
rc = execute("cp f.dbs f.sav") | execute shell command and wait for result |
t = time() | get current system time (seconds) |
assert(i >= 0) | check the assert condition, throw exception if predicate is false |
loadDLL("test.dll") | load dynamic linking library |
loadModule("test.ctk") | load C-Talk module |
chdir(path) | change current directory |
dir = pwd() | get name of working directory |
sleep(seconds) | sleep specified amount of seconds |
options("socket") | when called without argumetns, returns array of command line options, or gets value of specified option |
printExceptionStackTrace() | print stack trace for the frame where exception was thrown,
till the frame where it is catched |
Program execution
C-Talk is command line tool which accepts list of files with C-Talk programs
as parameters:
$ ctalk file-1 file-2 ...
The loaded module is first compiled to byte code and the all global-level
statements are executed. For example, the result of following program execution:
hello = "Hello World";
foo(hello);
foo(s) {
println(s);
}
will be printing of "Hello World" line at the screen
C-Talk primitives
C-Talk system library includes only basci set of functions.
It makes it possible to make C-Talk distribution very compact.
It was inteded that particular extensions will be added to C-Talk using primitives mechanism.
Most of C-Talk functions will be implemented in C/C++.
C-Talk provides special library for mapping C-Talk type to C++ types. C-Talk primitives can accept varying
number of arguments. To declare C-Talk primitive, C programmer should define
the function:
CtkObject foo_func(int nArgs, CtkObject args[]) { ... }
REGISTER(foo_func, "foo");
The code above defines the function "foo_func" and registers it as C-Talk
primitive "foo". Now C-Talk program can call "foo()" function in the same way
as it was declared in C-Talk.
The C-Talk C-interface library provides methods for creating objects of C-Talk
types, converting CtkObject
with type checking to primitive C
types, operations with C-Talk types (such as strings, arrays and mutexes),
throwing C-Talk exceptions. Macros IS_XXX can be used to check object type,
macros TO_XXX perform conversion to the specified type or throw exception if type
doesn't match, macro MAKE_XXX create object with specified type and value,
mcaros CHECK_PRIMITIVE_N_ARGS and CHECK_PRIMITIVE_ARGUMENT can be used to check number
of passed arguments and type of each argument.
C-Talk provide even more convinient weay for checking types passed arguments.
Function ctkParseArguments
takes format string and optional list of arguments palceholder and
perform necessary checks and conversions.
void ctkParseArguments(int nArgs, CtkObject* args, char const* format, ...);
- Parameters:
- nArgs - number of arguments passed to the function (first parameter of any primitive)
- args - array of arguments passed to the function (second parameter of any primitive)
- format - format string specifying number and types of expected arguments.
In format string each character describes one correpondent parameter.
Upercase character in format string cause checking of the argument type and copying CtkObject to the placeholder.
Lowercase character in format string cause checking and storing arguments in native C format.
',' character in format string split mandatory and optional parameters.
If type or number of parameters doesn't match, exception is thrown.
Format symbol | Expected C-Talk type of argument | Type of placeholder for parameter value |
o | any | CtkObject |
i | CTK_INTEGER | ctk_integer |
r | CTK_REAL | ctk_real |
p | CTK_RAW_POINTER or CTK_NULL | void* |
P | CTK_RAW_POINTER | CtkObject |
s | CTK_STRING or CTK_NULL | char* |
S | CTK_STRING | CtkObject |
a | CTK_ARRAY or CTK_NULL | CtkArray* |
A | CTK_ARRAY | CtkObject |
f | CTK_FILE or CTK_NULL | CtkFile* |
F | CTK_FILE | CtkObject |
m | CTK_MUTEX or CTK_NULL | CtkMutex* |
M | CTK_MUTEX | CtkObject |
t | CTK_THREAD or CTK_NULL | CtkThread* |
T | CTK_THREAD | CtkObject |
l | CTK_FUNCTION or CTK_NULL | CtkFunction* |
L | CTK_FUNCTION | CtkObject |
u | CTK_USER_TYPE or CTK_NULL | void* |
U | CTK_USER_TYPE | CtkObject |
Example:
CtkObject myPrimitive(int nArgs, CtkObject* args) {
char* s;
ctk_integer i;
ctk_real r;
CtkObject o;
ctkParseArguments(nArgs, args, "siro", &s, &i, &r, &o);
...
}