diff --git a/api/transpiler/transpiler.go b/api/transpiler/transpiler.go deleted file mode 100644 index 5b69b52..0000000 --- a/api/transpiler/transpiler.go +++ /dev/null @@ -1,6 +0,0 @@ -package transpiler - -// Transpiler specifies the behaviour of taking Go source code and transforming it into another language. -type Transpiler interface { - Transpile() error -} diff --git a/api/worker/mapping.go b/api/worker/mapping.go deleted file mode 100644 index e1d1f45..0000000 --- a/api/worker/mapping.go +++ /dev/null @@ -1,6 +0,0 @@ -package worker - -// Mapping specifies the api logic to apply transformation to a specific identifier. -type Mapping interface { - Apply(ident string) string -} diff --git a/api/worker/source.go b/api/worker/source.go deleted file mode 100644 index c93f49d..0000000 --- a/api/worker/source.go +++ /dev/null @@ -1,6 +0,0 @@ -package worker - -// Source stores the code which will be transformed into another format. -type Source interface { - String() string -} diff --git a/api/worker/target.go b/api/worker/target.go deleted file mode 100644 index e68345c..0000000 --- a/api/worker/target.go +++ /dev/null @@ -1,6 +0,0 @@ -package worker - -// Target stores the result of the transformation process. -type Target interface { - String() string -} diff --git a/api/worker/worker.go b/api/worker/worker.go deleted file mode 100644 index 610a4b7..0000000 --- a/api/worker/worker.go +++ /dev/null @@ -1,6 +0,0 @@ -package worker - -// Worker specifies the api logic of transforming a source code format into another target format. -type Worker interface { - Start() error -} diff --git a/go.mod b/go.mod index 077799b..2e505f4 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,3 @@ module github.com/andygeiss/esp32-transpiler -go 1.12 - -require github.com/andygeiss/assert v0.0.6 +go 1.14 diff --git a/go.sum b/go.sum deleted file mode 100644 index c461b8c..0000000 --- a/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/andygeiss/assert v0.0.6 h1:FyiAIudVwnxp55GIcNOaZ2ABr8n2RI9SXmaXG7+Y53o= -github.com/andygeiss/assert v0.0.6/go.mod h1:ztUvWrfUo43X0zMA1XfX8esn5Uavk6ANSKTT0w2qvAI= diff --git a/impl/transpile/transpile.go b/impl/transpile/transpile.go deleted file mode 100644 index d611696..0000000 --- a/impl/transpile/transpile.go +++ /dev/null @@ -1,30 +0,0 @@ -package transpile - -import ( - "fmt" - "github.com/andygeiss/esp32-transpiler/api/transpiler" - "github.com/andygeiss/esp32-transpiler/api/worker" -) - -// Transpiler uses a given worker to main source code. -type Transpiler struct { - w worker.Worker -} - -const ( - // ErrorTranspilerWorkerIsNil ... - ErrorTranspilerWorkerIsNil = "Worker should not be nil" -) - -// NewTranspiler creates a new transpiler and returns its address. -func NewTranspiler(w worker.Worker) transpiler.Transpiler { - return &Transpiler{w} -} - -// Transpile invokes the workers -func (c *Transpiler) Transpile() error { - if c.w == nil { - return fmt.Errorf("Error: %v", ErrorTranspilerWorkerIsNil) - } - return c.w.Start() -} diff --git a/impl/transpile/transpile_test.go b/impl/transpile/transpile_test.go deleted file mode 100644 index 31ab8b2..0000000 --- a/impl/transpile/transpile_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package transpile_test - -import ( - "bytes" - "github.com/andygeiss/assert" - "github.com/andygeiss/esp32-transpiler/api/worker" - "github.com/andygeiss/esp32-transpiler/impl/transpile" - "io" - "testing" -) - -type mockupWorker struct { - in io.Reader - out io.Writer -} - -func (w *mockupWorker) Prepare(source []worker.Source) (chan worker.Source, error) { - out := make(chan worker.Source) - return out, nil -} -func (w *mockupWorker) Start() error { - return nil -} -func (w *mockupWorker) Transform(source chan worker.Source) (chan worker.Target, error) { - out := make(chan worker.Target) - return out, nil -} - -func TestTranspileErrorShouldBeNil(t *testing.T) { - var in, out bytes.Buffer - worker := &mockupWorker{&in, &out} - trans := transpile.NewTranspiler(worker) - err := trans.Transpile() - assert.That(t, err, nil) -} diff --git a/impl/worker/mapping.go b/impl/worker/mapping.go deleted file mode 100644 index 616cac0..0000000 --- a/impl/worker/mapping.go +++ /dev/null @@ -1,84 +0,0 @@ -package worker - -import ( - "github.com/andygeiss/esp32-transpiler/api/worker" -) - -var ( - rules = map[string]string{ - "digital.Low": "LOW", - "digital.High": "HIGH", - "digital.ModeInput": "INPUT", - "digital.ModeOutput": "OUTPUT", - "digital.PinMode": "pinMode", - "digital.Write": "digitalWrite", - "random.Num": "random", - "random.NumBetween": "random", - "random.Seed": "randomSeed", - "serial.Available": "Serial.available", - "serial.BaudRate300": "300", - "serial.BaudRate600": "600", - "serial.BaudRate1200": "1200", - "serial.BaudRate2400": "2400", - "serial.BaudRate4800": "4800", - "serial.BaudRate9600": "9600", - "serial.BaudRate14400": "14400", - "serial.BaudRate28800": "28800", - "serial.BaudRate38400": "38400", - "serial.BaudRate57600": "57600", - "serial.BaudRate115200": "115200", - "serial.Begin": "Serial.begin", - "serial.Print": "Serial.print", - "serial.Println": "Serial.println", - "timer.Delay": "delay", - "wifi": "WiFi", - "wifi.Client": "WiFiClient", - "client.Connect": "client.connect", - "client.Println": "client.println", - "client.Write": "client.write", - "wifi.Begin": "WiFi.begin", - "wifi.BeginEncrypted": "WiFi.begin", - "wifi.BSSID": "WiFi.BSSID", - "wifi.Disconnect": "WiFi.disconnect", - "wifi.EncryptionType": "WiFi.encryptionType", - "wifi.EncryptionTypeAuto": "8", - "wifi.EncryptionTypeCCMP": "4", - "wifi.EncryptionTypeNone": "7", - "wifi.EncryptionTypeTKIP": "2", - "wifi.EncryptionTypeWEP": "5", - "wifi.LocalIP": "WiFi.localIP", - "wifi.RSSI": "WiFi.RSSI", - "wifi.ScanNetworks": "WiFi.scanNetworks", - "wifi.SetDNS": "WiFi.setDNS", - "wifi.SSID": "WiFi.SSID", - "wifi.Status": "WiFi.status", - "wifi.StatusConnected": "WL_CONNECTED", - "wifi.StatusConnectionLost": "WL_CONNECTION_LOST", - "wifi.StatusConnectFailed": "WL_CONNECT_FAILED", - "wifi.StatusDisconnected": "WL_DISCONNECTED", - "wifi.StatusIdle": "WL_IDLE_STATUS", - "wifi.StatusNoShield": "WL_NO_SHIELD", - "wifi.StatusNoSSIDAvailable": "WL_NO_SSID_AVAIL", - "wifi.StatusScanCompleted": "WL_SCAN_COMPLETED", - "Loop": "void loop", - "Setup": "void setup", - } -) - -// Mapping specifies the api logic to apply transformation to a specific Golang identifier by reading simple JSON map. -type Mapping struct{} - -// NewMapping creates a new mapping and returns its address. -func NewMapping() worker.Mapping { - return &Mapping{} -} - -// Apply checks the Golang identifier and transforms it to a specific representation. -func (*Mapping) Apply(ident string) string { - for wanted := range rules { - if ident == wanted { - ident = rules[ident] - } - } - return ident -} diff --git a/main.go b/main.go index a8c756c..7f77d57 100644 --- a/main.go +++ b/main.go @@ -1,10 +1,9 @@ package main import ( + "esp32-transpiler/transpile" "flag" "fmt" - "github.com/andygeiss/esp32-transpiler/impl/transpile" - "github.com/andygeiss/esp32-transpiler/impl/worker" "os" ) @@ -34,7 +33,7 @@ func printUsage() { flag.PrintDefaults() fmt.Print("\n") fmt.Print("Example:\n") - fmt.Printf("\tesp32 -source impl/blink/controller.go -target impl/blink/controller.worker\n\n") + fmt.Printf("\tesp32 -source impl/blink/controller.go -target impl/blink/controller.transpile\n\n") } func safeTranspile(source, target string) { @@ -53,9 +52,8 @@ func safeTranspile(source, target string) { os.Exit(1) } // Transpiles the Golang source into Arduino sketch. - wrk := worker.NewWorker(in, out, worker.NewMapping()) - trans := transpile.NewTranspiler(wrk) - if err := trans.Transpile(); err != nil { + service := transpile.NewService(in, out) + if err := service.Start(); err != nil { fmt.Fprintf(os.Stderr, "%v", err) os.Exit(1) } diff --git a/transpile/mapping.go b/transpile/mapping.go new file mode 100644 index 0000000..0ad1b3c --- /dev/null +++ b/transpile/mapping.go @@ -0,0 +1,60 @@ +package transpile + +var mapping = map[string]string{ + "digital.Low": "LOW", + "digital.High": "HIGH", + "digital.ModeInput": "INPUT", + "digital.ModeOutput": "OUTPUT", + "digital.PinMode": "pinMode", + "digital.Write": "digitalWrite", + "random.Num": "random", + "random.NumBetween": "random", + "random.Seed": "randomSeed", + "serial.Available": "Serial.available", + "serial.BaudRate300": "300", + "serial.BaudRate600": "600", + "serial.BaudRate1200": "1200", + "serial.BaudRate2400": "2400", + "serial.BaudRate4800": "4800", + "serial.BaudRate9600": "9600", + "serial.BaudRate14400": "14400", + "serial.BaudRate28800": "28800", + "serial.BaudRate38400": "38400", + "serial.BaudRate57600": "57600", + "serial.BaudRate115200": "115200", + "serial.Begin": "Serial.begin", + "serial.Print": "Serial.print", + "serial.Println": "Serial.println", + "timer.Delay": "delay", + "wifi": "WiFi", + "wifi.Client": "WiFiClient", + "client.Connect": "client.connect", + "client.Println": "client.println", + "client.Write": "client.write", + "wifi.Begin": "WiFi.begin", + "wifi.BeginEncrypted": "WiFi.begin", + "wifi.BSSID": "WiFi.BSSID", + "wifi.Disconnect": "WiFi.disconnect", + "wifi.EncryptionType": "WiFi.encryptionType", + "wifi.EncryptionTypeAuto": "8", + "wifi.EncryptionTypeCCMP": "4", + "wifi.EncryptionTypeNone": "7", + "wifi.EncryptionTypeTKIP": "2", + "wifi.EncryptionTypeWEP": "5", + "wifi.LocalIP": "WiFi.localIP", + "wifi.RSSI": "WiFi.RSSI", + "wifi.ScanNetworks": "WiFi.scanNetworks", + "wifi.SetDNS": "WiFi.setDNS", + "wifi.SSID": "WiFi.SSID", + "wifi.Status": "WiFi.status", + "wifi.StatusConnected": "WL_CONNECTED", + "wifi.StatusConnectionLost": "WL_CONNECTION_LOST", + "wifi.StatusConnectFailed": "WL_CONNECT_FAILED", + "wifi.StatusDisconnected": "WL_DISCONNECTED", + "wifi.StatusIdle": "WL_IDLE_STATUS", + "wifi.StatusNoShield": "WL_NO_SHIELD", + "wifi.StatusNoSSIDAvailable": "WL_NO_SSID_AVAIL", + "wifi.StatusScanCompleted": "WL_SCAN_COMPLETED", + "Loop": "void loop", + "Setup": "void setup", +} diff --git a/impl/worker/worker.go b/transpile/service.go similarity index 88% rename from impl/worker/worker.go rename to transpile/service.go index c2aa3ca..83c7ae7 100644 --- a/impl/worker/worker.go +++ b/transpile/service.go @@ -1,8 +1,7 @@ -package worker +package transpile import ( "fmt" - "github.com/andygeiss/esp32-transpiler/api/worker" "go/ast" "go/parser" "go/token" @@ -10,6 +9,11 @@ import ( "strings" ) +// Service specifies the api logic of transforming a source code format into another target format. +type Service interface { + Start() error +} + const ( // ErrorWorkerReaderIsNil ... ErrorWorkerReaderIsNil = "Reader should not be nil" @@ -17,37 +21,37 @@ const ( ErrorWorkerWriterIsNil = "Writer should not be nil" ) -var mapping worker.Mapping - -// Worker specifies the api logic of transforming a source code format into another target format. -type Worker struct { +// defaultService specifies the api logic of transforming a source code format into another target format. +type defaultService struct { in io.Reader out io.Writer } -// NewWorker creates a a new worker and returns its address. -func NewWorker(in io.Reader, out io.Writer, m worker.Mapping) worker.Worker { - mapping = m - return &Worker{in, out} +// NewService creates a a new transpile and returns its address. +func NewService(in io.Reader, out io.Writer) Service { + return &defaultService{ + in: in, + out: out, + } } // Start ... -func (w *Worker) Start() error { - if w.in == nil { +func (s *defaultService) Start() error { + if s.in == nil { return fmt.Errorf("Error: %s", ErrorWorkerReaderIsNil) } - if w.out == nil { + if s.out == nil { return fmt.Errorf("Error: %s", ErrorWorkerWriterIsNil) } // Read tokens from file by using Go's parser. fset := token.NewFileSet() - file, err := parser.ParseFile(fset, "source.go", w.in, 0) + file, err := parser.ParseFile(fset, "source.go", s.in, 0) if err != nil { return fmt.Errorf("ParseFile failed! %v", err) } // If source has no declarations then main it to an empty for loop. if file.Decls == nil { - fmt.Fprint(w.out, "void loop() {} void setup() {}") + fmt.Fprint(s.out, "void loop() {} void setup() {}") return nil } // Use Goroutines to work concurrently. @@ -57,7 +61,7 @@ func (w *Worker) Start() error { for i := 0; i < count; i++ { dst[i] = make(chan string, 1) } - // Start a worker with an individual channel for each declaration in the source file. + // Start a transpile with an individual channel for each declaration in the source file. for i, decl := range file.Decls { go handleDecl(i, decl, dst[i], done) } @@ -70,7 +74,7 @@ func (w *Worker) Start() error { // Print the ordered result. for i := 0; i < count; i++ { for content := range dst[i] { - w.out.Write([]byte(content)) + s.out.Write([]byte(content)) } } // Print the AST. @@ -160,7 +164,7 @@ func handleExpr(expr ast.Expr) string { return code } -func handleParenExpr (stmt *ast.ParenExpr) string { +func handleParenExpr(stmt *ast.ParenExpr) string { code := "" code += handleExpr(stmt.X) return code @@ -249,7 +253,9 @@ func handleFuncDeclName(ident *ast.Ident) string { return code } code += ident.Name - code = mapping.Apply(code) + if val, ok := mapping[code]; ok { + code = val + } return code } @@ -302,7 +308,9 @@ func handleImportSpec(spec ast.Spec) string { code := "" if s.Name != nil { name := handleIdent(s.Name) - name = mapping.Apply(name) + if val, ok := mapping[name]; ok { + name = val + } if name != "" { if name != "controller" { code = "#include <" + name + ".h>\n" @@ -321,7 +329,9 @@ func handleSelectorExpr(expr ast.Expr) string { } code += "." code += handleIdent(s.Sel) - code = mapping.Apply(code) + if val, ok := mapping[code]; ok { + code = val + } return code } @@ -370,9 +380,9 @@ func handleForStmt(stmt *ast.ForStmt) string { } else { code += "for" } - code += "(" // stmt.Init + code += "(" // stmt.Init code += handleBinaryExpr(stmt.Cond) // stmt.Cond - code += "" // stmt.Post + code += "" // stmt.Post code += ") {" code += handleBlockStmt(stmt.Body) // stmt.Body code += "}" diff --git a/impl/worker/worker_test.go b/transpile/service_test.go similarity index 94% rename from impl/worker/worker_test.go rename to transpile/service_test.go index 2865f92..79ee854 100644 --- a/impl/worker/worker_test.go +++ b/transpile/service_test.go @@ -1,9 +1,9 @@ -package worker_test +package transpile_test import ( "bytes" - "github.com/andygeiss/assert" - "github.com/andygeiss/esp32-transpiler/impl/worker" + "esp32-transpiler/transpile" + "reflect" "strings" "testing" ) @@ -18,15 +18,20 @@ func Trim(s string) string { } // Validate the content of a given source with an expected outcome by using a string compare. -// The Worker will be started and used to transform the source into an Arduino sketch format. +// The defaultService will be started and used to transform the source into an Arduino sketch format. func Validate(source, expected string, t *testing.T) { var in, out bytes.Buffer in.WriteString(source) - wrk := worker.NewWorker(&in, &out, worker.NewMapping()) - assert.That(t, wrk.Start(), nil) - code := out.String() - tcode, texpected := Trim(code), Trim(expected) - assert.That(t, tcode, texpected) + service := transpile.NewService(&in, &out) + err := service.Start() + got := out.String() + tgot, texpected := Trim(got), Trim(expected) + if !reflect.DeepEqual(err, nil) { + t.Fatalf("got %v, but expected %v", err, nil) + } + if !reflect.DeepEqual(err, nil) { + t.Fatalf("got %v, but expected %v", tgot, texpected) + } } func Test_Empty_Package(t *testing.T) {