diff --git a/transpile_python/service.go b/transpile_python/service.go index d64f652..bab29fa 100644 --- a/transpile_python/service.go +++ b/transpile_python/service.go @@ -7,6 +7,8 @@ import ( "go/token" "io" "strings" + + "github.com/davecgh/go-spew/spew" ) // Service specifies the api logic of transforming a source code format into another target format. @@ -27,6 +29,8 @@ type defaultService struct { out io.Writer } +var ind int + // NewService creates a a new transpile and returns its address. func NewService(in io.Reader, out io.Writer) Service { return &defaultService{ @@ -43,15 +47,16 @@ func (s *defaultService) Start() error { if s.out == nil { return fmt.Errorf("Error: %s", ErrorWorkerWriterIsNil) } + ind = 0 // Read tokens from file by using Go's parser. fset := token.NewFileSet() - file, err := parser.ParseFile(fset, "source.go", s.in, 0) + file, err := parser.ParseFile(fset, "source.go", s.in, parser.ParseComments) 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(s.out, "void loop() {} void setup() {}") + fmt.Fprint(s.out, "from skidl import *\n") return nil } // Use Goroutines to work concurrently. @@ -62,15 +67,20 @@ func (s *defaultService) Start() error { dst[i] = make(chan string, 1) } // 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) - } + go func() { + for i, decl := range file.Decls { + handleDecl(i, decl, dst[i], done) + } + }() // Wait for all workers are done. for i := 0; i < count; i++ { select { case <-done: } } + + s.out.Write([]byte("from skidl import *\n")) + // Print the ordered result. for i := 0; i < count; i++ { for content := range dst[i] { @@ -78,17 +88,37 @@ func (s *defaultService) Start() error { } } - s.out.Write([]byte("\n")) + s.out.Write([]byte("main()\n")) // Print the AST. // ast.Fprint(os.Stderr, fset, file, nil) return nil } +func increaseInd() { + ind++ +} +func decreaseInd() { + ind-- +} +func indSpaces() string { + res := "" + for i := 0; i < ind; i++ { + res += " " + } + return res +} + func handleAssignStmt(as *ast.AssignStmt) string { code := handleAssignStmtExpr(as.Lhs) - code += as.Tok.String() + switch as.Tok { + case token.DEFINE: + code += " = " + default: + code += " " + as.Tok.String() + " " + } code += handleAssignStmtExpr(as.Rhs) + code += "\n" return code } @@ -115,7 +145,12 @@ func handleUnaryExpr(expr *ast.UnaryExpr) string { func handleBinaryExpr(expr ast.Expr) string { be := expr.(*ast.BinaryExpr) code := handleExpr(be.X) - code += be.Op.String() + switch be.Op { + case token.EQL: + code += "=" + default: + code += " " + be.Op.String() + " " + } code += handleExpr(be.Y) return code } @@ -171,6 +206,11 @@ func handleExpr(expr ast.Expr) string { code += handleParenExpr(e) case *ast.SelectorExpr: code += handleSelectorExpr(e) + case *ast.IndexExpr: + code += handleIndexExpr(e) + default: + spew.Dump(e) + code += "Unknown in handleExpr" } return code } @@ -186,7 +226,13 @@ func handleExprStmt(stmt *ast.ExprStmt) string { switch x := stmt.X.(type) { case *ast.CallExpr: code += handleCallExpr(x) + case *ast.BinaryExpr: + code += handleBinaryExpr(x) + default: + spew.Dump(stmt.X) + code += "unknown in handleExprStmt" } + code += "\n" return code } @@ -196,9 +242,19 @@ func handleFuncDecl(decl ast.Decl) string { return "" } code := "" + if fd.Doc != nil { + t := fd.Doc.Text() + switch t { + case "@package\n": + code += t + case "@subcircuit\n": + code += t + } + } + code += "def " name := "" code += handleFuncDeclType(fd.Type) - code += " " + code += "" name = handleFuncDeclName(fd.Name) if name == "NewController" { return "" @@ -206,9 +262,11 @@ func handleFuncDecl(decl ast.Decl) string { code += name code += "(" code += handleFuncDeclParams(fd.Type) - code += ") {" + code += "):\n" + increaseInd() code += handleBlockStmt(fd.Body) - code += "}" + decreaseInd() + code += "" return code } func shouldSkipFunction(t *ast.FuncType) (res bool) { @@ -256,7 +314,7 @@ func handleFuncDeclParams(t *ast.FuncType) string { ftype = handleIdent(ft) } for _, names := range field.Names { - values = append(values, ftype+" "+names.Name) + values = append(values, ftype+""+names.Name) } } code += strings.Join(values, ",") @@ -268,6 +326,9 @@ func handleBlockStmt(body *ast.BlockStmt) string { if body == nil { return code } + if len(body.List) == 0 { + return indSpaces() + "None\n" + } for _, stmt := range body.List { code += handleStmt(stmt, false) } @@ -307,7 +368,7 @@ func handleFuncDeclName(ident *ast.Ident) string { func handleFuncDeclType(t *ast.FuncType) string { code := "" if t.Results == nil { - code = "void" + code = "" } return code } @@ -330,7 +391,7 @@ func handleIdent(expr ast.Expr) string { code := "" switch ident.Name { case "string": - code += "char*" + code += "" default: code += ident.Name } @@ -339,11 +400,16 @@ func handleIdent(expr ast.Expr) string { func handleIfStmt(stmt *ast.IfStmt) string { cond := handleExpr(stmt.Cond) + increaseInd() body := handleBlockStmt(stmt.Body) - code := fmt.Sprintf(`if (%s) { %s }`, cond, body) + decreaseInd() + code := fmt.Sprintf("if %s:\n%s", cond, body) if stmt.Else != nil { + increaseInd() tail := handleBlockStmt(stmt.Else.(*ast.BlockStmt)) - code += fmt.Sprintf(" else { %s }", tail) + decreaseInd() + code += indSpaces() + code += fmt.Sprintf("else:\n%s", tail) } return code } @@ -380,6 +446,14 @@ func handleSelectorExpr(expr ast.Expr) string { return code } +func handleIndexExpr(expr *ast.IndexExpr) string { + code := expr.X.(*ast.Ident).String() + code += "[" + code += expr.Index.(*ast.BasicLit).Value + code += "]" + return code +} + func handleSpecs(specs []ast.Spec) string { code := "" for _, spec := range specs { @@ -394,12 +468,12 @@ func handleSpecs(specs []ast.Spec) string { } func handleStmt(stmt ast.Stmt, standaloneAssignment bool) string { - code := "" + code := indSpaces() switch s := stmt.(type) { case *ast.AssignStmt: code += handleAssignStmt(s) if !standaloneAssignment { - code += ";" + code += "" } case *ast.BranchStmt: code += handleBranchStmt(s) @@ -409,7 +483,6 @@ func handleStmt(stmt ast.Stmt, standaloneAssignment bool) string { code += handleDeclStmt(s) case *ast.ExprStmt: code += handleExprStmt(s) - code += ";" case *ast.ForStmt: code += handleForStmt(s) case *ast.IfStmt: @@ -418,6 +491,9 @@ func handleStmt(stmt ast.Stmt, standaloneAssignment bool) string { code += handleSwitchStmt(s) case *ast.ReturnStmt: code += handleReturnStmt(s) + default: + spew.Dump(stmt) + code += "unknown handleStmt" } return code } diff --git a/transpile_python/service_test.go b/transpile_python/service_test.go index e26856a..8d49604 100644 --- a/transpile_python/service_test.go +++ b/transpile_python/service_test.go @@ -7,636 +7,362 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + gomega_format "github.com/onsi/gomega/format" ) func TestUtils(t *testing.T) { RegisterFailHandler(Fail) - RunSpecs(t, "Go Translator") + gomega_format.CharactersAroundMismatchToInclude = 20 + RunSpecs(t, "Go Translator to Python/Skidl") } -var _ = Describe("Go Translator", func() { +var _ = Describe("Go Translator to Python/Skidl", func() { Describe("All", func() { - It("Empty_Package", func() { + It("Empty Package", func() { source := `package test` - expected := `void loop(){} - void setup(){}` + expected := `from skidl import * +` Compare(source, expected) }) - It("Function_Declaration", func() { + It("Function Declaration", func() { source := `package test - func foo() {} - func bar() {} + func main() {} ` - expected := `void foo(){} - void bar() {}` + expected := `from skidl import * +def main(): + None +main() +` Compare(source, expected) }) - It("Function_Declaration_With_Args", func() { + It("Func call", func() { source := `package test - func foo(x int) {} - func bar(y int) {} + func main() { + generate_netlist() + } ` - expected := `void foo(int x){} - void bar(int y) {}` + expected := `from skidl import * +def main(): + generate_netlist() +main() +` Compare(source, expected) }) - It("Const_String_Declaration", func() { + It("Net Declaration", func() { source := `package test - const foo string = "bar" - ` - expected := ` - const char* foo = "bar"; + func main() { + vin := Net("3.3v") + } ` + expected := `from skidl import * +def main(): + vin = Net("3.3v") +main() +` Compare(source, expected) }) - It("Var_String_Declaration", func() { + It("Nets Declaration", func() { source := `package test - var client wifi.Client - ` - expected := ` - WiFiClient client; + func main() { + vin := Net("3.3v") + gnd := Net("GND") + } ` + expected := `from skidl import * +def main(): + vin = Net("3.3v") + gnd = Net("GND") +main() +` Compare(source, expected) }) - It("Function_With_Const_String_Declaration", func() { + It("Part Declaration", func() { source := `package test - func foo() { - const foo string = "bar" - } - ` - expected := ` - void foo() { - const char* foo = "bar"; + func main() { + ESP32 := Part("RF_Module", "ESP32-WROOM-32", TEMPLATE, footprint == "RF_Module:ESP32-WROOM-32") } ` + expected := `from skidl import * +def main(): + ESP32 = Part("RF_Module","ESP32-WROOM-32",TEMPLATE,footprint="RF_Module:ESP32-WROOM-32") +main() +` Compare(source, expected) }) - It("Function_With_Var_String_Declaration", func() { + It("Parts Declaration", func() { source := `package test - func foo() { - var foo string = "bar" - } - ` - expected := ` - void foo() { - char* foo = "bar"; + func main() { + ESP32 := Part("RF_Module", "ESP32-WROOM-32", TEMPLATE, footprint == "RF_Module:ESP32-WROOM-32") + Klema := Part("Connector_Generic_MountingPin", "Conn_01x01_MountingPin", TEMPLATE, footprint == "TestPoint_Pad_2.0x2.0mm") } ` + expected := `from skidl import * +def main(): + ESP32 = Part("RF_Module","ESP32-WROOM-32",TEMPLATE,footprint="RF_Module:ESP32-WROOM-32") + Klema = Part("Connector_Generic_MountingPin","Conn_01x01_MountingPin",TEMPLATE,footprint="TestPoint_Pad_2.0x2.0mm") +main() +` Compare(source, expected) }) - It("Function_With_Function_Call", func() { + It("Values Declaration", func() { source := `package test - func foo() { - bar() - } - ` - expected := ` - void foo() { - bar(); + func main() { + esp32 := ESP32(value == "ESP32") + k_vin, k_gnd := Klema(2) } ` + expected := `from skidl import * +def main(): + esp32 = ESP32(value="ESP32") + k_vin,k_gnd = Klema(2) +main() +` Compare(source, expected) }) - It("Function_With_Function_Call_With_Args", func() { + It("Values with params Declaration", func() { source := `package test - func foo() { - bar(1,2,3) - } - ` - expected := ` - void foo() { - bar(1,2,3); + func main() { + tr_tok_verh := tr_npn(value == "tr Tok verh NPN") } ` + expected := `from skidl import * +def main(): + tr_tok_verh = tr_npn(value="tr Tok verh NPN") +main() +` Compare(source, expected) }) - It("Function_With_Function_Call_With_String", func() { + It("Assignments += by name ", func() { source := `package test - func foo() { - bar("foo") - } - ` - expected := ` - void foo() { - bar("foo"); + func main() { + esp32["GND"] += gnd + esp32["VDD"] += vin } ` + expected := `from skidl import * +def main(): + esp32["GND"] += gnd + esp32["VDD"] += vin +main() +` Compare(source, expected) }) - It("Function_With_Package_Function_Call", func() { + It("Assignments += by index", func() { source := `package test - func foo() { - foo.Bar(1,"2") - } - ` - expected := ` - void foo() { - foo.Bar(1,"2"); + func main() { + esp32[1] += gnd + vin += r_fb[1] + tr1[1] += tr2[2] } ` + expected := `from skidl import * +def main(): + esp32[1] += gnd + vin += r_fb[1] + tr1[1] += tr2[2] +main() +` Compare(source, expected) }) - It("Function_With_Assignments", func() { + It("Assignments &", func() { source := `package test - func foo() { - x = 1 - y = 2 - z = x + y - } - ` - expected := ` - void foo() { - x = 1; - y = 2; - z = x + y; + func main() { + tr_vkl["G"] & vkl + tr_vkl["G"] & tr2["S"] + tr_vkl & tr2["S"] } ` + expected := `from skidl import * +def main(): + tr_vkl["G"] & vkl + tr_vkl["G"] & tr2["S"] + tr_vkl & tr2["S"] +main() +` Compare(source, expected) }) - It("Function_With_Package_Selector_Assignments", func() { + It("Value Assignment", func() { source := `package test - func foo() { - x = bar() - y = pkg.Bar() - z = x + y - } - ` - expected := ` - void foo() { - x = bar(); - y = pkg.Bar(); - z = x + y; + func main() { + vkl_iface.value = "k vkl" + vkl_iface.value = 19 + vkl_iface.value = 19 / 3 + vkl_iface.value = 19 * 2 } ` + expected := `from skidl import * +def main(): + vkl_iface.value = "k vkl" + vkl_iface.value = 19 + vkl_iface.value = 19 / 3 + vkl_iface.value = 19 * 2 +main() +` Compare(source, expected) }) - It("Function_Ident_Mapping", func() { + It("Condition", func() { source := `package test - func foo() { - serial.Begin() - } - ` - expected := ` - void foo() { - Serial.begin(); - } - ` - Compare(source, expected) - }) - - It("Function_With_Ident_Param", func() { - source := `package test - func foo() { - foo.Bar(1,"2",digital.Low) - } - ` - expected := ` - void foo() { - foo.Bar(1,"2",LOW); - } - ` - Compare(source, expected) - }) - - It("Function_With_Function_Param", func() { - source := `package test - func foo() { - serial.Println(wifi.LocalIP()) - } - ` - expected := ` - void foo() { - Serial.println(WiFi.localIP()); - } - ` - Compare(source, expected) - }) - - It("Function_Should_Be_Skipped", func() { - source := `package test - func foo() (s ShouldBeSkipped) { - return; - } - ` - expected := `` - Compare(source, expected) - }) - - It("Package_Import", func() { - source := `package test - import "github.com/andygeiss/esp32-mqtt/api/controller" - import "github.com/andygeiss/esp32-mqtt/api/controller/serial" - import "github.com/andygeiss/esp32/api/controller/timer" - import wifi "github.com/andygeiss/esp32/api/controller/wifi" - ` - expected := ` - #include - ` - Compare(source, expected) - }) - - It("Package_Import_But_Ignore_Controller", func() { - source := `package test - import controller "my/go-controller" - import "github.com/andygeiss/esp32-mqtt/api/controller/serial" - import "github.com/andygeiss/esp32/api/controller/timer" - import wifi "github.com/andygeiss/esp32/api/controller/wifi" - ` - expected := ` - #include - ` - Compare(source, expected) - }) - - It("IfStmt_With_Condition_BasicLit_And_BasicLit", func() { - source := `package test - func Setup() {} - func Loop() { - if 1 == 1 { - serial.Println("1") - } - } - ` - expected := ` - void setup() {} - void loop() { - if (1 == 1) { - Serial.println("1"); - } - } - ` - Compare(source, expected) - }) - - It("IfStmt_With_Condition_Ident_And_BasicLit", func() { - source := `package test - func Setup() {} - func Loop() { - if x == 1 { - serial.Println("1") - } - } - ` - expected := ` - void setup() {} - void loop() { - if (x == 1) { - Serial.println("1"); - } - } - ` - Compare(source, expected) - }) - - It("IfStmt_With_Condition_CallExpr_And_BasicLit", func() { - source := `package test - func Setup() {} - func Loop() { - if x() == 1 { - serial.Println("1") - } - } - ` - expected := ` - void setup() {} - void loop() { - if (x() == 1) { - Serial.println("1"); - } - } - ` - Compare(source, expected) - }) - - It("IfStmt_With_Condition_Const_And_BasicLit", func() { - source := `package test - const maxX = 1 - func Setup() {} - func Loop() { - if x == maxX { - serial.Println("1") - } - } - ` - expected := ` - const maxX = 1; - void setup() {} - void loop() { - if (x == maxX) { - Serial.println("1"); - } - } - ` - Compare(source, expected) - }) - - It("IfStmt_With_Else", func() { - source := `package test - const maxX = 1 - func Setup() {} - func Loop() { - if x == maxX { - serial.Println("1") + func main() { + if a > 2 { + x = 1 + y = 5 } else { - serial.Println("2") + x = 6 + y = 9 } } - ` - expected := ` - const maxX = 1; - void setup() {} - void loop() { - if (x == maxX) { - Serial.println("1"); + ` + expected := `from skidl import * +def main(): + if a > 2: + x = 1 + y = 5 + else: + x = 6 + y = 9 +main() +` + Compare(source, expected) + }) + + It("Condition complex", func() { + source := `package test + func main() { + if a > 2 { + x = 1 + y = 5 + if b > 5 { + x = 6 + y = 9 + } else { + x = 15 + } } else { - Serial.println("2"); + x = 18 } } - ` + ` + expected := `from skidl import * +def main(): + if a > 2: + x = 1 + y = 5 + if b > 5: + x = 6 + y = 9 + else: + x = 15 + else: + x = 18 +main() +` Compare(source, expected) }) - It("SwitchStmt_With_Ident_And_BasicLit", func() { + It("Function decl/call", func() { source := `package test - func Setup() {} - func Loop() { - switch x { - case 1: - serial.Println("1") - } + func vdiv(inp, outp, param string) { + r1 := r(value == 1000) + r2 := r(value == param) + inp & r1 + r1 & outp + outp & r2 + r2 & gnd } - ` - expected := ` - void setup() {} - void loop() { - switch (x) { - case 1: - Serial.println("1"); - } + + func main() { + v := vdiv(inp, outp, "500") } - ` + ` + expected := `from skidl import * +def vdiv(inp,outp,param): + r1 = r(value=1000) + r2 = r(value=param) + inp & r1 + r1 & outp + outp & r2 + r2 & gnd +def main(): + v = vdiv(inp,outp,"500") +main() +` Compare(source, expected) }) - It("SwitchStmt_With_Break", func() { + It("Subcircuit function decorator", func() { source := `package test - func Setup() {} - func Loop() { - switch x { - case 1: - serial.Println("1") - break - case 2: - serial.Println("1") - } + //@subcircuit + func vdiv(inp, outp, param string) { + r1 := r(value == 1000) + r2 := r(value == param) + inp & r1 + r1 & outp + outp & r2 + r2 & gnd } - ` - expected := ` - void setup() {} - void loop() { - switch (x) { - case 1: - Serial.println("1"); - break; - case 2: - Serial.println("1"); - } + + func main() { + v := vdiv(inp, outp, "500") } - ` + ` + expected := `from skidl import * +@subcircuit +def vdiv(inp,outp,param): + r1 = r(value=1000) + r2 = r(value=param) + inp & r1 + r1 & outp + outp & r2 + r2 & gnd +def main(): + v = vdiv(inp,outp,"500") +main() +` Compare(source, expected) }) - It("ForLoop_WithoutInit_And_Post_Transpiles_To_While", func() { + It("Package function decorator", func() { source := `package test - import wifi "github.com/andygeiss/esp32/api/controller/wifi" - func Setup() { - serial.Begin(serial.BaudRate115200) - wifi.BeginEncrypted("SSID", "PASS") - for wifi.Status() != wifi.StatusConnected { - serial.Println("Connecting ...") - } - serial.Println("Connected!") - } - func Loop() {} - ` - expected := ` - #include - void setup() { - Serial.begin(115200); - WiFi.begin("SSID","PASS"); - while(WiFi.status()!=WL_CONNECTED){ - Serial.println("Connecting..."); - } - Serial.println("Connected!"); - } - void loop() {} - ` - Compare(source, expected) - }) - - It("WiFiWebClient", func() { - source := `package test - import wifi "github.com/andygeiss/esp32/api/controller/wifi" - var client wifi.Client - func Setup() {} - func Loop() { - serial.Print("Connecting to ") - serial.Println(host) - serial.Print(" ...") - if (client.Connect(host, 443) == true) { - serial.Println(" Connected!") - } else { - serial.Println(" Failed!") - } - } - ` - expected := `#include - WiFiClient client; - voidsetup(){} - voidloop(){ - Serial.print("Connecting to"); - Serial.println(host); - Serial.print(" ..."); - if(client.connect(host, 443) == true){ - Serial.println(" Connected!"); - } else { - Serial.println(" Failed!"); - } - }` - Compare(source, expected) - }) - }) - - Describe("Arduino", func() { - It("Maps constants", func() { - source := `package test - var analogInPin int = arduino.A0 - func Setup() {} - func Loop() {} - ` - expected := ` - int analogInPin = A0; - void setup() {} - void loop() {} - ` - Compare(source, expected) - }) - }) - - Describe("Функции", func() { - It("Объявление void функции", func() { - source := `package test - func Setup() {} - func Loop() { + //@package + func vdiv(inp, outp, param string) { + r1 := r(value == 1000) + r2 := r(value == param) + inp & r1 + r1 & outp + outp & r2 + r2 & gnd } - func MyFunction() { + func main() { + v := vdiv(inp, outp, "500") } - ` - expected := ` - void setup() {} - void loop() { - } - void MyFunction() { - } - ` - Compare(source, expected) - }) - It("Объявление void функции с return", func() { - source := `package test - func Setup() {} - func Loop() { - } - - func MyFunction() { - return - } - ` - expected := ` - void setup() {} - void loop() { - } - void MyFunction() { - return; - } - ` - Compare(source, expected) - }) - It("Объявление int функции", func() { - source := `package test - func Setup() {} - func Loop() { - } - - func MyFunction() int { - } - ` - expected := ` - void setup() {} - void loop() { - } - MyFunction() { - } - ` - Compare(source, expected) - }) - It("Объявление int функции с return 0", func() { - source := `package test - func Setup() {} - func Loop() { - } - - func MyFunction() int { - return 0 - } - ` - expected := ` - void setup() {} - void loop() { - } - MyFunction() { - return 0; - } - ` - Compare(source, expected) - }) - It("Объявление int функции с return -1", func() { - source := `package test - func Setup() {} - func Loop() { - } - - func MyFunction() int { - return -1 - } - ` - expected := ` - void setup() {} - void loop() { - } - MyFunction() { - return -1; - } - ` - Compare(source, expected) - }) - It("Объявляет и вызывает функцию", func() { - source := `package test - func Setup() {} - func Loop() { - var x int = MyFunction() - } - - func MyFunction() int { - return 0 - } - ` - expected := ` - void setup() {} - void loop() { - int x = MyFunction(); - } - MyFunction() { - return 0; - } - ` - Compare(source, expected) - }) - }) - - Describe("Циклы", func() { - It("for i=0; i<10; i+=1", func() { - source := `package test - func Setup() {} - func Loop() { - var i int - for i=0; i<10; i+=1 { - i = i - } - } - ` - expected := ` - void setup() {} - void loop() { - int i; - for (i=0; i<10; i+=1) { - i = i; - } - } - ` + ` + expected := `from skidl import * +@package +def vdiv(inp,outp,param): + r1 = r(value=1000) + r2 = r(value=param) + inp & r1 + r1 & outp + outp & r2 + r2 & gnd +def main(): + v = vdiv(inp,outp,"500") +main() +` Compare(source, expected) }) }) @@ -655,10 +381,7 @@ func Compare(source, expected string) { } func Trim(s string) string { - s = strings.Replace(s, " ", "", -1) - s = strings.Replace(s, "\n", "", -1) - s = strings.Replace(s, "\r", "", -1) - s = strings.Replace(s, "\t", "", -1) + s = strings.Replace(s, "\t", " ", -1) return s }