package interp

import (
	
	
	
	
	
	
	
	

	gen 
)

// Symbols returns a map of interpreter exported symbol values for the given
// import path. If the argument is the empty string, all known symbols are
// returned.
func ( *Interpreter) ( string) Exports {
	 := map[string]map[string]reflect.Value{}
	.mutex.RLock()
	defer .mutex.RUnlock()

	for ,  := range .srcPkg {
		if  != "" &&  !=  {
			continue
		}
		 := map[string]reflect.Value{}
		for ,  := range  {
			if !canExport() {
				// Skip private non-exported symbols.
				continue
			}
			switch .kind {
			case constSym:
				[] = .rval
			case funcSym:
				[] = genFunctionWrapper(.node)(.frame)
			case varSym:
				[] = .frame.data[.index]
			case typeSym:
				[] = reflect.New(.typ.TypeOf())
			}
		}

		if len() > 0 {
			[] = 
		}

		if  != "" {
			return 
		}
	}

	if  != "" && len() > 0 {
		return 
	}

	for ,  := range .binPkg {
		if  != "" &&  !=  {
			continue
		}
		[] = 
		if  != "" {
			return 
		}
	}

	return 
}

// getWrapper returns the wrapper type of the corresponding interface, trying
// first the composed ones, or nil if not found.
func getWrapper( *node,  reflect.Type) reflect.Type {
	,  := .interp.binPkg[.PkgPath()]
	if ! {
		return nil
	}
	 := ["_"+.Name()]
	 := .typ.methods()

	// mapTypes may contain composed interfaces wrappers to test against, from
	// most complex to simplest (guaranteed by construction of mapTypes). Find the
	// first for which the interpreter type has all the methods.
	for ,  := range .interp.mapTypes[] {
		 := true
		for  := 1;  < .NumField(); ++ {
			// The interpreter type must have all required wrapper methods.
			if ,  := [.Field().Name[1:]]; ! {
				 = false
				break
			}
		}
		if  {
			return 
		}
	}

	// Otherwise return the direct "non-composed" interface.
	return .Type().Elem()
}

// Use loads binary runtime symbols in the interpreter context so
// they can be used in interpreted code.
func ( *Interpreter) ( Exports) error {
	for ,  := range  {
		 := path.Dir()
		 := path.Base()

		if  == "." && ["MapTypes"].IsValid() {
			// Use mapping for special interface wrappers.
			for ,  := range ["MapTypes"].Interface().(map[reflect.Value][]reflect.Type) {
				.mapTypes[] = 
			}
			continue
		}

		if  == "." {
			return fmt.Errorf("export path %[1]q is missing a package name; did you mean '%[1]s/%[1]s'?", )
		}

		if  == selfPrefix {
			.hooks.Parse()
			continue
		}

		if .binPkg[] == nil {
			.binPkg[] = make(map[string]reflect.Value)
			.pkgNames[] = 
		}

		for ,  := range  {
			.binPkg[][] = 
		}
		if  == selfPath {
			.binPkg[]["Self"] = reflect.ValueOf()
		}
	}

	// Checks if input values correspond to stdlib packages by looking for one
	// well known stdlib package path.
	if ,  := ["fmt/fmt"];  {
		fixStdlib()

		// Load stdlib generic source.
		for ,  := range gen.Sources {
			if ,  := .Compile();  != nil {
				return 
			}
		}
	}
	return nil
}

// fixStdlib redefines interpreter stdlib symbols to use the standard input,
// output and errror assigned to the interpreter. The changes are limited to
// the interpreter only.
// Note that it is possible to escape the virtualized stdio by
// read/write directly to file descriptors 0, 1, 2.
func fixStdlib( *Interpreter) {
	 := .binPkg["fmt"]
	if  == nil {
		return
	}

	, ,  := .stdin, .stdout, .stderr

	["Print"] = reflect.ValueOf(func( ...interface{}) ( int,  error) { return fmt.Fprint(, ...) })
	["Printf"] = reflect.ValueOf(func( string,  ...interface{}) ( int,  error) { return fmt.Fprintf(, , ...) })
	["Println"] = reflect.ValueOf(func( ...interface{}) ( int,  error) { return fmt.Fprintln(, ...) })

	["Scan"] = reflect.ValueOf(func( ...interface{}) ( int,  error) { return fmt.Fscan(, ...) })
	["Scanf"] = reflect.ValueOf(func( string,  ...interface{}) ( int,  error) { return fmt.Fscanf(, , ...) })
	["Scanln"] = reflect.ValueOf(func( ...interface{}) ( int,  error) { return fmt.Fscanln(, ...) })

	// Update mapTypes to virtualized symbols as well.
	.mapTypes[["Print"]] = .mapTypes[reflect.ValueOf(fmt.Print)]
	.mapTypes[["Printf"]] = .mapTypes[reflect.ValueOf(fmt.Printf)]
	.mapTypes[["Println"]] = .mapTypes[reflect.ValueOf(fmt.Println)]
	.mapTypes[["Scan"]] = .mapTypes[reflect.ValueOf(fmt.Scan)]
	.mapTypes[["Scanf"]] = .mapTypes[reflect.ValueOf(fmt.Scanf)]
	.mapTypes[["Scanln"]] = .mapTypes[reflect.ValueOf(fmt.Scanln)]

	if  = .binPkg["flag"];  != nil {
		 := flag.NewFlagSet(os.Args[0], flag.PanicOnError)
		.SetOutput()
		["CommandLine"] = reflect.ValueOf(&).Elem()
	}

	if  = .binPkg["log"];  != nil {
		 := log.New(, "", log.LstdFlags)
		// Restrict Fatal symbols to panic instead of exit.
		["Fatal"] = reflect.ValueOf(.Panic)
		["Fatalf"] = reflect.ValueOf(.Panicf)
		["Fatalln"] = reflect.ValueOf(.Panicln)

		["Flags"] = reflect.ValueOf(.Flags)
		["Output"] = reflect.ValueOf(.Output)
		["Panic"] = reflect.ValueOf(.Panic)
		["Panicf"] = reflect.ValueOf(.Panicf)
		["Panicln"] = reflect.ValueOf(.Panicln)
		["Prefix"] = reflect.ValueOf(.Prefix)
		["Print"] = reflect.ValueOf(.Print)
		["Printf"] = reflect.ValueOf(.Printf)
		["Println"] = reflect.ValueOf(.Println)
		["SetFlags"] = reflect.ValueOf(.SetFlags)
		["SetOutput"] = reflect.ValueOf(.SetOutput)
		["SetPrefix"] = reflect.ValueOf(.SetPrefix)
		["Writer"] = reflect.ValueOf(.Writer)

		// Update mapTypes to virtualized symbols as well.
		.mapTypes[["Print"]] = .mapTypes[reflect.ValueOf(log.Print)]
		.mapTypes[["Printf"]] = .mapTypes[reflect.ValueOf(log.Printf)]
		.mapTypes[["Println"]] = .mapTypes[reflect.ValueOf(log.Println)]
		.mapTypes[["Panic"]] = .mapTypes[reflect.ValueOf(log.Panic)]
		.mapTypes[["Panicf"]] = .mapTypes[reflect.ValueOf(log.Panicf)]
		.mapTypes[["Panicln"]] = .mapTypes[reflect.ValueOf(log.Panicln)]
	}

	if  = .binPkg["os"];  != nil {
		["Args"] = reflect.ValueOf(&.args).Elem()
		if .specialStdio {
			// Inherit streams from interpreter even if they do not have a file descriptor.
			["Stdin"] = reflect.ValueOf(&).Elem()
			["Stdout"] = reflect.ValueOf(&).Elem()
			["Stderr"] = reflect.ValueOf(&).Elem()
		} else {
			// Inherits streams from interpreter only if they have a file descriptor and preserve original type.
			if ,  := .(*os.File);  {
				["Stdin"] = reflect.ValueOf(&).Elem()
			}
			if ,  := .(*os.File);  {
				["Stdout"] = reflect.ValueOf(&).Elem()
			}
			if ,  := .(*os.File);  {
				["Stderr"] = reflect.ValueOf(&).Elem()
			}
		}
		if !.unrestricted {
			// In restricted mode, scripts can only access to a passed virtualized env, and can not write the real one.
			 := func( string) string { return .env[] }
			["Clearenv"] = reflect.ValueOf(func() { .env = map[string]string{} })
			["ExpandEnv"] = reflect.ValueOf(func( string) string { return os.Expand(, ) })
			["Getenv"] = reflect.ValueOf()
			["LookupEnv"] = reflect.ValueOf(func( string) ( string,  bool) { ,  = .env[]; return })
			["Setenv"] = reflect.ValueOf(func(,  string) error { .env[] = ; return nil })
			["Unsetenv"] = reflect.ValueOf(func( string) error { delete(.env, ); return nil })
			["Environ"] = reflect.ValueOf(func() ( []string) {
				for ,  := range .env {
					 = append(, +"="+)
				}
				return
			})
		}
	}

	if  = .binPkg["math/bits"];  != nil {
		// Do not trust extracted value maybe from another arch.
		["UintSize"] = reflect.ValueOf(constant.MakeInt64(bits.UintSize))
	}
}