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

prompto.instance.ItemInstance Maven / Gradle / Ivy

The newest version!
package prompto.instance;

import prompto.compiler.CompilerUtils;
import prompto.compiler.Flags;
import prompto.compiler.IOperand;
import prompto.compiler.MethodConstant;
import prompto.compiler.MethodInfo;
import prompto.compiler.Opcode;
import prompto.compiler.ResultInfo;
import prompto.error.NotMutableError;
import prompto.error.PromptoError;
import prompto.error.SyntaxError;
import prompto.expression.IExpression;
import prompto.expression.ItemSelector;
import prompto.grammar.Identifier;
import prompto.intrinsic.PromptoAny;
import prompto.intrinsic.PromptoDict;
import prompto.intrinsic.PromptoDocument;
import prompto.intrinsic.PromptoList;
import prompto.intrinsic.PromptoTuple;
import prompto.parser.CodeSection;
import prompto.parser.ICodeSection;
import prompto.runtime.Context;
import prompto.transpiler.Transpiler;
import prompto.type.AnyType;
import prompto.type.IType;
import prompto.utils.CodeWriter;
import prompto.value.IContainer;
import prompto.value.IValue;

public class ItemInstance extends CodeSection implements IAssignableSelector {

	IAssignableInstance parent;
	IExpression item;
	
	public ItemInstance(IExpression item) {
		this.item = item;
	}
	
	@Override
	public String toString() {
		return parent.toString() + "[" + item.toString() + "]";
	}
	
	@Override
	public void setParent(IAssignableInstance parent) {
		this.parent = parent;
	}
	
	public IExpression getItem() {
		return item;
	}
	
	@Override
	public void toDialect(CodeWriter writer, IExpression expression) {
		parent.toDialect(writer, null);
		writer.append('[');
		item.toDialect(writer);
		writer.append(']');
	}
	
	@Override
	public IType checkAssignValue(Context context, IType valueType, ICodeSection section) {
		// called when a[3] = value
		IType itemType = item.check(context);
		return parent.checkAssignItem(context, itemType, valueType, section);
	}
	
	@Override
	public IType checkAssignMember(Context context, Identifier memberName, IType valueType, ICodeSection section) {
		// called when a[3].member = value
		return AnyType.instance(); // TODO 
	}
	
	@Override
	public IType checkAssignItem(Context context, IType itemType, IType valueType, ICodeSection section) {
		// called when a[3][x] = value
		IType thisItemType = item.check(context);
		IType parentType = parent.checkAssignItem(context, thisItemType, valueType, section);
		return parentType.checkItem(context, itemType, section); 
	}
	
	@Override
	public void assign(Context context, IExpression expression) throws PromptoError {
		IValue root = parent.interpret(context);
		if(!root.isMutable())
			throw new NotMutableError();
		IValue idx = item.interpret(context);
		IValue value = expression.interpret(context);
		root.setItem(context, idx, value);
	}
	
	@Override
	public IValue interpret(Context context) throws PromptoError {
		IValue parent = this.parent.interpret(context);
		IValue item = this.item.interpret(context);
        if (parent instanceof IContainer)
            return ((IContainer)parent).getItem(context, item);
         else
 			throw new SyntaxError("Unknown item/key: " + item.getClass().getName());
	}
	
	@Override
	public ResultInfo compileParent(Context context, MethodInfo method, Flags flags) {
		ResultInfo parentInfo = this.parent.compileParent(context, method, flags);
		return ItemSelector.compileGetItem(context, method, flags, parentInfo, item);
	}
	
	@Override
	public ResultInfo compileAssign(Context context, MethodInfo method, Flags flags, IExpression value) {
		ResultInfo parentInfo = this.parent.compileParent(context, method, flags);
		if(Object.class==parentInfo.getType() || PromptoAny.class==parentInfo.getType() || PromptoDocument.class==parentInfo.getType())
			return compileAssignAny(context, method, flags, item, value);
		else if(PromptoList.class==parentInfo.getType())
			return compileAssignList(context, method, flags, item, value);
		else if(PromptoTuple.class==parentInfo.getType())
			return compileAssignTuple(context, method, flags, item, value);
		else if(PromptoDict.class==parentInfo.getType())
			return compileAssignDict(context, method, flags, item, value);
		else 
			throw new UnsupportedOperationException("Cannot compileAssign for " + parentInfo.getType().getTypeName());
	}
	
	private ResultInfo compileAssignList(Context context, MethodInfo method, Flags flags, IExpression item2, IExpression value) {
		ResultInfo itemInfo = item.compile(context, method, flags.withPrimitive(true));
		CompilerUtils.numberToint(method, itemInfo);
		method.addInstruction(Opcode.ICONST_M1);
		method.addInstruction(Opcode.IADD);
		value.compile(context, method, flags.withPrimitive(false));
		IOperand oper = new MethodConstant(PromptoList.class, "set", int.class, Object.class, Object.class);
		method.addInstruction(Opcode.INVOKEVIRTUAL, oper);
		method.addInstruction(Opcode.POP); // consume result
		return new ResultInfo(void.class);
	}

	private ResultInfo compileAssignTuple(Context context, MethodInfo method, Flags flags, IExpression item2, IExpression value) {
		ResultInfo itemInfo = item.compile(context, method, flags.withPrimitive(true));
		CompilerUtils.numberToint(method, itemInfo);
		method.addInstruction(Opcode.ICONST_M1);
		method.addInstruction(Opcode.IADD);
		value.compile(context, method, flags.withPrimitive(false));
		IOperand oper = new MethodConstant(PromptoTuple.class, "set", int.class, Object.class, Object.class);
		method.addInstruction(Opcode.INVOKEVIRTUAL, oper);
		method.addInstruction(Opcode.POP); // consume result
		return new ResultInfo(void.class);
	}

	private ResultInfo compileAssignDict(Context context, MethodInfo method, Flags flags, IExpression item2, IExpression value) {
		item.compile(context, method, flags.withPrimitive(false));
		value.compile(context, method, flags.withPrimitive(false));
		IOperand oper = new MethodConstant(PromptoDict.class, "put", Object.class, Object.class, Object.class);
		method.addInstruction(Opcode.INVOKEVIRTUAL, oper);
		method.addInstruction(Opcode.POP); // consume result
		return new ResultInfo(void.class);
	}

	private ResultInfo compileAssignAny(Context context, MethodInfo method, Flags flags, IExpression item, IExpression value) {
		item.compile(context, method, flags.withPrimitive(false));
		value.compile(context, method, flags.withPrimitive(false));
		IOperand oper = new MethodConstant(PromptoAny.class, "setItem", Object.class, Object.class, Object.class, void.class);
		method.addInstruction(Opcode.INVOKESTATIC, oper);
		return new ResultInfo(void.class);
	}
	
	@Override
	public IType check(Context context) {
		IType parentType = this.parent.check(context);
		IType itemType = this.item.check(context);
	    return parentType.checkItem(context, itemType, this);
	}
	
	@Override
	public void declare(Transpiler transpiler) {
	    this.parent.declare(transpiler);
	    this.item.declare(transpiler);
	}
	
	@Override
	public void declareAssign(Transpiler transpiler, IExpression expression) {
		transpiler.require("NativeError");
	    this.parent.declare(transpiler);
	    this.item.declare(transpiler);
	    expression.declare(transpiler);
	}
	
	
	@Override
	public void transpileAssign(Transpiler transpiler, IExpression expression) {
	    IType parentType = this.parent.check(transpiler.getContext());
	    this.parent.transpileAssignParent(transpiler);
	    parentType.transpileAssignItemValue(transpiler, this.item, expression);
	}
	
	@Override
	public void transpileAssignParent(Transpiler transpiler) {
	    this.parent.transpileAssignParent(transpiler);
	    transpiler.append(".getItem(");
	    this.item.transpile(transpiler);
	    transpiler.append(", true)");
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy