<commit_before>(ns ralang.gen
  (:use [clojure.java.io])
  (:require [clojure.string :as string])
  (:gen-class))

(declare tokenReader)
(declare genReturn)
(def output1 "output-1.ra")
(def output2 "output-2.ra")
(def indent (string/join (repeat 4 " ")))
(def j_string "Ljava/lang/String;")
(def j_print "invokevirtual java/io/PrintStream/println")
(def lastWritten "")
(def funcsHash (hash-map))

(defn initOutput []
  (.delete (clojure.java.io/file output1))
  (.delete (clojure.java.io/file output2)))

(defn write
  "Write bytecode to the output file."
  [file, bytecode]
  (spit file (str bytecode "\n") :append true)
  (def lastWritten bytecode))

(defn getType
  "Returns JVM type."
  [type]
  (case (str type)
    ":int"    (str "i")
    ":string" (str "a")
    (str type)))

(defn getMethodType
  "Returns JVM type for methods."
  [type]
  (case (str type)
    ":string" (str j_string)
    ":int"    (str "I")
    ":float"  (str "F")
    (str "")))

(defn convertDatatype
  "Converts datatype from ralang to JVM."
  [type]
  (cond
    (= (first type) :array) (str "[" (tokenReader (second type)))
    :else (case type
            "String" (str j_string)
            "Int"    (str "I")
            "Void"   (str "V")
            (str type))))

(defn readTuple
  "Function argument's tuple reader."
  [tuple]
  (def args (apply str (map #(tokenReader (nth % 1)) tuple)))
  (str "(" args ")"))

(defn genModule
  "Generates a module."
  [id]
  (initOutput)
  (write output1 (str ".class public " id))
  (write output1 ".super java/lang/Object")
  (write output1 ".method public <init>()V")
  (write output1 "    aload_0")
  (write output1 "    invokespecial java/lang/Object/<init>()V")
  (def moduleName id))

(defn genFunction
  "Generates a new function.
    name  - Function's name.
    ar    - Function's arguments.
    rt    - Function's return type."
  [name, ar, rt]
  (cond
    (not (= lastWritten ".end method")) (genReturn output1 nil)
    :else (println "Ended correctly."))
  (write output1 (str ".method public static " name ar rt))
  (write output1 "    .limit stack 50")
  (write output1 "    .limit locals 50")
  (def funcsHash (merge funcsHash {name (str ar rt)})))

(defn genReturn
  "Generates the ending of the function.
    rt    - Function's return type."
  [file, rt]
  (def returnType (getType rt))
  (write file (str indent returnType "return"))
  (write file ".end method"))

(defn genFunctionCallPlaceHolder
  "Generates a placeholder for function calls."
  [token]
  (def fName (tokenReader token))
  (write output1 (str "->fc" fName))
  fName)

(defn genOutput2
  "Generates:
    Function calls.
    Missing print statements." []
  (with-open [rdr (reader output1)]
    (doseq [line (line-seq rdr)]
      (def oPart (split-at 4 line))
      (def oCode (apply str (first oPart)))
      (def oArgs (apply str (second oPart)))
      (case oCode
        "->fc" (write output2 (str indent "invokestatic " moduleName "/" oArgs (first (map funcsHash [oArgs]))))
        "->pr" (write output2 (str indent j_print "(" (second (string/split (first (map funcsHash [oArgs])) #"\(.*\)")) ")V"))
        (write output2 line))))
  ; The following checks for proper ending to a simple program with only 1 main function.
  ; It checks if the last line ends in ".end method"<commit_msg>Some more refactoring<commit_after>(ns ralang.gen
  (:use [clojure.java.io])
  (:require [clojure.string :as string])
  (:gen-class))

(declare tokenReader)
(declare genReturn)
(def output1        "output-1.ra")
(def output2        "output-2.ra")
(def indent         (string/join (repeat 4 " ")))
(def functionsTable (hash-map))
(def j_string       "Ljava/lang/String;")
(def j_print        "invokevirtual java/io/PrintStream/println")

(defn initOutput
  "Deletes output1 and output2 iff they already exist." []
  (.delete (clojure.java.io/file output1))
  (.delete (clojure.java.io/file output2)))

(defn write
  "Write bytecode to the output file."
  [file, bytecode]
  (spit file (str bytecode "\n") :append true)
  (def lastWritten bytecode))

(defn getType
  "Returns JVM type."
  [type]
  (case (str type)
    ":int"    (str "i")
    ":string" (str "a")
    (str type)))

(defn getMethodType
  "Returns JVM type for methods."
  [type]
  (case (str type)
    ":string" (str j_string)
    ":int"    (str "I")
    ":float"  (str "F")
    (str "")))

(defn convertDatatype
  "Converts datatype from ralang to JVM."
  [type]
  (cond
    (= (first type) :array) (str "[" (tokenReader (second type)))
    :else (case type
            "String" (str j_string)
            "Int"    (str "I")
            "Void"   (str "V")
            (str type))))

(defn readTuple
  "Function argument's tuple reader."
  [tuple]
  (def args (apply str (map #(tokenReader (nth % 1)) tuple)))
  (str "(" args ")"))

(defn genModule
  "Generates a module."
  [id]
  (initOutput)
  (write output1 (str ".class public " id))
  (write output1 ".super java/lang/Object")
  (write output1 ".method public <init>()V")
  (write output1 "    aload_0")
  (write output1 "    invokespecial java/lang/Object/<init>()V")
  (def moduleName id))

(defn genFunction
  "Generates a new function.
    name  - Function's name.
    ar    - Function's arguments.
    rt    - Function's return type."
  [name, ar, rt]
  (cond
    (not (= lastWritten ".end method")) (genReturn output1 nil)
    :else (println "Ended correctly."))
  (write output1 (str ".method public static " name ar rt))
  (write output1 "    .limit stack 50")
  (write output1 "    .limit locals 50")
  (def functionsTable (merge functionsTable {name (str ar rt)})))

(defn genReturn
  "Generates the ending of the function.
    rt    - Function's return type."
  [file, rt]
  (def returnType (getType rt))
  (write file (str indent returnType "return"))
  (write file ".end method"))

(defn genFunctionCallPlaceHolder
  "Generates a placeholder for function calls."
  [token]
  (def fName (tokenReader token))
  (write output1 (str "->fc" fName))
  fName)

(defn genOutput2
  "Generates:
    Function calls.
    Missing print statements." []
  (with-open [rdr (reader output1)]
    (doseq [line (line-seq rdr)]
      (def oPart (split-at 4 line))
      (def oCode (apply str (first oPart)))
      (def oArgs (apply str (second oPart)))
      (case oCode
        "->fc" (write output2 (str indent "invokestatic " moduleName "/" oArgs (first (map functionsTable [oArgs]))))
        "->pr" (write output2 (str indent j_print "(" (second (string/split (first (map functionsTable [oArgs])) #"\(.*\)")) ")V"))
        (write output2 line))))
  ; The following checks for proper ending to a simple program with only 1 main function.
  ; It checks if the last line ends in ".end method"
{'fraction_non_alphanumeric': 0.14915809864401727, 'fraction_numerical': 0.009238563552376695, 'mean_word_length': 3.117791411042945, 'pattern_counts': {'":': 10, '<': 7, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6393663', 'n_tokens_mistral': 2329, 'n_tokens_neox': 2277, 'n_words': 759}