Skip to content
Binary file modified source_.jar
Binary file not shown.
251 changes: 143 additions & 108 deletions src/main/java/cod/interpreter/Index.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
package cod.interpreter;

import cod.error.ProgramError;
import cod.ir.IRManager;
import cod.lexer.*;
import static cod.lexer.TokenType.*;
import static cod.syntax.Symbol.*;
import static cod.syntax.Keyword.*;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
* Index file for Coderive units.
* Stores classname → filename mappings for O(1) import resolution.
*
* File format: {projectRoot}/src/idx/{unit}.toml
* File format (preferred): {projectRoot}/src/bin/project.codc -> HOOK.toml
*
* Example:
* # unit sample
Expand All @@ -29,10 +31,9 @@
*/
public final class Index {

private static final String IDX_DIR_NAME = "idx";
private static final String SRC_DIR_NAME = "src";
private static final String FILE_EXTENSION = ".toml";
private static final String CLASSES_SECTION = "classes";
private static final String CLASSES_SECTION_PREFIX = CLASSES_SECTION + ":";
private static final String SRC_DIR_NAME = "src";
private static final String DEFAULT_GENERATOR = "Coderive 1.0";

private final String unit;
Expand Down Expand Up @@ -82,15 +83,8 @@ public static String getProjectRoot() {
return projectRoot;
}

/**
* Gets the index file path for a unit.
*/
private static File getIndexFile(String unitName) {
if (projectRoot == null) {
return new File("src/" + IDX_DIR_NAME + "/" + unitName + FILE_EXTENSION);
}
return new File(projectRoot + File.separator + SRC_DIR_NAME +
File.separator + IDX_DIR_NAME + File.separator + unitName + FILE_EXTENSION);
private static String getUnitSectionName(String unitName) {
return CLASSES_SECTION_PREFIX + unitName;
}

/**
Expand Down Expand Up @@ -134,71 +128,20 @@ public static Index load(String unitName) {
if (unitName == null || unitName.trim().isEmpty()) {
return null;
}

File file = getIndexFile(unitName);
if (!file.exists()) {
String docText = loadPreferredDocumentText(unitName);
if (docText == null) {
return null;
}

BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
Index index = new Index(unitName);
String currentSection = "";
String line;

while ((line = reader.readLine()) != null) {
line = line.trim();

if (line.isEmpty() || line.startsWith("#")) {
continue;
}

if (line.startsWith("[") && line.endsWith("]")) {
currentSection = line.substring(1, line.length() - 1);
continue;
}

int eq = line.indexOf('=');
if (eq == -1) {
continue;
}

String key = line.substring(0, eq).trim();
String value = line.substring(eq + 1).trim();

if (value.startsWith("\"") && value.endsWith("\"")) {
value = value.substring(1, value.length() - 1);
}

if (currentSection.isEmpty()) {
if ("timestamp".equals(key)) {
try {
index.timestamp = Long.parseLong(value);
} catch (NumberFormatException e) {
// Keep existing timestamp
}
} else if ("generator".equals(key)) {
index.generator = value;
}
} else if (CLASSES_SECTION.equals(currentSection)) {
index.classes.put(key, value);
}
}

return index;

} catch (IOException e) {

IndexDocument doc = parseDocument(docText, unitName);
Map<String, String> unitMappings = doc.unitMappings.get(unitName);
if (unitMappings == null || unitMappings.isEmpty()) {
return null;
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// Ignore
}
}
}

Index index = new Index(unitName, doc.timestamp, doc.generator);
index.classes.putAll(unitMappings);
return index;
}

/**
Expand All @@ -207,42 +150,23 @@ public static Index load(String unitName) {
* @return true if saved successfully, false otherwise
*/
public boolean save() {
File file = getIndexFile(unit);

File parent = file.getParentFile();
if (parent != null && !parent.exists()) {
if (!parent.mkdirs()) {
return false;
}
if (projectRoot == null) {
return false;
}

PrintWriter writer = null;

IndexDocument merged = loadExistingDocument(unit);
merged.timestamp = timestamp;
merged.generator = (generator == null || generator.isEmpty()) ? DEFAULT_GENERATOR : generator;
merged.unitMappings.put(unit, new HashMap<String, String>(classes));

String documentText = writeDocumentText(merged);

IRManager manager = new IRManager(projectRoot);
try {
writer = new PrintWriter(new FileWriter(file));

writer.println("# unit " + unit);
writer.println("timestamp = \"" + timestamp + "\"");
writer.println("generator = \"" + generator + "\"");
writer.println();
writer.println("[" + CLASSES_SECTION + "]");

List<String> sorted = new ArrayList<String>(classes.keySet());
Collections.sort(sorted);

for (String className : sorted) {
String fileName = classes.get(className);
writer.println(className + " = \"" + fileName + "\"");
}

writer.flush();
manager.saveIndex(unit, documentText);
return true;

} catch (IOException e) {
return false;
} finally {
if (writer != null) {
writer.close();
}
}
}

Expand Down Expand Up @@ -562,10 +486,121 @@ public Map<String, String> getMappings() {
}

// ========== Private Helpers ==========


private static String loadPreferredDocumentText(String unitName) {
if (projectRoot == null) {
return null;
}

IRManager manager = new IRManager(projectRoot);
return manager.loadIndex(unitName);
}

private static IndexDocument loadExistingDocument(String unitName) {
String content = loadPreferredDocumentText(unitName);
if (content == null) {
return new IndexDocument(System.currentTimeMillis(), DEFAULT_GENERATOR, new HashMap<String, Map<String, String>>());
}
return parseDocument(content, unitName);
}

private static String writeDocumentText(IndexDocument doc) {
StringBuilder out = new StringBuilder();
out.append("# project-wide multi-unit class index\n");
out.append("timestamp = \"").append(doc.timestamp).append("\"\n");
out.append("generator = \"").append(doc.generator).append("\"\n");
out.append("\n");

List<String> units = new ArrayList<String>(doc.unitMappings.keySet());
Collections.sort(units);
for (String unitName : units) {
out.append("[").append(getUnitSectionName(unitName)).append("]\n");
Map<String, String> mappings = doc.unitMappings.get(unitName);
List<String> classNames = new ArrayList<String>(mappings.keySet());
Collections.sort(classNames);
for (String className : classNames) {
out.append(className).append(" = \"").append(mappings.get(className)).append("\"\n");
}
out.append("\n");
}
return out.toString();
}

private static IndexDocument parseDocument(String content, String fallbackUnitName) {
IndexDocument doc = new IndexDocument(System.currentTimeMillis(), DEFAULT_GENERATOR, new HashMap<String, Map<String, String>>());
if (content == null) return doc;

BufferedReader reader = new BufferedReader(new StringReader(content));
String currentSection = "";
try {
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.isEmpty() || line.startsWith("#")) {
continue;
}
if (line.startsWith("[") && line.endsWith("]")) {
currentSection = line.substring(1, line.length() - 1);
continue;
}

int eq = line.indexOf('=');
if (eq == -1) {
continue;
}

String key = line.substring(0, eq).trim();
String value = line.substring(eq + 1).trim();
if (value.startsWith("\"") && value.endsWith("\"")) {
value = value.substring(1, value.length() - 1);
}

if (currentSection.isEmpty()) {
if ("timestamp".equals(key)) {
try {
doc.timestamp = Long.parseLong(value);
} catch (NumberFormatException ignored) {}
} else if ("generator".equals(key)) {
doc.generator = value;
}
continue;
}

String targetUnit = null;
if (CLASSES_SECTION.equals(currentSection)) {
targetUnit = fallbackUnitName;
} else if (currentSection.startsWith(CLASSES_SECTION_PREFIX)) {
targetUnit = currentSection.substring(CLASSES_SECTION_PREFIX.length());
}
if (targetUnit == null || targetUnit.isEmpty()) continue;

Map<String, String> map = doc.unitMappings.get(targetUnit);
if (map == null) {
map = new HashMap<String, String>();
doc.unitMappings.put(targetUnit, map);
}
map.put(key, value);
}
} catch (IOException ignored) {}

return doc;
}

private static final class IndexDocument {
long timestamp;
String generator;
Map<String, Map<String, String>> unitMappings;

IndexDocument(long timestamp, String generator, Map<String, Map<String, String>> unitMappings) {
this.timestamp = timestamp;
this.generator = generator;
this.unitMappings = unitMappings;
}
}

private static String readFileToString(File file) throws IOException {
StringBuilder content = new StringBuilder();
BufferedReader reader = new BufferedReader(new FileReader(file));
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
try {
String line;
while ((line = reader.readLine()) != null) {
Expand Down Expand Up @@ -648,4 +683,4 @@ public Index build() {
return index;
}
}
}
}
Loading