Search in sources :

Example 1 with MethodCall

use of dyvilx.tools.compiler.ast.expression.access.MethodCall in project Dyvil by Dyvil.

the class ForEachStatement method resolve.

@Override
public IValue resolve(MarkerList markers, IContext context) {
    IType varType = this.variable.getType();
    final IValue value = this.resolveValue(markers, context);
    final IType valueType = value.getType();
    if (value.valueTag() == IValue.METHOD_CALL) {
        final MethodCall rangeOperator = (MethodCall) value;
        if (RangeForStatement.isRangeOperator(rangeOperator)) {
            final IType elementType = RangeForStatement.getElementType(rangeOperator);
            if (varType == Types.UNKNOWN) {
                this.inferVariableType(markers, elementType);
            } else if (!Types.isAssignable(varType, elementType)) {
                final Marker marker = Markers.semanticError(value.getPosition(), "for.range.type");
                marker.addInfo(Markers.getSemantic("range.type", valueType));
                marker.addInfo(Markers.getSemantic("variable.type", varType));
                markers.add(marker);
            }
            final RangeForStatement rangeForStatement = new RangeForStatement(this.position, this.variable, elementType);
            rangeForStatement.resolveAction(this.action, markers, context);
            return rangeForStatement;
        }
    }
    final ArrayType arrayType = valueType.extract(ArrayType.class);
    if (arrayType != null) {
        if (varType == Types.UNKNOWN) {
            this.inferVariableType(markers, arrayType.getElementType());
        } else if (!Types.isAssignable(varType, arrayType.getElementType())) {
            final Marker marker = Markers.semanticError(value.getPosition(), "for.array.type");
            marker.addInfo(Markers.getSemantic("array.type", valueType));
            marker.addInfo(Markers.getSemantic("variable.type", varType));
            markers.add(marker);
        }
        final ArrayForStatement arrayForStatement = new ArrayForStatement(this.position, this.variable, arrayType);
        arrayForStatement.resolveAction(this.action, markers, context);
        return arrayForStatement;
    }
    if (Types.isAssignable(IterableForStatement.LazyFields.ITERATOR, valueType)) {
        return this.toIteratorLoop(markers, context, varType, value, valueType);
    }
    if (Types.isAssignable(IterableForStatement.LazyFields.ITERABLE, valueType)) {
        return this.toIterable(markers, context, varType, value, valueType);
    }
    if (Types.isAssignable(Types.STRING, valueType)) {
        return this.toStringLoop(markers, context, varType, value);
    }
    final Marker marker = Markers.semanticError(this.variable.getPosition(), "for.each.invalid");
    marker.addInfo(Markers.getSemantic("value.type", valueType));
    markers.add(marker);
    this.resolveAction(this.action, markers, context);
    return this;
}
Also used : ArrayType(dyvilx.tools.compiler.ast.type.compound.ArrayType) IValue(dyvilx.tools.compiler.ast.expression.IValue) Marker(dyvilx.tools.parsing.marker.Marker) MethodCall(dyvilx.tools.compiler.ast.expression.access.MethodCall) IType(dyvilx.tools.compiler.ast.type.IType)

Example 2 with MethodCall

use of dyvilx.tools.compiler.ast.expression.access.MethodCall in project Dyvil by Dyvil.

the class Template method makeMainMethod.

private void makeMainMethod() {
    // func main(args: [String]) -> void = new TemplateName().mainImpl(args)
    final ParameterList params = this.mainMethod.getParameters();
    final CodeParameter argsParam = new CodeParameter(this.mainMethod, null, Name.fromRaw("args"), new ArrayType(Types.STRING));
    params.add(argsParam);
    final IValue newTemplate = new ConstructorCall(null, this.templateClass.getClassType(), ArgumentList.EMPTY);
    this.mainMethod.setValue(new MethodCall(null, newTemplate, Name.fromRaw("mainImpl"), new ArgumentList(new FieldAccess(argsParam))));
}
Also used : ArrayType(dyvilx.tools.compiler.ast.type.compound.ArrayType) IValue(dyvilx.tools.compiler.ast.expression.IValue) ParameterList(dyvilx.tools.compiler.ast.parameter.ParameterList) ConstructorCall(dyvilx.tools.compiler.ast.expression.access.ConstructorCall) ArgumentList(dyvilx.tools.compiler.ast.parameter.ArgumentList) FieldAccess(dyvilx.tools.compiler.ast.expression.access.FieldAccess) CodeParameter(dyvilx.tools.compiler.ast.parameter.CodeParameter) MethodCall(dyvilx.tools.compiler.ast.expression.access.MethodCall)

Example 3 with MethodCall

use of dyvilx.tools.compiler.ast.expression.access.MethodCall in project Dyvil by Dyvil.

the class UnapplyPattern method withType.

@Override
public Pattern withType(IType type, MarkerList markers) {
    // PatternType.unapply(_ : MatchedType)
    final IClass matchClass = this.type.getTheClass();
    if (matchClass == null) {
        return null;
    }
    final MethodCall methodCall = new MethodCall(this.position, new ClassAccess(this.type), Names.unapply, new ArgumentList(new DummyValue(type)));
    final IValue resolvedCall = methodCall.resolveCall(MarkerList.BLACKHOLE, matchClass, false);
    return resolvedCall != null && this.withMethod(type, resolvedCall, markers) ? this : null;
}
Also used : IValue(dyvilx.tools.compiler.ast.expression.IValue) ClassAccess(dyvilx.tools.compiler.ast.expression.access.ClassAccess) IClass(dyvilx.tools.compiler.ast.classes.IClass) ArgumentList(dyvilx.tools.compiler.ast.parameter.ArgumentList) MethodCall(dyvilx.tools.compiler.ast.expression.access.MethodCall) DummyValue(dyvilx.tools.compiler.ast.expression.DummyValue)

Example 4 with MethodCall

use of dyvilx.tools.compiler.ast.expression.access.MethodCall in project Dyvil by Dyvil.

the class CaseClassMetadata method createUnapplyAnyMethod.

private CodeMethod createUnapplyAnyMethod() {
    // static final func unapply<TypeParams...>(value: any) -> (T...)?
    final SourcePosition position = this.theClass.position();
    final AttributeList attributes = AttributeList.of(Modifiers.PUBLIC | Modifiers.STATIC_FINAL | Modifiers.GENERATED);
    final IType type = NullableType.apply(this.getUnapplyReturnType());
    final CodeMethod unapply = new CodeMethod(this.theClass, Names.unapply, type, attributes);
    unapply.setPosition(position);
    unapply.getTypeParameters().addAll(this.theClass.getTypeParameters());
    final CodeParameter parameter = new CodeParameter(unapply, position, Names.value, Types.NULLABLE_ANY);
    unapply.getParameters().add(parameter);
    // = (param is This) ? unapply(param as This) : null
    final InstanceOfOperator isOperator = new InstanceOfOperator(new FieldAccess(parameter), this.theClass.getClassType());
    final CastOperator castOperator = new CastOperator(new FieldAccess(parameter), this.theClass.getThisType());
    final IValue call = new MethodCall(position, null, Names.unapply, new ArgumentList(castOperator));
    final IfStatement ifStatement = new IfStatement(isOperator, call, new NullValue());
    unapply.setValue(ifStatement);
    return unapply;
}
Also used : AttributeList(dyvilx.tools.compiler.ast.attribute.AttributeList) CastOperator(dyvilx.tools.compiler.ast.expression.CastOperator) ArgumentList(dyvilx.tools.compiler.ast.parameter.ArgumentList) CodeParameter(dyvilx.tools.compiler.ast.parameter.CodeParameter) MethodCall(dyvilx.tools.compiler.ast.expression.access.MethodCall) IType(dyvilx.tools.compiler.ast.type.IType) InstanceOfOperator(dyvilx.tools.compiler.ast.expression.InstanceOfOperator) IfStatement(dyvilx.tools.compiler.ast.statement.IfStatement) IValue(dyvilx.tools.compiler.ast.expression.IValue) NullValue(dyvilx.tools.compiler.ast.expression.constant.NullValue) CodeMethod(dyvilx.tools.compiler.ast.method.CodeMethod) SourcePosition(dyvil.source.position.SourcePosition) FieldAccess(dyvilx.tools.compiler.ast.expression.access.FieldAccess)

Example 5 with MethodCall

use of dyvilx.tools.compiler.ast.expression.access.MethodCall in project Dyvil by Dyvil.

the class RangeForStatement method writeStatement.

@Override
public void writeStatement(MethodWriter writer) throws BytecodeException {
    // Determine the kind (int, long, float, double, Rangeable) of the range to fasten up compilation.
    byte kind = RANGEABLE;
    boolean boxed = false;
    final int lineNumber = this.lineNumber();
    final IVariable var = this.variable;
    final IType varType = var.getType();
    final MethodCall rangeOperator = (MethodCall) var.getValue();
    final IValue startValue = getStartValue(rangeOperator);
    final IValue endValue = getEndValue(rangeOperator);
    final IType elementType = this.elementType;
    final boolean halfOpen = isHalfOpen(rangeOperator);
    if (elementType.isPrimitive()) {
        switch(elementType.getTypecode()) {
            case PrimitiveType.BYTE_CODE:
            case PrimitiveType.SHORT_CODE:
            case PrimitiveType.CHAR_CODE:
            case PrimitiveType.INT_CODE:
                kind = INT;
                break;
            case PrimitiveType.LONG_CODE:
                kind = LONG;
                break;
            case PrimitiveType.FLOAT_CODE:
                kind = FLOAT;
                break;
            case PrimitiveType.DOUBLE_CODE:
                kind = DOUBLE;
                break;
        }
        if (!varType.isPrimitive()) {
            boxed = true;
        }
    }
    dyvilx.tools.asm.Label startLabel = this.startLabel.getTarget();
    dyvilx.tools.asm.Label updateLabel = this.updateLabel.getTarget();
    dyvilx.tools.asm.Label endLabel = this.endLabel.getTarget();
    dyvilx.tools.asm.Label scopeLabel = new dyvilx.tools.asm.Label();
    writer.visitLabel(scopeLabel);
    // Write the start value and store it in the variable.
    startValue.writeExpression(writer, elementType);
    final int counterVarIndex, varIndex;
    if (boxed) {
        // Create two variables, the counter variable and the user-visible loop variable
        writer.visitInsn(Opcodes.AUTO_DUP);
        counterVarIndex = writer.localCount();
        writer.visitVarInsn(elementType.getStoreOpcode(), counterVarIndex);
        elementType.writeCast(writer, varType, lineNumber);
        var.writeInit(writer, null);
        varIndex = var.getLocalIndex();
    } else {
        // Use the loop variable as the counter variable
        var.writeInit(writer, null);
        varIndex = counterVarIndex = var.getLocalIndex();
    }
    endValue.writeExpression(writer, elementType);
    final int endVarIndex = writer.localCount();
    writer.visitVarInsn(elementType.getStoreOpcode(), endVarIndex);
    writer.visitTargetLabel(startLabel);
    // Check the condition
    switch(kind) {
        case INT:
            writer.visitVarInsn(Opcodes.ILOAD, counterVarIndex);
            writer.visitVarInsn(Opcodes.ILOAD, endVarIndex);
            writer.visitJumpInsn(halfOpen ? Opcodes.IF_ICMPGE : Opcodes.IF_ICMPGT, endLabel);
            break;
        case LONG:
            writer.visitVarInsn(Opcodes.LLOAD, counterVarIndex);
            writer.visitVarInsn(Opcodes.LLOAD, endVarIndex);
            writer.visitJumpInsn(halfOpen ? Opcodes.IF_LCMPGE : Opcodes.IF_LCMPGT, endLabel);
            break;
        case FLOAT:
            writer.visitVarInsn(Opcodes.FLOAD, counterVarIndex);
            writer.visitVarInsn(Opcodes.FLOAD, endVarIndex);
            writer.visitJumpInsn(halfOpen ? Opcodes.IF_FCMPGE : Opcodes.IF_FCMPGT, endLabel);
            break;
        case DOUBLE:
            writer.visitVarInsn(Opcodes.DLOAD, counterVarIndex);
            writer.visitVarInsn(Opcodes.DLOAD, endVarIndex);
            writer.visitJumpInsn(halfOpen ? Opcodes.IF_DCMPGE : Opcodes.IF_DCMPGT, endLabel);
            break;
        case RANGEABLE:
            writer.visitVarInsn(Opcodes.ALOAD, counterVarIndex);
            writer.visitVarInsn(Opcodes.ALOAD, endVarIndex);
            writer.visitLineNumber(lineNumber);
            writer.visitMethodInsn(Opcodes.INVOKEINTERFACE, "dyvil/collection/range/Rangeable", "compareTo", "(Ldyvil/collection/range/Rangeable;)I", true);
            writer.visitJumpInsn(halfOpen ? Opcodes.IFGE : Opcodes.IFGT, endLabel);
            break;
    }
    // Action
    if (this.action != null) {
        this.action.writeExpression(writer, Types.VOID);
    }
    // Increment
    writer.visitLabel(updateLabel);
    switch(kind) {
        case INT:
            writer.visitIincInsn(counterVarIndex, 1);
            if (boxed) {
                writer.visitVarInsn(Opcodes.ILOAD, counterVarIndex);
                elementType.writeCast(writer, varType, lineNumber);
                writer.visitVarInsn(varType.getStoreOpcode(), varIndex);
            }
            break;
        case LONG:
            writer.visitVarInsn(Opcodes.LLOAD, counterVarIndex);
            writer.visitInsn(Opcodes.LCONST_1);
            writer.visitInsn(Opcodes.LADD);
            if (boxed) {
                writer.visitInsn(Opcodes.DUP2);
                elementType.writeCast(writer, varType, lineNumber);
                writer.visitVarInsn(varType.getStoreOpcode(), varIndex);
            }
            writer.visitVarInsn(Opcodes.LSTORE, counterVarIndex);
            break;
        case FLOAT:
            writer.visitVarInsn(Opcodes.FLOAD, counterVarIndex);
            writer.visitInsn(Opcodes.FCONST_1);
            writer.visitInsn(Opcodes.FADD);
            if (boxed) {
                writer.visitInsn(Opcodes.DUP);
                elementType.writeCast(writer, varType, lineNumber);
                writer.visitVarInsn(varType.getStoreOpcode(), varIndex);
            }
            writer.visitVarInsn(Opcodes.FSTORE, counterVarIndex);
            break;
        case DOUBLE:
            writer.visitVarInsn(Opcodes.DLOAD, counterVarIndex);
            writer.visitInsn(Opcodes.DCONST_1);
            writer.visitInsn(Opcodes.DADD);
            if (boxed) {
                writer.visitInsn(Opcodes.DUP2);
                elementType.writeCast(writer, varType, lineNumber);
                writer.visitVarInsn(varType.getStoreOpcode(), varIndex);
            }
            writer.visitVarInsn(Opcodes.DSTORE, counterVarIndex);
            break;
        case RANGEABLE:
            writer.visitVarInsn(Opcodes.ALOAD, counterVarIndex);
            writer.visitLineNumber(lineNumber);
            writer.visitMethodInsn(Opcodes.INVOKEINTERFACE, "dyvil/collection/range/Rangeable", "next", "()Ldyvil/collection/range/Rangeable;", true);
            if (elementType.getTheClass() != LazyFields.RANGEABLE_CLASS) {
                LazyFields.RANGEABLE.writeCast(writer, elementType, lineNumber);
            }
            assert !boxed;
            writer.visitVarInsn(Opcodes.ASTORE, counterVarIndex);
            break;
    }
    writer.visitJumpInsn(Opcodes.GOTO, startLabel);
    // Local Variables
    writer.resetLocals(counterVarIndex);
    writer.visitLabel(endLabel);
    var.writeLocal(writer, scopeLabel, endLabel);
}
Also used : IValue(dyvilx.tools.compiler.ast.expression.IValue) IVariable(dyvilx.tools.compiler.ast.field.IVariable) MethodCall(dyvilx.tools.compiler.ast.expression.access.MethodCall) IType(dyvilx.tools.compiler.ast.type.IType)

Aggregations

MethodCall (dyvilx.tools.compiler.ast.expression.access.MethodCall)6 IValue (dyvilx.tools.compiler.ast.expression.IValue)5 FieldAccess (dyvilx.tools.compiler.ast.expression.access.FieldAccess)3 ArgumentList (dyvilx.tools.compiler.ast.parameter.ArgumentList)3 IType (dyvilx.tools.compiler.ast.type.IType)3 ConstructorCall (dyvilx.tools.compiler.ast.expression.access.ConstructorCall)2 CodeParameter (dyvilx.tools.compiler.ast.parameter.CodeParameter)2 ArrayType (dyvilx.tools.compiler.ast.type.compound.ArrayType)2 SourcePosition (dyvil.source.position.SourcePosition)1 AttributeList (dyvilx.tools.compiler.ast.attribute.AttributeList)1 IClass (dyvilx.tools.compiler.ast.classes.IClass)1 CastOperator (dyvilx.tools.compiler.ast.expression.CastOperator)1 DummyValue (dyvilx.tools.compiler.ast.expression.DummyValue)1 InstanceOfOperator (dyvilx.tools.compiler.ast.expression.InstanceOfOperator)1 ClassAccess (dyvilx.tools.compiler.ast.expression.access.ClassAccess)1 NullValue (dyvilx.tools.compiler.ast.expression.constant.NullValue)1 IVariable (dyvilx.tools.compiler.ast.field.IVariable)1 Variable (dyvilx.tools.compiler.ast.field.Variable)1 CodeMethod (dyvilx.tools.compiler.ast.method.CodeMethod)1 ParameterList (dyvilx.tools.compiler.ast.parameter.ParameterList)1