001/*
002 * Copyright (c) 2012-2021 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 com.beust.jcommander.converters.FileConverter;
019import org.eclipse.golo.cli.command.spi.CliCommand;
020import org.eclipse.golo.compiler.GoloCompiler;
021import gololang.ir.GoloModule;
022import gololang.ir.IrTreeDumper;
023import org.eclipse.golo.compiler.parser.ASTCompilationUnit;
024import org.eclipse.golo.cli.GoloFilesManager;
025
026import java.io.File;
027import java.util.LinkedList;
028import java.util.List;
029import java.util.function.Consumer;
030
031import static gololang.Messages.*;
032
033@Parameters(commandNames = "diagnose", resourceBundle = "commands", commandDescriptionKey = "diagnose")
034public final class DiagnoseCommand implements CliCommand {
035
036  @Parameter(names = "--tool", hidden = true, descriptionKey = "diagnose.tool", validateWith = DiagnoseModeValidator.class)
037  String mode = "ir";
038
039  @Parameter(names = "--stage", descriptionKey = "diagnose.stage", validateWith = DiagnoseStageValidator.class)
040  String stage = "refined";
041
042  @Parameter(description = "source_files", converter = FileConverter.class)
043  List<File> files = new LinkedList<>();
044
045  @ParametersDelegate
046  ClasspathOption classpath = new ClasspathOption();
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    GoloCompiler compiler = classpath.initGoloClassLoader().getCompiler();
057    switch (this.mode) {
058      case "ast":
059        GoloFilesManager.goloFiles(this.files).forEach(dumpAST(compiler));
060        break;
061      case "ir":
062        IrTreeDumper dumper = new IrTreeDumper();
063        GoloFilesManager.goloFiles(this.files).forEach(dumpIR(compiler, dumper));
064        break;
065      default:
066        throw new AssertionError("WTF?");
067    }
068  }
069
070  private Consumer<File> dumpAST(GoloCompiler compiler) throws Throwable {
071    return wrappedAction(file -> {
072      compiler.resetExceptionBuilder();
073      System.out.println(">>> AST: " + file.getAbsolutePath());
074      ASTCompilationUnit ast = compiler.parse(file);
075      ast.dump("% ");
076      System.out.println();
077    });
078  }
079
080  private Consumer<File> dumpIR(GoloCompiler compiler, IrTreeDumper dumper) throws Throwable {
081    return wrappedAction(file -> {
082      compiler.resetExceptionBuilder();
083      System.out.println(">>> IR: " + file.getAbsolutePath());
084      GoloModule module = compiler.transform(compiler.parse(file));
085      switch (this.stage) {
086        case "raw":
087          break;
088        case "expanded":
089          compiler.expand(module);
090          break;
091        case "refined":
092          compiler.expand(module);
093          compiler.refine(module);
094          break;
095        default:
096          break;
097      }
098      module.accept(dumper);
099      System.out.println();
100    });
101  }
102
103  public static final class DiagnoseModeValidator implements IParameterValidator {
104
105    @Override
106    public void validate(String name, String value) throws ParameterException {
107      warning(message("diagnose_tool_warning"));
108      switch (value) {
109        case "ast":
110        case "ir":
111          return;
112        default:
113          throw new ParameterException(message("diagnose_tool_error", "{ast, ir}"));
114      }
115    }
116  }
117
118  public static final class DiagnoseStageValidator implements IParameterValidator {
119
120    @Override
121    public void validate(String name, String value) throws ParameterException {
122      switch (value) {
123        case "ast":
124        case "raw":
125        case "expanded":
126        case "refined":
127          return;
128        default:
129          throw new ParameterException(message("diagnose_stage_error", "{ast, raw, expanded, refined}"));
130      }
131    }
132  }
133
134}