Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions lib/resources/langages/python/Remote.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import sys

debug_fd = None

def get_answer_line():
line = sys.stdin.readline()
if line == "":
sys.exit(1)

if debug_fd:
print(f"Answer: {line.rstrip()}", file=debug_fd)
debug_fd.flush()

return line.rstrip("\r\n")


def get_answer_int():
return int(get_answer_line())


def get_answer_double():
return float(get_answer_line())


def get_answer_string():
return get_answer_line()


def get_answer_char():
line = get_answer_line()
return line[0] if line else ""


def send_command(format_string, *args):
command = format_string % args

if debug_fd:
print(f"Command from C world: '{command}'", file=debug_fd)
debug_fd.flush()

print(command, file=sys.stderr)
sys.stderr.flush()


# BEGIN UTILS FUNCTIONS

def int2str(nb):
return str(nb)

# END UTILS FUNCTIONS
130 changes: 130 additions & 0 deletions src/plm/core/lang/LangPython.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,23 @@
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.python.core.PyException;
import plm.core.lang.primitives.CommandArgumentType;
import plm.core.lang.primitives.ExternalPrimitiveLanguage;
import plm.core.lang.primitives.PrimitiveMethod;
import plm.core.lang.primitives.PrimitiveParameter;
import plm.core.model.Game;
import plm.core.model.lesson.RunOutcome;
import plm.core.ui.ResourcesCache;
import plm.universe.Entity;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

public class LangPython extends ScriptingLanguage {

public LangPython() {
Expand Down Expand Up @@ -159,4 +171,122 @@ public boolean handleLangException(ScriptException e, Entity ent, RunOutcome pro

return true; // That was indeed a Python exception
}

public static class LangPythonExternalPrimitiveGenerator implements ExternalPrimitiveLanguage {

String getLanguageType(CommandArgumentType<?> type) {
if (type == CommandArgumentType.COLOR) return "int";
if (type == CommandArgumentType.DIRECTION) return "int";
if (type == CommandArgumentType.DOUBLE) return "float";
if (type == CommandArgumentType.INT) return "int";
if (type == CommandArgumentType.STRING) return "str";
if (type == CommandArgumentType.CHAR) return "str";
if (type == CommandArgumentType.BOOLEAN)
return "bool";

throw new IllegalStateException("Unknown type: " + type);
}

String getTypeDeclaration(CommandArgumentType<?> type) {
if (type == CommandArgumentType.DIRECTION) {
return "NORTH = 0\n" +
"EAST = 1\n" +
"SOUTH = 2\n" +
"WEST = 3\n";
}
if (type == CommandArgumentType.COLOR) {
return "white = 0\n" +
"black = 1\n" +
"blue = 2\n" +
"cyan = 3\n" +
"darkGray = 4\n" +
"gray = 5\n" +
"green = 6\n" +
"lightGray = 7\n" +
"magenta = 8\n" +
"orange = 9\n" +
"pink = 10\n" +
"red = 11\n" +
"yellow = 12\n";
}
return "";
}

String getParameter(PrimitiveParameter parameter) {
return parameter.name()+": "+getLanguageType(parameter.type());
}

String getPrototype(PrimitiveMethod method) {
String name = method.name();
List<PrimitiveParameter> parameters = method.parameters();
CommandArgumentType<?> output = method.output();


final String outputString = Optional.ofNullable(output).map(this::getLanguageType).orElse("None");

return "def " + name + "(" + parameters.stream().map(this::getParameter).collect(Collectors.joining(", ")) + ") -> "+outputString+":";
}

String getReturning(CommandArgumentType<?> type) {
if (type == null)
return "";

if (type == CommandArgumentType.STRING) return "get_answer_string()";
if (type == CommandArgumentType.DOUBLE) return "get_answer_double()";
if (type == CommandArgumentType.CHAR) return "get_answer_char()";
if (type == CommandArgumentType.COLOR) return "get_answer_int()";
if (type == CommandArgumentType.DIRECTION) return "get_answer_int()";
if (type == CommandArgumentType.INT) return "get_answer_int()";
if (type == CommandArgumentType.BOOLEAN)
return "get_answer_int()";

throw new IllegalStateException("Unknown type: " + type);
}

String getTemplatingForType(CommandArgumentType<?> type) {
if (type == CommandArgumentType.STRING) return "%s";
if (type == CommandArgumentType.DOUBLE) return "%f";
if (type == CommandArgumentType.CHAR) return "%s";
if (type == CommandArgumentType.COLOR) return "%d";
if (type == CommandArgumentType.DIRECTION) return "%d";
if (type == CommandArgumentType.INT) return "%d";
if (type == CommandArgumentType.BOOLEAN)
return "%d";

throw new IllegalStateException("Unknown type: " + type);
}

String getImplementation(PrimitiveMethod method) {
String prototype = getPrototype(method);

int id = method.id();
String name = method.name();
String formats = method.parameters().stream().map(PrimitiveParameter::type)
.map(this::getTemplatingForType).map(s -> s + " ").collect(Collectors.joining());

String command = "\tsend_command(\"" + id + " " +
formats
+ name
+ "\"" + method.parameters().stream().map(PrimitiveParameter::name).map(s -> ", "+s).collect(Collectors.joining()) + ")";

String returning = method.output() != null ? "\treturn " + getReturning(method.output()) : "";

return prototype + "\n" + command + "\n" + returning + "\n";
}

@Override
public void generate(File folder, String name, List<PrimitiveMethod> methods) throws IOException {
Set<CommandArgumentType<?>> involved = ExternalPrimitiveLanguage.involved(methods);

final String type_declarations = involved.stream().map(this::getTypeDeclaration)
.filter(o -> !o.isBlank()).collect(Collectors.joining("\n\n"));

final String implementations = methods.stream().map(this::getImplementation).collect(Collectors.joining("\n\n"));

final String code = ("from Remote import *\n\n" + type_declarations + implementations).replace("\t", " ".repeat(4));

// System.err.println("XXX Generating "+folder+name+".c");
Files.writeString(new File(folder, name + ".py").toPath(), code);
}
}
}
28 changes: 22 additions & 6 deletions src/plm/core/lang/primitives/CodeCreation.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import lessons.sort.pancake.universe.PancakeEntity;
import org.reflections.Reflections;
import plm.core.lang.LangC;
import plm.core.lang.LangPython;
import plm.universe.Entity;
import plm.universe.bugglequest.AbstractBuggle;
import plm.universe.sort.SortingEntity;
Expand All @@ -19,9 +20,7 @@

public class CodeCreation {
public static void main(String[] args) throws IOException {
File folder = new File("target/classes/resources/langages/c");

LangC.LangCExternalPrimitiveGenerator generator = new LangC.LangCExternalPrimitiveGenerator();
File folder = new File("target/classes/resources/langages/");

Map<String, Class<? extends Entity>> remoteMap = Map.of(
"RemoteBuggle", AbstractBuggle.class,
Expand All @@ -33,6 +32,25 @@ public static void main(String[] args) throws IOException {
"RemoteFlag", DutchFlagEntity.class
);

LangC.LangCExternalPrimitiveGenerator langCGenerator = new LangC.LangCExternalPrimitiveGenerator();
File cFolder = new File(folder, "c");
for (Map.Entry<String, Class<? extends Entity>> entry : remoteMap.entrySet()) {
String name = entry.getKey();
Class<? extends Entity> clazz = entry.getValue();

Map<Integer, PrimitiveMethod> list = null;
try {
list = PrimitiveRegistration.getMaximalPrimitiveForEntity(clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
langCGenerator.generate(cFolder, name, list.values().stream().toList());
Files.move(new File(cFolder, name+".h"), new File(cFolder,"include/"+name+".h"));
Files.move(new File(cFolder, name+".c"), new File(cFolder,"src/"+name+".c"));
}

LangPython.LangPythonExternalPrimitiveGenerator langPythonGenerator = new LangPython.LangPythonExternalPrimitiveGenerator();
File pythonFolder = new File(folder, "python");
for (Map.Entry<String, Class<? extends Entity>> entry : remoteMap.entrySet()) {
String name = entry.getKey();
Class<? extends Entity> clazz = entry.getValue();
Expand All @@ -43,9 +61,7 @@ public static void main(String[] args) throws IOException {
} catch (Exception e) {
throw new RuntimeException(e);
}
generator.generate(folder, name, list.values().stream().toList());
Files.move(new File(folder, name+".h"), new File(folder,"include/"+name+".h"));
Files.move(new File(folder, name+".c"), new File(folder,"src/"+name+".c"));
langPythonGenerator.generate(pythonFolder, name, list.values().stream().toList());
}
}
}
Loading