001: package gnu.kawa.functions;
002:
003: import kawa.standard.Scheme;
004: import gnu.bytecode.Type;
005: import gnu.bytecode.ClassType;
006: import gnu.bytecode.CodeAttr;
007: import gnu.mapping.*;
008: import gnu.expr.*;
009: import gnu.kawa.reflect.Invoke;
010:
011: public class Convert extends Procedure2 implements CanInline,
012: Inlineable {
013: public static final Convert as = new Convert();
014: static {
015: as.setName("as");
016: }
017:
018: public static Convert getInstance() {
019: return as;
020: }
021:
022: public Object apply2(Object arg1, Object arg2) {
023: Type type = (Type) arg1;
024: return type.coerceFromObject(arg2);
025: }
026:
027: static gnu.bytecode.ClassType typeType;
028: static gnu.bytecode.Method coerceMethod;
029:
030: public Expression inline(ApplyExp exp, ExpWalker walker) {
031: return Invoke.inlineClassName(exp, 0, (InlineCalls) walker);
032: }
033:
034: public void compile(ApplyExp exp, Compilation comp, Target target) {
035: Expression[] args = exp.getArgs();
036: if (args.length != 2)
037: throw new Error("wrong number of arguments to " + getName());
038: CodeAttr code = comp.getCode();
039: Type type = Scheme.getTypeValue(args[0]);
040: if (type != null) {
041: args[1].compile(comp, Target.pushValue(type));
042: if (code.reachableHere())
043: target.compileFromStack(comp, type);
044: } else {
045: if (typeType == null) {
046: typeType = ClassType.make("gnu.bytecode.Type");
047: coerceMethod = typeType.addMethod("coerceFromObject",
048: Compilation.apply1args, Type.pointer_type,
049: gnu.bytecode.Access.PUBLIC);
050: }
051:
052: args[0].compile(comp, typeType);
053: args[1].compile(comp, Target.pushObject);
054: code.emitInvokeVirtual(coerceMethod);
055: target.compileFromStack(comp, Type.pointer_type);
056: }
057: }
058:
059: public Type getReturnType(Expression[] args) {
060: if (args != null && args.length == 2) {
061: Type type = Scheme.getTypeValue(args[0]);
062: if (type != null)
063: return type;
064: }
065: return Type.pointer_type;
066: }
067:
068: /**
069: * Convenience method to make an Expression that coerces a value.
070: * @param value to be coerced
071: * @param type to coerce value to
072: * @return expression that coerces value to type
073: */
074: public static Expression makeCoercion(Expression value,
075: Expression type) {
076: Expression[] exps = new Expression[2];
077: exps[0] = type;
078: exps[1] = value;
079: QuoteExp c = new QuoteExp(Convert.getInstance());
080: return new ApplyExp(c, exps);
081: }
082:
083: /**
084: * Convenience method to make an Expression that coerces a value.
085: * @param value to be coerced
086: * @param type to coerce value to
087: * @return expression that coerces value to type
088: */
089: public static Expression makeCoercion(Expression value, Type type) {
090: return makeCoercion(value, new QuoteExp(type));
091: }
092:
093: /** Modify LambdaExp so result is coerced to given type. */
094: public static void setCoercedReturnValue(LambdaExp lexp,
095: Expression type, Language language) {
096: gnu.bytecode.Type rtype = language.getTypeFor(type);
097: if (rtype != null) {
098: Expression value = lexp.body;
099: lexp.body = Convert.makeCoercion(value, type);
100: lexp.body.setLine(value);
101: lexp.setReturnType(rtype);
102: }
103: }
104: }
|