Exemplo n.º 1
0
func visitField(instr *ssa.Field, infer *TypeInfer, ctx *Context) {
	field, struc, index := instr, instr.X, instr.Field
	if sType, ok := struc.Type().Underlying().(*types.Struct); ok {
		sInst, ok := ctx.F.locals[struc]
		if !ok {
			infer.Logger.Fatalf("field: %s :%+v", ErrUnknownValue, struc)
			return
		}
		fields, ok := ctx.F.structs[sInst]
		if !ok {
			fields, ok = ctx.F.Prog.structs[sInst]
			if !ok {
				infer.Logger.Fatalf("field: %s: struct uninitialised %+v", ErrUnknownValue, sInst)
				return
			}
		}
		infer.Logger.Print(ctx.F.Sprintf(ValSymbol+"%s = %s"+FieldSymbol+"{%d} of type %s", instr.Name(), sInst, index, sType.String()))
		if fields[index] != nil {
			infer.Logger.Print(ctx.F.Sprintf(SubSymbol+"accessed as %s", fields[index]))
		} else {
			fields[index] = &Value{field, ctx.F.InstanceID(), ctx.L.Index}
			infer.Logger.Print(ctx.F.Sprintf(SubSymbol+"field uninitialised, set to %s", field.Name()))
		}
		initNestedRefVar(infer, ctx, ctx.F.locals[field], false)
		ctx.F.locals[field] = fields[index]
		return
	}
	infer.Logger.Fatalf("field: %s: field is not struct: %+v", ErrInvalidVarRead, struc)
}
Exemplo n.º 2
0
func visitField(inst *ssa.Field, fr *frame) {
	field := inst
	struc := inst.X
	index := inst.Field

	if stype, ok := struc.Type().Underlying().(*types.Struct); ok {
		switch vd, kind := fr.get(struc); kind {
		case Struct:
			fmt.Fprintf(os.Stderr, "   %s = %s(=%s).[%d] of type %s\n", cyan(reg(field)), struc.Name(), vd.String(), index, field.Type().String())
			if fr.env.structs[vd][index] == nil { // First use
				vdField := utils.NewDef(field)
				fr.env.structs[vd][index] = vdField
				fmt.Fprintf(os.Stderr, "     ^ accessed for the first time: use %s as field definition\n", field.Name())
				// If field is struct
				if fieldType, ok := field.Type().Underlying().(*types.Struct); ok {
					fr.env.structs[vdField] = make(Fields, fieldType.NumFields())
					fmt.Fprintf(os.Stderr, "     ^ field %s is a struct (allocating)\n", field.Name())
				}
			} else if fr.env.structs[vd][index].Var != field { // Previously defined
				fmt.Fprintf(os.Stderr, "     ^ field %s previously defined as %s\n", field.Name(), reg(fr.env.structs[vd][index].Var))
			} // else Accessed before (and unchanged)
			fr.locals[field] = fr.env.structs[vd][index]

		case LocalStruct:
			fmt.Fprintf(os.Stderr, "   %s = %s(=%s).[%d] (local) of type %s\n", cyan(reg(field)), struc.Name(), vd.String(), index, field.Type().String())
			if fr.structs[vd][index] == nil { // First use
				vdField := utils.NewDef(field)
				fr.structs[vd][index] = vdField
				fmt.Fprintf(os.Stderr, "     ^ accessed for the first time: use %s as field definition\n", field.Name())
				// If field is struct
				if fieldType, ok := field.Type().Underlying().(*types.Struct); ok {
					fr.structs[vdField] = make(Fields, fieldType.NumFields())
					fmt.Fprintf(os.Stderr, "     ^ field %s is a struct (allocating locally)\n", field.Name())
				}
			} else if fr.structs[vd][index].Var != field { // Previously defined
				fmt.Fprintf(os.Stderr, "     ^ field %s previously defined as %s\n", field.Name(), reg(fr.structs[vd][index].Var))
			} // else Accessed before (and unchanged)
			fr.locals[field] = fr.structs[vd][index]

		case Nothing, Untracked:
			// Nothing: Very likely external struct.
			// Untracked: likely branches of return values (e.g. returning nil)
			fmt.Fprintf(os.Stderr, "   %s = %s(=%s).[%d] (external) of type %s\n", cyan(reg(field)), inst.X.Name(), vd.String(), index, field.Type().String())
			vd := utils.NewDef(struc) // New external struct
			fr.locals[struc] = vd
			fr.env.structs[vd] = make(Fields, stype.NumFields())
			vdField := utils.NewDef(field) // New external field
			fr.env.structs[vd][index] = vdField
			fr.locals[field] = vdField
			fmt.Fprintf(os.Stderr, "     ^ accessed for the first time: use %s as field definition of type %s\n", field.Name(), inst.Type().Underlying().String())
			// If field is struct
			if fieldType, ok := field.Type().Underlying().(*types.Struct); ok {
				fr.env.structs[vdField] = make(Fields, fieldType.NumFields())
				fmt.Fprintf(os.Stderr, "     ^ field %s previously defined as %s\n", field.Name(), reg(fr.env.structs[vd][index].Var))
			}

		default:
			panic(fmt.Sprintf("Field: Cannot access non-struct %s %T %d", reg(struc), struc.Type(), kind))
		}
	} else {
		panic(fmt.Sprintf("Field: Cannot access field - %s not a struct\n", reg(struc)))
	}
}