The tables below summarize how BlingoEngine converts Lingo syntax into C#.
| Lingo example | C# equivalent |
|---|---|
-- comment |
// comment |
on handler a, b … end |
void Handler(type a, type b) { … } |
global gVar |
GlobalVars singleton injected via DI |
property myValue |
class field/property |
me |
this |
void |
null |
sprite(n).locH |
Sprite(n).LocH |
sprite(n).member = member("Name") |
Sprite(n).SetMember("Name"); |
member("Name").text |
Member<BlingoMemberText>("Name").Text |
the mouseH |
_Mouse.MouseH |
the actorList.append(me) |
_Movie.ActorList.Add(this) |
script("Class").new(args) |
new Class(args) |
sendSprite 2, #doIt |
SendSprite<B2>(2, b2 => b2.doIt()); |
myMovieHandler |
CallMovieScript<M1>(m1 => m1.myMovieHandler()); |
| Lingo example | C# equivalent |
|---|---|
repeat with i = 1 to n |
for (int i = 1; i <= n; i++) |
repeat with item in list |
foreach (var item in list) |
repeat while cond |
while (cond) |
repeat until cond |
do { … } while (!cond) |
repeat forever |
while (true) |
exit repeat |
break; |
exit repeat if cond |
if (cond) break; |
next repeat |
continue; |
next repeat if cond |
if (cond) continue; |
if a > b then … end if |
if (a > b) { … } |
case v of … end case |
switch (v) { … } |
exit |
return; |
[1,2,3] |
new[] { 1, 2, 3 } |
"A" & "B" |
"A" + "B" |
<> (not equal) |
!= |
voidp(x) |
x == null |
Additional notes:
- Lingo lists and collections are 1‑based, whereas C# arrays and lists are 0‑based.
- Lingo requires
thenandend ifaround conditionals; C# uses curly braces. - To access text members, use the generic
Member<T>helper, e.g.member("Name").textbecomesMember<BlingoMemberText>("Name").Text.
Lingo scripts are instantiated at runtime using the script("Class").new(args)
syntax. When converted to C#, each script becomes a class whose constructor can
accept dependencies. The engine resolves these dependencies through the
dependency injection container when the script is created.
// Example parent script
public class BlockParent : BlingoParentScript
{
private readonly GlobalVars _global;
// IBlingoMovieEnvironment is provided by the runtime; GlobalVars comes
// from the service container
public BlockParent(IBlingoMovieEnvironment env, GlobalVars global)
: base(env)
{
_global = global;
}
}Scripts are registered with the container using helpers such as
AddScriptsFromAssembly() or AddMovieScript<T>(). When Lingo code executes
new(script "Block"), BlingoEngine retrieves the constructor from the
container and supplies any required services automatically.
In Lingo you create new members using the newMember command. The type symbol indicates what kind of member to create.
-- create a new bitmap cast member
newBitmap = _movie.newMember(#bitmap)
newBitmap.name = "Background"
In C#, use the New factory on IBlingoMovie to create typed members:
// equivalent to the Lingo example above
var newBitmap = _movie.New.Bitmap(name: "Background");The factory exposes helper methods for each member type, such as Bitmap(), Sound(), FilmLoop() and Text(). Optional arguments let you specify the cast slot or member name.
Lingo's put syntax is used for assignment across a wide range of targets:
put "Hello" into field "Status"
put 100 into sprite(3).locH
put 42 into myList[2]
In Lingo, if the target does not exist (e.g., a missing field), it fails silently.
To match that behavior in C#, BlingoEngine introduces safe assignment helpers.
| Lingo | C# |
|---|---|
put 100 into x |
x = 100; |
put "Hi" into field "Greeting" |
PutTextIntoField("Greeting", "Hi"); |
put 100 into sprite(3).locH |
Sprite(3).LocH = 100; |
put 42 into myList[2] |
myList.SetAt(2, 42); |
PutTextIntoField("Greeting", "Hello");This method attempts to locate a field member and assign the text, but does nothing if the field is missing, just like Lingo.
protected void PutTextIntoField(string name, string text)
{
TryMember<IBlingoMemberField>(name, field => field.Text = text);
}To safely access any member (e.g., bitmap, field, text), use the Action<T> overload:
TryMember<IBlingoMemberText>("Title", m => m.Text = "Welcome");This form avoids explicit null checks and keeps the call concise.
TryMember<T>(string name, int? castLib = null, Action<T>? action = null)This method:
- Returns
nullif the member is not found - Executes the action if the member exists
You can create safe helpers for other member types, e.g.:
protected void PutSoundInto(string name, IBlingoSoundData sound)
{
TryMember<IBlingoMemberSound>(name, m => m.Sound = sound);
}| Pattern | Use |
|---|---|
| Direct assignment | For local variables or known safe references |
PutTextIntoField(name, value) |
For field text, silent on failure |
TryMember<T>(..., action) |
For concise safe access to members |
SafePut<T>() (optional) |
For generalized logic via delegates |
This ensures Lingo compatibility without throwing exceptions and keeps behavior fail-safe, just like in Director.