From 277c83425011dca210292181e8d52868d9f55884 Mon Sep 17 00:00:00 2001 From: Vilsol Date: Tue, 22 Dec 2020 00:02:54 +0200 Subject: [PATCH] Initial commit --- .github/workflows/build.yml | 70 +++++++ .github/workflows/release.yml | 29 +++ .gitignore | 116 ++++++++++++ .goreleaser.yml | 43 +++++ README.md | 60 ++++++ RECURSION.md | 10 + cmd/root.go | 69 +++++++ cmd/transpile.go | 39 ++++ go.mod | 10 + go.sum | 317 +++++++++++++++++++++++++++++++ m/main.go | 104 ++++++++++ main.go | 7 + transpiler/expression.go | 309 ++++++++++++++++++++++++++++++ transpiler/main.go | 302 +++++++++++++++++++++++++++++ transpiler/operators.go | 61 ++++++ transpiler/options.go | 7 + transpiler/statement.go | 284 ++++++++++++++++++++++++++++ transpiler/translations.go | 256 +++++++++++++++++++++++++ transpiler/types.go | 346 ++++++++++++++++++++++++++++++++++ wasm/main.go | 42 +++++ 20 files changed, 2481 insertions(+) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/release.yml create mode 100644 .gitignore create mode 100644 .goreleaser.yml create mode 100644 README.md create mode 100644 RECURSION.md create mode 100644 cmd/root.go create mode 100644 cmd/transpile.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 m/main.go create mode 100644 main.go create mode 100644 transpiler/expression.go create mode 100644 transpiler/main.go create mode 100644 transpiler/operators.go create mode 100644 transpiler/options.go create mode 100644 transpiler/statement.go create mode 100644 transpiler/translations.go create mode 100644 transpiler/types.go create mode 100644 wasm/main.go diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..e07099b --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,70 @@ +name: build + +on: [push, pull_request] + +jobs: + build: + name: Build for ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + file: go-mlog-linux-amd64 + args: --best --lzma + strip: true + cgo: 0 + - os: windows-latest + file: go-mlog-win-amd64.exe + args: -9 + strip: false + cgo: 1 + - os: macos-latest + file: go-mlog-osx-amd64 + args: --best + strip: false + cgo: 1 + steps: + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.15 + + - name: Check out code into the Go module directory + uses: actions/checkout@v2 + + - name: Build + run: go build -ldflags="-s -w" -v -o ${{ matrix.file }} . + env: + CGO_ENABLED: ${{ matrix.cgo }} + + analyze: + name: Analyze + runs-on: ubuntu-latest + steps: + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.15 + + - name: Checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: 2 + + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: go + + - name: Build + run: go build -ldflags="-s -w" -v -o go-mlog . + env: + CGO_ENABLED: 0 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e8fed33 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,29 @@ +name: release + +on: + push: + tags: + - v* + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.15 + + - name: Check out code into the Go module directory + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v2 + with: + version: latest + args: release --rm-dist + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a7fa8f --- /dev/null +++ b/.gitignore @@ -0,0 +1,116 @@ +# Created by https://www.gitignore.io/api/go,jetbrains+all +# Edit at https://www.gitignore.io/?templates=go,jetbrains+all + +### Go ### +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +### Go Patch ### +/vendor/ +/Godeps/ + +### JetBrains+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### JetBrains+all Patch ### +# Ignores the whole .idea folder and all .iml files +# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 + +.idea/ + +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +# Sonarlint plugin +.idea/sonarlint + +# End of https://www.gitignore.io/api/go,jetbrains+all + +*.wasm +samples/ +*.mlog +*.masm \ No newline at end of file diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..707671f --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,43 @@ +before: + hooks: + - go mod download + +builds: + - env: + - CGO_ENABLED=0 + goos: + - linux + - windows + - darwin + goarch: + - amd64 + - 386 + - arm + - arm64 + - ppc64le + - s390x + goarm: + - 6 + - 7 + +archives: + - replacements: + darwin: Darwin + linux: Linux + windows: Windows + 386: i386 + amd64: x86_64 + allow_different_binary_count: true + +checksum: + name_template: 'checksums.txt' + +snapshot: + name_template: "{{ .Tag }}-next" + +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' diff --git a/README.md b/README.md new file mode 100644 index 0000000..1e9b51f --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +# go-mlog + +Go to MLOG transpiler. + +## Web IDE + +``` +// TODO +``` + +## Supports + +* Functions +* Multiple function parameters/arguments +* `return` from functions +* `for` loops +* `if`/`else if`/`else` statements +* Binary and Unary math +* Function level variable scopes + +## Roadmap + +* Documentation +* `break` out of loops +* `switch` statement +* Full variable block scoping +* `print`/`println` multiple arguments +* Errors with context +* Extensions +* Variable argument count functions +* Multiple function return values + +## Design Limitations + +* Only hardcoded (translated) imports allowed +* Single file support only +* No recursion ([more info here](RECURSION.md)) + +## Endgame Roadmap + +* Transpilation optimizations +* MLOG Runtime + +## Usage + +``` +Usage: + go-mlog transpile [flags] + +Flags: + -h, --help help for transpile + +Global Flags: + --colors Force log output with colors + --comments Output comments + --debug Write to debug memory cell + --log string The log level to output (default "info") + --numbers Output line numbers + --output string Output file. Outputs to stdout if unspecified +``` \ No newline at end of file diff --git a/RECURSION.md b/RECURSION.md new file mode 100644 index 0000000..b432e6a --- /dev/null +++ b/RECURSION.md @@ -0,0 +1,10 @@ +# Issues with recursion + +We cannot use variables to store data, as they would be overwritten on the next depth pass of the function. +That forces us to use memory cells/banks. + +Currently, the game does not support writing objects to memory cells/banks. +That means we would be unable to support any functions that return any object types. + +It is planned in the future to implement recursion support, but if any function would call any function +that returns an object, it would instantly panic out of the transpiler. \ No newline at end of file diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..a63f7c1 --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,69 @@ +package cmd + +import ( + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "os" +) + +var rootCmd = &cobra.Command{ + Use: "go-mlog", + Short: "golang to mlog transpiler", + PersistentPreRun: func(cmd *cobra.Command, args []string) { + viper.SetConfigName("config") + viper.AddConfigPath(".") + viper.SetEnvPrefix("gomlog") + viper.AutomaticEnv() + + _ = viper.ReadInConfig() + + level, err := log.ParseLevel(viper.GetString("log")) + + if err != nil { + panic(err) + } + + log.SetFormatter(&log.TextFormatter{ + ForceColors: viper.GetBool("colors"), + }) + log.SetOutput(os.Stdout) + log.SetLevel(level) + }, +} + +func Execute() { + // Allow running from explorer + cobra.MousetrapHelpText = "" + + // Execute transpile command as default + cmd, _, err := rootCmd.Find(os.Args[1:]) + if (len(os.Args) <= 1 || os.Args[1] != "help") && (err != nil || cmd == rootCmd) { + args := append([]string{"transpile"}, os.Args[1:]...) + rootCmd.SetArgs(args) + } + + if err := rootCmd.Execute(); err != nil { + panic(err) + } +} + +func init() { + rootCmd.PersistentFlags().String("log", "info", "The log level to output") + rootCmd.PersistentFlags().Bool("colors", false, "Force log output with colors") + + rootCmd.PersistentFlags().Bool("numbers", false, "Output line numbers") + rootCmd.PersistentFlags().Bool("comments", false, "Output comments") + rootCmd.PersistentFlags().Bool("debug", false, "Write to debug memory cell") + + rootCmd.PersistentFlags().String("output", "", "Output file. Outputs to stdout if unspecified") + + _ = viper.BindPFlag("log", rootCmd.PersistentFlags().Lookup("log")) + _ = viper.BindPFlag("colors", rootCmd.PersistentFlags().Lookup("colors")) + + _ = viper.BindPFlag("numbers", rootCmd.PersistentFlags().Lookup("numbers")) + _ = viper.BindPFlag("comments", rootCmd.PersistentFlags().Lookup("comments")) + _ = viper.BindPFlag("debug", rootCmd.PersistentFlags().Lookup("debug")) + + _ = viper.BindPFlag("output", rootCmd.PersistentFlags().Lookup("output")) +} diff --git a/cmd/transpile.go b/cmd/transpile.go new file mode 100644 index 0000000..c2f5ee3 --- /dev/null +++ b/cmd/transpile.go @@ -0,0 +1,39 @@ +package cmd + +import ( + "fmt" + "github.com/Vilsol/go-mlog/transpiler" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "io/ioutil" +) + +func init() { + rootCmd.AddCommand(transpileCmd) +} + +var transpileCmd = &cobra.Command{ + Use: "transpile [flags] ", + Short: "Transpile Go to MLOG", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + result, err := transpiler.GolangToMLOGFile(args[0], transpiler.Options{ + Numbers: viper.GetBool("numbers"), + Comments: viper.GetBool("comments"), + Debug: viper.GetBool("debug"), + }) + if err != nil { + return err + } + + if output := viper.GetString("output"); output != "" { + if err := ioutil.WriteFile(output, []byte(result), 0644); err != nil { + return err + } + } else { + fmt.Println(result) + } + + return nil + }, +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..e4db49e --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module github.com/Vilsol/go-mlog + +go 1.15 + +require ( + github.com/davecgh/go-spew v1.1.1 + github.com/sirupsen/logrus v1.7.0 + github.com/spf13/cobra v1.1.1 + github.com/spf13/viper v1.7.1 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..9a6fc0f --- /dev/null +++ b/go.sum @@ -0,0 +1,317 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= +github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= +github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuroyoro/goast-viewer v0.0.0-20190531024818-3d08b047cb96 h1:/qcoOmSHcI30qPfJG3NhGiQQJ1DUL7QVcyIZud8UPmc= +github.com/yuroyoro/goast-viewer v0.0.0-20190531024818-3d08b047cb96/go.mod h1:FS/Z0ffn6HJgdtQyycVgnC/+fP/biHsTohAZXNlNxeM= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/m/main.go b/m/main.go new file mode 100644 index 0000000..21fd755 --- /dev/null +++ b/m/main.go @@ -0,0 +1,104 @@ +package m + +func Read(memory string, position int) int { + return 0 +} + +func Write(value int, memory string, position int) { +} + +func DrawClear(r int, g int, b int) { +} + +func DrawColor(r int, g int, b int, a int) { +} + +func DrawStroke(width int) { +} + +func DrawLine(x1 int, y1 int, x2 int, y2 int) { +} + +func DrawRect(x int, y int, width int, height int) { +} + +func DrawLineRect(x int, y int, width int, height int) { +} + +func DrawPoly(x int, y int, sides int, radius float32, rotation float32) { +} + +func DrawLinePoly(x int, y int, sides int, radius float32, rotation float32) { +} + +func DrawTriangle(x1 int, y1 int, x2 int, y2 int, x3 int, y3 int) { +} + +func DrawImage(x int, y int, image string, size float32, rotation float32) { +} + +func PrintFlush(targetMessage string) { +} + +func DrawFlush(targetDisplay string) { +} + +func GetLink(output string, address string) { +} + +func ControlEnabled(target string, enabled int) { +} + +func ControlShoot(target string, x int, y int, shoot int) { +} + +func ControlShootP(target string, unit int, shoot int) { +} + +func ControlConfigure(target string, configuration int) { +} + +type RadarTarget = int + +const ( + RTAny = RadarTarget(iota) + RTEnemy + RTAlly + RTPlayer + RTAttacker + RTFlying + RTBoss + RTGround +) + +type RadarSort = int + +const ( + RSDistance = RadarSort(iota) + RSHealth + RSShield + RSArmor + RSMaxHealth +) + +func Radar(from string, target1 RadarTarget, target2 RadarTarget, target3 RadarTarget, sortOrder int, sort RadarSort, output string) { +} + +func Sensor(variable string, sensor string, from string) { +} + +// TODO Operations + +func End() { +} + +func Floor(number float64) int { + return 0 +} + +func Random(max float64) float64 { + return 0 +} + +func Sleep(millis int) { +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..101f246 --- /dev/null +++ b/main.go @@ -0,0 +1,7 @@ +package main + +import "github.com/Vilsol/go-mlog/cmd" + +func main() { + cmd.Execute() +} diff --git a/transpiler/expression.go b/transpiler/expression.go new file mode 100644 index 0000000..2d88fea --- /dev/null +++ b/transpiler/expression.go @@ -0,0 +1,309 @@ +package transpiler + +import ( + "errors" + "fmt" + "github.com/davecgh/go-spew/spew" + "go/ast" + "go/token" +) + +func expressionToMLOG(ident Resolvable, expr ast.Expr, options Options) ([]MLOGStatement, error) { + switch expr.(type) { + case *ast.BasicLit: + basicExpr := expr.(*ast.BasicLit) + if basicExpr.Kind != token.INT && basicExpr.Kind != token.FLOAT { + return nil, errors.New("only integers and floating point numbers can be assigned to variables") + } + return []MLOGStatement{&MLOG{ + Comment: "Set the variable to the value", + Statement: [][]Resolvable{ + { + &Value{Value: "set"}, + ident, + &Value{Value: basicExpr.Value}, + }, + }, + }}, nil + case *ast.Ident: + identExpr := expr.(*ast.Ident) + return []MLOGStatement{&MLOG{ + Comment: "Set the variable to the value of other variable", + Statement: [][]Resolvable{ + { + &Value{Value: "set"}, + ident, + &NormalVariable{Name: identExpr.Name}, + }, + }, + }}, nil + case *ast.BinaryExpr: + binaryExpr := expr.(*ast.BinaryExpr) + + if opTranslated, ok := regularOperators[binaryExpr.Op]; ok { + instructions := make([]MLOGStatement, 0) + var leftSide Resolvable + var rightSide Resolvable + + if basicLit, ok := binaryExpr.X.(*ast.BasicLit); ok { + leftSide = &Value{Value: basicLit.Value} + } else if leftIdent, ok := binaryExpr.X.(*ast.Ident); ok { + leftSide = &NormalVariable{Name: leftIdent.Name} + } else if leftExpr, ok := binaryExpr.X.(ast.Expr); ok { + dVar := &DynamicVariable{} + + exprInstructions, err := expressionToMLOG(dVar, leftExpr, options) + if err != nil { + return nil, err + } + + instructions = append(instructions, exprInstructions...) + leftSide = dVar + } else { + return nil, errors.New(fmt.Sprintf("unknown left side expression type: %T", binaryExpr.X)) + } + + if basicLit, ok := binaryExpr.Y.(*ast.BasicLit); ok { + rightSide = &Value{Value: basicLit.Value} + } else if rightIdent, ok := binaryExpr.Y.(*ast.Ident); ok { + rightSide = &NormalVariable{Name: rightIdent.Name} + } else if rightExpr, ok := binaryExpr.Y.(ast.Expr); ok { + dVar := &DynamicVariable{} + + exprInstructions, err := expressionToMLOG(dVar, rightExpr, options) + if err != nil { + return nil, err + } + + instructions = append(instructions, exprInstructions...) + rightSide = dVar + } else { + return nil, errors.New(fmt.Sprintf("unknown right side expression type: %T", binaryExpr.Y)) + } + + return append(instructions, &MLOG{ + Comment: "Execute operation", + Statement: [][]Resolvable{ + { + &Value{Value: "op"}, + &Value{Value: opTranslated}, + ident, + leftSide, + rightSide, + }, + }, + }), nil + } else { + return nil, errors.New(fmt.Sprintf("operator statement cannot use this operation: %s", binaryExpr.Op.String())) + } + case *ast.CallExpr: + callInstructions, err := callExprToMLOG(expr.(*ast.CallExpr), options) + if err != nil { + return nil, err + } + + callInstructions = append(callInstructions, &MLOG{ + Comment: "Set the variable to the value", + Statement: [][]Resolvable{ + { + &Value{Value: "set"}, + ident, + &Value{Value: functionReturnVariable}, + }, + }, + }) + + return callInstructions, err + case *ast.UnaryExpr: + unaryExpr := expr.(*ast.UnaryExpr) + + if _, ok := regularOperators[unaryExpr.Op]; ok { + instructions := make([]MLOGStatement, 0) + + var x Resolvable + if basicLit, ok := unaryExpr.X.(*ast.BasicLit); ok { + x = &Value{Value: basicLit.Value} + } else if leftIdent, ok := unaryExpr.X.(*ast.Ident); ok { + x = &NormalVariable{Name: leftIdent.Name} + } else if leftExpr, ok := unaryExpr.X.(ast.Expr); ok { + dVar := &DynamicVariable{} + + exprInstructions, err := expressionToMLOG(dVar, leftExpr, options) + if err != nil { + return nil, err + } + + instructions = append(instructions, exprInstructions...) + x = dVar + } else { + return nil, errors.New(fmt.Sprintf("unknown unary expression type: %T", unaryExpr.X)) + } + + var statement []Resolvable + switch unaryExpr.Op { + case token.NOT: + statement = []Resolvable{ + &Value{Value: "op"}, + &Value{Value: regularOperators[token.NOT]}, + ident, + x, + &Value{Value: "-1"}, + } + break + case token.SUB: + statement = []Resolvable{ + &Value{Value: "op"}, + &Value{Value: regularOperators[token.MUL]}, + ident, + x, + &Value{Value: "-1"}, + } + break + } + + if statement == nil { + return nil, errors.New(fmt.Sprintf("unsupported unary operation: %s", unaryExpr.Op.String())) + } + + return append(instructions, &MLOG{ + Comment: "Execute unary operation", + Statement: [][]Resolvable{statement}, + }), nil + } else { + return nil, errors.New(fmt.Sprintf("operator statement cannot use this operation: %s", unaryExpr.Op.String())) + } + case *ast.ParenExpr: + parenExpr := expr.(*ast.ParenExpr) + instructions, err := expressionToMLOG(ident, parenExpr.X, options) + if err != nil { + return nil, err + } + return instructions, nil + default: + spew.Dump(expr) + return nil, errors.New(fmt.Sprintf("unsupported expression type: %T", expr)) + } +} + +func callExprToMLOG(callExpr *ast.CallExpr, options Options) ([]MLOGStatement, error) { + results := make([]MLOGStatement, 0) + + var funcName string + if identity, ok := callExpr.Fun.(*ast.Ident); ok { + funcName = identity.Name + } else if selector, ok := callExpr.Fun.(*ast.SelectorExpr); ok { + funcName = selector.Sel.Name + } else { + return nil, errors.New(fmt.Sprintf("unknown call expression: %T", callExpr.Fun)) + } + + if translatedFunc, ok := funcTranslations[funcName]; ok { + args, instructions, err := argumentsToResolvables(callExpr.Args, options) + if err != nil { + return nil, err + } + results = append(results, instructions...) + results = append(results, &MLOGFunc{ + Function: translatedFunc, + Arguments: args, + }) + } else { + for _, arg := range callExpr.Args { + results = append(results, &MLOGStackWriter{ + Action: "add", + }) + + var value Resolvable + if basicLit, ok := arg.(*ast.BasicLit); ok { + value = &Value{Value: basicLit.Value} + } else if ident, ok := arg.(*ast.Ident); ok { + value = &NormalVariable{Name: ident.Name} + } else if binaryExpr, ok := arg.(*ast.BinaryExpr); ok { + dVar := &DynamicVariable{} + + instructions, err := expressionToMLOG(dVar, binaryExpr, options) + if err != nil { + return nil, err + } + + results = append(results, instructions...) + value = dVar + } else { + return nil, errors.New(fmt.Sprintf("unknown argument type: %T", arg)) + } + + results = append(results, &MLOG{ + Comment: "Write argument to memory", + Statement: [][]Resolvable{ + { + &Value{Value: "write"}, + value, + &Value{Value: stackCellName}, + &Value{Value: stackVariable}, + }, + }, + }) + } + + results = append(results, &MLOGStackWriter{ + Action: "add", + }) + + extra := 2 + if options.Debug { + extra += debugCount + } + + results = append(results, &MLOGTrampoline{ + Variable: stackVariable, + Extra: extra, + }) + + results = append(results, &MLOGJump{ + MLOG: MLOG{ + Comment: "Jump to function: " + funcName, + }, + Condition: []Resolvable{ + &Value{Value: "always"}, + }, + JumpTarget: &FunctionJumpTarget{ + FunctionName: funcName, + }, + }) + + results = append(results, &MLOGStackWriter{ + Action: "sub", + Extra: len(callExpr.Args), + }) + } + + return results, nil +} + +func argumentsToResolvables(args []ast.Expr, options Options) ([]Resolvable, []MLOGStatement, error) { + result := make([]Resolvable, len(args)) + instructions := make([]MLOGStatement, 0) + + for i, arg := range args { + if basicExpr, ok := arg.(*ast.BasicLit); ok { + result[i] = &Value{Value: basicExpr.Value} + } else if identExpr, ok := arg.(*ast.Ident); ok { + result[i] = &NormalVariable{Name: identExpr.Name} + } else if expr, ok := arg.(ast.Expr); ok { + dVar := &DynamicVariable{} + + exprInstructions, err := expressionToMLOG(dVar, expr, options) + if err != nil { + return nil, nil, err + } + + instructions = append(instructions, exprInstructions...) + + result[i] = dVar + } else { + return nil, nil, errors.New(fmt.Sprintf("only arguments of basic types or variables are supported, received: %T", arg)) + } + } + + return result, instructions, nil +} diff --git a/transpiler/main.go b/transpiler/main.go new file mode 100644 index 0000000..3753efe --- /dev/null +++ b/transpiler/main.go @@ -0,0 +1,302 @@ +package transpiler + +import ( + "errors" + "fmt" + "go/ast" + "go/parser" + "go/token" + "io/ioutil" + "strconv" +) + +const stackVariable = `@stack` +const functionReturnVariable = `@return` + +const stackCellName = `bank1` +const debugCellName = `cell2` +const debugCount = 2 + +// TODO Change to List, Support Math +const validImport = `"github.com/Vilsol/go-mlog/m"` + +func GolangToMLOGFile(fileName string, options Options) (string, error) { + file, err := ioutil.ReadFile(fileName) + + if err != nil { + return "", err + } + + return GolangToMLOGBytes(file, options) +} + +func GolangToMLOGBytes(input []byte, options Options) (string, error) { + return GolangToMLOG(string(input), options) +} + +func GolangToMLOG(input string, options Options) (string, error) { + fileSet := token.NewFileSet() + f, err := parser.ParseFile(fileSet, "foo", input, 0) + + if err != nil { + return "", err + } + + if f.Name.Name != "main" { + return "", errors.New("package must be main") + } + + for _, imp := range f.Imports { + if imp.Path.Value != validImport { + return "", errors.New("you may not use any external imports") + } + } + + constants := make([]*ast.GenDecl, 0) + var mainFunc *ast.FuncDecl + for _, decl := range f.Decls { + switch decl.(type) { + case *ast.FuncDecl: + funcDecl := decl.(*ast.FuncDecl) + if funcDecl.Name.Name == "main" { + mainFunc = funcDecl + } + break + case *ast.GenDecl: + genDecl := decl.(*ast.GenDecl) + if genDecl.Tok.String() == "var" { + return "", errors.New("global scope may only contain constants not variables") + } else if genDecl.Tok.String() == "const" { + constants = append(constants, genDecl) + } + break + case *ast.BadDecl: + return "", errors.New("syntax error in input file") + } + } + + if mainFunc == nil { + return "", errors.New("file does not contain a main function") + } + + global := &Global{ + Functions: make([]*Function, 0), + } + + for _, decl := range f.Decls { + switch decl.(type) { + case *ast.FuncDecl: + funcDecl := decl.(*ast.FuncDecl) + if funcDecl.Name.Name == "main" { + continue + } + statements, err := statementToMLOG(funcDecl.Body, options) + if err != nil { + return "", err + } + + for i, param := range funcDecl.Type.Params.List { + position := len(funcDecl.Type.Params.List) - i + + dVar := &DynamicVariable{} + + // TODO Support multiple names + statements = append([]MLOGStatement{ + &MLOG{ + Comment: "Calculate address of parameter", + Statement: [][]Resolvable{ + { + &Value{Value: "op"}, + &Value{Value: "sub"}, + dVar, + &Value{Value: stackVariable}, + &Value{Value: strconv.Itoa(position)}, + }, + }, + }, + &MLOG{ + Comment: "Read parameter into variable", + Statement: [][]Resolvable{ + { + &Value{Value: "read"}, + &NormalVariable{Name: param.Names[0].Name}, + &Value{Value: stackCellName}, + dVar, + }, + }, + }, + }, statements...) + } + + lastStatement := statements[len(statements)-1] + if _, ok := lastStatement.(*MLOGTrampolineBack); !ok { + statements = append(statements, &MLOGTrampolineBack{}) + } + + global.Functions = append(global.Functions, &Function{ + Name: funcDecl.Name.Name, + Statements: statements, + ArgumentCount: len(funcDecl.Type.Params.List), + }) + break + } + } + + mainStatements, err := statementToMLOG(mainFunc.Body, options) + if err != nil { + return "", err + } + global.Functions = append(global.Functions, &Function{ + Name: mainFunc.Name.Name, + Statements: mainStatements, + ArgumentCount: len(mainFunc.Type.Params.List), + }) + + startup := []MLOGStatement{ + &MLOG{ + Comment: "Reset Stack", + Statement: [][]Resolvable{ + { + &Value{Value: "set"}, + &Value{Value: stackVariable}, + &Value{Value: "0"}, + }, + }, + }, + } + + global.Constants = make(map[string]bool) + constantPos := 0 + for _, constant := range constants { + for _, spec := range constant.Specs { + // Constants can only be ValueSpec + valueSpec := spec.(*ast.ValueSpec) + for i, name := range valueSpec.Names { + var value string + if basicLit, ok := valueSpec.Values[i].(*ast.BasicLit); ok { + value = basicLit.Value + } else if ident, ok := valueSpec.Values[i].(*ast.Ident); ok { + value = ident.Name + } else { + return "", errors.New(fmt.Sprintf("unknown constant type: %T", valueSpec.Values[i])) + } + + startup = append(startup, &MLOG{ + Position: constantPos, + Statement: [][]Resolvable{ + { + &Value{Value: "set"}, + &Value{Value: name.Name}, + &Value{Value: value}, + }, + }, + Comment: "Set global variable", + }) + constantPos += 1 + + global.Constants[name.Name] = true + } + } + } + + startup = append(startup, &MLOGJump{ + MLOG: MLOG{ + Comment: "Jump to start of main", + Position: len(startup), + }, + Condition: []Resolvable{ + &Value{Value: "always"}, + }, + JumpTarget: &FunctionJumpTarget{ + FunctionName: "main", + }, + }) + + debugWriter := []MLOGAble{ + &MLOG{ + Comment: "Debug", + Statement: [][]Resolvable{ + { + &Value{Value: "write"}, + &Value{Value: "@counter"}, + &Value{Value: debugCellName}, + &Value{Value: "0"}, + }, + }, + }, + &MLOG{ + Comment: "Debug", + Statement: [][]Resolvable{ + { + &Value{Value: "write"}, + &Value{Value: stackVariable}, + &Value{Value: debugCellName}, + &Value{Value: "1"}, + }, + }, + }, + } + + if len(debugWriter) != debugCount { + panic("debugWriter count != debugCount") + } + + position := len(startup) + for _, fn := range global.Functions { + for _, statement := range fn.Statements { + if options.Debug { + position += debugCount + } + + position += statement.SetPosition(position) + } + } + + for _, statement := range startup { + if err := statement.PostProcess(global, nil); err != nil { + return "", err + } + } + + for _, fn := range global.Functions { + for _, statement := range fn.Statements { + if err := statement.PostProcess(global, fn); err != nil { + return "", err + } + } + } + + result := "" + lineNumber := 0 + for _, statement := range startup { + statements := statement.ToMLOG() + result += MLOGToString(statements, statement, lineNumber, options) + lineNumber += len(statements) + } + + for _, fn := range global.Functions { + if options.Comments { + if result != "" { + result += "\n" + } + + result += " // Function: " + fn.Name + " //\n" + } + + for _, statement := range fn.Statements { + if options.Debug { + for _, debugStatement := range debugWriter { + deb := debugStatement.ToMLOG() + result += MLOGToString(deb, debugStatement, lineNumber, options) + lineNumber += len(deb) + } + } + + statements := statement.ToMLOG() + result += MLOGToString(statements, statement, lineNumber, options) + lineNumber += len(statements) + } + } + + return result, nil +} diff --git a/transpiler/operators.go b/transpiler/operators.go new file mode 100644 index 0000000..feef017 --- /dev/null +++ b/transpiler/operators.go @@ -0,0 +1,61 @@ +package transpiler + +import "go/token" + +var jumpOperators = map[token.Token]string{ + token.EQL: "equal", + token.NEQ: "notEqual", + token.LSS: "lessThan", + token.LEQ: "lessThanEq", + token.GTR: "greaterThan", + token.GEQ: "greaterThanEq", +} + +var regularOperators = map[token.Token]string{ + token.ADD: "add", + token.ADD_ASSIGN: "add", + token.SUB: "sub", + token.SUB_ASSIGN: "sub", + token.MUL: "mul", + token.MUL_ASSIGN: "mul", + token.QUO: "div", + token.QUO_ASSIGN: "div", + // TODO // + token.REM: "mod", + token.REM_ASSIGN: "mod", + // TODO SQRT + token.EQL: "equal", + token.NEQ: "notEqual", + token.LSS: "lessThan", + token.LEQ: "lessThanEq", + token.GTR: "greaterThan", + token.GEQ: "greaterThanEq", + token.LAND: "land", + token.SHL: "shl", + token.SHL_ASSIGN: "shl", + token.SHR: "shr", + token.SHR_ASSIGN: "shr", + token.LOR: "or", + token.OR: "or", + token.OR_ASSIGN: "or", + token.AND: "and", + token.AND_ASSIGN: "and", + token.XOR: "xor", + token.XOR_ASSIGN: "xor", + token.NOT: "not", + // TODO max + // TODO min + // TODO atan2 + // TODO dst + // TODO noise + // TODO abs + // TODO log + // TODO log10 + // TODO sin + // TODO cos + // TODO tan + // TODO floor + // TODO ceil + // TODO sqrt + // TODO rand +} diff --git a/transpiler/options.go b/transpiler/options.go new file mode 100644 index 0000000..dd24d24 --- /dev/null +++ b/transpiler/options.go @@ -0,0 +1,7 @@ +package transpiler + +type Options struct { + Numbers bool + Comments bool + Debug bool +} diff --git a/transpiler/statement.go b/transpiler/statement.go new file mode 100644 index 0000000..566610a --- /dev/null +++ b/transpiler/statement.go @@ -0,0 +1,284 @@ +package transpiler + +import ( + "errors" + "fmt" + "go/ast" + "go/token" +) + +func statementToMLOG(statement ast.Stmt, options Options) ([]MLOGStatement, error) { + results := make([]MLOGStatement, 0) + + switch statement.(type) { + case *ast.ForStmt: + forStatement := statement.(*ast.ForStmt) + + // TODO Switch from do while to while do + + if len(forStatement.Body.List) == 0 { + break + } + + // TODO Support all statements + if assignStatement, ok := forStatement.Init.(*ast.AssignStmt); ok { + assignMlog, err := assignStmtToMLOG(assignStatement, options) + if err != nil { + return nil, err + } + results = append(results, assignMlog...) + } else { + return nil, errors.New("for loop can only have variable assignment initiators") + } + + var loopStartJump *MLOGJump + if binaryExpr, ok := forStatement.Cond.(*ast.BinaryExpr); ok { + if translatedOp, ok := jumpOperators[binaryExpr.Op]; ok { + var leftSide Resolvable + var rightSide Resolvable + + if basicLit, ok := binaryExpr.X.(*ast.BasicLit); ok { + leftSide = &Value{Value: basicLit.Value} + } else if ident, ok := binaryExpr.X.(*ast.Ident); ok { + leftSide = &NormalVariable{Name: ident.Name} + } else { + return nil, errors.New(fmt.Sprintf("unknown left side expression type: %T", binaryExpr.X)) + } + + if basicLit, ok := binaryExpr.Y.(*ast.BasicLit); ok { + rightSide = &Value{Value: basicLit.Value} + } else if ident, ok := binaryExpr.Y.(*ast.Ident); ok { + rightSide = &NormalVariable{Name: ident.Name} + } else { + return nil, errors.New(fmt.Sprintf("unknown right side expression type: %T", binaryExpr.Y)) + } + + loopStartJump = &MLOGJump{ + MLOG: MLOG{ + Comment: "Jump to start of loop", + }, + Condition: []Resolvable{ + &Value{Value: translatedOp}, + leftSide, + rightSide, + }, + } + results = append(results) + } else { + return nil, errors.New(fmt.Sprintf("jump statement cannot use this operation: %T", binaryExpr.Op)) + } + } else { + return nil, errors.New("for loop can only have binary conditional expressions") + } + + bodyMLOG, err := statementToMLOG(forStatement.Body, options) + if err != nil { + return nil, err + } + + results = append(results, bodyMLOG...) + + // TODO Support more statements + if incDecStatement, ok := forStatement.Post.(*ast.IncDecStmt); ok { + name := &NormalVariable{Name: incDecStatement.X.(*ast.Ident).Name} + op := "add" + if incDecStatement.Tok == token.DEC { + op = "sub" + } + results = append(results, &MLOG{ + Comment: "Execute for loop post condition increment/decrement", + Statement: [][]Resolvable{ + { + &Value{Value: "op"}, + &Value{Value: op}, + name, + name, + &Value{Value: "1"}, + }, + }, + }) + } else { + return nil, errors.New("for loop supports only increment or decrement post statements") + } + + loopStartJump.JumpTarget = bodyMLOG[0] + results = append(results, loopStartJump) + + break + case *ast.ExprStmt: + expressionStatement := statement.(*ast.ExprStmt) + + if callExpression, ok := expressionStatement.X.(*ast.CallExpr); ok { + instructions, err := callExprToMLOG(callExpression, options) + if err != nil { + return nil, err + } + results = append(results, instructions...) + } else { + return nil, errors.New(fmt.Sprintf("unknown expression statement: %T", expressionStatement.X)) + } + + break + case *ast.IfStmt: + ifStmt := statement.(*ast.IfStmt) + + // TODO If statement init + + dVar := &DynamicVariable{} + + instructions, err := expressionToMLOG(dVar, ifStmt.Cond, options) + if err != nil { + return nil, err + } + + results = append(results, instructions...) + + blockInstructions, err := statementToMLOG(ifStmt.Body, options) + if err != nil { + return nil, err + } + + results = append(results, &MLOGJump{ + MLOG: MLOG{ + Comment: "Jump to if block if true", + }, + Condition: []Resolvable{ + &Value{Value: "equal"}, + dVar, + &Value{Value: "1"}, + }, + JumpTarget: &StatementJumpTarget{ + Statement: blockInstructions[0], + }, + }) + + afterIfTarget := &StatementJumpTarget{ + After: true, + Statement: blockInstructions[len(blockInstructions)-1], + } + results = append(results, &MLOGJump{ + MLOG: MLOG{ + Comment: "Jump to after if block", + }, + Condition: []Resolvable{ + &Value{Value: "always"}, + }, + JumpTarget: afterIfTarget, + }) + + results = append(results, blockInstructions...) + + if ifStmt.Else != nil { + elseInstructions, err := statementToMLOG(ifStmt.Else, options) + if err != nil { + return nil, err + } + + afterElseJump := &MLOGJump{ + MLOG: MLOG{ + Comment: "Jump to after else block", + }, + Condition: []Resolvable{ + &Value{Value: "always"}, + }, + JumpTarget: &StatementJumpTarget{ + After: true, + Statement: elseInstructions[len(elseInstructions)-1], + }, + } + results = append(results, afterElseJump) + afterIfTarget.Statement = afterElseJump + + results = append(results, elseInstructions...) + } + + break + case *ast.AssignStmt: + assignMlog, err := assignStmtToMLOG(statement.(*ast.AssignStmt), options) + if err != nil { + return nil, err + } + results = append(results, assignMlog...) + break + case *ast.ReturnStmt: + returnStmt := statement.(*ast.ReturnStmt) + + if len(returnStmt.Results) > 1 { + // TODO Multi-value returns + return nil, errors.New("only single value returns are supported") + } + + if len(returnStmt.Results) > 0 { + returnValue := returnStmt.Results[0] + + var resultVar Resolvable + if ident, ok := returnValue.(*ast.Ident); ok { + resultVar = &NormalVariable{Name: ident.Name} + } else if basicLit, ok := returnValue.(*ast.BasicLit); ok { + resultVar = &Value{Value: basicLit.Value} + } else if expr, ok := returnValue.(ast.Expr); ok { + dVar := &DynamicVariable{} + + instructions, err := expressionToMLOG(dVar, expr, options) + if err != nil { + return nil, err + } + + results = append(results, instructions...) + resultVar = dVar + } else { + return nil, errors.New(fmt.Sprintf("unknown return value type: %T", returnValue)) + } + + results = append(results, &MLOG{ + Comment: "Set return data", + Statement: [][]Resolvable{ + { + &Value{Value: "set"}, + &Value{Value: functionReturnVariable}, + resultVar, + }, + }, + }) + } + + results = append(results, &MLOGTrampolineBack{}) + break + case *ast.BlockStmt: + blockStmt := statement.(*ast.BlockStmt) + for _, s := range blockStmt.List { + instructions, err := statementToMLOG(s, options) + if err != nil { + return nil, err + } + results = append(results, instructions...) + } + break + default: + return nil, errors.New(fmt.Sprintf("statement type not supported: %T", statement)) + } + + return results, nil +} + +func assignStmtToMLOG(statement *ast.AssignStmt, options Options) ([]MLOGStatement, error) { + mlog := make([]MLOGStatement, 0) + + for i, expr := range statement.Lhs { + if ident, ok := expr.(*ast.Ident); ok { + if statement.Tok != token.ASSIGN && statement.Tok != token.DEFINE { + return nil, errors.New("only direct assignment is supported") + } + + exprMLOG, err := expressionToMLOG(&NormalVariable{Name: ident.Name}, statement.Rhs[i], options) + if err != nil { + return nil, err + } + mlog = append(mlog, exprMLOG...) + } else { + return nil, errors.New("left side variable assignment can only contain identifications") + } + } + + return mlog, nil +} diff --git a/transpiler/translations.go b/transpiler/translations.go new file mode 100644 index 0000000..e77e50e --- /dev/null +++ b/transpiler/translations.go @@ -0,0 +1,256 @@ +package transpiler + +import "strings" + +type Translator struct { + Count int + Translate func(args []Resolvable) []MLOGStatement +} + +var funcTranslations = map[string]Translator{ + "PrintFlush": { + Count: 1, + Translate: func(args []Resolvable) []MLOGStatement { + return []MLOGStatement{ + &MLOG{ + Statement: [][]Resolvable{ + { + &Value{Value: "printflush"}, + &Value{Value: strings.Trim(args[0].GetValue(), "\"")}, + }, + }, + }, + } + }, + }, + "print": { + Count: 1, + Translate: func(args []Resolvable) []MLOGStatement { + if len(args) == 0 { + panic("print with 0 arguments") + } + return []MLOGStatement{ + &MLOG{ + Statement: [][]Resolvable{ + { + &Value{Value: "print"}, + &Value{Value: args[0].GetValue()}, + }, + }, + }, + } + }, + }, + "println": { + Count: 2, + Translate: func(args []Resolvable) []MLOGStatement { + if len(args) == 0 { + panic("println with 0 arguments") + } + return []MLOGStatement{ + &MLOG{ + Statement: [][]Resolvable{ + { + &Value{Value: "print"}, + &Value{Value: args[0].GetValue()}, + }, + }, + }, + &MLOG{ + Statement: [][]Resolvable{ + { + &Value{Value: "print"}, + &Value{Value: `"\n"`}, + }, + }, + }, + } + }, + }, + "Write": { + Count: 1, + Translate: func(args []Resolvable) []MLOGStatement { + memoryName := strings.Trim(args[1].GetValue(), "\"") + + if memoryName == stackCellName { + panic("can't read/write to memory cell that is used for the stack: " + stackCellName) + } + + return []MLOGStatement{ + &MLOG{ + Statement: [][]Resolvable{ + { + &Value{Value: "write"}, + &Value{Value: args[0].GetValue()}, + &Value{Value: memoryName}, + &Value{Value: args[2].GetValue()}, + }, + }, + }, + } + }, + }, + "Random": { + Count: 1, + Translate: func(args []Resolvable) []MLOGStatement { + return []MLOGStatement{ + &MLOG{ + Statement: [][]Resolvable{ + { + &Value{Value: "op"}, + &Value{Value: "rand"}, + &Value{Value: functionReturnVariable}, + &Value{Value: args[0].GetValue()}, + }, + }, + }, + } + }, + }, + "Floor": { + Count: 1, + Translate: func(args []Resolvable) []MLOGStatement { + return []MLOGStatement{ + &MLOG{ + Statement: [][]Resolvable{ + { + &Value{Value: "op"}, + &Value{Value: "floor"}, + &Value{Value: functionReturnVariable}, + &Value{Value: args[0].GetValue()}, + }, + }, + }, + } + }, + }, + "Read": { + Count: 1, + Translate: func(args []Resolvable) []MLOGStatement { + memoryName := strings.Trim(args[0].GetValue(), "\"") + + if memoryName == stackCellName { + panic("can't read/write to memory cell that is used for the stack: " + stackCellName) + } + + return []MLOGStatement{ + &MLOG{ + Statement: [][]Resolvable{ + { + &Value{Value: "read"}, + &Value{Value: functionReturnVariable}, + &Value{Value: memoryName}, + &Value{Value: args[1].GetValue()}, + }, + }, + }, + } + }, + }, + "DrawRect": { + Count: 1, + Translate: func(args []Resolvable) []MLOGStatement { + return []MLOGStatement{ + &MLOG{ + Statement: [][]Resolvable{ + { + &Value{Value: "draw"}, + &Value{Value: "rect"}, + &Value{Value: args[0].GetValue()}, + &Value{Value: args[1].GetValue()}, + &Value{Value: args[2].GetValue()}, + &Value{Value: args[3].GetValue()}, + }, + }, + }, + } + }, + }, + "DrawFlush": { + Count: 1, + Translate: func(args []Resolvable) []MLOGStatement { + return []MLOGStatement{ + &MLOG{ + Statement: [][]Resolvable{ + { + &Value{Value: "drawflush"}, + &Value{Value: strings.Trim(args[0].GetValue(), "\"")}, + }, + }, + }, + } + }, + }, + "DrawClear": { + Count: 1, + Translate: func(args []Resolvable) []MLOGStatement { + return []MLOGStatement{ + &MLOG{ + Statement: [][]Resolvable{ + { + &Value{Value: "draw"}, + &Value{Value: "clear"}, + &Value{Value: args[0].GetValue()}, + &Value{Value: args[1].GetValue()}, + &Value{Value: args[2].GetValue()}, + }, + }, + }, + } + }, + }, + "DrawColor": { + Count: 1, + Translate: func(args []Resolvable) []MLOGStatement { + return []MLOGStatement{ + &MLOG{ + Statement: [][]Resolvable{ + { + &Value{Value: "draw"}, + &Value{Value: "color"}, + &Value{Value: args[0].GetValue()}, + &Value{Value: args[1].GetValue()}, + &Value{Value: args[2].GetValue()}, + &Value{Value: args[3].GetValue()}, + }, + }, + }, + } + }, + }, + "Sleep": { + Count: 2, + Translate: func(args []Resolvable) []MLOGStatement { + dVar := &DynamicVariable{} + + jump := &MLOGJump{ + MLOG: MLOG{}, + Condition: []Resolvable{ + &Value{Value: "lessThan"}, + &Value{Value: "@time"}, + dVar, + }, + } + + jump.JumpTarget = &StatementJumpTarget{ + Statement: jump, + After: false, + } + + return []MLOGStatement{ + &MLOG{ + Statement: [][]Resolvable{ + { + &Value{Value: "op"}, + &Value{Value: "add"}, + dVar, + &Value{Value: "@time"}, + &Value{Value: args[0].GetValue()}, + }, + }, + }, + jump, + } + }, + }, +} diff --git a/transpiler/types.go b/transpiler/types.go new file mode 100644 index 0000000..db60615 --- /dev/null +++ b/transpiler/types.go @@ -0,0 +1,346 @@ +package transpiler + +import ( + "errors" + "fmt" + "strconv" +) + +type Global struct { + Functions []*Function + Constants map[string]bool +} + +type Function struct { + Name string + Statements []MLOGStatement + ArgumentCount int + VariableCounter int +} + +type MLOGAble interface { + ToMLOG() [][]Resolvable + GetComment() string +} + +type Processable interface { + PostProcess(*Global, *Function) error +} + +type WithPosition interface { + GetPosition() int +} + +type MutablePosition interface { + SetPosition(int) int +} + +type MLOGStatement interface { + MLOGAble + WithPosition + MutablePosition + Processable +} + +func MLOGToString(statements [][]Resolvable, statement MLOGAble, lineNumber int, options Options) string { + result := "" + for _, line := range statements { + resultLine := "" + for _, t := range line { + if resultLine != "" { + resultLine += " " + } + resultLine += t.GetValue() + } + + if options.Numbers { + result += fmt.Sprintf("%3d: ", lineNumber) + } + + if options.Comments { + result += fmt.Sprintf("%-45s", resultLine) + result += " // " + statement.GetComment() + } else { + result += resultLine + } + + result += "\n" + lineNumber++ + } + return result +} + +type MLOG struct { + Statement [][]Resolvable + Position int + Comment string +} + +func (m *MLOG) ToMLOG() [][]Resolvable { + return m.Statement +} + +func (m *MLOG) PostProcess(global *Global, function *Function) error { + for _, resolvables := range m.Statement { + for _, resolvable := range resolvables { + if err := resolvable.PostProcess(global, function); err != nil { + return err + } + } + } + return nil +} + +func (m *MLOG) GetPosition() int { + return m.Position +} + +func (m *MLOG) SetPosition(position int) int { + m.Position = position + return 1 +} + +func (m *MLOG) GetComment() string { + return m.Comment +} + +type MLOGFunc struct { + Position int + Function Translator + Arguments []Resolvable + Unresolved []MLOGStatement +} + +func (m *MLOGFunc) ToMLOG() [][]Resolvable { + results := make([][]Resolvable, 0) + for _, statement := range m.Unresolved { + results = append(results, statement.ToMLOG()...) + } + return results +} + +func (m *MLOGFunc) GetPosition() int { + return m.Position +} + +func (m *MLOGFunc) SetPosition(position int) int { + m.Position = position + return m.Function.Count +} + +func (m *MLOGFunc) PostProcess(global *Global, function *Function) error { + for _, argument := range m.Arguments { + if err := argument.PostProcess(global, function); err != nil { + return err + } + } + m.Unresolved = m.Function.Translate(m.Arguments) + for i, statement := range m.Unresolved { + statement.SetPosition(m.Position + i) + if err := statement.PostProcess(global, function); err != nil { + return err + } + } + return nil +} + +func (m *MLOGFunc) GetComment() string { + return "Call to native function" +} + +type JumpTarget interface { + Processable + WithPosition +} + +type MLOGJump struct { + MLOG + Condition []Resolvable + JumpTarget JumpTarget +} + +func (m *MLOGJump) ToMLOG() [][]Resolvable { + return [][]Resolvable{ + append([]Resolvable{ + &Value{Value: "jump"}, + &Value{Value: strconv.Itoa(m.JumpTarget.GetPosition())}, + }, m.Condition...), + } +} + +func (m *MLOGJump) PostProcess(global *Global, function *Function) error { + for _, resolvable := range m.Condition { + if err := resolvable.PostProcess(global, function); err != nil { + return err + } + } + return m.JumpTarget.PostProcess(global, function) +} + +func (m *MLOGJump) GetComment() string { + if m.Comment == "" { + return "Jump to target" + } + return m.Comment +} + +type FunctionJumpTarget struct { + Statement WithPosition + FunctionName string +} + +func (m *FunctionJumpTarget) GetPosition() int { + return m.Statement.GetPosition() +} + +func (m *FunctionJumpTarget) PostProcess(global *Global, _ *Function) error { + for _, fn := range global.Functions { + if fn.Name == m.FunctionName { + m.Statement = fn.Statements[0] + return nil + } + } + return errors.New("unknown function: " + m.FunctionName) +} + +type Resolvable interface { + Processable + GetValue() string +} + +type Value struct { + Value string +} + +func (m *Value) GetValue() string { + return m.Value +} + +func (m *Value) PostProcess(*Global, *Function) error { + return nil +} + +func (m *Value) String() string { + return m.Value +} + +type NormalVariable struct { + Name string + CalculatedName string +} + +func (m *NormalVariable) PostProcess(global *Global, function *Function) error { + if m.CalculatedName == "" { + if _, ok := global.Constants[m.Name]; ok { + m.CalculatedName = m.Name + } else { + m.CalculatedName = "_" + function.Name + "_" + m.Name + } + } + return nil +} + +func (m *NormalVariable) GetValue() string { + if m.CalculatedName == "" { + panic("PostProcess not called on NormalVariable (" + m.Name + ")") + } + return m.CalculatedName +} + +type DynamicVariable struct { + Name string +} + +func (m *DynamicVariable) PostProcess(global *Global, function *Function) error { + if m.Name == "" { + suffix := function.VariableCounter + function.VariableCounter += 1 + m.Name = "_" + function.Name + "_" + strconv.Itoa(suffix) + } + return nil +} + +func (m *DynamicVariable) GetValue() string { + if m.Name == "" { + panic("PostProcess not called on DynamicVariable") + } + return m.Name +} + +type MLOGTrampoline struct { + MLOG + Variable string + Extra int +} + +func (m *MLOGTrampoline) ToMLOG() [][]Resolvable { + return [][]Resolvable{ + { + &Value{Value: "write"}, + &Value{Value: strconv.Itoa(m.Position + m.Extra)}, + &Value{Value: stackCellName}, + &Value{Value: m.Variable}, + }, + } +} + +func (m *MLOGTrampoline) GetComment() string { + return "Set Trampoline Address" +} + +type MLOGStackWriter struct { + MLOG + Action string + Extra int +} + +func (m *MLOGStackWriter) ToMLOG() [][]Resolvable { + return [][]Resolvable{ + { + &Value{Value: "op"}, + &Value{Value: m.Action}, + &Value{Value: stackVariable}, + &Value{Value: stackVariable}, + &Value{Value: strconv.Itoa(1 + m.Extra)}, + }, + } +} + +func (m *MLOGStackWriter) GetComment() string { + return "Update Stack Pointer" +} + +type StatementJumpTarget struct { + Statement WithPosition + After bool +} + +func (m *StatementJumpTarget) GetPosition() int { + if m.After { + return m.Statement.GetPosition() + 1 + } + return m.Statement.GetPosition() +} + +func (m *StatementJumpTarget) PostProcess(*Global, *Function) error { + return nil +} + +type MLOGTrampolineBack struct { + MLOG +} + +func (m *MLOGTrampolineBack) ToMLOG() [][]Resolvable { + return [][]Resolvable{ + { + &Value{Value: "read"}, + &Value{Value: "@counter"}, + &Value{Value: stackCellName}, + &Value{Value: stackVariable}, + }, + } +} + +func (m *MLOGTrampolineBack) GetComment() string { + return "Trampoline back" +} diff --git a/wasm/main.go b/wasm/main.go new file mode 100644 index 0000000..641d368 --- /dev/null +++ b/wasm/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "fmt" + "github.com/Vilsol/go-mlog/transpiler" + "runtime/debug" + "syscall/js" +) + +func transpileWrapper() js.Func { + transpileFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} { + if len(args) != 1 { + return "Invalid no of arguments passed" + } + input := args[0].String() + + defer func() { + if r := recover(); r != nil { + fmt.Printf("panic: %s\n", r) + fmt.Println(string(debug.Stack())) + } + }() + + mlog, err := transpiler.GolangToMLOG(input, transpiler.Options{ + Numbers: false, + Comments: false, + Debug: false, + }) + if err != nil { + fmt.Printf("error transpiling: %s\n", err) + return err.Error() + } + return mlog + }) + return transpileFunc +} + +func main() { + fmt.Println("Transpiler Initialized") + js.Global().Set("transpileGo", transpileWrapper()) + <-make(chan bool) +}