func (v *Codegen) genDefaultValue(typ parser.Type) llvm.Value { atyp := typ.ActualType() // Generate default struct values if structType, ok := atyp.(parser.StructType); ok { lit := createStructInitializer(typ) if lit != nil { return v.genStructLiteral(lit) } else { return llvm.Undef(v.typeToLLVMType(structType)) } } if tupleType, ok := atyp.(parser.TupleType); ok { values := make([]llvm.Value, len(tupleType.Members)) for idx, member := range tupleType.Members { values[idx] = v.genDefaultValue(member) } return llvm.ConstStruct(values, false) } if atyp.IsIntegerType() || atyp == parser.PRIMITIVE_bool { return llvm.ConstInt(v.typeToLLVMType(atyp), 0, false) } if atyp.IsFloatingType() { return llvm.ConstFloat(v.typeToLLVMType(atyp), 0) } panic("type does not have default value: " + atyp.TypeName()) }
func createStructInitializer(typ parser.Type) *parser.CompositeLiteral { lit := &parser.CompositeLiteral{Type: typ} hasDefaultValues := false structType := typ.ActualType().(parser.StructType) for _, decl := range structType.Variables { vari := decl.Variable var value parser.Expr if _, ok := vari.Type.ActualType().(parser.StructType); ok { value = createStructInitializer(vari.Type) } else { value = decl.Assignment } if value != nil { hasDefaultValues = true lit.Values = append(lit.Values, value) lit.Fields = append(lit.Fields, vari.Name) } } if hasDefaultValues { return lit } return nil }
func createStructInitializer(typ parser.Type) *parser.StructLiteral { lit := &parser.StructLiteral{Type: typ, Values: make(map[string]parser.Expr)} hasDefaultValues := false structType := typ.ActualType().(parser.StructType) for _, decl := range structType.Variables { vari := decl.Variable var value parser.Expr if _, ok := vari.Type.ActualType().(parser.StructType); ok { value = createStructInitializer(vari.Type) } else { value = decl.Assignment } if value != nil { hasDefaultValues = true lit.Values[vari.Name] = value } } if hasDefaultValues { return lit } return nil }
func isTypeRecursive(typ parser.Type) (bool, []parser.Type) { typ = typ.ActualType() var check func(current parser.Type, path *[]parser.Type, traversed map[parser.Type]bool) bool check = func(current parser.Type, path *[]parser.Type, traversed map[parser.Type]bool) bool { switch current.(type) { case *parser.NamedType: if traversed[current] { return true } traversed[current] = true } switch current.(type) { case parser.StructType: st := current.(parser.StructType) for _, decl := range st.Variables { if check(decl.Variable.Type, path, traversed) { *path = append(*path, decl.Variable.Type) return true } } case parser.TupleType: tt := current.(parser.TupleType) for _, mem := range tt.Members { if check(mem, path, traversed) { *path = append(*path, mem) return true } } case parser.EnumType: et := current.(parser.EnumType) for _, mem := range et.Members { if check(mem.Type, path, traversed) { *path = append(*path, mem.Type) return true } } case *parser.NamedType: nt := current.(*parser.NamedType) if check(nt.Type, path, traversed) { *path = append(*path, nt.Type) return true } // TODO: Add array if we ever add embedded fixed size/static arrays } return false } var path []parser.Type return check(typ, &path, make(map[parser.Type]bool)), path }