package sharpen.xobotos.api.interop; import sharpen.xobotos.api.interop.glue.*; import java.util.EnumSet; public final class NativeVariable { private final IVariable _var; private final EnumSet<NativeVariable.Flags> _flags; public enum Flags { CLASS, CONST, BYREF, REF, OUT } private static AbstractTypeReference getEffectiveType(AbstractTypeReference type, EnumSet<NativeVariable.Flags> flags) { if (flags.contains(Flags.OUT)) { return new PointerType(new PointerType(type)); } else if (flags.contains(Flags.BYREF)) { if (flags.contains(Flags.CONST)) return new ConstPointerType(type); else return new PointerType(type); } else if (flags.contains(Flags.CONST)) return new ConstReferenceType(type); else if (flags.contains(Flags.REF)) return new ReferenceType(type); else return type; } public static NativeVariable createLocal(Block body, AbstractTypeReference type, String name, Expression init, NativeVariable.Flags... flags) { return createLocal(body, type, name, init, HelperClassBuilder.buildSet(NativeVariable.Flags.class, flags)); } public static NativeVariable createLocal(Block body, AbstractTypeReference type, String name, Expression init, EnumSet<NativeVariable.Flags> flags) { AbstractTypeReference effective = getEffectiveType(type, flags); LocalVariable var = new LocalVariable(effective, name, init); body.addStatement(var); return new NativeVariable(var, flags); } public static NativeVariable createLocal(INativeMarshalContext context, AbstractTypeReference type, String name, Expression init, NativeVariable.Flags... flags) { return createLocal(context, type, name, init, HelperClassBuilder.buildSet(NativeVariable.Flags.class, flags)); } public static NativeVariable createLocal(INativeMarshalContext context, AbstractTypeReference type, String name, Expression init, EnumSet<NativeVariable.Flags> flags) { AbstractTypeReference effective = getEffectiveType(type, flags); NativeVariable var = context.createVariable(name, effective, init); var._flags.addAll(flags); return var; } public static NativeVariable createParameter(AbstractMethod method, AbstractTypeReference type, String name, NativeVariable.Flags... flags) { EnumSet<NativeVariable.Flags> e = HelperClassBuilder.buildSet(NativeVariable.Flags.class, flags); AbstractTypeReference effective = getEffectiveType(type, e); Parameter param = new Parameter(effective, name); method.addParameter(param); return new NativeVariable(param, e); } public static NativeVariable createParameter(INativeMarshalContext context, AbstractTypeReference type, String name, NativeVariable.Flags... flags) { EnumSet<NativeVariable.Flags> e = HelperClassBuilder.buildSet(NativeVariable.Flags.class, flags); AbstractTypeReference effective = getEffectiveType(type, e); NativeVariable var = context.createParameter(name, effective); var._flags.addAll(e); return var; } private NativeVariable(IVariable var, EnumSet<NativeVariable.Flags> flags) { this._var = var; this._flags = flags; } public NativeVariable(IVariable var, Flags... flags) { this._var = var; this._flags = HelperClassBuilder.buildSet(Flags.class, flags); } public Expression getReference() { return new VariableReference(_var); } public Expression getAddressOfExpr() { return new AddressOfExpression(getReference()); } public boolean isTarget() { return _flags.contains(Flags.CLASS); } public boolean isByRef() { return _flags.contains(Flags.BYREF) || _flags.contains(Flags.OUT); } public Expression getMemberAccess(String name) { if (isByRef()) return new InstanceMemberAccess(getReference(), name); else return new StructMemberAccess(getReference(), name); } public Expression getDereferenceExpr() { if (!isByRef()) throw new IllegalStateException(); return new DereferenceExpression(getReference()); } }