Search in sources :

Example 1 with IVariable

use of dyvilx.tools.compiler.ast.field.IVariable in project Dyvil by Dyvil.

the class IterableForStatement method writeStatement.

@Override
public void writeStatement(MethodWriter writer) throws BytecodeException {
    dyvilx.tools.asm.Label startLabel = this.startLabel.getTarget();
    dyvilx.tools.asm.Label updateLabel = this.updateLabel.getTarget();
    dyvilx.tools.asm.Label endLabel = this.endLabel.getTarget();
    final IVariable var = this.variable;
    final IType varType = var.getType();
    final int lineNumber = this.lineNumber();
    // Scope
    dyvilx.tools.asm.Label scopeLabel = new dyvilx.tools.asm.Label();
    writer.visitLabel(scopeLabel);
    int localCount = writer.localCount();
    // Get the iterator
    var.getValue().writeExpression(writer, null);
    if (!this.iterator) {
        writer.visitLineNumber(lineNumber);
        writer.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/lang/Iterable", "iterator", "()Ljava/util/Iterator;", true);
    }
    // Local Variables
    int iteratorVarIndex = writer.localCount();
    var.setLocalIndex(iteratorVarIndex + 1);
    // Store Iterator
    writer.visitVarInsn(Opcodes.ASTORE, iteratorVarIndex);
    // Jump to hasNext check
    writer.visitJumpInsn(Opcodes.GOTO, updateLabel);
    writer.visitTargetLabel(startLabel);
    // Invoke Iterator.next()
    writer.visitVarInsn(Opcodes.ALOAD, iteratorVarIndex);
    writer.visitLineNumber(lineNumber);
    writer.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;", true);
    // Auocasting
    Types.OBJECT.writeCast(writer, varType, lineNumber);
    // Store the next element
    writer.visitVarInsn(varType.getStoreOpcode(), iteratorVarIndex + 1);
    // Action
    if (this.action != null) {
        this.action.writeExpression(writer, Types.VOID);
    }
    writer.visitLabel(updateLabel);
    // Load Iterator
    writer.visitVarInsn(Opcodes.ALOAD, iteratorVarIndex);
    // Check hasNext
    writer.visitLineNumber(lineNumber);
    writer.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z", true);
    // Go back to start if Iterator.hasNext() returned true
    writer.visitJumpInsn(Opcodes.IFNE, startLabel);
    // Local Variables
    writer.resetLocals(localCount);
    writer.visitLabel(endLabel);
    var.writeLocal(writer, scopeLabel, endLabel);
}
Also used : IVariable(dyvilx.tools.compiler.ast.field.IVariable) IType(dyvilx.tools.compiler.ast.type.IType)

Example 2 with IVariable

use of dyvilx.tools.compiler.ast.field.IVariable in project Dyvil by Dyvil.

the class StringForStatement method writeStatement.

@Override
public void writeStatement(MethodWriter writer) throws BytecodeException {
    dyvilx.tools.asm.Label startLabel = this.startLabel.getTarget();
    dyvilx.tools.asm.Label updateLabel = this.updateLabel.getTarget();
    dyvilx.tools.asm.Label endLabel = this.endLabel.getTarget();
    final IVariable var = this.variable;
    final int lineNumber = this.lineNumber();
    // Scope
    dyvilx.tools.asm.Label scopeLabel = new dyvilx.tools.asm.Label();
    writer.visitLabel(scopeLabel);
    final int localCount = writer.localCount();
    // Load the String
    var.getValue().writeExpression(writer, null);
    // Local Variables
    final int stringVarIndex = writer.localCount();
    final int lengthVarIndex = stringVarIndex + 1;
    final int indexVarIndex = stringVarIndex + 2;
    writer.visitInsn(Opcodes.DUP);
    writer.visitVarInsn(Opcodes.ASTORE, stringVarIndex);
    // Get the length
    writer.visitLineNumber(lineNumber);
    writer.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "length", "()I", false);
    writer.visitInsn(Opcodes.DUP);
    writer.visitVarInsn(Opcodes.ISTORE, lengthVarIndex);
    // Initial Boundary Check - if the length is 0, skip the loop.
    writer.visitJumpInsn(Opcodes.IFEQ, endLabel);
    // Set index to 0
    writer.visitLdcInsn(0);
    writer.visitVarInsn(Opcodes.ISTORE, indexVarIndex);
    writer.visitTargetLabel(startLabel);
    // Get the char at the index
    writer.visitVarInsn(Opcodes.ALOAD, stringVarIndex);
    writer.visitVarInsn(Opcodes.ILOAD, indexVarIndex);
    writer.visitLineNumber(lineNumber);
    writer.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "charAt", "(I)C", false);
    // Autocasting
    Types.CHAR.writeCast(writer, var.getType(), lineNumber);
    var.writeInit(writer, null);
    // Action
    if (this.action != null) {
        this.action.writeExpression(writer, Types.VOID);
    }
    writer.visitLabel(updateLabel);
    // Increment index
    writer.visitIincInsn(indexVarIndex, 1);
    // Boundary Check
    writer.visitVarInsn(Opcodes.ILOAD, indexVarIndex);
    writer.visitVarInsn(Opcodes.ILOAD, lengthVarIndex);
    writer.visitJumpInsn(Opcodes.IF_ICMPLT, startLabel);
    // Local Variables
    writer.resetLocals(localCount);
    writer.visitLabel(endLabel);
    var.writeLocal(writer, scopeLabel, endLabel);
}
Also used : IVariable(dyvilx.tools.compiler.ast.field.IVariable)

Example 3 with IVariable

use of dyvilx.tools.compiler.ast.field.IVariable in project Dyvil by Dyvil.

the class StatementList method addVariable.

protected void addVariable(VariableStatement initializer, MarkerList markers, IContext context) {
    final IVariable variable = initializer.variable;
    final Name variableName = variable.getName();
    // Uninitialized Variables
    if (variable.getValue() == null) {
        variable.setValue(variable.getType().getDefaultValue());
        markers.add(Markers.semanticError(variable.getPosition(), "variable.uninitialized", variableName));
    }
    // Variable Name Shadowing
    final IDataMember dataMember = context.resolveField(variableName);
    if (dataMember != null && dataMember.isLocal() && !variable.hasModifier(Modifiers.GENERATED)) {
        markers.add(Markers.semantic(initializer.getPosition(), "variable.shadow", variableName));
    }
    // Actually add the Variable to the List (this has to happen after checking for shadowed variables)
    this.addVariable(variable);
}
Also used : IVariable(dyvilx.tools.compiler.ast.field.IVariable) IDataMember(dyvilx.tools.compiler.ast.field.IDataMember) Name(dyvil.lang.Name)

Example 4 with IVariable

use of dyvilx.tools.compiler.ast.field.IVariable 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)

Example 5 with IVariable

use of dyvilx.tools.compiler.ast.field.IVariable in project Dyvil by Dyvil.

the class StatementListParser method parse.

@Override
public void parse(IParserManager pm, IToken token) {
    final int type = token.type();
    if (type == BaseSymbols.CLOSE_CURLY_BRACKET) {
        this.end(pm);
        return;
    }
    if (type == Tokens.EOF) {
        this.end(pm);
        pm.report(token, "statement_list.close_brace");
        return;
    }
    switch(this.mode) {
        case OPEN_BRACKET:
            {
                final IToken next = token.next();
                final IToken lambdaArrow = this.findLambdaArrow(next);
                if (lambdaArrow != null) {
                    this.lambdaExpr = new LambdaExpr(lambdaArrow.raw());
                    this.lambdaExpr.setValue(this.statementList = new StatementList(token));
                    if (next == lambdaArrow) {
                        // { ->
                        // { =>
                        this.mode = LAMBDA_TYPE_ARROW;
                        return;
                    }
                    if (next.type() == BaseSymbols.OPEN_PARENTHESIS) {
                        // { ( ... ) =>
                        // { ( ... ) ->
                        pm.skip();
                        pm.pushParser(new ParameterListParser(this.lambdaExpr));
                        this.mode = LAMBDA_PARAMETERS_END;
                        return;
                    }
                    // { ... ->
                    // { ... =>
                    pm.pushParser(new ParameterListParser(this.lambdaExpr).withFlags(LAMBDA_ARROW_END));
                    this.mode = LAMBDA_TYPE_ARROW;
                    return;
                }
                // { ...
                this.statementList = this.closure ? new Closure(token) : new StatementList(token);
                this.mode = EXPRESSION;
                if (type != BaseSymbols.OPEN_CURLY_BRACKET) {
                    pm.report(token, "statement_list.open_brace");
                    pm.reparse();
                }
                return;
            }
        case LAMBDA_PARAMETERS_END:
            this.mode = LAMBDA_TYPE_ARROW;
            if (type != BaseSymbols.CLOSE_PARENTHESIS) {
                pm.report(token, "statement_list.lambda.close_paren");
            }
            return;
        case LAMBDA_TYPE_ARROW:
            if (type == DyvilSymbols.ARROW_RIGHT) {
                pm.pushParser(LambdaOrTupleParser.returnTypeParser(this.lambdaExpr));
                this.mode = LAMBDA_RETURN_ARROW;
                return;
            }
        // Fallthrough
        case LAMBDA_RETURN_ARROW:
            if (type != DyvilSymbols.DOUBLE_ARROW_RIGHT) {
                pm.report(token, "statement_list.lambda.arrow");
                return;
            }
            this.mode = EXPRESSION;
            return;
        case EXPRESSION:
            switch(type) {
                case BaseSymbols.SEMICOLON:
                case BaseSymbols.COMMA:
                    return;
                case DyvilKeywords.LABEL:
                    this.mode = LABEL_NAME;
                    return;
            }
            this.mode = SEPARATOR;
            final MemberParser<IVariable> parser = new MemberParser<>(this).withFlags(MemberParser.NO_FIELD_PROPERTIES);
            if (this.tryParserManager.tryParse(pm, parser, token, EXIT_ON_ROOT)) {
                return;
            }
            pm.pushParser(new ExpressionParser(this));
            return;
        case LABEL_NAME:
            if (Tokens.isIdentifier(type)) {
                this.label = token.nameValue();
                this.mode = LABEL_END;
                return;
            }
            this.mode = EXPRESSION;
            if (type != BaseSymbols.COLON) {
                pm.reparse();
            }
            pm.report(token, "statement_list.label.name");
            return;
        case LABEL_END:
            switch(type) {
                case BaseSymbols.COLON:
                case BaseSymbols.SEMICOLON:
                    this.mode = EXPRESSION;
                    return;
            }
            this.mode = EXPRESSION;
            pm.reparse();
            pm.report(SourcePosition.between(token, token.next()), "statement_list.label.separator");
            return;
        case SEPARATOR:
            this.mode = EXPRESSION;
            switch(type) {
                case BaseSymbols.SEMICOLON:
                case BaseSymbols.COMMA:
                    return;
            }
            pm.report(token, "statement_list.semicolon");
    }
}
Also used : ParameterListParser(dyvilx.tools.compiler.parser.method.ParameterListParser) Closure(dyvilx.tools.compiler.ast.statement.Closure) IToken(dyvilx.tools.parsing.token.IToken) LambdaExpr(dyvilx.tools.compiler.ast.expression.LambdaExpr) StatementList(dyvilx.tools.compiler.ast.statement.StatementList) IVariable(dyvilx.tools.compiler.ast.field.IVariable) ExpressionParser(dyvilx.tools.compiler.parser.expression.ExpressionParser)

Aggregations

IVariable (dyvilx.tools.compiler.ast.field.IVariable)12 IType (dyvilx.tools.compiler.ast.type.IType)4 IValue (dyvilx.tools.compiler.ast.expression.IValue)3 Name (dyvil.lang.Name)1 CastOperator (dyvilx.tools.compiler.ast.expression.CastOperator)1 LambdaExpr (dyvilx.tools.compiler.ast.expression.LambdaExpr)1 MethodCall (dyvilx.tools.compiler.ast.expression.access.MethodCall)1 OptionalUnwrapOperator (dyvilx.tools.compiler.ast.expression.optional.OptionalUnwrapOperator)1 IDataMember (dyvilx.tools.compiler.ast.field.IDataMember)1 Closure (dyvilx.tools.compiler.ast.statement.Closure)1 StatementList (dyvilx.tools.compiler.ast.statement.StatementList)1 Label (dyvilx.tools.compiler.ast.statement.control.Label)1 ExpressionParser (dyvilx.tools.compiler.parser.expression.ExpressionParser)1 ParameterListParser (dyvilx.tools.compiler.parser.method.ParameterListParser)1 Marker (dyvilx.tools.parsing.marker.Marker)1 IToken (dyvilx.tools.parsing.token.IToken)1