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

prompto.statement.BaseSwitchStatement Maven / Gradle / Ivy

The newest version!
package prompto.statement;

import java.util.LinkedList;
import java.util.Objects;

import prompto.error.ExecutionError;
import prompto.error.PromptoError;
import prompto.parser.ICodeSection;
import prompto.parser.ISection;
import prompto.runtime.Context;
import prompto.transpiler.Transpiler;
import prompto.type.IType;
import prompto.type.TypeMap;
import prompto.type.VoidType;
import prompto.utils.CodeWriter;
import prompto.value.IValue;


public abstract class BaseSwitchStatement extends BaseStatement {

	public static class SwitchCaseList extends LinkedList {

		private static final long serialVersionUID = 1L;
		
		public SwitchCaseList() {
		}

		public SwitchCaseList(SwitchCase item) {
			this.add(item);
		}

		public ICodeSection locateCodeSection(ISection section) {
			return this.stream()
					.map(s->s.locateCodeSection(section))
					.filter(Objects::nonNull)
					.findFirst()
					.orElse(null);
		}

	}
	
	SwitchCaseList switchCases;
	StatementList defaultCase;
	
	public BaseSwitchStatement() {
		this.switchCases = new SwitchCaseList();
		this.defaultCase = null;
	}

	public BaseSwitchStatement(SwitchCaseList switchCases, StatementList defaultCase) {
		this.switchCases = switchCases!=null ? switchCases : new SwitchCaseList();
		this.defaultCase = defaultCase;
	}

	public void addSwitchCase(SwitchCase switchCase) {
		switchCases.add(switchCase);
	}

	public void setDefaultCase(StatementList defaultCase) {
		this.defaultCase = defaultCase;
	}
	
	@Override
	public ICodeSection locateCodeSection(ISection section) {
		ICodeSection result = switchCases.locateCodeSection(section);
		if(result==null && defaultCase!=null)
			result = defaultCase.locateCodeSection(section);
		return result!=null ? result : super.locateCodeSection(section);
	}
	

	@Override
	public void toDialect(CodeWriter writer) {
		switch(writer.getDialect()) {
		case E:
			toEDialect(writer);
			break;
		case O:
			toODialect(writer);
			break;
		case M:
			toMDialect(writer);
			break;
		}
	}
	
	protected abstract void toEDialect(CodeWriter writer);
	protected abstract void toODialect(CodeWriter writer);
	protected abstract void toMDialect(CodeWriter writer);

	@Override
	public IType check(Context context) {
		checkSwitchCasesType(context);
		return checkReturnType(context);
	}
	
	@Override
	public boolean canReturn() {
		return true;
	}
	
	protected void checkSwitchCasesType(Context context) {
		IType type = checkSwitchType(context);
		for(SwitchCase sc : switchCases)
			sc.checkSwitchType(context,type);
	}

	abstract IType checkSwitchType(Context context);

	private IType checkReturnType(Context context) {
		TypeMap types = new TypeMap();
		collectReturnTypes(context, types);
		return types.inferType(context, this);
	}
	
	protected void collectReturnTypes(Context context, TypeMap types) {
		for(SwitchCase sc : switchCases) {
			IType type = sc.checkReturnType(context);
			if(type!=VoidType.instance())
				types.add(type);
		}
		if(defaultCase!=null) {
			IType type = defaultCase.check(context, null);
			if(type!=VoidType.instance())
				types.add(type);
		}
	}

	protected IValue interpretSwitch(Context context, IValue switchValue, ExecutionError toThrow) throws PromptoError {
		for(SwitchCase sc : switchCases) {
			if(sc.matches(context, switchValue))
				return sc.interpret(context);
		}
		if(defaultCase!=null)
			return defaultCase.interpret(context);
		if(toThrow!=null)
			throw toThrow;
		return null;
	}

	protected void declareSwitch(Transpiler transpiler) {
	    this.switchCases.forEach( kase -> {
	        kase.declare(transpiler);
	    });
	    if(this.defaultCase!=null) {
	        this.defaultCase.declare(transpiler);
	    }
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy