001/* 002 * Copyright (c) 2012-2017 Institut National des Sciences Appliquées de Lyon (INSA-Lyon) 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 */ 009 010package org.eclipse.golo.cli.command; 011 012import com.beust.jcommander.IParameterValidator; 013import com.beust.jcommander.Parameter; 014import com.beust.jcommander.ParameterException; 015import com.beust.jcommander.Parameters; 016import com.beust.jcommander.ParametersDelegate; 017import org.eclipse.golo.cli.command.spi.CliCommand; 018import org.eclipse.golo.compiler.GoloCompilationException; 019import org.eclipse.golo.compiler.GoloCompiler; 020import org.eclipse.golo.compiler.ir.GoloModule; 021import org.eclipse.golo.compiler.ir.IrTreeDumper; 022import org.eclipse.golo.compiler.parser.ASTCompilationUnit; 023 024import java.io.File; 025import java.io.IOException; 026import java.util.LinkedList; 027import java.util.List; 028 029import static gololang.Messages.*; 030 031@Parameters(commandNames = {"diagnose"}, resourceBundle = "commands", commandDescriptionKey = "diagnose") 032public class DiagnoseCommand implements CliCommand { 033 034 @Parameter(names = "--tool", hidden = true, descriptionKey = "diagnose.tool", validateWith = DiagnoseModeValidator.class) 035 String mode = "ir"; 036 037 @Parameter(names = "--stage", descriptionKey = "diagnose.stage", validateWith = DiagnoseStageValidator.class) 038 String stage = "refined"; 039 040 @Parameter(description = "source_files") 041 List<String> files = new LinkedList<>(); 042 043 @ParametersDelegate 044 ClasspathOption classpath = new ClasspathOption(); 045 046 GoloCompiler compiler = new GoloCompiler(); 047 048 @Override 049 public void execute() throws Throwable { 050 if ("ast".equals(this.stage) && !"ast".equals(this.mode)) { 051 this.mode = "ast"; 052 } 053 if ("ast".equals(this.mode) && !"ast".equals(this.stage)) { 054 this.stage = "ast"; 055 } 056 057 classpath.initGoloClassLoader(); 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 if ("refined".equals(this.stage)) { 123 compiler.refine(module); 124 } 125 module.accept(dumper); 126 } catch (IOException e) { 127 error(message("file_not_found", goloFile)); 128 } 129 System.out.println(); 130 } 131 } 132 133 public static final class DiagnoseModeValidator implements IParameterValidator { 134 135 @Override 136 public void validate(String name, String value) throws ParameterException { 137 warning(message("diagnose_tool_warning")); 138 switch (value) { 139 case "ast": 140 case "ir": 141 return; 142 default: 143 throw new ParameterException(message("diagnose_tool_error", "{ast, ir}")); 144 } 145 } 146 } 147 148 public static final class DiagnoseStageValidator implements IParameterValidator { 149 150 @Override 151 public void validate(String name, String value) throws ParameterException { 152 switch (value) { 153 case "ast": 154 case "raw": 155 case "refined": 156 return; 157 default: 158 throw new ParameterException(message("diagnose_stage_error", "{ast, raw, refined}")); 159 } 160 } 161 } 162 163}