Bridge Script
Paradigm | Imperative (procedural), structured |
---|---|
Designed by | Mikhail Botcharov[1] |
Developer | Mikhail Botcharov[1] |
First appeared | 2019 |
Typing discipline | Static, strongly typed, manifest, nominal |
OS | Cross-platform |
Filename extensions | .bridge |
Website | http://www.bridgescript.com/ |
Influenced by | |
C language, JavaScript |
Search Bridge Script on Amazon.
Bridge script is statically typed, platform independent programming language. It's syntactically similar to C language . Bridge script does not have any built-in APIs in the interpreter. It provides mechanism to invoke external functions by defining a bridge (Library type) to invoke. Bridge script syntax derived from C syntax with simplicity in mind and built-in memory management.
Syntax[edit]
Types relationship[edit]
All basic Bridge script types have one to one mapping to C types.
Bridge script | C | size (bytes) |
---|---|---|
bool
|
char
|
1 |
i8
|
char
|
1 |
ui8
|
unsigned char
|
1 |
i16
|
short int
|
2 |
ui16
|
unsigned short int
|
2 |
i32
|
long int
|
4 |
ui32
|
unsigned long int
|
4 |
i64
|
long long int
|
8 |
ui64
|
unsigned long long int
|
8 |
float
|
float
|
4 |
double
|
double
|
8 |
For constant integer values HEX and Binary formats are provided.
HEX prefixes: 0X, 0x:
i32 v0 = 0xABCD1234 v1 = 0Xaaaa1111;
HEX postfixes: H, h:
ui8 v0 = A1H v1 = abh;
Binary postfixes: B, b:
ui8 v0 = 001101B v1 = 101b;
Float and double formats are the same as in C:
double d0 = -.25e-3, d1 = 0.002E-22;
float f0 = 1.5, f1 = 1.0E+3;
There is one built-in type that does not have corresponding C type – string
type:
string str = "This is a string";
Structure type[edit]
struct
– this keyword is used to declare structure definition.
struct MyStruct {
ui32 v0;
struct _SubStruct {
bool _v0;
i64 _v1;
} v1;
_SubStruct v2;
} var0;
MyStruct var1;
Arrays[edit]
Arrays declarations (where Type is any Bridge script type except array):
array<Type>
– declares array without size.
array<Type, dim>
– declares array of size dim.
array<Type, dim0, dim1>
– declares 2-dimensional array.
Array can be declared with any number of dimensions. Dimension of array can be an expression evaluated at run time, in this case only one-dimensional array is allowed. Expression based dimension allows dynamically allocate array at run-time.
function array<ui8>@ AllocateArray(ui32 size) {
array<ui8, size> arr;
return arr;
}
array<ui8> arr0 @= AllocateArray(10);
array<ui8> arr1 @= AllocateArray(20);
array<ui32, 10> arr;
array<ui32, 2, 2> arr2;
arr2[0, 0] = 0;
arr2[0, 1] = 1;
arr2[1, 0] = 2;
arr2[1, 1] = 3;
arr[1] = arr2[0, 1];
Dynamic dimension as an expression:
array<i16, 2 * foo(n)> arr;
string
variable can be assigned to array
variable of type i8
or ui8
and vice versa, array
must be static with at least one dimension.
array<ui8, 5> arr0;
string str = "Test";
arr0 = str;
array<ui8, 4> arr1;
arr1[0] = 0x41;
arr1[1] = 0x42;
arr1[2] = 0x43;
str = arr1;
Functions[edit]
Function definition syntax:
function
Type FooName([arguments if any]) { return
value; }
Where Type is function return type, function
can have any number of arguments and return statement is optional.
function ui32 GetSum(ui32 a0, ui32 a1) {
return a0 + a1;
}
Function variable declaration:
function<GetSum> fn;
array<function<GetSum>, 4> fnArr;
function<GetSum> fn0 = fn;
Uninitialized function variable is set to function instance by default.
Any function can be called implicitly:
- when returned by a function call:function ui32 F0(ui32 a) { return a + 1; }
function ui32 F1(ui32 a) { return a + 2; }
function function<F0> F(ui32 a) { if (a == 0) return F0; else return F1; }
F(0)(10);
F(1)(10); - when function is in array:array<function<F0>, 2> fn;
fn[0] = F0;
fn[1] = F1;
fn[0](10);
fn[1](10);
References[edit]
All variables in the script are references (also see Special operators), however, to pass by reference you must use reference operator.
function ui32@ GetSum(ui32@ a0, ui32@ a1) {
return a0 + a1;
}
Passing a variable by double reference allows to overwrite it's reference.
function bool GetRef(ui32@@ a0) {
ui32 _var = 100;
a @= _var; // reference assignment operator
return true;
}
ui32 var = 10;
GetRef(var); // this function call will overwrite var reference by reference to _var
Another way to pass a reference by reference is to declare an array of reference type of size 1 and pass it by reference.
struct ST {
array<ui32@, 4>@ arr;
ui64 v64;
};
array<ST@, 1> refSt;
refSt[0].v64 = 0x0000000087654321;
function ui32 GetRef(array<ST@, 1> @ref) {
ST st;
st.v64 = 0x1234567800000000;
ui32 i = 0;
for (; i < sizeof(st.arr) / sizeof(i); ++i) {
st.arr[i] = (i + 1) * 10;
}
ref[0] @= st;
return 0;
}
GetRef(refSt);
Bridge script function and C function relationship[edit]
Brdge script | C |
---|---|
Function definition:
|
Function definition:
|
Function variable declaration:
|
Function variable declaration:
|
Function invocation:
|
Function invocation:
|
Library type (Bridge)[edit]
Library type allows dynamic linking with external library. If external function return type is void then use ui32
as return type for library function description. To describe library function arguments only types of arguments are allowed.
Either library name or library path is allowed.
lib ("kernel32.dll") {
ui32 GetModuleHandleA(array<ui8>@); // HMODULE GetModuleHandleA(LPCSTR lpModuleName);
} kernel;
array<ui8> moduleName @= str2arr("user32.dll");
ui32 handle = kernel.GetModuleHandleA(moduleName);
Built-in functions[edit]
– this function converts script's string to array of bytes.
array
<ui8
>@ str2arr
(string
@)
– this function converts script's string to array of words (as Unicode).
array
<ui16
>@ str2warr
(string
@)
– this function converts array of bytes to string.
string
@ arr2str
(array
<ui8
>@)
– this function converts array of words (as unicode) to string.
string
@ warr2str
(array
<ui16
>@)
Operators[edit]
These operators have the same functionality as in C.
Arithmetic operators:
+, ++, +=, -, --, -=, *, *=, /, /=, %, %=, =
Logical operators:
||, &&, !
Bitwise operators:
&, |, ~, ^, ^=,>>, <<
Comparison operators:
==, !=, <, <=, >, >=
Special operators[edit]
@=
– this is reference assignment operator.
ui32 v0 = 10;
ui32 v1 @= v0; // now both variables point to the same memory
@
– this operator is used to pass/return a variable to/from a function and to declare structure member variables.
function ui32@ Get(ui32 a0, ui32@a1, ui32@@ a2) {
a2 @= a1;
return a0;
}
struct A {
ui32@ v32;
i8@ v0, v1, v2;
};
lock()
– this operator locks memory which variable is referenced to. This operator should be used when you are passing local variable to asynchronous C function and caller goes out of scope. For example calling CreateThread() and passing local data as a parameter to the thread releases local variable when caller goes out of scope, hence you need to lock it and then unlock it in the thread.
unlock()
– this operator unlocks memory locked by lock()
.
function ui32 Callback(array<ui8>@ a) {
return a[0];
}
struct MyData {
ui32 v0;
function<Callback> fn;
array<ui8, 4> v1;
};
function ui32 ThreadFoo(MyData@ arg) {
unlock(arg);
return arg.fn(arg.v1);
}
struct SECURITY_ATTRIBUTES {
ui32 nLength;
ui32 lpSecurityDescriptor;
bool bInheritHandle;
};
lib("kernel32.dll") {
ui32 CreateThread(SECURITY_ATTRIBUTES@, ui32, function<ThreadFoo>, MyData@, ui32, ui32@);
ui32 WaitForMultipleObjects(ui32, array<ui32>@, ui32, ui32);
ui32 CloseHandle(ui32);
} kernel;
SECURITY_ATTRIBUTES sa;
MyData data;
ui32 threadId;
data.v1[0] = 10;
array<ui32, 1> handle;
handle[0] = kernel.CreateThread(sa, 0, ThreadFoo, lock(data), 0, threadId);
kernel.WaitForMultipleObjects(1, handle, true, -1);
kernel.CloseHandle(handle[0]);
sizeof()
– this operator returns size of memory allocated for that variable, it's useful to get size of a struct and an array, if array is dynamic and allocated externally this operator will return 0.
cast<Type>()
– this is typecast operator. This is very powerful operator and it breaks memory constrains once you typecast a variable static type paradigm is broken.
struct A {
ui32 v0;
ui32 v1;
} a;
a.v0 = 10;
a.v1 = 20;
ui64 v @= cast<ui64>(a);
array<ui8, 4> arr1dim;
array<ui8, 2, 2> arr2dim;
ui32 i = 0;
for(; i < 4; ++i) {
arr1dim[i] = 1;
}
struct Typecasted {
ui8 v0, v1, v2, v3;
} tc;
tc @= cast<Typecasted>(arr1dim); // now both variables points to the same memory
arr2dim = arr1dim; // copy by value
array<ui8> arrNodim @= arr1dim; // now arrNodim points to the same memory
Statements[edit]
if, else, for, while, break, continue, switch, case, return
– these statements have the same meaning as in C.
include
statement:
include "script_to_include.bridge";
include statement path is relative to the current script.
Bridge script references and C pointers relationship[edit]
Reference operator has the same meaning as a pointer in C, it's used to declare member variable of a structure or to pass a variable by reference to a function.
Bridge script | C |
---|---|
|
|
Run-time error handling[edit]
If a run-time error occurs an error object is thrown, to catch it use error
statement – error(e){}
Error object data members:
name
– name of the error, type is string
.
line
– line number where error occurred, type is ui32
.
position
– first character position of the symbol, type is ui32
.
file
– file path, type is string
.
trace
– stack trace, type is string
(new line separated strings).
symbol
– symbol name, type is string
.
function i8 f0() {
ui32 v0 = 100, v1 = 0;
v0 = v0 / v1;
}
function i8 f1() {
f0();
}
f1();
error (e) {
string err = e.name;
string trace = e.trace;
}
Bridge script examples[edit]
Visual debugger[edit]
Bridge script interpreter provides debugging facilities through debugging API. I created Bridge debugger for Microsoft Windows(c) platform. It exposes all standard debugging features using GUI. Bridge debugger has built-in interpreter and provides such features as:
- compile/decompile script
- edit script (this feature is limited to simple editing, it does not replace editing tool, but rather nice to have if you need to fix your code)
- file view/browser
- debugger actions: run, step over, step in, step out, pause and stop
- set/delete breakpoints
- breakpoints view
- function view/browser (available when script is running)
- global variables view (available when script is running)
- threads view (available when script is running)
- thread stack and variables view for each running thread (available when script is running)
- build and debug output views
Compiled Bridge script can be debugged without decompiling it.
See also[edit]
- C programming language
- C variable types and declarations
- Operators in C and C++
- C standard library
- List of C-family programming languages (C-influenced languages)
References[edit]
- ↑ 1.0 1.1 Botcharov, Mikhail. "Bridge Script".
This article "Bridge Script" is from Wikipedia. The list of its authors can be seen in its historical and/or the page Edithistory:Bridge Script. Articles copied from Draft Namespace on Wikipedia could be seen on the Draft Namespace of Wikipedia and not main one.