File: compiler.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 (268 lines) | stat: -rw-r--r-- 9,890 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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
/*
   FALCON - The Falcon Programming Language
   FILE: compiler.cpp

   Compiler module main file
   -------------------------------------------------------------------
   Author: Giancarlo Niccolai
   Begin: sab lug 21 2007

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

   See LICENSE file for licensing details.
*/

/** \file
   This module exports the compiler and module loader facility to falcon
   scripts.

   In this way, Falcon scripts are able to load other modules on their own,
   or compile arbitrary code.
*/

/*#
   @module feathers.compiler Reflexive compiler
   @brief Module implementing a Falcon compiler-in-a-box
   
   Falcon provides a reflexive compiler and module loader that allows scripts to
   load other falcon sources, pre-compiled modules or binary modules.
   The reflexive compiler is actually an interface to the internal compilation and
   link engine, so anything that can be done by the falcon command line utility can
   be done also through this facility.

   Falcon code structure is fixed; modules are read-only from a Virtual Machine
   stand point. This means that Falcon cannot alter the structure of scripts being
   currently executed. In example, it is not possible to compile a single code line
   and have it executed in the current script context.

   However, the reflexive compiler is so flexible that this limitation is hardly
   felt. It is possible to load a module, or to compile it on the fly, and then get
   or set any of the global symbols in the target module. By extracting items from
   the loaded module, or injecting known items into that, it is possible to
   configure, alter, and execute arbitrary parts of the loaded module as if it were
   coded internally to the loader script.

   @section compiler_sample_usage Example usages

   The following script shows how a source module may be compiled and executed on the fly.

   @code
   load compiler

   // create the compiler
   c = Compiler()

   // try to compile a source string
   str = '
      function func( a )
         > "Hello from compiled source: ", a
      end

      > "The main part of the module"
   '

   try
      // First param is the module logical name.
      sourceMod = c.compile( "aString", str )

      // in case of compilation error, we had an error and we bailed out

      // load the symbol func from our module...
      func = sourceMod.get( "func" )
      // and execute it...
      func( "test param" )

      // execute directly the main module, notice the () at eol
      sourceMod.get( "__main__" )()

   catch CodeError in e
      > "Had an error: ", e
   end
   @endcode

   We may also put symbols in target scripts, forcing them to execute some part of the
   loader code. In example, suppose this is a falcon source called "module1.fal":

   @code
   // this global variable will be mangled by the loader
   fromLoader = nil

   function test()
      > "Test from module 1"

      // trustfully call the readied global
      fromLoader()
   end
   The loader will look like this:
   load compiler
   c = Compiler()

   function saySomething()
      > "Something said from the main module."
   end

   // Load a module by its path.
   mod = c.loadModule( "./module1.fal" )

   // change target symbol
   mod.set( "fromLoader", saySomething )

   // call loaded function
   mod.get( "test" )()

   @endcode

   Of course, scripts can exchange objects, classes, methods, functions, lambdas
   and in general any value.

   It is not possible to set directly a global object method in the target module
   in this way. In example, if the target module defines an object Obj, with a
   property called prop, it is not possible to call
      @code
         mod.set( "Obj.prop", someValue )
      @endcode

   However, the object can be imported in the local script, and any change to
   its structure will be reflected in both the original owner and the loader. In
   example, if alphadef.fal defines the object:

   @code
   object alpha
      prop = nil

      function callProp()
         self.prop( "Called internally from self." )
      end
   end
   Then the loader may do:
   load compiler
   c = Compiler()

   function saySomething( param )
      > "Parameter is: ", param
   end

   // Load a module by its name.
   // It means, search a suitable .fal, .fam or binary module.
   mod = c.loadByName( "alphadef" )

   // get the object
   obj = mod.get( "alpha" )

   // and change the property to something in our script
   obj.prop = saySomething

   // then call it
   obj.callProp()

   @endcode

   As expected, the result is:
   @code
   $ ./falcon alphaload.fal
   Parameter is: Called internally from self.
   @endcode

*/

#include <falcon/module.h>
#include "compiler_ext.h"
#include "compiler_mod.h"
#include "compiler_st.h"

#include "version.h"


FALCON_MODULE_DECL
{
   #define FALCON_DECLARE_MODULE self

   Falcon::Module *self = new Falcon::Module();
   self->name( "compiler" );
   self->language( "en_US" );
   self->engineVersion( FALCON_VERSION_NUM );
   self->version( VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION );

   //====================================
   // Message setting
   #include "compiler_st.h"

   Falcon::Symbol *c_base_compiler = self->addClass( "BaseCompiler" );
   c_base_compiler->exported(false);
   self->addClassProperty( c_base_compiler, "path" );
   self->addClassProperty( c_base_compiler, "alwaysRecomp" );
   self->addClassProperty( c_base_compiler, "compileInMemory" );
   self->addClassProperty( c_base_compiler, "ignoreSources" );
   self->addClassProperty( c_base_compiler, "saveModules" );
   self->addClassProperty( c_base_compiler, "sourceEncoding" );
   self->addClassProperty( c_base_compiler, "saveMandatory" );
   self->addClassProperty( c_base_compiler, "detectTemplate" );
   self->addClassProperty( c_base_compiler, "compileTemplate" );
   self->addClassProperty( c_base_compiler, "launchAtLink" );
   self->addClassProperty( c_base_compiler, "language" );

   self->addClassMethod( c_base_compiler, "setDirective", &Falcon::Ext::BaseCompiler_setDirective).asSymbol()->
      addParam("dt")->addParam("value");
   self->addClassMethod( c_base_compiler, "addFalconPath", &Falcon::Ext::BaseCompiler_addFalconPath);


   Falcon::Symbol *c_compiler = self->addClass( "Compiler", &Falcon::Ext::Compiler_init );
   c_compiler->getClassDef()->factory( &Falcon::Ext::CompilerIfaceFactory );
   c_compiler->getClassDef()->addInheritance( new Falcon::InheritDef(c_base_compiler) );
   self->addClassMethod( c_compiler, "compile", &Falcon::Ext::Compiler_compile ).asSymbol()->
      addParam("modName")->addParam("data");
   self->addClassMethod( c_compiler, "loadByName", &Falcon::Ext::Compiler_loadByName ).asSymbol()->
      addParam("modName");
   self->addClassMethod( c_compiler, "loadFile", &Falcon::Ext::Compiler_loadFile).asSymbol()->
      addParam("modPath")->addParam( "alias" );



   Falcon::Symbol *c_icompiler = self->addClass( "ICompiler", &Falcon::Ext::ICompiler_init );
   c_icompiler->getClassDef()->factory( &Falcon::Ext::ICompilerIfaceFactory );
   c_icompiler->getClassDef()->addInheritance( new Falcon::InheritDef(c_base_compiler) );
   self->addClassProperty( c_icompiler, "stdOut" );
   self->addClassProperty( c_icompiler, "stdErr" );
   self->addClassProperty( c_icompiler, "stdIn" );
   self->addClassProperty( c_icompiler, "result" );

   self->addClassProperty( c_icompiler, "NOTHING" ).setInteger( (Falcon::int64) Falcon::InteractiveCompiler::e_nothing );
   self->addClassProperty( c_icompiler, "MORE" ).setInteger( (Falcon::int64) Falcon::InteractiveCompiler::e_more );
   self->addClassProperty( c_icompiler, "INCOMPLETE" ).setInteger( (Falcon::int64) Falcon::InteractiveCompiler::e_incomplete );
   self->addClassProperty( c_icompiler, "DECL" ).setInteger( (Falcon::int64) Falcon::InteractiveCompiler::e_decl );
   self->addClassProperty( c_icompiler, "STATEMENT" ).setInteger( (Falcon::int64) Falcon::InteractiveCompiler::e_statement );
   self->addClassProperty( c_icompiler, "EXPRESSION" ).setInteger( (Falcon::int64) Falcon::InteractiveCompiler::e_expression );
   self->addClassProperty( c_icompiler, "CALL" ).setInteger( (Falcon::int64) Falcon::InteractiveCompiler::e_call );
   self->addClassProperty( c_icompiler, "TERMINATED" ).setInteger( (Falcon::int64) Falcon::InteractiveCompiler::e_terminated );

   self->addClassMethod( c_icompiler, "compileNext", &Falcon::Ext::ICompiler_compileNext ).asSymbol()->
      addParam("code");
   self->addClassMethod( c_icompiler, "compileAll", &Falcon::Ext::ICompiler_compileAll ).asSymbol()->
      addParam("code");
   self->addClassMethod( c_icompiler, "reset", &Falcon::Ext::ICompiler_reset );


   Falcon::Symbol *c_module = self->addClass( "Module" );
   c_module->setWKS( true );
   self->addClassProperty( c_module, "name" );
   self->addClassProperty( c_module, "path" );
   self->addClassMethod( c_module, "exported", &Falcon::Ext::Module_exported );
   self->addClassMethod( c_module, "globals", &Falcon::Ext::Module_globals );
   self->addClassMethod( c_module, "get", &Falcon::Ext::Module_get ).asSymbol()->
      addParam("symName");
   self->addClassMethod( c_module, "set", &Falcon::Ext::Module_set ).asSymbol()->
      addParam("symName")->addParam("value");
   self->addClassMethod( c_module, "getReference", &Falcon::Ext::Module_getReference ).asSymbol()->
      addParam("symName");
   self->addClassMethod( c_module, "unload", &Falcon::Ext::Module_unload );
   self->addClassMethod( c_module, "engineVersion", &Falcon::Ext::Module_engineVersion );
   self->addClassMethod( c_module, "moduleVersion", &Falcon::Ext::Module_moduleVersion );
   self->addClassMethod( c_module, "attributes", &Falcon::Ext::Module_attributes );

   return self;
}


/* end of compiler.cpp */