@Override public DataType visitAtom(@NotNull PythonParser.AtomContext ctx) { // System.out.println("Zz" + ctx.NAME() + ctx.STRING()); if (ctx.test() != null) { // 1 return visitTest(ctx.test()); } else if (ctx.STRING().size() > 0) { // 7,8,9 String ss = ""; for (TerminalNode s : ctx.STRING()) { ss += s.getText(); } mv.visitLdcInsn(ss.length()); mv.visitIntInsn(NEWARRAY, T_CHAR); int tempIndex = 0; for (int i = 0; i < ss.length(); i++) { if (!("\"".equals(ss.substring(i, i + 1))) && !("\'".equals(ss.substring(i, i + 1)))) { mv.visitInsn(DUP); mv.visitLdcInsn(tempIndex); mv.visitLdcInsn(ss.charAt(i)); mv.visitInsn(CASTORE); tempIndex++; } } if (ctx.LBRACK() != null) { if (Integer.parseInt(ctx.INT().getText()) > tempIndex - 1) { throw new CompileException( String.format( "Index out of bounds exception for string %s with index %s", ss, Integer.parseInt(ctx.INT().getText()))); } mv.visitLdcInsn(Integer.parseInt(ctx.INT().getText())); mv.visitInsn(CALOAD); mv.visitMethodInsn( INVOKESTATIC, Type.getType(String.class).getInternalName(), "valueOf", "(C)Ljava/lang/String;", false); return new StringType(1); } else { mv.visitMethodInsn( INVOKESTATIC, Type.getType(String.class).getInternalName(), "valueOf", "([C)Ljava/lang/String;", false); return new StringType(ss.length()); } } else if (!ctx.NAME().isEmpty()) { // 3,4,5 DataType type = null; // System.out.println("GG" + ctx.getText() + "GG"); String varName = ctx.NAME().get(0).getText(); if (scope.isLocalVariable(varName)) { if (ctx.LBRACK() != null) { // 4,5 type = scope.getLocalVariableType(varName); if (!(type instanceof StringType)) { throw new CompileException(String.format("Trying to take index not from string!!")); } mv.visitVarInsn(type.isPrimitive() ? ILOAD : ALOAD, scope.getLocalVariableIndex(varName)); if (ctx.INT() != null) { mv.visitMethodInsn( INVOKEVIRTUAL, Type.getType(String.class).getInternalName(), "toCharArray", "()[C", false); if (Integer.parseInt(ctx.INT().getText()) > type.getSize()) { throw new CompileException(String.format("Index out of bounds exception!")); } mv.visitLdcInsn(Integer.parseInt(ctx.INT().getText())); mv.visitInsn(CALOAD); mv.visitMethodInsn( INVOKESTATIC, Type.getType(String.class).getInternalName(), "valueOf", "(C)Ljava/lang/String;", false); return new StringType(1); } else if (ctx.NAME(1) != null) { varName = ctx.NAME(1).getText(); type = scope.getLocalVariableType(ctx.NAME(1).getText()); if (!type.isInteger()) { throw new CompileException( String.format("Trying to take index from string not with int!")); } else { Label okLabel = new Label(); mv.visitMethodInsn( INVOKEVIRTUAL, Type.getType(String.class).getInternalName(), "toCharArray", "()[C", false); mv.visitVarInsn(ILOAD, scope.getLocalVariableIndex(ctx.NAME(1).getText())); mv.visitInsn(DUP); mv.visitLdcInsn(type.getSize()); mv.visitInsn(SWAP); mv.visitJumpInsn(IF_ICMPGT, okLabel); mv.visitLabel(okLabel); mv.visitInsn(CALOAD); mv.visitMethodInsn( INVOKESTATIC, Type.getType(String.class).getInternalName(), "valueOf", "(C)Ljava/lang/String;", false); // TODO out of bounds a[b] // mv.visitLdcInsn("Out of bounds!"); // mv.visitMethodInsn(INVOKESPECIAL, // "java/lang/CompilerException", "<init>", // "(Ljava/lang/String;)V", false); return new StringType(1); } } else { throw new CompileException(String.format("Unidentified operation")); } } else { // 3 type = scope.getLocalVariableType(varName); mv.visitVarInsn(type.isPrimitive() ? ILOAD : ALOAD, scope.getLocalVariableIndex(varName)); } } else if (scope.isGlobalVariable(varName)) { if (ctx.LBRACK() != null) { // 4,5 type = scope.getGlobalVariableType(varName); if (!(type instanceof StringType)) { throw new CompileException(String.format("Trying to take index not from string!!")); } mv.visitFieldInsn( GETSTATIC, scope.getClassName(), varName, type.getType().getDescriptor()); if (ctx.INT() != null) { mv.visitMethodInsn( INVOKEVIRTUAL, Type.getType(String.class).getInternalName(), "toCharArray", "()[C", false); if (Integer.parseInt(ctx.INT().getText()) > type.getSize()) { throw new CompileException(String.format("Index out of bounds exception!")); } mv.visitLdcInsn(Integer.parseInt(ctx.INT().getText())); mv.visitInsn(CALOAD); mv.visitMethodInsn( INVOKESTATIC, Type.getType(String.class).getInternalName(), "valueOf", "(C)Ljava/lang/String;", false); return new StringType(1); } else if (ctx.NAME(1) != null) { varName = ctx.NAME(1).getText(); type = scope.getLocalVariableType(ctx.NAME(1).getText()); if (!type.isInteger()) { throw new CompileException( String.format("Trying to take index from string not with int!")); } else { Label okLabel = new Label(); mv.visitMethodInsn( INVOKEVIRTUAL, Type.getType(String.class).getInternalName(), "toCharArray", "()[C", false); mv.visitVarInsn(ILOAD, scope.getLocalVariableIndex(ctx.NAME(1).getText())); mv.visitInsn(DUP); mv.visitLdcInsn(type.getSize()); mv.visitInsn(SWAP); mv.visitJumpInsn(IF_ICMPGT, okLabel); mv.visitLabel(okLabel); mv.visitInsn(CALOAD); mv.visitMethodInsn( INVOKESTATIC, Type.getType(String.class).getInternalName(), "valueOf", "(C)Ljava/lang/String;", false); // TODO out of bounds a[b] // mv.visitLdcInsn("Out of bounds!"); // mv.visitMethodInsn(INVOKESPECIAL, // "java/lang/CompilerException", "<init>", // "(Ljava/lang/String;)V", false); return new StringType(1); } } else { throw new CompileException(String.format("Unidentified operation")); } } else { // 3 type = scope.getGlobalVariableType(varName); mv.visitFieldInsn( GETSTATIC, scope.getClassName(), varName, type.getType().getDescriptor()); } } return type; // } else if (scope.isFunction) } else if (ctx.INT() != null) { // 6 mv.visitLdcInsn(Integer.parseInt(ctx.INT().getText())); return PrimitiveType.INTEGER; } else if (ctx.BOOL() != null) { // 2 mv.visitInsn("False".equals(ctx.BOOL().getText()) ? ICONST_0 : ICONST_1); return PrimitiveType.BOOLEAN; } else { throw new CompileException(String.format("Undefined thing to work with! %s", ctx.getText())); } }
@Override public DataType visitExpr_stmt(@NotNull PythonParser.Expr_stmtContext ctx) { if (ctx.power() != null) { if (ctx.power().atom().NAME() != null && ctx.power().atom().STRING().size() == 0) { String var = ctx.power().atom().NAME().get(0).getText(); if (ctx.power().atom().LBRACK() != null) { if (scope.isLocalVariable(var)) { if (!(scope.getLocalVariableType(var) instanceof StringType)) { throw new CompileException(String.format("Trying to take index not from string!")); } } else if (scope.isGlobalVariable(var)) { if (!(scope.getGlobalVariableType(var) instanceof StringType)) { throw new CompileException(String.format("Trying to take index not from string!")); } } throw new CompileException( String.format("Assigning to element of String is not implemented yet!")); // if (ctx.power().atom().INT() != null) { // // } else { // // } } else { if (ctx.test() != null) { if (ctx.power().trailer() != null) { throw new CompileException(String.format("Can't assign to function!")); } DataType etype = visitTest(ctx.test()); if (scope.isLocalVariable(var)) { // System.out.println("LOCAL" + var + "e" + etype + "e" + // scope.getLocalVariableType(var) ); if (etype.equals(scope.getLocalVariableType(var))) { // System.out.println("Type not changing!"); int opcode = scope.getLocalVariableType(var).isPrimitive() ? ISTORE : ASTORE; mv.visitVarInsn(opcode, scope.getLocalVariableIndex(var)); } else { // System.out.println("Type changing!"); scope.changeLocalVariableType(var, etype); int opcode = etype.isPrimitive() ? ISTORE : ASTORE; mv.visitVarInsn(opcode, scope.getLocalVariableIndex(var)); } } else if (scope.isGlobalVariable(var)) { DataType vtype = scope.getGlobalVariableType(var); mv.visitFieldInsn( PUTSTATIC, scope.getClassName(), var, vtype.getType().getDescriptor()); // } else if (scope.isFunctionDeclared(var)) { TODO } else { scope.addLocalVariable(var, etype); int opcode = scope.getLocalVariableType(var).isPrimitive() ? ISTORE : ASTORE; mv.visitVarInsn(opcode, scope.getLocalVariableIndex(var)); // throw new CompileException(String.format("Variable %s not found in context %s.", // var, ctx.getText())); } return etype; } else if (ctx.power().trailer() != null) { // is function visitPower(ctx.power()); // if // (!scope.isFunctionDeclared(ctx.power().atom().NAME(0).getText(), // ctx.power().trailer().arglist().argument().size())) // throw new CompileException(String.format("Function %s not // defined.", var)); // else // System.out.println("ACTION!"); } else if (scope.isLocalVariable(var)) { return scope.getLocalVariableType(var); } else if (scope.isGlobalVariable(var)) { return scope.getGlobalVariableType(var); } else throw new CompileException(String.format("Variable %s not defined.", var)); } } else { throw new CompileException(String.format("can't assign to operator")); } } else { System.out.println("Something bad happened!"); } return null; }