114 lines
4.2 KiB
Markdown
114 lines
4.2 KiB
Markdown
|
# Hello world
|
||
|
|
||
|
The following code in a file called `hello-world.gg` can be compiled to a static
|
||
|
binary which will output "Hello World!" and exit:
|
||
|
|
||
|
```
|
||
|
(. package "github.com/mediocregopher/ginger-hello-world"
|
||
|
(. defn main []
|
||
|
(: fmt.Println "Hello World!"))
|
||
|
)
|
||
|
```
|
||
|
|
||
|
While in the same directory as `hello-world.gg`, this can be compiled and run
|
||
|
with:
|
||
|
|
||
|
```
|
||
|
ginger run
|
||
|
```
|
||
|
|
||
|
and built into a static binary with:
|
||
|
|
||
|
```
|
||
|
ginger build
|
||
|
```
|
||
|
|
||
|
## package
|
||
|
|
||
|
The package string defines where in the namespace tree this file belongs. Code
|
||
|
in this file can directly reference variables, private or public, from other
|
||
|
files in the same package.
|
||
|
|
||
|
The physical layout of the files is not consequential, ginger only cares what
|
||
|
package they say they belong to, it's not required that the directory tree
|
||
|
matches the namespace tree.
|
||
|
|
||
|
## main
|
||
|
|
||
|
Every executable which ginger compiles needs one `main` function to use as the
|
||
|
entrypoint. Ginger looks for a `main` function in all the `.gg` files in the
|
||
|
current working directory in order to compile. If it finds one it uses that, if
|
||
|
it finds zero or more than one it errors and tells the user they need to specify
|
||
|
either a package or file name.
|
||
|
|
||
|
## Compilation
|
||
|
|
||
|
Ginger is first compiled into go code, and the subsequently uses the go tool to
|
||
|
compile that code into a static binary. Because of this ginger is able to use
|
||
|
any code from the go standard library, as well as any third-party go libraries
|
||
|
which may want to be used.
|
||
|
|
||
|
Ginger takes advantage of the `GOPATH` when compiling in order to find packages.
|
||
|
Upon starting up ginger will set the `GOPATH` as follows for the duration of the
|
||
|
run:
|
||
|
|
||
|
```
|
||
|
GOPATH=./target:$GOPATH
|
||
|
```
|
||
|
|
||
|
The following steps are then taken for compilation:
|
||
|
|
||
|
* Create a folder in the cwd called `target`, if it isn't already there. Also
|
||
|
create a `src` subfolder inside of that.
|
||
|
|
||
|
* Scan the cwd and any subdirectories (including `target`) for `.gg` files.
|
||
|
Translate them into `.go` files and place them according to their package name
|
||
|
in the `target/src` directory. So if a file has a package
|
||
|
`github.com/mediocregopher/foobar` it would be compiled and placed as
|
||
|
`target/src/github.com/mediocregopher/foobar/file.go`. The `main` function is
|
||
|
found and the package for it is determined in this step as well.
|
||
|
|
||
|
* As the cwd `.gg` files are scanned a set of packages which are required is
|
||
|
built. If any are not present in `target` at the end of the last step and are
|
||
|
not present as go projects in the `GOPATH` then they are searched for as
|
||
|
ginger projects in the `GOPATH`. Packages found will be translated into the
|
||
|
`target` directory (very important, this prevents the global GOPATH from
|
||
|
getting cluttered with tranlated `.go` files which aren't actually part of the
|
||
|
project). This step is repeated until all dependencies are met, or until
|
||
|
they're not and an error is thrown.
|
||
|
|
||
|
* At this point all necessary `.go` files to build the project are present in
|
||
|
the `GOPATH` (global or `target`). `go build` is called on the `main` package
|
||
|
and output to the `target` directory.
|
||
|
|
||
|
### Properties
|
||
|
|
||
|
Given those compilation steps ginger has the following properties:
|
||
|
|
||
|
* Dependencies for a ginger project, either go or ginger, can be installed
|
||
|
globally or to the `target` folder (sandboxed) by a dependency management tool
|
||
|
(probably built into ginger).
|
||
|
|
||
|
* It is easy to find exactly what your code is being translated to since it will
|
||
|
always be in the `target` directory.
|
||
|
|
||
|
* Translated code will not clutter up the global GOPATH.
|
||
|
|
||
|
* Only the `target` directory needs to be added to a `.gitignore` file.
|
||
|
|
||
|
* Some amount of ginger-to-ginger monkey patching may be possible. Not sure if
|
||
|
this is a good or bad thing.
|
||
|
|
||
|
* Compilation may take a while. There is some amount of hunting for `.gg` files
|
||
|
required, and all found ones *must* be compiled even if they're not going to
|
||
|
be used, since package names can be arbitrarily stated. There are some ways to
|
||
|
help this:
|
||
|
|
||
|
* Might be worth taking a shortcut like grepping through all files in the
|
||
|
`GOPATH` for the package string only compiling the ones which pass the
|
||
|
grep.
|
||
|
|
||
|
* Put placeholder `.go` files in the `target` directory to indicate that the
|
||
|
package isn't needed for subsequent installs. Not the *best* idea, since
|
||
|
changes to the dependency list in the project may not correctly process.
|