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

org.ssssssss.script.parsing.ast.UnaryOperation Maven / Gradle / Ivy

The newest version!
package org.ssssssss.script.parsing.ast;

import org.ssssssss.script.MagicScriptError;
import org.ssssssss.script.compile.MagicScriptCompileException;
import org.ssssssss.script.compile.MagicScriptCompiler;
import org.ssssssss.script.parsing.Token;
import org.ssssssss.script.parsing.TokenType;
import org.ssssssss.script.parsing.ast.statement.VariableAccess;
import org.ssssssss.script.runtime.handle.BitHandle;
import org.ssssssss.script.runtime.handle.OperatorHandle;

import java.util.function.Supplier;

/**
 * 一元操作符
 */
public class UnaryOperation extends Expression {

	private final UnaryOperator operator;
	private final Expression operand;
	private final boolean atAfter;

	public UnaryOperation(Token operator, Expression operand) {
		this(operator, operand, false);
	}

	public UnaryOperation(Token operator, Expression operand, boolean atAfter) {
		super(operator.getSpan());
		if(operator.getType().isModifiable() && operand instanceof VariableAccess && ((VariableAccess) operand).getVarIndex().isReadonly()){
			MagicScriptError.error("const修饰的变量不能被修改", getSpan());
		}
		this.operator = UnaryOperator.getOperator(operator);
		this.operand = operand;
		this.atAfter = atAfter;
	}

	public UnaryOperator getOperator() {
		return operator;
	}

	@Override
	public void visitMethod(MagicScriptCompiler compiler) {
		operand.visitMethod(compiler);
	}

	@Override
	public void compile(MagicScriptCompiler compiler) {
		switch (getOperator()) {
			case Not:
				compiler.compile(operand)
						.invoke(INVOKESTATIC, OperatorHandle.class, "isFalse", boolean.class, Object.class)
						.asBoolean();
				break;
			case BitNot:
				compiler.compile(operand)
						.invoke(INVOKESTATIC, BitHandle.class, "not", Object.class, Object.class);
				break;
			case PlusPlus:
			case MinusMinus:
				if (operand instanceof VariableSetter) {
					boolean access = operand instanceof VariableAccess;
					Supplier plus = () -> compiler.visit(operand)  // 访问变量
							// 执行 ± 1 操作
							.visitInt(operator == UnaryOperator.PlusPlus ? 1 : -1)
							.asInteger()
							.arithmetic("plus");
					if (atAfter) {    // ++ -- 在后
						if (access) { // a++ a--
							// 执行 ± 操作
							compiler.compile(operand).pre_store(((VariableAccess) operand).getVarIndex());
							plus.get().store(((VariableAccess) operand).getVarIndex());
						} else {  // map.key++ map.key--
							compiler.compile(operand);    // 先访问变量,后续返回使用
							compiler.newRuntimeContext();
							((VariableSetter) operand).compile_visit_variable(compiler); // 赋值前准备
							plus.get()
									.call("set_variable_value", 4)   // 赋值操作
									.insn(POP); // 抛弃 ++ -- 的返回值。
						}
					} else {  // ++ -- 在前
						if (access) { // ++a --a
							compiler.pre_store(((VariableAccess) operand).getVarIndex());
							// 执行 ± 操作
							plus.get().store(((VariableAccess) operand).getVarIndex())   // 结果存入到变量中
									.visit(operand);
						} else {  // ++map.key --map.key
							compiler.newRuntimeContext();
							// 赋值前准备
							((VariableSetter) operand).compile_visit_variable(compiler);
							// 将执行结果赋值给变量。
							plus.get().call("set_variable_value", 4);
						}
					}
					break;
				}
				throw new MagicScriptCompileException("此处不支持++/--操作");
			case Negate:
				compiler.visit(operand)
						.insn(ACONST_NULL)
						.arithmetic("neg");
				break;
			default:break;
		}
	}

	public enum UnaryOperator {
		/**
		 * !
		 */
		Not,

		/**
		 * -
		 */
		Negate,

		/**
		 * +
		 */
		Positive,

		/**
		 * ++
		 */
		PlusPlus,

		/**
		 * --
		 */
		MinusMinus,

		/**
		 * ~
		 */
		BitNot;

		public static UnaryOperator getOperator(Token op) {
			if (op.getType() == TokenType.Not) {
				return UnaryOperator.Not;
			}
			if (op.getType() == TokenType.Plus) {
				return UnaryOperator.Positive;
			}
			if (op.getType() == TokenType.Minus) {
				return UnaryOperator.Negate;
			}
			if (op.getType() == TokenType.PlusPlus) {
				return UnaryOperator.PlusPlus;
			}
			if (op.getType() == TokenType.MinusMinus) {
				return UnaryOperator.MinusMinus;
			}
			if (op.getType() == TokenType.BitNot) {
				return UnaryOperator.BitNot;
			}
			MagicScriptError.error("不支持的一元操作符:" + op, op.getSpan());
			return null; // not reached
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy