| // Copyright 2015 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package swift |
| |
| import ( |
| "fmt" |
| "strconv" |
| "strings" |
| |
| "v.io/v23/vdl" |
| "v.io/x/ref/lib/vdl/compile" |
| ) |
| |
| // swiftConstVal returns the value string for the provided constant value. |
| func swiftConstVal(v *vdl.Value, ctx *swiftContext) (ret string) { |
| ret = swiftVal(v, ctx) |
| if tdef := ctx.env.FindTypeDef(v.Type()); tdef != nil && tdef.File != compile.BuiltInFile { // User-defined type. |
| switch tdef.Type.Kind() { |
| case vdl.Union: |
| ret = fmt.Sprintf("%s.%s", ctx.swiftType(v.Type()), ret) |
| case vdl.Struct: |
| ret = fmt.Sprintf("%s(%s)", ctx.swiftType(v.Type()), ret) |
| case vdl.Enum: |
| return |
| default: |
| ret = fmt.Sprintf("%s(rawValue: %s)", ctx.swiftType(v.Type()), ret) |
| } |
| } |
| return |
| } |
| |
| // swiftVal returns the value string for the provided Value. |
| func swiftVal(v *vdl.Value, ctx *swiftContext) string { |
| switch v.Kind() { |
| case vdl.Any: |
| // TODO(azinman) Don't exactly know what to do here to generate the inference code... so instead come back to this |
| // but it doesn't seem to get triggered in the v23 VDL gen code base anyway? |
| panic("Don't know how to handle Any type in a given Value") |
| case vdl.Bool: |
| switch v.Bool() { |
| case true: |
| return "true" |
| case false: |
| return "false" |
| } |
| case vdl.Byte: |
| return "UInt8(0x" + strconv.FormatUint(v.Uint(), 16) + ")" |
| case vdl.Int8: |
| return "Int8(" + strconv.FormatInt(v.Int(), 10) + ")" |
| case vdl.Uint16: |
| return "UInt16(" + strconv.FormatUint(v.Uint(), 10) + ")" |
| case vdl.Int16: |
| return "Int16(" + strconv.FormatInt(v.Int(), 10) + ")" |
| case vdl.Uint32: |
| return "UInt32(" + strconv.FormatUint(v.Uint(), 10) + ")" |
| case vdl.Int32: |
| return "Int32(" + strconv.FormatInt(v.Int(), 10) + ")" |
| case vdl.Uint64: |
| return "UInt64(" + strconv.FormatUint(v.Uint(), 10) + ")" |
| case vdl.Int64: |
| return "Int64(" + strconv.FormatInt(v.Int(), 10) + ")" |
| case vdl.Float32, vdl.Float64: |
| c := strconv.FormatFloat(v.Float(), 'g', -1, bitlen(v.Kind())) |
| if strings.Index(c, ".") == -1 { |
| c += ".0" |
| } |
| if v.Kind() == vdl.Float32 { |
| return "Float(" + c + ")" |
| } else { |
| return "Double(" + c + ")" |
| } |
| case vdl.String: |
| in := v.RawString() |
| return swiftQuoteString(in) |
| case vdl.Enum: |
| return fmt.Sprintf("%s.%s", ctx.swiftType(v.Type()), v.EnumLabel()) |
| case vdl.Array, vdl.List: |
| ret := "[" |
| for i := 0; i < v.Len(); i++ { |
| if i > 0 { |
| ret = ret + ", " |
| } |
| ret = ret + swiftConstVal(v.Index(i), ctx) |
| } |
| return ret + "]" |
| case vdl.Map: |
| ret := "[" |
| for _, key := range vdl.SortValuesAsString(v.Keys()) { |
| keyStr := swiftConstVal(key, ctx) |
| elemStr := swiftConstVal(v.MapIndex(key), ctx) |
| ret = fmt.Sprintf("%s%s:%s, ", ret, keyStr, elemStr) |
| } |
| return ret + "]" |
| case vdl.Union: |
| index, value := v.UnionField() |
| name := v.Type().Field(index).Name |
| elemStr := swiftConstVal(value, ctx) |
| return fmt.Sprintf("%s(elem: %s)", name, elemStr) |
| case vdl.Set: |
| ret := "Set(" |
| for _, key := range vdl.SortValuesAsString(v.Keys()) { |
| ret = fmt.Sprintf("%s, %s", ret, swiftConstVal(key, ctx)) |
| } |
| return ret + ")" |
| case vdl.Struct: |
| tdef := ctx.env.FindTypeDef(v.Type()) |
| if tdef == nil { |
| panic("No plausible way to define a Swift struct constructor without the tdef") |
| } |
| var ret string |
| for i := 0; i < v.Type().NumField(); i++ { |
| if i > 0 { |
| ret = ret + ", " |
| } |
| fldValue := v.StructField(i) |
| fld := tdef.Type.Field(i) |
| ret = fmt.Sprintf("%v%v: %v", ret, swiftVariableName(tdef, fld), swiftConstVal(fldValue, ctx)) |
| } |
| return ret |
| case vdl.TypeObject: |
| // TODO(zinman) Support TypeObjects once we have vdlType support |
| return fmt.Sprintf("VdlTypeObject(type: nil)") |
| case vdl.Optional: |
| if v.Elem() != nil { |
| return swiftConstVal(v.Elem(), ctx) |
| } else { |
| return "nil" |
| } |
| } |
| panic(fmt.Errorf("vdl: swiftVal unhandled type %v %v", v.Kind(), v.Type())) |
| } |
| |
| func swiftQuoteString(str string) string { |
| // This accounts for Swift string interpolation \(likeThis) because |
| // vdl will already error if you create a const string that contains |
| // \( and not \\( |
| // In the future this may change and we might need to explicitly add |
| // the escapes. |
| return strconv.Quote(str) |
| } |