org.ssssssss.script.parsing.ast.linq.LinqSelect Maven / Gradle / Ivy
The newest version!
package org.ssssssss.script.parsing.ast.linq;
import org.ssssssss.script.MagicScriptError;
import org.ssssssss.script.compile.MagicScriptCompiler;
import org.ssssssss.script.parsing.Span;
import org.ssssssss.script.parsing.ast.Expression;
import org.ssssssss.script.parsing.ast.Literal;
import org.ssssssss.script.runtime.Variables;
import org.ssssssss.script.runtime.function.MagicScriptLambdaFunction;
import org.ssssssss.script.runtime.linq.LinQBuilder;
import java.util.List;
public class LinqSelect extends Expression {
private final List fields;
private final LinqField from;
private final List joins;
private final LinqExpression where;
private final List groups;
private final LinqExpression having;
private final List orders;
private final Expression limit;
private final Expression offset;
public LinqSelect(Span span, List fields, LinqField from, List joins, LinqExpression where, List groups, LinqExpression having, List orders, Expression limit, Expression offset) {
super(span);
this.fields = fields;
this.from = from;
this.joins = joins;
this.where = where;
this.groups = groups;
this.having = having;
this.orders = orders;
this.limit = limit;
this.offset = offset;
if(from.getVarIndex() == null){
MagicScriptError.error("LINQ中,别名是必须的", from.getSpan());
}
}
@Override
public void visitMethod(MagicScriptCompiler compiler) {
from.visitMethod(compiler);
fields.forEach(it -> it.visitMethod(compiler));
joins.forEach(it -> it.visitMethod(compiler));
groups.forEach(it -> it.visitMethod(compiler));
orders.forEach(it -> it.visitMethod(compiler));
if (where != null) {
where.visitMethod(compiler);
}
if (having != null) {
having.visitMethod(compiler);
}
if (limit != null) {
limit.visitMethod(compiler);
}
if (offset != null) {
offset.visitMethod(compiler);
}
}
@Override
public void compile(MagicScriptCompiler compiler) {
compiler.load2()
.invoke(INVOKESTATIC, LinQBuilder.class, "create", LinQBuilder.class, Variables.class)
.visit(from.getExpression())
.visitInt(from.getVarIndex().getIndex())
.invoke(INVOKEVIRTUAL, LinQBuilder.class, "from", LinQBuilder.class, Object.class, int.class);
if (where != null) {
compiler.visit(where)
.invoke(INVOKEVIRTUAL, LinQBuilder.class, "where", LinQBuilder.class, MagicScriptLambdaFunction.class);
}
if (having != null) {
compiler.visit(having)
.invoke(INVOKEVIRTUAL, LinQBuilder.class, "having", LinQBuilder.class, MagicScriptLambdaFunction.class);
}
groups.forEach(group -> compiler.visit(group)
.invoke(INVOKEVIRTUAL, LinQBuilder.class, "group", LinQBuilder.class, MagicScriptLambdaFunction.class));
joins.forEach(compiler::visit);
fields.forEach(field -> compiler.visit(field)
.ldc(field.getAlias())
.visitInt(field.getVarIndex() == null ? -1 : field.getVarIndex().getIndex())
.invoke(INVOKEVIRTUAL, LinQBuilder.class, "select", LinQBuilder.class, MagicScriptLambdaFunction.class, String.class, int.class));
orders.forEach(order -> compiler.visit(order)
.visitInt(order.getOrder())
.invoke(INVOKEVIRTUAL, LinQBuilder.class, "order", LinQBuilder.class, MagicScriptLambdaFunction.class, int.class));
if(limit != null){
if(offset == null && limit instanceof Literal && "1".equals(limit.getSpan().getText())){
compiler.invoke(INVOKEVIRTUAL, LinQBuilder.class, "executeAndFetchFirst", Object.class);
return;
}
compiler.visit(limit)
.invoke(INVOKEVIRTUAL, LinQBuilder.class, "limit", LinQBuilder.class, Object.class);
if(offset != null){
compiler.visit(offset)
.invoke(INVOKEVIRTUAL, LinQBuilder.class, "offset", LinQBuilder.class, Object.class);
}
}
compiler.invoke(INVOKEVIRTUAL, LinQBuilder.class, "execute", List.class);
}
}