From d9f28f54a86bd771e60c1dd2e2f929d023fd7a96 Mon Sep 17 00:00:00 2001 From: Elliot Chance Date: Sat, 22 Apr 2017 15:46:05 +1000 Subject: [PATCH] Split into multiple packages --- .gitignore | 1 + ast/always_inline_attr.go | 4 +- ast/array_subscript_expr.go | 12 +++-- ast/asm_label_attr.go | 6 ++- ast/ast.go | 90 +++++++++++++++++++----------------- ast/availability_attr.go | 6 ++- ast/binary_operator.go | 20 +++++--- ast/break_stmt.go | 6 ++- ast/builtin_type.go | 6 ++- ast/c_style_cast_expr.go | 8 +++- ast/call_expr.go | 13 ++++-- ast/cast.go | 32 ------------- ast/character_literal.go | 6 ++- ast/common.go | 49 -------------------- ast/compound_stmt.go | 12 +++-- ast/conditional_operator.go | 16 ++++--- ast/const_attr.go | 6 ++- ast/constant_array_type.go | 6 ++- ast/decl_ref_expr.go | 10 ++-- ast/decl_stmt.go | 12 +++-- ast/deprecated_attr.go | 6 ++- ast/elaborated_type.go | 6 ++- ast/enum.go | 6 ++- ast/enum_constant_decl.go | 6 ++- ast/enum_decl.go | 8 +++- ast/enum_type.go | 6 ++- ast/field_decl.go | 9 ++-- ast/floating_literal.go | 8 +++- ast/for_stmt.go | 20 ++++---- ast/format_attr.go | 6 ++- ast/function_decl.go | 37 ++++++++------- ast/function_proto_type.go | 6 ++- ast/if_stmt.go | 23 +++++---- ast/implicit_cast_expr.go | 8 +++- ast/integer_literal.go | 8 +++- ast/malloc_attr.go | 6 ++- ast/member_expr.go | 16 +++++-- ast/mode_attr.go | 6 ++- ast/no_throw_attr.go | 6 ++- ast/non_null_attr.go | 6 ++- ast/paren_expr.go | 10 ++-- ast/parm_var_decl.go | 8 +++- ast/pointer_type.go | 6 ++- ast/predefined_expr.go | 8 +++- ast/qual_type.go | 6 ++- ast/record.go | 6 ++- ast/record_decl.go | 17 ++++--- ast/record_type.go | 6 ++- ast/restrict_attr.go | 6 ++- ast/return_stmt.go | 13 ++++-- ast/string_literal.go | 4 +- ast/translation_unit_decl.go | 8 ++-- ast/typedef.go | 6 ++- ast/typedef_decl.go | 17 ++++--- ast/typedef_type.go | 6 ++- ast/unary_operator.go | 15 ++++-- ast/util.go | 18 ++------ ast/var_decl.go | 9 ++-- ast/while_stmt.go | 15 +++--- main.go | 7 +-- program/program.go | 47 +++++++++++++++++++ types/cast.go | 37 +++++++++++++++ {ast => types}/resolve.go | 31 ++++++++----- types/resolve_test.go | 27 +++++++++++ util/util.go | 17 +++++++ 65 files changed, 563 insertions(+), 311 deletions(-) delete mode 100644 ast/cast.go delete mode 100644 ast/common.go create mode 100644 program/program.go create mode 100644 types/cast.go rename {ast => types}/resolve.go (83%) create mode 100644 types/resolve_test.go create mode 100644 util/util.go diff --git a/.gitignore b/.gitignore index 3bad065ba..de8f91229 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ /bin /coverage.txt /c2go +/.vscode diff --git a/ast/always_inline_attr.go b/ast/always_inline_attr.go index defb380aa..3c30eae87 100644 --- a/ast/always_inline_attr.go +++ b/ast/always_inline_attr.go @@ -1,5 +1,7 @@ package ast +import "github.com/elliotchance/c2go/program" + type AlwaysInlineAttr struct { Address string Position string @@ -19,7 +21,7 @@ func parseAlwaysInlineAttr(line string) *AlwaysInlineAttr { } } -func (n *AlwaysInlineAttr) render(ast *Ast) (string, string) { +func (n *AlwaysInlineAttr) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/array_subscript_expr.go b/ast/array_subscript_expr.go index 204cef38f..25b6572ca 100644 --- a/ast/array_subscript_expr.go +++ b/ast/array_subscript_expr.go @@ -1,6 +1,10 @@ package ast -import "fmt" +import ( + "fmt" + + "github.com/elliotchance/c2go/program" +) type ArraySubscriptExpr struct { Address string @@ -25,10 +29,10 @@ func parseArraySubscriptExpr(line string) *ArraySubscriptExpr { } } -func (n *ArraySubscriptExpr) render(ast *Ast) (string, string) { +func (n *ArraySubscriptExpr) render(program *program.Program) (string, string) { children := n.Children - expression, _ := renderExpression(ast, children[0]) - index, _ := renderExpression(ast, children[1]) + expression, _ := renderExpression(program, children[0]) + index, _ := renderExpression(program, children[1]) src := fmt.Sprintf("%s[%s]", expression, index) return src, "unknown1" } diff --git a/ast/asm_label_attr.go b/ast/asm_label_attr.go index 716bcfebb..fca98d5e8 100644 --- a/ast/asm_label_attr.go +++ b/ast/asm_label_attr.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type AsmLabelAttr struct { Address string Position string @@ -21,7 +25,7 @@ func parseAsmLabelAttr(line string) *AsmLabelAttr { } } -func (n *AsmLabelAttr) render(ast *Ast) (string, string) { +func (n *AsmLabelAttr) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/ast.go b/ast/ast.go index cc7e6809e..70d05a6ee 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -1,54 +1,16 @@ package ast import ( + "bytes" + "fmt" "regexp" "strings" -) - -type Ast struct { - imports []string - - // for rendering go src - functionName string - indent int - returnType string -} - -func NewAst() *Ast { - return &Ast{ - imports: []string{"fmt"}, - } -} - -func (a *Ast) Imports() []string { - return a.imports -} - -func (a *Ast) addImport(name string) { - for _, i := range a.imports { - if i == name { - // already imported - return - } - } - - a.imports = append(a.imports, name) -} - -func (a *Ast) importType(name string) string { - if strings.Index(name, ".") != -1 { - parts := strings.Split(name, ".") - a.addImport(strings.Join(parts[:len(parts)-1], ".")) - - parts2 := strings.Split(name, "/") - return parts2[len(parts2)-1] - } - return name -} + "github.com/elliotchance/c2go/program" +) type Node interface { - render(ast *Ast) (string, string) + render(program *program.Program) (string, string) AddChild(node Node) } @@ -195,3 +157,45 @@ func groupsFromRegex(rx, line string) map[string]string { return result } + +func printLine(out *bytes.Buffer, line string, indent int) { + out.WriteString(fmt.Sprintf("%s%s\n", strings.Repeat("\t", indent), line)) +} + +func Render(program *program.Program, node Node) string { + src, _ := node.render(program) + return src +} + +func renderExpression(program *program.Program, node Node) (string, string) { + if node == nil { + return "", "unknown54" + } + + return node.render(program) +} + +func getFunctionParams(f *FunctionDecl) []*ParmVarDecl { + r := []*ParmVarDecl{} + for _, n := range f.Children { + if v, ok := n.(*ParmVarDecl); ok { + r = append(r, v) + } + } + + return r +} + +func getFunctionReturnType(f string) string { + // The type of the function will be the complete prototype, like: + // + // __inline_isfinitef(float) int + // + // will have a type of: + // + // int (float) + // + // The arguments will handle themselves, we only care about the + // return type ('int' in this case) + return strings.TrimSpace(strings.Split(f, "(")[0]) +} diff --git a/ast/availability_attr.go b/ast/availability_attr.go index 6451bf916..808b27cec 100644 --- a/ast/availability_attr.go +++ b/ast/availability_attr.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type AvailabilityAttr struct { Address string Position string @@ -40,7 +44,7 @@ func parseAvailabilityAttr(line string) *AvailabilityAttr { } } -func (n *AvailabilityAttr) render(ast *Ast) (string, string) { +func (n *AvailabilityAttr) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/binary_operator.go b/ast/binary_operator.go index 220c86bfb..2a1a52282 100644 --- a/ast/binary_operator.go +++ b/ast/binary_operator.go @@ -1,6 +1,12 @@ package ast -import "fmt" +import ( + "fmt" + + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/types" + "github.com/elliotchance/c2go/util" +) type BinaryOperator struct { Address string @@ -25,21 +31,21 @@ func parseBinaryOperator(line string) *BinaryOperator { } } -func (n *BinaryOperator) render(ast *Ast) (string, string) { +func (n *BinaryOperator) render(program *program.Program) (string, string) { operator := n.Operator - left, leftType := renderExpression(ast, n.Children[0]) - right, rightType := renderExpression(ast, n.Children[1]) + left, leftType := renderExpression(program, n.Children[0]) + right, rightType := renderExpression(program, n.Children[1]) return_type := "bool" - if inStrings(operator, []string{"|", "&", "+", "-", "*", "/"}) { + if util.InStrings(operator, []string{"|", "&", "+", "-", "*", "/"}) { // TODO: The left and right type might be different return_type = leftType } if operator == "&&" { - left = cast(ast, left, leftType, return_type) - right = cast(ast, right, rightType, return_type) + left = types.Cast(program, left, leftType, return_type) + right = types.Cast(program, right, rightType, return_type) } if (operator == "!=" || operator == "==") && right == "(0)" { diff --git a/ast/break_stmt.go b/ast/break_stmt.go index 394bf7ace..91127379b 100644 --- a/ast/break_stmt.go +++ b/ast/break_stmt.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type BreakStmt struct { Address string Position string @@ -19,7 +23,7 @@ func parseBreakStmt(line string) *BreakStmt { } } -func (n *BreakStmt) render(ast *Ast) (string, string) { +func (n *BreakStmt) render(program *program.Program) (string, string) { return "break", "" } diff --git a/ast/builtin_type.go b/ast/builtin_type.go index afae81923..37d96622f 100644 --- a/ast/builtin_type.go +++ b/ast/builtin_type.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type BuiltinType struct { Address string Type string @@ -19,7 +23,7 @@ func parseBuiltinType(line string) *BuiltinType { } } -func (n *BuiltinType) render(ast *Ast) (string, string) { +func (n *BuiltinType) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/c_style_cast_expr.go b/ast/c_style_cast_expr.go index b2e58fc61..8cc8c1f25 100644 --- a/ast/c_style_cast_expr.go +++ b/ast/c_style_cast_expr.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type CStyleCastExpr struct { Address string Position string @@ -23,9 +27,9 @@ func parseCStyleCastExpr(line string) *CStyleCastExpr { } } -func (n *CStyleCastExpr) render(ast *Ast) (string, string) { +func (n *CStyleCastExpr) render(program *program.Program) (string, string) { children := n.Children - return renderExpression(ast, children[0]) + return renderExpression(program, children[0]) } func (n *CStyleCastExpr) AddChild(node Node) { diff --git a/ast/call_expr.go b/ast/call_expr.go index 33eabab48..c78acb042 100644 --- a/ast/call_expr.go +++ b/ast/call_expr.go @@ -3,6 +3,9 @@ package ast import ( "fmt" "strings" + + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/types" ) type CallExpr struct { @@ -26,15 +29,15 @@ func parseCallExpr(line string) *CallExpr { } } -func (n *CallExpr) render(ast *Ast) (string, string) { +func (n *CallExpr) render(program *program.Program) (string, string) { children := n.Children - func_name, _ := renderExpression(ast, children[0]) + func_name, _ := renderExpression(program, children[0]) func_def := getFunctionDefinition(func_name) if func_def.Substitution != "" { parts := strings.Split(func_def.Substitution, ".") - ast.addImport(strings.Join(parts[:len(parts)-1], ".")) + program.AddImport(strings.Join(parts[:len(parts)-1], ".")) parts2 := strings.Split(func_def.Substitution, "/") func_name = parts2[len(parts2)-1] @@ -43,7 +46,7 @@ func (n *CallExpr) render(ast *Ast) (string, string) { args := []string{} i := 0 for _, arg := range children[1:] { - e, eType := renderExpression(ast, arg) + e, eType := renderExpression(program, arg) if i > len(func_def.ArgumentTypes)-1 { // This means the argument is one of the varargs @@ -51,7 +54,7 @@ func (n *CallExpr) render(ast *Ast) (string, string) { // cast to. args = append(args, e) } else { - args = append(args, cast(ast, e, eType, func_def.ArgumentTypes[i])) + args = append(args, types.Cast(program, e, eType, func_def.ArgumentTypes[i])) } i++ diff --git a/ast/cast.go b/ast/cast.go deleted file mode 100644 index bb21f942c..000000000 --- a/ast/cast.go +++ /dev/null @@ -1,32 +0,0 @@ -package ast - -import "fmt" - -func cast(ast *Ast, expr, fromType, toType string) string { - fromType = resolveType(ast, fromType) - toType = resolveType(ast, toType) - - if fromType == toType { - return expr - } - - types := []string{"int", "int64", "uint32", "__darwin_ct_rune_t", - "byte", "float32", "float64"} - - for _, v := range types { - if fromType == v && toType == "bool" { - return fmt.Sprintf("%s != 0", expr) - } - } - - if fromType == "*int" && toType == "bool" { - return fmt.Sprintf("%s != nil", expr) - } - - if inStrings(fromType, types) && inStrings(toType, types) { - return fmt.Sprintf("%s(%s)", toType, expr) - } - - ast.addImport("github.com/elliotchance/c2go/noarch") - return fmt.Sprintf("noarch.%sTo%s(%s)", ucfirst(fromType), ucfirst(toType), expr) -} diff --git a/ast/character_literal.go b/ast/character_literal.go index a4cc6d3eb..83417e2d9 100644 --- a/ast/character_literal.go +++ b/ast/character_literal.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type CharacterLiteral struct { Address string Position string @@ -23,7 +27,7 @@ func parseCharacterLiteral(line string) *CharacterLiteral { } } -func (n *CharacterLiteral) render(ast *Ast) (string, string) { +func (n *CharacterLiteral) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/common.go b/ast/common.go deleted file mode 100644 index 903f54a81..000000000 --- a/ast/common.go +++ /dev/null @@ -1,49 +0,0 @@ -package ast - -import ( - "bytes" - "fmt" - "strings" -) - -func printLine(out *bytes.Buffer, line string, indent int) { - out.WriteString(fmt.Sprintf("%s%s\n", strings.Repeat("\t", indent), line)) -} - -func Render(ast *Ast, node Node) string { - src, _ := node.render(ast) - return src -} - -func renderExpression(ast *Ast, node Node) (string, string) { - if node == nil { - return "", "unknown54" - } - - return node.render(ast) -} - -func getFunctionParams(f *FunctionDecl) []*ParmVarDecl { - r := []*ParmVarDecl{} - for _, n := range f.Children { - if v, ok := n.(*ParmVarDecl); ok { - r = append(r, v) - } - } - - return r -} - -func getFunctionReturnType(f string) string { - // The type of the function will be the complete prototype, like: - // - // __inline_isfinitef(float) int - // - // will have a type of: - // - // int (float) - // - // The arguments will handle themselves, we only care about the - // return type ('int' in this case) - return strings.TrimSpace(strings.Split(f, "(")[0]) -} diff --git a/ast/compound_stmt.go b/ast/compound_stmt.go index 6d7feacd0..5c33d44b4 100644 --- a/ast/compound_stmt.go +++ b/ast/compound_stmt.go @@ -1,6 +1,10 @@ package ast -import "bytes" +import ( + "bytes" + + "github.com/elliotchance/c2go/program" +) type CompoundStmt struct { Address string @@ -21,12 +25,12 @@ func parseCompoundStmt(line string) *CompoundStmt { } } -func (n *CompoundStmt) render(ast *Ast) (string, string) { +func (n *CompoundStmt) render(program *program.Program) (string, string) { out := bytes.NewBuffer([]byte{}) for _, c := range n.Children { - src, _ := renderExpression(ast, c) - printLine(out, src, ast.indent) + src, _ := renderExpression(program, c) + printLine(out, src, program.Indent) } return out.String(), "" diff --git a/ast/conditional_operator.go b/ast/conditional_operator.go index c06f13048..1191ce216 100644 --- a/ast/conditional_operator.go +++ b/ast/conditional_operator.go @@ -1,6 +1,10 @@ package ast -import "fmt" +import ( + "fmt" + + "github.com/elliotchance/c2go/program" +) type ConditionalOperator struct { Address string @@ -23,12 +27,12 @@ func parseConditionalOperator(line string) *ConditionalOperator { } } -func (n *ConditionalOperator) render(ast *Ast) (string, string) { - a, _ := renderExpression(ast, n.Children[0]) - b, _ := renderExpression(ast, n.Children[1]) - c, _ := renderExpression(ast, n.Children[2]) +func (n *ConditionalOperator) render(program *program.Program) (string, string) { + a, _ := renderExpression(program, n.Children[0]) + b, _ := renderExpression(program, n.Children[1]) + c, _ := renderExpression(program, n.Children[2]) - ast.addImport("github.com/elliotchance/c2go/noarch") + program.AddImport("github.com/elliotchance/c2go/noarch") src := fmt.Sprintf("noarch.Ternary(%s, func () interface{} { return %s }, func () interface{} { return %s })", a, b, c) return src, n.Type } diff --git a/ast/const_attr.go b/ast/const_attr.go index 019346205..619ce7717 100644 --- a/ast/const_attr.go +++ b/ast/const_attr.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type ConstAttr struct { Address string Position string @@ -21,7 +25,7 @@ func parseConstAttr(line string) *ConstAttr { } } -func (n *ConstAttr) render(ast *Ast) (string, string) { +func (n *ConstAttr) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/constant_array_type.go b/ast/constant_array_type.go index 3afdca646..27ef3f66d 100644 --- a/ast/constant_array_type.go +++ b/ast/constant_array_type.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type ConstantArrayType struct { Address string Type string @@ -21,7 +25,7 @@ func parseConstantArrayType(line string) *ConstantArrayType { } } -func (n *ConstantArrayType) render(ast *Ast) (string, string) { +func (n *ConstantArrayType) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/decl_ref_expr.go b/ast/decl_ref_expr.go index 2f759ec3e..829266894 100644 --- a/ast/decl_ref_expr.go +++ b/ast/decl_ref_expr.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type DeclRefExpr struct { Address string Position string @@ -38,15 +42,15 @@ func parseDeclRefExpr(line string) *DeclRefExpr { } } -func (n *DeclRefExpr) render(ast *Ast) (string, string) { +func (n *DeclRefExpr) render(program *program.Program) (string, string) { name := n.Name if name == "argc" { name = "len(os.Args)" - ast.addImport("os") + program.AddImport("os") } else if name == "argv" { name = "os.Args" - ast.addImport("os") + program.AddImport("os") } return name, n.Type diff --git a/ast/decl_stmt.go b/ast/decl_stmt.go index 7107b8f81..d06edb71c 100644 --- a/ast/decl_stmt.go +++ b/ast/decl_stmt.go @@ -1,6 +1,10 @@ package ast -import "bytes" +import ( + "bytes" + + "github.com/elliotchance/c2go/program" +) type DeclStmt struct { Address string @@ -21,12 +25,12 @@ func parseDeclStmt(line string) *DeclStmt { } } -func (n *DeclStmt) render(ast *Ast) (string, string) { +func (n *DeclStmt) render(program *program.Program) (string, string) { out := bytes.NewBuffer([]byte{}) for _, child := range n.Children { - src, _ := renderExpression(ast, child) - printLine(out, src, ast.indent) + src, _ := renderExpression(program, child) + printLine(out, src, program.Indent) } return out.String(), "" diff --git a/ast/deprecated_attr.go b/ast/deprecated_attr.go index f7e29860e..04fbc0722 100644 --- a/ast/deprecated_attr.go +++ b/ast/deprecated_attr.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type DeprecatedAttr struct { Address string Position string @@ -23,7 +27,7 @@ func parseDeprecatedAttr(line string) *DeprecatedAttr { } } -func (n *DeprecatedAttr) render(ast *Ast) (string, string) { +func (n *DeprecatedAttr) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/elaborated_type.go b/ast/elaborated_type.go index 440d38e98..14a9360ba 100644 --- a/ast/elaborated_type.go +++ b/ast/elaborated_type.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type ElaboratedType struct { Address string Type string @@ -21,7 +25,7 @@ func parseElaboratedType(line string) *ElaboratedType { } } -func (n *ElaboratedType) render(ast *Ast) (string, string) { +func (n *ElaboratedType) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/enum.go b/ast/enum.go index 504430d88..45e69a63a 100644 --- a/ast/enum.go +++ b/ast/enum.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type Enum struct { Address string Name string @@ -19,7 +23,7 @@ func parseEnum(line string) *Enum { } } -func (n *Enum) render(ast *Ast) (string, string) { +func (n *Enum) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/enum_constant_decl.go b/ast/enum_constant_decl.go index 178dc7fd1..d64022877 100644 --- a/ast/enum_constant_decl.go +++ b/ast/enum_constant_decl.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type EnumConstantDecl struct { Address string Position string @@ -28,7 +32,7 @@ func parseEnumConstantDecl(line string) *EnumConstantDecl { } } -func (n *EnumConstantDecl) render(ast *Ast) (string, string) { +func (n *EnumConstantDecl) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/enum_decl.go b/ast/enum_decl.go index a81d176e5..b4de19402 100644 --- a/ast/enum_decl.go +++ b/ast/enum_decl.go @@ -1,6 +1,10 @@ package ast -import "strings" +import ( + "strings" + + "github.com/elliotchance/c2go/program" +) type EnumDecl struct { Address string @@ -25,7 +29,7 @@ func parseEnumDecl(line string) *EnumDecl { } } -func (n *EnumDecl) render(ast *Ast) (string, string) { +func (n *EnumDecl) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/enum_type.go b/ast/enum_type.go index 573fa3077..e107c09a6 100644 --- a/ast/enum_type.go +++ b/ast/enum_type.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type EnumType struct { Address string Name string @@ -19,7 +23,7 @@ func parseEnumType(line string) *EnumType { } } -func (n *EnumType) render(ast *Ast) (string, string) { +func (n *EnumType) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/field_decl.go b/ast/field_decl.go index b3d301c34..20cd895ff 100644 --- a/ast/field_decl.go +++ b/ast/field_decl.go @@ -3,6 +3,9 @@ package ast import ( "fmt" "strings" + + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/types" ) type FieldDecl struct { @@ -36,8 +39,8 @@ func parseFieldDecl(line string) *FieldDecl { } } -func (n *FieldDecl) render(ast *Ast) (string, string) { - fieldType := resolveType(ast, n.Type) +func (n *FieldDecl) render(program *program.Program) (string, string) { + fieldType := types.ResolveType(program, n.Type) name := n.Name //if name == "" { @@ -53,7 +56,7 @@ func (n *FieldDecl) render(ast *Ast) (string, string) { // It may have a default value. suffix := "" if len(n.Children) > 0 { - src, _ := renderExpression(ast, n.Children[0]) + src, _ := renderExpression(program, n.Children[0]) suffix = fmt.Sprintf(" = %s", src) } diff --git a/ast/floating_literal.go b/ast/floating_literal.go index e914528da..dae16dc73 100644 --- a/ast/floating_literal.go +++ b/ast/floating_literal.go @@ -1,6 +1,10 @@ package ast -import "fmt" +import ( + "fmt" + + "github.com/elliotchance/c2go/program" +) type FloatingLiteral struct { Address string @@ -25,7 +29,7 @@ func parseFloatingLiteral(line string) *FloatingLiteral { } } -func (n *FloatingLiteral) render(ast *Ast) (string, string) { +func (n *FloatingLiteral) render(program *program.Program) (string, string) { return fmt.Sprintf("%f", n.Value), "double" } diff --git a/ast/for_stmt.go b/ast/for_stmt.go index 02a9d04b4..43a093dd9 100644 --- a/ast/for_stmt.go +++ b/ast/for_stmt.go @@ -3,6 +3,8 @@ package ast import ( "bytes" "fmt" + + "github.com/elliotchance/c2go/program" ) type ForStmt struct { @@ -24,7 +26,7 @@ func parseForStmt(line string) *ForStmt { } } -func (n *ForStmt) render(ast *Ast) (string, string) { +func (n *ForStmt) render(program *program.Program) (string, string) { out := bytes.NewBuffer([]byte{}) children := n.Children @@ -52,20 +54,20 @@ func (n *ForStmt) render(ast *Ast) (string, string) { panic("non-nil child 1 in ForStmt") } - init, _ := renderExpression(ast, children[0]) - conditional, _ := renderExpression(ast, children[2]) - step, _ := renderExpression(ast, children[3]) - body, _ := renderExpression(ast, children[4]) + init, _ := renderExpression(program, children[0]) + conditional, _ := renderExpression(program, children[2]) + step, _ := renderExpression(program, children[3]) + body, _ := renderExpression(program, children[4]) if init == "" && conditional == "" && step == "" { - printLine(out, "for {", ast.indent) + printLine(out, "for {", program.Indent) } else { printLine(out, fmt.Sprintf("for %s; %s; %s {", - init, conditional, step), ast.indent) + init, conditional, step), program.Indent) } - printLine(out, body, ast.indent+1) - printLine(out, "}", ast.indent) + printLine(out, body, program.Indent+1) + printLine(out, "}", program.Indent) return out.String(), "" } diff --git a/ast/format_attr.go b/ast/format_attr.go index 3e1c5f1d4..b9dc9327c 100644 --- a/ast/format_attr.go +++ b/ast/format_attr.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type FormatAttr struct { Address string Position string @@ -34,7 +38,7 @@ func parseFormatAttr(line string) *FormatAttr { } } -func (n *FormatAttr) render(ast *Ast) (string, string) { +func (n *FormatAttr) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/function_decl.go b/ast/function_decl.go index 7d43acecc..0f3d35cd2 100644 --- a/ast/function_decl.go +++ b/ast/function_decl.go @@ -4,6 +4,9 @@ import ( "bytes" "fmt" "strings" + + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/types" ) type FunctionDecl struct { @@ -51,18 +54,18 @@ func parseFunctionDecl(line string) *FunctionDecl { } } -func (n *FunctionDecl) render(ast *Ast) (string, string) { +func (n *FunctionDecl) render(program *program.Program) (string, string) { out := bytes.NewBuffer([]byte{}) - ast.functionName = n.Name + program.FunctionName = n.Name - if ast.functionName == "__istype" || - ast.functionName == "__isctype" || - ast.functionName == "__wcwidth" || - ast.functionName == "__sputc" || - ast.functionName == "__inline_signbitf" || - ast.functionName == "__inline_signbitd" || - ast.functionName == "__inline_signbitl" { + if program.FunctionName == "__istype" || + program.FunctionName == "__isctype" || + program.FunctionName == "__wcwidth" || + program.FunctionName == "__sputc" || + program.FunctionName == "__inline_signbitf" || + program.FunctionName == "__inline_signbitd" || + program.FunctionName == "__inline_signbitl" { return "", "" } @@ -77,28 +80,28 @@ func (n *FunctionDecl) render(ast *Ast) (string, string) { args := []string{} for _, a := range getFunctionParams(n) { - args = append(args, fmt.Sprintf("%s %s", a.Name, resolveType(ast, a.Type))) + args = append(args, fmt.Sprintf("%s %s", a.Name, types.ResolveType(program, a.Type))) } if hasBody { returnType := getFunctionReturnType(n.Type) - if ast.functionName == "main" { - printLine(out, "func main() {", ast.indent) + if program.FunctionName == "main" { + printLine(out, "func main() {", program.Indent) } else { printLine(out, fmt.Sprintf("func %s(%s) %s {", - ast.functionName, strings.Join(args, ", "), - resolveType(ast, returnType)), ast.indent) + program.FunctionName, strings.Join(args, ", "), + types.ResolveType(program, returnType)), program.Indent) } for _, c := range n.Children { if _, ok := c.(*CompoundStmt); ok { - src, _ := renderExpression(ast, c) - printLine(out, src, ast.indent+1) + src, _ := renderExpression(program, c) + printLine(out, src, program.Indent+1) } } - printLine(out, "}\n", ast.indent) + printLine(out, "}\n", program.Indent) params := []string{} for _, v := range getFunctionParams(n) { diff --git a/ast/function_proto_type.go b/ast/function_proto_type.go index cfc0ed5d1..827799882 100644 --- a/ast/function_proto_type.go +++ b/ast/function_proto_type.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type FunctionProtoType struct { Address string Type string @@ -21,7 +25,7 @@ func parseFunctionProtoType(line string) *FunctionProtoType { } } -func (n *FunctionProtoType) render(ast *Ast) (string, string) { +func (n *FunctionProtoType) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/if_stmt.go b/ast/if_stmt.go index c734e2864..54b70dbfa 100644 --- a/ast/if_stmt.go +++ b/ast/if_stmt.go @@ -3,6 +3,9 @@ package ast import ( "bytes" "fmt" + + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/types" ) type IfStmt struct { @@ -24,7 +27,7 @@ func parseIfStmt(line string) *IfStmt { } } -func (n *IfStmt) render(ast *Ast) (string, string) { +func (n *IfStmt) render(program *program.Program) (string, string) { out := bytes.NewBuffer([]byte{}) children := n.Children @@ -65,22 +68,22 @@ func (n *IfStmt) render(ast *Ast) (string, string) { panic("non-nil child 0 in ForStmt") } - conditional, conditionalType := renderExpression(ast, children[1]) + conditional, conditionalType := renderExpression(program, children[1]) // The condition in Go must always be a bool. - boolCondition := cast(ast, conditional, conditionalType, "bool") + boolCondition := types.Cast(program, conditional, conditionalType, "bool") - printLine(out, fmt.Sprintf("if %s {", boolCondition), ast.indent) - body, _ := renderExpression(ast, children[2]) - printLine(out, body, ast.indent+1) + printLine(out, fmt.Sprintf("if %s {", boolCondition), program.Indent) + body, _ := renderExpression(program, children[2]) + printLine(out, body, program.Indent+1) if children[3] != nil { - printLine(out, "} else {", ast.indent) - body, _ := renderExpression(ast, children[3]) - printLine(out, body, ast.indent+1) + printLine(out, "} else {", program.Indent) + body, _ := renderExpression(program, children[3]) + printLine(out, body, program.Indent+1) } - printLine(out, "}", ast.indent) + printLine(out, "}", program.Indent) return out.String(), "" } diff --git a/ast/implicit_cast_expr.go b/ast/implicit_cast_expr.go index ec0955a33..27c776319 100644 --- a/ast/implicit_cast_expr.go +++ b/ast/implicit_cast_expr.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type ImplicitCastExpr struct { Address string Position string @@ -23,8 +27,8 @@ func parseImplicitCastExpr(line string) *ImplicitCastExpr { } } -func (n *ImplicitCastExpr) render(ast *Ast) (string, string) { - return renderExpression(ast, n.Children[0]) +func (n *ImplicitCastExpr) render(program *program.Program) (string, string) { + return renderExpression(program, n.Children[0]) } func (n *ImplicitCastExpr) AddChild(node Node) { diff --git a/ast/integer_literal.go b/ast/integer_literal.go index 09a319165..7e6329656 100644 --- a/ast/integer_literal.go +++ b/ast/integer_literal.go @@ -1,6 +1,10 @@ package ast -import "strconv" +import ( + "strconv" + + "github.com/elliotchance/c2go/program" +) type IntegerLiteral struct { Address string @@ -25,7 +29,7 @@ func parseIntegerLiteral(line string) *IntegerLiteral { } } -func (n *IntegerLiteral) render(ast *Ast) (string, string) { +func (n *IntegerLiteral) render(program *program.Program) (string, string) { literal := n.Value // FIXME diff --git a/ast/malloc_attr.go b/ast/malloc_attr.go index aa6e0f713..9bb1e0a7a 100644 --- a/ast/malloc_attr.go +++ b/ast/malloc_attr.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type MallocAttr struct { Address string Position string @@ -19,7 +23,7 @@ func parseMallocAttr(line string) *MallocAttr { } } -func (n *MallocAttr) render(ast *Ast) (string, string) { +func (n *MallocAttr) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/member_expr.go b/ast/member_expr.go index 4440dacfe..c0252b843 100644 --- a/ast/member_expr.go +++ b/ast/member_expr.go @@ -1,6 +1,12 @@ package ast -import "fmt" +import ( + "fmt" + + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/types" + "github.com/elliotchance/c2go/util" +) type MemberExpr struct { Address string @@ -33,14 +39,14 @@ func parseMemberExpr(line string) *MemberExpr { } } -func (n *MemberExpr) render(ast *Ast) (string, string) { +func (n *MemberExpr) render(program *program.Program) (string, string) { children := n.Children - lhs, lhsType := renderExpression(ast, children[0]) - lhsResolvedType := resolveType(ast, lhsType) + lhs, lhsType := renderExpression(program, children[0]) + lhsResolvedType := types.ResolveType(program, lhsType) rhs := n.Name - if inStrings(lhsResolvedType, []string{"darwin.Float2", "darwin.Double2"}) { + if util.InStrings(lhsResolvedType, []string{"darwin.Float2", "darwin.Double2"}) { rhs = getExportedName(rhs) } diff --git a/ast/mode_attr.go b/ast/mode_attr.go index 417b080e6..d3c1ca0f1 100644 --- a/ast/mode_attr.go +++ b/ast/mode_attr.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type ModeAttr struct { Address string Position string @@ -21,7 +25,7 @@ func parseModeAttr(line string) *ModeAttr { } } -func (n *ModeAttr) render(ast *Ast) (string, string) { +func (n *ModeAttr) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/no_throw_attr.go b/ast/no_throw_attr.go index ab31f9172..01806ca8a 100644 --- a/ast/no_throw_attr.go +++ b/ast/no_throw_attr.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type NoThrowAttr struct { Address string Position string @@ -19,7 +23,7 @@ func parseNoThrowAttr(line string) *NoThrowAttr { } } -func (n *NoThrowAttr) render(ast *Ast) (string, string) { +func (n *NoThrowAttr) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/non_null_attr.go b/ast/non_null_attr.go index b38755e29..f9384444d 100644 --- a/ast/non_null_attr.go +++ b/ast/non_null_attr.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type NonNullAttr struct { Address string Position string @@ -19,7 +23,7 @@ func parseNonNullAttr(line string) *NonNullAttr { } } -func (n *NonNullAttr) render(ast *Ast) (string, string) { +func (n *NonNullAttr) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/paren_expr.go b/ast/paren_expr.go index e327482ed..4c6214ca9 100644 --- a/ast/paren_expr.go +++ b/ast/paren_expr.go @@ -1,6 +1,10 @@ package ast -import "fmt" +import ( + "fmt" + + "github.com/elliotchance/c2go/program" +) type ParenExpr struct { Address string @@ -23,8 +27,8 @@ func parseParenExpr(line string) *ParenExpr { } } -func (n *ParenExpr) render(ast *Ast) (string, string) { - a, aType := renderExpression(ast, n.Children[0]) +func (n *ParenExpr) render(program *program.Program) (string, string) { + a, aType := renderExpression(program, n.Children[0]) src := fmt.Sprintf("(%s)", a) return src, aType } diff --git a/ast/parm_var_decl.go b/ast/parm_var_decl.go index e94ed7898..58737b25e 100644 --- a/ast/parm_var_decl.go +++ b/ast/parm_var_decl.go @@ -1,6 +1,10 @@ package ast -import "strings" +import ( + "strings" + + "github.com/elliotchance/c2go/program" +) type ParmVarDecl struct { Address string @@ -46,7 +50,7 @@ func parseParmVarDecl(line string) *ParmVarDecl { } } -func (n *ParmVarDecl) render(ast *Ast) (string, string) { +func (n *ParmVarDecl) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/pointer_type.go b/ast/pointer_type.go index 0d039b2a4..8599ac00a 100644 --- a/ast/pointer_type.go +++ b/ast/pointer_type.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type PointerType struct { Address string Type string @@ -19,7 +23,7 @@ func parsePointerType(line string) *PointerType { } } -func (n *PointerType) render(ast *Ast) (string, string) { +func (n *PointerType) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/predefined_expr.go b/ast/predefined_expr.go index 73d238df7..ac8ac840c 100644 --- a/ast/predefined_expr.go +++ b/ast/predefined_expr.go @@ -1,6 +1,10 @@ package ast -import "fmt" +import ( + "fmt" + + "github.com/elliotchance/c2go/program" +) type PredefinedExpr struct { Address string @@ -27,7 +31,7 @@ func parsePredefinedExpr(line string) *PredefinedExpr { } } -func (n *PredefinedExpr) render(ast *Ast) (string, string) { +func (n *PredefinedExpr) render(program *program.Program) (string, string) { if n.Name == "__PRETTY_FUNCTION__" { // FIXME return "\"void print_number(int *)\"", "const char*" diff --git a/ast/qual_type.go b/ast/qual_type.go index 830234e46..680208ee8 100644 --- a/ast/qual_type.go +++ b/ast/qual_type.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type QualType struct { Address string Type string @@ -21,7 +25,7 @@ func parseQualType(line string) *QualType { } } -func (n *QualType) render(ast *Ast) (string, string) { +func (n *QualType) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/record.go b/ast/record.go index 69645b7df..42c3d4d4e 100644 --- a/ast/record.go +++ b/ast/record.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type Record struct { Address string Type string @@ -19,7 +23,7 @@ func parseRecord(line string) *Record { } } -func (n *Record) render(ast *Ast) (string, string) { +func (n *Record) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/record_decl.go b/ast/record_decl.go index 1f54b0f0f..887251853 100644 --- a/ast/record_decl.go +++ b/ast/record_decl.go @@ -4,6 +4,9 @@ import ( "bytes" "fmt" "strings" + + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/types" ) type RecordDecl struct { @@ -50,28 +53,28 @@ func parseRecordDecl(line string) *RecordDecl { } } -func (n *RecordDecl) render(ast *Ast) (string, string) { +func (n *RecordDecl) render(program *program.Program) (string, string) { out := bytes.NewBuffer([]byte{}) name := strings.TrimSpace(n.Name) - if name == "" || typeIsAlreadyDefined(name) { + if name == "" || types.TypeIsAlreadyDefined(name) { return "", "" } - typeIsNowDefined(name) + types.TypeIsNowDefined(name) if n.Kind == "union" { return "", "" } - printLine(out, fmt.Sprintf("type %s %s {", name, n.Kind), ast.indent) + printLine(out, fmt.Sprintf("type %s %s {", name, n.Kind), program.Indent) if len(n.Children) > 0 { for _, c := range n.Children { - src, _ := renderExpression(ast, c) - printLine(out, src, ast.indent) + src, _ := renderExpression(program, c) + printLine(out, src, program.Indent) } } - printLine(out, "}\n", ast.indent) + printLine(out, "}\n", program.Indent) return out.String(), "" } diff --git a/ast/record_type.go b/ast/record_type.go index 9a9ec4676..d276bc37d 100644 --- a/ast/record_type.go +++ b/ast/record_type.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type RecordType struct { Address string Type string @@ -19,7 +23,7 @@ func parseRecordType(line string) *RecordType { } } -func (n *RecordType) render(ast *Ast) (string, string) { +func (n *RecordType) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/restrict_attr.go b/ast/restrict_attr.go index 300ac6c7d..77f190855 100644 --- a/ast/restrict_attr.go +++ b/ast/restrict_attr.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type RestrictAttr struct { Address string Position string @@ -21,7 +25,7 @@ func parseRestrictAttr(line string) *RestrictAttr { } } -func (n *RestrictAttr) render(ast *Ast) (string, string) { +func (n *RestrictAttr) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/return_stmt.go b/ast/return_stmt.go index a051a4d2d..6968cabfd 100644 --- a/ast/return_stmt.go +++ b/ast/return_stmt.go @@ -2,6 +2,9 @@ package ast import ( "bytes" + + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/types" ) type ReturnStmt struct { @@ -23,16 +26,16 @@ func parseReturnStmt(line string) *ReturnStmt { } } -func (n *ReturnStmt) render(ast *Ast) (string, string) { +func (n *ReturnStmt) render(program *program.Program) (string, string) { out := bytes.NewBuffer([]byte{}) r := "return" - if len(n.Children) > 0 && ast.functionName != "main" { - re, reType := renderExpression(ast, n.Children[0]) - r = "return " + cast(ast, re, reType, "int") + if len(n.Children) > 0 && program.FunctionName != "main" { + re, reType := renderExpression(program, n.Children[0]) + r = "return " + types.Cast(program, re, reType, "int") } - printLine(out, r, ast.indent) + printLine(out, r, program.Indent) return out.String(), "" } diff --git a/ast/string_literal.go b/ast/string_literal.go index 1d2d37f1f..4a4c284e0 100644 --- a/ast/string_literal.go +++ b/ast/string_literal.go @@ -3,6 +3,8 @@ package ast import ( "fmt" "strings" + + "github.com/elliotchance/c2go/program" ) type StringLiteral struct { @@ -30,7 +32,7 @@ func parseStringLiteral(line string) *StringLiteral { } } -func (n *StringLiteral) render(ast *Ast) (string, string) { +func (n *StringLiteral) render(program *program.Program) (string, string) { src := fmt.Sprintf("\"%s\"", strings.Replace(n.Value, "\n", "\\n", -1)) return src, "const char *" } diff --git a/ast/translation_unit_decl.go b/ast/translation_unit_decl.go index 4326e7729..7a630a9ad 100644 --- a/ast/translation_unit_decl.go +++ b/ast/translation_unit_decl.go @@ -2,6 +2,8 @@ package ast import ( "bytes" + + "github.com/elliotchance/c2go/program" ) type TranslationUnitDecl struct { @@ -18,11 +20,11 @@ func parseTranslationUnitDecl(line string) *TranslationUnitDecl { } } -func (n *TranslationUnitDecl) render(ast *Ast) (string, string) { +func (n *TranslationUnitDecl) render(program *program.Program) (string, string) { out := bytes.NewBuffer([]byte{}) for _, c := range n.Children { - src, _ := renderExpression(ast, c) - printLine(out, src, ast.indent) + src, _ := renderExpression(program, c) + printLine(out, src, program.Indent) } return out.String(), "" diff --git a/ast/typedef.go b/ast/typedef.go index 28e5df5a9..f8e6a1b0d 100644 --- a/ast/typedef.go +++ b/ast/typedef.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type Typedef struct { Address string Type string @@ -19,7 +23,7 @@ func parseTypedef(line string) *Typedef { } } -func (n *Typedef) render(ast *Ast) (string, string) { +func (n *Typedef) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/typedef_decl.go b/ast/typedef_decl.go index 391da9e8a..a9827bd56 100644 --- a/ast/typedef_decl.go +++ b/ast/typedef_decl.go @@ -4,6 +4,9 @@ import ( "bytes" "fmt" "strings" + + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/types" ) type TypedefDecl struct { @@ -48,15 +51,15 @@ func parseTypedefDecl(line string) *TypedefDecl { } } -func (n *TypedefDecl) render(ast *Ast) (string, string) { +func (n *TypedefDecl) render(program *program.Program) (string, string) { out := bytes.NewBuffer([]byte{}) name := strings.TrimSpace(n.Name) - if typeIsAlreadyDefined(name) { + if types.TypeIsAlreadyDefined(name) { return "", "" } - typeIsNowDefined(name) + types.TypeIsNowDefined(name) // FIXME: All of the logic here is just to avoid errors, it // needs to be fixed up. @@ -64,15 +67,15 @@ func (n *TypedefDecl) render(ast *Ast) (string, string) { // return n.Type = strings.Replace(n.Type, "unsigned", "", -1) - resolvedType := resolveType(ast, n.Type) + resolvedType := types.ResolveType(program, n.Type) if name == "__mbstate_t" { - ast.addImport("github.com/elliotchance/c2go/darwin") + program.AddImport("github.com/elliotchance/c2go/darwin") resolvedType = "darwin.C__mbstate_t" } if name == "__darwin_ct_rune_t" { - ast.addImport("github.com/elliotchance/c2go/darwin") + program.AddImport("github.com/elliotchance/c2go/darwin") resolvedType = "darwin.C__darwin_ct_rune_t" } @@ -82,7 +85,7 @@ func (n *TypedefDecl) render(ast *Ast) (string, string) { return "", "" } - printLine(out, fmt.Sprintf("type %s %s\n", name, resolvedType), ast.indent) + printLine(out, fmt.Sprintf("type %s %s\n", name, resolvedType), program.Indent) return out.String(), "" } diff --git a/ast/typedef_type.go b/ast/typedef_type.go index b380796a8..c25601bf4 100644 --- a/ast/typedef_type.go +++ b/ast/typedef_type.go @@ -1,5 +1,9 @@ package ast +import ( + "github.com/elliotchance/c2go/program" +) + type TypedefType struct { Address string Type string @@ -21,7 +25,7 @@ func parseTypedefType(line string) *TypedefType { } } -func (n *TypedefType) render(ast *Ast) (string, string) { +func (n *TypedefType) render(program *program.Program) (string, string) { return "", "" } diff --git a/ast/unary_operator.go b/ast/unary_operator.go index c06a77e86..46c1decb4 100644 --- a/ast/unary_operator.go +++ b/ast/unary_operator.go @@ -1,6 +1,11 @@ package ast -import "fmt" +import ( + "fmt" + + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/util" +) type UnaryOperator struct { Address string @@ -34,17 +39,17 @@ func parseUnaryOperator(line string) *UnaryOperator { } } -func (n *UnaryOperator) render(ast *Ast) (string, string) { +func (n *UnaryOperator) render(program *program.Program) (string, string) { operator := n.Operator - expr, exprType := renderExpression(ast, n.Children[0]) + expr, exprType := renderExpression(program, n.Children[0]) if operator == "!" { if exprType == "bool" { return fmt.Sprintf("!(%s)", expr), exprType } - ast.addImport("github.com/elliotchance/c2go/noarch") - return fmt.Sprintf("%s(%s)", fmt.Sprintf("noarch.Not%s", ucfirst(exprType)), expr), exprType + program.AddImport("github.com/elliotchance/c2go/noarch") + return fmt.Sprintf("%s(%s)", fmt.Sprintf("noarch.Not%s", util.Ucfirst(exprType)), expr), exprType } if operator == "*" { diff --git a/ast/util.go b/ast/util.go index 1af1e304b..ba28e5931 100644 --- a/ast/util.go +++ b/ast/util.go @@ -3,24 +3,12 @@ package ast import ( "strconv" "strings" -) -func ucfirst(word string) string { - return strings.ToUpper(string(word[0])) + word[1:] -} + "github.com/elliotchance/c2go/util" +) func getExportedName(field string) string { - return ucfirst(strings.TrimLeft(field, "_")) -} - -func inStrings(item string, items []string) bool { - for _, v := range items { - if item == v { - return true - } - } - - return false + return util.Ucfirst(strings.TrimLeft(field, "_")) } func atoi(s string) int { diff --git a/ast/var_decl.go b/ast/var_decl.go index ace904fdb..b02db10f3 100644 --- a/ast/var_decl.go +++ b/ast/var_decl.go @@ -3,6 +3,9 @@ package ast import ( "fmt" "strings" + + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/types" ) type VarDecl struct { @@ -49,8 +52,8 @@ func parseVarDecl(line string) *VarDecl { } } -func (n *VarDecl) render(ast *Ast) (string, string) { - theType := resolveType(ast, n.Type) +func (n *VarDecl) render(program *program.Program) (string, string) { + theType := types.ResolveType(program, n.Type) name := n.Name // FIXME: These names dont seem to work when testing more than 1 file @@ -73,7 +76,7 @@ func (n *VarDecl) render(ast *Ast) (string, string) { suffix := "" if len(n.Children) > 0 { children := n.Children - src, _ := renderExpression(ast, children[0]) + src, _ := renderExpression(program, children[0]) suffix = fmt.Sprintf(" = %s", src) } diff --git a/ast/while_stmt.go b/ast/while_stmt.go index fe8b3c0bb..68170c8a7 100644 --- a/ast/while_stmt.go +++ b/ast/while_stmt.go @@ -3,6 +3,9 @@ package ast import ( "bytes" "fmt" + + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/types" ) type WhileStmt struct { @@ -24,19 +27,19 @@ func parseWhileStmt(line string) *WhileStmt { } } -func (n *WhileStmt) render(ast *Ast) (string, string) { +func (n *WhileStmt) render(program *program.Program) (string, string) { out := bytes.NewBuffer([]byte{}) // TODO: The first child of a WhileStmt appears to always be null. // Are there any cases where it is used? children := n.Children[1:] - e, eType := renderExpression(ast, children[0]) - printLine(out, fmt.Sprintf("for %s {", cast(ast, e, eType, "bool")), ast.indent) + e, eType := renderExpression(program, children[0]) + printLine(out, fmt.Sprintf("for %s {", types.Cast(program, e, eType, "bool")), program.Indent) - body, _ := renderExpression(ast, children[1]) - printLine(out, body, ast.indent+1) + body, _ := renderExpression(program, children[1]) + printLine(out, body, program.Indent+1) - printLine(out, "}", ast.indent) + printLine(out, "}", program.Indent) return out.String(), "" } diff --git a/main.go b/main.go index 7f7ccb759..8b96480d0 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,7 @@ import ( "go/format" "github.com/elliotchance/c2go/ast" + "github.com/elliotchance/c2go/program" ) var ( @@ -166,8 +167,8 @@ func Start(args []string) string { //go_file_path := fmt.Sprintf("%s.go", parts[len(parts) - 1][:len(parts) - 2]) // Render(go_out, tree[0], "", 0, "") - astTree := ast.NewAst() - goOut := ast.Render(astTree, tree[0].(ast.Node)) + p := program.NewProgram() + goOut := ast.Render(p, tree[0].(ast.Node)) // Format the code goOutFmt, err := format.Source([]byte(goOut)) @@ -178,7 +179,7 @@ func Start(args []string) string { // Put together the whole file all := "package main\n\nimport (\n" - for _, importName := range astTree.Imports() { + for _, importName := range p.Imports() { all += fmt.Sprintf("\t\"%s\"\n", importName) } diff --git a/program/program.go b/program/program.go new file mode 100644 index 000000000..3369d6b87 --- /dev/null +++ b/program/program.go @@ -0,0 +1,47 @@ +package program + +import ( + "strings" +) + +type Program struct { + imports []string + + // for rendering go src + FunctionName string + Indent int + ReturnType string +} + +func NewProgram() *Program { + return &Program{ + imports: []string{"fmt"}, + } +} + +func (a *Program) Imports() []string { + return a.imports +} + +func (a *Program) AddImport(name string) { + for _, i := range a.imports { + if i == name { + // already imported + return + } + } + + a.imports = append(a.imports, name) +} + +func (a *Program) ImportType(name string) string { + if strings.Index(name, ".") != -1 { + parts := strings.Split(name, ".") + a.AddImport(strings.Join(parts[:len(parts)-1], ".")) + + parts2 := strings.Split(name, "/") + return parts2[len(parts2)-1] + } + + return name +} diff --git a/types/cast.go b/types/cast.go new file mode 100644 index 000000000..8d7b269f5 --- /dev/null +++ b/types/cast.go @@ -0,0 +1,37 @@ +package types + +import ( + "fmt" + + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/util" +) + +func Cast(program *program.Program, expr, fromType, toType string) string { + fromType = ResolveType(program, fromType) + toType = ResolveType(program, toType) + + if fromType == toType { + return expr + } + + types := []string{"int", "int64", "uint32", "__darwin_ct_rune_t", + "byte", "float32", "float64"} + + for _, v := range types { + if fromType == v && toType == "bool" { + return fmt.Sprintf("%s != 0", expr) + } + } + + if fromType == "*int" && toType == "bool" { + return fmt.Sprintf("%s != nil", expr) + } + + if util.InStrings(fromType, types) && util.InStrings(toType, types) { + return fmt.Sprintf("%s(%s)", toType, expr) + } + + program.AddImport("github.com/elliotchance/c2go/noarch") + return fmt.Sprintf("noarch.%sTo%s(%s)", util.Ucfirst(fromType), util.Ucfirst(toType), expr) +} diff --git a/ast/resolve.go b/types/resolve.go similarity index 83% rename from ast/resolve.go rename to types/resolve.go index 6f47f4ac8..c087c8120 100644 --- a/ast/resolve.go +++ b/types/resolve.go @@ -1,9 +1,12 @@ -package ast +package types import ( "fmt" "regexp" "strings" + + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/util" ) // TODO: Some of these are based on assumptions that may not be true for all @@ -66,15 +69,15 @@ var TypesAlreadyDefined = []string{ "__double2", } -func typeIsAlreadyDefined(typeName string) bool { - return inStrings(typeName, TypesAlreadyDefined) +func TypeIsAlreadyDefined(typeName string) bool { + return util.InStrings(typeName, TypesAlreadyDefined) } -func typeIsNowDefined(typeName string) { +func TypeIsNowDefined(typeName string) { TypesAlreadyDefined = append(TypesAlreadyDefined, typeName) } -func resolveType(ast *Ast, s string) string { +func ResolveType(program *program.Program, s string) string { // Remove any whitespace or attributes that are not relevant to Go. s = strings.Replace(s, "const ", "", -1) s = strings.Replace(s, "*__restrict", "*", -1) @@ -93,14 +96,14 @@ func resolveType(ast *Ast, s string) string { // equivalent. For example float, int, etc. for k, v := range simpleResolveTypes { if k == s { - return ast.importType(v) + return program.ImportType(v) } } // If the type is already defined we can proceed with the same name. for _, v := range TypesAlreadyDefined { if v == s { - return ast.importType(s) + return program.ImportType(s) } } @@ -111,7 +114,7 @@ func resolveType(ast *Ast, s string) string { for _, v := range simpleResolveTypes { if v == s { - return "*" + ast.importType(simpleResolveTypes[s]) + return "*" + program.ImportType(simpleResolveTypes[s]) } } @@ -121,7 +124,7 @@ func resolveType(ast *Ast, s string) string { for _, v := range simpleResolveTypes { if v == s { - return ast.importType(simpleResolveTypes[s]) + return program.ImportType(simpleResolveTypes[s]) } } @@ -146,10 +149,14 @@ func resolveType(ast *Ast, s string) string { // It may be a pointer of a simple type. For example, float *, int *, // etc. if regexp.MustCompile("[\\w ]+\\*+$").MatchString(s) { - return "*" + resolveType(ast, strings.TrimSpace(s[:len(s)-2])) + return "*" + ResolveType(program, strings.TrimSpace(s[:len(s)-2])) + } + + if regexp.MustCompile(`[\w ]+\*\[\d+\]$`).MatchString(s) { + return "[]string" } - // Function pointers are not yet supported. In th mean time they will be + // Function pointers are not yet supported. In the mean time they will be // replaced with a type that certainly wont work until we can fix this // properly. search := regexp.MustCompile("[\\w ]+\\(\\*.*?\\)\\(.*\\)").MatchString(s) @@ -165,7 +172,7 @@ func resolveType(ast *Ast, s string) string { // It could be an array of fixed length. search2 := regexp.MustCompile("([\\w ]+)\\[(\\d+)\\]").FindStringSubmatch(s) if len(search2) > 0 { - return fmt.Sprintf("[%s]%s", search2[2], resolveType(ast, search2[1])) + return fmt.Sprintf("[%s]%s", search2[2], ResolveType(program, search2[1])) } panic(fmt.Sprintf("'%s'", s)) diff --git a/types/resolve_test.go b/types/resolve_test.go new file mode 100644 index 000000000..a17e70df9 --- /dev/null +++ b/types/resolve_test.go @@ -0,0 +1,27 @@ +package types_test + +import ( + "testing" + + "github.com/elliotchance/c2go/types" +) + +type resolveTestCase struct { + cType string + goType string +} + +var resolveTestCases = []resolveTestCase{ + {"int", "int"}, + {"char *[13]", "[]string"}, +} + +func TestResolve(t *testing.T) { + for _, testCase := range resolveTestCases { + goType := types.ResolveType(nil, testCase.cType) + if goType != testCase.goType { + t.Errorf("Expected '%s' -> '%s', got '%s'", + testCase.cType, testCase.goType, goType) + } + } +} diff --git a/util/util.go b/util/util.go new file mode 100644 index 000000000..43c0a78ff --- /dev/null +++ b/util/util.go @@ -0,0 +1,17 @@ +package util + +import "strings" + +func InStrings(item string, items []string) bool { + for _, v := range items { + if item == v { + return true + } + } + + return false +} + +func Ucfirst(word string) string { + return strings.ToUpper(string(word[0])) + word[1:] +}