Ejemplo n.º 1
0
func (sc *PackageScoping) MangleExpr(e ast.Expr) ast.Expr {
	switch e := e.(type) {
	case *ast.CallExpr:
		for i := range e.Args {
			e.Args[i] = sc.MangleExpr(e.Args[i])
		}
		sc.MangleExpr(e.Fun)
		if fn, ok := e.Fun.(*ast.Ident); ok {
			switch fn.Name {
			case "print", "println":
				sc.Do("runtime.print")
				sc.Do("runtime.print_int")
			case "new":
				sc.Do("runtime.malloc")
			}
		}
	case *ast.Ident:
		if pkg, ok := sc.Globals[e.Name]; ok {
			// It's a global identifier, so we need to mangle it...
			sc.Do(pkg + "." + e.Name)
			oldname := e.Name
			e.Name = ManglePackageAndName(pkg, e.Name)
			fmt.Println("Name is", e.Name, "from", pkg, oldname)
		} else {
			// Nothing to do here, it is a local identifier or builtin.
		}
	case *ast.BasicLit:
		// Nothing to do here, a literal is never imported.
	case *ast.BinaryExpr:
		e.X = sc.MangleExpr(e.X)
		e.Y = sc.MangleExpr(e.Y)
		// FIXME: We could do better here if we had type information...
		switch e.Op {
		case token.EQL:
			sc.Do("runtime.strings_equal")
		case token.NEQ:
			sc.Do("runtime.strings_unequal")
		}
	case *ast.UnaryExpr:
		sc.MangleExpr(e.X)
	case *ast.ParenExpr:
		sc.MangleExpr(e.X)
	case *ast.IndexExpr:
		e.X = sc.MangleExpr(e.X)
		e.Index = sc.MangleExpr(e.Index)
	case *ast.SliceExpr:
		e.X = sc.MangleExpr(e.X)
		e.Low = sc.MangleExpr(e.Low)
		e.High = sc.MangleExpr(e.High)
		sc.Do("runtime.slice_string")
	case *ast.StarExpr:
		sc.MangleExpr(e.X)
	case *ast.SelectorExpr:
		if b, ok := e.X.(*ast.Ident); ok {
			if theimp, ok := sc.Imports[b.Name]; ok {
				sc.Do(theimp + "." + e.Sel.Name)
				e.Sel.Name = ManglePackageAndName(theimp, e.Sel.Name)
				return e.Sel
			} else {
				fmt.Println("not a package: ", b.Name)
				fmt.Println("Imports are", sc.Imports)
				sc.MangleExpr(e.X)
			}
		} else {
			sc.MangleExpr(e.X)
		}
	case *ast.StructType:
		for _, f := range e.Fields.List {
			sc.MangleExpr(f.Type)
		}
	case *ast.CompositeLit:
		e.Type = sc.MangleExpr(e.Type)
		for i := range e.Elts {
			e.Elts[i] = sc.MangleExpr(e.Elts[i])
		}
	case *ast.MapType:
		e.Key = sc.MangleExpr(e.Key)
		e.Value = sc.MangleExpr(e.Value)
	case *ast.Ellipsis:
		e.Elt = sc.MangleExpr(e.Elt)
	case *ast.InterfaceType:
		for _, field := range e.Methods.List {
			field.Type = sc.MangleExpr(field.Type)
		}
	case *ast.ArrayType:
		e.Len = sc.MangleExpr(e.Len)
		e.Elt = sc.MangleExpr(e.Elt)
	case *ast.TypeAssertExpr:
		e.X = sc.MangleExpr(e.X)
		e.Type = sc.MangleExpr(e.Type)
	case *ast.FuncType:
		for _, field := range e.Params.List {
			field.Type = sc.MangleExpr(field.Type)
		}
		for _, field := range e.Results.List {
			field.Type = sc.MangleExpr(field.Type)
		}
	case *ast.FuncLit:
		for _, field := range e.Type.Params.List {
			field.Type = sc.MangleExpr(field.Type)
		}
		for _, field := range e.Type.Results.List {
			field.Type = sc.MangleExpr(field.Type)
		}
		sc.MangleStatement(e.Body)
	case *ast.KeyValueExpr:
		e.Key = sc.MangleExpr(e.Key)
		e.Value = sc.MangleExpr(e.Value)
	case nil:
		// Nothing to do with nil expression
	default:
		panic(fmt.Sprintf("Tracked weird expression of type %T", e))
	}
	return e
}