File: fal_include.cpp

package info (click to toggle)
falconpl 0.9.6.9-git20120606-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 46,176 kB
  • sloc: cpp: 181,389; ansic: 109,025; yacc: 2,310; xml: 1,218; sh: 403; objc: 245; makefile: 82; sql: 20
file content (155 lines) | stat: -rw-r--r-- 4,794 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
   FALCON - The Falcon Programming Language.
   FILE: fal_include.cpp

   Include function - Dynamic module loading.
   -------------------------------------------------------------------
   Author: Giancarlo Niccolai
   Begin: Sun, 31 Aug 2008 19:01:59 +0200

   -------------------------------------------------------------------
   (C) Copyright 2008: the FALCON developers (see list in AUTHORS file)

   See LICENSE file for licensing details.
*/

#include <falcon/setup.h>
#include <falcon/vm.h>
#include <falcon/module.h>
#include <falcon/modloader.h>

/*#
   @beginmodule core
*/

namespace Falcon {
namespace core {

/*#
   @function include
   @brief Dynamically loads a module as a plugin.
   @param file The relative filename of the module.
   @optparam inputEnc Input encoding.
   @optparam path A string of ';' separated search paths.
   @optparam symDict Symbols to be queried (or nil).

   @raise IoError if the module cannot be found or loaded.

   A module indicated by filename is compiled, loaded and linked in the
   running Virtual Machine. The inclusion is relative to the current
   path, be it set in the script, in the current embedding application
   or in the falcon command line interpreter. It is possible to use
   a path relative to the current script path by using the scriptPath
   variable.

   If a dictionary of symbols to be queried is @b not provided, the module
   is loaded and its main code, if present, is executed.

   If @b symDict is provided, its keys are strings which refer to symbol names
   to be searched in the loaded module. If present, the entry are filled with
   symbols coming from the loaded module. When @b symDict is provided, the
   linked module won't have its main code executed (it is possible to execute
   it at a later time adding "__main__" to the searched symbols). If a symbol
   is not found, its entry in the dictionary will be set to nil. When loaded
   this way, the export requests in the loaded module are @b not honored (import/from
   semantic).

   The @b compiler Feather module provides a more complete interface to dynamic
   load and compilation, but this minimal dynamic load support is provided at
   base level for flexibility.
*/

FALCON_FUNC fal_include( Falcon::VMachine *vm )
{
   Falcon::Item *i_file = vm->param(0);
   Falcon::Item *i_enc = vm->param(1);
   Falcon::Item *i_path = vm->param(2);
   Falcon::Item *i_syms = vm->param(3);

   if( i_file == 0 || ! i_file->isString()
      || (i_syms != 0 && ! (i_syms->isDict() || i_syms->isNil())  )
      || (i_enc != 0 && !(i_enc->isString() || i_enc->isNil()) )
      || (i_path != 0 && !(i_path->isString() || i_path->isNil()) )
      )
   {
      throw new Falcon::ParamError(
         Falcon::ErrorParam( Falcon::e_inv_params, __LINE__ )
         .origin(e_orig_runtime)
         .extra( "S,[S],[S],[D]" ) );
   }

   // create the loader/runtime pair.
   ModuleLoader cpl( i_path == 0 || i_path->isNil() ? vm->appSearchPath() : String(*i_path->asString()) );
   cpl.delayRaise(true);
   Runtime rt( &cpl, vm );
   rt.hasMainModule( false );

   // minimal config
   if ( i_enc != 0 && ! i_enc->isNil() )
   {
      cpl.sourceEncoding( *i_enc->asString() );
   }
   else
   {
      String sEnc, sIoEnc;
      Engine::getEncodings( sEnc, sIoEnc );
      cpl.sourceEncoding( sEnc );
   }

   bool execAtLink = vm->launchAtLink();

   //! Copy the filename so to be sure to display it correctly in an eventual error.
   String fileName = *i_file->asString();
   fileName.bufferize();

   // load and link
   try {
      rt.loadFile( fileName, true );

      vm->launchAtLink( i_syms == 0 || i_syms->isNil() );
      LiveModule *lmod = vm->link( &rt );

      // shall we read the symbols?
      if( lmod != 0 && ( i_syms != 0 && i_syms->isDict() ) )
      {
         CoreDict *dict = i_syms->asDict();

         // traverse the dictionary
         Iterator iter( &dict->items() );
         while( iter.hasCurrent() )
         {
            // if the key is a string and a corresponding item is found...
            Item *ival;
            if ( iter.getCurrentKey().isString() &&
                  ( ival = lmod->findModuleItem( *iter.getCurrentKey().asString() ) ) != 0 )
            {
               // copy it locally
               iter.getCurrent() = *ival;
            }
            else {
               iter.getCurrent().setNil();
            }

            iter.next();
         }
      }

      // reset launch status
      vm->launchAtLink( execAtLink );
   }
   catch(Error* err)
   {
      CodeError *ce = new CodeError( ErrorParam( e_loaderror, __LINE__ ).
         extra( fileName ) );

      ce->appendSubError(err);
      err->decref();

      // reset launch status
      vm->launchAtLink( execAtLink );
      throw ce;
   }
}

}
}