001: package gnu.expr;
002:
003: import gnu.bytecode.*;
004:
005: public class ProcInitializer extends Initializer {
006: LambdaExp proc;
007:
008: public ProcInitializer(LambdaExp lexp, Compilation comp) {
009: field = lexp.allocFieldFor(comp);
010: proc = lexp;
011: LambdaExp heapLambda = lexp.getOwningLambda();
012: if (heapLambda instanceof ModuleExp && comp.isStatic()) {
013: next = comp.clinitChain;
014: comp.clinitChain = this ;
015: } else {
016: next = heapLambda.initChain;
017: heapLambda.initChain = this ;
018: }
019: }
020:
021: /** Create and load a ModuleMethod for the given procedure. */
022: public static void emitLoadModuleMethod(LambdaExp proc,
023: Compilation comp) {
024: CodeAttr code = comp.getCode();
025: ClassType procClass = Compilation.typeModuleMethod;
026: code.emitNew(procClass);
027: code.emitDup(1);
028: LambdaExp owning = proc.getOwningLambda();
029: if (owning instanceof ClassExp
030: && owning.staticLinkField != null)
031: code.emitLoad(code.getCurrentScope().getVariable(1));
032: else if (!(owning instanceof ModuleExp)
033: || (comp.moduleClass == comp.mainClass && !comp.method
034: .getStaticFlag()))
035: code.emitPushThis();
036: else {
037: if (comp.moduleInstanceVar == null) {
038: comp.moduleInstanceVar = code.locals.current_scope
039: .addVariable(code, comp.moduleClass,
040: "$instance");
041: if (comp.moduleClass != comp.mainClass
042: && !comp.isStatic()) {
043: code.emitNew(comp.moduleClass);
044: code.emitDup(comp.moduleClass);
045: code
046: .emitInvokeSpecial(comp.moduleClass.constructor);
047: comp.moduleInstanceMainField = comp.moduleClass
048: .addField("$main", comp.mainClass, 0);
049: code.emitDup(comp.moduleClass);
050: code.emitPushThis();
051: code.emitPutField(comp.moduleInstanceMainField);
052: } else
053: code.emitGetStatic(comp.moduleInstanceMainField);
054: code.emitStore(comp.moduleInstanceVar);
055: }
056: code.emitLoad(comp.moduleInstanceVar);
057: }
058: code.emitPushInt(proc.getSelectorValue(comp));
059: comp.compileConstant(proc.nameDecl != null ? proc.nameDecl
060: .getSymbol() : proc.getName(), Target.pushObject);
061: // If there are keyword arguments, we treat that as "unlimited" maxArgs,
062: // so that ModuleBody.matchX methods call matchN. A kludge, I guess.
063: code.emitPushInt(proc.min_args
064: | ((proc.keywords == null ? proc.max_args : -1) << 12));
065: Method initModuleMethod = procClass.getDeclaredMethod("<init>",
066: 4);
067: code.emitInvokeSpecial(initModuleMethod);
068:
069: if (proc.properties != null) {
070: int len = proc.properties.length;
071: for (int i = 0; i < len; i += 2) {
072: Object key = proc.properties[i];
073: // Skip "name" property since we've taken care of that specially.
074: if (key != null && key != "name") {
075: Object val = proc.properties[i + 1];
076: code.emitDup(1);
077: comp.compileConstant(key);
078: Target target = Target.pushObject;
079: if (val instanceof Expression)
080: ((Expression) val).compile(comp, target);
081: else
082: comp.compileConstant(val, target);
083: Method m = (ClassType
084: .make("gnu.mapping.PropertySet")
085: .getDeclaredMethod("setProperty", 2));
086: code.emitInvokeVirtual(m);
087: }
088: }
089: }
090: }
091:
092: public void emit(Compilation comp) {
093: CodeAttr code = comp.getCode();
094: if (!field.getStaticFlag())
095: code.emitPushThis();
096:
097: emitLoadModuleMethod(proc, comp);
098:
099: if (field.getStaticFlag())
100: code.emitPutStatic(field);
101: else
102: code.emitPutField(field);
103: }
104:
105: public void reportError(String message, Compilation comp) {
106: String saveFile = comp.getFileName();
107: int saveLine = comp.getLineNumber();
108: int saveColumn = comp.getColumnNumber();
109: comp.setLocation(proc);
110: String name = proc.getName();
111: StringBuffer sbuf = new StringBuffer(message);
112: if (name == null)
113: sbuf.append("unnamed procedure");
114: else {
115: sbuf.append("procedure ");
116: sbuf.append(name);
117: }
118: comp.error('e', sbuf.toString());
119: comp.setLine(saveFile, saveLine, saveColumn);
120: }
121: }
|