All Downloads are FREE. Search and download functionalities are using the official Maven repository.

prompto.param.ExtendedParameter Maven / Gradle / Ivy

The newest version!
package prompto.param;

import java.lang.reflect.Type;
import java.util.Objects;

import prompto.compiler.ClassConstant;
import prompto.compiler.CompilerUtils;
import prompto.compiler.Flags;
import prompto.compiler.MethodConstant;
import prompto.compiler.MethodInfo;
import prompto.compiler.Opcode;
import prompto.compiler.ResultInfo;
import prompto.declaration.AttributeDeclaration;
import prompto.declaration.ConcreteCategoryDeclaration;
import prompto.declaration.IDeclaration;
import prompto.error.PromptoError;
import prompto.error.SyntaxError;
import prompto.grammar.ArgumentList;
import prompto.grammar.INamed;
import prompto.grammar.Identifier;
import prompto.intrinsic.PromptoProxy;
import prompto.runtime.Context;
import prompto.type.IType;
import prompto.utils.CodeWriter;
import prompto.utils.IdentifierList;

public class ExtendedParameter extends CategoryParameter {
	
	IdentifierList attributes;
	
	public ExtendedParameter(IType type, Identifier id, IdentifierList attributes) {
		super(type, id);
		this.attributes = attributes;
	}

	public IdentifierList getAttributes() {
		return attributes;
	}
	
	@Override
	public String getProto() {
		return type.getTypeNameId().toString() + '(' + attributes.toString() + ')';
	}
	
	@Override
	public void toDialect(CodeWriter writer) {
		if(mutable)
			writer.append("mutable ");
		switch(writer.getDialect()) {
		case E:
			toEDialect(writer);
			break;
		case O:
			toODialect(writer);
			break;
		case M:
			toMDialect(writer);
			break;
		}
		if(defaultExpression!=null) {
			writer.append(" = ");
			defaultExpression.toDialect(writer);
		}
	}
	
	private void toEDialect(CodeWriter writer) {
		type.toDialect(writer);
		writer.append(' ');
		writer.append(id);
		switch(attributes.size()) {
		case 0:
			break;
		case 1:
			writer.append(" with attribute ");
			attributes.toDialect(writer, false);
			break;
		default:
			writer.append(" with attributes ");
			attributes.toDialect(writer, true);
			break;
		}
	}

	private void toODialect(CodeWriter writer) {
		type.toDialect(writer);
		writer.append('(');
		attributes.toDialect(writer, false);
		writer.append(')');
		writer.append(' ');
		writer.append(id);
	}

	private void toMDialect(CodeWriter writer) {
		writer.append(id);
		writer.append(':');
		type.toDialect(writer);
		writer.append('(');
		attributes.toDialect(writer, false);
		writer.append(')');
	}

	@Override
	public String toString() {
		return id.toString() + ':' + getProto();
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj==this)
			return true;
		if(obj==null)
			return false;
		if(!(obj instanceof ExtendedParameter))
			return false;
		ExtendedParameter other = (ExtendedParameter)obj;
		return Objects.equals(this.getType(),other.getType())
				&& Objects.equals(this.getId(),other.getId())
				&& Objects.equals(this.getAttributes(),other.getAttributes());
	}

	@Override
	public void register(Context context) {
		INamed actual = context.getRegisteredValue(INamed.class, id);
		if(actual!=null)
			throw new SyntaxError("Duplicate argument: \"" + id + "\"");
		ConcreteCategoryDeclaration declaration = 
				new ConcreteCategoryDeclaration(id, attributes,
						new IdentifierList(type.getTypeNameId()), null);
		context.registerDeclaration(declaration);
		context.registerInstance(this);
		if(defaultExpression!=null) try {
			context.setValue(id, defaultExpression.interpret(context));
		} catch(PromptoError error) {
			throw new SyntaxError("Unable to register default value: "+ defaultExpression.toString() + " for argument: " + id);
		}
	}
	
	@Override
	public IType check(Context context) {
		type.checkExists(context);
		for(Identifier attribute : attributes) {
			AttributeDeclaration actual = context.getRegisteredDeclaration(AttributeDeclaration.class, attribute);
			if(actual==null)
				throw new SyntaxError("Unknown attribute: \"" + attribute + "\"");
		}
		return type;
	}
	
	@Override
	public IType getType(Context context) {
		IDeclaration decl = context.getRegisteredDeclaration(IDeclaration.class, id);
		return decl!=null ? decl.getType(context) :this.type;
	}
	
	@Override
	public Type getJavaType(Context context) {
		return CompilerUtils.getExtendedInterfaceType(type.getTypeNameId(), attributes);
	}

	@Override
	public ResultInfo compileParameter(Context context, MethodInfo method, Flags flags, ArgumentList assignments, boolean isFirst) {
		super.compileParameter(context, method, flags, assignments, isFirst);
		// create a proxy to the required java type
		ClassConstant c = new ClassConstant(getJavaType(context));
		method.addInstruction(Opcode.LDC, c);
		MethodConstant m = new MethodConstant(PromptoProxy.class, "newProxy", Object.class, Class.class, Object.class);
		method.addInstruction(Opcode.INVOKESTATIC, m);
		method.addInstruction(Opcode.CHECKCAST, c);
		return new ResultInfo(c.getType());
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy