From a2f1ff3d5a61e9de92e095bb3ca6c314a4ca0afe Mon Sep 17 00:00:00 2001
From: Johannes Mey <johannes.mey@tu-dresden.de>
Date: Thu, 2 Jan 2020 00:27:42 +0100
Subject: [PATCH] initial version of modelica, analysis currently empty

---
 scope4m/.gitignore                            |  27 ++++
 scope4m/build.gradle                          | 145 ++++++++++++++++++
 scope4m/src/gen-res/BuildInfo.properties      |   7 +
 scope4m/src/main/jastadd/ASTPrinting.jadd     |  50 ++++++
 scope4m/src/main/jastadd/Helpers.jadd         |  19 +++
 .../src/main/jastadd/ModelicaToScopeTree.jrag |  12 ++
 .../main/jastadd/ModelicaToScopeTree.relast   |   2 +
 .../java/org/jmodelica/ScopeAnalysis.java     | 143 +++++++++++++++++
 settings.gradle                               |   2 +
 9 files changed, 407 insertions(+)
 create mode 100644 scope4m/.gitignore
 create mode 100644 scope4m/build.gradle
 create mode 100644 scope4m/src/gen-res/BuildInfo.properties
 create mode 100644 scope4m/src/main/jastadd/ASTPrinting.jadd
 create mode 100644 scope4m/src/main/jastadd/Helpers.jadd
 create mode 100644 scope4m/src/main/jastadd/ModelicaToScopeTree.jrag
 create mode 100644 scope4m/src/main/jastadd/ModelicaToScopeTree.relast
 create mode 100644 scope4m/src/main/java/org/jmodelica/ScopeAnalysis.java

diff --git a/scope4m/.gitignore b/scope4m/.gitignore
new file mode 100644
index 0000000..d8bcc39
--- /dev/null
+++ b/scope4m/.gitignore
@@ -0,0 +1,27 @@
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+out/
+*.iml
+/.idea/*
+!.idea/codeStyles
+!libs/relast.jar
+
+graph/
+src/gen/
+build/
diff --git a/scope4m/build.gradle b/scope4m/build.gradle
new file mode 100644
index 0000000..e49253b
--- /dev/null
+++ b/scope4m/build.gradle
@@ -0,0 +1,145 @@
+buildscript {
+    repositories.mavenLocal()
+    repositories.mavenCentral()
+    dependencies {
+        classpath 'org.jastadd:jastaddgradle:1.13.3'
+    }
+}
+
+apply plugin: 'java'
+apply plugin: 'application'
+apply plugin: 'jastadd'
+apply plugin: 'idea'
+
+repositories {
+    mavenLocal()
+}
+
+idea {
+    module {
+        generatedSourceDirs += file('./src/gen/java')
+        sourceDirs += file('../jmodelica/src/main/java')
+    }
+}
+
+test {
+    useJUnitPlatform {}
+}
+
+sourceSets.main {
+    java {
+        srcDir 'src/gen/java'
+        srcDir '../jmodelica/src/main/java'
+    }
+    resources {
+        srcDir '../jmodelica/src/main/resources'
+        srcDir jastadd.buildInfoDir
+    }
+}
+
+dependencies {
+    compile group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
+    compile group: 'junit', name: 'junit', version: '4.12'
+    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.2'
+    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.2'
+    testCompile 'org.junit.platform:junit-platform-runner:1.4.2'
+    testImplementation 'org.junit.jupiter:junit-jupiter-params:5.4.2'
+}
+
+jastadd {
+    configureModuleBuild()
+
+    modules {
+        include("../jmodelica/jastadd_modules")
+
+        module "dependencyanalysis", {
+
+            imports "jmodelica"
+
+            jastadd {
+                basedir ".."
+                include "scope4m/src/gen/jastadd/Modelica.ast"
+                include "scope4m/src/gen/jastadd/Modelica.jadd"
+                include "scope4m/src/main/jastadd/*.jrag"
+                include "scope4m/src/main/jastadd/*.jadd"
+                include "scope/src/main/jastadd/*.jrag"
+                include "scope/src/main/jastadd/*.jadd"
+
+                excludeFrom "jmodelica", "ast/BaseAST.ast"
+                excludeFrom "jmodelica", "ast/Error.ast"
+                excludeFrom "jmodelica", "ast/Modelica.ast"
+            }
+
+            java {
+                basedir "src/main/java/"
+                include "**/*.java"
+                excludeFrom "jmodelica", "gen/java/**/*.java"
+            }
+
+        }
+
+    }
+
+
+
+    buildInfoDir = 'src/gen-res'
+
+    // Target module to build:
+    module = 'dependencyanalysis'
+
+    astPackage = 'org.jmodelica.compiler'
+    parser.name = 'ModelicaParser'
+    scanner.name = 'OriginalScanner'
+
+    genDir = 'src/gen/java'
+    parser.genDir = 'src/gen/java/org/jmodelica/parser'
+    scanner.genDir = 'src/gen/java/org/jmodelica/scanner'
+
+    jastaddOptions = ["--rewrite=cnta", "--safeLazy", "--tracing=api", "--visitCheck=false"]
+}
+
+run {
+    mainClassName = 'org.jmodelica.SimpleMain'
+}
+
+task preprocess(type: JavaExec) {
+    group = 'Build'
+    main = "-jar"
+
+    doFirst {
+        delete "src/gen/jastadd"
+        mkdir "src/gen/jastadd"
+    }
+
+    args = [
+            "../tools/relast.jar",
+            "src/main/jastadd/ModelicaToScopeTree.relast",
+            "../scope/src/main/jastadd/ScopeTree.relast",
+            "../jmodelica/src/main/jastadd/ast/BaseAST.ast",
+            "../jmodelica/src/main/jastadd/ast/Error.ast",
+            "../jmodelica/src/main/jastadd/ast/Modelica.ast",
+            "--listClass=ArrayList",
+            "--useJastAddNames",
+            "--file",
+            "--grammarName=src/gen/jastadd/Modelica"
+    ]
+
+    inputs.files file("../tools/relast.jar"),
+            file("src/main/jastadd/ModelicaToScopeTree.relast"),
+            file("../scope/src/main/jastadd/ScopeTree.relast"),
+            file("../jmodelica/src/main/jastadd/ast/BaseAST.ast"),
+            file("../jmodelica/src/main/jastadd/ast/Error.ast"),
+            file("../jmodelica/src/main/jastadd/ast/Modelica.ast")
+    outputs.files file("src/gen/jastadd/Modelica.ast")
+            file("src/gen/jastadd/Modelica.jadd")
+}
+
+
+generateAst.dependsOn preprocess
+
+mainClassName = 'org.jmodelica.ScopeAnalysis'
+jar.manifest.attributes 'Main-Class': mainClassName
+jar.destinationDirectory = projectDir
+
+sourceCompatibility = '1.8'
+targetCompatibility = '1.8'
diff --git a/scope4m/src/gen-res/BuildInfo.properties b/scope4m/src/gen-res/BuildInfo.properties
new file mode 100644
index 0000000..15116f7
--- /dev/null
+++ b/scope4m/src/gen-res/BuildInfo.properties
@@ -0,0 +1,7 @@
+#Thu, 02 Jan 2020 00:10:22 +0100
+
+moduleId=dependencyanalysis
+moduleName=null
+moduleVariant=null
+timestamp=2020-01-02T00\:10Z
+build.date=2020-01-02
diff --git a/scope4m/src/main/jastadd/ASTPrinting.jadd b/scope4m/src/main/jastadd/ASTPrinting.jadd
new file mode 100644
index 0000000..0864144
--- /dev/null
+++ b/scope4m/src/main/jastadd/ASTPrinting.jadd
@@ -0,0 +1,50 @@
+aspect Debugging {
+
+  public String ASTNode.getASTString() {
+
+    String result = this.getClass().getSimpleName() + "\n";
+
+    for (java.lang.reflect.Method method : this.getClass().getMethods()) {
+      ASTNodeAnnotation.Token annotation = method.getAnnotation(ASTNodeAnnotation.Token.class);
+      if (annotation != null) {
+        try {
+          String name = annotation.name();
+          if (name.startsWith("_impl_")) {
+            name = "rel " + name.substring(6) + " -> ";
+          } else {
+            name += ":= ";
+          }
+          result += "|--" + name + method.invoke(this);
+        } catch (IllegalAccessException e) {
+          e.printStackTrace();
+        } catch (java.lang.reflect.InvocationTargetException e) {
+          e.printStackTrace();
+        }
+        result += "\n";
+      }
+    }
+
+    for(int childIndex = 0; childIndex < getNumChildNoTransform(); childIndex++) {
+
+      ASTNode<?> child = getChildNoTransform(childIndex);
+      String childString = "NULL\n";
+      if(child != null) {
+        childString = child.getASTString();
+      }
+
+      if(childIndex < getNumChildNoTransform() - 1) {
+        childString = childString.replaceAll("(?m)^", "|  ");
+      } else {
+        childString = childString.replaceAll("(?m)^", "   ");
+      }
+
+      result += "|\n|--" + childString.substring(3);
+    }
+
+    return result;
+  }
+
+  public void ASTNode.printAST() {
+    System.out.println(getASTString());
+  }
+}
diff --git a/scope4m/src/main/jastadd/Helpers.jadd b/scope4m/src/main/jastadd/Helpers.jadd
new file mode 100644
index 0000000..3e171a6
--- /dev/null
+++ b/scope4m/src/main/jastadd/Helpers.jadd
@@ -0,0 +1,19 @@
+/** copy of the extendj source location interface */
+aspect SourceLocation {
+
+  protected String ASTNode.sourceFile() {
+    return retrieveFileName();
+  }
+
+  syn int ASTNode.lineNumber() {
+    ASTNode n = this;
+    while (n.getParent() != null && n.getStart() == 0) {
+      n = n.getParent();
+    }
+    return getLine(n.getStart());
+  }
+
+  public String ASTNode.sourceLocation() {
+    return sourceFile() + ":" + lineNumber();
+  }
+}
diff --git a/scope4m/src/main/jastadd/ModelicaToScopeTree.jrag b/scope4m/src/main/jastadd/ModelicaToScopeTree.jrag
new file mode 100644
index 0000000..b3c375d
--- /dev/null
+++ b/scope4m/src/main/jastadd/ModelicaToScopeTree.jrag
@@ -0,0 +1,12 @@
+aspect ModelicaToScopeTree {
+  syn lazy ScopeTree SourceRoot.scopeTree() {
+    ScopeTree tree = new ScopeTree();
+    tree.setSourceRoot(this);
+
+    return tree;
+  }
+}
+
+aspect ScopeGenerationAttributes {
+
+}
diff --git a/scope4m/src/main/jastadd/ModelicaToScopeTree.relast b/scope4m/src/main/jastadd/ModelicaToScopeTree.relast
new file mode 100644
index 0000000..4c47dbc
--- /dev/null
+++ b/scope4m/src/main/jastadd/ModelicaToScopeTree.relast
@@ -0,0 +1,2 @@
+// glue relation for the Java-based variable shadowing analysis
+rel ScopeTree.SourceRoot -> SourceRoot;
diff --git a/scope4m/src/main/java/org/jmodelica/ScopeAnalysis.java b/scope4m/src/main/java/org/jmodelica/ScopeAnalysis.java
new file mode 100644
index 0000000..f7ce25d
--- /dev/null
+++ b/scope4m/src/main/java/org/jmodelica/ScopeAnalysis.java
@@ -0,0 +1,143 @@
+package org.jmodelica;
+
+
+import beaver.Parser;
+import org.jmodelica.compiler.*;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
+import org.jmodelica.util.exceptions.CompilerException;
+
+public class ScopeAnalysis {
+
+
+
+  public SourceRoot getSourceRoot() {
+    return sourceRoot;
+  }
+
+  private SourceRoot sourceRoot;
+
+  /**
+   * Entry point for the Java checker.
+   *
+   * @param args command-line arguments
+   */
+  public static void main(String[] args) {
+
+    List<String> arguments = new ArrayList<>(Arrays.asList(args));
+
+    boolean debug = arguments.isEmpty() || arguments.remove("--debug");
+    boolean tree = arguments.remove("--tree");
+    boolean warnings = arguments.remove("--warnings");
+
+    if (arguments.size() > 1) {
+      System.out.println("usage: ScopeAnalysis [--debug] [--tree] [--warnings] <directory with java files>");
+      System.exit(-1);
+    }
+    String path = arguments.isEmpty() ? "../testprograms/modelica" : arguments.get(arguments.size() - 1);
+
+    if (debug) {
+      new ScopeAnalysis().analyze(path, tree, warnings);
+    } else {
+      new ScopeAnalysis().analyzeTimed(path);
+    }
+
+  }
+
+  public void analyzeTimed(String path) {
+    try {
+      List<String> files = Files.walk(Paths.get(path))
+          .filter(Files::isRegularFile)
+          .filter(x -> x.getFileName().toString().endsWith(".mo")).map(Path::toString).collect(Collectors.toList());
+
+      // measure the time (with parsing) from here
+      long startMeasurementTime = System.nanoTime();
+
+      sourceRoot = readProgram(files);
+
+      // measure the time (without parsing) from here
+      long startGenerationTime = System.nanoTime();
+
+      ScopeTree scopeTree = sourceRoot.scopeTree();
+
+      long startAnalysisTime = System.nanoTime();
+
+      Set<AbstractFinding> findings = scopeTree.variableShadowings();
+
+      // measure the time until here
+      long endTime = System.nanoTime();
+
+      System.out.print("modelica,inner,false,"
+          + files.size() + ","
+          + scopeTree.numScopes() + ","
+          + scopeTree.numDeclarations() + ","
+          + (scopeTree.numScopes() + scopeTree.numDeclarations()) + ","
+          + findings.size() + ",");
+
+      long parseTime = startGenerationTime - startMeasurementTime;
+      long generationTime = startAnalysisTime - startGenerationTime;
+      long analysisTime = endTime - startAnalysisTime;
+      long fullTime = endTime - startMeasurementTime;
+
+      System.out.print((fullTime / 1000000) + ",");
+      System.out.print((parseTime / 1000000) + ",");
+      System.out.print((generationTime / 1000000) + ",");
+      System.out.print((analysisTime / 1000000) + ",");
+      System.out.print(((generationTime + analysisTime) / 1000000) + ",");
+
+    } catch (IOException | Parser.Exception | CompilerException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+
+  public Set<AbstractFinding> analyze(String path, boolean tree, boolean warnings) {
+    try {
+      List<String> files = Files.walk(Paths.get(path))
+          .filter(Files::isRegularFile)
+          .filter(x -> x.getFileName().toString().endsWith(".mo")).map(Path::toString).collect(Collectors.toList());
+
+      sourceRoot = readProgram(files);
+
+      ScopeTree scopeTree = sourceRoot.scopeTree();
+
+      if (tree) {
+        scopeTree.printAST();
+
+      }
+
+      // TODO just temp debug output:
+      sourceRoot.printAST();
+
+      if (warnings) {
+        // TODO find out if there are compiler warnings in JModelica
+      }
+
+      Set<AbstractFinding> findings = scopeTree.variableShadowings();
+
+      System.out.println("\nScope4J found the following problems:");
+      for (AbstractFinding finding : findings) {
+        System.out.println(finding);
+      }
+      System.out.println();
+
+      return findings;
+    } catch (IOException | Parser.Exception | CompilerException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  private static SourceRoot readProgram(Collection<String> files) throws IOException, beaver.Parser.Exception, CompilerException {
+
+
+    ModelicaCompiler mc = new ModelicaCompiler(ModelicaCompiler.createOptions());
+    return mc.getParserHandler().parseModel(UtilInterface.create(mc), (files.toArray(new String[]{})));
+
+  }
+}
diff --git a/settings.gradle b/settings.gradle
index 2dfdf27..5dc7447 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -11,10 +11,12 @@ rootProject.name = 'relast-reuse'
 
 include 'statemachine'
 include 'extendj'
+include 'jmodelica'
 include 'dg'
 include 'deps4j'
 include 'scope'
 include 'scope4j'
+include 'scope4m'
 include 'simplecfg'
 include 'extendj:java4'
 include 'extendj:java5'
-- 
GitLab