├── .gitattributes
├── .gitignore
├── .gitlab-ci.yml
├── LICENSE
├── Makefile
├── README.md
├── cli.go
├── docs
├── .nojekyll
├── README.md
├── _coverpage.md
├── _media
│ ├── bg.jpg
│ ├── hello_preview.gif
│ ├── og_preview.gif
│ └── overview_color.png
├── _sidebar.md
├── build.md
├── changelog.md
├── features.md
├── index.html
├── next.md
├── quick_start.md
├── todo.md
├── usage.md
└── vendor
│ ├── docsify.js
│ ├── prism-og.js
│ └── themes
│ └── dark.css
├── lib
├── ast
│ ├── ast.go
│ ├── ast.og
│ └── walker
│ │ ├── desugar.go
│ │ ├── desugar.og
│ │ ├── gob_register.go
│ │ ├── gob_register.og
│ │ ├── print.go
│ │ ├── print.og
│ │ ├── returnable.go
│ │ ├── returnable.og
│ │ ├── template.go
│ │ ├── template.og
│ │ ├── template_generator.go
│ │ ├── template_generator.og
│ │ ├── template_loader.go
│ │ ├── template_loader.og
│ │ ├── template_parse.go
│ │ ├── template_parse.og
│ │ ├── template_replace.go
│ │ ├── template_replace.og
│ │ ├── template_usage.go
│ │ ├── template_usage.og
│ │ ├── type_checker.go
│ │ ├── type_checker.og
│ │ ├── walker.go
│ │ └── walker.og
├── common
│ ├── config.go
│ ├── config.og
│ ├── error.go
│ ├── error.og
│ ├── file.go
│ ├── file.og
│ ├── node.go
│ ├── node.og
│ ├── printer.go
│ └── printer.og
├── og
│ ├── compile.go
│ ├── compile.og
│ ├── interpreter.go
│ ├── interpreter.og
│ ├── og.go
│ ├── og.og
│ ├── parse.go
│ ├── parse.og
│ ├── pool.go
│ ├── pool.og
│ ├── preproc.go
│ └── preproc.og
├── std
│ ├── .og
│ │ └── template
│ ├── slices.go
│ └── slices.og
└── translator
│ ├── translator.go
│ └── translator.og
├── main.go
├── parser
├── Og.g4
├── Og.interp
├── Og.tokens
├── OgLexer.interp
├── OgLexer.tokens
├── antlr4-4.7.2-SNAPSHOT-complete.jar
├── og_base_listener.go
├── og_base_visitor.go
├── og_lexer.go
├── og_listener.go
├── og_parser.go
└── og_visitor.go
├── scripts
├── fix_parser_imports.sh
└── release_from_develop.sh
└── tests
├── exemples
├── .og
│ └── template
├── anonymous.og
├── assignable_stmt.og
├── bar
│ ├── .og
│ │ └── template
│ ├── bar.go
│ └── bar.og
├── bitwise.og
├── chan.og
├── const.og
├── for.og
├── func_literal.og
├── func_type.og
├── generics.og
├── goroutine.og
├── if.og
├── import.og
├── import_parenthesis.og
├── inc.og
├── interface.og
├── internal_method.og
├── loop_flow.og
├── map.og
├── nested_property.og
├── operation.og
├── package.og
├── package_short.og
├── ref.og
├── rest.og
├── select.og
├── slices.og
├── struct.og
├── struct_inst.og
├── switch.og
├── test.og
├── this.og
├── top_fn.og
├── utopia.og.exemple
└── var.og
└── og_test.go
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.og linguist-language=Go
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 |
8 | # Test binary, build with `go test -c`
9 | *.test
10 |
11 | # Output of the go coverage tool, specifically when used with LiteIDE
12 | *.out
13 |
14 | ./og
15 | .antlr
16 | .vscode
17 | src/**/*.go
18 | tests/exemples/*.go
19 |
--------------------------------------------------------------------------------
/.gitlab-ci.yml:
--------------------------------------------------------------------------------
1 | pages:
2 | stage: deploy
3 | script:
4 | - mkdir .public
5 | - cp -r docs/ .public
6 | - mv .public public
7 | artifacts:
8 | paths:
9 | - public
10 | only:
11 | - master
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: all build clean
2 |
3 | COM_COLOR = \033[0;34m
4 | OBJ_COLOR = \033[0;36m
5 | MAGENTA_COLOR = \033[0;35m
6 | CYAN_COLOR = \033[0;36m
7 | OK_COLOR = \033[0;32m
8 | ERROR_COLOR = \033[0;31m
9 | WARN_COLOR = \033[0;33m
10 | NO_COLOR = \033[m
11 |
12 | OK_STRING = [OK]
13 | ERROR_STRING = [ERROR]
14 | WARN_STRING = [WARNING]
15 | COM_STRING = [Compiling]
16 |
17 | define title
18 | printf "%b" "\n$(CYAN_COLOR)=> $(WARN_COLOR)$(1)$(NO_COLOR)\n";
19 | endef
20 |
21 | define section_title
22 | printf "%b" "$(MAGENTA_COLOR)-> $(OK_COLOR)$(1)$(NO_COLOR)\n";
23 | endef
24 |
25 | define run_and_test
26 | printf "%b" "- $(OBJ_COLOR)$(2)$(NO_COLOR)\r"; \
27 | $(1) 2> $@.log; \
28 | RESULT=$$?; \
29 | if [ $$RESULT -ne 0 ]; then \
30 | printf '%-60b%b' '- $(OBJ_COLOR)$(2)' '$(ERROR_COLOR)$(ERROR_STRING)$(NO_COLOR)\n'; \
31 | elif [ -s $@.log ]; then \
32 | printf '%-60b%b' '- $(OBJ_COLOR)$(2)' '$(WARNING_COLOR)$(WARNING_STRING)$(NO_COLOR)\n'; \
33 | else \
34 | printf '%-60b%b' '- $(OBJ_COLOR)$(2)' '$(OK_COLOR)$(OK_STRING)$(NO_COLOR)\n'; \
35 | fi; \
36 | cat $@.log; \
37 | rm -f $@.log; \
38 | exit $$RESULT
39 | endef
40 |
41 | SRC_PATH=lib/
42 | SRC=$(wildcard $(SRC_PATH)og/*.og $(SRC_PATH)translator/*.og $(SRC_PATH)ast/*.og $(SRC_PATH)ast/walker/*.og $(SRC_PATH)ast/common/*.og)
43 | RES=$(SRC:.og=.go)
44 | EXE=og
45 | CC=og
46 |
47 | all: grammar build
48 |
49 | grammar: parser/*.go
50 | parser/*.go: parser/Og.g4
51 | @$(call section_title,Grammar)
52 | @$(call run_and_test,go generate,Generating parser from $<)
53 |
54 | build:
55 | @$(call title,Building from `$(CC) -v`)
56 | @$(CC) lib
57 | @make test -s --no-print-directory
58 |
59 | $(EXE): $(SRC) $(RES)
60 | @make test --no-print-directory
61 | # @$(call section_title,Building Binary)
62 | # @go build
63 |
64 | re:
65 | @$(call title,Full Re-Bootstrap)
66 | @make re_ --no-print-directory
67 |
68 | re_: grammar
69 | @make clean build --no-print-directory
70 | @make CC='./og' clean new --no-print-directory
71 |
72 | new:
73 | @make CC='./og' all --no-print-directory
74 |
75 | test:
76 | @$(call section_title,Testing)
77 | @go test ./tests
78 |
79 | doc:
80 | @docsify serve ./docs
81 |
82 | clean:
83 | @$(call section_title,Cleaning src folder)
84 | @rm -f $(RES)
85 | @rm -f tests/exemples/*.go
86 |
87 | # lib/%.go: src/%.og
88 | # @$(call run_and_test,$(CC) -o lib $?,Compiling $<)
89 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Og-Lang *v0.7.2* (Optimistic Golang)
2 | ===
3 |
4 | ### [Documentation Website](https://champii.github.io/og)
5 | ### [GoDoc](https://godoc.org/github.com/Champii/og)
6 |
7 | We are looking for a better name !
8 | [Renaming Og](https://github.com/Champii/og/issues/7)
9 |
10 | # Disclamer
11 |
12 |
This software is in its early stage.
13 |
14 | # Quick overview
15 |
16 | This language aim to save developer time as much as possible by implementing syntactic sugar like templates or auto return. It might borrow some concepts from functionnal languages like function composition or currying.
17 |
18 | This is a quick and dirty syntactic coloration made by hand in optic to highlight main features of the language, please don't judge me (Or better, please contribute to make a better one :] )
19 |
20 | 
21 |
22 | ## Demo
23 |
24 |
25 |
26 |
27 |
28 |
29 | # Build
30 |
31 | Here is the procedure to regenerate the parser from the grammar if you want to make changes to it.
32 | If you just want to (re)build the binary, you can call `make build` or just `go build` (needs a previously generated parser from grammar. See below)
33 | You will need `Java`, the Antlr4 library is in `./parser/antlr4-4.7.1-SNAPSHOT-complete.jar`
34 |
35 | ```bash
36 | # Get Og
37 | go get -u github.com/champii/og
38 | cd $GOPATH/src/github.com/champii/og
39 |
40 | # This will regenerate the grammar,
41 | # Compile the existing sources from the previous Og (`og lib`)
42 | # And run the tests.
43 | # Needs the last official `og` binary version at global scope.
44 | make
45 |
46 | # It cleans the `lib` folder,
47 | # Then compiles og from the previous global version (`og lib`)
48 | # Then recomiles it from itself (`./og lib`)
49 | # And run the tests
50 | make re
51 |
52 | # Simple exemple
53 | og exemples/import.og
54 | ```
55 |
56 | The current build time of the project is around 5s for all sources files with `./og` alone, and around 20s for full rebootstrap with `make re` (That bootstraps from old version then rebootstraps from itself, with `go build` and `go test` each time).
57 |
58 | # Quotes
59 |
60 |
61 | "Golang On Steroids" - Socrates
62 | "The Code like it should be. 5/7" - Mahatma Gandhi
63 | "(..Recursive Facepalm..)" - Google
64 |
65 |
--------------------------------------------------------------------------------
/cli.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "os"
5 | "time"
6 |
7 | "github.com/champii/og/lib/common"
8 |
9 | "github.com/urfave/cli"
10 | )
11 |
12 | func parseArgs(done func(*common.OgConfig)) {
13 | cli_ := setupCli()
14 |
15 | cli_.Action = func(c *cli.Context) error {
16 | options := common.OgConfig{
17 | Blocks: c.Bool("b"),
18 | Dirty: c.Bool("d"),
19 | Print: c.Bool("p"),
20 | Ast: c.Bool("a"),
21 | SimpleAst: c.Bool("s"),
22 | Quiet: c.Bool("q"),
23 | Workers: c.Int("w"),
24 | OutPath: c.String("o"),
25 | Interpreter: c.Bool("i"),
26 | NoBuild: c.Bool("n"),
27 | Run: c.Bool("r"),
28 | Force: c.Bool("f"),
29 | Paths: []string(c.Args()),
30 | }
31 |
32 | done(&options)
33 |
34 | return nil
35 | }
36 |
37 | cli_.Run(os.Args)
38 | }
39 |
40 | func setupCli() *cli.App {
41 | cli.AppHelpTemplate = `NAME:
42 | {{.Name}} - {{.Usage}}
43 |
44 | VERSION:
45 | {{.Version}}
46 |
47 | USAGE:
48 | {{if .VisibleFlags}}{{.HelpName}} [options] [folders...|files...]
49 |
50 | If a Print argument (-p, -b, -d, -a) is given, no write on disk is done.
51 |
52 | If run without files, it will compile and build '.'{{end}}
53 | {{if len .Authors}}
54 | AUTHOR:
55 | {{range .Authors}}{{ . }}{{end}}
56 | {{end}}{{if .Commands}}
57 | OPTIONS:
58 | {{range .VisibleFlags}}{{.}}
59 | {{end}}{{end}}{{if .Copyright }}
60 |
61 | COPYRIGHT:
62 | {{.Copyright}}
63 | {{end}}{{if .Version}}
64 | {{end}}
65 | `
66 |
67 | cli.VersionFlag = cli.BoolFlag{
68 | Name: "v, version",
69 | Usage: "Print version",
70 | }
71 |
72 | cli.HelpFlag = cli.BoolFlag{
73 | Name: "h, help",
74 | Usage: "Print help",
75 | }
76 |
77 | app := cli.NewApp()
78 |
79 | app.Name = "Oglang"
80 | app.Version = "v0.7.2"
81 | app.Compiled = time.Now()
82 |
83 | app.Usage = "Golang on steroids"
84 |
85 | app.Flags = []cli.Flag{
86 | cli.BoolFlag{
87 | Name: "r, run",
88 | Usage: "Run the binary",
89 | },
90 | cli.StringFlag{
91 | Name: "o, out",
92 | Usage: "Output destination `directory`.",
93 | Value: "./",
94 | },
95 | cli.IntFlag{
96 | Name: "w, workers",
97 | Usage: "Set the number of `jobs`",
98 | Value: 8,
99 | },
100 | cli.BoolFlag{
101 | Name: "f, force",
102 | Usage: "Force the compilation even if no changes",
103 | },
104 | cli.BoolFlag{
105 | Name: "p, print",
106 | Usage: "Print the file",
107 | },
108 | cli.BoolFlag{
109 | Name: "d, dirty",
110 | Usage: "Print the file before going through 'go fmt'",
111 | },
112 | cli.BoolFlag{
113 | Name: "b, blocks",
114 | Usage: "Print the file after it goes to preprocessor.",
115 | },
116 | cli.BoolFlag{
117 | Name: "a, ast",
118 | Usage: "Print the generated AST",
119 | },
120 | cli.BoolFlag{
121 | Name: "s, simple-ast",
122 | Usage: "Print a simple AST instead with only terminals",
123 | },
124 | cli.BoolFlag{
125 | Name: "i, interpreter",
126 | Usage: "Run a small interpreter (ALPHA)",
127 | },
128 | cli.BoolFlag{
129 | Name: "q, quiet",
130 | Usage: "Hide the progress output",
131 | },
132 | cli.BoolFlag{
133 | Name: "n, no-build",
134 | Usage: "Don't run 'go build'",
135 | },
136 | }
137 |
138 | app.UsageText = "og [options] [folders|files]"
139 |
140 | return app
141 | }
142 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Champii/og/228c5a04bfb7c7a4784932ca4b8121e3385d8365/docs/.nojekyll
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 | ---
3 |
4 |
5 | 'Og' is to be pronounced `Oh-Jee` and stands for ~~`Orgasmic Granny`~~ `Optimistic Golang`
6 | It is an indentation based language mainly inspired from [Livescript](http://livescript.net) that compiles to GoLang.
7 |
8 | ```og
9 | !main
10 |
11 | class Oglang
12 | Foo T
13 | GetFoo: T -> @Foo
14 |
15 | main ->
16 | foo := Oglang
17 | Foo: 42
18 |
19 | foo.GetFoo()
20 | ```
21 |
22 | Go to the [Features](/features.md) section for more exemples of code.
23 |
24 | ### Bootstraped Language
25 | ---
26 |
27 | Oglang is written in itself. It is said to be a 'Bootstraped' language. In fact, Oglang needs the previous release of itself to build itself.
28 | See the [Build](/build.md) section for more details
29 |
30 | Go to the [./lib](https://github.com/champii/og/tree/master/lib) folder on github for both Oglang and compiled Golang sources.
31 |
32 | Built with [Antlr4](https://github.com/champii/antlr4) from their Golang grammar.
33 |
34 | ### Goal
35 | ---
36 |
37 | The main goal is to simplify the syntax, to borrow some concepts from Livescript and other functional languages, to implement Generics and macro processing, as well as some syntaxic sugar to avoid all the boilerplate code Golang forces us into.
38 |
--------------------------------------------------------------------------------
/docs/_coverpage.md:
--------------------------------------------------------------------------------
1 | # Og lang v0.7.2
2 |
3 | ## Optimistic Golang
4 |
5 | [GitHub](https://github.com/Champii/og/)
6 | [Get Started](#introduction)
7 |
8 |
9 | 
10 |
11 |
--------------------------------------------------------------------------------
/docs/_media/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Champii/og/228c5a04bfb7c7a4784932ca4b8121e3385d8365/docs/_media/bg.jpg
--------------------------------------------------------------------------------
/docs/_media/hello_preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Champii/og/228c5a04bfb7c7a4784932ca4b8121e3385d8365/docs/_media/hello_preview.gif
--------------------------------------------------------------------------------
/docs/_media/og_preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Champii/og/228c5a04bfb7c7a4784932ca4b8121e3385d8365/docs/_media/og_preview.gif
--------------------------------------------------------------------------------
/docs/_media/overview_color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Champii/og/228c5a04bfb7c7a4784932ca4b8121e3385d8365/docs/_media/overview_color.png
--------------------------------------------------------------------------------
/docs/_sidebar.md:
--------------------------------------------------------------------------------
1 | * [Introduction](/#introduction)
2 | * [Quick Start](/quick_start.md)
3 | * [Features](/features.md)
4 | * [Usage](/usage.md)
5 | * [Build](/build.md)
6 | * [Todo](/todo.md)
7 | * [What's next](/next.md)
8 | * [Changelog](/changelog.md)
--------------------------------------------------------------------------------
/docs/build.md:
--------------------------------------------------------------------------------
1 | # Build
2 |
3 | Here is the procedure to regenerate the parser from the grammar if you want to make changes to it.
4 |
5 | If you just want to (re)build the binary, you can call `make build` or just `go build` (needs a previously generated parser from grammar. See below)
6 |
7 | You will need `Java`, the Antlr4 library is in `./parser/antlr4-4.7.1-SNAPSHOT-complete.jar`
8 |
9 | ## Get Og
10 | ---
11 | ```bash
12 | go get -u github.com/champii/og
13 | cd $GOPATH/src/github.com/champii/og
14 | ```
15 |
16 | ## Make
17 | ---
18 |
19 | Simply call
20 | ```bash
21 | make
22 | ```
23 | Calling `make` will regenerate the grammar,
24 | Compile the existing sources from the previous Og (`$> og lib`)
25 | And run the tests.
26 | Needs the last official `og` binary version at global scope.
27 |
28 | To recompile the whole project:
29 | ```bash
30 | make re
31 | ```
32 |
33 | This cleans the `lib` folder,
34 | Then compiles og from the previous global version (`$> og lib`)
35 | Then recomiles it from itself (`$> ./og lib`)
36 | And run the tests
37 |
38 | 
39 |
40 | ### Simple test
41 | ```bash
42 | og exemples/import.og
43 | ```
44 |
45 | ### Build time
46 | ---
47 | The current build time of the project is around 5s for all sources files with `./og` alone, and around 20s for full rebootstrap with `make re`.
48 | That bootstraps from old version then rebootstraps from itself, with `go build` and `go test` each time.
49 |
50 |
51 | ### The Doc
52 |
53 | This beautiful documentation is generated with [https://docsify.js.org](https://docsify.js.org) from markdown language
54 |
55 | Check the [./docs](https://github.com/Champii/og/tree/master/docs) folder for the sources
56 |
57 | To launch the doc on `localhost:3000`, just run
58 |
59 | ```bash
60 | make doc
61 | ```
62 |
63 | It has an auto-reload feature to ease the edition of the doc
--------------------------------------------------------------------------------
/docs/changelog.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## v0.7.2: Current version
4 | - Add `-s` option to show a simplified AST with only terminal nodes
5 | - Errors show now the good original lines and columns
6 | - Show an error when a template in unknown
7 | - Colorful ast and lines/columns are shown
8 | - Replace every tabs with 2 spaces in the source. You should use spaces.
9 | - Templates can now be used across packages
10 | - Templates generate a hidden file in the given package to avoid reparsing the whole. This allows for the creation of a Standard Templated Library
11 |
12 |
13 | ## v0.7.1
14 | - Fix `-p` that showed the non-formated output
15 | - Add `-f` for force compilation even if nothing has changed
16 | - Fix printing problems
17 | - Templates are now generated once for each type in each package. We still cannot generate them cross package.
18 |
19 | ## v0.7.0
20 | - Warning when go format fails
21 | - Warning on the interpreter about its uselessness
22 | - Exit the program on exiting the interpreter
23 | - OOP everywhere
24 | - Printer class to handle the printing job (you don't say)
25 |
26 | ## v0.6.4
27 | - Skipped
28 |
29 | ## v0.6.3
30 | - Generics for Struct
31 | ```og
32 | struct Foo
33 | bar T
34 |
35 | main ->
36 | foo := Foo
37 | bar: 2
38 | ```
39 |
40 | ## v0.6.2
41 | - Be `--quiet` when either `-p`, `-d`, `-b` or `-a`
42 | - Force recompile if `-p`, `-d`, `-b` or `-a`
43 | - Hide and show cursor while compiling
44 | - Show a spinner
45 | - Fix `switch res := t.(type)`
46 | - Go format error is no more swallowed
47 | - Add template syntax for `struct Foo` but not implemented yet (needed that switch fix)
48 |
49 | ## v0.6.0
50 | - Generics that are produced at compile time
51 | ```og
52 | genericFunction(arg T): T -> arg
53 |
54 | main ->
55 | genericFunction(a)
56 | genericFunction(a)
57 | ```
58 | - Cleaner Makefile
59 | - Awesome cli tool to use multi-threaded compilation
60 | - Multithreaded tests
61 | - Overall project compilation time down to 8s, tests down to 2s.
62 | - Beautiful progress, made verbose default
63 | - Removed option `-v, --verbose` to be the opposite: `-q, --quiet`
64 | - Add option `-w, --workers` to specify a number of thread for compilation
65 | - Changed `-V, --version` for little `-v, --version`
66 | - Auto build after compile, add option `-n, --no-build` to avoid that behaviour
67 | - Add option `-r, --run` to run after compile
68 | - Overview improvements
69 | - Allow comments starting with `#`
70 | - First type-checker implementation
71 | - Better `AstWalker`
72 | - Colors everywhere !
73 |
74 |
75 | ## v0.5.0
76 | - Removed every non necessary terminal `return`
77 | - Makefile now compiles with the previous released version by default instead of the last compiled one. New rule `make new` that compiles itself with the last present `og`
78 | - Fix a bug on ParameterDecl that wanted a name for each type
79 | - Auto return for `if` statement
80 | ```og
81 | someFunc: int ->
82 | if true => 42
83 | else => 0
84 | ```
85 | - Assignation for `if` statement
86 | ```og
87 | var a int =
88 | if true => 42
89 | else => 0
90 | ```
91 | - Overview section in the docs
92 |
93 | ## v0.4.2
94 | - Auto return for function with no return keyword (only for simple statement yet)
95 | ```og
96 | someFunc: int -> 2
97 | ```
98 |
99 | ## v0.4.1
100 | - Abstract AST walker and a derived AST Printer
101 | - `-a` CLI option to show the AST
102 | - Disambiguation of `for`, `if` and `else if` statements with a `;` before the block
103 | - Empty statement and empty onliner-function body with `;`
104 | ```og
105 | foobar -> ;
106 |
107 | if foo == bar => ;
108 | ```
109 |
110 | ## v0.4.0
111 | - New AST system for more flexibility
112 | - Switched to SLL prediction mode to greatly improve performances
113 | - Multiline `type`, `const` and `var` declaration
114 | ```og
115 | var (
116 | foo string
117 | bar = 2
118 | )
119 | ```
120 | - Disambiguation character `~` for `label` statements
121 | ```og
122 | ~myLabel: something()
123 | ```
124 |
125 | ## v0.3.0
126 | - Allow single line If statement
127 | ```og
128 | if b == 0 => 0
129 | else => 1
130 | ```
131 | - Pretty error display (but trivial for some cases)
132 | ```
133 | path/file.og (8:6): Unexpected 'foo'
134 | bar foo
135 | ^
136 | ```
137 | - Allow empty Return statement
138 | - Small and dirty interpreter that allow only a few expressions
139 |
140 | ## v0.2.0
141 | - Variadic arguments
142 | ```og
143 | someFunc(a ...int) -> fmt.Println(a)
144 | main -> someFunc([]int{1, 2, 3}...)
145 | ```
146 | - Parenthesis allowed for import declaration
147 | ```og
148 | import (
149 | fmt
150 | strings
151 | )
152 | ```
153 | - For statement with 3 flavors
154 | ```og
155 | for _, i in a
156 | for i < 10
157 | for i := 0; i < 10; i++
158 | ```
159 | - Bitwise operators `&`, `|`, `^`, `&^`, `<<`, `>>`
160 | - Import renaming
161 | ```og
162 | import
163 | fmt
164 | strings
165 | "some/repo": otherName
166 | "another/repo": .
167 | ```
168 |
169 | ## v0.1.11
170 | - Function literal but with a mandatory desambiguation symbol `fn`
171 | ```og
172 | a := fn -> fmt.Println(1)
173 | b := fn (a int) -> fmt.Println(a)
174 | c := fn (a int) :int -> return a
175 | a := fn :int -> return 1
176 | ```
177 | - Function Type with the same mandatory `fn`
178 | ```og
179 | a(arg fn: int) -> fmt.Println(arg())
180 | main -> a(fn: int -> return 2)
181 | ```
182 |
183 | ## v0.1.10
184 | - Better `Makefile` that cares about whether a file has changed or not before applying rules
185 | - Proper Anonymous field in structs
186 | ```og
187 | struct Foo
188 | *SomeClass
189 | a int
190 | ```
191 | - Channel Send and Receive
192 | ```og
193 | c := make(chan int)
194 | c <- 1
195 | x := <-c
196 | ```
197 | - Select statement
198 | ```og
199 | select
200 | <-c1 => something()
201 | x := <-c1 => something()
202 | c1 <- 1 =>
203 | something()
204 | somethingElse()
205 | _ => defaultCase()
206 | ```
207 | - Pointer type for receiver in methods
208 | ```og
209 | // inline
210 | struct Foo
211 | nonPointer : int -> return 1
212 | *pointerReceiver : int -> return 1
213 |
214 | // external
215 | Foo::nonPointer2 : int -> return 1
216 | Foo::*pointerReceiver2 : int -> return 1
217 | ```
218 | - External CHANGELOG
219 | - Function literal (Big performance issue caused by the grammar that keeps increasing in complexity, disabled until it's sorted out)
220 | ```og
221 | a := -> fmt.Println(1)
222 | a := (a int) -> fmt.Println(a)
223 | ```
224 |
225 | ## v0.1.9
226 | - `break`, `goto`, `continue`, `fallthrough`, `labels`
227 |
228 | ## v0.1.8
229 | - Proper `const` declaration
230 | - Proper `var` declaration
231 | - Map declaration
232 | - Chan type (`chan T`, `<-chan T` and `chan<- T`)
233 | - Fixed a bug with result type that were not being parsed. We can now use `interface` instread of `interface{}` everywhere
234 |
235 | ## v0.1.7
236 | - Add custom antlr4 directly into sources. No need to build it yourself
237 |
238 | ## v0.1.6
239 | - Release system for develop
240 |
241 | ## v0.1.5
242 | - Forced `Go` syntax highlight on `Og` files for `Github`
243 | - Rework translator to adapt to new method syntax and `@` alias
244 | - No need to specify the `{}` in `interface{}` for arguments types (not for return values yet)
245 | ```og
246 | fn(a interface): interface{} -> a
247 | ```
248 |
249 | ## v0.1.4
250 | - Class-like method declaration (nested into the struct)
251 | ```og
252 | struct Foo
253 | bar int
254 | f : int -> return @bar
255 | ```
256 |
257 | ## v0.1.3
258 | - Slice manipulation
259 | ```og
260 | someArr[1:x]
261 | ```
262 | - Interfaces
263 | ```og
264 | interface Foo
265 | Fn(a ArgType): ResType
266 | ```
267 | - Alias `@` => `this`
268 | ```og
269 | Foo::bar : SomeType -> return @someProp
270 | ```
271 | ## v0.1.2
272 | - Support for simple `struct ID {}` declaration. Still support `type ID struct {}`.
273 | ```og
274 | // Equivalent
275 | struct Foo {}
276 | type Foo struct {}
277 | ```
278 | - Alias `class` => `struct`.
279 | ```og
280 | // Equivalent
281 | struct Foo {}
282 | class Foo {}
283 | ```
284 | - Allow empty `class` declaration
285 | ```og
286 | struct Foo
287 | ```
288 | - Shorthand for `package main` => `!main`.
289 | ```og
290 | // Equivalent
291 | !main
292 | package main
293 | ```
294 | - Cli support with options and recursive directory walking
295 | ```bash
296 | og -o lib src
297 | ```
298 | - External method declaration
299 | ```og
300 | struct Foo
301 | Foo::bar -> doSomething()
302 | ```
303 |
304 | ## v0.1.0
305 | - Initial release
306 |
--------------------------------------------------------------------------------
/docs/features.md:
--------------------------------------------------------------------------------
1 | # Features
2 | ---
3 |
4 | - Indentation based
5 | - Transpile to `Golang`
6 | - No brackets (almost)
7 | - Clean and nice syntax
8 | - Auto return the last statement in a block
9 | - Returnable/Assignable statements (`if` only for the moment)
10 | - Inline method declaration in `struct`
11 | - One-liners
12 | - Syntaxic sugars
13 | - Bootstraped language
14 | - Antlr4 parser
15 | - Multithreaded compilation
16 | - CLI tool to parse and debug your files
17 | - Templates (C++ style, at compile time. ALPHA)
18 | - Interpreter (ALPHA)
19 |
20 | # Overview
21 | ---
22 |
23 | # Global
24 |
25 | ```og
26 | !main // package shorthand
27 |
28 | // No parenthesis and single word can omit quotes
29 | import
30 | fmt
31 | strings
32 | "some/repo"
33 |
34 | // Alias for `type Foo struct`
35 | struct Foo
36 | // Classical property declaration
37 | bar int
38 |
39 | // Inline method declaration that returns `this.bar`
40 | getBar : int -> @bar
41 |
42 | // Pointer type for receiver
43 | *setBar(i int) -> @bar = i
44 |
45 | // External Foo method declaration
46 | Foo::inc(foo int): int -> @bar + foo
47 |
48 | // Pointer type for receiver
49 | Foo::*setInc(foo int) -> @bar = @bar + foo
50 |
51 | // Alias for `type Bar interface`
52 | interface Bar
53 | Foo()
54 | Bar(i int): SomeType
55 |
56 | // Alias for struct
57 | class Test
58 |
59 | // Classical top-level function declaration
60 | // Automatic return for last statement of a block
61 | otherFunc(a string): string -> a
62 |
63 | autoIfReturn: int ->
64 | // Auto return for if statement
65 | if true => 1
66 | else => 0
67 |
68 | // Template definition (ALPHA)
69 | genericFunction(arg T): T -> arg
70 |
71 | main ->
72 | test := Foo{}
73 | test.inc(42)
74 |
75 | // Template call for int
76 | genericFunction(42)
77 |
78 | // Conditional assignation
79 | var a int =
80 | if true => 1
81 | else => 0
82 |
83 | // No brackets
84 | someArr := []string
85 | "value1"
86 | "value2"
87 |
88 | // Classical `for in` form
89 | for i, v in someArray
90 | fmt.Println(i, v)
91 |
92 | switch test.getBar()
93 | 42 => doSomething()
94 | _ => doDefault()
95 |
96 | // Function literal with the keywork `fn`
97 | callback := fn (arg int): int -> arg + 1
98 |
99 | // Auto executed closure when in goroutines
100 | // No need to add the extra `()`
101 | go someFunc()
102 | go -> doSomething()
103 | ```
104 |
105 | Compiles to:
106 |
107 | ```go
108 | package main
109 |
110 | import (
111 | "fmt"
112 | "some/repo"
113 | "strings"
114 | )
115 |
116 | type Foo struct {
117 | bar int
118 | }
119 |
120 | func (this Foo) getBar() int {
121 | return this.bar
122 | }
123 | func (this *Foo) setBar(i int) {
124 | this.bar = i
125 | }
126 | func (this Foo) inc(foo int) int {
127 | return this.bar + foo
128 | }
129 | func (this *Foo) setInc(foo int) {
130 | this.bar = this.bar + foo
131 | }
132 |
133 | type Bar interface {
134 | Foo()
135 | Bar(i int) SomeType
136 | }
137 | type Test struct {
138 | }
139 |
140 | func otherFunc(a string) string {
141 | return a
142 | }
143 | func autoIfReturn() int {
144 | if true {
145 | return 1
146 | } else {
147 | return 0
148 | }
149 | }
150 | func main() {
151 | test := Foo{}
152 | test.inc(42)
153 | genericFunctionint(42)
154 | var (
155 | a int = func() int {
156 | if true {
157 | return 1
158 | } else {
159 | return 0
160 | }
161 | }()
162 | )
163 | someArr := []string{
164 | "value1",
165 | "value2",
166 | }
167 | for i, v := range someArray {
168 | fmt.Println(i, v)
169 | }
170 | switch test.getBar() {
171 | case 42:
172 | doSomething()
173 | default:
174 | doDefault()
175 | }
176 | callback := func(arg int) int {
177 | return arg + 1
178 | }
179 | go someFunc()
180 | go func() {
181 | doSomething()
182 | }()
183 | }
184 | func genericFunctionint(arg int) int {
185 | return arg
186 | }
187 | ```
188 |
189 | # Details
190 |
191 | ## Package
192 |
193 | #### Og
194 |
195 | ```og
196 | !main
197 | // Or
198 | package main
199 | ```
200 |
201 | #### Go
202 |
203 | ```go
204 | package main
205 | ```
206 |
207 | ## Import
208 |
209 | #### Og
210 |
211 | ```og
212 | // Single import
213 | import fmt
214 |
215 | // Multiple imports
216 | import
217 | fmt
218 | "some/repo"
219 |
220 | // Leave the parenthesis if you want
221 | import (
222 | fmt
223 | )
224 |
225 | // Import rename
226 | import
227 | "some/repo": newName
228 | ```
229 |
230 | #### Go
231 |
232 | ```go
233 | import "fmt"
234 |
235 | import (
236 | "fmt"
237 | "some/repo"
238 | )
239 |
240 | import (
241 | "fmt"
242 | )
243 |
244 | import (
245 | newName "some/repo"
246 | )
247 | ```
248 |
249 | ## Top Level Function
250 |
251 | #### Og
252 |
253 | ```og
254 | // Empty online function
255 | f -> ;
256 |
257 | // Return type
258 | g: int -> 2
259 |
260 | // Arguments and return
261 | h(a int): int -> a
262 |
263 | // Multiline
264 | multi(a, b int): int, bool ->
265 | c := a + b
266 |
267 | return c, false // return needed when multiple return values
268 | ```
269 |
270 | #### Go
271 |
272 | ```go
273 | func f() {
274 | }
275 |
276 | func g() int {
277 | return 2
278 | }
279 |
280 | func h(a int) int {
281 | return a
282 | }
283 |
284 | func multi(a, b int) (int, bool) {
285 | c := a + b
286 | return c + 42, false
287 | }
288 | ```
289 |
290 | ## Function Literal
291 |
292 | #### Og
293 |
294 | ```og
295 | // `fn` keyword to denote the function type
296 | struct Foo
297 | Bar fn(int): string
298 |
299 | // No need of the `fn` in interface
300 | interface Bar
301 | Foo(string): error
302 |
303 | f(callback fn(int): error): error -> callback(0)
304 |
305 | var g = fn(a int): error -> nil
306 | ```
307 |
308 | #### Go
309 |
310 | ```go
311 | struct Foo {
312 | Bar func (int) string
313 | }
314 |
315 | interface Bar {
316 | Foo(string) error
317 | }
318 |
319 | func f(callback func (int) error) error {
320 | return callback(0)
321 | }
322 |
323 | var g = func (a int) error {
324 | return nil
325 | }
326 | ```
327 |
328 | ## If / Else
329 |
330 | #### Og
331 |
332 | ```og
333 | // Classical
334 | if foo == bar
335 | foo.Do()
336 | else if foo == other
337 | bar.Do()
338 | else
339 | nothing()
340 |
341 | // Compressed
342 | if foo == bar => foo.Do()
343 | else => bar.Do()
344 |
345 | // One line
346 | if foo == bar => 1 ; else => 0
347 |
348 | //Assignement, type is mandatory here
349 | var a int =
350 | if foo == bar => 1
351 | else => 0
352 |
353 | // Auto return when last statement in function block
354 | f: int ->
355 | if foo == bar => 1
356 | else => 0
357 | ```
358 |
359 |
360 | #### Go
361 |
362 | ```go
363 | if foo == bar {
364 | foo.Do()
365 | } else if foo == other{
366 | bar.Do()
367 | } else {
368 | nothing()
369 | }
370 |
371 | if foo == bar {
372 | foo.Do()
373 | } else {
374 | bar.Do()
375 | }
376 |
377 | if foo == bar {
378 | 1
379 | } else {
380 | 0
381 | }
382 |
383 | var (
384 | a int = func() int {
385 | if foo == bar {
386 | return 1
387 | } else {
388 | return 0
389 | }
390 | }()
391 | )
392 |
393 | func f() int {
394 | if foo == bar {
395 | return 1
396 | } else {
397 | return 0
398 | }
399 | }
400 | ```
401 |
402 | ## For
403 |
404 | #### Og
405 |
406 | ```og
407 | // Infinite loop
408 | for
409 | do()
410 |
411 | // Classical
412 | for i < 10
413 | do()
414 |
415 | // Range
416 | for _, v in array
417 | do(v)
418 |
419 | // Maniac style
420 | for i := 0; i < 10; i++
421 | do(i)
422 | ```
423 |
424 | #### Go
425 |
426 | ```go
427 | for {
428 | do()
429 | }
430 |
431 | for i < 10 {
432 | do()
433 | }
434 |
435 | for _, v := range array {
436 | do(v)
437 | }
438 |
439 | for i := 0; i < 10; i++ {
440 | do(i)
441 | }
442 | ```
443 |
444 | ## Goroutine
445 |
446 | #### Og
447 |
448 | ```og
449 | // classical
450 | go some.Func()
451 |
452 | // With auto-executed closure
453 | go -> some.Func()
454 | ```
455 |
456 | #### Go
457 |
458 | ```go
459 | go some.Func()
460 |
461 | go func() {
462 | some.Func()
463 | }()
464 | ```
465 |
466 | ## Slice
467 |
468 | #### Og
469 |
470 | ```og
471 | a := []string
472 | "a"
473 | "b"
474 | "c"
475 | ```
476 |
477 | #### Go
478 |
479 | ```go
480 | a := []string{
481 | "a",
482 | "b",
483 | "c",
484 | }
485 | ```
486 |
487 | ## Switch/Case
488 |
489 | #### Og
490 |
491 | ```og
492 | // Switch case with default
493 | switch value
494 | 42 => do()
495 | _ => doDefault()
496 |
497 | // Type switch
498 | switch value.(type)
499 | int => do()
500 | _ => doDefault()
501 | ```
502 |
503 | #### Go
504 |
505 | ```go
506 | switch value {
507 | case 42:
508 | do()
509 | default:
510 | doDefault()
511 | }
512 |
513 | switch value.(type) {
514 | case int:
515 | do()
516 | default:
517 | doDefault()
518 | }
519 | ```
520 |
521 | ## Select
522 |
523 | #### Og
524 |
525 | ```og
526 | select
527 | <-c => do()
528 | x := <-c => doWith(x)
529 | c2 <- 1 => hasSend()
530 | _ => doDefault()
531 | ```
532 |
533 | #### Go
534 |
535 | ```go
536 | select {
537 | case <-c1:
538 | do()
539 | case x := <-c2:
540 | doWith(x)
541 | case c2 <- 1:
542 | hasSend()
543 | default:
544 | doDefault()
545 | }
546 | ```
547 |
548 | ## Struct
549 |
550 | #### Og
551 |
552 | ```og
553 | // Struct type with internal method
554 | struct Foo
555 | Bar int
556 | GetBar: int -> @Bar
557 | *SetBar(v int) -> @Bar = v
558 |
559 | // Class is an alias for `struct`
560 | class MyClass
561 | myValue int `json:"-"`
562 |
563 | // External method declaration
564 | MyClass::*MyMethod: int -> @myValue
565 |
566 | // Instantiation
567 | NewMyMethod: *MyMethod ->
568 | &MyMethod
569 | myValue: 0
570 | ```
571 |
572 | #### Go
573 |
574 | ```go
575 | type Foo struct {
576 | Bar int
577 | }
578 |
579 | func (this Foo) GetBar() int {
580 | return this.Bar
581 | }
582 |
583 | func (this *Foo) SetBar(v int) {
584 | this.Bar = v
585 | }
586 |
587 | type MyClass struct {
588 | myValue int `json:"-"`
589 | }
590 |
591 | func (this *MyClass) MyMethod() int {
592 | return this.myValue
593 | }
594 |
595 | func NewMyMethod() *MyMethod {
596 | return &MyMethod{
597 | myValue: 0,
598 | }
599 | }
600 | ```
601 |
602 | ## Interface
603 |
604 | #### Og
605 |
606 | ```og
607 | // Empty interface
608 | interface Foo
609 |
610 | // Method decl
611 | interface Bar
612 | *CompositeField
613 | Method(Type): ReturnType
614 | ```
615 |
616 | #### Go
617 |
618 | ```go
619 | type Foo interface{}
620 |
621 | type Bar interface {
622 | Method(Type) ReturnType
623 | }
624 | ```
625 | ## Template
626 |
627 | Templates can be defined across packages, their definition is kept in a hidden file in order to avoir reparsing the whole package when needed
628 |
629 | #### Og
630 |
631 | ```og
632 | struct Foo
633 | bar T
634 |
635 | genericFunction(arg T): T -> arg
636 |
637 | main ->
638 | a := Foo
639 | bar: 1
640 |
641 | genericFunction(a)
642 | genericFunction(a)
643 | ```
644 |
645 | #### Go
646 |
647 | ```go
648 | type example_Foo_int struct {
649 | bar int
650 | }
651 |
652 | func example_genericFunction_int(arg int) int {
653 | return arg
654 | }
655 |
656 | func example_genericFunction_string(arg string) string {
657 | return arg
658 | }
659 |
660 | func main() {
661 | a := example_Foo_int{
662 | bar: 1,
663 | }
664 | example_genericFunction_int(a)
665 | example_genericFunction_string(a)
666 | }
667 | ```
668 |
669 | ## Label
670 |
671 | #### Og
672 |
673 | ```og
674 | main ->
675 | ~here:
676 | goto here
677 | ```
678 |
679 | #### Go
680 |
681 | ```go
682 | func main() {
683 | here:
684 | goto here
685 | }
686 | ```
687 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Oglang v0.7.2
6 |
7 |
8 |
9 |
10 |
60 |
61 |
62 |
63 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/docs/next.md:
--------------------------------------------------------------------------------
1 | # What's next
2 | ---
3 |
4 | Here is an overview of what we want Og to look like in the future
5 |
6 | Don't mind the syntactic coloration that is not suited for non-existant features
7 |
8 | ```og
9 | !main
10 |
11 | import fmt
12 |
13 | // Generics
14 | struct Generic
15 | // attributes
16 | pub test T
17 |
18 | // Instance method
19 | fn : T -> @test
20 |
21 | // Class method with external type declaration
22 | $ T -> Generic
23 | pub @new(v) -> Generic{ v }
24 |
25 |
26 | // External grouped method definition
27 | Generic::(
28 | // With '*', tells the receiver (this or @) is a pointer to Generic
29 | *method1 : int -> 1
30 |
31 | // External type declaration with no return
32 | $ int -> SomeComplexType -> (AnotherOne -> interface{}) -> ()
33 | method2(a, b, c) -> 2
34 | )
35 |
36 | // Returnable statements, nil existence test, predicat recapture (that)
37 | genericFunc(g Generic): T -> if g.fn()? => that
38 | else => somethingElse
39 |
40 | // External type declaration
41 | $ Generic -> T
42 | genericFunc(g) -> g.test
43 |
44 | // Multiple return values
45 | $ int -> (int, string)
46 | multipleReturn(i) -> i, "foo"
47 |
48 | // Automatic "it" argument when not specified
49 | $ string -> string
50 | someFunc -> it + "Hello"
51 |
52 | // No arguments, multiple return values, error bubbling
53 | # (error, SomeType)
54 | failableFunc ->
55 | res1 := funcsThatMayFail()?
56 | res2 := funcsThatFail()?
57 |
58 | res1 + res2
59 |
60 | // Macro definition (like rust)
61 | $macro my_macro ->
62 | ($number:expr) =>
63 | myFunc$(number) : int -> $number
64 | if $number > 0
65 | $my_macro($number - 1)
66 |
67 | // Generate 10 function `myFunc10(), myFunc9(), .. myFunc0()` that all return their number,
68 | $my_macro(10)
69 |
70 | // Operator definition with precedence
71 | operator ~~ 9
72 |
73 | // Typeclass (could be implemented with macros ? lets see...)
74 | impl SomeTypeClass for MyType
75 | x ~~ y = x.DoSomething(y)
76 |
77 | main ->
78 | t := Generic::new("str")
79 |
80 | // Range array creation, call chaining,
81 | // function currying and function shorthand.
82 | // Here a == [10, 11, 12, 13, 14, 15]
83 | a := []int{0..10}
84 | |> map((+ 10))
85 | |> filter((<= 15))
86 |
87 | // Function composition
88 | f := map >> filter
89 |
90 | ```
--------------------------------------------------------------------------------
/docs/quick_start.md:
--------------------------------------------------------------------------------
1 | # Quick Start
2 |
3 | ## Install
4 | ---
5 |
6 | You just have to `go get` the repo
7 |
8 | ```bash
9 | go get -u github.com/champii/og
10 | ```
11 |
12 | If your `$PATH` includes `$GOPATH/bin` (and it should), you can print the version
13 |
14 | ```bash
15 | og -v
16 | ```
17 |
18 | ## Hello world
19 | ---
20 |
21 | 
22 |
23 | Create a new folder and a new file
24 |
25 | ```bash
26 | mkdir hello
27 | cd hello
28 | nano hello.og
29 | ```
30 |
31 | Type in this little hello world
32 |
33 | ```og
34 | !main
35 |
36 | import fmt
37 |
38 | main -> fmt.Println("Hello world !")
39 | ```
40 |
41 | Compile and execute
42 |
43 | ```bash
44 | og -r
45 | ```
46 |
47 | You should get an output like this one:
48 |
49 | ```
50 | ~> Oglang: Compiled 1 files
51 | ~> Oglang: Running...
52 | Hello world !
53 | ```
54 |
55 | A new file `hello.go` should apprear in your folder and it should look like this
56 |
57 | ```go
58 | package main
59 |
60 | import (
61 | "fmt"
62 | )
63 |
64 | func main() {
65 | fmt.Println("Hello world !")
66 | }
67 | ```
68 |
69 | ## Full Exemple
70 |
71 |
72 | ```og
73 | !main
74 |
75 | import
76 | fmt
77 | strings
78 | "some/repo"
79 |
80 | struct Foo
81 | bar int
82 | getBar: int -> @bar
83 | *setBar(i int) -> @bar = i
84 |
85 | Foo::inc (foo int): int -> @bar + foo
86 | Foo::*setInc(foo int) -> @bar = @bar + foo
87 |
88 | interface Bar
89 | Foo()
90 | Bar(i int): SomeType
91 |
92 | otherFunc(a string): string -> a
93 |
94 | autoIfReturn: int ->
95 | if true => 1
96 | else => 0
97 |
98 | genericFunction(arg T): T -> arg
99 |
100 | main ->
101 | test := Foo{}
102 | test.inc(42)
103 |
104 | genericFunction(42)
105 |
106 | var a int =
107 | if true => 1
108 | else => 0
109 |
110 | someArr := []string
111 | "value1"
112 | "value2"
113 |
114 | for i, v in someArray
115 | fmt.Println(i, v)
116 |
117 | switch test.getBar()
118 | 42 => doSomething()
119 | _ => doDefault()
120 |
121 | callback := fn (arg int): int -> arg + 1
122 |
123 | go someFunc()
124 | go -> doSomething()
125 | ```
126 |
127 | This example, while producing a valid Go syntax, calls some undefined function and serves only as a showcase of the features of the language.
128 | If you want to compile it to Golang anyway, you must use the `og -n` option that does not build the go files after compilation.
129 |
130 | Go to the [Build](/build.md) section for more informations about the options
131 |
--------------------------------------------------------------------------------
/docs/todo.md:
--------------------------------------------------------------------------------
1 | # Todo
2 | ---
3 |
4 | ## Golang basics
5 | ---
6 |
7 | - [ ] Named return
8 |
9 | ## Syntaxic Sugar
10 | ---
11 |
12 | - [ ] Slices declaration without type `[1, 2, 3]`, `[]string` (need type inference)
13 | - [ ] `*` Operator in slices to reference own lenght `arr = arr[*-1]`
14 | - [ ] Suffix keyword `return foo if bar`, `foo += i for i in array`
15 | - [ ] Returnable and assignable statements (for, switch, ...)
16 | - [ ] Predicat recapture: `if a => that`
17 | - [ ] External type declaration like Haskell: `myFunc :: string -> Foo -> Bar`
18 | - [ ] Existance test (if foo? => bar) for non-nil value test
19 | - [ ] `pub` visibility instead of capitalizing
20 | - [ ] For with a range (for i in [0..10])
21 | - [ ] Pattern matching
22 | - [ ] Auto setup package name with folder name if not specified
23 | - [ ] Error bubbling
24 | - [ ] Function currying
25 | - [ ] Function shorthand `(+ 10)`, `map(structArr, (.SomeField))`
26 | - [ ] Import pattern matching
27 | - [ ] Remove that `fn` keywork that diminish lisibility
28 | - [ ] Conditionnal expression like `res := getFirst() || getSecond()` that make `if` statements
29 | - [ ] Assignation and return for `for`, `switch`
30 | - [ ] `super` keyword
31 | - [ ] Default arguments `f := (i int = 2, s string = "foo") ->`
32 | - [ ] Extended arguments to set to this `Foo::bar(@someVar) -> `
33 | - [ ] Global type inference and auto-generic generation to access full parametric polymorphism
34 |
35 | ## Technical
36 | ---
37 |
38 | - [ ] Make a distinction between Generics(run time) and Templates(compile time)
39 | - [ ] Early checks like import validity or undefined references based on first pass analysis of the project
40 | - [ ] Interoperable Generics on differents Og projects
41 | - [ ] Recursive Generics
42 | - [ ] Fix: Cannot have a function literal other than last argument in function (actual workaround is to define a `type` and to pass it instead)
43 | - [ ] Perfs !! (More specific rules, reduce size and workload of Walkers, remove ambiguity in grammar)
44 | - [ ] Do a single pass on AST instead of multiple walkers (for perfs)
45 | - [ ] Fix bad perfs for nested struct instantiation and if/else block
46 | - [ ] Simple type checker to catch errors before Golang formater/compiler does
47 | - [ ] Language extensions ?
48 | - [ ] Make tests truly executable
49 | - [ ] VSCode extension
50 | - [ ] Adapt Golang tooling like `gofmt` or `golint`
51 | - [ ] Allow to give arguments to finaly executed binary with `og -r -- arg1 arg2`
52 | - [ ] Fix typeswitch that cannot allow a pointer as second case without `;`
53 | ```go
54 | switch template.Node.(type)
55 | *FunctionDecl => @GenerateTopFns(template); // <- that `;` is needed here
56 | *StructType => @GenerateStruct(template)
57 | ```
58 |
--------------------------------------------------------------------------------
/docs/usage.md:
--------------------------------------------------------------------------------
1 | # Usage
2 |
3 | ## The Binary
4 | ---
5 |
6 | ```
7 | $> og -h
8 | NAME:
9 | Oglang - Golang on steroids
10 |
11 | VERSION:
12 | v0.7.2
13 |
14 | USAGE:
15 | og [options] [folders...|files...]
16 |
17 | If a Print argument (-p, -b, -d, -a) is given, NO COMPILATION is done.
18 |
19 | If run without files, it will compile and execute '.'
20 |
21 | OPTIONS:
22 | -r, --run Run the binary
23 | -o directory, --out directory Output destination `directory` (default: "./")
24 | -w jobs, --workers jobs Set the number of jobs (default: 8)
25 | -p, --print Print the file
26 | -d, --dirty Print the file before going through 'go fmt'
27 | -b, --blocks Print the file after it goes to preprocessor.
28 | -a, --ast Print the generated AST
29 | -i, --interpreter Run a small interpreter (ALPHA)
30 | -q, --quiet Hide the progress output
31 | -n, --no-build Dont run 'go build'
32 | -h, --help Print help
33 | -v, --version Print version
34 | ```
35 |
36 | ## Basic file compilation
37 | ---
38 |
39 | By default Og recursively compile every `.og` file in the current folder `.` and produce `.go` files that are along their Og source. It will then run `go build` on the folder
40 | ```bash
41 | ./og
42 | ```
43 |
44 | To additionaly run the produces binary, you can add the `-r` flag
45 | ```bash
46 | ./og -r
47 | ```
48 |
49 | With just a file name, the compiler will produce a single `.go` file inside the same directory
50 | ```bash
51 | ./og folder/file.og
52 | ```
53 |
54 | You can give multiple files and folder that will be walked recursively
55 | ```bash
56 | ./og file.og folder/ anotherFile.og
57 | ```
58 |
59 | The output flag `-o` will save the files into another folder. The folder hierarchy is recreated.
60 | ```bash
61 | ./og -o lib src/file.og
62 | ```
63 |
64 | ## Debug
65 | ---
66 |
67 | You can also print the file without affecting the fs with `-p`
68 | ```bash
69 | ./og -p src/file.og
70 | ```
71 |
72 | The `-d` (`--dirty`) option shows you the bare generated file from the parser, without formating with `go fmt`.
73 | This is useful to check if the generated syntax is valid.
74 |
75 | The `-b` (`--block`) option prints the output of the preprocessor who's in charge to create the blocks from indentation. No compilation is done.
76 |
77 | The `-a` (`--ast`) option prints the generated AST from the parser
78 |
79 |
80 | ## Interpreter (ALPHA)
81 | ---
82 |
83 | Og embed a small interpreter that in fact compiles the given string into a `/tmp/main.go` skelton and run it. A better implementation will come.
84 |
85 | ```bash
86 | ./og -i
87 | > 1+1
88 | 2
89 | ```
--------------------------------------------------------------------------------
/docs/vendor/prism-og.js:
--------------------------------------------------------------------------------
1 | Prism.languages.og = {
2 | 'comment': /\/\/.*/,
3 | 'builtin': /\b(?:bool|byte|complex(?:64|128)|error|float(?:32|64)|rune|string|u?int(?:8|16|32|64)?|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(?:ln)?|real|recover)\b/,
4 | 'keyword': /\b(?:class|fn|in|break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,
5 | 'boolean': /\b(?:_|iota|nil|true|false)\b/,
6 | 'funcName': { // TODO
7 | pattern: /^(\w+) *(?=:?)(?=.+?)(?=->)/,
8 | },
9 | 'returnType': {
10 | pattern: /(: )(\w+)/,
11 | lookbehind: true,
12 | },
13 | 'funcCall': [
14 | {
15 | pattern: /(\w+)(?=\()/,
16 | },
17 | {
18 | pattern: /(\w+) *(?=->)/,
19 | },
20 | {
21 | pattern: /(\w+) *(?=: )/,
22 | },
23 | {
24 | pattern: /(\w+)(?=<)/,
25 | },
26 | ],
27 | 'secondary': {
28 | pattern: /(\.)(\w+)/,
29 | lookbehind: true
30 | },
31 | 'assign': {
32 | pattern: /(\w+) +(?=:=)/,
33 | },
34 | 'thisProp': {
35 | pattern: /(@)(\w+)/,
36 | lookbehind: true,
37 | },
38 |
39 | 'externalReceiver': /(\w+)(?=::)/,
40 | 'externalMethod': {
41 | pattern: /(::\*?)(\w+)/,
42 | lookbehind: true,
43 | },
44 | // 'lol': /::/,
45 | // 'externalMethod': {
46 | // pattern: /(\w+)(.)(\*?)(\w+)/g,
47 | // inside: {
48 | // externalReceiver: /(\w+)(?=::)/,
49 | // externalMethod: {
50 | // pattern: /(\*?)/,
51 | // lookbehind: true,
52 | // },
53 | // },
54 | // },
55 | 'operator': /\{\}|,|\.|\[\]|[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|:|\.\.\./,
56 | 'number': /(?:\b0x[a-f\d]+|(?:\b\d+\.?\d*|\B\.\d+)(?:e[-+]?\d+)?)i?/i,
57 | 'this': /(@|this)/i,
58 | 'argType': {
59 | pattern: /( +)(\w+)(?=(,|\)))/,
60 | },
61 | 'structInst': {
62 | pattern: /(\w+)(?=\{)/,
63 | },
64 | 'parens': /\(|\)/g,
65 | 'string': {
66 | pattern: /(["'`])(\\[\s\S]|(?!\1)[^\\])*\1/,
67 | greedy: true
68 | }
69 | };
70 | // delete Prism.languages.og['class-name'];
71 |
72 | Prism.languages.insertBefore('og', 'keyword', {
73 | 'className': {
74 | pattern: /(struct|class|interface)(.*)/,
75 | lookbehind: true,
76 | },
77 | 'packageName': {
78 | pattern: /^(\!)(\w*)/,
79 | lookbehind: true,
80 | },
81 |
82 | });
83 |
--------------------------------------------------------------------------------
/docs/vendor/themes/dark.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600");*{-webkit-font-smoothing:antialiased;-webkit-overflow-scrolling:touch;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-text-size-adjust:none;-webkit-touch-callout:none;box-sizing:border-box}body:not(.ready){overflow:hidden}body:not(.ready) .app-nav,body:not(.ready)>nav,body:not(.ready) [data-cloak]{display:none}div#app{font-size:30px;font-weight:lighter;margin:40vh auto;text-align:center}div#app:empty:before{content:"Loading..."}.emoji{height:1.2rem;vertical-align:middle}.progress{background-color:var(--theme-color,#ea6f5a);height:2px;left:0;position:fixed;right:0;top:0;transition:width .2s,opacity .4s;width:0;z-index:5}.search .search-keyword,.search a:hover{color:var(--theme-color,#ea6f5a)}.search .search-keyword{font-style:normal;font-weight:700}body,html{height:100%}body{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;color:#c8c8c8;font-family:Source Sans Pro,Helvetica Neue,Arial,sans-serif;font-size:15px;letter-spacing:0;margin:0;overflow-x:hidden}img{max-width:100%}a[disabled]{cursor:not-allowed;opacity:.6}kbd{border:1px solid #ccc;border-radius:3px;display:inline-block;font-size:12px!important;line-height:12px;margin-bottom:3px;padding:3px 5px;vertical-align:middle}.task-list-item{list-style-type:none}li input[type=checkbox]{margin:0 .2em .25em -1.6em;vertical-align:middle}.app-nav{margin:25px 60px 0 0;position:absolute;right:0;text-align:right;z-index:2}.app-nav.no-badge{margin-right:25px}.app-nav p{margin:0}.app-nav>a{margin:0 1rem;padding:5px 0}.app-nav li,.app-nav ul{display:inline-block;list-style:none;margin:0}.app-nav a{color:inherit;font-size:16px;text-decoration:none;transition:color .3s}.app-nav a.active,.app-nav a:hover{color:var(--theme-color,#ea6f5a)}.app-nav a.active{border-bottom:2px solid var(--theme-color,#ea6f5a)}.app-nav li{display:inline-block;margin:0 1rem;padding:5px 0;position:relative}.app-nav li ul{background-color:#fff;border:1px solid #ddd;border-bottom-color:#ccc;border-radius:4px;box-sizing:border-box;display:none;max-height:calc(100vh - 61px);overflow-y:auto;padding:10px 0;position:absolute;right:-15px;text-align:left;top:100%;white-space:nowrap}.app-nav li ul li{display:block;font-size:14px;line-height:1rem;margin:0;margin:8px 14px;white-space:nowrap}.app-nav li ul a{display:block;font-size:inherit;margin:0;padding:0}.app-nav li ul a.active{border-bottom:0}.app-nav li:hover ul{display:block}.github-corner{border-bottom:0;position:fixed;right:0;text-decoration:none;top:0;z-index:1}.github-corner:hover .octo-arm{animation:a .56s ease-in-out}.github-corner svg{color:#3f3f3f;fill:var(--theme-color,#ea6f5a);height:80px;width:80px}main{display:block;position:relative;width:100vw;height:100%;z-index:0}main.hidden{display:none}.anchor{display:inline-block;text-decoration:none;transition:all .3s}.anchor span{color:#c8c8c8}.anchor:hover{text-decoration:underline}.sidebar{border-right:1px solid rgba(0,0,0,.07);overflow-y:auto;padding:40px 0 0;position:absolute;top:0;bottom:0;left:0;transition:transform .25s ease-out;width:300px;z-index:3}.sidebar>h1{margin:0 auto 1rem;font-size:1.5rem;font-weight:300;text-align:center}.sidebar>h1 a{color:inherit;text-decoration:none}.sidebar>h1 .app-nav{display:block;position:static}.sidebar .sidebar-nav{line-height:2em;padding-bottom:40px}.sidebar li.collapse .app-sub-sidebar{display:none}.sidebar ul{margin:0 0 0 15px;padding:0}.sidebar li>p{font-weight:700;margin:0}.sidebar ul,.sidebar ul li{list-style:none}.sidebar ul li a{border-bottom:none;display:block}.sidebar ul li ul{padding-left:20px}.sidebar::-webkit-scrollbar{width:4px}.sidebar::-webkit-scrollbar-thumb{background:transparent;border-radius:4px}.sidebar:hover::-webkit-scrollbar-thumb{background:hsla(0,0%,53%,.4)}.sidebar:hover::-webkit-scrollbar-track{background:hsla(0,0%,53%,.1)}.sidebar-toggle{background-color:transparent;background-color:rgba(63,63,63,.8);border:0;outline:none;padding:10px;position:absolute;bottom:0;left:0;text-align:center;transition:opacity .3s;width:284px;z-index:4}.sidebar-toggle .sidebar-toggle-button:hover{opacity:.4}.sidebar-toggle span{background-color:var(--theme-color,#ea6f5a);display:block;margin-bottom:4px;width:16px;height:2px}body.sticky .sidebar,body.sticky .sidebar-toggle{position:fixed}.content{padding-top:60px;position:absolute;top:0;right:0;bottom:0;left:300px;transition:left .25s ease}.markdown-section{margin:0 auto;max-width:800px;padding:30px 15px 40px;position:relative}.markdown-section>*{box-sizing:border-box;font-size:inherit}.markdown-section>:first-child{margin-top:0!important}.markdown-section hr{border:none;border-bottom:1px solid #eee;margin:2em 0}.markdown-section iframe{border:1px solid #eee}.markdown-section table{border-collapse:collapse;border-spacing:0;display:block;margin-bottom:1rem;overflow:auto;width:100%}.markdown-section th{font-weight:700}.markdown-section td,.markdown-section th{border:1px solid #ddd;padding:6px 13px}.markdown-section tr{border-top:1px solid #ccc}.markdown-section p.tip,.markdown-section tr:nth-child(2n){background-color:#f8f8f8}.markdown-section p.tip{border-bottom-right-radius:2px;border-left:4px solid #f66;border-top-right-radius:2px;margin:2em 0;padding:12px 24px 12px 30px;position:relative}.markdown-section p.tip:before{background-color:#f66;border-radius:100%;color:#3f3f3f;content:"!";font-family:Dosis,Source Sans Pro,Helvetica Neue,Arial,sans-serif;font-size:14px;font-weight:700;left:-12px;line-height:20px;position:absolute;height:20px;width:20px;text-align:center;top:14px}.markdown-section p.tip code{background-color:#efefef}.markdown-section p.tip em{color:#c8c8c8}.markdown-section p.warn{background:hsla(9,77%,64%,.1);border-radius:2px;padding:1rem}body.close .sidebar{transform:translateX(-300px)}body.close .sidebar-toggle{width:auto}body.close .content{left:0}@media print{.app-nav,.github-corner,.sidebar,.sidebar-toggle{display:none}}@media screen and (max-width:768px){.github-corner,.sidebar,.sidebar-toggle{position:fixed}.app-nav{margin-top:16px}.app-nav li ul{top:30px}main{height:auto;overflow-x:hidden}.sidebar{left:-300px;transition:transform .25s ease-out}.content{left:0;max-width:100vw;position:static;padding-top:20px;transition:transform .25s ease}.app-nav,.github-corner{transition:transform .25s ease-out}.sidebar-toggle{background-color:transparent;width:auto;padding:30px 30px 10px 10px}body.close .sidebar{transform:translateX(300px)}body.close .sidebar-toggle{background-color:rgba(63,63,63,.8);transition:background-color 1s;width:284px;padding:10px}body.close .content{transform:translateX(300px)}body.close .app-nav,body.close .github-corner{display:none}.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:a .56s ease-in-out}}@keyframes a{0%,to{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}section.cover{-ms-flex-align:center;align-items:center;background-position:50%;background-repeat:no-repeat;background-size:cover;height:100vh;display:none}section.cover.show{display:-ms-flexbox;display:flex}section.cover.has-mask .mask{background-color:#3f3f3f;opacity:.8;position:absolute;top:0;height:100%;width:100%}section.cover .cover-main{-ms-flex:1;flex:1;margin:-20px 16px 0;text-align:center;z-index:1}section.cover a{color:inherit}section.cover a,section.cover a:hover{text-decoration:none}section.cover p{line-height:1.5rem;margin:1em 0}section.cover h1{color:inherit;font-size:2.5rem;font-weight:300;margin:.625rem 0 2.5rem;position:relative;text-align:center}section.cover h1 a{display:block}section.cover h1 small{bottom:-.4375rem;font-size:1rem;position:absolute}section.cover blockquote{font-size:1.5rem;text-align:center}section.cover ul{line-height:1.8;list-style-type:none;margin:1em auto;max-width:500px;padding:0}section.cover .cover-main>p:last-child a{border:1px solid var(--theme-color,#ea6f5a);border-radius:2rem;box-sizing:border-box;color:var(--theme-color,#ea6f5a);display:inline-block;font-size:1.05rem;letter-spacing:.1rem;margin:.5rem 1rem;padding:.75em 2rem;text-decoration:none;transition:all .15s ease}section.cover .cover-main>p:last-child a:last-child{background-color:var(--theme-color,#ea6f5a);color:#fff}section.cover .cover-main>p:last-child a:last-child:hover{color:inherit;opacity:.8}section.cover .cover-main>p:last-child a:hover{color:inherit}section.cover blockquote>p>a{border-bottom:2px solid var(--theme-color,#ea6f5a);transition:color .3s}section.cover blockquote>p>a:hover{color:var(--theme-color,#ea6f5a)}.sidebar,body{background-color:#3f3f3f}.sidebar{color:#c8c8c8}.sidebar li{margin:6px 15px 6px 0}.sidebar ul li a{color:#c8c8c8;font-size:14px;overflow:hidden;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}.sidebar ul li a:hover{text-decoration:underline}.sidebar ul li ul{padding:0}.sidebar ul li.active>a{color:var(--theme-color,#ea6f5a);font-weight:600}.markdown-section h1,.markdown-section h2,.markdown-section h3,.markdown-section h4,.markdown-section strong{color:#657b83;font-weight:600}.markdown-section a{color:var(--theme-color,#ea6f5a);font-weight:600}.markdown-section h1{font-size:2rem;margin:0 0 1rem}.markdown-section h2{font-size:1.75rem;margin:45px 0 .8rem}.markdown-section h3{font-size:1.5rem;margin:40px 0 .6rem}.markdown-section h4{font-size:1.25rem}.markdown-section h5{font-size:1rem}.markdown-section h6{color:#777;font-size:1rem}.markdown-section figure,.markdown-section ol,.markdown-section p,.markdown-section ul{margin:1.2em 0}.markdown-section ol,.markdown-section p,.markdown-section ul{line-height:1.6rem;word-spacing:.05rem}.markdown-section ol,.markdown-section ul{padding-left:1.5rem}.markdown-section blockquote{border-left:4px solid var(--theme-color,#ea6f5a);color:#858585;margin:2em 0;padding-left:20px}.markdown-section blockquote p{font-weight:600;margin-left:0}.markdown-section iframe{margin:1em 0}.markdown-section em{color:#7f8c8d}.markdown-section code{border-radius:2px;color:#657b83;font-size:.8rem;margin:0 2px;padding:3px 5px;white-space:pre-wrap}.markdown-section code,.markdown-section pre{background-color:#282828;font-family:Roboto Mono,Monaco,courier,monospace}.markdown-section pre{-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;line-height:1.5rem;margin:1.2em 0;overflow:auto;padding:0 1.4rem;position:relative;word-wrap:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#8e908c}.token.namespace{opacity:.7}.token.boolean,.token.number{color:#c76b29}.token.punctuation{color:#525252}.token.property{color:#c08b30}.token.tag{color:#2973b7}.token.string{color:var(--theme-color,#ea6f5a)}.token.selector{color:#6679cc}.token.attr-name{color:#2973b7}.language-css .token.string,.style .token.string,.token.entity,.token.url{color:#22a2c9}.token.attr-value,.token.control,.token.directive,.token.unit{color:var(--theme-color,#ea6f5a)}.token.keyword{color:#e96900}.token.atrule,.token.regex,.token.statement{color:#22a2c9}.token.placeholder,.token.variable{color:#3d8fd1}.token.deleted{text-decoration:line-through}.token.inserted{border-bottom:1px dotted #202746;text-decoration:none}.token.italic{font-style:italic}.token.bold,.token.important{font-weight:700}.token.important{color:#c94922}.token.entity{cursor:help}.markdown-section pre>code{-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;background-color:#282828;border-radius:2px;color:#657b83;display:block;font-family:Roboto Mono,Monaco,courier,monospace;font-size:.8rem;line-height:inherit;margin:0 2px;max-width:inherit;overflow:inherit;padding:2.2em 5px;white-space:inherit}.markdown-section code:after,.markdown-section code:before{letter-spacing:.05rem}code .token{-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;min-height:1.5rem}pre:after{color:#ccc;content:attr(data-lang);font-size:.6rem;font-weight:600;height:15px;line-height:15px;padding:5px 10px 0;position:absolute;right:0;text-align:right;top:0}.markdown-section p.tip{background-color:#282828;color:#657b83}input[type=search]{background:#4f4f4f;border-color:#4f4f4f;color:#c8c8c8}
--------------------------------------------------------------------------------
/lib/ast/walker/desugar.go:
--------------------------------------------------------------------------------
1 | package walker
2 |
3 | import (
4 | "github.com/champii/og/lib/common"
5 | )
6 |
7 | type Desugar struct {
8 | Templates *Templates
9 | }
10 |
11 | func (this *Desugar) Run(files []*common.File) {
12 | RunGobRegister()
13 | for _, file := range files {
14 | file.Ast = RunReturnable(file.Ast)
15 | RunTemplateLoader(file.Ast, this.Templates)
16 | RunTemplateParse(file, this.Templates)
17 | }
18 | this.Templates.Store()
19 | for _, file := range files {
20 | RunTemplateUsage(file, this.Templates)
21 | RunTemplateGenerator(file.Ast, this.Templates)
22 | this.Templates.ResetUsedFor()
23 | }
24 | }
25 | func NewDesugar() *Desugar {
26 | return &Desugar{Templates: NewTemplates()}
27 | }
28 |
--------------------------------------------------------------------------------
/lib/ast/walker/desugar.og:
--------------------------------------------------------------------------------
1 | !walker
2 |
3 | import
4 | "github.com/champii/og/lib/common"
5 |
6 | struct Desugar
7 | Templates *Templates
8 |
9 | Run(files []*common.File) ->
10 | RunGobRegister()
11 |
12 | for _, file in files
13 | file.Ast = RunReturnable(file.Ast)
14 | RunTemplateLoader(file.Ast, @Templates)
15 | RunTemplateParse(file, @Templates)
16 |
17 | @Templates.Store()
18 |
19 | for _, file in files
20 | RunTemplateUsage(file, @Templates)
21 | RunTemplateGenerator(file.Ast, @Templates)
22 | @Templates.ResetUsedFor()
23 |
24 | NewDesugar: *Desugar ->
25 | &Desugar
26 | Templates: NewTemplates()
27 |
--------------------------------------------------------------------------------
/lib/ast/walker/gob_register.go:
--------------------------------------------------------------------------------
1 | package walker
2 |
3 | import (
4 | "encoding/gob"
5 | "github.com/champii/og/lib/ast"
6 | )
7 |
8 | func RunGobRegister() {
9 | gob.Register(&Template{})
10 | gob.Register(&TemplateSerie{})
11 | gob.Register(&ast.SourceFile{})
12 | gob.Register(&ast.Package{})
13 | gob.Register(&ast.Import{})
14 | gob.Register(&ast.ImportSpec{})
15 | gob.Register(&ast.TopLevel{})
16 | gob.Register(&ast.Declaration{})
17 | gob.Register(&ast.ConstDecl{})
18 | gob.Register(&ast.ConstSpec{})
19 | gob.Register(&ast.ExpressionList{})
20 | gob.Register(&ast.Parameters{})
21 | gob.Register(&ast.TypeDecl{})
22 | gob.Register(&ast.TypeSpec{})
23 | gob.Register(&ast.FunctionDecl{})
24 | gob.Register(&ast.Function{})
25 | gob.Register(&ast.MethodDecl{})
26 | gob.Register(&ast.Receiver{})
27 | gob.Register(&ast.VarDecl{})
28 | gob.Register(&ast.VarSpec{})
29 | gob.Register(&ast.Block{})
30 | gob.Register(&ast.Statement{})
31 | gob.Register(&ast.SimpleStmt{})
32 | gob.Register(&ast.SendStmt{})
33 | gob.Register(&ast.IncDecStmt{})
34 | gob.Register(&ast.Assignment{})
35 | gob.Register(&ast.ShortVarDecl{})
36 | gob.Register(&ast.LabeledStmt{})
37 | gob.Register(&ast.ReturnStmt{})
38 | gob.Register(&ast.BreakStmt{})
39 | gob.Register(&ast.ContinueStmt{})
40 | gob.Register(&ast.GotoStmt{})
41 | gob.Register(&ast.FallthroughStmt{})
42 | gob.Register(&ast.DeferStmt{})
43 | gob.Register(&ast.IfStmt{})
44 | gob.Register(&ast.SwitchStmt{})
45 | gob.Register(&ast.ExprSwitchStmt{})
46 | gob.Register(&ast.ExprCaseClause{})
47 | gob.Register(&ast.ExprSwitchCase{})
48 | gob.Register(&ast.TypeSwitchStmt{})
49 | gob.Register(&ast.TypeSwitchGuard{})
50 | gob.Register(&ast.TypeCaseClause{})
51 | gob.Register(&ast.TypeSwitchCase{})
52 | gob.Register(&ast.SelectStmt{})
53 | gob.Register(&ast.CommClause{})
54 | gob.Register(&ast.CommCase{})
55 | gob.Register(&ast.RecvStmt{})
56 | gob.Register(&ast.ForStmt{})
57 | gob.Register(&ast.ForClause{})
58 | gob.Register(&ast.RangeClause{})
59 | gob.Register(&ast.GoStmt{})
60 | gob.Register(&ast.Type{})
61 | gob.Register(&ast.TypeLit{})
62 | gob.Register(&ast.ArrayType{})
63 | gob.Register(&ast.PointerType{})
64 | gob.Register(&ast.InterfaceType{})
65 | gob.Register(&ast.SliceType{})
66 | gob.Register(&ast.MapType{})
67 | gob.Register(&ast.ChannelType{})
68 | gob.Register(&ast.MethodSpec{})
69 | gob.Register(&ast.FunctionType{})
70 | gob.Register(&ast.Signature{})
71 | gob.Register(&ast.TemplateSpec{})
72 | gob.Register(&ast.Result{})
73 | gob.Register(&ast.Parameter{})
74 | gob.Register(&ast.Operand{})
75 | gob.Register(&ast.Literal{})
76 | gob.Register(&ast.OperandName{})
77 | gob.Register(&ast.CompositeLit{})
78 | gob.Register(&ast.LiteralType{})
79 | gob.Register(&ast.LiteralValue{})
80 | gob.Register(&ast.KeyedElement{})
81 | gob.Register(&ast.Key{})
82 | gob.Register(&ast.Element{})
83 | gob.Register(&ast.StructType{})
84 | gob.Register(&ast.FieldDecl{})
85 | gob.Register(&ast.IdentifierList{})
86 | gob.Register(&ast.InlineStructMethod{})
87 | gob.Register(&ast.AnonymousField{})
88 | gob.Register(&ast.FunctionLit{})
89 | gob.Register(&ast.PrimaryExpr{})
90 | gob.Register(&ast.SecondaryExpr{})
91 | gob.Register(&ast.Index{})
92 | gob.Register(&ast.Slice{})
93 | gob.Register(&ast.TypeAssertion{})
94 | gob.Register(&ast.Arguments{})
95 | gob.Register(&ast.MethodExpr{})
96 | gob.Register(&ast.ReceiverType{})
97 | gob.Register(&ast.Expression{})
98 | gob.Register(&ast.UnaryExpr{})
99 | gob.Register(&ast.Conversion{})
100 | gob.Register(&ast.Interpret{})
101 | }
102 |
--------------------------------------------------------------------------------
/lib/ast/walker/gob_register.og:
--------------------------------------------------------------------------------
1 | !walker
2 |
3 | import
4 | "encoding/gob"
5 | "github.com/champii/og/lib/ast"
6 |
7 | RunGobRegister ->
8 | gob.Register(&Template{})
9 | gob.Register(&TemplateSerie{})
10 | gob.Register(&ast.SourceFile{})
11 | gob.Register(&ast.Package{})
12 | gob.Register(&ast.Import{})
13 | gob.Register(&ast.ImportSpec{})
14 | gob.Register(&ast.TopLevel{})
15 | gob.Register(&ast.Declaration{})
16 | gob.Register(&ast.ConstDecl{})
17 | gob.Register(&ast.ConstSpec{})
18 | gob.Register(&ast.ExpressionList{})
19 | gob.Register(&ast.Parameters{})
20 | gob.Register(&ast.TypeDecl{})
21 | gob.Register(&ast.TypeSpec{})
22 | gob.Register(&ast.FunctionDecl{})
23 | gob.Register(&ast.Function{})
24 | gob.Register(&ast.MethodDecl{})
25 | gob.Register(&ast.Receiver{})
26 | gob.Register(&ast.VarDecl{})
27 | gob.Register(&ast.VarSpec{})
28 | gob.Register(&ast.Block{})
29 | gob.Register(&ast.Statement{})
30 | gob.Register(&ast.SimpleStmt{})
31 | gob.Register(&ast.SendStmt{})
32 | gob.Register(&ast.IncDecStmt{})
33 | gob.Register(&ast.Assignment{})
34 | gob.Register(&ast.ShortVarDecl{})
35 | gob.Register(&ast.LabeledStmt{})
36 | gob.Register(&ast.ReturnStmt{})
37 | gob.Register(&ast.BreakStmt{})
38 | gob.Register(&ast.ContinueStmt{})
39 | gob.Register(&ast.GotoStmt{})
40 | gob.Register(&ast.FallthroughStmt{})
41 | gob.Register(&ast.DeferStmt{})
42 | gob.Register(&ast.IfStmt{})
43 | gob.Register(&ast.SwitchStmt{})
44 | gob.Register(&ast.ExprSwitchStmt{})
45 | gob.Register(&ast.ExprCaseClause{})
46 | gob.Register(&ast.ExprSwitchCase{})
47 | gob.Register(&ast.TypeSwitchStmt{})
48 | gob.Register(&ast.TypeSwitchGuard{})
49 | gob.Register(&ast.TypeCaseClause{})
50 | gob.Register(&ast.TypeSwitchCase{})
51 | gob.Register(&ast.SelectStmt{})
52 | gob.Register(&ast.CommClause{})
53 | gob.Register(&ast.CommCase{})
54 | gob.Register(&ast.RecvStmt{})
55 | gob.Register(&ast.ForStmt{})
56 | gob.Register(&ast.ForClause{})
57 | gob.Register(&ast.RangeClause{})
58 | gob.Register(&ast.GoStmt{})
59 | gob.Register(&ast.Type{})
60 | gob.Register(&ast.TypeLit{})
61 | gob.Register(&ast.ArrayType{})
62 | gob.Register(&ast.PointerType{})
63 | gob.Register(&ast.InterfaceType{})
64 | gob.Register(&ast.SliceType{})
65 | gob.Register(&ast.MapType{})
66 | gob.Register(&ast.ChannelType{})
67 | gob.Register(&ast.MethodSpec{})
68 | gob.Register(&ast.FunctionType{})
69 | gob.Register(&ast.Signature{})
70 | gob.Register(&ast.TemplateSpec{})
71 | gob.Register(&ast.Result{})
72 | gob.Register(&ast.Parameter{})
73 | gob.Register(&ast.Operand{})
74 | gob.Register(&ast.Literal{})
75 | gob.Register(&ast.OperandName{})
76 | gob.Register(&ast.CompositeLit{})
77 | gob.Register(&ast.LiteralType{})
78 | gob.Register(&ast.LiteralValue{})
79 | gob.Register(&ast.KeyedElement{})
80 | gob.Register(&ast.Key{})
81 | gob.Register(&ast.Element{})
82 | gob.Register(&ast.StructType{})
83 | gob.Register(&ast.FieldDecl{})
84 | gob.Register(&ast.IdentifierList{})
85 | gob.Register(&ast.InlineStructMethod{})
86 | gob.Register(&ast.AnonymousField{})
87 | gob.Register(&ast.FunctionLit{})
88 | gob.Register(&ast.PrimaryExpr{})
89 | gob.Register(&ast.SecondaryExpr{})
90 | gob.Register(&ast.Index{})
91 | gob.Register(&ast.Slice{})
92 | gob.Register(&ast.TypeAssertion{})
93 | gob.Register(&ast.Arguments{})
94 | gob.Register(&ast.MethodExpr{})
95 | gob.Register(&ast.ReceiverType{})
96 | gob.Register(&ast.Expression{})
97 | gob.Register(&ast.UnaryExpr{})
98 | gob.Register(&ast.Conversion{})
99 | gob.Register(&ast.Interpret{})
100 |
--------------------------------------------------------------------------------
/lib/ast/walker/print.go:
--------------------------------------------------------------------------------
1 | package walker
2 |
3 | import (
4 | "fmt"
5 | "github.com/champii/og/lib/common"
6 | "github.com/fatih/color"
7 | "reflect"
8 | "strconv"
9 | "strings"
10 | )
11 |
12 | var (
13 | magenta = color.New(color.Bold, color.FgHiMagenta).SprintFunc()
14 | )
15 | var (
16 | yellow = color.New(color.FgHiYellow).SprintfFunc()
17 | )
18 | var (
19 | green = color.New(color.FgHiGreen).SprintfFunc()
20 | )
21 | var (
22 | cyan = color.New(color.FgCyan).SprintFunc()
23 | )
24 |
25 | type Printer struct {
26 | AstWalker
27 | Simple bool
28 | indent int
29 | }
30 |
31 | func (this *Printer) Before(n common.INode) {
32 | this.indent++
33 | }
34 | func (this *Printer) After(n common.INode) {
35 | this.indent--
36 | }
37 | func (this Printer) getTerminalText(n common.INode) string {
38 | txt := ""
39 | struc := reflect.ValueOf(n).Elem()
40 | for i := 0; i < struc.NumField(); i++ {
41 | if struc.Field(i).Kind() == reflect.String {
42 | txt = struc.Field(i).String()
43 | }
44 | if struc.Field(i).Kind() == reflect.Slice {
45 | if struc.Field(i).Type().Elem().Kind() == reflect.String {
46 | txt = strings.Join(struc.Field(i).Interface().([]string), ",")
47 | }
48 | }
49 | }
50 | return txt
51 | }
52 | func (this *Printer) Each(n common.INode) common.INode {
53 | name := reflect.TypeOf(n).String()[5:]
54 | txt := this.getTerminalText(n)
55 | if this.Simple && len(txt) == 0 {
56 | return n
57 | }
58 | line := fmt.Sprintf("(%s:%s):", yellow("%d", n.Line()), yellow("%d", n.Col()))
59 | line += strings.Repeat(" ", 8-len(strconv.Itoa(n.Line())+strconv.Itoa(n.Col())))
60 | if len(txt) > 0 {
61 | name = green(name)
62 | } else {
63 | name = cyan(name)
64 | }
65 | fmt.Printf("%s %s %s\n", line, strings.Repeat(" ", this.indent)+name, magenta(txt))
66 | return n
67 | }
68 | func Print(ast common.INode, simple bool) {
69 | p := Printer{Simple: simple}
70 | p.type_ = &p
71 | p.Walk(ast)
72 | }
73 |
--------------------------------------------------------------------------------
/lib/ast/walker/print.og:
--------------------------------------------------------------------------------
1 | !walker
2 |
3 | import
4 | fmt
5 | reflect
6 | strings
7 | strconv
8 | "github.com/fatih/color"
9 | "github.com/champii/og/lib/common"
10 |
11 | var magenta = color.New(color.Bold, color.FgHiMagenta).SprintFunc()
12 | var yellow = color.New(color.FgHiYellow).SprintfFunc()
13 | var green = color.New(color.FgHiGreen).SprintfFunc()
14 | var cyan = color.New(color.FgCyan).SprintFunc()
15 |
16 | struct Printer
17 | AstWalker
18 | Simple bool
19 | indent int
20 |
21 | *Before(n common.INode) -> @indent++
22 | *After(n common.INode) -> @indent--
23 |
24 | getTerminalText(n common.INode): string ->
25 | txt := ""
26 |
27 | struc := reflect.ValueOf(n).Elem()
28 | for i := 0; i < struc.NumField(); i++
29 | if struc.Field(i).Kind() == reflect.String
30 | txt = struc.Field(i).String()
31 | if struc.Field(i).Kind() == reflect.Slice
32 | if struc.Field(i).Type().Elem().Kind() == reflect.String
33 | txt = strings.Join(struc.Field(i).Interface().([]string), ",")
34 |
35 | txt
36 |
37 | *Each(n common.INode): common.INode ->
38 | name := reflect.TypeOf(n).String()[5:]
39 | txt := @getTerminalText(n)
40 |
41 | if @Simple && len(txt) == 0
42 | return n
43 |
44 | line := fmt.Sprintf("(%s:%s):", yellow("%d", n.Line()), yellow("%d", n.Col()))
45 | line += strings.Repeat(" ", 8 - len(strconv.Itoa(n.Line()) + strconv.Itoa(n.Col())))
46 |
47 | if len(txt) > 0
48 | name = green(name)
49 | else
50 | name = cyan(name)
51 |
52 | fmt.Printf("%s %s %s\n", line, strings.Repeat(" ", @indent) + name, magenta(txt))
53 |
54 | n
55 |
56 | Print(ast common.INode, simple bool) ->
57 | p := Printer
58 | Simple: simple
59 |
60 | p.type_ = &p
61 |
62 | p.Walk(ast)
63 |
--------------------------------------------------------------------------------
/lib/ast/walker/returnable.go:
--------------------------------------------------------------------------------
1 | package walker
2 |
3 | import (
4 | "github.com/champii/og/lib/ast"
5 | "github.com/champii/og/lib/common"
6 | )
7 |
8 | type Returnable struct {
9 | AstWalker
10 | Root common.INode
11 | }
12 |
13 | func (this *Returnable) VarDecl(n common.INode) common.INode {
14 | varDecl := n.(*ast.VarDecl)
15 | for _, varSpec := range varDecl.VarSpecs {
16 | statement := varSpec.Statement
17 | if statement == nil {
18 | continue
19 | }
20 | ifStmt := statement.IfStmt
21 | if ifStmt == nil {
22 | if statement.Block != nil && len(statement.Block.Statements) == 1 && statement.Block.Statements[0].IfStmt != nil {
23 | ifStmt = statement.Block.Statements[0].IfStmt
24 | } else {
25 | continue
26 | }
27 | }
28 | varSpec.Statement = ifStmt.MakeReturnClosureStatement(varSpec.Type)
29 | }
30 | return varDecl
31 | }
32 | func (this *Returnable) Function(n common.INode) common.INode {
33 | function := n.(*ast.Function)
34 | sig := function.Signature
35 | if sig == nil {
36 | return n
37 | }
38 | retType := sig.Result
39 | if retType == nil || len(retType.Types) != 1 {
40 | return n
41 | }
42 | block := function.Block
43 | if block != nil && len(block.Statements) > 0 {
44 | last := block.Statements[len(block.Statements)-1]
45 | if last.ReturnStmt == nil {
46 | if last.SimpleStmt != nil {
47 | block.AddReturn()
48 | }
49 | if last.IfStmt != nil {
50 | last.IfStmt.AddReturn()
51 | }
52 | }
53 | }
54 | return n
55 | }
56 | func RunReturnable(tree common.INode) common.INode {
57 | returnable := Returnable{Root: tree}
58 | returnable.type_ = &returnable
59 | return returnable.Walk(tree)
60 | }
61 |
--------------------------------------------------------------------------------
/lib/ast/walker/returnable.og:
--------------------------------------------------------------------------------
1 | !walker
2 |
3 | import
4 | "github.com/champii/og/lib/ast"
5 | "github.com/champii/og/lib/common"
6 |
7 | struct Returnable
8 | AstWalker
9 | Root common.INode
10 |
11 | *VarDecl(n common.INode): common.INode ->
12 | varDecl := n.(*ast.VarDecl)
13 | for _, varSpec in varDecl.VarSpecs
14 | statement := varSpec.Statement
15 |
16 | if statement == nil
17 | continue
18 |
19 | ifStmt := statement.IfStmt
20 | if ifStmt == nil
21 | /* Hack: Get the inner ifStmt if existant */
22 | if statement.Block != nil && len(statement.Block.Statements) == 1 && statement.Block.Statements[0].IfStmt != nil
23 | ifStmt = statement.Block.Statements[0].IfStmt
24 | else
25 | continue
26 |
27 | varSpec.Statement = ifStmt.MakeReturnClosureStatement(varSpec.Type)
28 |
29 | varDecl
30 |
31 | *Function(n common.INode): common.INode ->
32 | function := n.(*ast.Function)
33 | sig := function.Signature
34 |
35 | /* No signature means no return type */
36 | if sig == nil
37 | return n
38 |
39 | retType := sig.Result
40 |
41 | /* We don't support multiple return type (yet) */
42 | if retType == nil || len(retType.Types) != 1
43 | return n
44 |
45 | block := function.Block
46 | if block != nil && len(block.Statements) > 0
47 | last := block.Statements[len(block.Statements)-1]
48 |
49 | if last.ReturnStmt == nil
50 | if last.SimpleStmt != nil => block.AddReturn()
51 | if last.IfStmt != nil => last.IfStmt.AddReturn()
52 |
53 | n
54 |
55 | RunReturnable(tree common.INode): common.INode ->
56 | returnable := Returnable
57 | Root: tree
58 |
59 | returnable.type_ = &returnable
60 |
61 | returnable.Walk(tree)
62 |
--------------------------------------------------------------------------------
/lib/ast/walker/template.go:
--------------------------------------------------------------------------------
1 | package walker
2 |
3 | import (
4 | "bytes"
5 | "encoding/gob"
6 | "fmt"
7 | "github.com/champii/og/lib/common"
8 | "io/ioutil"
9 | "os"
10 | "path"
11 | "reflect"
12 | "strings"
13 | )
14 |
15 | type Template struct {
16 | Name string
17 | Pack string
18 | Types []string
19 | UsedFor [][]string
20 | GeneratedFor map[string][]string
21 | Node common.INode
22 | }
23 |
24 | func (this Template) contains(arr []string, str string) bool {
25 | for _, item := range arr {
26 | if str == item {
27 | return true
28 | }
29 | }
30 | return false
31 | }
32 | func (this *Template) IsGeneratedFor(types []string, packageName string) bool {
33 | serie := strings.Join(types, ",")
34 | packages, _ := this.GeneratedFor[serie]
35 | return this.contains(packages, packageName)
36 | }
37 | func (this *Template) AddGeneratedFor(types []string, packageName string) {
38 | serie := strings.Join(types, ",")
39 | packages, _ := this.GeneratedFor[serie]
40 | if !this.contains(packages, packageName) {
41 | this.GeneratedFor[serie] = append(this.GeneratedFor[serie], packageName)
42 | }
43 | }
44 | func (this *Template) AddUsedFor(types []string) {
45 | for _, usedFor := range this.UsedFor {
46 | if reflect.DeepEqual(types, usedFor) {
47 | return
48 | }
49 | }
50 | this.UsedFor = append(this.UsedFor, types)
51 | }
52 | func NewTemplate(name, pack string, types []string, node common.INode) *Template {
53 | return &Template{
54 | Name: name,
55 | Pack: pack,
56 | Types: types,
57 | UsedFor: [][]string{},
58 | Node: node,
59 | GeneratedFor: make(map[string][]string),
60 | }
61 | }
62 |
63 | type Templates struct {
64 | Names []string
65 | Packages []string
66 | Templates []*Template
67 | }
68 |
69 | func (this *Templates) Add(name, pack string, template *Template) {
70 | this.Names = append(this.Names, name)
71 | this.Packages = append(this.Packages, pack)
72 | this.Templates = append(this.Templates, template)
73 | }
74 | func (this *Templates) Get(name, pack string) *Template {
75 | for i, n := range this.Names {
76 | if n == name && this.Packages[i] == pack {
77 | return this.Templates[i]
78 | }
79 | }
80 | return nil
81 | }
82 | func (this Templates) ResetUsedFor() {
83 | for _, template := range this.Templates {
84 | template.UsedFor = [][]string{}
85 | }
86 | }
87 | func (this *Templates) Decode(content []byte) {
88 | arr := []*TemplateSerie{}
89 | buf := bytes.NewBuffer(content)
90 | dec := gob.NewDecoder(buf)
91 | if err := dec.Decode(&arr); err != nil {
92 | panic("ERROR DECODE" + err.Error())
93 | }
94 | for _, tmpl := range arr {
95 | this.Add(tmpl.Name, tmpl.Template.Pack, tmpl.Template)
96 | }
97 | }
98 | func (this *Templates) Encode(arr []*Template) []byte {
99 | res := []*TemplateSerie{}
100 | for _, template := range arr {
101 | res = append(res, &TemplateSerie{
102 | template.Name,
103 | template,
104 | })
105 | }
106 | var (
107 | buf bytes.Buffer
108 | )
109 | enc := gob.NewEncoder(&buf)
110 | if err := enc.Encode(&res); err != nil {
111 | panic("ERROR ENCODE" + err.Error())
112 | }
113 | return buf.Bytes()
114 | }
115 | func (this *Templates) byPackage() map[string][]*Template {
116 | res := make(map[string][]*Template)
117 | for _, template := range this.Templates {
118 | res[template.Pack] = append(res[template.Pack], template)
119 | }
120 | return res
121 | }
122 | func (this Templates) Store() {
123 | for pack, arr := range this.byPackage() {
124 | templateDir := path.Join(pack, ".og")
125 | _, err := os.Stat(templateDir)
126 | if err != nil {
127 | err = os.Mkdir(templateDir, 0755)
128 | if err != nil {
129 | fmt.Println("Cannot create template directory: " + templateDir)
130 | return
131 | }
132 | }
133 | blob := this.Encode(arr)
134 | ioutil.WriteFile(path.Join(templateDir, "template"), blob, 0644)
135 | }
136 | }
137 | func NewTemplates() *Templates {
138 | return &Templates{}
139 | }
140 |
141 | type TemplateSerie struct {
142 | Name string
143 | Template *Template
144 | }
145 |
--------------------------------------------------------------------------------
/lib/ast/walker/template.og:
--------------------------------------------------------------------------------
1 | !walker
2 |
3 | import
4 | os
5 | fmt
6 | path
7 | bytes
8 | strings
9 | reflect
10 | "io/ioutil"
11 | "encoding/gob"
12 | "github.com/champii/og/lib/common"
13 |
14 | struct Template
15 | Name string
16 | Pack string
17 | Types []string
18 | UsedFor [][]string
19 | GeneratedFor map[string][]string // Join(UsedFor[i], ",") -> []PackageName
20 | Node common.INode
21 |
22 | contains(arr []string, str string): bool ->
23 | for _, item in arr
24 | if str == item
25 | return true
26 |
27 | false
28 |
29 | *IsGeneratedFor(types []string, packageName string): bool ->
30 | serie := strings.Join(types, ",")
31 |
32 | packages, _ := @GeneratedFor[serie]
33 |
34 | return @contains(packages, packageName)
35 |
36 | *AddGeneratedFor(types []string, packageName string) ->
37 | serie := strings.Join(types, ",")
38 |
39 | packages, _ := @GeneratedFor[serie]
40 |
41 | if !@contains(packages, packageName)
42 | @GeneratedFor[serie] = append(@GeneratedFor[serie], packageName)
43 |
44 | *AddUsedFor(types []string) ->
45 | for _, usedFor in @UsedFor
46 | if reflect.DeepEqual(types, usedFor)
47 | return
48 |
49 | @UsedFor = append(@UsedFor, types)
50 |
51 | NewTemplate(name, pack string, types []string, node common.INode): *Template ->
52 | &Template
53 | Name: name
54 | Pack: pack
55 | Types: types
56 | UsedFor: [][]string{}
57 | Node: node
58 | GeneratedFor: make(map[string][]string)
59 |
60 | struct Templates
61 | Names []string
62 | Packages []string
63 | Templates []*Template
64 |
65 | *Add(name, pack string, template *Template) ->
66 | @Names = append(@Names, name)
67 | @Packages = append(@Packages, pack)
68 | @Templates = append(@Templates, template)
69 |
70 | Get(name, pack string): *Template ->
71 | for i, n in @Names
72 | if n == name && @Packages[i] == pack
73 | return @Templates[i]
74 |
75 | return nil
76 |
77 | ResetUsedFor ->
78 | for _, template in @Templates
79 | template.UsedFor = [][]string{}
80 |
81 | *Decode(content []byte) ->
82 | arr := []*TemplateSerie{}
83 |
84 | buf := bytes.NewBuffer(content)
85 |
86 | dec := gob.NewDecoder(buf)
87 |
88 | if err := dec.Decode(&arr); err != nil
89 | panic("ERROR DECODE" + err.Error())
90 |
91 | for _, tmpl in arr
92 | @Add(tmpl.Name, tmpl.Template.Pack, tmpl.Template)
93 |
94 | Encode(arr []*Template): []byte ->
95 | res := []*TemplateSerie{}
96 |
97 | for _, template in arr
98 | res = append(res, &TemplateSerie{template.Name, template})
99 |
100 | var buf bytes.Buffer
101 |
102 | enc := gob.NewEncoder(&buf)
103 |
104 | if err := enc.Encode(&res); err != nil
105 | panic("ERROR ENCODE" + err.Error())
106 |
107 | buf.Bytes()
108 |
109 | byPackage: map[string][]*Template ->
110 | res := make(map[string][]*Template)
111 |
112 | for _, template in @Templates
113 | res[template.Pack] = append(res[template.Pack], template)
114 |
115 | res
116 |
117 | Store ->
118 | for pack, arr in @byPackage()
119 | templateDir := path.Join(pack, ".og")
120 |
121 | _, err := os.Stat(templateDir)
122 |
123 | if err != nil
124 | err = os.Mkdir(templateDir, 0755)
125 | if err != nil
126 | fmt.Println("Cannot create template directory: " + templateDir)
127 | return
128 |
129 | blob := @Encode(arr)
130 |
131 | ioutil.WriteFile(path.Join(templateDir, "template"), blob, 0644)
132 |
133 | NewTemplates: *Templates ->
134 | &Templates{}
135 |
136 | struct TemplateSerie
137 | Name string
138 | Template *Template
--------------------------------------------------------------------------------
/lib/ast/walker/template_generator.go:
--------------------------------------------------------------------------------
1 | package walker
2 |
3 | import (
4 | "bytes"
5 | "encoding/gob"
6 | "fmt"
7 | "github.com/champii/og/lib/ast"
8 | "github.com/champii/og/lib/common"
9 | "path"
10 | "strings"
11 | )
12 |
13 | type TemplateGenerator struct {
14 | Root common.INode
15 | }
16 |
17 | func (this *TemplateGenerator) GenerateStruct(template *Template) {
18 | source := this.Root.(*ast.SourceFile)
19 | for _, usedFor := range template.UsedFor {
20 | if template.IsGeneratedFor(usedFor, source.Package.Eval()) {
21 | continue
22 | }
23 | other := &ast.StructType{}
24 | var (
25 | buf bytes.Buffer
26 | )
27 | enc := gob.NewEncoder(&buf)
28 | if err := enc.Encode(template.Node.(*ast.StructType)); err != nil {
29 | fmt.Println("ERROR ENCODE", err)
30 | }
31 | dec := gob.NewDecoder(&buf)
32 | if err := dec.Decode(&other); err != nil {
33 | fmt.Println("ERROR DECODE", err)
34 | }
35 | newStruct := RunTemplateReplace(other, template.Types, usedFor).(*ast.StructType)
36 | prefix := path.Base(template.Pack) + "_"
37 | newStruct.Name = prefix + newStruct.Name + "_" + strings.Join(usedFor, "_")
38 | topLevel := &ast.TopLevel{Declaration: &ast.Declaration{TypeDecl: &ast.TypeDecl{StructType: newStruct},
39 | },
40 | }
41 | source.TopLevels = append(source.TopLevels, topLevel)
42 | template.AddGeneratedFor(usedFor, source.Package.Eval())
43 | }
44 | }
45 | func (this *TemplateGenerator) GenerateTopFns(template *Template) {
46 | source := this.Root.(*ast.SourceFile)
47 | for _, usedFor := range template.UsedFor {
48 | if template.IsGeneratedFor(usedFor, source.Package.Eval()) {
49 | continue
50 | }
51 | other := &ast.FunctionDecl{}
52 | var (
53 | buf bytes.Buffer
54 | )
55 | enc := gob.NewEncoder(&buf)
56 | if err := enc.Encode(template.Node.(*ast.FunctionDecl)); err != nil {
57 | fmt.Println("ERROR ENCODE", err)
58 | }
59 | dec := gob.NewDecoder(&buf)
60 | if err := dec.Decode(&other); err != nil {
61 | fmt.Println("ERROR DECODE", err)
62 | }
63 | newFn := RunTemplateReplace(other, template.Types, usedFor).(*ast.FunctionDecl)
64 | prefix := path.Base(template.Pack) + "_"
65 | newFn.Name = prefix + newFn.Name + "_" + strings.Join(usedFor, "_")
66 | topLevel := &ast.TopLevel{FunctionDecl: newFn}
67 | source.TopLevels = append(source.TopLevels, topLevel)
68 | template.AddGeneratedFor(usedFor, source.Package.Eval())
69 | }
70 | }
71 | func (this *TemplateGenerator) GenerateTemplates(templates *Templates) {
72 | if this.Root == nil {
73 | return
74 | }
75 | source := this.Root.(*ast.SourceFile)
76 | for _, template := range templates.Templates {
77 | topArr := source.TopLevels
78 | for i, top := range topArr {
79 | if top.FunctionDecl == template.Node || (top.Declaration != nil && top.Declaration.TypeDecl != nil && top.Declaration.TypeDecl.StructType != nil && top.Declaration.TypeDecl.StructType == template.Node) {
80 | if len(topArr)-1 == i {
81 | source.TopLevels = source.TopLevels[:i]
82 | } else if i == 0 {
83 | source.TopLevels = source.TopLevels[1:]
84 | } else {
85 | source.TopLevels = append(source.TopLevels[0:i], source.TopLevels[i+1:]...)
86 | }
87 | break
88 | }
89 | }
90 | switch template.Node.(type) {
91 | case *ast.FunctionDecl:
92 | this.GenerateTopFns(template)
93 | case *ast.StructType:
94 | this.GenerateStruct(template)
95 | }
96 | }
97 | }
98 | func RunTemplateGenerator(tree common.INode, templates *Templates) {
99 | templateGenerator := TemplateGenerator{Root: tree}
100 | templateGenerator.GenerateTemplates(templates)
101 | }
102 |
--------------------------------------------------------------------------------
/lib/ast/walker/template_generator.og:
--------------------------------------------------------------------------------
1 | !walker
2 |
3 | import
4 | fmt
5 | path
6 | bytes
7 | strings
8 | "encoding/gob"
9 | "github.com/champii/og/lib/ast"
10 | "github.com/champii/og/lib/common"
11 |
12 | struct TemplateGenerator
13 | Root common.INode
14 |
15 | *GenerateStruct(template *Template) ->
16 | source := @Root.(*ast.SourceFile)
17 |
18 | for _, usedFor in template.UsedFor
19 | if template.IsGeneratedFor(usedFor, source.Package.Eval())
20 | continue
21 |
22 | other := &ast.StructType{}
23 |
24 | var buf bytes.Buffer
25 | enc := gob.NewEncoder(&buf)
26 | if err := enc.Encode(template.Node.(*ast.StructType)); err != nil
27 | fmt.Println("ERROR ENCODE", err)
28 |
29 | dec := gob.NewDecoder(&buf)
30 | if err := dec.Decode(&other); err != nil
31 | fmt.Println("ERROR DECODE", err)
32 |
33 | newStruct := RunTemplateReplace(other, template.Types, usedFor).(*ast.StructType)
34 |
35 | prefix := path.Base(template.Pack) + "_"
36 |
37 | newStruct.Name = prefix + newStruct.Name + "_" + strings.Join(usedFor, "_")
38 |
39 | topLevel := &ast.TopLevel
40 | Declaration: &ast.Declaration
41 | TypeDecl: &ast.TypeDecl
42 | StructType: newStruct
43 |
44 | source.TopLevels = append(source.TopLevels, topLevel)
45 |
46 | template.AddGeneratedFor(usedFor, source.Package.Eval())
47 |
48 | *GenerateTopFns(template *Template) ->
49 | source := @Root.(*ast.SourceFile)
50 |
51 | for _, usedFor in template.UsedFor
52 | if template.IsGeneratedFor(usedFor, source.Package.Eval())
53 | continue
54 |
55 | other := &ast.FunctionDecl{}
56 |
57 | var buf bytes.Buffer
58 | enc := gob.NewEncoder(&buf)
59 | if err := enc.Encode(template.Node.(*ast.FunctionDecl)); err != nil
60 | fmt.Println("ERROR ENCODE", err)
61 |
62 | dec := gob.NewDecoder(&buf)
63 | if err := dec.Decode(&other); err != nil
64 | fmt.Println("ERROR DECODE", err)
65 |
66 | newFn := RunTemplateReplace(other, template.Types, usedFor).(*ast.FunctionDecl)
67 |
68 | prefix := path.Base(template.Pack) + "_"
69 |
70 | newFn.Name = prefix + newFn.Name + "_" + strings.Join(usedFor, "_")
71 |
72 | topLevel := &ast.TopLevel{FunctionDecl: newFn}
73 |
74 | source.TopLevels = append(source.TopLevels, topLevel)
75 |
76 | template.AddGeneratedFor(usedFor, source.Package.Eval())
77 |
78 | *GenerateTemplates(templates *Templates) ->
79 | if @Root == nil
80 | return
81 |
82 | source := @Root.(*ast.SourceFile)
83 |
84 | for _, template in templates.Templates
85 | topArr := source.TopLevels
86 | for i, top in topArr
87 | if top.FunctionDecl == template.Node || (top.Declaration != nil && top.Declaration.TypeDecl != nil && top.Declaration.TypeDecl.StructType != nil && top.Declaration.TypeDecl.StructType == template.Node)
88 | if len(topArr) - 1 == i => source.TopLevels = source.TopLevels[:i]
89 | else if i == 0 => source.TopLevels = source.TopLevels[1:]
90 | else => source.TopLevels = append(source.TopLevels[0:i], source.TopLevels[i+1:]...)
91 | break
92 |
93 | switch template.Node.(type)
94 | *ast.FunctionDecl => @GenerateTopFns(template);
95 | *ast.StructType => @GenerateStruct(template)
96 |
97 | RunTemplateGenerator(tree common.INode, templates *Templates) ->
98 | templateGenerator := TemplateGenerator
99 | Root: tree
100 |
101 | templateGenerator.GenerateTemplates(templates)
102 |
--------------------------------------------------------------------------------
/lib/ast/walker/template_loader.go:
--------------------------------------------------------------------------------
1 | package walker
2 |
3 | import (
4 | "github.com/champii/og/lib/ast"
5 | "github.com/champii/og/lib/common"
6 | "io/ioutil"
7 | "os"
8 | "path"
9 | )
10 |
11 | func load(dir string, templates *Templates) {
12 | templateDir := path.Join(os.Getenv("GOPATH"), "src", dir, ".og")
13 | _, err := os.Stat(templateDir)
14 | if err != nil {
15 | return
16 | }
17 | content, err := ioutil.ReadFile(path.Join(templateDir, "template"))
18 | if err != nil {
19 | return
20 | }
21 | templates.Decode(content)
22 | }
23 | func RunTemplateLoader(tree common.INode, templates *Templates) {
24 | imports := tree.(*ast.SourceFile).Import
25 | if imports == nil {
26 | return
27 | }
28 | for _, imp := range imports.Items {
29 | load(imp.Path[1:len(imp.Path)-2], templates)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/lib/ast/walker/template_loader.og:
--------------------------------------------------------------------------------
1 | !walker
2 |
3 | import
4 | os
5 | path
6 | "io/ioutil"
7 | "github.com/champii/og/lib/ast"
8 | "github.com/champii/og/lib/common"
9 |
10 | load(dir string, templates *Templates) ->
11 | templateDir := path.Join(os.Getenv("GOPATH"), "src", dir, ".og")
12 |
13 | _, err := os.Stat(templateDir)
14 |
15 | if err != nil
16 | return
17 |
18 | content, err := ioutil.ReadFile(path.Join(templateDir, "template"))
19 |
20 | if err != nil
21 | return
22 |
23 | templates.Decode(content)
24 |
25 | RunTemplateLoader(tree common.INode, templates *Templates) ->
26 | imports := tree.(*ast.SourceFile).Import
27 |
28 | if imports == nil
29 | return
30 |
31 | for _, imp in imports.Items
32 | load(imp.Path[1:len(imp.Path)-2], templates)
33 |
--------------------------------------------------------------------------------
/lib/ast/walker/template_parse.go:
--------------------------------------------------------------------------------
1 | package walker
2 |
3 | import (
4 | "github.com/champii/og/lib/ast"
5 | "github.com/champii/og/lib/common"
6 | "path"
7 | )
8 |
9 | type TemplateParse struct {
10 | AstWalker
11 | Root common.INode
12 | Package string
13 | Templates *Templates
14 | ImportName string
15 | }
16 |
17 | func (this *TemplateParse) StructType(n common.INode) common.INode {
18 | structType := n.(*ast.StructType)
19 | if structType.TemplateSpec != nil {
20 | types := []string{}
21 | for _, t := range structType.TemplateSpec.Result.Types {
22 | types = append(types, t.Eval())
23 | }
24 | this.Templates.Add(structType.Name, this.ImportName, NewTemplate(structType.Name, this.ImportName, types, structType))
25 | }
26 | return n
27 | }
28 | func (this *TemplateParse) Signature(n common.INode) common.INode {
29 | sig := n.(*ast.Signature)
30 | if sig.TemplateSpec != nil {
31 | if f, ok := sig.GetParent().(*ast.Function); ok {
32 | fDecl := f.GetParent().(*ast.FunctionDecl)
33 | types := []string{}
34 | for _, t := range sig.TemplateSpec.Result.Types {
35 | types = append(types, t.Eval())
36 | }
37 | this.Templates.Add(fDecl.Name, this.ImportName, NewTemplate(fDecl.Name, this.ImportName, types, fDecl))
38 | }
39 | }
40 | return n
41 | }
42 | func RunTemplateParse(file *common.File, templates *Templates) {
43 | templateParse := TemplateParse{
44 | Root: file.Ast,
45 | Templates: templates,
46 | Package: file.Ast.(*ast.SourceFile).Package.Name,
47 | ImportName: path.Dir(file.FullPath),
48 | }
49 | templateParse.type_ = &templateParse
50 | templateParse.Walk(file.Ast)
51 | }
52 |
--------------------------------------------------------------------------------
/lib/ast/walker/template_parse.og:
--------------------------------------------------------------------------------
1 | !walker
2 |
3 | import
4 | path
5 | "github.com/champii/og/lib/ast"
6 | "github.com/champii/og/lib/common"
7 |
8 | struct TemplateParse
9 | AstWalker
10 | Root common.INode
11 | Package string
12 | Templates *Templates
13 | ImportName string
14 |
15 | *StructType(n common.INode): common.INode ->
16 | structType := n.(*ast.StructType)
17 | if structType.TemplateSpec != nil
18 | types := []string{}
19 | for _, t in structType.TemplateSpec.Result.Types
20 | types = append(types, t.Eval())
21 |
22 | @Templates.Add(structType.Name, @ImportName, NewTemplate(structType.Name, @ImportName, types, structType))
23 | n
24 |
25 | *Signature(n common.INode): common.INode ->
26 | sig := n.(*ast.Signature)
27 | if sig.TemplateSpec != nil
28 |
29 | if f, ok := sig.GetParent().(*ast.Function); ok
30 | fDecl := f.GetParent().(*ast.FunctionDecl)
31 |
32 | types := []string{}
33 | for _, t in sig.TemplateSpec.Result.Types
34 | types = append(types, t.Eval())
35 |
36 | @Templates.Add(fDecl.Name, @ImportName, NewTemplate(fDecl.Name, @ImportName, types, fDecl))
37 | n
38 |
39 | RunTemplateParse(file *common.File, templates *Templates) ->
40 | templateParse := TemplateParse
41 | Root: file.Ast
42 | Templates: templates
43 | Package: file.Ast.(*ast.SourceFile).Package.Name
44 | ImportName: path.Dir(file.FullPath)
45 |
46 | templateParse.type_ = &templateParse
47 |
48 | templateParse.Walk(file.Ast)
49 |
--------------------------------------------------------------------------------
/lib/ast/walker/template_replace.go:
--------------------------------------------------------------------------------
1 | package walker
2 |
3 | import (
4 | "github.com/champii/og/lib/ast"
5 | "github.com/champii/og/lib/common"
6 | )
7 |
8 | type TemplateReplace struct {
9 | AstWalker
10 | typeSrc []string
11 | typeDest []string
12 | }
13 |
14 | func (this *TemplateReplace) Type(n common.INode) common.INode {
15 | t := n.(*ast.Type)
16 | tName := t.Eval()
17 | for i, ty := range this.typeSrc {
18 | if tName == ty {
19 | t.TypeName = this.typeDest[i]
20 | t.TypeLit = nil
21 | t.Type = nil
22 | }
23 | }
24 | return n
25 | }
26 | func RunTemplateReplace(tree common.INode, typeSrc []string, typeDest []string) common.INode {
27 | templateReplace := TemplateReplace{
28 | typeSrc: typeSrc,
29 | typeDest: typeDest,
30 | }
31 | templateReplace.type_ = &templateReplace
32 | return templateReplace.Walk(tree)
33 | }
34 |
--------------------------------------------------------------------------------
/lib/ast/walker/template_replace.og:
--------------------------------------------------------------------------------
1 | !walker
2 |
3 | import
4 | "github.com/champii/og/lib/ast"
5 | "github.com/champii/og/lib/common"
6 |
7 | struct TemplateReplace
8 | AstWalker
9 | typeSrc []string
10 | typeDest []string
11 |
12 | *Type(n common.INode): common.INode ->
13 | t := n.(*ast.Type)
14 | tName := t.Eval()
15 | for i, ty in @typeSrc
16 | if tName == ty
17 | t.TypeName = @typeDest[i]
18 | t.TypeLit = nil
19 | t.Type = nil
20 | n
21 |
22 | RunTemplateReplace(tree common.INode, typeSrc []string, typeDest []string): common.INode ->
23 | templateReplace := TemplateReplace
24 | typeSrc: typeSrc
25 | typeDest: typeDest
26 |
27 | templateReplace.type_ = &templateReplace
28 |
29 | templateReplace.Walk(tree)
30 |
--------------------------------------------------------------------------------
/lib/ast/walker/template_usage.go:
--------------------------------------------------------------------------------
1 | package walker
2 |
3 | import (
4 | "github.com/champii/og/lib/ast"
5 | "github.com/champii/og/lib/common"
6 | "os"
7 | "path"
8 | "strings"
9 | )
10 |
11 | type TemplateUsage struct {
12 | AstWalker
13 | File *common.File
14 | Root common.INode
15 | Package string
16 | Templates *Templates
17 | }
18 |
19 | func (this *TemplateUsage) computeTypes(callee common.INode, templateSpec *ast.TemplateSpec) string {
20 | calleeName := callee.Eval()
21 | types := []string{}
22 | for _, t := range templateSpec.Result.Types {
23 | types = append(types, t.Eval())
24 | }
25 | splited := strings.Split(calleeName, ".")
26 | pack := this.Package
27 | if len(splited) > 1 {
28 | pack = this.File.Imports[splited[0]]
29 | calleeName = splited[1]
30 | }
31 | template := this.Templates.Get(calleeName, pack)
32 | if template == nil {
33 | err := this.File.Error(callee.Line(), callee.Col(), "Unknown template name", callee.Eval())
34 | common.Print.Error(err)
35 | os.Exit(1)
36 | return calleeName
37 | }
38 | template.AddUsedFor(types)
39 | prefix := path.Base(template.Pack) + "_"
40 | return prefix + calleeName + "_" + strings.Join(types, "_")
41 | }
42 | func (this *TemplateUsage) Arguments(n common.INode) common.INode {
43 | args := n.(*ast.Arguments)
44 | if args.TemplateSpec != nil {
45 | callee := args.GetParent().(*ast.SecondaryExpr).GetParent().(*ast.PrimaryExpr).PrimaryExpr.Operand
46 | callee.OperandName.Name = this.computeTypes(callee, args.TemplateSpec)
47 | }
48 | return n
49 | }
50 | func (this *TemplateUsage) CompositeLit(n common.INode) common.INode {
51 | composite := n.(*ast.CompositeLit)
52 | if composite.TemplateSpec != nil {
53 | callee := composite.LiteralType
54 | callee.Type = this.computeTypes(callee, composite.TemplateSpec)
55 | }
56 | return n
57 | }
58 | func RunTemplateUsage(file *common.File, templates *Templates) {
59 | templateUsage := TemplateUsage{
60 | Root: file.Ast,
61 | File: file,
62 | Templates: templates,
63 | Package: path.Dir(file.FullPath),
64 | }
65 | templateUsage.type_ = &templateUsage
66 | templateUsage.Walk(file.Ast)
67 | }
68 |
--------------------------------------------------------------------------------
/lib/ast/walker/template_usage.og:
--------------------------------------------------------------------------------
1 | !walker
2 |
3 | import
4 | os
5 | path
6 | strings
7 | "github.com/champii/og/lib/ast"
8 | "github.com/champii/og/lib/common"
9 |
10 | struct TemplateUsage
11 | AstWalker
12 | File *common.File
13 | Root common.INode
14 | Package string
15 | Templates *Templates
16 |
17 | *computeTypes(callee common.INode, templateSpec *ast.TemplateSpec): string ->
18 | calleeName := callee.Eval()
19 |
20 | types := []string{}
21 |
22 | for _, t in templateSpec.Result.Types
23 | types = append(types, t.Eval())
24 |
25 | splited := strings.Split(calleeName, ".")
26 | pack := @Package
27 | if len(splited) > 1
28 | pack = @File.Imports[splited[0]]
29 | calleeName = splited[1]
30 |
31 | template := @Templates.Get(calleeName, pack)
32 |
33 | if template == nil
34 | err := @File.Error(callee.Line(), callee.Col(), "Unknown template name", callee.Eval())
35 | common.Print.Error(err)
36 | os.Exit(1)
37 | return calleeName
38 |
39 | template.AddUsedFor(types)
40 |
41 | prefix := path.Base(template.Pack) + "_"
42 |
43 | prefix + calleeName + "_" + strings.Join(types, "_")
44 |
45 | *Arguments(n common.INode): common.INode ->
46 | args := n.(*ast.Arguments)
47 |
48 | if args.TemplateSpec != nil
49 | callee := args.GetParent().(*ast.SecondaryExpr).GetParent().(*ast.PrimaryExpr).PrimaryExpr.Operand
50 | callee.OperandName.Name = @computeTypes(callee, args.TemplateSpec)
51 |
52 | n
53 |
54 | *CompositeLit(n common.INode): common.INode ->
55 | composite := n.(*ast.CompositeLit)
56 |
57 | if composite.TemplateSpec != nil
58 | callee := composite.LiteralType
59 | callee.Type = @computeTypes(callee, composite.TemplateSpec)
60 |
61 | n
62 |
63 | RunTemplateUsage(file *common.File, templates *Templates) ->
64 | templateUsage := TemplateUsage
65 | Root: file.Ast
66 | File: file
67 | Templates: templates
68 | Package: path.Dir(file.FullPath)
69 |
70 | templateUsage.type_ = &templateUsage
71 |
72 | templateUsage.Walk(file.Ast)
73 |
--------------------------------------------------------------------------------
/lib/ast/walker/type_checker.go:
--------------------------------------------------------------------------------
1 | package walker
2 |
3 | import (
4 | "github.com/champii/og/lib/common"
5 | )
6 |
7 | type FuncSig struct {
8 | name string
9 | arguments map[string]string
10 | returns map[string]string
11 | }
12 |
13 | func NewFuncSig() *FuncSig {
14 | return &FuncSig{
15 | arguments: make(map[string]string),
16 | returns: make(map[string]string),
17 | }
18 | }
19 |
20 | type Scope struct {
21 | vars map[string]string
22 | funcs map[string]*FuncSig
23 | }
24 |
25 | func NewScope() *Scope {
26 | return &Scope{vars: make(map[string]string)}
27 | }
28 |
29 | type Stack struct {
30 | scopes []*Scope
31 | }
32 |
33 | func (this *Stack) PushScope() {
34 | this.scopes = append([]*Scope{NewScope()}, this.scopes...)
35 | }
36 | func (this *Stack) PopScope() {
37 | this.scopes = this.scopes[1:]
38 | }
39 | func (this *Stack) AddVar(name, t string) bool {
40 | if _, ok := this.GetVar(name); ok {
41 | return false
42 | }
43 | this.scopes[0].vars[name] = t
44 | return true
45 | }
46 | func (this *Stack) GetVar(name string) (string, bool) {
47 | for _, scope := range this.scopes {
48 | if t, ok := scope.vars[name]; ok {
49 | return t, true
50 | }
51 | }
52 | return "", false
53 | }
54 | func (this *Stack) AddFunc(name string, f *FuncSig) bool {
55 | if r := this.GetFunc(name); r != nil {
56 | return false
57 | }
58 | this.scopes[0].funcs[name] = f
59 | return true
60 | }
61 | func (this *Stack) GetFunc(name string) *FuncSig {
62 | for _, scope := range this.scopes {
63 | if f, ok := scope.funcs[name]; ok {
64 | return f
65 | }
66 | }
67 | return nil
68 | }
69 |
70 | type TypeChecker struct {
71 | AstWalker
72 | stack *Stack
73 | }
74 |
75 | func (this *TypeChecker) VarSpec(n common.INode) common.INode {
76 | return n
77 | }
78 | func (this *TypeChecker) Assignment(n common.INode) common.INode {
79 | return n
80 | }
81 | func (this *TypeChecker) BeforeBlock(n common.INode) {
82 | this.stack.PushScope()
83 | }
84 | func (this *TypeChecker) AfterBlock(n common.INode) {
85 | this.stack.PopScope()
86 | }
87 | func (this *TypeChecker) Each(n common.INode) common.INode {
88 | return n
89 | }
90 | func TypeCheck(ast common.INode) {
91 | t := TypeChecker{stack: &Stack{}}
92 | t.stack.PushScope()
93 | t.type_ = &t
94 | t.Walk(ast)
95 | }
96 |
--------------------------------------------------------------------------------
/lib/ast/walker/type_checker.og:
--------------------------------------------------------------------------------
1 | !walker
2 |
3 | import
4 | "github.com/champii/og/lib/common"
5 |
6 | struct FuncSig
7 | name string
8 | arguments map[string]string
9 | returns map[string]string
10 |
11 | NewFuncSig: *FuncSig ->
12 | &FuncSig
13 | arguments: make(map[string]string)
14 | returns: make(map[string]string)
15 |
16 | struct Scope
17 | vars map[string]string
18 | funcs map[string]*FuncSig
19 |
20 | NewScope: *Scope ->
21 | &Scope
22 | vars: make(map[string]string)
23 |
24 | struct Stack
25 | scopes []*Scope
26 | *PushScope -> @scopes = append([]*Scope{NewScope()}, @scopes...)
27 | *PopScope -> @scopes = @scopes[1:]
28 | *AddVar(name, t string): bool ->
29 | if _, ok := @GetVar(name); ok
30 | return false
31 |
32 | @scopes[0].vars[name] = t
33 |
34 | true
35 |
36 | *GetVar(name string): string, bool ->
37 | for _, scope in @scopes
38 | if t, ok := scope.vars[name]; ok
39 | return t, true
40 | return "", false
41 |
42 | *AddFunc(name string, f *FuncSig): bool ->
43 | if r := @GetFunc(name); r != nil
44 | return false
45 |
46 | @scopes[0].funcs[name] = f
47 |
48 | true
49 |
50 | *GetFunc(name string): *FuncSig ->
51 | for _, scope in @scopes
52 | if f, ok := scope.funcs[name]; ok
53 | return f
54 | return nil
55 |
56 | struct TypeChecker
57 | AstWalker
58 | stack *Stack
59 |
60 | *VarSpec(n common.INode): common.INode ->
61 | // fmt.Printf("VarSpec %#v\n", n)
62 | n
63 |
64 | *Assignment(n common.INode): common.INode ->
65 | // fmt.Printf("ASSIGN %#v\n", n)
66 | n
67 |
68 | *BeforeBlock(n common.INode) ->
69 | // fmt.Println("PUSH")
70 | @stack.PushScope()
71 |
72 | *AfterBlock(n common.INode) ->
73 | // fmt.Println("POP")
74 | @stack.PopScope()
75 |
76 | *Each(n common.INode): common.INode -> n
77 | // name := reflect.TypeOf(n).String()[5:]
78 |
79 | // fmt.Printf("%s\n", strings.Repeat(" ", @indent) + name)
80 |
81 | TypeCheck(ast common.INode) ->
82 | t := TypeChecker
83 | stack: &Stack{}
84 |
85 | t.stack.PushScope()
86 |
87 | t.type_ = &t
88 |
89 | t.Walk(ast)
90 |
--------------------------------------------------------------------------------
/lib/ast/walker/walker.go:
--------------------------------------------------------------------------------
1 | package walker
2 |
3 | import (
4 | "github.com/champii/og/lib/common"
5 | "reflect"
6 | )
7 |
8 | type AstWalker struct {
9 | type_ interface{}
10 | }
11 |
12 | func (this *AstWalker) callDelegate(name string, arg reflect.Value) ([]reflect.Value, bool) {
13 | method := reflect.ValueOf(this.type_).MethodByName(name)
14 | if method.IsValid() {
15 | res := method.Call([]reflect.Value{arg})
16 | if len(res) == 0 {
17 | return []reflect.Value{reflect.Zero(arg.Type())}, false
18 | } else {
19 | return res, true
20 | }
21 | }
22 | return []reflect.Value{reflect.Zero(arg.Type())}, false
23 | }
24 | func (this *AstWalker) Trigger(arg reflect.Value, parentField reflect.Value, parentNode common.INode) (reflect.Value, bool) {
25 | node := arg.Interface().(common.INode)
26 | if node == nil {
27 | return reflect.Zero(arg.Type()), false
28 | }
29 | node.SetParent(parentNode)
30 | name := arg.Type().String()[5:]
31 | this.callDelegate("Before", arg)
32 | this.callDelegate("Before"+name, arg)
33 | res, ok := this.callDelegate("Each", arg)
34 | if ok {
35 | node = res[0].Interface().(common.INode)
36 | parentField.Set(reflect.ValueOf(node))
37 | }
38 | this.callDelegate(name, arg)
39 | parentField.Set(reflect.ValueOf(this.Walk(node)))
40 | res, ok = this.callDelegate("After", arg)
41 | if ok {
42 | node = res[0].Interface().(common.INode)
43 | parentField.Set(reflect.ValueOf(node))
44 | }
45 | this.callDelegate("After"+name, arg)
46 | return reflect.ValueOf(node), true
47 | }
48 | func (this *AstWalker) Walk(tree common.INode) common.INode {
49 | val := reflect.ValueOf(tree).Elem()
50 | for i := 0; i < val.NumField(); i++ {
51 | valueField := val.Field(i)
52 | valueType := val.Type().Field(i)
53 | valueKind := valueField.Kind()
54 | if valueKind == reflect.String || valueKind == reflect.Bool || valueType.Name == "Node" {
55 | continue
56 | }
57 | if valueKind == reflect.Slice {
58 | for j := 0; j < valueField.Len(); j++ {
59 | if valueField.Index(j).Kind() == reflect.String {
60 | continue
61 | }
62 | if !valueField.Index(j).IsValid() {
63 | continue
64 | }
65 | res, ok := this.Trigger(valueField.Index(j), valueField.Index(j), tree)
66 | if ok {
67 | valueField.Index(j).Set(res)
68 | }
69 | }
70 | continue
71 | }
72 | if valueField.IsNil() {
73 | continue
74 | }
75 | res, ok := this.Trigger(valueField, val.Field(i), tree)
76 | if ok {
77 | val.Field(i).Set(res)
78 | }
79 | }
80 | return tree
81 | }
82 |
--------------------------------------------------------------------------------
/lib/ast/walker/walker.og:
--------------------------------------------------------------------------------
1 | !walker
2 |
3 | import
4 | // fmt
5 | reflect
6 | "github.com/champii/og/lib/common"
7 |
8 | struct AstWalker
9 | type_ interface
10 |
11 | *callDelegate(name string, arg reflect.Value): []reflect.Value, bool ->
12 | method := reflect.ValueOf(@type_).MethodByName(name)
13 |
14 | if method.IsValid()
15 | res := method.Call([]reflect.Value{arg})
16 | if len(res) == 0
17 | return []reflect.Value{reflect.Zero(arg.Type())}, false
18 | else
19 | return res, true
20 |
21 | return []reflect.Value{reflect.Zero(arg.Type())}, false
22 |
23 | *Trigger(arg reflect.Value, parentField reflect.Value, parentNode common.INode): reflect.Value, bool->
24 | node := arg.Interface().(common.INode)
25 |
26 | if node == nil
27 | return reflect.Zero(arg.Type()), false
28 |
29 | node.SetParent(parentNode)
30 |
31 | name := arg.Type().String()[5:]
32 |
33 | @callDelegate("Before", arg)
34 | @callDelegate("Before" + name, arg)
35 |
36 | res, ok := @callDelegate("Each", arg)
37 | if ok
38 | node = res[0].Interface().(common.INode)
39 | parentField.Set(reflect.ValueOf(node))
40 |
41 | @callDelegate(name, arg)
42 |
43 | parentField.Set(reflect.ValueOf(@Walk(node)))
44 | res, ok = @callDelegate("After", arg)
45 | if ok
46 | node = res[0].Interface().(common.INode)
47 | parentField.Set(reflect.ValueOf(node))
48 |
49 | @callDelegate("After" + name, arg)
50 |
51 | return reflect.ValueOf(node), true
52 |
53 | *Walk(tree common.INode): common.INode ->
54 | val := reflect.ValueOf(tree).Elem()
55 |
56 | for i := 0; i < val.NumField(); i++
57 | valueField := val.Field(i)
58 | valueType := val.Type().Field(i)
59 |
60 | valueKind := valueField.Kind()
61 |
62 | if valueKind == reflect.String || valueKind == reflect.Bool || valueType.Name == "Node"
63 | continue
64 |
65 | if valueKind == reflect.Slice
66 | for j := 0; j < valueField.Len(); j++
67 | if valueField.Index(j).Kind() == reflect.String
68 | continue
69 |
70 | if !valueField.Index(j).IsValid()
71 | continue
72 |
73 | res, ok := @Trigger(valueField.Index(j), valueField.Index(j), tree)
74 | if ok
75 | valueField.Index(j).Set(res)
76 |
77 | continue
78 |
79 | if valueField.IsNil()
80 | continue
81 |
82 | res, ok := @Trigger(valueField, val.Field(i), tree)
83 | if ok
84 | val.Field(i).Set(res)
85 |
86 | tree
87 |
--------------------------------------------------------------------------------
/lib/common/config.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | type OgConfig struct {
4 | Blocks bool
5 | Dirty bool
6 | Print bool
7 | Force bool
8 | Ast bool
9 | SimpleAst bool
10 | Quiet bool
11 | Interpreter bool
12 | Paths []string
13 | Workers int
14 | OutPath string
15 | NoBuild bool
16 | Run bool
17 | }
18 |
19 | func NewOgConfig() *OgConfig {
20 | return &OgConfig{
21 | Workers: 8,
22 | Interpreter: false,
23 | OutPath: "./",
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/common/config.og:
--------------------------------------------------------------------------------
1 | !common
2 |
3 | struct OgConfig
4 | Blocks bool
5 | Dirty bool
6 | Print bool
7 | Force bool
8 | Ast bool
9 | SimpleAst bool
10 | Quiet bool
11 | Interpreter bool
12 | Paths []string // from command line
13 | Workers int
14 | OutPath string
15 | NoBuild bool
16 | Run bool
17 |
18 | NewOgConfig: *OgConfig ->
19 | &OgConfig
20 | Workers: 8
21 | Interpreter: false
22 | OutPath: "./"
23 |
--------------------------------------------------------------------------------
/lib/common/error.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | type Error struct {
4 | Path string
5 | Source []string
6 | Line int
7 | Column int
8 | Msg string
9 | Msg2 string
10 | }
11 |
12 | func NewError(filePath string, source []string, line, column int, msg, msg2 string) *Error {
13 | return &Error{
14 | Path: filePath,
15 | Source: source,
16 | Line: line,
17 | Column: column,
18 | Msg: msg,
19 | Msg2: msg2,
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/lib/common/error.og:
--------------------------------------------------------------------------------
1 | !common
2 |
3 | struct Error
4 | Path string
5 | Source []string
6 | Line int
7 | Column int
8 | Msg string
9 | Msg2 string
10 |
11 | NewError(filePath string, source []string, line, column int, msg, msg2 string): *Error ->
12 | &Error
13 | Path: filePath
14 | Source: source
15 | Line: line
16 | Column: column
17 | Msg: msg
18 | Msg2: msg2
19 |
--------------------------------------------------------------------------------
/lib/common/file.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "io/ioutil"
7 | "os"
8 | "os/exec"
9 | "path"
10 | "path/filepath"
11 | "strings"
12 | )
13 |
14 | type File struct {
15 | Path string
16 | Imports map[string]string
17 | FullPath string
18 | OutPath string
19 | Name string
20 | Ast INode
21 | Output string
22 | LineMapping []int
23 | Source []byte
24 | }
25 |
26 | func (this File) Write() {
27 | os.MkdirAll(filepath.Dir(this.OutPath), os.ModePerm)
28 | ioutil.WriteFile(this.OutPath, []byte(this.Output), os.ModePerm)
29 | }
30 | func (this *File) Format() error {
31 | cmd := exec.Command("gofmt")
32 | stdin, _ := cmd.StdinPipe()
33 | stdin.Write([]byte(this.Output))
34 | stdin.Close()
35 | final, err := cmd.CombinedOutput()
36 | if err != nil {
37 | fmt.Println("!!! THIS IS A BUG !!!\n")
38 | fmt.Println("If you see this text, Oglang have generated an invalid Go code")
39 | fmt.Println("and cannot go through the go formater.")
40 | fmt.Println("You should report this as an issue along with the file that produced that error")
41 | fmt.Println("https://github.com/Champii/og/issues")
42 | return errors.New(this.Path + ": " + string(final))
43 | }
44 | this.Output = string(final)
45 | return nil
46 | }
47 | func (this *File) Error(line, column int, msg, msg2 string) *Error {
48 | source := strings.Split(string(this.Source), "\n")
49 | return NewError(this.Path, source, line, column, msg, msg2)
50 | }
51 | func NewFile(filePath, outPath string) *File {
52 | name := path.Base(filePath)
53 | fullPath := filePath
54 | dir, _ := os.Getwd()
55 | fullPath = path.Join(dir, filePath)
56 | source, err := ioutil.ReadFile(filePath)
57 | if err != nil {
58 | return nil
59 | }
60 | return &File{
61 | Path: filePath,
62 | FullPath: fullPath,
63 | OutPath: outPath,
64 | Name: name,
65 | Source: source,
66 | Output: "",
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/common/file.og:
--------------------------------------------------------------------------------
1 | !common
2 |
3 | import
4 | os
5 | fmt
6 | path
7 | errors
8 | strings
9 | "os/exec"
10 | "io/ioutil"
11 | "path/filepath"
12 |
13 | struct File
14 | Path string
15 | Imports map[string]string // alias -> fullpath
16 | FullPath string
17 | OutPath string
18 | Name string
19 | Ast INode
20 | Output string
21 | LineMapping []int
22 | Source []byte
23 | Write ->
24 | os.MkdirAll(filepath.Dir(@OutPath), os.ModePerm);
25 | ioutil.WriteFile(@OutPath, []byte(@Output), os.ModePerm)
26 |
27 | *Format: error ->
28 | cmd := exec.Command("gofmt")
29 |
30 | stdin, _ := cmd.StdinPipe()
31 |
32 | stdin.Write([]byte(@Output))
33 | stdin.Close()
34 |
35 | final, err := cmd.CombinedOutput()
36 |
37 | if err != nil
38 | fmt.Println("!!! THIS IS A BUG !!!\n")
39 | fmt.Println("If you see this text, Oglang have generated an invalid Go code")
40 | fmt.Println("and cannot go through the go formater.")
41 | fmt.Println("You should report this as an issue along with the file that produced that error")
42 | fmt.Println("https://github.com/Champii/og/issues")
43 | return errors.New(@Path + ": " + string(final))
44 |
45 | @Output = string(final)
46 |
47 | return nil
48 |
49 | Error(line, column int, msg, msg2 string): *Error ->
50 | source := strings.Split(string(@Source), "\n")
51 | NewError(@Path, source, line, column, msg, msg2)
52 |
53 | NewFile(filePath, outPath string): *File ->
54 | name := path.Base(filePath)
55 |
56 | fullPath := filePath
57 | dir, _ := os.Getwd()
58 | fullPath = path.Join(dir, filePath)
59 |
60 | source, err := ioutil.ReadFile(filePath)
61 |
62 | if err != nil
63 | return nil
64 |
65 | &File
66 | Path: filePath
67 | FullPath: fullPath
68 | OutPath: outPath
69 | Name: name
70 | Source: source
71 | Output: ""
72 |
73 |
--------------------------------------------------------------------------------
/lib/common/node.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import (
4 | "github.com/champii/antlr4/runtime/Go/antlr"
5 | )
6 |
7 | type INode interface {
8 | Eval() string
9 | Text() string
10 | Line() int
11 | Col() int
12 | SetParent(n INode)
13 | GetParent() INode
14 | ChildrenCount() int
15 | T() interface{}
16 | }
17 | type Node struct {
18 | Line_ int
19 | Col_ int
20 | Text_ string
21 | Children []INode
22 | parent INode
23 | ChildrenCount_ int
24 | t interface{}
25 | }
26 |
27 | func (this Node) Eval() string {
28 | return ""
29 | }
30 | func (this Node) Text() string {
31 | return this.Text_
32 | }
33 | func (this Node) Line() int {
34 | return this.Line_
35 | }
36 | func (this Node) Col() int {
37 | return this.Col_
38 | }
39 | func (this Node) ChildrenCount() int {
40 | return this.ChildrenCount_
41 | }
42 | func (this *Node) SetParent(n INode) {
43 | if this.parent == nil {
44 | this.parent = n
45 | }
46 | }
47 | func (this *Node) GetParent() INode {
48 | return this.parent
49 | }
50 | func (this Node) T() interface{} {
51 | return this.t
52 | }
53 | func NewNode(ctx antlr.ParserRuleContext, file *File, t interface{}) *Node {
54 | tok := ctx.GetStart()
55 | line := file.LineMapping[tok.GetLine()]
56 | col := tok.GetColumn()
57 | return &Node{
58 | Text_: ctx.GetText(),
59 | Line_: line,
60 | Col_: col,
61 | ChildrenCount_: len(ctx.GetChildren()),
62 | t: t,
63 | }
64 | }
65 | func NewNodeNoCtx(t interface{}) *Node {
66 | return &Node{t: t}
67 | }
68 |
--------------------------------------------------------------------------------
/lib/common/node.og:
--------------------------------------------------------------------------------
1 | !common
2 |
3 | import
4 | "github.com/champii/antlr4/runtime/Go/antlr"
5 |
6 | interface INode
7 | Eval: string
8 | Text: string
9 | Line: int
10 | Col: int
11 | SetParent(n INode)
12 | GetParent: INode
13 | ChildrenCount: int
14 | T: interface
15 |
16 | struct Node
17 | Line_ int
18 | Col_ int
19 | Text_ string
20 | Children []INode
21 | parent INode
22 | ChildrenCount_ int
23 | t interface
24 |
25 | Eval: string -> ""
26 | Text: string -> @Text_
27 | Line: int -> @Line_
28 | Col: int -> @Col_
29 | ChildrenCount: int -> @ChildrenCount_
30 | *SetParent(n INode) -> if @parent == nil => @parent = n;
31 | *GetParent: INode -> @parent
32 | T: interface -> @t
33 |
34 | NewNode(ctx antlr.ParserRuleContext, file *File, t interface): *Node ->
35 | tok := ctx.GetStart()
36 | line := file.LineMapping[tok.GetLine()]
37 | col := tok.GetColumn();
38 |
39 | &Node
40 | Text_: ctx.GetText()
41 | Line_: line
42 | Col_: col
43 | ChildrenCount_: len(ctx.GetChildren())
44 | t: t
45 |
46 | NewNodeNoCtx(t interface): *Node ->
47 | &Node
48 | t: t
49 |
--------------------------------------------------------------------------------
/lib/common/printer.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import (
4 | "fmt"
5 | tm "github.com/buger/goterm"
6 | "github.com/fatih/color"
7 | curs "github.com/k0kubun/go-ansi"
8 | "strconv"
9 | )
10 |
11 | var (
12 | yellow = color.New(color.FgHiYellow).SprintFunc()
13 | )
14 | var (
15 | red = color.New(color.FgHiRed).SprintFunc()
16 | )
17 | var (
18 | cyan = color.New(color.FgCyan).SprintFunc()
19 | )
20 | var (
21 | magenta = color.New(color.Bold, color.FgHiMagenta).SprintFunc()
22 | )
23 | var (
24 | blue = color.New(color.Bold, color.FgHiBlue).SprintfFunc()
25 | )
26 | var (
27 | green = color.New(color.FgHiGreen).SprintfFunc()
28 | )
29 |
30 | type Printer struct {
31 | Config *OgConfig
32 | spinner int
33 | }
34 |
35 | func (this Printer) Compiling(nbFiles int) {
36 | if this.Config.Quiet {
37 | return
38 | }
39 | tm.Print(" \r")
40 | tm.Println(tm.Color("[", tm.RED), tm.Color(strconv.Itoa(nbFiles), tm.GREEN), tm.Color("/", tm.RED), tm.Color(strconv.Itoa(nbFiles), tm.GREEN), tm.Color("]", tm.RED), tm.Color("Compiling go", tm.YELLOW))
41 | tm.MoveCursorUp(1)
42 | tm.Flush()
43 | }
44 | func (this Printer) Compiled(nbFiles int) {
45 | if this.Config.Quiet {
46 | return
47 | }
48 | tm.MoveCursorUp(1)
49 | tm.Print(" \r")
50 | tm.Print(tm.Color("~> ", tm.RED), tm.Color("Oglang: ", tm.MAGENTA), tm.Color("Compiled ", tm.GREEN), tm.Color(strconv.Itoa(nbFiles), tm.YELLOW), tm.Color(" files.", tm.GREEN))
51 | tm.Flush()
52 | }
53 | func (this Printer) Running() {
54 | if this.Config.Quiet {
55 | return
56 | }
57 | tm.MoveCursorUp(1)
58 | tm.Print(" \r")
59 | tm.Print(tm.Color("~> ", tm.RED), tm.Color("Oglang: ", tm.MAGENTA), tm.Color("Running... \n", tm.GREEN))
60 | tm.Flush()
61 | }
62 | func (this Printer) NothingToDo() {
63 | if this.Config.Quiet {
64 | return
65 | }
66 | tm.Print(" \r")
67 | tm.Print(tm.Color("~> ", tm.RED), tm.Color("Oglang: ", tm.MAGENTA), tm.Color("Nothing to do.", tm.GREEN))
68 | tm.Flush()
69 | }
70 | func (this *Printer) CompileList(files []string, workerIds []int, nbWorkers, finished, total int) {
71 | if this.Config.Quiet {
72 | return
73 | }
74 | spinners := []string{
75 | "|",
76 | "/",
77 | "-",
78 | "\\",
79 | }
80 | tm.Print(" \r")
81 | tm.Println(spinners[this.spinner], tm.Color("[", tm.RED), tm.Color(strconv.Itoa(finished), tm.YELLOW), tm.Color("/", tm.RED), tm.Color(strconv.Itoa(total), tm.GREEN), tm.Color("]", tm.RED), tm.Color("Building sources", tm.YELLOW))
82 | for i, file := range files {
83 | tm.Print(" \r")
84 | tm.Println(tm.Color(strconv.Itoa(workerIds[i]), tm.CYAN), tm.Color(":", tm.RED), tm.Color(file, tm.MAGENTA))
85 | }
86 | workers := nbWorkers
87 | for len(files) < workers {
88 | tm.Print(" \n")
89 | workers--
90 | }
91 | tm.MoveCursorUp(nbWorkers + 2)
92 | tm.Flush()
93 | this.spinner += 1
94 | this.spinner %= 4
95 | }
96 | func (this *Printer) Error(err *Error) {
97 | for i := 0; i < 8; i++ {
98 | tm.Println(" ")
99 | }
100 | tm.MoveCursorUp(9)
101 | tm.Flush()
102 | fileInfo := fmt.Sprintf("%s (%s:%s)", green(err.Path), yellow(err.Line), yellow(err.Column))
103 | fmt.Printf("\n%s: %s '%s'\n", fileInfo, red(err.Msg), magenta(err.Msg2))
104 | badLine := err.Source[err.Line-1]
105 | badLine = cyan(badLine[:err.Column]) + magenta(err.Msg2) + cyan(badLine[err.Column+len(err.Msg2):])
106 | fmt.Println(badLine)
107 | fmt.Print(blue("%"+strconv.Itoa(err.Column+1)+"s\n", "^"))
108 | }
109 | func (this Printer) CursorHide() {
110 | if !this.Config.Quiet {
111 | curs.CursorHide()
112 | }
113 | }
114 | func (this Printer) CursorShow() {
115 | if !this.Config.Quiet {
116 | curs.CursorShow()
117 | }
118 | }
119 | func NewPrinter(config *OgConfig) *Printer {
120 | return &Printer{Config: config}
121 | }
122 |
123 | var (
124 | Print *Printer
125 | )
126 |
--------------------------------------------------------------------------------
/lib/common/printer.og:
--------------------------------------------------------------------------------
1 | !common
2 |
3 | import
4 | fmt
5 | strconv
6 | "github.com/fatih/color"
7 | "github.com/buger/goterm": tm
8 | "github.com/k0kubun/go-ansi": curs
9 |
10 | var yellow = color.New(color.FgHiYellow).SprintFunc()
11 | var red = color.New(color.FgHiRed).SprintFunc()
12 | var cyan = color.New(color.FgCyan).SprintFunc()
13 | var magenta = color.New(color.Bold, color.FgHiMagenta).SprintFunc()
14 | var blue = color.New(color.Bold, color.FgHiBlue).SprintfFunc()
15 | var green = color.New(color.FgHiGreen).SprintfFunc()
16 |
17 | struct Printer
18 | Config *OgConfig
19 | spinner int
20 |
21 | Compiling(nbFiles int) ->
22 | if @Config.Quiet
23 | return
24 |
25 | tm.Print(" \r")
26 | tm.Println(tm.Color("[", tm.RED), tm.Color(strconv.Itoa(nbFiles), tm.GREEN), tm.Color("/", tm.RED), tm.Color(strconv.Itoa(nbFiles), tm.GREEN), tm.Color("]", tm.RED), tm.Color("Compiling go", tm.YELLOW))
27 | tm.MoveCursorUp(1)
28 | tm.Flush()
29 |
30 | Compiled(nbFiles int) ->
31 | if @Config.Quiet
32 | return
33 |
34 | tm.MoveCursorUp(1)
35 | tm.Print(" \r")
36 | tm.Print(tm.Color("~> ", tm.RED), tm.Color("Oglang: ", tm.MAGENTA), tm.Color("Compiled ", tm.GREEN), tm.Color(strconv.Itoa(nbFiles), tm.YELLOW), tm.Color(" files.", tm.GREEN))
37 | tm.Flush()
38 |
39 | Running ->
40 | if @Config.Quiet
41 | return
42 |
43 | tm.MoveCursorUp(1)
44 | tm.Print(" \r")
45 | tm.Print(tm.Color("~> ", tm.RED), tm.Color("Oglang: ", tm.MAGENTA), tm.Color("Running... \n", tm.GREEN))
46 | tm.Flush()
47 |
48 | NothingToDo ->
49 | if @Config.Quiet
50 | return
51 |
52 | tm.Print(" \r")
53 | tm.Print(tm.Color("~> ", tm.RED), tm.Color("Oglang: ", tm.MAGENTA), tm.Color("Nothing to do.", tm.GREEN))
54 | tm.Flush()
55 |
56 | *CompileList(files []string, workerIds []int, nbWorkers, finished, total int) ->
57 | if @Config.Quiet
58 | return
59 |
60 | spinners := []string{"|", "/", "-", "\\"}
61 | tm.Print(" \r")
62 | tm.Println(spinners[@spinner], tm.Color("[", tm.RED), tm.Color(strconv.Itoa(finished), tm.YELLOW), tm.Color("/", tm.RED), tm.Color(strconv.Itoa(total), tm.GREEN), tm.Color("]", tm.RED), tm.Color("Building sources", tm.YELLOW))
63 |
64 | for i, file in files
65 | tm.Print(" \r")
66 | tm.Println(tm.Color(strconv.Itoa(workerIds[i]), tm.CYAN), tm.Color(":", tm.RED), tm.Color(file, tm.MAGENTA))
67 |
68 | workers := nbWorkers
69 | for len(files) < workers
70 | tm.Print(" \n")
71 | workers--
72 |
73 | tm.MoveCursorUp(nbWorkers + 2)
74 | tm.Flush()
75 |
76 | @spinner += 1
77 | @spinner %= 4
78 |
79 | *Error(err *Error) ->
80 | for i := 0; i < 8; i++
81 | tm.Println(" ")
82 | tm.MoveCursorUp(9)
83 | tm.Flush()
84 |
85 | fileInfo := fmt.Sprintf("%s (%s:%s)", green(err.Path), yellow(err.Line), yellow(err.Column))
86 | fmt.Printf("\n%s: %s '%s'\n", fileInfo, red(err.Msg), magenta(err.Msg2))
87 |
88 | badLine := err.Source[err.Line-1]
89 | badLine = cyan(badLine[:err.Column]) + magenta(err.Msg2) + cyan(badLine[err.Column+len(err.Msg2):])
90 |
91 | fmt.Println(badLine)
92 | fmt.Print(blue("%"+strconv.Itoa(err.Column+1)+"s\n","^"))
93 |
94 | CursorHide -> if !@Config.Quiet => curs.CursorHide()
95 | CursorShow -> if !@Config.Quiet => curs.CursorShow()
96 |
97 |
98 | NewPrinter(config *OgConfig): *Printer ->
99 | &Printer
100 | Config: config
101 |
102 | var Print *Printer
103 |
--------------------------------------------------------------------------------
/lib/og/compile.go:
--------------------------------------------------------------------------------
1 | package og
2 |
3 | import (
4 | "fmt"
5 | "github.com/champii/og/lib/ast/walker"
6 | "github.com/champii/og/lib/common"
7 | "os"
8 | "path"
9 | "path/filepath"
10 | "strings"
11 | )
12 |
13 | type OgCompiler struct {
14 | Config *common.OgConfig
15 | Parser *OgParser
16 | Preproc *OgPreproc
17 | Files []*common.File
18 | }
19 |
20 | func (this *OgCompiler) Compile() error {
21 | for _, p := range this.Config.Paths {
22 | if err := filepath.Walk(p, this.walker); err != nil {
23 | fmt.Println("Error", err)
24 | return err
25 | }
26 | }
27 | if len(this.Files) == 0 {
28 | if this.Config.Run {
29 | return nil
30 | }
31 | }
32 | poolSize := this.Config.Workers
33 | if len(this.Files) < poolSize {
34 | poolSize = len(this.Files)
35 | }
36 | pool := NewPool(poolSize, len(this.Files), this.ParseFile)
37 | for _, file := range this.Files {
38 | pool.Queue(file)
39 | }
40 | if err := pool.Run(); err != nil {
41 | return err
42 | }
43 | if this.Config.Blocks {
44 | return nil
45 | }
46 | walker.NewDesugar().Run(this.Files)
47 | return this.outputFiles()
48 | }
49 | func (this *OgCompiler) outputFiles() error {
50 | for _, file := range this.Files {
51 | file.Output = file.Ast.Eval()
52 | if !this.Config.Dirty {
53 | if err := file.Format(); err != nil {
54 | return err
55 | }
56 | }
57 | if this.Config.Print || this.Config.Dirty || this.Config.Blocks {
58 | fmt.Println(file.Output)
59 | } else {
60 | file.Write()
61 | }
62 | }
63 | return nil
64 | }
65 | func (this *OgCompiler) walker(filePath string, info os.FileInfo, err error) error {
66 | if err != nil {
67 | return err
68 | }
69 | if info.IsDir() {
70 | return nil
71 | }
72 | if path.Ext(filePath) != ".og" {
73 | return nil
74 | }
75 | if !this.mustCompile(filePath, info) {
76 | return nil
77 | }
78 | this.Files = append(this.Files, common.NewFile(filePath, this.getNewPath(filePath)))
79 | return nil
80 | }
81 | func (this OgCompiler) mustCompile(filePath string, info os.FileInfo) bool {
82 | newPath := this.getNewPath(filePath)
83 | stat, err := os.Stat(newPath)
84 | if err != nil {
85 | return true
86 | }
87 | if this.Config.Ast || this.Config.Print || this.Config.Dirty || this.Config.Blocks || this.Config.Force {
88 | return true
89 | }
90 | return info.ModTime().After(stat.ModTime())
91 | }
92 | func (this *OgCompiler) ParseFile(file *common.File) error {
93 | this.Preproc.Run(file)
94 | if this.Config.Blocks {
95 | fmt.Println(file.Output)
96 | return nil
97 | }
98 | var (
99 | err error
100 | )
101 | if !this.Config.Interpreter {
102 | err = this.Parser.Parse(file)
103 | } else {
104 | err = this.Parser.ParseInterpret(file)
105 | }
106 | if err != nil {
107 | return err
108 | }
109 | return nil
110 | }
111 | func (this OgCompiler) getNewPath(filePath string) string {
112 | if this.Config.OutPath != "./" {
113 | splited := strings.SplitN(filePath, "/", 2)
114 | filePath = splited[1]
115 | }
116 | return strings.Replace(path.Join(this.Config.OutPath, filePath), ".og", ".go", 1)
117 | }
118 | func NewOgCompiler(config *common.OgConfig) *OgCompiler {
119 | return &OgCompiler{
120 | Config: config,
121 | Parser: NewOgParser(config),
122 | Preproc: NewOgPreproc(),
123 | Files: []*common.File{},
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/lib/og/compile.og:
--------------------------------------------------------------------------------
1 | !og
2 |
3 | import
4 | fmt
5 | os
6 | path
7 | strings
8 | "path/filepath"
9 | "github.com/champii/og/lib/common"
10 | "github.com/champii/og/lib/ast/walker"
11 |
12 | struct OgCompiler
13 | Config *common.OgConfig
14 | Parser *OgParser
15 | Preproc *OgPreproc
16 | Files []*common.File
17 |
18 | *Compile: error ->
19 | for _, p in @Config.Paths
20 | if err := filepath.Walk(p, @walker); err != nil
21 | fmt.Println("Error", err)
22 |
23 | return err
24 |
25 | if len(@Files) == 0
26 | if @Config.Run
27 | return nil
28 |
29 | poolSize := @Config.Workers
30 |
31 | if len(@Files) < poolSize
32 | poolSize = len(@Files)
33 |
34 | pool := NewPool(poolSize, len(@Files), @ParseFile)
35 |
36 | for _, file in @Files
37 | pool.Queue(file)
38 |
39 | if err := pool.Run(); err != nil
40 | return err
41 |
42 | if @Config.Blocks
43 | return nil
44 |
45 | walker.NewDesugar().Run(@Files)
46 |
47 | @outputFiles()
48 |
49 | *outputFiles: error ->
50 | for _, file in @Files
51 | file.Output = file.Ast.Eval()
52 |
53 | if !@Config.Dirty
54 | if err := file.Format(); err != nil
55 | return err
56 |
57 | if @Config.Print || @Config.Dirty || @Config.Blocks
58 | fmt.Println(file.Output)
59 | else
60 | file.Write()
61 |
62 | nil
63 |
64 | *walker(filePath string, info os.FileInfo, err error): error ->
65 | if err != nil
66 | return err
67 |
68 | if info.IsDir()
69 | return nil
70 |
71 | if path.Ext(filePath) != ".og"
72 | return nil
73 |
74 | if !@mustCompile(filePath, info)
75 | return nil
76 |
77 | @Files = append(@Files, common.NewFile(filePath, @getNewPath(filePath)))
78 |
79 | nil
80 |
81 | mustCompile(filePath string, info os.FileInfo): bool ->
82 | newPath := @getNewPath(filePath)
83 |
84 | stat, err := os.Stat(newPath)
85 | if err != nil
86 | return true
87 |
88 | if @Config.Ast || @Config.Print || @Config.Dirty || @Config.Blocks || @Config.Force
89 | return true
90 |
91 | return info.ModTime().After(stat.ModTime())
92 |
93 | *ParseFile(file *common.File): error ->
94 | @Preproc.Run(file)
95 |
96 | if @Config.Blocks
97 | fmt.Println(file.Output)
98 | return nil
99 |
100 | var err error
101 | if !@Config.Interpreter
102 | err = @Parser.Parse(file)
103 | else
104 | err = @Parser.ParseInterpret(file)
105 |
106 | if err != nil
107 | return err
108 |
109 | return nil
110 |
111 | getNewPath(filePath string): string ->
112 | if @Config.OutPath != "./"
113 | splited := strings.SplitN(filePath, "/", 2)
114 | filePath = splited[1]
115 |
116 | strings.Replace(path.Join(@Config.OutPath, filePath), ".og", ".go", 1)
117 |
118 | NewOgCompiler(config *common.OgConfig): *OgCompiler ->
119 | &OgCompiler
120 | Config: config
121 | Parser: NewOgParser(config)
122 | Preproc: NewOgPreproc()
123 | Files: []*common.File{}
124 |
--------------------------------------------------------------------------------
/lib/og/interpreter.go:
--------------------------------------------------------------------------------
1 | package og
2 |
3 | import (
4 | "bufio"
5 | "fmt"
6 | "github.com/champii/og/lib/common"
7 | "io/ioutil"
8 | "os"
9 | "os/exec"
10 | )
11 |
12 | func RunInterpreter(compiler *OgCompiler) {
13 | fmt.Println("-> This is an experimental feature, only small expressions are allowed, no declaration")
14 | running := true
15 | scanner := bufio.NewScanner(os.Stdin)
16 | scanner.Split(bufio.ScanLines)
17 | for running {
18 | fmt.Print("> ")
19 | if !scanner.Scan() {
20 | return
21 | }
22 | ln := scanner.Text()
23 | if len(ln) == 0 {
24 | continue
25 | }
26 | file := &common.File{
27 | Path: "STDIN",
28 | Name: "STDIN",
29 | Source: []byte(ln),
30 | }
31 | err := compiler.ParseFile(file)
32 | if err != nil {
33 | fmt.Println(err)
34 | } else {
35 | execCode(file.Output)
36 | }
37 | }
38 | }
39 | func execCode(str string) {
40 | skelton := `package main
41 | import "fmt"
42 | func main() {
43 | fmt.Print(` + str[:len(str)-1] + `)
44 | }`
45 | ioutil.WriteFile("/tmp/main.go", []byte(skelton), os.ModePerm)
46 | cmd := exec.Command("go", "run", "/tmp/main.go")
47 | stdin, _ := cmd.StdinPipe()
48 | stdin.Write([]byte(str))
49 | stdin.Close()
50 | final, err := cmd.CombinedOutput()
51 | if err != nil {
52 | fmt.Println(err)
53 | }
54 | fmt.Println(string(final))
55 | }
56 |
--------------------------------------------------------------------------------
/lib/og/interpreter.og:
--------------------------------------------------------------------------------
1 | !og
2 |
3 | import
4 | os
5 | fmt
6 | bufio
7 | "io/ioutil"
8 | "os/exec"
9 | "github.com/champii/og/lib/common"
10 |
11 | RunInterpreter(compiler *OgCompiler) ->
12 | fmt.Println("-> This is an experimental feature, only small expressions are allowed, no declaration")
13 | running := true
14 | scanner := bufio.NewScanner(os.Stdin)
15 | scanner.Split(bufio.ScanLines)
16 |
17 | for running
18 | fmt.Print("> ")
19 |
20 | if !scanner.Scan()
21 | return
22 |
23 | ln := scanner.Text()
24 |
25 | if len(ln) == 0
26 | continue
27 |
28 | file := &common.File
29 | Path: "STDIN"
30 | Name: "STDIN"
31 | Source: []byte(ln)
32 |
33 | err := compiler.ParseFile(file)
34 | if err != nil
35 | fmt.Println(err)
36 | else
37 | execCode(file.Output)
38 |
39 | execCode(str string) ->
40 | skelton := `package main
41 | import "fmt"
42 | func main() {
43 | fmt.Print(` + str[:len(str)-1] + `)
44 | }`
45 |
46 | ioutil.WriteFile("/tmp/main.go", []byte(skelton), os.ModePerm)
47 | cmd := exec.Command("go", "run", "/tmp/main.go")
48 |
49 | stdin, _ := cmd.StdinPipe()
50 |
51 | stdin.Write([]byte(str))
52 | stdin.Close()
53 |
54 | final, err := cmd.CombinedOutput()
55 |
56 | if err != nil
57 | fmt.Println(err)
58 |
59 | fmt.Println(string(final))
--------------------------------------------------------------------------------
/lib/og/og.go:
--------------------------------------------------------------------------------
1 | package og
2 |
3 | import (
4 | "fmt"
5 | "github.com/champii/og/lib/common"
6 | "os"
7 | "os/exec"
8 | "path"
9 | )
10 |
11 | type Og struct {
12 | Config *common.OgConfig
13 | Compiler *OgCompiler
14 | }
15 |
16 | func (this Og) Run() error {
17 | if len(this.Config.Paths) == 0 {
18 | this.Config.Paths = []string{"."}
19 | }
20 | if this.Config.Interpreter {
21 | RunInterpreter(this.Compiler)
22 | return nil
23 | }
24 | if err := this.Compiler.Compile(); err != nil {
25 | return err
26 | }
27 | if len(this.Compiler.Files) == 0 {
28 | common.Print.NothingToDo()
29 | if !this.Config.Run {
30 | return nil
31 | }
32 | }
33 | if this.Config.Print || this.Config.Ast || this.Config.SimpleAst || this.Config.Blocks || this.Config.Dirty {
34 | return nil
35 | }
36 | if !this.Config.NoBuild {
37 | if err := this.Build(); err != nil {
38 | return err
39 | }
40 | }
41 | if this.Config.Run {
42 | if err := this.RunBinary(); err != nil {
43 | return err
44 | }
45 | }
46 | return nil
47 | }
48 | func (this Og) Build() error {
49 | common.Print.Compiling(len(this.Compiler.Files))
50 | cmd := exec.Command("go", "build")
51 | out, err := cmd.CombinedOutput()
52 | if err != nil {
53 | fmt.Println(string(out))
54 | return err
55 | }
56 | if len(this.Compiler.Files) > 0 {
57 | common.Print.Compiled(len(this.Compiler.Files))
58 | }
59 | return nil
60 | }
61 | func (this Og) RunBinary() error {
62 | dir, err := os.Getwd()
63 | if err != nil {
64 | return err
65 | }
66 | current := path.Base(dir)
67 | common.Print.Running()
68 | cmd := exec.Command("./" + current)
69 | cmd.Stdout = os.Stdout
70 | cmd.Stderr = os.Stderr
71 | if err = cmd.Start(); err != nil {
72 | return err
73 | }
74 | cmd.Wait()
75 | return nil
76 | }
77 | func NewOg(config *common.OgConfig) *Og {
78 | common.Print = common.NewPrinter(config)
79 | return &Og{
80 | Config: config,
81 | Compiler: NewOgCompiler(config),
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/lib/og/og.og:
--------------------------------------------------------------------------------
1 | !og
2 |
3 | import
4 | os
5 | fmt
6 | path
7 | "os/exec"
8 | "github.com/champii/og/lib/common"
9 |
10 | struct Og
11 | Config *common.OgConfig
12 | Compiler *OgCompiler
13 |
14 | Run: error ->
15 | if len(@Config.Paths) == 0
16 | @Config.Paths = []string{"."}
17 |
18 | if @Config.Interpreter
19 | RunInterpreter(@Compiler)
20 | return nil
21 |
22 | if err := @Compiler.Compile(); err != nil
23 | return err
24 |
25 | if len(@Compiler.Files) == 0
26 | common.Print.NothingToDo()
27 | if !@Config.Run
28 | return nil
29 |
30 | if @Config.Print || @Config.Ast || @Config.SimpleAst || @Config.Blocks || @Config.Dirty
31 | return nil
32 |
33 | if !@Config.NoBuild
34 | if err := @Build(); err != nil
35 | return err
36 |
37 | if @Config.Run
38 | if err := @RunBinary(); err != nil
39 | return err
40 |
41 | return nil
42 |
43 | Build: error ->
44 | common.Print.Compiling(len(@Compiler.Files))
45 |
46 | cmd := exec.Command("go", "build")
47 |
48 | out, err := cmd.CombinedOutput()
49 |
50 | if err != nil
51 | fmt.Println(string(out))
52 | return err
53 |
54 | if len(@Compiler.Files) > 0
55 | common.Print.Compiled(len(@Compiler.Files))
56 |
57 | nil
58 |
59 | RunBinary: error ->
60 | dir, err := os.Getwd()
61 |
62 | if err != nil
63 | return err
64 |
65 | current := path.Base(dir)
66 |
67 | common.Print.Running()
68 |
69 | cmd := exec.Command("./" + current)
70 | cmd.Stdout = os.Stdout
71 | cmd.Stderr = os.Stderr
72 |
73 | if err = cmd.Start(); err != nil
74 | return err
75 |
76 | cmd.Wait()
77 |
78 | return nil
79 |
80 | NewOg(config *common.OgConfig): *Og ->
81 | common.Print = common.NewPrinter(config);
82 |
83 | &Og
84 | Config: config
85 | Compiler: NewOgCompiler(config)
86 |
--------------------------------------------------------------------------------
/lib/og/parse.go:
--------------------------------------------------------------------------------
1 | package og
2 |
3 | import (
4 | "errors"
5 | "os"
6 | "strings"
7 |
8 | "github.com/champii/antlr4/runtime/Go/antlr"
9 | "github.com/champii/og/lib/ast"
10 | "github.com/champii/og/lib/ast/walker"
11 | "github.com/champii/og/lib/common"
12 | "github.com/champii/og/lib/translator"
13 | "github.com/champii/og/parser"
14 | )
15 |
16 | type ErrorHandler struct {
17 | *antlr.DefaultErrorStrategy
18 | }
19 |
20 | func (this ErrorHandler) Recover(p antlr.Parser, r antlr.RecognitionException) {
21 | os.Exit(1)
22 | }
23 | func NewErrorHandler() *ErrorHandler {
24 | return &ErrorHandler{DefaultErrorStrategy: antlr.NewDefaultErrorStrategy()}
25 | }
26 |
27 | type ErrorListener struct {
28 | *antlr.DefaultErrorListener
29 | filePath string
30 | source []string
31 | }
32 |
33 | func (this *ErrorListener) SyntaxError(rec antlr.Recognizer, offendingSymbol interface{}, line, column int, msg string, e antlr.RecognitionException) {
34 | err := common.NewError(this.filePath, this.source, line, column, "Unexpected", offendingSymbol.(antlr.Token).GetText())
35 | common.Print.Error(err)
36 | }
37 | func NewErrorListener(filePath, source string) *ErrorListener {
38 | return &ErrorListener{
39 | DefaultErrorListener: antlr.NewDefaultErrorListener(),
40 | filePath: filePath,
41 | source: strings.Split(source, "\n"),
42 | }
43 | }
44 |
45 | type OgParser struct {
46 | Config *common.OgConfig
47 | }
48 |
49 | func (this *OgParser) parserInit(file *common.File) *parser.OgParser {
50 | input := antlr.NewInputStream(string(file.Output))
51 | lexer := parser.NewOgLexer(input)
52 | stream := antlr.NewCommonTokenStream(lexer, 0)
53 | p := parser.NewOgParser(stream)
54 | p.GetInterpreter().SetPredictionMode(antlr.PredictionModeSLL)
55 | p.RemoveErrorListeners()
56 | p.SetErrorHandler(NewErrorHandler())
57 | p.AddErrorListener(NewErrorListener(file.Path, string(file.Source)))
58 | p.AddErrorListener(antlr.NewDiagnosticErrorListener(true))
59 | return p
60 | }
61 | func (this *OgParser) Parse(file *common.File) error {
62 | p := this.parserInit(file)
63 | res := p.SourceFile()
64 | if res == nil {
65 | return errors.New("Cannot parse file: " + file.Path)
66 | }
67 | t := new(translator.OgVisitor)
68 | t.File = file
69 | tree := t.VisitSourceFile(res.(*parser.SourceFileContext), t).(*ast.SourceFile)
70 | if this.Config.Ast || this.Config.SimpleAst {
71 | walker.Print(tree, this.Config.SimpleAst)
72 | }
73 | file.Ast = tree
74 | file.Imports = tree.GetImports()
75 | return nil
76 | }
77 | func (this *OgParser) ParseStmt(file *common.File) error {
78 | p := this.parserInit(file)
79 | res := p.Statement()
80 | t := new(translator.OgVisitor)
81 | file.Ast = t.VisitStatement(res.(*parser.StatementContext), t).(*ast.Statement)
82 | return nil
83 | }
84 | func (this *OgParser) ParseInterpret(file *common.File) error {
85 | p := this.parserInit(file)
86 | res := p.Interp()
87 | t := new(translator.OgVisitor)
88 | file.Ast = t.VisitInterp(res.(*parser.InterpContext), t).(*ast.Interpret)
89 | return nil
90 | }
91 | func NewOgParser(config *common.OgConfig) *OgParser {
92 | return &OgParser{Config: config}
93 | }
94 |
--------------------------------------------------------------------------------
/lib/og/parse.og:
--------------------------------------------------------------------------------
1 | !og
2 |
3 | import
4 | os
5 | errors
6 | strings
7 | "github.com/champii/og/parser"
8 | "github.com/champii/og/lib/ast"
9 | "github.com/champii/og/lib/common"
10 | "github.com/champii/og/lib/ast/walker"
11 | "github.com/champii/og/lib/translator"
12 | "github.com/champii/antlr4/runtime/Go/antlr"
13 |
14 | struct ErrorHandler
15 | *antlr.DefaultErrorStrategy
16 |
17 | Recover(p antlr.Parser, r antlr.RecognitionException) ->
18 | os.Exit(1)
19 |
20 | NewErrorHandler: *ErrorHandler ->
21 | &ErrorHandler
22 | DefaultErrorStrategy: antlr.NewDefaultErrorStrategy()
23 |
24 | struct ErrorListener
25 | *antlr.DefaultErrorListener
26 | filePath string
27 | source []string
28 |
29 | *SyntaxError(rec antlr.Recognizer, offendingSymbol interface, line, column int, msg string, e antlr.RecognitionException) ->
30 | err := common.NewError(@filePath, @source, line, column, "Unexpected", offendingSymbol.(antlr.Token).GetText())
31 | common.Print.Error(err)
32 |
33 | NewErrorListener(filePath, source string): *ErrorListener ->
34 | &ErrorListener
35 | DefaultErrorListener: antlr.NewDefaultErrorListener()
36 | filePath: filePath
37 | source: strings.Split(source, "\n")
38 |
39 | struct OgParser
40 | Config *common.OgConfig
41 |
42 | parserInit(file *common.File): *parser.OgParser ->
43 | input := antlr.NewInputStream(string(file.Output))
44 | lexer := parser.NewOgLexer(input)
45 |
46 | stream := antlr.NewCommonTokenStream(lexer, 0)
47 |
48 | p := parser.NewOgParser(stream)
49 |
50 | p.GetInterpreter().SetPredictionMode(antlr.PredictionModeSLL)
51 |
52 | p.RemoveErrorListeners()
53 | p.SetErrorHandler(NewErrorHandler())
54 | p.AddErrorListener(NewErrorListener(file.Path, string(file.Source)))
55 | p.AddErrorListener(antlr.NewDiagnosticErrorListener(true))
56 | // p.SetErrorHandler(antlr.NewBailErrorStrategy())
57 |
58 | p
59 |
60 | Parse(file *common.File): error ->
61 | p := @parserInit(file)
62 |
63 | res := p.SourceFile()
64 |
65 | if res == nil
66 | return errors.New("Cannot parse file: " + file.Path)
67 |
68 | t := new(translator.OgVisitor)
69 |
70 | t.File = file
71 |
72 | tree := t.VisitSourceFile(res.(*parser.SourceFileContext), t).(*ast.SourceFile)
73 |
74 | if @Config.Ast || @Config.SimpleAst
75 | walker.Print(tree, @Config.SimpleAst)
76 |
77 | file.Ast = tree
78 | file.Imports = tree.GetImports()
79 |
80 | nil
81 |
82 | ParseStmt(file *common.File): error ->
83 | p := @parserInit(file)
84 |
85 | res := p.Statement()
86 |
87 | t := new(translator.OgVisitor)
88 |
89 | file.Ast = t.VisitStatement(res.(*parser.StatementContext), t).(*ast.Statement)
90 |
91 | nil
92 |
93 | ParseInterpret(file *common.File): error ->
94 | p := @parserInit(file)
95 |
96 | res := p.Interp()
97 |
98 | t := new(translator.OgVisitor)
99 |
100 | file.Ast = t.VisitInterp(res.(*parser.InterpContext), t).(*ast.Interpret)
101 |
102 | nil
103 |
104 | NewOgParser(config *common.OgConfig): *OgParser ->
105 | &OgParser
106 | Config: config
107 |
--------------------------------------------------------------------------------
/lib/og/pool.go:
--------------------------------------------------------------------------------
1 | package og
2 |
3 | import (
4 | "github.com/champii/og/lib/common"
5 | "time"
6 | )
7 |
8 | type WorkerCallback (func(*common.File) error)
9 | type Worker struct {
10 | In chan *common.File
11 | Out chan error
12 | Processing *common.File
13 | Job WorkerCallback
14 | }
15 |
16 | func (this *Worker) Run() {
17 | for todo := range this.In {
18 | this.Processing = todo
19 | res := this.Job(todo)
20 | this.Processing = nil
21 | this.Out <- res
22 | }
23 | }
24 | func NewWorker(i chan *common.File, out chan error, job WorkerCallback) *Worker {
25 | return &Worker{
26 | Processing: nil,
27 | In: i,
28 | Out: out,
29 | Job: job,
30 | }
31 | }
32 |
33 | type Pool struct {
34 | Size int
35 | Workers []*Worker
36 | Total int
37 | Finished int
38 | In chan *common.File
39 | Out chan error
40 | }
41 |
42 | func (this *Pool) Queue(job *common.File) {
43 | this.In <- job
44 | }
45 | func (this *Pool) Run() error {
46 | for _, worker := range this.Workers {
47 | go worker.Run()
48 | }
49 | close(this.In)
50 | common.Print.CursorHide()
51 | defer common.Print.CursorShow()
52 | ticker := time.NewTicker(100 * time.Millisecond)
53 | go func() {
54 | for true {
55 | <-ticker.C
56 | this.Print()
57 | }
58 | }()
59 | for this.Finished < this.Total {
60 | if err := <-this.Out; err != nil {
61 | ticker.Stop()
62 | return err
63 | }
64 | this.Finished++
65 | }
66 | ticker.Stop()
67 | this.Print()
68 | return nil
69 | }
70 | func (this Pool) Print() {
71 | workerIds := []int{}
72 | files := []string{}
73 | for i, worker := range this.Workers {
74 | if worker.Processing != nil {
75 | files = append(files, worker.Processing.Path)
76 | workerIds = append(workerIds, i+1)
77 | }
78 | }
79 | common.Print.CompileList(files, workerIds, len(this.Workers), this.Finished, this.Total)
80 | }
81 | func NewPool(size int, nbJobs int, cb WorkerCallback) *Pool {
82 | pool := &Pool{
83 | Size: size,
84 | Total: nbJobs,
85 | Finished: 0,
86 | In: make(chan *common.File, nbJobs),
87 | Out: make(chan error, nbJobs),
88 | }
89 | for i := 0; i < pool.Size; i++ {
90 | pool.Workers = append(pool.Workers, NewWorker(pool.In, pool.Out, cb))
91 | }
92 | return pool
93 | }
94 |
--------------------------------------------------------------------------------
/lib/og/pool.og:
--------------------------------------------------------------------------------
1 | !og
2 |
3 | import
4 | time
5 | "github.com/champii/og/lib/common"
6 |
7 | type WorkerCallback (fn(*common.File): error)
8 |
9 | struct Worker
10 | In chan *common.File
11 | Out chan error
12 | Processing *common.File
13 | Job WorkerCallback
14 |
15 | *Run ->
16 | for todo in @In
17 | @Processing = todo
18 |
19 | res := @Job(todo)
20 |
21 | @Processing = nil
22 |
23 | @Out <- res
24 |
25 | NewWorker(i chan *common.File, out chan error, job WorkerCallback): *Worker ->
26 | &Worker
27 | Processing: nil
28 | In: i
29 | Out: out
30 | Job: job
31 |
32 | struct Pool
33 | Size int
34 | Workers []*Worker
35 | Total int
36 | Finished int
37 | In chan *common.File
38 | Out chan error
39 |
40 | Queue(job *common.File) ->
41 | @In <- job
42 |
43 | Run: error ->
44 | for _, worker in @Workers
45 | go worker.Run()
46 |
47 | close(@In)
48 |
49 | common.Print.CursorHide()
50 | defer common.Print.CursorShow()
51 |
52 | ticker := time.NewTicker(100 * time.Millisecond)
53 | go ->
54 | for true
55 | <-ticker.C
56 | @Print()
57 |
58 | for @Finished < @Total
59 | if err := <-@Out; err != nil
60 | ticker.Stop()
61 | return err
62 |
63 | @Finished++
64 |
65 | ticker.Stop()
66 | @Print()
67 |
68 | nil
69 |
70 | Print ->
71 | workerIds := []int{}
72 | files := []string{}
73 |
74 | for i, worker in @Workers
75 | if worker.Processing != nil
76 | files = append(files, worker.Processing.Path)
77 | workerIds = append(workerIds, i + 1)
78 |
79 | common.Print.CompileList(files, workerIds, len(@Workers), @Finished, @Total)
80 |
81 | NewPool(size int, nbJobs int, cb WorkerCallback): *Pool ->
82 | pool := &Pool
83 | Size: size
84 | Total: nbJobs
85 | Finished: 0
86 | In: make(chan *common.File, nbJobs)
87 | Out: make(chan error, nbJobs)
88 |
89 | for i := 0; i < pool.Size; i++
90 | pool.Workers = append(pool.Workers, NewWorker(pool.In, pool.Out, cb))
91 |
92 | pool
--------------------------------------------------------------------------------
/lib/og/preproc.go:
--------------------------------------------------------------------------------
1 | package og
2 |
3 | import (
4 | "github.com/champii/og/lib/common"
5 | "strings"
6 | )
7 |
8 | type OgPreproc struct {
9 | }
10 |
11 | func (this OgPreproc) indentCount(str string) int {
12 | for i := range str {
13 | if str[i] != ' ' && str[i] != '\t' {
14 | return i
15 | }
16 | }
17 | return 0
18 | }
19 | func (this *OgPreproc) Run(file *common.File) {
20 | lineCount := 0
21 | file.Source = []byte(strings.Replace(string(file.Source), "\t", " ", -1))
22 | lines := strings.Split(string(file.Source), "\n")
23 | res := []string{}
24 | lastIndent := 0
25 | indentSize := 0
26 | file.LineMapping = []int{0}
27 | for i := range lines {
28 | lineCount++
29 | if len(lines[i]) == 0 {
30 | continue
31 | }
32 | file.LineMapping = append(file.LineMapping, lineCount)
33 | indent := this.indentCount(lines[i])
34 | token := "=>"
35 | eqIf := "= if "
36 | if len(lines[i]) > indent+4 && lines[i][indent:indent+4] == "for " {
37 | lines[i] += ";"
38 | }
39 | if len(lines[i]) > indent+3 && lines[i][indent:indent+3] == "if " && !strings.Contains(lines[i], token) {
40 | lines[i] += ";"
41 | }
42 | if len(lines[i]) > indent+3 && strings.Contains(lines[i], eqIf) && !strings.Contains(lines[i], token) {
43 | lines[i] += ";"
44 | }
45 | if len(lines[i]) > indent+5 && lines[i][indent:indent+5] == "else " && !strings.Contains(lines[i], token) {
46 | lines[i] += ";"
47 | }
48 | if indentSize == 0 && indent != lastIndent {
49 | indentSize = indent
50 | }
51 | if indent > lastIndent {
52 | res[len(res)-1] = res[len(res)-1] + " {"
53 | } else if indent < lastIndent {
54 | indentBuff := lastIndent - indent
55 | for indentBuff > 0 {
56 | res = append(res, "}")
57 | file.LineMapping = append(file.LineMapping, lineCount)
58 | indentBuff -= indentSize
59 | }
60 | }
61 | lastIndent = indent
62 | res = append(res, lines[i])
63 | }
64 | for lastIndent > 0 {
65 | res = append(res, "}")
66 | file.LineMapping = append(file.LineMapping, lineCount)
67 | lastIndent -= indentSize
68 | }
69 | file.Output = strings.Join(res, "\n") + "\n"
70 | }
71 | func NewOgPreproc() *OgPreproc {
72 | return &OgPreproc{}
73 | }
74 |
--------------------------------------------------------------------------------
/lib/og/preproc.og:
--------------------------------------------------------------------------------
1 | !og
2 |
3 | import
4 | "strings"
5 | "github.com/champii/og/lib/common"
6 |
7 | struct OgPreproc
8 | indentCount(str string): int ->
9 | for i in str
10 | if str[i] != ' ' && str[i] != '\t'
11 | return i
12 |
13 | 0
14 |
15 | Run(file *common.File) ->
16 | lineCount := 0
17 | file.Source = []byte(strings.Replace(string(file.Source), "\t", " ", -1))
18 | lines := strings.Split(string(file.Source), "\n")
19 |
20 | res := []string{}
21 |
22 | lastIndent := 0
23 | indentSize := 0
24 |
25 | file.LineMapping = []int{0}
26 |
27 | for i in lines
28 | lineCount++
29 | if len(lines[i]) == 0
30 | continue
31 |
32 | file.LineMapping = append(file.LineMapping, lineCount)
33 |
34 | indent := @indentCount(lines[i])
35 |
36 | token := "=>"
37 | eqIf := "= if "
38 |
39 | // SEMI-COLUMN
40 | if len(lines[i]) > indent + 4 && lines[i][indent:indent+4] == "for "
41 | lines[i] += ";"
42 |
43 | if len(lines[i]) > indent + 3 && lines[i][indent:indent+3] == "if " && !strings.Contains(lines[i], token)
44 | lines[i] += ";"
45 |
46 | if len(lines[i]) > indent + 3 && strings.Contains(lines[i], eqIf) && !strings.Contains(lines[i], token)
47 | lines[i] += ";"
48 |
49 | if len(lines[i]) > indent + 5 && lines[i][indent:indent+5] == "else " && !strings.Contains(lines[i], token)
50 | lines[i] += ";"
51 |
52 |
53 | // INDENT
54 |
55 | if indentSize == 0 && indent != lastIndent
56 | indentSize = indent
57 |
58 | //&& lines[i-1][len(lines[i-1])-1] != '='
59 | if indent > lastIndent
60 | res[len(res)-1] = res[len(res)-1] + " {"
61 | else if indent < lastIndent
62 | indentBuff := lastIndent - indent
63 |
64 | for indentBuff > 0
65 | res = append(res, "}")
66 | file.LineMapping = append(file.LineMapping, lineCount)
67 | indentBuff -= indentSize
68 |
69 | lastIndent = indent
70 |
71 |
72 | res = append(res, lines[i])
73 |
74 | for lastIndent > 0
75 | res = append(res, "}")
76 | file.LineMapping = append(file.LineMapping, lineCount)
77 | lastIndent -= indentSize
78 |
79 | file.Output = strings.Join(res, "\n") + "\n"
80 |
81 | NewOgPreproc: *OgPreproc ->
82 | &OgPreproc{}
--------------------------------------------------------------------------------
/lib/std/.og/template:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Champii/og/228c5a04bfb7c7a4784932ca4b8121e3385d8365/lib/std/.og/template
--------------------------------------------------------------------------------
/lib/std/slices.go:
--------------------------------------------------------------------------------
1 | package std
2 |
--------------------------------------------------------------------------------
/lib/std/slices.og:
--------------------------------------------------------------------------------
1 | !std
2 |
3 | RemoveIdx(arr []T, idx int): []T ->
4 | if len(arr) - 1 == i => arr[:i]
5 | else if i == 0 => arr[1:]
6 | else => append(arr[0:i], arr[i+1:]...)
7 |
8 | clone(t T): T ->
9 | var res T
10 | var buf bytes.Buffer
11 | enc := gob.NewEncoder(&buf)
12 | if err := enc.Encode(t); err != nil
13 | fmt.Println("ERROR ENCODE", err)
14 |
15 | dec := gob.NewDecoder(&buf)
16 | if err := dec.Decode(&res); err != nil
17 | fmt.Println("ERROR DECODE", err)
18 |
19 | res
20 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/champii/og/lib/common"
7 | "github.com/champii/og/lib/og"
8 | )
9 |
10 | //go:generate java -Xmx500M -cp "./parser/antlr4-4.7.2-SNAPSHOT-complete.jar" org.antlr.v4.Tool -Dlanguage=Go ./parser/Og.g4 -visitor -o .
11 | //go:generate ./scripts/fix_parser_imports.sh
12 | func main() {
13 | parseArgs(func(options *common.OgConfig) {
14 | ogLang := og.NewOg(options)
15 |
16 | if err := ogLang.Run(); err != nil {
17 | fmt.Println(err)
18 | }
19 | })
20 | }
21 |
--------------------------------------------------------------------------------
/parser/Og.tokens:
--------------------------------------------------------------------------------
1 | T__0=1
2 | T__1=2
3 | T__2=3
4 | T__3=4
5 | T__4=5
6 | T__5=6
7 | T__6=7
8 | T__7=8
9 | T__8=9
10 | T__9=10
11 | T__10=11
12 | T__11=12
13 | T__12=13
14 | T__13=14
15 | T__14=15
16 | T__15=16
17 | T__16=17
18 | T__17=18
19 | T__18=19
20 | T__19=20
21 | T__20=21
22 | T__21=22
23 | T__22=23
24 | T__23=24
25 | T__24=25
26 | T__25=26
27 | T__26=27
28 | T__27=28
29 | T__28=29
30 | T__29=30
31 | T__30=31
32 | T__31=32
33 | T__32=33
34 | T__33=34
35 | T__34=35
36 | T__35=36
37 | T__36=37
38 | T__37=38
39 | T__38=39
40 | T__39=40
41 | T__40=41
42 | T__41=42
43 | T__42=43
44 | T__43=44
45 | T__44=45
46 | T__45=46
47 | T__46=47
48 | T__47=48
49 | T__48=49
50 | T__49=50
51 | T__50=51
52 | T__51=52
53 | T__52=53
54 | T__53=54
55 | T__54=55
56 | T__55=56
57 | T__56=57
58 | T__57=58
59 | T__58=59
60 | T__59=60
61 | T__60=61
62 | T__61=62
63 | T__62=63
64 | T__63=64
65 | T__64=65
66 | T__65=66
67 | T__66=67
68 | T__67=68
69 | IDENTIFIER=69
70 | KEYWORD=70
71 | BINARY_OP=71
72 | FUNC=72
73 | INT_LIT=73
74 | FLOAT_LIT=74
75 | IMAGINARY_LIT=75
76 | RUNE_LIT=76
77 | LITTLE_U_VALUE=77
78 | BIG_U_VALUE=78
79 | STRING_LIT=79
80 | WS=80
81 | COMMENT=81
82 | LINE_COMMENT=82
83 | TERMINATOR=83
84 | ErrorChar=84
85 | 'package'=1
86 | '!'=2
87 | 'import'=3
88 | '('=4
89 | ')'=5
90 | '{'=6
91 | '}'=7
92 | ':'=8
93 | '.'=9
94 | 'const'=10
95 | '='=11
96 | '_'=12
97 | ','=13
98 | 'type'=14
99 | '::'=15
100 | '*'=16
101 | 'var'=17
102 | '<-'=18
103 | '++'=19
104 | '--'=20
105 | '+'=21
106 | '-'=22
107 | '|'=23
108 | '^'=24
109 | '/'=25
110 | '%'=26
111 | '<<'=27
112 | '>>'=28
113 | '&'=29
114 | '&^'=30
115 | ':='=31
116 | ';'=32
117 | '~'=33
118 | 'return'=34
119 | 'break'=35
120 | 'continue'=36
121 | 'goto'=37
122 | 'fallthrough'=38
123 | 'defer'=39
124 | 'if'=40
125 | '=>'=41
126 | 'else'=42
127 | 'switch'=43
128 | 'select'=44
129 | 'for'=45
130 | 'in'=46
131 | 'go'=47
132 | '['=48
133 | ']'=49
134 | 'interface'=50
135 | 'map'=51
136 | 'chan'=52
137 | 'fn'=53
138 | '<'=54
139 | '>'=55
140 | '...'=56
141 | 'true'=57
142 | 'false'=58
143 | 'nil'=59
144 | '@'=60
145 | 'struct'=61
146 | 'class'=62
147 | '||'=63
148 | '&&'=64
149 | '=='=65
150 | '!='=66
151 | '<='=67
152 | '>='=68
153 | '->'=72
154 |
--------------------------------------------------------------------------------
/parser/OgLexer.tokens:
--------------------------------------------------------------------------------
1 | T__0=1
2 | T__1=2
3 | T__2=3
4 | T__3=4
5 | T__4=5
6 | T__5=6
7 | T__6=7
8 | T__7=8
9 | T__8=9
10 | T__9=10
11 | T__10=11
12 | T__11=12
13 | T__12=13
14 | T__13=14
15 | T__14=15
16 | T__15=16
17 | T__16=17
18 | T__17=18
19 | T__18=19
20 | T__19=20
21 | T__20=21
22 | T__21=22
23 | T__22=23
24 | T__23=24
25 | T__24=25
26 | T__25=26
27 | T__26=27
28 | T__27=28
29 | T__28=29
30 | T__29=30
31 | T__30=31
32 | T__31=32
33 | T__32=33
34 | T__33=34
35 | T__34=35
36 | T__35=36
37 | T__36=37
38 | T__37=38
39 | T__38=39
40 | T__39=40
41 | T__40=41
42 | T__41=42
43 | T__42=43
44 | T__43=44
45 | T__44=45
46 | T__45=46
47 | T__46=47
48 | T__47=48
49 | T__48=49
50 | T__49=50
51 | T__50=51
52 | T__51=52
53 | T__52=53
54 | T__53=54
55 | T__54=55
56 | T__55=56
57 | T__56=57
58 | T__57=58
59 | T__58=59
60 | T__59=60
61 | T__60=61
62 | T__61=62
63 | T__62=63
64 | T__63=64
65 | T__64=65
66 | T__65=66
67 | T__66=67
68 | T__67=68
69 | IDENTIFIER=69
70 | KEYWORD=70
71 | BINARY_OP=71
72 | FUNC=72
73 | INT_LIT=73
74 | FLOAT_LIT=74
75 | IMAGINARY_LIT=75
76 | RUNE_LIT=76
77 | LITTLE_U_VALUE=77
78 | BIG_U_VALUE=78
79 | STRING_LIT=79
80 | WS=80
81 | COMMENT=81
82 | LINE_COMMENT=82
83 | TERMINATOR=83
84 | ErrorChar=84
85 | 'package'=1
86 | '!'=2
87 | 'import'=3
88 | '('=4
89 | ')'=5
90 | '{'=6
91 | '}'=7
92 | ':'=8
93 | '.'=9
94 | 'const'=10
95 | '='=11
96 | '_'=12
97 | ','=13
98 | 'type'=14
99 | '::'=15
100 | '*'=16
101 | 'var'=17
102 | '<-'=18
103 | '++'=19
104 | '--'=20
105 | '+'=21
106 | '-'=22
107 | '|'=23
108 | '^'=24
109 | '/'=25
110 | '%'=26
111 | '<<'=27
112 | '>>'=28
113 | '&'=29
114 | '&^'=30
115 | ':='=31
116 | ';'=32
117 | '~'=33
118 | 'return'=34
119 | 'break'=35
120 | 'continue'=36
121 | 'goto'=37
122 | 'fallthrough'=38
123 | 'defer'=39
124 | 'if'=40
125 | '=>'=41
126 | 'else'=42
127 | 'switch'=43
128 | 'select'=44
129 | 'for'=45
130 | 'in'=46
131 | 'go'=47
132 | '['=48
133 | ']'=49
134 | 'interface'=50
135 | 'map'=51
136 | 'chan'=52
137 | 'fn'=53
138 | '<'=54
139 | '>'=55
140 | '...'=56
141 | 'true'=57
142 | 'false'=58
143 | 'nil'=59
144 | '@'=60
145 | 'struct'=61
146 | 'class'=62
147 | '||'=63
148 | '&&'=64
149 | '=='=65
150 | '!='=66
151 | '<='=67
152 | '>='=68
153 | '->'=72
154 |
--------------------------------------------------------------------------------
/parser/antlr4-4.7.2-SNAPSHOT-complete.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Champii/og/228c5a04bfb7c7a4784932ca4b8121e3385d8365/parser/antlr4-4.7.2-SNAPSHOT-complete.jar
--------------------------------------------------------------------------------
/parser/og_visitor.go:
--------------------------------------------------------------------------------
1 | // Generated from ./parser/Og.g4 by ANTLR 4.7.1.
2 |
3 | package parser // Og
4 |
5 | import "github.com/champii/antlr4/runtime/Go/antlr"
6 |
7 | // A complete Visitor for a parse tree produced by OgParser.
8 | type OgVisitor interface {
9 | antlr.ParseTreeVisitor
10 | }
11 |
12 | type SourceFileVisitor interface {
13 | VisitSourceFile(ctx *SourceFileContext, delegate antlr.ParseTreeVisitor) interface{}
14 | }
15 | type InterpVisitor interface {
16 | VisitInterp(ctx *InterpContext, delegate antlr.ParseTreeVisitor) interface{}
17 | }
18 | type PackageClauseVisitor interface {
19 | VisitPackageClause(ctx *PackageClauseContext, delegate antlr.ParseTreeVisitor) interface{}
20 | }
21 | type ImportDeclVisitor interface {
22 | VisitImportDecl(ctx *ImportDeclContext, delegate antlr.ParseTreeVisitor) interface{}
23 | }
24 | type ImportBodyVisitor interface {
25 | VisitImportBody(ctx *ImportBodyContext, delegate antlr.ParseTreeVisitor) interface{}
26 | }
27 | type ImportSpecVisitor interface {
28 | VisitImportSpec(ctx *ImportSpecContext, delegate antlr.ParseTreeVisitor) interface{}
29 | }
30 | type ImportPathVisitor interface {
31 | VisitImportPath(ctx *ImportPathContext, delegate antlr.ParseTreeVisitor) interface{}
32 | }
33 | type TopLevelDeclVisitor interface {
34 | VisitTopLevelDecl(ctx *TopLevelDeclContext, delegate antlr.ParseTreeVisitor) interface{}
35 | }
36 | type DeclarationVisitor interface {
37 | VisitDeclaration(ctx *DeclarationContext, delegate antlr.ParseTreeVisitor) interface{}
38 | }
39 | type ConstDeclVisitor interface {
40 | VisitConstDecl(ctx *ConstDeclContext, delegate antlr.ParseTreeVisitor) interface{}
41 | }
42 | type ConstSpecVisitor interface {
43 | VisitConstSpec(ctx *ConstSpecContext, delegate antlr.ParseTreeVisitor) interface{}
44 | }
45 | type IdentifierListVisitor interface {
46 | VisitIdentifierList(ctx *IdentifierListContext, delegate antlr.ParseTreeVisitor) interface{}
47 | }
48 | type ExpressionListVisitor interface {
49 | VisitExpressionList(ctx *ExpressionListContext, delegate antlr.ParseTreeVisitor) interface{}
50 | }
51 | type TypeDeclVisitor interface {
52 | VisitTypeDecl(ctx *TypeDeclContext, delegate antlr.ParseTreeVisitor) interface{}
53 | }
54 | type TypeSpecVisitor interface {
55 | VisitTypeSpec(ctx *TypeSpecContext, delegate antlr.ParseTreeVisitor) interface{}
56 | }
57 | type FunctionDeclVisitor interface {
58 | VisitFunctionDecl(ctx *FunctionDeclContext, delegate antlr.ParseTreeVisitor) interface{}
59 | }
60 | type FunctionVisitor interface {
61 | VisitFunction(ctx *FunctionContext, delegate antlr.ParseTreeVisitor) interface{}
62 | }
63 | type MethodDeclVisitor interface {
64 | VisitMethodDecl(ctx *MethodDeclContext, delegate antlr.ParseTreeVisitor) interface{}
65 | }
66 | type ReceiverVisitor interface {
67 | VisitReceiver(ctx *ReceiverContext, delegate antlr.ParseTreeVisitor) interface{}
68 | }
69 | type VarDeclVisitor interface {
70 | VisitVarDecl(ctx *VarDeclContext, delegate antlr.ParseTreeVisitor) interface{}
71 | }
72 | type VarSpecVisitor interface {
73 | VisitVarSpec(ctx *VarSpecContext, delegate antlr.ParseTreeVisitor) interface{}
74 | }
75 | type BlockVisitor interface {
76 | VisitBlock(ctx *BlockContext, delegate antlr.ParseTreeVisitor) interface{}
77 | }
78 | type StatementListVisitor interface {
79 | VisitStatementList(ctx *StatementListContext, delegate antlr.ParseTreeVisitor) interface{}
80 | }
81 | type StatementVisitor interface {
82 | VisitStatement(ctx *StatementContext, delegate antlr.ParseTreeVisitor) interface{}
83 | }
84 | type SimpleStmtVisitor interface {
85 | VisitSimpleStmt(ctx *SimpleStmtContext, delegate antlr.ParseTreeVisitor) interface{}
86 | }
87 | type SendStmtVisitor interface {
88 | VisitSendStmt(ctx *SendStmtContext, delegate antlr.ParseTreeVisitor) interface{}
89 | }
90 | type IncDecStmtVisitor interface {
91 | VisitIncDecStmt(ctx *IncDecStmtContext, delegate antlr.ParseTreeVisitor) interface{}
92 | }
93 | type AssignmentVisitor interface {
94 | VisitAssignment(ctx *AssignmentContext, delegate antlr.ParseTreeVisitor) interface{}
95 | }
96 | type Assign_opVisitor interface {
97 | VisitAssign_op(ctx *Assign_opContext, delegate antlr.ParseTreeVisitor) interface{}
98 | }
99 | type ShortVarDeclVisitor interface {
100 | VisitShortVarDecl(ctx *ShortVarDeclContext, delegate antlr.ParseTreeVisitor) interface{}
101 | }
102 | type EmptyStmtVisitor interface {
103 | VisitEmptyStmt(ctx *EmptyStmtContext, delegate antlr.ParseTreeVisitor) interface{}
104 | }
105 | type LabeledStmtVisitor interface {
106 | VisitLabeledStmt(ctx *LabeledStmtContext, delegate antlr.ParseTreeVisitor) interface{}
107 | }
108 | type ReturnStmtVisitor interface {
109 | VisitReturnStmt(ctx *ReturnStmtContext, delegate antlr.ParseTreeVisitor) interface{}
110 | }
111 | type BreakStmtVisitor interface {
112 | VisitBreakStmt(ctx *BreakStmtContext, delegate antlr.ParseTreeVisitor) interface{}
113 | }
114 | type ContinueStmtVisitor interface {
115 | VisitContinueStmt(ctx *ContinueStmtContext, delegate antlr.ParseTreeVisitor) interface{}
116 | }
117 | type GotoStmtVisitor interface {
118 | VisitGotoStmt(ctx *GotoStmtContext, delegate antlr.ParseTreeVisitor) interface{}
119 | }
120 | type FallthroughStmtVisitor interface {
121 | VisitFallthroughStmt(ctx *FallthroughStmtContext, delegate antlr.ParseTreeVisitor) interface{}
122 | }
123 | type DeferStmtVisitor interface {
124 | VisitDeferStmt(ctx *DeferStmtContext, delegate antlr.ParseTreeVisitor) interface{}
125 | }
126 | type IfStmtVisitor interface {
127 | VisitIfStmt(ctx *IfStmtContext, delegate antlr.ParseTreeVisitor) interface{}
128 | }
129 | type SwitchStmtVisitor interface {
130 | VisitSwitchStmt(ctx *SwitchStmtContext, delegate antlr.ParseTreeVisitor) interface{}
131 | }
132 | type ExprSwitchStmtVisitor interface {
133 | VisitExprSwitchStmt(ctx *ExprSwitchStmtContext, delegate antlr.ParseTreeVisitor) interface{}
134 | }
135 | type ExprCaseClauseVisitor interface {
136 | VisitExprCaseClause(ctx *ExprCaseClauseContext, delegate antlr.ParseTreeVisitor) interface{}
137 | }
138 | type ExprSwitchCaseVisitor interface {
139 | VisitExprSwitchCase(ctx *ExprSwitchCaseContext, delegate antlr.ParseTreeVisitor) interface{}
140 | }
141 | type TypeSwitchStmtVisitor interface {
142 | VisitTypeSwitchStmt(ctx *TypeSwitchStmtContext, delegate antlr.ParseTreeVisitor) interface{}
143 | }
144 | type TypeSwitchGuardVisitor interface {
145 | VisitTypeSwitchGuard(ctx *TypeSwitchGuardContext, delegate antlr.ParseTreeVisitor) interface{}
146 | }
147 | type TypeCaseClauseVisitor interface {
148 | VisitTypeCaseClause(ctx *TypeCaseClauseContext, delegate antlr.ParseTreeVisitor) interface{}
149 | }
150 | type TypeSwitchCaseVisitor interface {
151 | VisitTypeSwitchCase(ctx *TypeSwitchCaseContext, delegate antlr.ParseTreeVisitor) interface{}
152 | }
153 | type TypeListVisitor interface {
154 | VisitTypeList(ctx *TypeListContext, delegate antlr.ParseTreeVisitor) interface{}
155 | }
156 | type SelectStmtVisitor interface {
157 | VisitSelectStmt(ctx *SelectStmtContext, delegate antlr.ParseTreeVisitor) interface{}
158 | }
159 | type CommClauseVisitor interface {
160 | VisitCommClause(ctx *CommClauseContext, delegate antlr.ParseTreeVisitor) interface{}
161 | }
162 | type CommCaseVisitor interface {
163 | VisitCommCase(ctx *CommCaseContext, delegate antlr.ParseTreeVisitor) interface{}
164 | }
165 | type RecvStmtVisitor interface {
166 | VisitRecvStmt(ctx *RecvStmtContext, delegate antlr.ParseTreeVisitor) interface{}
167 | }
168 | type ForStmtVisitor interface {
169 | VisitForStmt(ctx *ForStmtContext, delegate antlr.ParseTreeVisitor) interface{}
170 | }
171 | type ForClauseVisitor interface {
172 | VisitForClause(ctx *ForClauseContext, delegate antlr.ParseTreeVisitor) interface{}
173 | }
174 | type RangeClauseVisitor interface {
175 | VisitRangeClause(ctx *RangeClauseContext, delegate antlr.ParseTreeVisitor) interface{}
176 | }
177 | type GoStmtVisitor interface {
178 | VisitGoStmt(ctx *GoStmtContext, delegate antlr.ParseTreeVisitor) interface{}
179 | }
180 | type Type_Visitor interface {
181 | VisitType_(ctx *Type_Context, delegate antlr.ParseTreeVisitor) interface{}
182 | }
183 | type TypeNameVisitor interface {
184 | VisitTypeName(ctx *TypeNameContext, delegate antlr.ParseTreeVisitor) interface{}
185 | }
186 | type TypeLitVisitor interface {
187 | VisitTypeLit(ctx *TypeLitContext, delegate antlr.ParseTreeVisitor) interface{}
188 | }
189 | type ArrayTypeVisitor interface {
190 | VisitArrayType(ctx *ArrayTypeContext, delegate antlr.ParseTreeVisitor) interface{}
191 | }
192 | type ArrayLengthVisitor interface {
193 | VisitArrayLength(ctx *ArrayLengthContext, delegate antlr.ParseTreeVisitor) interface{}
194 | }
195 | type ElementTypeVisitor interface {
196 | VisitElementType(ctx *ElementTypeContext, delegate antlr.ParseTreeVisitor) interface{}
197 | }
198 | type PointerTypeVisitor interface {
199 | VisitPointerType(ctx *PointerTypeContext, delegate antlr.ParseTreeVisitor) interface{}
200 | }
201 | type InterfaceTypeVisitor interface {
202 | VisitInterfaceType(ctx *InterfaceTypeContext, delegate antlr.ParseTreeVisitor) interface{}
203 | }
204 | type SliceTypeVisitor interface {
205 | VisitSliceType(ctx *SliceTypeContext, delegate antlr.ParseTreeVisitor) interface{}
206 | }
207 | type MapTypeVisitor interface {
208 | VisitMapType(ctx *MapTypeContext, delegate antlr.ParseTreeVisitor) interface{}
209 | }
210 | type ChannelTypeVisitor interface {
211 | VisitChannelType(ctx *ChannelTypeContext, delegate antlr.ParseTreeVisitor) interface{}
212 | }
213 | type ChannelDeclVisitor interface {
214 | VisitChannelDecl(ctx *ChannelDeclContext, delegate antlr.ParseTreeVisitor) interface{}
215 | }
216 | type MethodSpecVisitor interface {
217 | VisitMethodSpec(ctx *MethodSpecContext, delegate antlr.ParseTreeVisitor) interface{}
218 | }
219 | type FunctionTypeVisitor interface {
220 | VisitFunctionType(ctx *FunctionTypeContext, delegate antlr.ParseTreeVisitor) interface{}
221 | }
222 | type SignatureVisitor interface {
223 | VisitSignature(ctx *SignatureContext, delegate antlr.ParseTreeVisitor) interface{}
224 | }
225 | type TemplateSpecVisitor interface {
226 | VisitTemplateSpec(ctx *TemplateSpecContext, delegate antlr.ParseTreeVisitor) interface{}
227 | }
228 | type ResultVisitor interface {
229 | VisitResult(ctx *ResultContext, delegate antlr.ParseTreeVisitor) interface{}
230 | }
231 | type ParametersVisitor interface {
232 | VisitParameters(ctx *ParametersContext, delegate antlr.ParseTreeVisitor) interface{}
233 | }
234 | type ParameterListVisitor interface {
235 | VisitParameterList(ctx *ParameterListContext, delegate antlr.ParseTreeVisitor) interface{}
236 | }
237 | type ParameterDeclVisitor interface {
238 | VisitParameterDecl(ctx *ParameterDeclContext, delegate antlr.ParseTreeVisitor) interface{}
239 | }
240 | type RestOpVisitor interface {
241 | VisitRestOp(ctx *RestOpContext, delegate antlr.ParseTreeVisitor) interface{}
242 | }
243 | type OperandVisitor interface {
244 | VisitOperand(ctx *OperandContext, delegate antlr.ParseTreeVisitor) interface{}
245 | }
246 | type LiteralVisitor interface {
247 | VisitLiteral(ctx *LiteralContext, delegate antlr.ParseTreeVisitor) interface{}
248 | }
249 | type BasicLitVisitor interface {
250 | VisitBasicLit(ctx *BasicLitContext, delegate antlr.ParseTreeVisitor) interface{}
251 | }
252 | type OperandNameVisitor interface {
253 | VisitOperandName(ctx *OperandNameContext, delegate antlr.ParseTreeVisitor) interface{}
254 | }
255 | type This_Visitor interface {
256 | VisitThis_(ctx *This_Context, delegate antlr.ParseTreeVisitor) interface{}
257 | }
258 | type QualifiedIdentVisitor interface {
259 | VisitQualifiedIdent(ctx *QualifiedIdentContext, delegate antlr.ParseTreeVisitor) interface{}
260 | }
261 | type CompositeLitVisitor interface {
262 | VisitCompositeLit(ctx *CompositeLitContext, delegate antlr.ParseTreeVisitor) interface{}
263 | }
264 | type LiteralTypeVisitor interface {
265 | VisitLiteralType(ctx *LiteralTypeContext, delegate antlr.ParseTreeVisitor) interface{}
266 | }
267 | type LiteralValueVisitor interface {
268 | VisitLiteralValue(ctx *LiteralValueContext, delegate antlr.ParseTreeVisitor) interface{}
269 | }
270 | type ElementListVisitor interface {
271 | VisitElementList(ctx *ElementListContext, delegate antlr.ParseTreeVisitor) interface{}
272 | }
273 | type KeyedElementVisitor interface {
274 | VisitKeyedElement(ctx *KeyedElementContext, delegate antlr.ParseTreeVisitor) interface{}
275 | }
276 | type KeyVisitor interface {
277 | VisitKey(ctx *KeyContext, delegate antlr.ParseTreeVisitor) interface{}
278 | }
279 | type ElementVisitor interface {
280 | VisitElement(ctx *ElementContext, delegate antlr.ParseTreeVisitor) interface{}
281 | }
282 | type StructTypeVisitor interface {
283 | VisitStructType(ctx *StructTypeContext, delegate antlr.ParseTreeVisitor) interface{}
284 | }
285 | type FieldDeclVisitor interface {
286 | VisitFieldDecl(ctx *FieldDeclContext, delegate antlr.ParseTreeVisitor) interface{}
287 | }
288 | type InlineStructMethodVisitor interface {
289 | VisitInlineStructMethod(ctx *InlineStructMethodContext, delegate antlr.ParseTreeVisitor) interface{}
290 | }
291 | type AnonymousFieldVisitor interface {
292 | VisitAnonymousField(ctx *AnonymousFieldContext, delegate antlr.ParseTreeVisitor) interface{}
293 | }
294 | type FunctionLitVisitor interface {
295 | VisitFunctionLit(ctx *FunctionLitContext, delegate antlr.ParseTreeVisitor) interface{}
296 | }
297 | type PrimaryExprVisitor interface {
298 | VisitPrimaryExpr(ctx *PrimaryExprContext, delegate antlr.ParseTreeVisitor) interface{}
299 | }
300 | type SecondaryExprVisitor interface {
301 | VisitSecondaryExpr(ctx *SecondaryExprContext, delegate antlr.ParseTreeVisitor) interface{}
302 | }
303 | type SelectorVisitor interface {
304 | VisitSelector(ctx *SelectorContext, delegate antlr.ParseTreeVisitor) interface{}
305 | }
306 | type IndexVisitor interface {
307 | VisitIndex(ctx *IndexContext, delegate antlr.ParseTreeVisitor) interface{}
308 | }
309 | type SliceVisitor interface {
310 | VisitSlice(ctx *SliceContext, delegate antlr.ParseTreeVisitor) interface{}
311 | }
312 | type TypeAssertionVisitor interface {
313 | VisitTypeAssertion(ctx *TypeAssertionContext, delegate antlr.ParseTreeVisitor) interface{}
314 | }
315 | type ArgumentsVisitor interface {
316 | VisitArguments(ctx *ArgumentsContext, delegate antlr.ParseTreeVisitor) interface{}
317 | }
318 | type MethodExprVisitor interface {
319 | VisitMethodExpr(ctx *MethodExprContext, delegate antlr.ParseTreeVisitor) interface{}
320 | }
321 | type ReceiverTypeVisitor interface {
322 | VisitReceiverType(ctx *ReceiverTypeContext, delegate antlr.ParseTreeVisitor) interface{}
323 | }
324 | type ExpressionVisitor interface {
325 | VisitExpression(ctx *ExpressionContext, delegate antlr.ParseTreeVisitor) interface{}
326 | }
327 | type UnaryExprVisitor interface {
328 | VisitUnaryExpr(ctx *UnaryExprContext, delegate antlr.ParseTreeVisitor) interface{}
329 | }
330 | type ConversionVisitor interface {
331 | VisitConversion(ctx *ConversionContext, delegate antlr.ParseTreeVisitor) interface{}
332 | }
333 | type EosVisitor interface {
334 | VisitEos(ctx *EosContext, delegate antlr.ParseTreeVisitor) interface{}
335 | }
336 |
--------------------------------------------------------------------------------
/scripts/fix_parser_imports.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | sed -i -e 's/"strconv"/"strconv"\n\t"strings"/g' parser/og_parser.go
--------------------------------------------------------------------------------
/scripts/release_from_develop.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | BRANCH=`git branch | grep '*'`
6 |
7 | if [[ "$BRANCH" != "* develop" ]]; then
8 | echo "Must be launched from develop"
9 | exit 1
10 | fi
11 |
12 | TYPE=patch
13 |
14 | if [[ "$1" != "" ]]; then
15 | TYPE=$1
16 | fi
17 |
18 | VERSION=`git describe --abbrev=0`
19 |
20 | VERSION_BITS=(${VERSION//./ })
21 |
22 | VNUM1=${VERSION_BITS[0]}
23 | VNUM2=${VERSION_BITS[1]}
24 | VNUM3=${VERSION_BITS[2]}
25 |
26 | if [[ "$TYPE" == "patch" ]]; then
27 | VNUM3=$((VNUM3+1))
28 | elif [[ "$TYPE" == "minor" ]]; then
29 | VNUM2=$((VNUM2+1))
30 | VNUM3=0
31 | elif [[ "$TYPE" == "major" ]]; then
32 | VNUM1=$((VNUM1+1))
33 | VNUM2=0
34 | VNUM3=0
35 | else
36 | echo "Bad semver action: $TYPE"
37 | exit 1
38 | fi
39 |
40 | NEW_TAG="$VNUM1.$VNUM2.$VNUM3"
41 |
42 | echo "Preparing next version: $NEW_TAG"
43 |
44 | sed -i -e "s/DEV: Current version/$NEW_TAG: Current version/g" docs/changelog.md
45 |
46 | sed -i -e "s/DEV/$NEW_TAG/g" docs/index.html
47 |
48 | sed -i -e "s/DEV/$NEW_TAG/g" docs/usage.md
49 |
50 | sed -i -e "s/DEV/$NEW_TAG/g" docs/_coverpage.md
51 |
52 | sed -i -e "s/DEV/$NEW_TAG/g" README.md
53 |
54 | sed -i -e "s/DEV/$NEW_TAG/g" cli.go
55 |
56 | git commit -am "Version tag $NEW_TAG"
57 |
58 | git push origin develop
59 |
60 | echo "Releasing $NEW_TAG to master"
61 |
62 | git checkout master
63 |
64 | git pull origin master
65 |
66 | git pull origin develop
67 |
68 | git push origin master
69 |
70 | git tag -a $NEW_TAG -m "$NEW_TAG"
71 |
72 | git push --tags
73 |
74 | echo "Update the global Og binary to $NEW_TAG"
75 |
76 | go get github.com/champii/og
77 |
78 | git checkout develop
79 |
80 | git pull origin master
81 |
82 | echo "Release of $NEW_TAG OK"
83 |
84 | echo "Restoring DEV tag in develop"
85 |
86 | sed -i -e "s/$NEW_TAG: Current version/DEV: Current version\\n\\n## $NEW_TAG/g" docs/changelog.md
87 |
88 | sed -i -e "s/$NEW_TAG/DEV/g" docs/index.html
89 |
90 | sed -i -e "s/$NEW_TAG/DEV/g" docs/_coverpage.md
91 |
92 | sed -i -e "s/$NEW_TAG/DEV/g" docs/usage.md
93 |
94 | sed -i -e "s/$NEW_TAG/DEV/g" README.md
95 |
96 | sed -i -e "s/$NEW_TAG/DEV/g" cli.go
97 |
98 | git commit -am "Restoring DEV version"
99 |
100 | git push origin develop
101 |
102 | echo "Ok"
103 |
--------------------------------------------------------------------------------
/tests/exemples/.og/template:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Champii/og/228c5a04bfb7c7a4784932ca4b8121e3385d8365/tests/exemples/.og/template
--------------------------------------------------------------------------------
/tests/exemples/anonymous.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | struct Foo
4 | *SomeClass
5 |
6 | struct Foo
7 | SomeClass
8 |
9 | struct Foo
10 | SomeClass
11 | *SomeClass2
12 |
--------------------------------------------------------------------------------
/tests/exemples/assignable_stmt.og:
--------------------------------------------------------------------------------
1 | !og
2 |
3 | voila: int ->
4 | var a int = if true
5 | 1
6 | else
7 | 2
8 |
9 | var b int = if true => 1 ; else => 2
10 |
11 | if true => 1
12 | else => 2
13 |
--------------------------------------------------------------------------------
/tests/exemples/bar/.og/template:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Champii/og/228c5a04bfb7c7a4784932ca4b8121e3385d8365/tests/exemples/bar/.og/template
--------------------------------------------------------------------------------
/tests/exemples/bar/bar.go:
--------------------------------------------------------------------------------
1 | package bar
2 |
--------------------------------------------------------------------------------
/tests/exemples/bar/bar.og:
--------------------------------------------------------------------------------
1 | !bar
2 |
3 | struct Foo
4 | bar T
5 |
--------------------------------------------------------------------------------
/tests/exemples/bitwise.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | main ->
4 | x := 0xAC
5 | x = x & 0xF0
6 | x = x | 0xF0
7 | x = x ^ 0xF0
8 | x = x &^ 0xF0
9 | x = x >> 0xF0
10 | x = x << 0xF0
--------------------------------------------------------------------------------
/tests/exemples/chan.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | someFunc(c1 chan<- int,c2 <-chan int): chan int -> 0
4 | main ->
5 | c := make(chan string)
6 | c := make(chan<- string)
7 | c := make(<-chan string)
8 |
--------------------------------------------------------------------------------
/tests/exemples/const.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | const foo = "bar"
4 | const foo string = "bar"
5 |
--------------------------------------------------------------------------------
/tests/exemples/for.og:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import
4 | "fmt"
5 |
6 | main ->
7 | for _, i in a
8 | fmt.Println(i)
9 |
10 | for i < 10
11 | fmt.Println(i)
12 |
13 | for i := 0; i < 10; i++
14 | fmt.Println(i)
15 |
--------------------------------------------------------------------------------
/tests/exemples/func_literal.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | main ->
4 | a := fn -> fmt.Println(1)
5 | a := fn :int -> return 1
6 | b := fn (a int) -> fmt.Println(a)
7 | c := fn (a int): int -> return a
8 |
--------------------------------------------------------------------------------
/tests/exemples/func_type.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | a(arg fn:int) ->
4 | arg()
5 |
6 | main ->
7 | a(fn:int->2)
--------------------------------------------------------------------------------
/tests/exemples/generics.og:
--------------------------------------------------------------------------------
1 | !og
2 |
3 | import
4 | "github.com/champii/og/tests/exemples/bar"
5 |
6 | a(t T): T-> t
7 |
8 | struct Foo
9 | bar T
10 |
11 | main ->
12 | fmt.Println(a(1))
13 | fmt.Println(a("a"))
14 | a := Foo
15 | bar: 1
16 |
17 | # b := bar.Foo
18 | # bar: 1
19 |
--------------------------------------------------------------------------------
/tests/exemples/goroutine.og:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | main ->
4 | go ->
5 | fmt.Println("test")
6 |
7 | go some.lol()
8 |
--------------------------------------------------------------------------------
/tests/exemples/if.og:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | main ->
4 | a := 2
5 |
6 | if a == 2
7 | fmt.Println(a)
8 |
9 | if a == 2
10 | fmt.Println(a)
11 | else
12 | fmt.Println(a)
13 |
14 | if a == 2
15 | fmt.Println(a)
16 | else if a == 3
17 | fmt.Println(a)
18 |
19 | if a == 2
20 | fmt.Println(a)
21 | else if a == 3
22 | fmt.Println(a)
23 | else if a == 4
24 | fmt.Println(a)
25 | else
26 | fmt.Println(a)
27 |
28 | if a != a => fmt.Println(a)
29 | else if b != b => fmt.Println(a)
30 | else => fmt.Println(a)
31 |
32 |
--------------------------------------------------------------------------------
/tests/exemples/import.og:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import
4 | fmt
5 | strings
6 | "some/repo": otherName
7 | "another/repo": .
8 |
--------------------------------------------------------------------------------
/tests/exemples/import_parenthesis.og:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | fmt
5 | strings
6 | )
--------------------------------------------------------------------------------
/tests/exemples/inc.og:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | main ->
4 | a := 1
5 |
6 | a++
7 | a--
8 |
9 | a.b.c().d++
10 |
--------------------------------------------------------------------------------
/tests/exemples/interface.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | interface Foo
4 |
5 | type Foo2 interface
6 |
7 | interface Foo4
8 | Foo(a int): string
9 |
10 | interface Foo5
11 | SomeType
12 | Foo()
13 | Bar(a int): string
14 | Other : interface{}
15 |
--------------------------------------------------------------------------------
/tests/exemples/internal_method.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | class Foo
4 | a int
5 | f -> fmt.Println(@a)
6 | *g -> fmt.Println(@a)
7 |
8 | main ->
9 | foo := Foo{}
10 | foo.f()
11 |
--------------------------------------------------------------------------------
/tests/exemples/loop_flow.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | main ->
4 | ~here: toto()
5 | for i in foo
6 | continue
7 | continue label
8 | break
9 | break label
10 | fallthrough
11 | goto here
12 |
--------------------------------------------------------------------------------
/tests/exemples/map.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | someFunc(m map[string]string): map[string]string -> return m
4 | main ->
5 | m := map[string]string{}
6 |
--------------------------------------------------------------------------------
/tests/exemples/nested_property.og:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | main ->
4 | a.b[1][2].c()()(a)[1].d
--------------------------------------------------------------------------------
/tests/exemples/operation.og:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | main ->
4 | a := 1 + 1
5 | b := 1 + 2 / 4 - 21 % 42 * 84
--------------------------------------------------------------------------------
/tests/exemples/package.og:
--------------------------------------------------------------------------------
1 | package main
2 |
--------------------------------------------------------------------------------
/tests/exemples/package_short.og:
--------------------------------------------------------------------------------
1 | !main
--------------------------------------------------------------------------------
/tests/exemples/ref.og:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | main ->
4 | a := &b
5 | b := **a.b
6 |
--------------------------------------------------------------------------------
/tests/exemples/rest.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | someFunc(a int, b ...int) ->
4 | fmt.Println(a, b)
5 |
6 | main ->
7 | a := []int{1, 2, 3}
8 | someFunc(a...)
9 |
--------------------------------------------------------------------------------
/tests/exemples/select.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | main ->
4 | c1 := make(chan int)
5 | c2 := make(chan int)
6 |
7 | select
8 | <-c1 => fmt.Println("Yeah")
9 | x := <-c2 => fmt.Println("Yeah", x)
10 | x := <-c2 =>
11 | fmt.Println("Yeah", x)
12 | fmt.Println("Yeah2", x)
13 | c2 <- 1 => fmt.Println("Yeah", x)
14 | _ => fmt.Println("Default")
15 |
--------------------------------------------------------------------------------
/tests/exemples/slices.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | main ->
4 | a := []string
5 | "a"
6 | "b"
7 | "c"
8 |
9 | b := a[1:2]
10 | b := a[1:]
11 | b := a[:]
12 | b := a[:3]
13 | b := a[1:2:3]
14 | b := a[:2:3]
15 |
--------------------------------------------------------------------------------
/tests/exemples/struct.og:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | struct Foo
4 | class Foo
5 | type Foo struct
6 | type Foo class
7 |
8 | class Foo
9 | bar string
10 |
11 | struct Foo
12 | foo int
13 | bar string
14 |
15 | type FooTag struct
16 | bar string `json: "test"`
17 | foobar int `sql: "-"`
18 |
--------------------------------------------------------------------------------
/tests/exemples/struct_inst.og:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | class Foo
4 | foo int
5 | bar string
6 |
7 | main ->
8 | a := Foo
9 | foo: 1
10 | bar: "lol"
11 |
--------------------------------------------------------------------------------
/tests/exemples/switch.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | main ->
4 | switch a
5 | 2 => 1
6 |
7 | switch b
8 | "x" => b
9 | _ => other
10 |
11 | switch t.(type)
12 | string => "string"
13 | _ => "other"
14 |
15 | switch res := t.(type)
16 | string => res
17 | _ => "other"
18 |
--------------------------------------------------------------------------------
/tests/exemples/test.og:
--------------------------------------------------------------------------------
1 | !og
2 |
3 | #struct Foo
4 | # bar T
5 |
6 | #main ->
7 | # wesh := tata.Foo2
8 | # bar: 1
9 |
--------------------------------------------------------------------------------
/tests/exemples/this.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | struct Test
4 | i int
5 |
6 | Test::f : Test -> @
7 | Test::*g : int -> @i
8 |
--------------------------------------------------------------------------------
/tests/exemples/top_fn.og:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | oneLiner -> fmt.Println("a")
4 |
5 | testBody ->
6 | fmt.Println("a")
7 |
8 | testArg (str string) ->
9 | fmt.Println(str)
10 |
11 | arrArg (str []string) ->
12 | fmt.Println(str)
13 |
14 | doubleArrArg (str [][]string) ->
15 | fmt.Println(str)
16 |
17 | doubleArrPointerArg (str **[]*[]*string) ->
18 | fmt.Println(str)
19 |
20 | testRet (str string): string ->
21 | return str
22 |
23 | testRet2 (str string, str2 string): string, string ->
24 | return str, str2
25 |
26 | testAssign ->
27 | a := foo()
28 | a, b := foo()
29 | a, b, c := foo()
30 |
--------------------------------------------------------------------------------
/tests/exemples/utopia.og.exemple:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | import fmt
4 |
5 | // Generics
6 | struct Generic
7 | // attributes
8 | pub test T
9 |
10 | // Instance method
11 | fn : T -> @test
12 |
13 | // Class method with external type declaration
14 | $ T -> Generic
15 | pub @new(v) -> Generic{ v }
16 |
17 |
18 | // External grouped method definition
19 | Generic::(
20 | // With '*', tells the receiver (this or @) is a pointer to Generic
21 | *method1 : int -> 1
22 |
23 | // External type declaration with no return
24 | $ int -> SomeComplexType -> (AnotherOne -> interface{}) -> ()
25 | method2(a, b, c) -> 2
26 | )
27 |
28 | // Returnable statements, nil existence test, predicat recapture (that)
29 | genericFunc(g Generic): T -> if g.fn()? => that
30 | else => somethingElse
31 |
32 | // External type declaration
33 | $ Generic -> T
34 | genericFunc(g) -> g.test
35 |
36 | // Multiple return values
37 | $ int -> (int, string)
38 | multipleReturn(i) -> i, "foo"
39 |
40 | // Automatic "it" argument when not specified
41 | $ string -> string
42 | someFunc -> it + "Hello"
43 |
44 | // No arguments, multiple return values, error bubbling
45 | # (error, SomeType)
46 | failableFunc ->
47 | res1 := funcsThatMayFail()?
48 | res2 := funcsThatFail()?
49 |
50 | res1 + res2
51 |
52 | // Macro definition (like rust)
53 | $macro my_macro ->
54 | ($number:expr) =>
55 | myFunc$(number) : int -> $number
56 | if $number > 0
57 | $my_macro($number - 1)
58 |
59 | // Generate 10 function `myFunc10(), myFunc9(), .. myFunc0()` that all return their number,
60 | $my_macro(10)
61 |
62 | // Operator definition with precedence
63 | operator ~~ 9
64 |
65 | // Typeclass (could be implemented with macros ? lets see...)
66 | impl SomeTypeClass for MyType
67 | x ~~ y = x.DoSomething(y)
68 |
69 | main ->
70 | t := Generic::new("str")
71 |
72 | // Range array creation, call chaining,
73 | // function currying and function shorthand.
74 | // Here a == [10, 11, 12, 13, 14, 15]
75 | a := []int{0..10}
76 | |> map((+ 10))
77 | |> filter((<= 15))
78 |
79 | // Function composition
80 | f := map >> filter
81 |
--------------------------------------------------------------------------------
/tests/exemples/var.og:
--------------------------------------------------------------------------------
1 | !main
2 |
3 | var foo string
4 | var foo = "bar"
5 | var foo string = "bar"
6 |
--------------------------------------------------------------------------------
/tests/og_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 |
7 | "github.com/champii/og/lib/common"
8 | "github.com/champii/og/lib/og"
9 | )
10 |
11 | func TestMain(t *testing.T) {
12 | expected := []string{
13 | // package.og
14 | `package main
15 | `,
16 | // package_short.og
17 | `package main
18 | `,
19 | // import.og
20 | `package main
21 |
22 | import (
23 | . "another/repo"
24 | "fmt"
25 | otherName "some/repo"
26 | "strings"
27 | )
28 | `,
29 | // import_parenthesis.og
30 | `package main
31 |
32 | import (
33 | "fmt"
34 | "strings"
35 | )
36 | `,
37 | // struct.og
38 | `package main
39 |
40 | type Foo struct {
41 | }
42 | type Foo struct {
43 | }
44 | type Foo struct {
45 | }
46 | type Foo struct {
47 | }
48 | type Foo struct {
49 | bar string
50 | }
51 | type Foo struct {
52 | foo int
53 | bar string
54 | }
55 | type FooTag struct {
56 | bar string ` + "`json: \"test\"`" + `
57 | foobar int ` + "`sql: \"-\"`" + `
58 | }
59 | `,
60 | // top_fn.og
61 | `package main
62 |
63 | func oneLiner() {
64 | fmt.Println("a")
65 | }
66 | func testBody() {
67 | fmt.Println("a")
68 | }
69 | func testArg(str string) {
70 | fmt.Println(str)
71 | }
72 | func arrArg(str []string) {
73 | fmt.Println(str)
74 | }
75 | func doubleArrArg(str [][]string) {
76 | fmt.Println(str)
77 | }
78 | func doubleArrPointerArg(str **[]*[]*string) {
79 | fmt.Println(str)
80 | }
81 | func testRet(str string) string {
82 | return str
83 | }
84 | func testRet2(str string, str2 string) (string, string) {
85 | return str, str2
86 | }
87 | func testAssign() {
88 | a := foo()
89 | a, b := foo()
90 | a, b, c := foo()
91 | }
92 | `,
93 | // if.og
94 | `package main
95 |
96 | func main() {
97 | a := 2
98 | if a == 2 {
99 | fmt.Println(a)
100 | }
101 | if a == 2 {
102 | fmt.Println(a)
103 | } else {
104 | fmt.Println(a)
105 | }
106 | if a == 2 {
107 | fmt.Println(a)
108 | } else if a == 3 {
109 | fmt.Println(a)
110 | }
111 | if a == 2 {
112 | fmt.Println(a)
113 | } else if a == 3 {
114 | fmt.Println(a)
115 | } else if a == 4 {
116 | fmt.Println(a)
117 | } else {
118 | fmt.Println(a)
119 | }
120 | if a != a {
121 | fmt.Println(a)
122 | } else if b != b {
123 | fmt.Println(a)
124 | } else {
125 | fmt.Println(a)
126 | }
127 | }
128 | `,
129 | // for.og
130 | `package main
131 |
132 | import (
133 | "fmt"
134 | )
135 |
136 | func main() {
137 | for _, i := range a {
138 | fmt.Println(i)
139 | }
140 | for i < 10 {
141 | fmt.Println(i)
142 | }
143 | for i := 0; i < 10; i++ {
144 | fmt.Println(i)
145 | }
146 | }
147 | `,
148 | // nested_property.og
149 | `package main
150 |
151 | func main() {
152 | a.b[1][2].c()()(a)[1].d
153 | }
154 | `,
155 | // goroutine.og
156 | `package main
157 |
158 | func main() {
159 | go func() {
160 | fmt.Println("test")
161 | }()
162 | go some.lol()
163 | }
164 | `,
165 | // operation.og
166 | `package main
167 |
168 | func main() {
169 | a := 1 + 1
170 | b := 1 + 2/4 - 21%42*84
171 | }
172 | `,
173 | // ref.og
174 | `package main
175 |
176 | func main() {
177 | a := &b
178 | b := **a.b
179 | }
180 | `,
181 | // inc.og
182 | `package main
183 |
184 | func main() {
185 | a := 1
186 | a++
187 | a--
188 | a.b.c().d++
189 | }
190 | `,
191 | // struct_inst.og
192 | `package main
193 |
194 | type Foo struct {
195 | foo int
196 | bar string
197 | }
198 |
199 | func main() {
200 | a := Foo{
201 | foo: 1,
202 | bar: "lol",
203 | }
204 | }
205 | `,
206 | // slices.og
207 | `package main
208 |
209 | func main() {
210 | a := []string{
211 | "a",
212 | "b",
213 | "c",
214 | }
215 | b := a[1:2]
216 | b := a[1:]
217 | b := a[:]
218 | b := a[:3]
219 | b := a[1:2:3]
220 | b := a[:2:3]
221 | }
222 | `,
223 | // interface.og
224 | `package main
225 |
226 | type Foo interface{}
227 | type Foo2 interface{}
228 | type Foo4 interface {
229 | Foo(a int) string
230 | }
231 | type Foo5 interface {
232 | SomeType
233 | Foo()
234 | Bar(a int) string
235 | Other() interface{}
236 | }
237 | `,
238 | // switch.og
239 | `package main
240 |
241 | func main() {
242 | switch a {
243 | case 2:
244 | 1
245 | }
246 | switch b {
247 | case "x":
248 | b
249 | default:
250 | other
251 | }
252 | switch t.(type) {
253 | case string:
254 | "string"
255 | default:
256 | "other"
257 | }
258 | switch res := t.(type) {
259 | case string:
260 | res
261 | default:
262 | "other"
263 | }
264 | }
265 | `,
266 | // this.og
267 | `package main
268 |
269 | type Test struct {
270 | i int
271 | }
272 |
273 | func (this Test) f() Test {
274 | return this
275 | }
276 | func (this *Test) g() int {
277 | return this.i
278 | }
279 | `,
280 | // internal_method.og
281 | `package main
282 |
283 | type Foo struct {
284 | a int
285 | }
286 |
287 | func (this Foo) f() {
288 | fmt.Println(this.a)
289 | }
290 | func (this *Foo) g() {
291 | fmt.Println(this.a)
292 | }
293 | func main() {
294 | foo := Foo{}
295 | foo.f()
296 | }
297 | `,
298 | // const.og
299 | `package main
300 |
301 | const (
302 | foo = "bar"
303 | )
304 | const (
305 | foo string = "bar"
306 | )
307 | `,
308 | // var.og
309 | `package main
310 |
311 | var (
312 | foo string
313 | )
314 | var (
315 | foo = "bar"
316 | )
317 | var (
318 | foo string = "bar"
319 | )
320 | `,
321 | // map.og
322 | `package main
323 |
324 | func someFunc(m map[string]string) map[string]string {
325 | return m
326 | }
327 | func main() {
328 | m := map[string]string{}
329 | }
330 | `,
331 | // chan.og
332 | `package main
333 |
334 | func someFunc(c1 chan<- int, c2 <-chan int) chan int {
335 | return 0
336 | }
337 | func main() {
338 | c := make(chan string)
339 | c := make(chan<- string)
340 | c := make(<-chan string)
341 | }
342 | `,
343 | // loop_flow.og
344 | `package main
345 |
346 | func main() {
347 | here:
348 | toto()
349 | for i := range foo {
350 | continue
351 | continue label
352 | break
353 | break label
354 | fallthrough
355 | goto here
356 | }
357 | }
358 | `,
359 | // anonymous.og
360 | `package main
361 |
362 | type Foo struct {
363 | *SomeClass
364 | }
365 | type Foo struct {
366 | SomeClass
367 | }
368 | type Foo struct {
369 | SomeClass
370 | *SomeClass2
371 | }
372 | `,
373 | // select.og
374 | `package main
375 |
376 | func main() {
377 | c1 := make(chan int)
378 | c2 := make(chan int)
379 | select {
380 | case <-c1:
381 | fmt.Println("Yeah")
382 | case x := <-c2:
383 | fmt.Println("Yeah", x)
384 | case x := <-c2:
385 | fmt.Println("Yeah", x)
386 | fmt.Println("Yeah2", x)
387 | case c2 <- 1:
388 | fmt.Println("Yeah", x)
389 | default:
390 | fmt.Println("Default")
391 | }
392 | }
393 | `,
394 | // func_literal.og
395 | `package main
396 |
397 | func main() {
398 | a := func() {
399 | fmt.Println(1)
400 | }
401 | a := func() int {
402 | return 1
403 | }
404 | b := func(a int) {
405 | fmt.Println(a)
406 | }
407 | c := func(a int) int {
408 | return a
409 | }
410 | }
411 | `,
412 | // func_type.og
413 | `package main
414 |
415 | func a(arg func() int) {
416 | arg()
417 | }
418 | func main() {
419 | a(func() int {
420 | return 2
421 | })
422 | }
423 | `,
424 | // rest.og
425 | `package main
426 |
427 | func someFunc(a int, b ...int) {
428 | fmt.Println(a, b)
429 | }
430 | func main() {
431 | a := []int{
432 | 1,
433 | 2,
434 | 3,
435 | }
436 | someFunc(a...)
437 | }
438 | `,
439 | // bitwise.og
440 | `package main
441 |
442 | func main() {
443 | x := 0xAC
444 | x = x & 0xF0
445 | x = x | 0xF0
446 | x = x ^ 0xF0
447 | x = x &^ 0xF0
448 | x = x >> 0xF0
449 | x = x << 0xF0
450 | }
451 | `,
452 | // assignable_stmt.og
453 | `package og
454 |
455 | func voila() int {
456 | var (
457 | a int = func() int {
458 | if true {
459 | return 1
460 | } else {
461 | return 2
462 | }
463 | }()
464 | )
465 | var (
466 | b int = func() int {
467 | if true {
468 | return 1
469 | } else {
470 | return 2
471 | }
472 | }()
473 | )
474 | if true {
475 | return 1
476 | } else {
477 | return 2
478 | }
479 | }
480 | `,
481 | // generics.og
482 | `package og
483 |
484 | import (
485 | "github.com/champii/og/tests/exemples/bar"
486 | )
487 |
488 | func main() {
489 | fmt.Println(exemples_a_int(1))
490 | fmt.Println(exemples_a_string("a"))
491 | a := exemples_Foo_int{bar: 1}
492 | }
493 | func exemples_a_int(t int) int {
494 | return t
495 | }
496 | func exemples_a_string(t string) string {
497 | return t
498 | }
499 |
500 | type exemples_Foo_int struct {
501 | bar int
502 | }
503 | `,
504 | }
505 |
506 | paths := []string{
507 | `package`,
508 | `package_short`,
509 | `import`,
510 | `import_parenthesis`,
511 | `struct`,
512 | `top_fn`,
513 | `if`,
514 | `for`,
515 | `nested_property`,
516 | `goroutine`,
517 | `operation`,
518 | `ref`,
519 | `inc`,
520 | `struct_inst`,
521 | `slices`,
522 | `interface`,
523 | `switch`,
524 | `this`,
525 | `internal_method`,
526 | `const`,
527 | `var`,
528 | `map`,
529 | `chan`,
530 | `loop_flow`,
531 | `anonymous`,
532 | `select`,
533 | `func_literal`,
534 | `func_type`,
535 | `rest`,
536 | `bitwise`,
537 | `assignable_stmt`,
538 | `generics`,
539 | }
540 |
541 | config := common.NewOgConfig()
542 |
543 | config.Force = true
544 |
545 | for _, p := range paths {
546 | config.Paths = append(config.Paths, "./exemples/"+p+".og")
547 | }
548 |
549 | common.Print = common.NewPrinter(config)
550 | compiler := og.NewOgCompiler(config)
551 |
552 | if err := compiler.Compile(); err != nil {
553 | t.Fatalf(err.Error())
554 | }
555 |
556 | for i, file := range compiler.Files {
557 | if file.Output != expected[i] {
558 | t.Fatalf(fmt.Sprint("Error: ", file.Path, "\nGot: \n---\n", file.Output, "\n---\nExpected: \n---\n", expected[i], "\n---\n"))
559 | }
560 | }
561 | }
562 |
--------------------------------------------------------------------------------