001/* 002 * Copyright (c) 2012-2018 Institut National des Sciences Appliquées de Lyon (INSA Lyon) and others 003 * 004 * This program and the accompanying materials are made available under the 005 * terms of the Eclipse Public License 2.0 which is available at 006 * http://www.eclipse.org/legal/epl-2.0. 007 * 008 * SPDX-License-Identifier: EPL-2.0 009 */ 010 011package org.eclipse.golo.cli.command; 012 013import com.beust.jcommander.IParameterValidator; 014import com.beust.jcommander.Parameter; 015import com.beust.jcommander.ParameterException; 016import com.beust.jcommander.Parameters; 017import com.beust.jcommander.ParametersDelegate; 018import org.eclipse.golo.cli.command.spi.CliCommand; 019import org.eclipse.golo.compiler.GoloCompilationException; 020import org.eclipse.golo.compiler.GoloCompiler; 021import gololang.ir.GoloModule; 022import gololang.ir.IrTreeDumper; 023import org.eclipse.golo.compiler.parser.ASTCompilationUnit; 024 025import java.io.File; 026import java.io.IOException; 027import java.util.LinkedList; 028import java.util.List; 029 030import static gololang.Messages.*; 031 032@Parameters(commandNames = {"diagnose"}, resourceBundle = "commands", commandDescriptionKey = "diagnose") 033public class DiagnoseCommand implements CliCommand { 034 035 @Parameter(names = "--tool", hidden = true, descriptionKey = "diagnose.tool", validateWith = DiagnoseModeValidator.class) 036 String mode = "ir"; 037 038 @Parameter(names = "--stage", descriptionKey = "diagnose.stage", validateWith = DiagnoseStageValidator.class) 039 String stage = "refined"; 040 041 @Parameter(description = "source_files") 042 List<String> files = new LinkedList<>(); 043 044 @ParametersDelegate 045 ClasspathOption classpath = new ClasspathOption(); 046 047 GoloCompiler compiler; 048 049 @Override 050 public void execute() throws Throwable { 051 if ("ast".equals(this.stage) && !"ast".equals(this.mode)) { 052 this.mode = "ast"; 053 } 054 if ("ast".equals(this.mode) && !"ast".equals(this.stage)) { 055 this.stage = "ast"; 056 } 057 compiler = classpath.initGoloClassLoader().getCompiler(); 058 try { 059 switch (this.mode) { 060 case "ast": 061 dumpASTs(this.files); 062 break; 063 case "ir": 064 dumpIRs(this.files); 065 break; 066 default: 067 throw new AssertionError("WTF?"); 068 } 069 } catch (GoloCompilationException e) { 070 handleCompilationException(e); 071 } 072 } 073 074 075 private void dumpASTs(List<String> files) { 076 for (String file : files) { 077 dumpAST(file); 078 } 079 } 080 081 private void dumpAST(String goloFile) { 082 File file = new File(goloFile); 083 if (file.isDirectory()) { 084 File[] directoryFiles = file.listFiles(); 085 if (directoryFiles != null) { 086 for (File directoryFile : directoryFiles) { 087 dumpAST(directoryFile.getAbsolutePath()); 088 } 089 } 090 } else if (file.getName().endsWith(".golo")) { 091 System.out.println(">>> AST: " + goloFile); 092 try { 093 ASTCompilationUnit ast = compiler.parse(goloFile); 094 ast.dump("% "); 095 System.out.println(); 096 } catch (IOException e) { 097 error(message("file_not_found", goloFile)); 098 } 099 } 100 } 101 102 private void dumpIRs(List<String> files) { 103 IrTreeDumper dumper = new IrTreeDumper(); 104 for (String file : files) { 105 dumpIR(file, dumper); 106 } 107 } 108 109 private void dumpIR(String goloFile, IrTreeDumper dumper) { 110 File file = new File(goloFile); 111 if (file.isDirectory()) { 112 File[] directoryFiles = file.listFiles(); 113 if (directoryFiles != null) { 114 for (File directoryFile : directoryFiles) { 115 dumpIR(directoryFile.getAbsolutePath(), dumper); 116 } 117 } 118 } else if (file.getName().endsWith(".golo")) { 119 System.out.println(">>> IR: " + file); 120 try { 121 GoloModule module = compiler.transform(compiler.parse(goloFile)); 122 switch (this.stage) { 123 case "raw": 124 break; 125 case "refined": 126 compiler.refine(module); 127 break; 128 default: 129 break; 130 } 131 module.accept(dumper); 132 } catch (IOException e) { 133 error(message("file_not_found", goloFile)); 134 } 135 System.out.println(); 136 } 137 } 138 139 public static final class DiagnoseModeValidator implements IParameterValidator { 140 141 @Override 142 public void validate(String name, String value) throws ParameterException { 143 warning(message("diagnose_tool_warning")); 144 switch (value) { 145 case "ast": 146 case "ir": 147 return; 148 default: 149 throw new ParameterException(message("diagnose_tool_error", "{ast, ir}")); 150 } 151 } 152 } 153 154 public static final class DiagnoseStageValidator implements IParameterValidator { 155 156 @Override 157 public void validate(String name, String value) throws ParameterException { 158 switch (value) { 159 case "ast": 160 case "raw": 161 case "refined": 162 return; 163 default: 164 throw new ParameterException(message("diagnose_stage_error", "{ast, raw, refined}")); 165 } 166 } 167 } 168 169}