-
Notifications
You must be signed in to change notification settings - Fork 29
Home
There may be more in the wiki eventually, but for the moment this is it... For non-technical information and more project background please see: http://tardisgo.github.io
The entry point for tardisgo is the main() function in file tardisgo.go in the root directory. Around line 304 of the tardisgo.go file is the line:
err = pogo.EntryPoint(main) // TARDIS Go entry point, returns an error
That is the main entry point into the code written to generate Haxe code from the SSA form (http://en.wikipedia.org/wiki/Static_single_assignment_form).
The "pogo" package is common to all target languages, but the "haxe" package is particular to Haxe.
But how are you passed from pogo (which is the common package), to haxe? Pogo code calls methods in the haxe package using "pogo.LanguageList[pogo.TargetLang]" as the base type. But how is this set up? The settings for "pogo.LanguageList[pogo.TargetLang]" are made in file "haxe/base.go" around line 37 inside the init() function, which Go automatically runs before all other code.
Why is it so complicated? To allow another language to be added using the language interface defined in: pogo/language.go
Yes the generated Haxe is huge, there is a lot of work to do to reduce its size. But it will probably always be big, if only because it will contain a full set of SSA comments (and may also contain the Go source code too eventually). Until there is a workable system in sight, the size of the generated Haxe file, and eventually splitting across multiple Haxe files for speed, is not a priority. However, the current one-for-one translation of SSA instructions into Haxe code contributes to a large code size.
The Go standard libraries implement some low-level functions in C or assembler, rather than in Go. The purpose of golibruntime is to provide Go implementations of these functions, maybe with calls to Haxe as required. It does this by overlapping the name-spaces of packages with the same package name, rather than using the package paths, which is probably an unsustainable over-simplification in the long term.
The key thing about the SSA form is that every statement generates a single static assignment, the _t0..._tn variables in the code are the targets of those assignments. Think of them as the variables used when doing the computations. Some of these variables are (potentially) required to hold state between invocations of the goroutine, these are held as class variables, others are only temporary variables used by local calculations, these are held in the private inline functions subFn1, subFn2 etc...
Variable initialization is done in a synthetic init() function, generated by the SSA package. For the SSA package, which has huge amounts of data, this initialization code is very big indeed. So large in fact that it originally broke the Java 64k bytes per function limit, which is why for large functions, the subFns are not marked inline.
All generated haxe classes for go functions implement the StackFrame interface and extend StackFrameBasis. Each goroutine has its own stack, made up of Classes implementing the StackFrame interface. The Scheduler class provides very simple round-robin scheduling of which of all the goroutines that are currently active.