001: /**************************************************************************/
002: /* N I C E */
003: /* A high-level object-oriented research language */
004: /* (c) Daniel Bonniot 2000 */
005: /* */
006: /* This program is free software; you can redistribute it and/or modify */
007: /* it under the terms of the GNU General Public License as published by */
008: /* the Free Software Foundation; either version 2 of the License, or */
009: /* (at your option) any later version. */
010: /* */
011: /**************************************************************************/package nice.tools.code;
012:
013: import gnu.bytecode.*;
014: import gnu.expr.*;
015:
016: /**
017: Code generation functions.
018: */
019: public class Gen {
020:
021: public static Expression instanceOfExp(Expression value, Type ct) {
022: return Inline.inline(nice.lang.inline.Instanceof.instance,
023: value, new QuoteExp(ct));
024: }
025:
026: public static Expression isOfClass(Expression value, Type ct,
027: boolean possiblyNull) {
028: return Inline
029: .inline(new IsOfClassProc(ct, possiblyNull), value);
030: }
031:
032: public static Expression isNullExp(Expression value) {
033: return Inline.inline(nice.lang.inline.ReferenceOp.create("=="),
034: value, QuoteExp.nullExp);
035: }
036:
037: public static Expression referenceEqualsExp(Expression value1,
038: Expression value2) {
039: return Inline.inline(nice.lang.inline.ReferenceOp.create("=="),
040: value1, value2);
041: }
042:
043: public static Expression boolNotExp(Expression value) {
044: return Inline
045: .inline(nice.lang.inline.BoolNotOp.instance, value);
046: }
047:
048: public static Expression integerComparison(String kind,
049: Expression value1, long value2) {
050: char type = value1.getType().getSignature().charAt(0);
051: if (type == 'J')
052: return Inline.inline(nice.lang.inline.CompOp.create("l"
053: + kind), value1, new gnu.expr.QuoteExp(new Long(
054: value2), gnu.bytecode.Type.long_type));
055:
056: if (type == 'B' || type == 'S' || type == 'I' || type == 'C')
057: return Inline.inline(nice.lang.inline.CompOp.create("i"
058: + kind), value1, new gnu.expr.QuoteExp(new Long(
059: value2), gnu.bytecode.Type.int_type));
060:
061: throw bossa.util.Internal.error("not an integer type");
062: }
063:
064: public static Expression shortCircuitAnd(Expression value1,
065: Expression value2) {
066: if (value1 == QuoteExp.trueExp)
067: return value2;
068: if (value2 == QuoteExp.trueExp)
069: return value1;
070:
071: return Inline.inline(nice.lang.inline.ShortCircuitOp
072: .create("&&"), value1, value2);
073: }
074:
075: public static Expression stringEquals(String value1,
076: Expression value2) {
077: return new ApplyExp(equals, new Expression[] {
078: new QuoteExp(value1, Type.string_type), value2 });
079: }
080:
081: private static final Expression equals = new QuoteExp(
082: new PrimProcedure(Type.pointer_type.getDeclaredMethod(
083: "equals", 1)));
084:
085: /**
086: Create a lambda expression to generate code for the method.
087:
088: @param args can be null if there are no arguments
089: @param member true iff this method is a non-static member of
090: the class in argTypes[0]
091: @param toplevel If the method can be called from foreign code.
092: This forces its generation even if it is
093: apparently never called.
094: **/
095: public static LambdaExp createMemberMethod(String bytecodeName,
096: Type receiver, Type[] argTypes, Type retType,
097: Expression[] params) {
098: Declaration this Decl = new Declaration("this");
099: LambdaExp lexp = new MemberLambdaExp(this Decl);
100:
101: bytecodeName = nice.tools.code.Strings.escape(bytecodeName);
102: int arity = 1 + (argTypes == null ? 0 : argTypes.length);
103:
104: lexp.setReturnType(retType);
105: lexp.setName(bytecodeName);
106: lexp.min_args = lexp.max_args = arity - 1;
107: lexp.forceGeneration();
108: lexp.setCanCall(true);
109: lexp.setClassMethod(true);
110:
111: // Parameters
112: for (int n = 0; n < arity; n++) {
113: boolean isThis = n == 0;
114: String parameterName = "anonymous_" + n;
115:
116: gnu.expr.Declaration d;
117: if (isThis) {
118: d = this Decl;
119: d.setType(receiver);
120: params[n] = new ThisExp(d);
121: } else {
122: d = lexp.addDeclaration(parameterName);
123: d.setType(argTypes[n - 1]);
124: params[n] = new ReferenceExp(d);
125: }
126: d.noteValue(null);
127: d.setCanRead(true);
128: d.setCanWrite(true);
129: }
130:
131: return lexp;
132: }
133:
134: public static void setMethodBody(LambdaExp method, Expression body) {
135: method.body = body;
136: }
137:
138: /**
139: @return the lambda expression referenced.
140: */
141: public static LambdaExp dereference(Expression ref) {
142: return (LambdaExp) ((ReferenceExp) ref).getBinding().getValue();
143: }
144:
145: public static Expression returnVoid() {
146: return Inline.inline(nice.lang.inline.Return.instance);
147: }
148:
149: public static Expression returnValue(Expression value) {
150: return Inline.inline(nice.lang.inline.Return.instance, value);
151: }
152:
153: public static void store(Compilation comp, Expression destination,
154: Target target) {
155: if (destination instanceof ReferenceExp) {
156: ((ReferenceExp) destination).getBinding()
157: .compileStore(comp);
158: return;
159: }
160:
161: // Destination must be a field.
162: gnu.bytecode.CodeAttr code = comp.getCode();
163:
164: ApplyExp apply = (ApplyExp) destination;
165: GetFieldProc fieldProc = (GetFieldProc) ((QuoteExp) apply
166: .getFunction()).getValue();
167: Field field = fieldProc.getField();
168:
169: apply.getArgs()[0].compile(comp, field.getDeclaringClass());
170: code.emitSwap();
171: code.emitPutField(field);
172: }
173:
174: /** Creates a LambdaExp that applies a Procedure
175: * to the appropriate number of arguments.
176: *
177: * This is usefull to generate an Expression from a given Procedure.
178: */
179: public static LambdaExp wrapInLambda(gnu.mapping.Procedure proc) {
180: int numArgs = proc.minArgs();
181:
182: LambdaExp lambda = new LambdaExp();
183: lambda.min_args = lambda.max_args = numArgs;
184:
185: Expression[] args = new Expression[numArgs];
186: for (int i = 0; i < numArgs; i++) {
187: // The parameters have type Object, since calls to anonymous functions
188: // have never precise types.
189: // Besides, work would be needed to know the types in the case
190: // of inlined methods (macros).
191: Declaration decl = lambda.addDeclaration("param__" + i,
192: Type.pointer_type);
193:
194: args[i] = new ReferenceExp(decl);
195: }
196:
197: lambda.body = new ApplyExp(proc, args);
198: return lambda;
199: }
200:
201: public static Expression super Call(Expression method,
202: Expression[] args) {
203: return new ApplyExp(method, args, true);
204: }
205:
206: public static Expression super Caller(Method method) {
207: return new QuoteExp(PrimProcedure.specialCall(method));
208: }
209: }
|