public Scope visitFile_input(@NotNull PythonParser.File_inputContext ctx, String name) { if (ctx == null) throw new IllegalArgumentException("No input context! Something wrong while lexing-parsing!"); init(); scope.setClassName(name); cw.visit(V1_7, ACC_PUBLIC, name, null, "java/lang/Object", null); mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null); for (PythonParser.StmtContext sctx : ctx.stmt()) visitStmt(sctx); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); cw.visitEnd(); scope.setByteCode(cw.toByteArray()); return scope; }
@Override public DataType visitWhile_stmt(@NotNull PythonParser.While_stmtContext ctx) { Label continueLabel = new Label(); Label breakLabel = new Label(); Label elseLabel = new Label(); scope.enterLoop(continueLabel, breakLabel); mv.visitLabel(continueLabel); visitTest(ctx.test()); // verifyType(visitExpression(ctx.expression()), PrimitiveType.BOOLEAN, ctx); mv.visitJumpInsn(IFEQ, elseLabel); visitSuite(ctx.suite(0)); mv.visitJumpInsn(GOTO, continueLabel); mv.visitLabel(elseLabel); if (ctx.suite(1) != null) visitSuite(ctx.suite(1)); mv.visitLabel(breakLabel); scope.exitLoop(); return null; }
@Override public DataType visitFuncdef(@NotNull PythonParser.FuncdefContext ctx) { String name = ctx.NAME().getText(); scope.setMethodName(name); String[] argumentNames = visitParameters(ctx.parameters()); Integer numberParms = argumentNames.length; // System.out.println(name + numberParms); scope.declareFunction(name, numberParms); scope.addFunctionSuite(name, numberParms, ctx.suite()); scope.addFunctionArgumentsNames(name, numberParms, argumentNames); // mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, name, "()V", null, null);//TODO to // function call // visitSuite(ctx.suite()); // mv.visitMaxs(0, 0); // mv.visitEnd(); // scope.setMethodName(name); // scope.refreshLocalVariables(); return null; }
@Override public DataType visitGlobal_stmt(@NotNull PythonParser.Global_stmtContext ctx) { for (TerminalNode e : ctx.NAME()) { scope.addGlobalVariable(e.getText(), PrimitiveType.INTEGER); String descriptor = PrimitiveType.INTEGER.getType().getDescriptor(); Object value = PrimitiveType.INTEGER.isPrimitive() ? 0 : null; cw.visitField(ACC_PUBLIC | ACC_STATIC, e.getText(), descriptor, null, value).visitEnd(); } return PrimitiveType.INTEGER; }
@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 visitPower(@NotNull PythonParser.PowerContext ctx) { // System.out.println("called!"); if (ctx.trailer() != null) if (ctx.atom().NAME() != null) { String name = ctx.atom().NAME(0).getText(); Integer argumentGiven = 0; String returnSignatue = "V"; String argSignature = ""; String totalSinature = ""; if (ctx.trailer().arglist() != null) { argumentGiven = ctx.trailer().arglist().argument().size(); } if (!scope.isFunctionDeclared(name)) throw new CompileException(String.format("Function %s is not defined.", name)); else { Integer argumentsCount = scope.functionArgumentCount(name); if (!argumentsCount.equals(argumentGiven)) { throw new CompileException( String.format( "Function %s takes exactly %s arguments (%s given)", name, argumentsCount, argumentGiven)); } else { if (argumentGiven == 0) { argSignature = ""; } else { int i = 0; String[] argumentsNames = scope.getFunctionArgumentsNames(name, argumentGiven); for (PythonParser.ArgumentContext argctx : ctx.trailer().arglist().argument()) { DataType argType = visitArgument(argctx); argSignature += argType.getType().getDescriptor(); // System.out.println("Хуйня тут" + argType + argumentsNames[i]); scope.addLocalVariable(argumentsNames[i], argType); // int opcode = // scope.getLocalVariableType(argumentsNames[i]).isPrimitive() ? ISTORE : ASTORE; // mv.visitVarInsn(opcode, // scope.getLocalVariableIndex(argumentsNames[i])); i++; } } totalSinature = "(" + argSignature + ")" + returnSignatue; System.out.println("ACTION!" + totalSinature); MethodVisitor mvSave = mv; mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, name, totalSinature, null, null); visitSuite(scope.getFunctionSuite(name, argumentGiven)); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); scope.setMethodName(name); scope.refreshLocalVariables(); mv = mvSave; mv.visitMethodInsn(INVOKESTATIC, scope.getClassName(), name, totalSinature, false); } } // //TODO function with () call {a()} + default values // DataType returnType = scope.getFunctionReturnType(name, argumentType); // mv.visitMethodInsn(INVOKESTATIC, scope.getClassName(), name, // Utils.getFunctionDescriptor(returnType, argumentType), false); // System.out.println("called!"); return null; } else { throw new CompileException( String.format("%s object is not callable!", ctx.atom().getText())); } return visitAtom(ctx.atom()); }
@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; }
@Override public DataType visitContinue_stmt(@NotNull PythonParser.Continue_stmtContext ctx) { if (!scope.inLoop()) throw new CompileException("Continue is out of loop " + ctx.getText()); mv.visitJumpInsn(GOTO, scope.getContinueLabel()); return null; }