├── .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 | ![Overview](https://github.com/Champii/og/raw/master/docs/_media/overview_color.png) 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 | 62 | 63 | 64 |
"Golang On Steroids" - Socrates
"The Code like it should be. 5/7"- Mahatma Gandhi
"(..Recursive Facepalm..)" - Google
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 | # Oglang v0.7.2 2 | 3 | ## Optimistic Golang 4 | 5 | [GitHub](https://github.com/Champii/og/) 6 | [Get Started](#introduction) 7 | 8 | 9 | ![color](#222222) 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 | ![make](https://github.com/Champii/og/raw/master/docs/_media/og_preview.gif) 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 | ![Hello](https://github.com/Champii/og/raw/master/docs/_media/hello_preview.gif) 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 | --------------------------------------------------------------------------------