[This is preliminary documentation and subject to change]
Liogo is a Logo compiler for .NET. So when you launch the Liogo compiler (with the LIOGOC command line or with LIOGOI) on a Logo script, Liogo:
Finally, you just have to call your EXE to run your Logo code. Note that the first time your EXE is launch, the .NET Runtime automatically call its Just-in-time compiler to compile the IL p-code to processor native assembly language.
May be you think that Liogo is a Logo to C# translator ? In a sense you're right but remind you that at the end of the process, Logo code is really translated to the processor machine language !
For debugging reason, Liogo let you see a part of the building process. For example, build again our first sample "fact.lgo" with the "/debug" option:
;-- Compute Factorial to fact :n if equal? :n 1 [output 1] output :n * fact :n - 1 end print fact 1 print fact 4
Then open in your favorite editor the file named "fact.exe.cs". This file is the C# equivalent to the Liogo CODEDOM structure:
// // Source generated by LIOGO compiler on 18/06/2006 08:32:42 // namespace LIOGO.Framework { using System; using System.Reflection; using LIOGO.Core; [LogoLibrary()] public class fact_dlgo { static LogoNumber number_1 = new LogoNumber(1); static LogoNumber number_4 = new LogoNumber(4); [LogoProcedure()] public static ILogoValue fact(ILogoValue n) { LogoContext.BeginProcedure("fact", n); LogoContext.DeclareVar("n", n); if (LogoContext.TestIfTrue(BoolLib.equal_q(LogoContext.GetVar("n"), number_1))) { return LogoContext.EndProcedure("fact", number_1); } return LogoContext.EndProcedure("fact", MathLib.product(LogoContext.GetVar("n"), fact_dlgo.fact(MathLib.difference(LogoContext.GetVar("n"), number_1)))); } public static void StartUp() { LogoContext.AssertNull(IOLib.print(LogoList.CreateList(fact_dlgo.fact(number_1)))); LogoContext.AssertNull(IOLib.print(LogoList.CreateList(fact_dlgo.fact(number_4)))); } public static void Main(String[] args) { LogoContext.Init(); LogoContext.Debug = true; LogoContext.LoadLibrary("fact.exe", Assembly.GetExecutingAssembly()); LogoContext.SetVar("args", LogoList.CreateListFromString(args)); LogoTurtle turtle = new LogoTurtle(); turtle.Do(new JobDelegate(new JobDelegate.StartUpDelegate(fact_dlgo.StartUp))); LogoContext.Run(); LogoContext.Terminate(); } } } |
In this C# source you find all your Logo statements translated to C#:
If you look more precisely in the C# generated file, here what you can see:
There are two sort of dynamic statements: MAP call (using "named-procedure" template form) and RUN (or MAP call using any other template for than "named-procedure").
To process a MAP call, Liogo use reflection. More precisely, Liogo keep in memory one hashtable for each DLL loaded in the Liogo context. This hastable contains the name of the Logo procedure and the name of the .NET equivalent method. So when you do a MAP, Liogo find easily which .NET method need to be invoke.
To process a RUN call (explicit call using RUN command or implicit call using a variable), Liogo call the Liogo compiler on the new statement, build it to a memory DLL and invoke the "StartUp" method.
Of course there is an overhead to do a dynamic call with Liogo. More dynamic statements you have, less performance you have !
So in the sample above:
to myproc :l output :l end print myproc [Hello] ; direct call print map "myproc [Hello] ; call using reflection print run [myproc [Hello]] ; call using compiler
If you're interested by performance and Liogo, read more on the technical article here.
LIOGO - GPL Copyright (c) 2005-2006 Lionel Laské