package io.gitlab.jfronny.muscript.ast.dynamic; import io.gitlab.jfronny.muscript.ast.DynamicExpr; import io.gitlab.jfronny.muscript.ast.Expr; import io.gitlab.jfronny.muscript.annotations.CanThrow; import io.gitlab.jfronny.muscript.annotations.UncheckedDynamic; import io.gitlab.jfronny.muscript.ast.literal.StringLiteral; import io.gitlab.jfronny.muscript.compiler.*; import io.gitlab.jfronny.muscript.data.Scope; import io.gitlab.jfronny.muscript.data.dynamic.*; import io.gitlab.jfronny.muscript.error.TypeMismatchException; import java.io.IOException; @CanThrow @UncheckedDynamic public class Get extends DynamicExpr { private final DynamicExpr left; private final Expr name; public Get(int chStart, int chEnd, DynamicExpr left, Expr name) { super(Order.Call, chStart, chEnd); this.left = left; this.name = name; if (name.getResultType() != Type.String && name.getResultType() != Type.Number && name.getResultType() != Type.Dynamic) { throw new TypeMismatchException(chStart, chEnd, Type.String, name.getResultType(), "Name must be either a string or a number"); } } @Override public Dynamic get(Scope dataRoot) { Dynamic left = this.left.get(dataRoot); if (left instanceof DObject o) { return o.get(name.asStringExpr().get(dataRoot)); } else if (left instanceof DList l) { return l.get(name.asNumberExpr().get(dataRoot).intValue()); } throw new DynamicTypeConversionException("object or list").locational(chStart, chEnd); } @Override public DynamicExpr optimize() { DynamicExpr left = this.left.optimize(); Expr name = this.name.optimize(); return new Get(chStart, chEnd, left, name); } @Override public void decompile(ExprWriter writer) throws IOException { parenthesize(left, writer, false); if (name instanceof StringLiteral lit && Lexer.isValidId(lit.value)) { writer.append('.').append(lit.value); } else { writer.append('['); name.decompile(writer); writer.append(']'); } } @Override public boolean equals(Object obj) { return obj instanceof Get get && left.equals(get.left) && name.equals(get.name); } }