001: /*
002: * $Id: ModuleStatement.java,v 1.4 2002/09/16 08:05:06 jkl Exp $
003: *
004: * Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
005: *
006: * Use is subject to license terms, as defined in
007: * Anvil Sofware License, Version 1.1. See LICENSE
008: * file, or http://njet.org/license-1.1.txt
009: */
010: package anvil.script.statements;
011:
012: import java.io.IOException;
013: import java.net.URL;
014: import java.util.Enumeration;
015: import java.util.Iterator;
016: import java.util.Calendar;
017: import java.util.HashSet;
018: import java.util.HashMap;
019: import anvil.ForgingException;
020: import anvil.java.util.BindingEnumeration;
021: import anvil.core.Any;
022: import anvil.core.AnyString;
023: import anvil.core.Array;
024: import anvil.core.Modules;
025: import anvil.core.runtime.AnyFunction;
026: import anvil.ErrorListener;
027: import anvil.Location;
028: import anvil.Log;
029: import anvil.codec.Code;
030: import anvil.codec.ClassRoom;
031: import anvil.codec.Field;
032: import anvil.codec.Method;
033: import anvil.codec.CodecConstants;
034: import anvil.codec.ConstantPool;
035: import anvil.doc.Doc;
036: import anvil.doc.DocParser;
037: import anvil.parser.Tag;
038: import anvil.ErrorListener;
039: import anvil.script.ClassType;
040: import anvil.script.CompilableFunction;
041: import anvil.script.compiler.ByteCompiler;
042: import anvil.script.Context;
043: import anvil.script.Type;
044: import anvil.script.Function;
045: import anvil.script.Dependency;
046: import anvil.script.Import;
047: import anvil.script.InterfaceType;
048: import anvil.script.Namespace;
049: import anvil.script.NamespaceType;
050: import anvil.script.parser.TemplateParser;
051: import anvil.script.Scope;
052: import anvil.script.Module;
053: import anvil.script.ModuleEnvelope;
054: import anvil.script.Grammar;
055: import anvil.script.expression.Expression;
056: import anvil.script.statements.taglib.TagLibrary;
057: import anvil.server.Address;
058: import anvil.server.LocalizationPreferences;
059: import anvil.server.Zone;
060: import anvil.java.util.Hashlist;
061: import anvil.java.util.Holder;
062:
063: /**
064: * class ModuleStatement
065: *
066: * @author: Jani Lehtimäki
067: */
068: public class ModuleStatement extends DefinitionStatement implements
069: Module, CodecConstants {
070:
071: private ModuleEnvelope _envelope;
072: private Address _address;
073: private BlockStatement _staticinit;
074: private BlockStatement _init;
075: private int _inlinecount;
076: private Method _constructor;
077: private HashMap _dependencies = new HashMap();
078:
079: public ModuleStatement(ModuleEnvelope envelope, Location location) {
080: super (null, location);
081: init(envelope, location);
082: }
083:
084: public ModuleStatement(ModuleEnvelope envelope, Location location,
085: String name, String document) {
086: super (null, location, name, DocParser.parseModule(name,
087: document));
088: init(envelope, location);
089: declare(new ImportedModuleStatement(name, this , _document));
090: }
091:
092: private void init(ModuleEnvelope envelope, Location location) {
093: _staticinit = new ImplicitBlockStatement(this , location);
094: _init = new ImplicitBlockStatement(this , location);
095: _envelope = envelope;
096: _address = envelope.getAddress();
097: _descriptor = envelope.getDescriptor();
098: _contentstate = envelope.getAddress().getZone()
099: .getContentProcessing();
100: declare(new ImportedModuleStatement("module", this , null));
101: addExternal(Context.GLOBAL, Context.TYPE);
102: }
103:
104: public int typeOf() {
105: return Statement.ST_MODULE;
106: }
107:
108: public String name() {
109: return "module";
110: }
111:
112: public int getType() {
113: return MODULE;
114: }
115:
116: public Scope getParent() {
117: return null;
118: }
119:
120: public String getQualifiedName() {
121: return "";
122: }
123:
124: public void addDependency(Import imprt) {
125: Address addr = imprt.getAddress();
126: if (addr != null) {
127: _dependencies.put(addr, new Dependency(addr, null, imprt
128: .getLocation()));
129: }
130: }
131:
132: public Iterator getDependencies() {
133: return _dependencies.values().iterator();
134: }
135:
136: public Dependency getDependency(Address address) {
137: return (Dependency) _dependencies.get(address);
138: }
139:
140: public ModuleEnvelope getEnvelope() {
141: return _envelope;
142: }
143:
144: public Address getAddress() {
145: return _address;
146: }
147:
148: public String getPathinfo() {
149: return _address.getPathinfo();
150: }
151:
152: public int getNextInlined() {
153: return _inlinecount++;
154: }
155:
156: public boolean isStaticRegion() {
157: return true;
158: }
159:
160: public Type lookupDeclaration(String name) {
161: Type type = (Type) _types.get(name);
162: if (type != null) {
163: return type;
164: }
165: Namespace ns = _address.getZone().getNamespace(name);
166: if (ns != null) {
167: type = new ImportedNamespaceStatement(this , name, null);
168: if (type != null) {
169: return type;
170: }
171: }
172: return super .lookupDeclaration(name);
173: }
174:
175: public VariableStatement declare(Location location, String name,
176: Expression expr, String document, boolean statik) {
177: VariableStatement var;
178: declare(var = new StaticVariableStatement(location, this , name,
179: expr, document));
180: return var;
181: }
182:
183: public void parse(TemplateParser parser, Tag tag) {
184: super .parse(parser, tag);
185: String name = tag.getValue("name");
186: if (name != null) {
187: if (Grammar.isValidIdentifier(name)) {
188: declare(new ImportedModuleStatement(name, this , null));
189: _name = name;
190: } else {
191: parser.error(getLocation(), "Template name '" + _name
192: + "' is invalid");
193: }
194: } else {
195: _name = "module";
196: }
197: _document = DocParser.parseModule(_name, parser.getDocument());
198: declare(new ImportedModuleStatement(_name, this , _document));
199: }
200:
201: private void addInitializers(Enumeration types) {
202: while (types.hasMoreElements()) {
203: Type type = (Type) types.nextElement();
204: switch (type.getType()) {
205: case STATIC_VARIABLE:
206: case CONSTANT_VARIABLE:
207: VariableStatement var = (VariableStatement) type;
208: _staticinit.add(new EvalStatement(_staticinit,
209: getLocation(), var.createStaticInitializer()));
210: if (!var.hasConstantInitializer()) {
211: _init.add(new EvalStatement(_init, getLocation(),
212: var.createInitializer()));
213: }
214: break;
215: case CLASS:
216: case INTERFACE:
217: case NAMESPACE:
218: addInitializers(((Scope) type).getDeclarations());
219: break;
220: }
221: }
222:
223: }
224:
225: public void check(ErrorListener context) {
226: super .check(context);
227: addInitializers(getDeclarations());
228: }
229:
230: public final synchronized void init(Context context) {
231: throw new RuntimeException(
232: "Attempted to call 'void init(Context)' on ModuleStatement");
233: }
234:
235: public void onCharacters(TemplateParser parser, String cdata) {
236: }
237:
238: public boolean onTag(TemplateParser parser, int type, Tag tag) {
239: switch (type) {
240: case ST_TAG:
241: break;
242:
243: case ST_IMPORT:
244: onImport(parser, tag);
245: break;
246:
247: case ST_VAR:
248: onVar(parser, tag);
249: break;
250:
251: case ST_CONST:
252: onConst(parser, tag);
253: break;
254:
255: case ST_FUNCTION:
256: onFunction(parser, type, tag);
257: break;
258:
259: case ST_CLASS:
260: onClass(parser, type, tag);
261: break;
262:
263: case ST_NAMESPACE:
264: onNamespace(parser, type, tag);
265: break;
266:
267: case ST_ENDMODULE:
268: parser.pop();
269: break;
270:
271: default:
272: return false;
273: }
274:
275: return true;
276: }
277:
278: public Method getConstructor() {
279: return _constructor;
280: }
281:
282: public void compileConstructor(ByteCompiler context) {
283: ClassRoom clazz = context.getClassRoom();
284: ConstantPool pool = clazz.getPool();
285: Method constructor = clazz.createConstructor("()V", ACC_PUBLIC);
286: _constructor = constructor;
287: Code code = constructor.getCode();
288:
289: StringBuffer clsid = new StringBuffer();
290: clsid.append("$Id: ");
291: clsid.append(_address.getPathinfo());
292: clsid.append(" 1.0 ");
293: LocalizationPreferences prefs = _address.getZone()
294: .getLocalizationPreferences();
295: Calendar cal = Calendar.getInstance(
296: prefs.getTimezoneInstance(), prefs.getLocaleInstance());
297: anvil.util.Conversions.toString(clsid, cal);
298: Field clsidfield = clazz.createField("_id",
299: "Ljava/lang/String;", ACC_PUBLIC | ACC_STATIC
300: | ACC_FINAL);
301: clsidfield.setConstantValue(pool.addString(clsid.toString()));
302:
303: context.pushCode(code);
304: code.self();
305: code.invokespecial(pool
306: .addMethodRef("anvil/script/compiler/CompiledModule",
307: "<init>", "()V"));
308: context.popCode();
309:
310: Method versionmethod = clazz.createMethod("getVersion", "()I",
311: ACC_PUBLIC);
312: code = versionmethod.getCode();
313: context.pushCode(code);
314: code.iconst(_envelope.getVersion());
315: code.ireturn();
316:
317: clazz.createField("_module",
318: "Lanvil/script/compiler/CompiledModule;", ACC_PUBLIC
319: | ACC_STATIC);
320: clazz.createField("_type", "Lanvil/core/Any;", ACC_PUBLIC
321: | ACC_STATIC);
322:
323: context.popCode();
324: }
325:
326: public void compileStaticInit(ByteCompiler context) {
327: ClassRoom clazz = context.getClassRoom();
328: Code code = clazz.getStatic().getCode();
329: ConstantPool pool = code.getPool();
330: context.pushCode(code);
331: if (_staticinit != null) {
332: _staticinit.compile(context);
333: }
334: Enumeration e = _types.elements();
335: while (e.hasMoreElements()) {
336: Type type = (Type) e.nextElement();
337: int typeid = type.getType();
338: if (typeid == CLASS || typeid == INTERFACE) {
339: code.getstatic(pool.addFieldRef(type.getTypeRef(pool),
340: "_members", "[Ljava/lang/Object;"));
341: code.pop();
342: }
343: }
344: context.popCode();
345: }
346:
347: public void compileInit(ByteCompiler context) {
348: ClassRoom clazz = context.getClassRoom();
349: Method method = clazz.createMethod("init",
350: "(Lanvil/script/Context;)V", ACC_PUBLIC | ACC_FINAL
351: | ACC_SYNCHRONIZED);
352: Code code = method.getCode();
353: context.pushCode(code);
354: code.addLocal();
355: if (_init != null) {
356: _init.compile(context);
357: }
358: code.vreturn();
359: context.popCode();
360: }
361:
362: private void compileDependencies(ByteCompiler context) {
363: ClassRoom clazz = context.getClassRoom();
364: Code code = context.getCode();
365: ConstantPool pool = code.getPool();
366: Field field = clazz.createField("_imports",
367: "[Ljava/lang/String;", Code.ACC_PUBLIC
368: | Code.ACC_STATIC);
369: code.iconst(_dependencies.size() * 2);
370: code.anewarray("java/lang/String");
371: Iterator iter = _dependencies.values().iterator();
372: for (int i = 0; iter.hasNext();) {
373: Dependency dep = (Dependency) iter.next();
374: code.dup();
375: code.iconst(i++);
376: code.astring(dep.getPathinfo());
377: code.aastore();
378: code.dup();
379: code.iconst(i++);
380: code.astring(dep.getDescriptor());
381: code.aastore();
382: }
383: code.putstatic(field);
384:
385: }
386:
387: public void compile(ByteCompiler context) {
388: compileMembers(context, _types.size(), _types.elements());
389: compileDependencies(context);
390: compileConstructor(context);
391: compileStaticInit(context);
392: compileInit(context);
393: super.compile(context);
394: _constructor.getCode().vreturn();
395: }
396:
397: }
|